2 * Copyright 1998 Bertho A. Stultiens (BS)
18 extern void set_pp_ignore(int); /* From parser.l */
21 static pp_entry_t
*pp_defines
[HASHKEY
];
24 static if_state_t if_stack
[MAXIFSTACK
];
25 static int if_stack_idx
= 0;
28 void pp_status(void) __attribute__((destructor
));
36 fprintf(stderr
, "Defines statistics:\n");
37 for(i
= 0; i
< HASHKEY
; i
++)
40 for(ppp
= pp_defines
[i
]; ppp
; ppp
= ppp
->next
)
43 fprintf(stderr
, "%4d, %3d\n", i
, sum
);
45 fprintf(stderr
, "Total defines: %d\n", total
);
49 /* Don't comment on the hash, its primitive but functional... */
58 pp_entry_t
*pplookup(char *ident
)
60 int idx
= pphash(ident
);
63 for(ppp
= pp_defines
[idx
]; ppp
; ppp
= ppp
->next
)
65 if(!strcmp(ident
, ppp
->ident
))
71 void del_define(char *name
)
76 if((ppp
= pplookup(name
)) == NULL
)
79 yywarning("%s was not defined", name
);
85 if(debuglevel
& DEBUGLEVEL_PPMSG
)
86 fprintf(stderr
, "del_define: %s:%d: includelogic removed, include_ppp='%s', file=%s\n", input_name
, line_number
, name
, ppp
->iep
->filename
);
87 if(ppp
->iep
== includelogiclist
)
89 includelogiclist
= ppp
->iep
->next
;
91 includelogiclist
->prev
= NULL
;
95 ppp
->iep
->prev
->next
= ppp
->iep
->next
;
97 ppp
->iep
->next
->prev
= ppp
->iep
->prev
;
99 free(ppp
->iep
->filename
);
104 if(pp_defines
[idx
] == ppp
)
106 pp_defines
[idx
] = ppp
->next
;
108 pp_defines
[idx
]->prev
= NULL
;
112 ppp
->prev
->next
= ppp
->next
;
114 ppp
->next
->prev
= ppp
->prev
;
119 if(debuglevel
& DEBUGLEVEL_PPMSG
)
120 printf("Deleted (%s, %d) <%s>\n", input_name
, line_number
, name
);
123 pp_entry_t
*add_define(char *def
, char *text
)
127 int idx
= pphash(def
);
130 if((ppp
= pplookup(def
)) != NULL
)
133 yywarning("Redefinition of %s\n\tPrevious definition: %s:%d", def
, ppp
->filename
, ppp
->linenumber
);
136 ppp
= (pp_entry_t
*)xmalloc(sizeof(pp_entry_t
));
138 ppp
->type
= def_define
;
139 ppp
->subst
.text
= text
;
140 ppp
->filename
= input_name
? xstrdup(input_name
) : "<internal or cmdline>";
141 ppp
->linenumber
= input_name
? line_number
: 0;
142 ppp
->next
= pp_defines
[idx
];
143 pp_defines
[idx
] = ppp
;
145 ppp
->next
->prev
= ppp
;
148 /* Strip trailing white space from subst text */
150 while(len
&& strchr(" \t\r\n", text
[len
-1]))
154 /* Strip leading white space from subst text */
155 for(cptr
= text
; *cptr
&& strchr(" \t\r", *cptr
); cptr
++)
158 memmove(text
, cptr
, strlen(cptr
)+1);
160 if(debuglevel
& DEBUGLEVEL_PPMSG
)
161 printf("Added define (%s, %d) <%s> to <%s>\n", input_name
, line_number
, ppp
->ident
, text
? text
: "(null)");
166 pp_entry_t
*add_cmdline_define(char *set
)
168 char *cpy
= xstrdup(set
); /* Because gcc passes a R/O string */
169 char *cptr
= strchr(cpy
, '=');
172 return add_define(cpy
, xstrdup(cptr
? cptr
+1 : ""));
175 pp_entry_t
*add_special_define(char *id
)
177 pp_entry_t
*ppp
= add_define(xstrdup(id
), xstrdup(""));
178 ppp
->type
= def_special
;
182 pp_entry_t
*add_macro(char *id
, marg_t
*args
[], int nargs
, mtext_t
*exp
)
184 int idx
= pphash(id
);
187 if((ppp
= pplookup(id
)) != NULL
)
190 yywarning("Redefinition of %s\n\tPrevious definition: %s:%d", id
, ppp
->filename
, ppp
->linenumber
);
193 ppp
= (pp_entry_t
*)xmalloc(sizeof(pp_entry_t
));
195 ppp
->type
= def_macro
;
198 ppp
->subst
.mtext
= exp
;
199 ppp
->filename
= input_name
? xstrdup(input_name
) : "<internal or cmdline>";
200 ppp
->linenumber
= input_name
? line_number
: 0;
201 ppp
->next
= pp_defines
[idx
];
202 pp_defines
[idx
] = ppp
;
204 ppp
->next
->prev
= ppp
;
206 if(debuglevel
& DEBUGLEVEL_PPMSG
)
208 fprintf(stderr
, "Added macro (%s, %d) <%s(%d)> to <", input_name
, line_number
, ppp
->ident
, nargs
);
209 for(; exp
; exp
= exp
->next
)
214 fprintf(stderr
, " \"%s\" ", exp
->subst
.text
);
217 fprintf(stderr
, " #(%d) ", exp
->subst
.argidx
);
220 fprintf(stderr
, "##");
223 fprintf(stderr
, " <%d> ", exp
->subst
.argidx
);
227 fprintf(stderr
, ">\n");
234 *-------------------------------------------------------------------------
236 *-------------------------------------------------------------------------
238 #if defined(_Windows) || defined(__MSDOS__)
239 #define INCLUDESEPARATOR ";"
241 #define INCLUDESEPARATOR ":"
244 static char **includepath
;
245 static int nincludepath
= 0;
247 void add_include_path(char *path
)
250 char *cpy
= xstrdup(path
);
252 tok
= strtok(cpy
, INCLUDESEPARATOR
);
260 for(cptr
= dir
; *cptr
; cptr
++)
262 /* Convert to forward slash */
266 /* Kill eventual trailing '/' */
267 if(*(cptr
= dir
+ strlen(dir
)-1) == '/')
272 includepath
= (char **)xrealloc(includepath
, nincludepath
* sizeof(*includepath
));
273 includepath
[nincludepath
-1] = dir
;
274 tok
= strtok(NULL
, INCLUDESEPARATOR
);
279 FILE *open_include(const char *name
, int search
, char **newpath
)
281 char *cpy
= xstrdup(name
);
286 for(cptr
= cpy
; *cptr
; cptr
++)
288 /* kill double backslash */
289 if(*cptr
== '\\' && *(cptr
+1) == '\\')
290 memmove(cptr
, cptr
+1, strlen(cptr
));
291 /* Convert to forward slash */
298 /* Search current dir and then -I path */
299 fp
= fopen(cpy
, "rt");
302 if(debuglevel
& DEBUGLEVEL_PPMSG
)
303 printf("Going to include <%s>\n", name
);
312 for(i
= 0; i
< nincludepath
; i
++)
315 path
= (char *)xmalloc(strlen(includepath
[i
]) + strlen(cpy
) + 2);
316 strcpy(path
, includepath
[i
]);
319 fp
= fopen(path
, "rt");
320 if(fp
&& (debuglevel
& DEBUGLEVEL_PPMSG
))
321 printf("Going to include <%s>\n", path
);
340 *-------------------------------------------------------------------------
341 * #if, #ifdef, #ifndef, #else, #elif and #endif state management
343 * #if state transitions are made on basis of the current TOS and the next
344 * required state. The state transitions are required to housekeep because
345 * #if:s can be nested. The ignore case is activated to prevent output from
346 * within a false clause.
347 * Some special cases come from the fact that the #elif cases are not
348 * binary, but three-state. The problem is that all other elif-cases must
349 * be false when one true one has been found. A second problem is that the
350 * #else clause is a final clause. No extra #else:s may follow.
353 * if_true Process input to output
354 * if_false Process input but no output
355 * if_ignore Process input but no output
356 * if_elif Process input but no output
357 * if_elsefalse Process input but no output
358 * if_elsettrue Process input to output
360 * The possible state-sequences are [state(stack depth)] (rest can be deduced):
361 * TOS #if 1 #else #endif
362 * if_true(n) if_true(n+1) if_elsefalse(n+1)
363 * if_false(n) if_ignore(n+1) if_ignore(n+1)
364 * if_elsetrue(n) if_true(n+1) if_elsefalse(n+1)
365 * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1)
366 * if_elif(n) if_ignore(n+1) if_ignore(n+1)
367 * if_ignore(n) if_ignore(n+1) if_ignore(n+1)
369 * TOS #if 1 #elif 0 #else #endif
370 * if_true(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
371 * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
372 * if_elsetrue(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
373 * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
374 * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
375 * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
377 * TOS #if 0 #elif 1 #else #endif
378 * if_true(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
379 * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
380 * if_elsetrue(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
381 * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
382 * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
383 * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
385 *-------------------------------------------------------------------------
387 static char *if_state_str
[] = {
396 void push_if(if_state_t s
)
398 if(if_stack_idx
>= MAXIFSTACK
)
399 internal_error(__FILE__
, __LINE__
, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK
);
401 if(debuglevel
& DEBUGLEVEL_PPLEX
)
402 fprintf(stderr
, "Push if %s:%d: %s(%d) -> %s(%d)\n", input_name
, line_number
, if_state_str
[if_state()], if_stack_idx
, if_state_str
[s
], if_stack_idx
+1);
404 if_stack
[if_stack_idx
++] = s
;
420 if_state_t
pop_if(void)
422 if(if_stack_idx
<= 0)
423 yyerror("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
438 if(debuglevel
& DEBUGLEVEL_PPLEX
)
439 fprintf(stderr
, "Pop if %s:%d: %s(%d) -> %s(%d)\n",
442 if_state_str
[if_state()],
444 if_state_str
[if_stack
[if_stack_idx
<= 1 ? if_true
: if_stack_idx
-2]],
447 return if_stack
[--if_stack_idx
];
450 if_state_t
if_state(void)
455 return if_stack
[if_stack_idx
-1];
459 void next_if_state(int i
)
465 push_if(i
? if_true
: if_false
);
474 internal_error(__FILE__
, __LINE__
, "Invalid if_state (%d) in #{if,ifdef,ifndef} directive", (int)if_state());
478 int get_if_depth(void)