ReactOS  0.4.15-dev-321-g2d9b385
preproc.c
Go to the documentation of this file.
1 /*
2  * Copyright 1998 Bertho A. Stultiens (BS)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <assert.h>
20 #include <ctype.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 
27 #include "wpp_private.h"
28 
30 
31 #define HASHKEY 2039
32 
33 typedef struct pp_def_state
34 {
35  struct pp_def_state *next;
38 
40 
41 #define MAXIFSTACK 64
43 static int if_stack_idx = 0;
44 
45 void *pp_xmalloc(size_t size)
46 {
47  void *res;
48 
49  assert(size > 0);
50  res = malloc(size);
51  if(res == NULL)
52  {
53  /* Set the error flag */
54  pp_status.state = 1;
55  }
56  return res;
57 }
58 
59 void *pp_xrealloc(void *p, size_t size)
60 {
61  void *res;
62 
63  assert(size > 0);
64  res = realloc(p, size);
65  if(res == NULL)
66  {
67  /* Set the error flag */
68  pp_status.state = 1;
69  }
70  return res;
71 }
72 
73 char *pp_xstrdup(const char *str)
74 {
75  char *s;
76  int len;
77 
78  assert(str != NULL);
79  len = strlen(str)+1;
80  s = pp_xmalloc(len);
81  if(!s)
82  return NULL;
83  return memcpy(s, str, len);
84 }
85 
86 /* Don't comment on the hash, it's primitive but functional... */
87 static int pphash(const char *str)
88 {
89  int sum = 0;
90  while(*str)
91  sum += *str++;
92  return sum % HASHKEY;
93 }
94 
95 pp_entry_t *pplookup(const char *ident)
96 {
97  int idx;
98  pp_entry_t *ppp;
99 
100  if(!ident)
101  return NULL;
102  idx = pphash(ident);
103  for(ppp = pp_def_state->defines[idx]; ppp; ppp = ppp->next)
104  {
105  if(!strcmp(ident, ppp->ident))
106  return ppp;
107  }
108  return NULL;
109 }
110 
111 static void free_pp_entry( pp_entry_t *ppp, int idx )
112 {
113  if(ppp->iep)
114  {
115  if(ppp->iep == pp_includelogiclist)
116  {
117  pp_includelogiclist = ppp->iep->next;
120  }
121  else
122  {
123  ppp->iep->prev->next = ppp->iep->next;
124  if(ppp->iep->next)
125  ppp->iep->next->prev = ppp->iep->prev;
126  }
127  free(ppp->iep->filename);
128  free(ppp->iep);
129  }
130 
131  if(pp_def_state->defines[idx] == ppp)
132  {
133  pp_def_state->defines[idx] = ppp->next;
134  if(pp_def_state->defines[idx])
136  }
137  else
138  {
139  ppp->prev->next = ppp->next;
140  if(ppp->next)
141  ppp->next->prev = ppp->prev;
142  }
143 
144  free(ppp);
145 }
146 
147 /* push a new (empty) define state */
149 {
150  pp_def_state_t *state = pp_xmalloc( sizeof(*state) );
151  if(!state)
152  return 1;
153 
154  memset( state->defines, 0, sizeof(state->defines) );
155  state->next = pp_def_state;
157  return 0;
158 }
159 
160 /* pop the current define state */
162 {
163  int i;
164  pp_entry_t *ppp;
166 
167  for (i = 0; i < HASHKEY; i++)
168  {
169  while ((ppp = pp_def_state->defines[i]) != NULL) pp_del_define( ppp->ident );
170  }
172  pp_def_state = state->next;
173  free( state );
174 }
175 
176 void pp_del_define(const char *name)
177 {
178  pp_entry_t *ppp;
179  int idx = pphash(name);
180 
181  if((ppp = pplookup(name)) == NULL)
182  {
183  if(pp_status.pedantic)
184  ppy_warning("%s was not defined", name);
185  return;
186  }
187 
188  free( ppp->ident );
189  free( ppp->subst.text );
190  free( ppp->filename );
191  free_pp_entry( ppp, idx );
192 }
193 
194 pp_entry_t *pp_add_define(const char *def, const char *text)
195 {
196  int len;
197  char *cptr;
198  int idx;
199  pp_entry_t *ppp;
200 
201  if(!def)
202  return NULL;
203  idx = pphash(def);
204  if((ppp = pplookup(def)) != NULL)
205  {
206  if(pp_status.pedantic)
207  ppy_warning("Redefinition of %s\n\tPrevious definition: %s:%d", def, ppp->filename, ppp->linenumber);
208  pp_del_define(def);
209  }
210  ppp = pp_xmalloc(sizeof(pp_entry_t));
211  if(!ppp)
212  return NULL;
213  memset( ppp, 0, sizeof(*ppp) );
214  ppp->ident = pp_xstrdup(def);
215  if(!ppp->ident)
216  goto error;
217  ppp->type = def_define;
218  ppp->subst.text = text ? pp_xstrdup(text) : NULL;
219  if(text && !ppp->subst.text)
220  goto error;
221  ppp->filename = pp_xstrdup(pp_status.input ? pp_status.input : "<internal or cmdline>");
222  if(!ppp->filename)
223  goto error;
225  ppp->next = pp_def_state->defines[idx];
226  pp_def_state->defines[idx] = ppp;
227  if(ppp->next)
228  ppp->next->prev = ppp;
229  if(ppp->subst.text)
230  {
231  /* Strip trailing white space from subst text */
232  len = strlen(ppp->subst.text);
233  while(len && strchr(" \t\r\n", ppp->subst.text[len-1]))
234  {
235  ppp->subst.text[--len] = '\0';
236  }
237  /* Strip leading white space from subst text */
238  for(cptr = ppp->subst.text; *cptr && strchr(" \t\r", *cptr); cptr++)
239  ;
240  if(ppp->subst.text != cptr)
241  memmove(ppp->subst.text, cptr, strlen(cptr)+1);
242  }
243  return ppp;
244 
245 error:
246  free(ppp->ident);
247  free(ppp->subst.text);
248  free(ppp);
249  return NULL;
250 }
251 
252 pp_entry_t *pp_add_macro(char *id, marg_t *args[], int nargs, mtext_t *exp)
253 {
254  int idx;
255  pp_entry_t *ppp;
256 
257  if(!id)
258  return NULL;
259  idx = pphash(id);
260  if((ppp = pplookup(id)) != NULL)
261  {
262  if(pp_status.pedantic)
263  ppy_warning("Redefinition of %s\n\tPrevious definition: %s:%d", id, ppp->filename, ppp->linenumber);
264  pp_del_define(id);
265  }
266  ppp = pp_xmalloc(sizeof(pp_entry_t));
267  if(!ppp)
268  return NULL;
269  memset( ppp, 0, sizeof(*ppp) );
270  ppp->ident = id;
271  ppp->type = def_macro;
272  ppp->margs = args;
273  ppp->nargs = nargs;
274  ppp->subst.mtext= exp;
275  ppp->filename = pp_xstrdup(pp_status.input ? pp_status.input : "<internal or cmdline>");
276  if(!ppp->filename)
277  {
278  free(ppp);
279  return NULL;
280  }
282  ppp->next = pp_def_state->defines[idx];
283  pp_def_state->defines[idx] = ppp;
284  if(ppp->next)
285  ppp->next->prev = ppp;
286  return ppp;
287 }
288 
289 
290 void *pp_open_include(const char *name, int type, const char *parent_name, char **newpath)
291 {
292  char *path;
293  void *fp;
294 
295  if (!(path = wpp_lookup(name, type, parent_name))) return NULL;
296  fp = wpp_open(path, type);
297 
298  if (fp)
299  {
300  if (newpath) *newpath = path;
301  else free( path );
302  return fp;
303  }
304  free( path );
305  return NULL;
306 }
307 
308 /*
309  *-------------------------------------------------------------------------
310  * #if, #ifdef, #ifndef, #else, #elif and #endif state management
311  *
312  * #if state transitions are made on basis of the current TOS and the next
313  * required state. The state transitions are required to housekeep because
314  * #if:s can be nested. The ignore case is activated to prevent output from
315  * within a false clause.
316  * Some special cases come from the fact that the #elif cases are not
317  * binary, but three-state. The problem is that all other elif-cases must
318  * be false when one true one has been found. A second problem is that the
319  * #else clause is a final clause. No extra #else:s may follow.
320  *
321  * The states mean:
322  * if_true Process input to output
323  * if_false Process input but no output
324  * if_ignore Process input but no output
325  * if_elif Process input but no output
326  * if_elsefalse Process input but no output
327  * if_elsettrue Process input to output
328  *
329  * The possible state-sequences are [state(stack depth)] (rest can be deduced):
330  * TOS #if 1 #else #endif
331  * if_true(n) if_true(n+1) if_elsefalse(n+1)
332  * if_false(n) if_ignore(n+1) if_ignore(n+1)
333  * if_elsetrue(n) if_true(n+1) if_elsefalse(n+1)
334  * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1)
335  * if_elif(n) if_ignore(n+1) if_ignore(n+1)
336  * if_ignore(n) if_ignore(n+1) if_ignore(n+1)
337  *
338  * TOS #if 1 #elif 0 #else #endif
339  * if_true(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
340  * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
341  * if_elsetrue(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
342  * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
343  * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
344  * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
345  *
346  * TOS #if 0 #elif 1 #else #endif
347  * if_true(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
348  * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
349  * if_elsetrue(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
350  * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
351  * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
352  * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
353  *
354  *-------------------------------------------------------------------------
355  */
356 
358 {
359  if(if_stack_idx >= MAXIFSTACK)
360  pp_internal_error(__FILE__, __LINE__, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK);
361 
362  if_stack[if_stack_idx++] = s;
363 
364  switch(s)
365  {
366  case if_true:
367  case if_elsetrue:
368  break;
369  case if_false:
370  case if_elsefalse:
371  case if_elif:
372  case if_ignore:
374  break;
375  default:
376  pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d)", (int)pp_if_state());
377  }
378 }
379 
381 {
382  if(if_stack_idx <= 0)
383  {
384  ppy_error("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
385  return if_error;
386  }
387 
388  switch(pp_if_state())
389  {
390  case if_true:
391  case if_elsetrue:
392  break;
393  case if_false:
394  case if_elsefalse:
395  case if_elif:
396  case if_ignore:
398  break;
399  default:
400  pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d)", (int)pp_if_state());
401  }
402  return if_stack[--if_stack_idx];
403 }
404 
406 {
407  if(!if_stack_idx)
408  return if_true;
409  else
410  return if_stack[if_stack_idx-1];
411 }
412 
413 
415 {
416  switch(pp_if_state())
417  {
418  case if_true:
419  case if_elsetrue:
421  break;
422  case if_false:
423  case if_elsefalse:
424  case if_elif:
425  case if_ignore:
427  break;
428  default:
429  pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #{if,ifdef,ifndef} directive", (int)pp_if_state());
430  }
431 }
432 
434 {
435  return if_stack_idx;
436 }
437 
438 void WINAPIV pp_internal_error(const char *file, int line, const char *s, ...)
439 {
441  __ms_va_start(ap, s);
442  fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
443  vfprintf(stderr, s, ap);
444  fprintf(stderr, "\n");
445  __ms_va_end(ap);
446  exit(3);
447 }
#define realloc
Definition: debug_ros.c:6
pp_entry_t * defines[HASHKEY]
Definition: preproc.c:36
int nargs
Definition: wpp_private.h:101
static pp_def_state_t * pp_def_state
Definition: preproc.c:39
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
void WINAPIV pp_internal_error(const char *file, int line, const char *s,...)
Definition: preproc.c:438
int pp_get_if_depth(void)
Definition: preproc.c:433
char * text
Definition: wpp_private.h:104
static static const char __ms_va_list
Definition: printf.c:76
#define error(str)
Definition: mkdosfs.c:1605
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
pp_if_state_t
Definition: wpp_private.h:118
GLsizei const GLchar ** path
Definition: glext.h:7234
void * pp_xrealloc(void *p, size_t size)
Definition: preproc.c:59
const WCHAR * text
Definition: package.c:1827
#define free
Definition: debug_ros.c:5
char * ident
Definition: wpp_private.h:99
int line_number
Definition: wpp_private.h:222
void pp_push_if(pp_if_state_t s)
Definition: preproc.c:357
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define assert(x)
Definition: debug.h:53
struct pp_entry * prev
Definition: wpp_private.h:97
static void free_pp_entry(pp_entry_t *ppp, int idx)
Definition: preproc.c:111
Definition: match.c:390
#define HASHKEY
Definition: preproc.c:31
pp_if_state_t pp_if_state(void)
Definition: preproc.c:405
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
void * pp_open_include(const char *name, int type, const char *parent_name, char **newpath)
Definition: preproc.c:290
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
void pp_next_if_state(int i)
Definition: preproc.c:414
unsigned int idx
Definition: utils.c:41
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
union pp_entry::@241 subst
Definition: parser.c:48
struct pp_def_state pp_def_state_t
struct includelogicentry * prev
Definition: wpp_private.h:46
static int pphash(const char *str)
Definition: preproc.c:87
mtext_t * mtext
Definition: wpp_private.h:103
int linenumber
Definition: wpp_private.h:108
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
char * input
Definition: wpp_private.h:220
int ppy_error(const char *s,...)
Definition: preproc.c:735
_In_ ULONG _In_ ULONG_PTR ident
Definition: winddi.h:3993
int ppy_warning(const char *s,...)
Definition: preproc.c:745
static pp_if_state_t if_stack[MAXIFSTACK]
Definition: preproc.c:42
GLsizeiptr size
Definition: glext.h:5919
char * pp_xstrdup(const char *str)
Definition: preproc.c:73
Definition: wpp_private.h:95
void * wpp_open(const char *filename, int type)
Definition: compiler.c:195
includelogicentry_t * pp_includelogiclist
Definition: ppl.yy.c:1547
char * wpp_lookup(const char *filename, int type, const char *parent_name)
Definition: compiler.c:162
static int state
Definition: maze.c:121
void pp_del_define(const char *name)
Definition: preproc.c:176
char * filename
Definition: wpp_private.h:107
pp_entry_t * pp_add_define(const char *def, const char *text)
Definition: preproc.c:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
#define WINAPIV
Definition: sdbpapi.h:64
pp_entry_t * pplookup(const char *ident)
Definition: preproc.c:95
struct includelogicentry * next
Definition: wpp_private.h:45
pp_entry_t * pp_add_macro(char *id, marg_t *args[], int nargs, mtext_t *exp)
Definition: preproc.c:252
void pp_push_ignore_state(void)
Definition: ppl.yy.c:4748
#define __ms_va_end(list)
Definition: windef.h:458
marg_t ** margs
Definition: wpp_private.h:100
DWORD exp
Definition: msg.c:16033
char * strchr(const char *String, int ch)
Definition: utclib.c:501
struct pp_entry * next
Definition: wpp_private.h:96
def_type_t type
Definition: wpp_private.h:98
static int if_stack_idx
Definition: preproc.c:43
#define __ms_va_start(list, arg)
Definition: windef.h:457
Definition: name.c:38
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
void pp_pop_ignore_state(void)
Definition: ppl.yy.c:4753
includelogicentry_t * iep
Definition: wpp_private.h:109
GLuint res
Definition: glext.h:9613
void * pp_xmalloc(size_t size)
Definition: preproc.c:45
GLenum GLuint id
Definition: glext.h:5579
FILE * stderr
int pedantic
Definition: wpp_private.h:225
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int pp_push_define_state(void)
Definition: preproc.c:148
#define malloc
Definition: debug_ros.c:4
void exit(int exitcode)
Definition: _exit.c:33
GLfloat GLfloat p
Definition: glext.h:8902
_Check_return_opt_ _CRTIMP int __cdecl vfprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
#define memset(x, y, z)
Definition: compat.h:39
#define MAXIFSTACK
Definition: preproc.c:41
#define args
Definition: format.c:66
void pp_pop_define_state(void)
Definition: preproc.c:161
pp_if_state_t pp_pop_if(void)
Definition: preproc.c:380
struct pp_def_state * next
Definition: preproc.c:35
Definition: fci.c:126