2 * Exported functions of the Wine preprocessor
4 * Copyright 1998 Bertho A. Stultiens
5 * Copyright 2002 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
37 #include "wpp_private.h"
40 struct pp_status pp_status
;
44 static struct list pp_defines
[HASHKEY
];
47 static pp_if_state_t if_stack
[MAXIFSTACK
];
48 static int if_stack_idx
= 0;
50 int ppy_debug
, pp_flex_debug
;
59 static struct list cmdline_defines
= LIST_INIT( cmdline_defines
);
61 void *pp_xmalloc(size_t size
)
69 fprintf( stderr
, "Virtual memory exhausted\n" );
75 void *pp_xrealloc(void *p
, size_t size
)
80 res
= realloc(p
, size
);
83 fprintf( stderr
, "Virtual memory exhausted\n" );
89 char *pp_xstrdup(const char *str
)
91 int len
= strlen(str
)+1;
92 return memcpy(pp_xmalloc(len
), str
, len
);
95 char *wpp_lookup(const char *name
, int type
, const char *parent_name
,
96 char **include_path
, int include_path_count
)
104 cpy
= pp_xmalloc(strlen(name
)+1);
107 for(ccptr
= name
; *ccptr
; ccptr
++)
109 /* Convert to forward slash */
111 /* kill double backslash */
122 if(type
&& parent_name
)
124 /* Search directory of parent include and then -I path */
127 if ((p
= strrchr( parent_name
, '/' ))) p
++;
128 else p
= parent_name
;
129 path
= pp_xmalloc( (p
- parent_name
) + strlen(cpy
) + 1 );
130 memcpy( path
, parent_name
, p
- parent_name
);
131 strcpy( path
+ (p
- parent_name
), cpy
);
132 fd
= open( path
, O_RDONLY
);
142 for(i
= 0; i
< include_path_count
; i
++)
144 path
= pp_xmalloc(strlen(include_path
[i
]) + strlen(cpy
) + 2);
145 strcpy(path
, include_path
[i
]);
148 fd
= open( path
, O_RDONLY
);
161 /* Don't comment on the hash, it's primitive but functional... */
162 static int pphash(const char *str
)
167 return sum
% HASHKEY
;
170 pp_entry_t
*pplookup(const char *ident
)
178 LIST_FOR_EACH_ENTRY( ppp
, &pp_defines
[idx
], pp_entry_t
, entry
)
180 if(!strcmp(ident
, ppp
->ident
))
186 static void free_pp_entry( pp_entry_t
*ppp
, int idx
)
190 list_remove( &ppp
->iep
->entry
);
191 free(ppp
->iep
->filename
);
194 list_remove( &ppp
->entry
);
198 /* initialize the define state */
199 void pp_init_define_state(void)
203 for (i
= 0; i
< HASHKEY
; i
++) list_init( &pp_defines
[i
] );
206 /* free the current define state */
207 void pp_free_define_state(void)
210 pp_entry_t
*ppp
, *ppp2
;
212 for (i
= 0; i
< HASHKEY
; i
++)
214 LIST_FOR_EACH_ENTRY_SAFE( ppp
, ppp2
, &pp_defines
[i
], pp_entry_t
, entry
)
217 free( ppp
->subst
.text
);
218 free( ppp
->filename
);
219 free_pp_entry( ppp
, i
);
224 void pp_del_define(const char *name
)
227 int idx
= pphash(name
);
229 if((ppp
= pplookup(name
)) == NULL
)
231 if(pp_status
.pedantic
)
232 ppy_warning("%s was not defined", name
);
237 printf("Deleting (%s, %d) <%s>\n", pp_status
.input
, pp_status
.line_number
, name
);
240 free( ppp
->subst
.text
);
241 free( ppp
->filename
);
242 free_pp_entry( ppp
, idx
);
245 pp_entry_t
*pp_add_define(const char *def
, const char *text
)
253 if((ppp
= pplookup(def
)) != NULL
)
255 if(pp_status
.pedantic
)
256 ppy_warning("Redefinition of %s\n\tPrevious definition: %s:%d", def
, ppp
->filename
, ppp
->linenumber
);
259 ppp
= pp_xmalloc(sizeof(pp_entry_t
));
260 memset( ppp
, 0, sizeof(*ppp
) );
261 ppp
->ident
= pp_xstrdup(def
);
262 ppp
->type
= def_define
;
263 ppp
->subst
.text
= text
? pp_xstrdup(text
) : NULL
;
264 ppp
->filename
= pp_xstrdup(pp_status
.input
? pp_status
.input
: "<internal or cmdline>");
265 ppp
->linenumber
= pp_status
.input
? pp_status
.line_number
: 0;
266 list_add_head( &pp_defines
[idx
], &ppp
->entry
);
269 /* Strip trailing white space from subst text */
270 len
= strlen(ppp
->subst
.text
);
271 while(len
&& strchr(" \t\r\n", ppp
->subst
.text
[len
-1]))
273 ppp
->subst
.text
[--len
] = '\0';
275 /* Strip leading white space from subst text */
276 for(cptr
= ppp
->subst
.text
; *cptr
&& strchr(" \t\r", *cptr
); cptr
++)
278 if(ppp
->subst
.text
!= cptr
)
279 memmove(ppp
->subst
.text
, cptr
, strlen(cptr
)+1);
282 printf("Added define (%s, %d) <%s> to <%s>\n", pp_status
.input
, pp_status
.line_number
, ppp
->ident
, ppp
->subst
.text
? ppp
->subst
.text
: "(null)");
287 pp_entry_t
*pp_add_macro(char *id
, char *args
[], int nargs
, mtext_t
*exp
)
293 if((ppp
= pplookup(id
)) != NULL
)
295 if(pp_status
.pedantic
)
296 ppy_warning("Redefinition of %s\n\tPrevious definition: %s:%d", id
, ppp
->filename
, ppp
->linenumber
);
299 ppp
= pp_xmalloc(sizeof(pp_entry_t
));
300 memset( ppp
, 0, sizeof(*ppp
) );
302 ppp
->type
= def_macro
;
305 ppp
->subst
.mtext
= exp
;
306 ppp
->filename
= pp_xstrdup(pp_status
.input
? pp_status
.input
: "<internal or cmdline>");
307 ppp
->linenumber
= pp_status
.input
? pp_status
.line_number
: 0;
308 list_add_head( &pp_defines
[idx
], &ppp
->entry
);
311 fprintf(stderr
, "Added macro (%s, %d) <%s(%d)> to <", pp_status
.input
, pp_status
.line_number
, ppp
->ident
, nargs
);
312 for(; exp
; exp
= exp
->next
)
317 fprintf(stderr
, " \"%s\" ", exp
->subst
.text
);
320 fprintf(stderr
, " #(%d) ", exp
->subst
.argidx
);
323 fprintf(stderr
, "##");
326 fprintf(stderr
, " <%d> ", exp
->subst
.argidx
);
330 fprintf(stderr
, ">\n");
337 *-------------------------------------------------------------------------
339 *-------------------------------------------------------------------------
341 #if defined(_WIN32) || defined(__MSDOS__)
342 #define INCLUDESEPARATOR ";"
344 #define INCLUDESEPARATOR ":"
347 static char **includepath
;
348 static int nincludepath
= 0;
350 void wpp_add_include_path(const char *path
)
353 char *cpy
= pp_xstrdup(path
);
355 tok
= strtok(cpy
, INCLUDESEPARATOR
);
362 dir
= pp_xstrdup(tok
);
363 for(cptr
= dir
; *cptr
; cptr
++)
365 /* Convert to forward slash */
369 /* Kill eventual trailing '/' */
370 if(*(cptr
= dir
+ strlen(dir
)-1) == '/')
374 includepath
= pp_xrealloc(includepath
, (nincludepath
+1) * sizeof(*includepath
));
375 includepath
[nincludepath
] = dir
;
378 tok
= strtok(NULL
, INCLUDESEPARATOR
);
383 char *wpp_find_include(const char *name
, const char *parent_name
)
385 return wpp_lookup(name
, !!parent_name
, parent_name
, includepath
, nincludepath
);
388 void *pp_open_include(const char *name
, int type
, const char *parent_name
, char **newpath
)
393 if (!(path
= wpp_lookup(name
, type
, parent_name
, includepath
, nincludepath
))) return NULL
;
394 fp
= fopen(path
, "rt");
399 printf("Going to include <%s>\n", path
);
400 if (newpath
) *newpath
= path
;
409 *-------------------------------------------------------------------------
410 * #if, #ifdef, #ifndef, #else, #elif and #endif state management
412 * #if state transitions are made on basis of the current TOS and the next
413 * required state. The state transitions are required to housekeep because
414 * #if:s can be nested. The ignore case is activated to prevent output from
415 * within a false clause.
416 * Some special cases come from the fact that the #elif cases are not
417 * binary, but three-state. The problem is that all other elif-cases must
418 * be false when one true one has been found. A second problem is that the
419 * #else clause is a final clause. No extra #else:s may follow.
422 * if_true Process input to output
423 * if_false Process input but no output
424 * if_ignore Process input but no output
425 * if_elif Process input but no output
426 * if_elsefalse Process input but no output
427 * if_elsettrue Process input to output
429 * The possible state-sequences are [state(stack depth)] (rest can be deduced):
430 * TOS #if 1 #else #endif
431 * if_true(n) if_true(n+1) if_elsefalse(n+1)
432 * if_false(n) if_ignore(n+1) if_ignore(n+1)
433 * if_elsetrue(n) if_true(n+1) if_elsefalse(n+1)
434 * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1)
435 * if_elif(n) if_ignore(n+1) if_ignore(n+1)
436 * if_ignore(n) if_ignore(n+1) if_ignore(n+1)
438 * TOS #if 1 #elif 0 #else #endif
439 * if_true(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
440 * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
441 * if_elsetrue(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
442 * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
443 * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
444 * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
446 * TOS #if 0 #elif 1 #else #endif
447 * if_true(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
448 * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
449 * if_elsetrue(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
450 * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
451 * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
452 * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
454 *-------------------------------------------------------------------------
456 static const char * const pp_if_state_str
[] = {
465 void pp_push_if(pp_if_state_t s
)
467 if(if_stack_idx
>= MAXIFSTACK
)
468 pp_internal_error(__FILE__
, __LINE__
, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK
);
471 fprintf(stderr
, "Push if %s:%d: %s(%d) -> %s(%d)\n", pp_status
.input
, pp_status
.line_number
, pp_if_state_str
[pp_if_state()], if_stack_idx
, pp_if_state_str
[s
], if_stack_idx
+1);
473 if_stack
[if_stack_idx
++] = s
;
484 pp_push_ignore_state();
487 pp_internal_error(__FILE__
, __LINE__
, "Invalid pp_if_state (%d)", (int)pp_if_state());
491 pp_if_state_t
pp_pop_if(void)
493 if(if_stack_idx
<= 0)
495 ppy_error("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
499 switch(pp_if_state())
508 pp_pop_ignore_state();
511 pp_internal_error(__FILE__
, __LINE__
, "Invalid pp_if_state (%d)", (int)pp_if_state());
515 fprintf(stderr
, "Pop if %s:%d: %s(%d) -> %s(%d)\n",
517 pp_status
.line_number
,
518 pp_if_state_str
[pp_if_state()],
520 pp_if_state_str
[if_stack
[if_stack_idx
<= 1 ? if_true
: if_stack_idx
-2]],
523 return if_stack
[--if_stack_idx
];
526 pp_if_state_t
pp_if_state(void)
531 return if_stack
[if_stack_idx
-1];
535 void pp_next_if_state(int i
)
537 switch(pp_if_state())
541 pp_push_if(i
? if_true
: if_false
);
547 pp_push_if(if_ignore
);
550 pp_internal_error(__FILE__
, __LINE__
, "Invalid pp_if_state (%d) in #{if,ifdef,ifndef} directive", (int)pp_if_state());
554 int pp_get_if_depth(void)
559 static void generic_msg(const char *s
, const char *t
, const char *n
, va_list ap
)
561 fprintf(stderr
, "%s:%d:%d: %s: ", pp_status
.input
? pp_status
.input
: "stdin",
562 pp_status
.line_number
, pp_status
.char_number
, t
);
563 vfprintf(stderr
, s
, ap
);
564 fprintf(stderr
, "\n");
567 int ppy_error(const char *s
, ...)
571 generic_msg(s
, "error", ppy_text
, ap
);
576 int ppy_warning(const char *s
, ...)
580 generic_msg(s
, "warning", ppy_text
, ap
);
585 void pp_internal_error(const char *file
, int line
, const char *s
, ...)
589 fprintf(stderr
, "Internal error (please report) %s %d: ", file
, line
);
590 vfprintf(stderr
, s
, ap
);
591 fprintf(stderr
, "\n");
596 static void add_cmdline_defines(void)
600 LIST_FOR_EACH_ENTRY( def
, &cmdline_defines
, struct define
, entry
)
602 if (def
->value
) pp_add_define( def
->name
, def
->value
);
606 static void add_special_defines(void)
608 time_t now
= time(NULL
);
612 strftime(buf
, sizeof(buf
), "\"%b %d %Y\"", localtime(&now
));
613 pp_add_define( "__DATE__", buf
);
615 strftime(buf
, sizeof(buf
), "\"%H:%M:%S\"", localtime(&now
));
616 pp_add_define( "__TIME__", buf
);
618 ppp
= pp_add_define( "__FILE__", "" );
619 ppp
->type
= def_special
;
621 ppp
= pp_add_define( "__LINE__", "" );
622 ppp
->type
= def_special
;
625 /* add a define to the preprocessor list */
626 static void wpp_add_define( const char *name
, const char *value
)
630 if (!value
) value
= "";
632 LIST_FOR_EACH_ENTRY( def
, &cmdline_defines
, struct define
, entry
)
634 if (!strcmp( def
->name
, name
))
637 def
->value
= pp_xstrdup(value
);
642 def
= pp_xmalloc( sizeof(*def
) );
643 def
->name
= pp_xstrdup(name
);
644 def
->value
= pp_xstrdup(value
);
645 list_add_head( &cmdline_defines
, &def
->entry
);
649 /* undefine a previously added definition */
650 void wpp_del_define( const char *name
)
654 LIST_FOR_EACH_ENTRY( def
, &cmdline_defines
, struct define
, entry
)
656 if (!strcmp( def
->name
, name
))
666 /* add a command-line define of the form NAME=VALUE */
667 void wpp_add_cmdline_define( const char *value
)
670 char *str
= pp_xstrdup(value
);
672 p
= strchr( str
, '=' );
674 wpp_add_define( str
, p
);
679 /* set the various debug flags */
680 void wpp_set_debug( int lex_debug
, int parser_debug
, int msg_debug
)
682 pp_flex_debug
= lex_debug
;
683 ppy_debug
= parser_debug
;
684 pp_status
.debug
= msg_debug
;
688 /* set the pedantic mode */
689 void wpp_set_pedantic( int on
)
691 pp_status
.pedantic
= on
;
695 /* the main preprocessor parsing loop */
696 int wpp_parse( const char *input
, FILE *output
)
700 pp_status
.input
= NULL
;
701 pp_status
.line_number
= 1;
702 pp_status
.char_number
= 1;
704 pp_init_define_state();
705 add_cmdline_defines();
706 add_special_defines();
708 if (!input
) pp_status
.file
= stdin
;
709 else if (!(pp_status
.file
= fopen(input
, "rt")))
710 ppy_error("Could not open %s\n", input
);
712 pp_status
.input
= input
? pp_xstrdup(input
) : NULL
;
715 pp_writestring("# 1 \"%s\" 1\n", input
? input
: "");
721 fclose(pp_status
.file
);
722 free(pp_status
.input
);
724 /* Clean if_stack, it could remain dirty on errors */
725 while (pp_get_if_depth()) pp_pop_if();
726 pp_free_define_state();