ReactOS 0.4.15-dev-7788-g1ad9096
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
33typedef struct pp_def_state
34{
38
40
41#define MAXIFSTACK 64
43static int if_stack_idx = 0;
44
45void *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
59void *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
73char *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... */
87static int pphash(const char *str)
88{
89 int sum = 0;
90 while(*str)
91 sum += *str++;
92 return sum % HASHKEY;
93}
94
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
111static void free_pp_entry( pp_entry_t *ppp, int idx )
112{
113 if(ppp->iep)
114 {
115 if(ppp->iep == pp_includelogiclist)
116 {
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;
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
176void 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 {
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
194pp_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 {
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
245error:
246 free(ppp->ident);
247 free(ppp->subst.text);
248 free(ppp);
249 return NULL;
250}
251
252pp_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 {
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
290void *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{
360 pp_internal_error(__FILE__, __LINE__, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK);
361
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
438void WINAPIV pp_internal_error(const char *file, int line, const char *s, ...)
439{
442 fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
443 vfprintf(stderr, s, ap);
444 fprintf(stderr, "\n");
446 exit(3);
447}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static int state
Definition: maze.c:121
void * wpp_open(const char *filename, int type)
Definition: compiler.c:195
int WINAPIV ppy_error(const char *msg,...)
Definition: compiler.c:135
int WINAPIV ppy_warning(const char *msg,...)
Definition: compiler.c:149
char * wpp_lookup(const char *filename, int type, const char *parent_name)
Definition: compiler.c:162
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
static void free_pp_entry(pp_entry_t *ppp, int idx)
Definition: preproc.c:111
static pp_if_state_t if_stack[MAXIFSTACK]
Definition: preproc.c:42
pp_entry_t * pp_add_define(const char *def, const char *text)
Definition: preproc.c:194
pp_if_state_t pp_if_state(void)
Definition: preproc.c:405
char * pp_xstrdup(const char *str)
Definition: preproc.c:73
int pp_get_if_depth(void)
Definition: preproc.c:433
struct pp_def_state pp_def_state_t
void * pp_open_include(const char *name, int type, const char *parent_name, char **newpath)
Definition: preproc.c:290
void * pp_xrealloc(void *p, size_t size)
Definition: preproc.c:59
#define MAXIFSTACK
Definition: preproc.c:41
void * pp_xmalloc(size_t size)
Definition: preproc.c:45
int pp_push_define_state(void)
Definition: preproc.c:148
void pp_next_if_state(int i)
Definition: preproc.c:414
static int pphash(const char *str)
Definition: preproc.c:87
static int if_stack_idx
Definition: preproc.c:43
void pp_push_if(pp_if_state_t s)
Definition: preproc.c:357
pp_entry_t * pplookup(const char *ident)
Definition: preproc.c:95
void pp_pop_define_state(void)
Definition: preproc.c:161
pp_if_state_t pp_pop_if(void)
Definition: preproc.c:380
pp_entry_t * pp_add_macro(char *id, marg_t *args[], int nargs, mtext_t *exp)
Definition: preproc.c:252
static pp_def_state_t * pp_def_state
Definition: preproc.c:39
void WINAPIV pp_internal_error(const char *file, int line, const char *s,...)
Definition: preproc.c:438
void pp_del_define(const char *name)
Definition: preproc.c:176
#define HASHKEY
Definition: preproc.c:31
void pp_push_ignore_state(void)
pp_if_state_t
Definition: wpp_private.h:118
@ if_true
Definition: wpp_private.h:120
@ if_elif
Definition: wpp_private.h:121
@ if_elsefalse
Definition: wpp_private.h:122
@ if_elsetrue
Definition: wpp_private.h:123
@ if_error
Definition: wpp_private.h:125
@ if_false
Definition: wpp_private.h:119
@ if_ignore
Definition: wpp_private.h:124
void pp_pop_ignore_state(void)
includelogicentry_t * pp_includelogiclist
@ def_define
Definition: wpp_private.h:90
@ def_macro
Definition: wpp_private.h:91
unsigned int idx
Definition: utils.c:41
const WCHAR * text
Definition: package.c:1799
#define assert(x)
Definition: debug.h:53
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
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
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_opt_ _CRTIMP int __cdecl vfprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
DWORD exp
Definition: msg.c:16058
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
const WCHAR * str
#define WINAPIV
Definition: sdbpapi.h:64
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
#define args
Definition: format.c:66
#define HASHKEY
Definition: preproc.c:41
Definition: match.c:390
Definition: fci.c:127
struct includelogicentry * next
Definition: wpp_private.h:45
struct includelogicentry * prev
Definition: wpp_private.h:46
Definition: parser.c:49
Definition: name.c:39
struct pp_def_state * next
Definition: preproc.c:35
pp_entry_t * defines[HASHKEY]
Definition: preproc.c:36
Definition: wpp_private.h:95
struct pp_entry * next
Definition: wpp_private.h:96
mtext_t * mtext
Definition: wpp_private.h:103
int linenumber
Definition: wpp_private.h:108
marg_t ** margs
Definition: wpp_private.h:100
int nargs
Definition: wpp_private.h:101
includelogicentry_t * iep
Definition: wpp_private.h:109
char * text
Definition: wpp_private.h:104
char * filename
Definition: wpp_private.h:107
def_type_t type
Definition: wpp_private.h:98
struct pp_entry * prev
Definition: wpp_private.h:97
char * ident
Definition: wpp_private.h:99
union pp_entry::@246 subst
int pedantic
Definition: wpp_private.h:225
char * input
Definition: wpp_private.h:220
int line_number
Definition: wpp_private.h:222
_In_ ULONG _In_ ULONG_PTR ident
Definition: winddi.h:3994
#define __ms_va_list
Definition: windef.h:456
#define __ms_va_end(list)
Definition: windef.h:458
#define __ms_va_start(list, arg)
Definition: windef.h:457
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36