wpp vendor drop Added: vendor/wine/libs/wpp/ Added: vendor/wine/libs/wpp/current/ Added: vendor/wine/libs/wpp/current/Makefile.in Added: vendor/wine/libs/wpp/current/ppl.l Added: vendor/wine/libs/wpp/current/ppy.y Added: vendor/wine/libs/wpp/current/preproc.c Added: vendor/wine/libs/wpp/current/wpp.c Added: vendor/wine/libs/wpp/current/wpp_private.h _____
Added: vendor/wine/libs/wpp/current/Makefile.in --- vendor/wine/libs/wpp/current/Makefile.in 2005-02-19 18:27:30 UTC (rev 13646) +++ vendor/wine/libs/wpp/current/Makefile.in 2005-02-19 22:16:09 UTC (rev 13647) @@ -0,0 +1,37 @@
+TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +LEXOPT = -Cf #-w -b +YACCOPT = #-v +MODULE = libwpp.a + +C_SRCS = \ + preproc.c \ + wpp.c + +EXTRA_SRCS = ppy.y ppl.l +EXTRA_OBJS = y.tab.o @LEX_OUTPUT_ROOT@.o + +all: $(MODULE) + +@MAKE_RULES@ + +$(MODULE): $(OBJS) + $(RM) $@ + $(AR) $@ $(OBJS) + $(RANLIB) $@ + +y.tab.c y.tab.h: ppy.y + $(YACC) $(YACCOPT) -ppp -d -t $(SRCDIR)/ppy.y + +# hack to allow parallel make +y.tab.h: y.tab.c +y.tab.o: y.tab.h + +@LEX_OUTPUT_ROOT@.c: ppl.l + $(LEX) $(LEXOPT) -d -Ppp -o$@ -8 $(SRCDIR)/ppl.l + +@LEX_OUTPUT_ROOT@.o: y.tab.h + +### Dependencies: Property changes on: vendor/wine/libs/wpp/current/Makefile.in ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native _____
Added: vendor/wine/libs/wpp/current/ppl.l --- vendor/wine/libs/wpp/current/ppl.l 2005-02-19 18:27:30 UTC (rev 13646) +++ vendor/wine/libs/wpp/current/ppl.l 2005-02-19 22:16:09 UTC (rev 13647) @@ -0,0 +1,1476 @@
+/* + * Wrc preprocessor lexical analysis + * + * Copyright 1999-2000 Bertho A. Stultiens (BS) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * History: + * 24-Apr-2000 BS - Started from scratch to restructure everything + * and reintegrate the source into the wine-tree. + * 04-Jan-2000 BS - Added comments about the lexicographical + * grammar to give some insight in the complexity. + * 28-Dec-1999 BS - Eliminated backing-up of the flexer by running + * `flex -b' on the source. This results in some + * weirdo extra rules, but a much faster scanner. + * 23-Dec-1999 BS - Started this file + * + *----------------------------------------------------------------------- -- + * The preprocessor's lexographical grammar (approximately): + * + * pp := {ws} # {ws} if {ws} {expr} {ws} \n + * | {ws} # {ws} ifdef {ws} {id} {ws} \n + * | {ws} # {ws} ifndef {ws} {id} {ws} \n + * | {ws} # {ws} elif {ws} {expr} {ws} \n + * | {ws} # {ws} else {ws} \n + * | {ws} # {ws} endif {ws} \n + * | {ws} # {ws} include {ws} < {anytext} > \n + * | {ws} # {ws} include {ws} " {anytext} " \n + * | {ws} # {ws} define {ws} {anytext} \n + * | {ws} # {ws} define( {arglist} ) {ws} {expansion} \n + * | {ws} # {ws} pragma {ws} {anytext} \n + * | {ws} # {ws} ident {ws} {anytext} \n + * | {ws} # {ws} error {ws} {anytext} \n + * | {ws} # {ws} warning {ws} {anytext} \n + * | {ws} # {ws} line {ws} " {anytext} " {number} \n + * | {ws} # {ws} {number} " {anytext} " {number} [ {number} [{number}] ] \n + * | {ws} # {ws} \n + * + * ws := [ \t\r\f\v]* + * + * expr := {expr} [+-*%^/|&] {expr} + * | {expr} {logor|logand} {expr} + * | [!~+-] {expr} + * | {expr} ? {expr} : {expr} + * + * logor := || + * + * logand := && + * + * id := [a-zA-Z_][a-zA-Z0-9_]* + * + * anytext := [^\n]* (see note) + * + * arglist := + * | {id} + * | {arglist} , {id} + * | {arglist} , {id} ... + * + * expansion := {id} + * | # {id} + * | {anytext} + * | {anytext} ## {anytext} + * + * number := [0-9]+ + * + * Note: "anytext" is not always "[^\n]*". This is because the + * trailing context must be considered as well. + * + * The only certain assumption for the preprocessor to make is that + * directives start at the beginning of the line, followed by a '#' + * and end with a newline. + * Any directive may be suffixed with a line-continuation. Also + * classical comment / *...* / (note: no comments within comments, + * therefore spaces) is considered to be a line-continuation + * (according to gcc and egcs AFAIK, ANSI is a bit vague). + * Comments have not been added to the above grammar for simplicity + * reasons. However, it is allowed to enter comment anywhere within + * the directives as long as they do not interfere with the context. + * All comments are considered to be deletable whitespace (both + * classical form "/ *...* /" and C++ form "//...\n"). + * + * All recursive scans, except for macro-expansion, are done by the + * parser, whereas the simple state transitions of non-recursive + * directives are done in the scanner. This results in the many + * exclusive start-conditions of the scanner. + * + * Macro expansions are slightly more difficult because they have to + * prescan the arguments. Parameter substitution is literal if the + * substitution is # or ## (either side). This enables new identifiers + * to be created (see 'info cpp' node Macro|Pitfalls|Prescan for more + * information). + * + * FIXME: Variable macro parameters is recognized, but not yet + * expanded. I have to reread the ANSI standard on the subject (yes, + * ANSI defines it). + * + * The following special defines are supported: + * __FILE__ -> "thissource.c" + * __LINE__ -> 123 + * __DATE__ -> "May 1 2000" + * __TIME__ -> "23:59:59" + * These macros expand, as expected, into their ANSI defined values. + * + * The same include prevention is implemented as gcc and egcs does. + * This results in faster processing because we do not read the text + * at all. Some wine-sources attempt to include the same file 4 or 5 + * times. This strategy also saves a lot blank output-lines, which in + * its turn improves the real resource scanner/parser. + * + */ + +/* + * Special flex options and exclusive scanner start-conditions + */ +%option stack +%option never-interactive + +%x pp_pp +%x pp_eol +%x pp_inc +%x pp_dqs +%x pp_sqs +%x pp_iqs +%x pp_comment +%x pp_def +%x pp_define +%x pp_macro +%x pp_mbody +%x pp_macign +%x pp_macscan +%x pp_macexp +%x pp_if +%x pp_ifd +%x pp_endif +%x pp_line +%x pp_defined +%x pp_ignore +%x RCINCL + +ws [ \v\f\t\r] +cident [a-zA-Z_][0-9a-zA-Z_]* +ul [uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL] + +%{ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> + +#include "wpp_private.h" +#include "y.tab.h" + +/* + * Make sure that we are running an appropriate version of flex. + */ +#if !defined(YY_FLEX_MAJOR_VERSION) || (1000 * YY_FLEX_MAJOR_VERSION + YY_FLEX_MINOR_VERSION < 2005) +#error Must use flex version 2.5.1 or higher (yy_scan_* routines are required). +#endif + +#define YY_USE_PROTOS +#define YY_NO_UNPUT +#define YY_READ_BUF_SIZE 65536 /* So we read most of a file at once */ + +#define yy_current_state() YY_START +#define yy_pp_state(x) yy_pop_state(); yy_push_state(x) + +/* + * Always update the current character position within a line + */ +#define YY_USER_ACTION pp_status.char_number+=ppleng; + +/* + * Buffer management for includes and expansions + */ +#define MAXBUFFERSTACK 128 /* Nesting more than 128 includes or macro expansion textss is insane */ + +typedef struct bufferstackentry { + YY_BUFFER_STATE bufferstate; /* Buffer to switch back to */ + pp_entry_t *define; /* Points to expanding define or NULL if handling includes */ + int line_number; /* Line that we were handling */ + int char_number; /* The current position on that line */ + const char *filename; /* Filename that we were handling */ + int if_depth; /* How many #if:s deep to check matching #endif:s */ + int ncontinuations; /* Remember the continuation state */ + int should_pop; /* Set if we must pop the start-state on EOF */ + /* Include management */ + include_state_t incl; + char *include_filename; + int pass_data; +} bufferstackentry_t; + +#define ALLOCBLOCKSIZE (1 << 10) /* Allocate these chunks at a time for string-buffers */ + +/* + * Macro expansion nesting + * We need the stack to handle expansions while scanning + * a macro's arguments. The TOS must always be the macro + * that receives the current expansion from the scanner. + */ +#define MAXMACEXPSTACK 128 /* Nesting more than 128 macro expansions is insane */ + +typedef struct macexpstackentry { + pp_entry_t *ppp; /* This macro we are scanning */ + char **args; /* With these arguments */ + char **ppargs; /* Resulting in these preprocessed arguments */ + int *nnls; /* Number of newlines per argument */ + int nargs; /* And this many arguments scanned */ + int parentheses; /* Nesting level of () */ + int curargsize; /* Current scanning argument's size */ + int curargalloc; /* Current scanning argument's block allocated */ + char *curarg; /* Current scanning argument's content */ +} macexpstackentry_t; + +#define MACROPARENTHESES() (top_macro()->parentheses) + +/* + * Prototypes + */ +static void newline(int); +static int make_number(int radix, YYSTYPE *val, const char *str, int len); +static void put_buffer(const char *s, int len); +/* Buffer management */ +static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop); +static bufferstackentry_t *pop_buffer(void); +/* String functions */ +static void new_string(void); +static void add_string(const char *str, int len); +static char *get_string(void); +static void put_string(void); +static int string_start(void); +/* Macro functions */ +static void push_macro(pp_entry_t *ppp); +static macexpstackentry_t *top_macro(void); +static macexpstackentry_t *pop_macro(void); +static void free_macro(macexpstackentry_t *mep); +static void add_text_to_macro(const char *text, int len); +static void macro_add_arg(int last); +static void macro_add_expansion(void); +/* Expansion */ +static void expand_special(pp_entry_t *ppp); +static void expand_define(pp_entry_t *ppp); +static void expand_macro(macexpstackentry_t *mep); + +/* + * Local variables + */ +static int ncontinuations; + +static int strbuf_idx = 0; +static int strbuf_alloc = 0; +static char *strbuffer = NULL; +static int str_startline; + +static macexpstackentry_t *macexpstack[MAXMACEXPSTACK]; +static int macexpstackidx = 0; + +static bufferstackentry_t bufferstack[MAXBUFFERSTACK]; +static int bufferstackidx = 0; + +static int pass_data=1; + +/* + * Global variables + */ +include_state_t pp_incl_state = +{ + -1, /* state */ + NULL, /* ppp */ + 0, /* ifdepth */ + 0 /* seen_junk */ +}; + +includelogicentry_t *pp_includelogiclist = NULL; + +%} + +/* + ************************************************************************ ** + * The scanner starts here + ************************************************************************ ** + */ + +%% + /* + * Catch line-continuations. + * Note: Gcc keeps the line-continuations in, for example, strings + * intact. However, I prefer to remove them all so that the next + * scanner will not need to reduce the continuation state. + * + * <*>\\n newline(0); + */ + + /* + * Detect the leading # of a preprocessor directive. + */ +<INITIAL,pp_ignore>^{ws}*# pp_incl_state.seen_junk++; yy_push_state(pp_pp); + + /* + * Scan for the preprocessor directives + */ +<pp_pp>{ws}*include{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_inc); return tINCLUDE;} else {yy_pp_state(pp_eol);} +<pp_pp>{ws}*define{ws}* yy_pp_state(yy_current_state() != pp_ignore ? pp_def : pp_eol); +<pp_pp>{ws}*error{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tERROR; +<pp_pp>{ws}*warning{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tWARNING; +<pp_pp>{ws}*pragma{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tPRAGMA; +<pp_pp>{ws}*ident{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tPPIDENT; +<pp_pp>{ws}*undef{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_ifd); return tUNDEF;} else {yy_pp_state(pp_eol);} +<pp_pp>{ws}*ifdef{ws}* yy_pp_state(pp_ifd); return tIFDEF; +<pp_pp>{ws}*ifndef{ws}* pp_incl_state.seen_junk--; yy_pp_state(pp_ifd); return tIFNDEF; +<pp_pp>{ws}*if{ws}* yy_pp_state(pp_if); return tIF; +<pp_pp>{ws}*elif{ws}* yy_pp_state(pp_if); return tELIF; +<pp_pp>{ws}*else{ws}* yy_pp_state(pp_endif); return tELSE; +<pp_pp>{ws}*endif{ws}* yy_pp_state(pp_endif); return tENDIF; +<pp_pp>{ws}*line{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_line); return tLINE;} else {yy_pp_state(pp_eol);} +<pp_pp>{ws}+ if(yy_top_state() != pp_ignore) {yy_pp_state(pp_line); return tGCCLINE;} else {yy_pp_state(pp_eol);} +<pp_pp>{ws}*[a-z]+ pperror("Invalid preprocessor token '%s'", pptext); +<pp_pp>\r?\n newline(1); yy_pop_state(); return tNL; /* This could be the null-token */ +<pp_pp>\\r?\n newline(0); +<pp_pp>\\r? pperror("Preprocessor junk '%s'", pptext); +<pp_pp>. return *pptext; + + /* + * Handle #include and #line + */ +<pp_line>[0-9]+ return make_number(10, &pplval, pptext, ppleng); +<pp_inc>< new_string(); add_string(pptext, ppleng); yy_push_state(pp_iqs); +<pp_inc,pp_line>" new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs); +<pp_inc,pp_line>{ws}+ ; +<pp_inc,pp_line>\n newline(1); yy_pop_state(); return tNL; +<pp_inc,pp_line>\\r?\n newline(0); +<pp_inc,pp_line>(\\r?)|(.) pperror(yy_current_state() == pp_inc ? "Trailing junk in #include" : "Trailing junk in #line"); + + /* + * Ignore all input when a false clause is parsed + */ +<pp_ignore>[^#/\\n]+ ; +<pp_ignore>\n newline(1); +<pp_ignore>\\r?\n newline(0); +<pp_ignore>(\\r?)|(.) ; + + /* + * Handle #if and #elif. + * These require conditionals to be evaluated, but we do not + * want to jam the scanner normally when we see these tokens. + * Note: tIDENT is handled below. + */ + +<pp_if>0[0-7]*{ul}? return make_number(8, &pplval, pptext, ppleng); +<pp_if>0[0-7]*[8-9]+{ul}? pperror("Invalid octal digit"); +<pp_if>[1-9][0-9]*{ul}? return make_number(10, &pplval, pptext, ppleng); +<pp_if>0[xX][0-9a-fA-F]+{ul}? return make_number(16, &pplval, pptext, ppleng); +<pp_if>0[xX] pperror("Invalid hex number"); +<pp_if>defined yy_push_state(pp_defined); return tDEFINED; +<pp_if>"<<" return tLSHIFT; +<pp_if>">>" return tRSHIFT; +<pp_if>"&&" return tLOGAND; +<pp_if>"||" return tLOGOR; +<pp_if>"==" return tEQ; +<pp_if>"!=" return tNE; +<pp_if>"<=" return tLTE; +<pp_if>">=" return tGTE; +<pp_if>\n newline(1); yy_pop_state(); return tNL; +<pp_if>\\r?\n newline(0); +<pp_if>\\r? pperror("Junk in conditional expression"); +<pp_if>{ws}+ ; +<pp_if>' new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs); +<pp_if>" pperror("String constants not allowed in conditionals"); +<pp_if>. return *pptext; + + /* + * Handle #ifdef, #ifndef and #undef + * to get only an untranslated/unexpanded identifier + */ +<pp_ifd>{cident} pplval.cptr = pp_xstrdup(pptext); return tIDENT; +<pp_ifd>{ws}+ ; +<pp_ifd>\n newline(1); yy_pop_state(); return tNL; +<pp_ifd>\\r?\n newline(0); +<pp_ifd>(\\r?)|(.) pperror("Identifier expected"); + + /* + * Handle #else and #endif. + */ +<pp_endif>{ws}+ ; +<pp_endif>\n newline(1); yy_pop_state(); return tNL; +<pp_endif>\\r?\n newline(0); +<pp_endif>. pperror("Garbage after #else or #endif."); + + /* + * Handle the special 'defined' keyword. + * This is necessary to get the identifier prior to any + * substitutions. + */ +<pp_defined>{cident} yy_pop_state(); pplval.cptr = pp_xstrdup(pptext); return tIDENT; +<pp_defined>{ws}+ ; +<pp_defined>(()|()) return *pptext; +<pp_defined>\\r?\n newline(0); +<pp_defined>(\.)|(\n)|(.) pperror("Identifier expected"); + + /* + * Handle #error, #warning, #pragma and #ident. + * Pass everything literally to the parser, which + * will act appropriately. + * Comments are stripped from the literal text. + */ +<pp_eol>[^/\\n]+ if(yy_top_state() != pp_ignore) { pplval.cptr = pp_xstrdup(pptext); return tLITERAL; } +<pp_eol>/[^/\\n*]* if(yy_top_state() != pp_ignore) { pplval.cptr = pp_xstrdup(pptext); return tLITERAL; } +<pp_eol>(\\r?)|(/[^/*]) if(yy_top_state() != pp_ignore) { pplval.cptr = pp_xstrdup(pptext); return tLITERAL; } +<pp_eol>\n newline(1); yy_pop_state(); if(yy_current_state() != pp_ignore) { return tNL; } +<pp_eol>\\r?\n newline(0); + + /* + * Handle left side of #define + */ +<pp_def>{cident}( pplval.cptr = pp_xstrdup(pptext); pplval.cptr[ppleng-1] = '\0'; yy_pp_state(pp_macro); return tMACRO; +<pp_def>{cident} pplval.cptr = pp_xstrdup(pptext); yy_pp_state(pp_define); return tDEFINE; +<pp_def>{ws}+ ; +<pp_def>\\r?\n newline(0); +<pp_def>(\\r?)|(\n)|(.) perror("Identifier expected"); + + /* + * Scan the substitution of a define + */ +<pp_define>[^'"/\\n]+ pplval.cptr = pp_xstrdup(pptext); return tLITERAL; +<pp_define>(\\r?)|(/[^/*]) pplval.cptr = pp_xstrdup(pptext); return tLITERAL; +<pp_define>\\r?\n{ws}+ newline(0); pplval.cptr = pp_xstrdup(" "); return tLITERAL; +<pp_define>\\r?\n newline(0); +<pp_define>\n newline(1); yy_pop_state(); return tNL; +<pp_define>' new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs); +<pp_define>" new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs); + + /* + * Scan the definition macro arguments + */ +<pp_macro>){ws}* yy_pp_state(pp_mbody); return tMACROEND; +<pp_macro>{ws}+ ; +<pp_macro>{cident} pplval.cptr = pp_xstrdup(pptext); return tIDENT; +<pp_macro>, return ','; +<pp_macro>"..." return tELIPSIS; +<pp_macro>(\\r?)|(\n)|(.)|(..?) pperror("Argument identifier expected"); +<pp_macro>\\r?\n newline(0); + + /* + * Scan the substitution of a macro + */ +<pp_mbody>[^a-zA-Z0-9'"#/\\n]+ pplval.cptr = pp_xstrdup(pptext); return tLITERAL; +<pp_mbody>{cident} pplval.cptr = pp_xstrdup(pptext); return tIDENT; +<pp_mbody>## return tCONCAT; +<pp_mbody># return tSTRINGIZE; +<pp_mbody>[0-9][^'"#/\\n]* pplval.cptr = pp_xstrdup(pptext); return tLITERAL; +<pp_mbody>(\\r?)|(/[^/*'"#\\n]*) pplval.cptr = pp_xstrdup(pptext); return tLITERAL; +<pp_mbody>\\r?\n{ws}+ newline(0); pplval.cptr = pp_xstrdup(" "); return tLITERAL; +<pp_mbody>\\r?\n newline(0); +<pp_mbody>\n newline(1); yy_pop_state(); return tNL; +<pp_mbody>' new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs); +<pp_mbody>" new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs); + + /* + * Macro expansion text scanning. + * This state is active just after the identifier is scanned + * that triggers an expansion. We *must* delete the leading + * whitespace before we can start scanning for arguments. + * + * If we do not see a '(' as next trailing token, then we have + * a false alarm. We just continue with a nose-bleed... + */ +<pp_macign>{ws}*/( yy_pp_state(pp_macscan); +<pp_macign>{ws}*\n { + if(yy_top_state() != pp_macscan) + newline(0); + } +<pp_macign>{ws}*\\r?\n newline(0); +<pp_macign>{ws}+|{ws}*\\r?|. { + macexpstackentry_t *mac = pop_macro(); + yy_pop_state(); + put_buffer(mac->ppp->ident, strlen(mac->ppp->ident)); + put_buffer(pptext, ppleng); + free_macro(mac); + } + + /* + * Macro expansion argument text scanning. + * This state is active when a macro's arguments are being read for expansion. + */ +<pp_macscan>( { + if(++MACROPARENTHESES() > 1) + add_text_to_macro(pptext, ppleng); + } +<pp_macscan>) { + if(--MACROPARENTHESES() == 0) + { + yy_pop_state(); + macro_add_arg(1); + } + else + add_text_to_macro(pptext, ppleng); + } +<pp_macscan>, { + if(MACROPARENTHESES() > 1) + add_text_to_macro(pptext, ppleng); + else + macro_add_arg(0); + } +<pp_macscan>" new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs); +<pp_macscan>' new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs); +<pp_macscan>"/*" yy_push_state(pp_comment); add_text_to_macro(" ", 1); +<pp_macscan>\n pp_status.line_number++; pp_status.char_number = 1; add_text_to_macro(pptext, ppleng); +<pp_macscan>([^/(),\\n"']+)|(/[^/*(),\\n'"]*)|(\\r?)|(.) add_text_to_macro(pptext, ppleng); +<pp_macscan>\\r?\n newline(0); + + /* + * Comment handling (almost all start-conditions) + */ +<INITIAL,pp_pp,pp_ignore,pp_eol,pp_inc,pp_if,pp_ifd,pp_endif,pp_defined ,pp_def,pp_define,pp_macro,pp_mbody,RCINCL>"/*" yy_push_state(pp_comment); +<pp_comment>[^*\n]*|"*"+[^*/\n]* ; +<pp_comment>\n newline(0); +<pp_comment>"*"+"/" yy_pop_state(); + + /* + * Remove C++ style comment (almost all start-conditions) + */ +<INITIAL,pp_pp,pp_ignore,pp_eol,pp_inc,pp_if,pp_ifd,pp_endif,pp_defined ,pp_def,pp_define,pp_macro,pp_mbody,pp_macscan,RCINCL>"//"[^\n]* { + if(pptext[ppleng-1] == '\') + ppwarning("C++ style comment ends with an escaped newline (escape ignored)"); + } + + /* + * Single, double and <> quoted constants + */ +<INITIAL,pp_macexp>" pp_incl_state.seen_junk++; new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs); +<INITIAL,pp_macexp>' pp_incl_state.seen_junk++; new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs); +<pp_dqs>[^"\\n]+ add_string(pptext, ppleng); +<pp_dqs>" { + add_string(pptext, ppleng); + yy_pop_state(); + switch(yy_current_state()) + { + case pp_pp: + case pp_define: + case pp_mbody: + case pp_inc: + case pp_line: + case RCINCL: + if (yy_current_state()==RCINCL) yy_pop_state(); + pplval.cptr = get_string(); + return tDQSTRING; + default: + put_string(); + } + } +<pp_sqs>[^'\\n]+ add_string(pptext, ppleng); +<pp_sqs>' { + add_string(pptext, ppleng); + yy_pop_state(); + switch(yy_current_state()) + { + case pp_if: + case pp_define: + case pp_mbody: + pplval.cptr = get_string(); + return tSQSTRING; + default: + put_string(); + } + } +<pp_iqs>[^>\\n]+ add_string(pptext, ppleng); +<pp_iqs>> { + add_string(pptext, ppleng); + yy_pop_state(); + pplval.cptr = get_string(); + return tIQSTRING; + } +<pp_dqs>\\r?\n { + /* + * This is tricky; we need to remove the line-continuation + * from preprocessor strings, but OTOH retain them in all + * other strings. This is because the resource grammar is + * even more braindead than initially analysed and line- + * continuations in strings introduce, sigh, newlines in + * the output. There goes the concept of non-breaking, non- + * spacing whitespace. + */ + switch(yy_top_state()) + { + case pp_pp: + case pp_define: + case pp_mbody: + case pp_inc: + case pp_line: + newline(0); + break; + default: + add_string(pptext, ppleng); + newline(-1); + } + } +<pp_iqs,pp_dqs,pp_sqs>\. add_string(pptext, ppleng); +<pp_iqs,pp_dqs,pp_sqs>\n { + newline(1); + add_string(pptext, ppleng); + ppwarning("Newline in string constant encounterd (started line %d)", string_start()); + } + + /* + * Identifier scanning + */ +<INITIAL,pp_if,pp_inc,pp_macexp>{cident} { + pp_entry_t *ppp; + pp_incl_state.seen_junk++; + if(!(ppp = pplookup(pptext))) + { + if(yy_current_state() == pp_inc) + pperror("Expected include filename"); + + if(yy_current_state() == pp_if) + { + pplval.cptr = pp_xstrdup(pptext); + return tIDENT; + } + else { + if((yy_current_state()==INITIAL) && (strcasecmp(pptext,"RCINCLUDE")==0)){ + yy_push_state(RCINCL); + return tRCINCLUDE; + } + else put_buffer(pptext, ppleng); + } + } + else if(!ppp->expanding) + { + switch(ppp->type) + { + case def_special: + expand_special(ppp); + break; + case def_define: + expand_define(ppp); + break; + case def_macro: + yy_push_state(pp_macign); + push_macro(ppp); + break; + default: + pp_internal_error(__FILE__, __LINE__, "Invalid define type %d\n", ppp->type); + } + } + } + + /* + * Everything else that needs to be passed and + * newline and continuation handling + */ +<INITIAL,pp_macexp>[^a-zA-Z_#'"/\\n \r\t\f\v]+|(/|\)[^a-zA-Z_/*'"\\n \r\t\v\f]* pp_incl_state.seen_junk++; put_buffer(pptext, ppleng); +<INITIAL,pp_macexp>{ws}+ put_buffer(pptext, ppleng); +<INITIAL>\n newline(1); +<INITIAL>\\r?\n newline(0); +<INITIAL>\\r? pp_incl_state.seen_junk++; put_buffer(pptext, ppleng); + + /* + * Special catcher for macro argmument expansion to prevent + * newlines to propagate to the output or admin. + */ +<pp_macexp>(\n)|(.)|(\\r?(\n|.)) put_buffer(pptext, ppleng); + +<RCINCL>[A-Za-z0-9_.\/]+ { + pplval.cptr=pp_xstrdup(pptext); + yy_pop_state(); + return tRCINCLUDEPATH; + } + +<RCINCL>{ws}+ ; + +<RCINCL>" { + new_string(); add_string(pptext,ppleng);yy_push_state(pp_dqs); + } + + /* + * This is a 'catch-all' rule to discover errors in the scanner + * in an orderly manner. + */ +<*>. pp_incl_state.seen_junk++; ppwarning("Unmatched text '%c' (0x%02x); please report\n", isprint(*pptext & 0xff) ? *pptext : ' ', *pptext); + +<<EOF>> { + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + bufferstackentry_t *bep = pop_buffer(); + + if((!bep && pp_get_if_depth()) || (bep && pp_get_if_depth() != bep->if_depth)) + ppwarning("Unmatched #if/#endif at end of file"); + + if(!bep) + { + if(YY_START != INITIAL) + pperror("Unexpected end of file during preprocessing"); + yyterminate(); + } + else if(bep->should_pop == 2) + { + macexpstackentry_t *mac; + mac = pop_macro(); + expand_macro(mac); + } + pp_delete_buffer(b); + } + +%% +/* + ************************************************************************ ** + * Support functions + ************************************************************************ ** + */ + +#ifndef ppwrap +int ppwrap(void) +{ + return 1; +} +#endif + + +/* + *----------------------------------------------------------------------- -- + * Output newlines or set them as continuations + * + * Input: -1 - Don't count this one, but update local position (see pp_dqs) + * 0 - Line-continuation seen and cache output + * 1 - Newline seen and flush output + *----------------------------------------------------------------------- -- + */ +static void newline(int dowrite) +{ + pp_status.line_number++; + pp_status.char_number = 1; + + if(dowrite == -1) + return; + + ncontinuations++; + if(dowrite) + { + for(;ncontinuations; ncontinuations--) + put_buffer("\n", 1); + } +} + + +/* + *----------------------------------------------------------------------- -- + * Make a number out of an any-base and suffixed string + * + * Possible number extensions: + * - "" int + * - "L" long int + * - "LL" long long int + * - "U" unsigned int + * - "UL" unsigned long int + * - "ULL" unsigned long long int + * - "LU" unsigned long int + * - "LLU" unsigned long long int + * - "LUL" invalid + * + * FIXME: + * The sizes of resulting 'int' and 'long' are compiler specific. + * I depend on sizeof(int) > 2 here (although a relatively safe + * assumption). + * Long longs are not yet implemented because this is very compiler + * specific and I don't want to think too much about the problems. + * + *----------------------------------------------------------------------- -- + */ +static int make_number(int radix, YYSTYPE *val, const char *str, int len) +{ + int is_l = 0; + int is_ll = 0; + int is_u = 0; + char ext[4]; + + ext[3] = '\0'; + ext[2] = toupper(str[len-1]); + ext[1] = len > 1 ? toupper(str[len-2]) : ' '; + ext[0] = len > 2 ? toupper(str[len-3]) : ' '; + + if(!strcmp(ext, "LUL")) + pperror("Invalid constant suffix"); + else if(!strcmp(ext, "LLU") || !strcmp(ext, "ULL")) + { + is_ll++; + is_u++; + } + else if(!strcmp(ext+1, "LU") || !strcmp(ext+1, "UL")) + { + is_l++; + is_u++; + } + else if(!strcmp(ext+1, "LL")) + { + is_ll++; + } + else if(!strcmp(ext+2, "L")) + { + is_l++; + } + else if(!strcmp(ext+2, "U")) + { + is_u++; + } + + if(is_ll) + pp_internal_error(__FILE__, __LINE__, "long long constants not implemented yet"); + + if(is_u && is_l) + { + val->ulong = strtoul(str, NULL, radix); + return tULONG; + } + else if(!is_u && is_l) + { + val->slong = strtol(str, NULL, radix); + return tSLONG; + } + else if(is_u && !is_l) + { + val->uint = (unsigned int)strtoul(str, NULL, radix); + return tUINT; + } + + /* Else it must be an int... */ + val->sint = (int)strtol(str, NULL, radix); + return tSINT; +} + + +/* + *----------------------------------------------------------------------- -- + * Macro and define expansion support + * + * FIXME: Variable macro arguments. + *----------------------------------------------------------------------- -- + */ +static void expand_special(pp_entry_t *ppp) +{ + const char *dbgtext = "?"; + static char *buf = NULL; + + assert(ppp->type == def_special); + + if(!strcmp(ppp->ident, "__LINE__")) + { + dbgtext = "def_special(__LINE__)"; + buf = pp_xrealloc(buf, 32); + sprintf(buf, "%d", pp_status.line_number); + } + else if(!strcmp(ppp->ident, "__FILE__")) + { + dbgtext = "def_special(__FILE__)"; + buf = pp_xrealloc(buf, strlen(pp_status.input) + 3); + sprintf(buf, ""%s"", pp_status.input); + } + else + pp_internal_error(__FILE__, __LINE__, "Special macro '%s' not found...\n", ppp->ident); + + if(pp_flex_debug) + fprintf(stderr, "expand_special(%d): %s:%d: '%s' -> '%s'\n", + macexpstackidx, + pp_status.input, + pp_status.line_number, + ppp->ident, + buf ? buf : ""); + + if(buf && buf[0]) + { + push_buffer(ppp, NULL, NULL, 0); + yy_scan_string(buf); + } +} + +static void expand_define(pp_entry_t *ppp) +{ + assert(ppp->type == def_define); + + if(pp_flex_debug) + fprintf(stderr, "expand_define(%d): %s:%d: '%s' -> '%s'\n", + macexpstackidx, + pp_status.input, + pp_status.line_number, + ppp->ident, + ppp->subst.text); + if(ppp->subst.text && ppp->subst.text[0]) + { + push_buffer(ppp, NULL, NULL, 0); + yy_scan_string(ppp->subst.text); + } +} + +static int curdef_idx = 0; +static int curdef_alloc = 0; +static char *curdef_text = NULL; + +static void add_text(const char *str, int len) +{ + if(len == 0) + return; + if(curdef_idx >= curdef_alloc || curdef_alloc - curdef_idx < len) + { + curdef_alloc += (len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1); + curdef_text = pp_xrealloc(curdef_text, curdef_alloc * sizeof(curdef_text[0])); + if(curdef_alloc > 65536) + ppwarning("Reallocating macro-expansion buffer larger than 64kB"); + } + memcpy(&curdef_text[curdef_idx], str, len); + curdef_idx += len; +} + +static mtext_t *add_expand_text(mtext_t *mtp, macexpstackentry_t *mep, int *nnl) +{ + char *cptr; + char *exp; + int tag; + int n; + + if(mtp == NULL) + return NULL; + + switch(mtp->type) + { + case exp_text: + if(pp_flex_debug) + fprintf(stderr, "add_expand_text: exp_text: '%s'\n", mtp->subst.text); + add_text(mtp->subst.text, strlen(mtp->subst.text)); + break; + + case exp_stringize: + if(pp_flex_debug) + fprintf(stderr, "add_expand_text: exp_stringize(%d): '%s'\n", + mtp->subst.argidx, + mep->args[mtp->subst.argidx]); + cptr = mep->args[mtp->subst.argidx]; [truncated at 1000 lines; 2307 more skipped]