From 27337af65c73006a2b1059f765bcd102405edf5d Mon Sep 17 00:00:00 2001 From: Bertho Stultiens Date: Mon, 1 May 2000 20:05:58 +0000 Subject: [PATCH] - Implemented a new preprocessor that is (nearly) ANSI-C compliant. The old parser has been stripped from the old preprocessor-code which cleaned up both resource-scanner and -parser. - Standard defines have been introduced (see README.wrc) - Both preprocessor- and resource-scanner have been optimized slightly so that no backing up is required (one char lookahead is enough). - Filename-scanning has been cleaned up, though not perfect yet. - User-type resources are compatible now. - Line-continuation in strings is corrected so that it does not introduce a newline in the output. --- dlls/comctl32/rsrc.rc | 1 + dlls/commdlg/rsrc.rc | 1 + dlls/display/disp.rc | 2 +- dlls/shell32/shres.rc | 1 + programs/clock/Makefile.in | 4 - programs/notepad/Makefile.in | 4 - programs/progman/Makefile.in | 4 - programs/winemine/Makefile.in | 4 - programs/winhelp/Makefile.in | 4 - resources/user32.rc | 1 + tools/Makefile.in | 2 +- tools/wrc/.cvsignore | 3 + tools/wrc/CHANGES | 15 + tools/wrc/Makefile.in | 20 +- tools/wrc/README.wrc | 112 +-- tools/wrc/newstruc.c | 1 + tools/wrc/parser.h | 10 +- tools/wrc/parser.l | 792 +++++-------------- tools/wrc/parser.y | 699 ++++++++-------- tools/wrc/ppl.l | 1407 +++++++++++++++++++++++++++++++++ tools/wrc/ppy.y | 624 +++++++++++++++ tools/wrc/preproc.c | 386 ++++++--- tools/wrc/preproc.h | 199 ++++- tools/wrc/utils.c | 79 +- tools/wrc/utils.h | 14 +- tools/wrc/wrc.c | 206 ++++- tools/wrc/wrc.h | 23 +- tools/wrc/writeres.c | 5 - 28 files changed, 3435 insertions(+), 1188 deletions(-) create mode 100644 tools/wrc/ppl.l create mode 100644 tools/wrc/ppy.y diff --git a/dlls/comctl32/rsrc.rc b/dlls/comctl32/rsrc.rc index 7daddab5eac..7b0372522ed 100644 --- a/dlls/comctl32/rsrc.rc +++ b/dlls/comctl32/rsrc.rc @@ -1,3 +1,4 @@ +#include "windef.h" #include "winuser.h" #include "comctl32.h" diff --git a/dlls/commdlg/rsrc.rc b/dlls/commdlg/rsrc.rc index 5d4748a381c..81126adb1d5 100644 --- a/dlls/commdlg/rsrc.rc +++ b/dlls/commdlg/rsrc.rc @@ -3,6 +3,7 @@ * */ +#include "windef.h" #include "winuser.h" #include "winnls.h" #include "cdlg.h" diff --git a/dlls/display/disp.rc b/dlls/display/disp.rc index ea89eeaeee7..d89a745c368 100644 --- a/dlls/display/disp.rc +++ b/dlls/display/disp.rc @@ -3,7 +3,7 @@ * */ -1 "OEMBIN" +1 OEMBIN { 0x11, /* vertical thumb height (in pixels) */ 0x11, /* horizontal thumb width (in pixels) */ diff --git a/dlls/shell32/shres.rc b/dlls/shell32/shres.rc index d5ea4112721..e87c4ecc23b 100644 --- a/dlls/shell32/shres.rc +++ b/dlls/shell32/shres.rc @@ -3,6 +3,7 @@ * */ +#include "windef.h" #include "winuser.h" #include "winnls.h" #include "shlobj.h" diff --git a/programs/clock/Makefile.in b/programs/clock/Makefile.in index 4cf9f3176f0..89b04b00517 100644 --- a/programs/clock/Makefile.in +++ b/programs/clock/Makefile.in @@ -25,10 +25,6 @@ all: check_wrc $(PROGRAMS) @MAKE_RULES@ -# Override resource compiler rules -.rc.s: - $(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s - clock: $(OBJS) $(CC) -o clock $(OBJS) $(DLL_LINK) $(LIBS) diff --git a/programs/notepad/Makefile.in b/programs/notepad/Makefile.in index 4cce51bb0da..b8dbfbe51bd 100644 --- a/programs/notepad/Makefile.in +++ b/programs/notepad/Makefile.in @@ -26,10 +26,6 @@ all: check_wrc $(PROGRAMS) @MAKE_RULES@ -# Override resource compiler rules -.rc.s: - $(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s - notepad: $(OBJS) $(CC) -o notepad $(OBJS) $(DLL_LINK) $(LIBS) diff --git a/programs/progman/Makefile.in b/programs/progman/Makefile.in index 722564f52ed..e5658643a92 100644 --- a/programs/progman/Makefile.in +++ b/programs/progman/Makefile.in @@ -28,10 +28,6 @@ all: check_wrc $(PROGRAMS) @MAKE_RULES@ -# Override resource compiler rules -.rc.s: - $(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s - progman: $(OBJS) $(CC) -o progman $(OBJS) $(DLL_LINK) $(LIBS) diff --git a/programs/winemine/Makefile.in b/programs/winemine/Makefile.in index 7c9b943ab23..ea6129c4d5d 100644 --- a/programs/winemine/Makefile.in +++ b/programs/winemine/Makefile.in @@ -22,10 +22,6 @@ all: check_wrc $(PROGRAMS) @MAKE_RULES@ -# Override resource compiler rules -.rc.s: - $(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s - winemine: $(OBJS) $(CC) -o winemine $(OBJS) $(DLL_LINK) $(LIBS) diff --git a/programs/winhelp/Makefile.in b/programs/winhelp/Makefile.in index a59e55eedac..218165712bd 100644 --- a/programs/winhelp/Makefile.in +++ b/programs/winhelp/Makefile.in @@ -27,10 +27,6 @@ depend: y.tab.h @MAKE_RULES@ -# Override resource compiler rules -.rc.s: - $(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s - winhelp: $(OBJS) $(CC) -o winhelp $(OBJS) $(DLL_LINK) $(LIBS) diff --git a/resources/user32.rc b/resources/user32.rc index 0b5c1106c48..3518df00542 100644 --- a/resources/user32.rc +++ b/resources/user32.rc @@ -3,6 +3,7 @@ * */ +#include "windef.h" #include "winuser.h" #include "winnls.h" #include "dlgs.h" diff --git a/tools/Makefile.in b/tools/Makefile.in index 76affffadf5..b985f3e667f 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -19,7 +19,7 @@ EXTRASUBDIRS = \ winapi_check/win32 \ wineconf.libs -all: $(PROGRAMS) +all: $(PROGRAMS) wrc @MAKE_RULES@ diff --git a/tools/wrc/.cvsignore b/tools/wrc/.cvsignore index b99ef0a0938..e2959437d89 100644 --- a/tools/wrc/.cvsignore +++ b/tools/wrc/.cvsignore @@ -1,5 +1,8 @@ Makefile +lex.ppl.c lex.yy.c +ppy.tab.c +ppy.tab.h wrc y.tab.c y.tab.h diff --git a/tools/wrc/CHANGES b/tools/wrc/CHANGES index 7b38d48f59d..6b7b648a77d 100644 --- a/tools/wrc/CHANGES +++ b/tools/wrc/CHANGES @@ -1,3 +1,18 @@ +--------------------------------------------------------------------------- +Version 1.1.0 (01-May-2000) + +Bertho Stultiens +- Implemented a new preprocessor that is (nearly) ANSI-C compliant. The + old parser has been stripped from the old preprocessor-code which + cleaned up both resource-scanner and -parser. +- Standard defines have been introduced (see README.wrc) +- Both preprocessor- and resource-scanner have been optimized slightly + so that no backing up is required (one char lookahead is enough). +- Filename-scanning has been cleaned up, though not perfect yet. +- User-type resources are compatible now. +- Line-continuation in strings is corrected so that it does not + introduce a newline in the output. + --------------------------------------------------------------------------- Version 1.0.18 (28-Dec-1999) diff --git a/tools/wrc/Makefile.in b/tools/wrc/Makefile.in index 5f544f2f043..8fd50bf7df9 100644 --- a/tools/wrc/Makefile.in +++ b/tools/wrc/Makefile.in @@ -3,6 +3,8 @@ TOPSRCDIR = @top_srcdir@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ +LEXOPT = -Cf #-w -b +YACCOPT = #-v PROGRAMS = wrc@PROGEXT@ MODULE = none @@ -17,12 +19,12 @@ C_SRCS = \ wrc.c \ writeres.c -EXTRA_SRCS = parser.y parser.l -EXTRA_OBJS = y.tab.o lex.yy.o +EXTRA_SRCS = parser.y parser.l ppl.l ppy.y ppy.tab.c lex.ppl.c +EXTRA_OBJS = y.tab.o lex.yy.o ppy.tab.o lex.ppl.o all: $(PROGRAMS) -depend: y.tab.h +depend: y.tab.h ppy.tab.h ppy.tab.c lex.ppl.c @MAKE_RULES@ @@ -30,12 +32,18 @@ wrc@PROGEXT@: $(OBJS) $(CC) $(CFLAGS) -o wrc@PROGEXT@ $(OBJS) $(LEXLIB) y.tab.c y.tab.h: parser.y - $(YACC) -d -t $(SRCDIR)/parser.y + $(YACC) $(YACCOPT) -d -t $(SRCDIR)/parser.y + +ppy.tab.c ppy.tab.h: ppy.y + $(YACC) $(YACCOPT) -bppy -ppp -d -t $(SRCDIR)/ppy.y lex.yy.c: parser.l - $(LEX) -8 $(SRCDIR)/parser.l + $(LEX) $(LEXOPT) -d -8 $(SRCDIR)/parser.l + +lex.ppl.c: ppl.l + $(LEX) $(LEXOPT) -d -Ppp -8 -olex.ppl.c $(SRCDIR)/ppl.l clean:: - $(RM) y.tab.c y.tab.h lex.yy.c + $(RM) y.tab.c y.tab.h lex.yy.c ppy.tab.c ppy.tab.h lex.ppl.c ppy.output lex.backup y.output ### Dependencies: diff --git a/tools/wrc/README.wrc b/tools/wrc/README.wrc index 26c4fd6bd70..30bc0e2faf2 100644 --- a/tools/wrc/README.wrc +++ b/tools/wrc/README.wrc @@ -1,14 +1,14 @@ -Release 1.0.2 of wrc (20-Jun-1998), the wine resource compiler. +Release 1.1.0 of wrc (01-May-2000), the wine resource compiler. See the file CHANGES for differences between the version and what has been corrected in the current version. Wrc features: -- source preprocessing +- full source preprocessing - 16 and 32 bit support - LANGUAGE support (32 bit only) -- almost all resource types are supported +- most resource types are supported - enhanced expression capabilities and resource naming - indirect loadable resources - NE/PE resource directory generation @@ -34,13 +34,15 @@ Usage: wrc [options...] [infile[.rc|.res]] -d n Set debug level to 'n' -D id[=val] Define preprocessor identifier id=val -e Disable recognition of win32 keywords in 16bit compile + -E Preprocess only -g Add symbols to the global c namespace -h Also generate a .h file -H file Same as -h but written to file -I path Set include search dir to path (multiple -I allowed) - -l lan Set default language to lan (default is neutral {0}) + -l lan Set default language to lan (default is neutral {0, 0}) -L Leave case of embedded filenames as is -n Do not generate .s file + -N Do not preprocess input -o file Output to file (default is infile.[res|s|h] -p prefix Give a prefix for the generated names -r Create binary .res file (compile only) @@ -57,6 +59,9 @@ Debug level 'n' is a bitmask with following meaning: * 0x01 Tell which resource is parsed (verbose mode) * 0x02 Dump internal structures * 0x04 Create a parser trace (yydebug=1) + * 0x08 Preprocessor messages + * 0x10 Preprocessor lex messages + * 0x20 Preprocessor yacc trace The -o option only applies to the final destination file, which is in case of normal compile a .s file. You must use the '-H header.h' @@ -67,10 +72,12 @@ with -o and/or -H, then the output is written to "wrc.tab.[sh]" Preprocessing ------------- -The build-in preprocessor is not a full implementation of the C counterpart. -Wrc does not understand function-type macros. These are discarded as they -are scanned. This will be a future project. Wrc does understand these: -#define +The preprocessor is a fully operational C preprocessor. It handles all +directives supported by ANSI-C. It also includes some additions from +gcc/egcs. +Wrc understands these directives: +#define (both simple and macro) +#undef #if #ifdef #ifndef @@ -78,13 +85,42 @@ are scanned. This will be a future project. Wrc does understand these: #else #endif #error +#warning +#line +# +#pragma (ignored) +#ident (ignored) -Also 'defined' is supported as operator (both with and without parenthesis). -'#if' expressions can be anything valid that evaluates to an integer -expression (where 0 is false and anything else is true). Others (#pragma, -#line) are ignored. A special case '#' generates an error. This is due to -the implementation to enable generation of errors on preprocessing and will -be improved in the future. +The extensions include '#'-line directives. +Not handled at the moment are variable argument macros. They are parsed, +but not expanded properly. This will be corrected in the future. + +The preprocessor handles the special defines and aditionally defines an +extra set of defines: + Define | Value | Comment +-----------+-------------------+--------------- +RC_INVOKED | 1 | Always defined +__FLAT__ | 1 | Only defined if win32 compile +__WIN32__ | 1 | Only defined if win32 compile +__FILE__ | "..." | Current filename as string +__LINE__ | nnn | Current linenumber as integer +__TIME__ | "23:59:59" | Timestring of compilation +__DATE__ | "May 1 2000" | Datestring of compilation +__WRC__  1 | Wrc's major version +__WRC_MINOR__ | 1 | Wrc's minor version +__WRC_MICRO__ | 0 | Wrc's minor version +__WRC_PATCH__ | 0 | Alias of __WRC_MICRO__ + +Include-files are not read twice if they are protected with this scheme: +#ifndef SOME_DEFINE +#define SOME_DEFINE +... +#endif +This strategy has been borrowed from gcc/egcs and results in significantly +reduced preprocessing times (20..30%). There must not be any junk before +the first #ifndef and not after the last #endif; comments and whitespace +excepted. Wrc will check the existance of the define prior to inclusion to +detect "#undef SOME_DEFINE" (notably poppack.h) and act accordingly. 16 and 32 bit support @@ -115,35 +151,15 @@ statement before (and evt. after) the code in the resource file. Resource types supported ------------------------ All types are supported except for: -- FONT -- MESSAGETABLE -- extensions like TOOLBAR and the like (is this a user-type?) +- FONT (RT_FONT, RT_FONTDIR) +- MESSAGETABLE (RT_MESSAGETABLE) +- Animated cursors/icons (RT_ANIICON, RT_ANICURSOR) +- RT_VXD +- RT_PLUGPLAY These types will be implemented as soon as I get a proper specification of the layout. -Note: Usertype resources with character strings as types have a different -layout and do not accept expressions when a numerical type is specified. The -must be enclosed in double quotes. These are examples of valid usertype -resources: - -MyName "MyType" mydata.bin -MyName 12345 mydata.bin -MyName "MyType" "mydata.bin" -MyName 12345 "mydata.bin" - -MyName "MyType" -{ - ..., data, ... -} - -or - -MyName 12345 -{ - ..., data, ... -} - Expression capabilities and resource names ------------------------------------------ @@ -152,22 +168,19 @@ expects a number (except usertype type). Operators supported: () parenthesis * multiply / divide -+ add ++ plus/add - minus/substract | binary or & binary and ~ binary not (unary operator though) NOT ... (sigh) -Minus (-) can both be unary and binary. The NOT operator is (primarily) -used to disable window styles but I strongly suggest to refrain from using -this operator. -There is a shift/reduce conflict on the unary minus, but this is not -problematic. I was too lazy to make a new expression parser (next version or -so). Unary plus (+) would cause another confilct, so I let it out for now. +Plus (+) and minus (-) can both be unary and binary. The NOT operator is +(primarily) used to disable window styles but I strongly suggest to refrain +from using this operator. Resource names can be both numerical (expressions) and character typed. Wrc -does supports this insane (deep sigh) construct: +does support this insane (deep sigh) construct: MENU MENU { @@ -250,9 +263,8 @@ though): - No documentation ('wrc -?' gives command-line options though) - grep for FIXME in the source - Memory options are wrong under some conditions. There seems to be a - different action for win32 and win16. -- User-type resources have slightly different layout. -- Filename scanning is still hopeless. + different action for win32 and win16 +- Little/big-endian Reporting bugs and patches -------------------------- diff --git a/tools/wrc/newstruc.c b/tools/wrc/newstruc.c index 2b1f2ddf1c6..0e4d1f9af22 100644 --- a/tools/wrc/newstruc.c +++ b/tools/wrc/newstruc.c @@ -293,3 +293,4 @@ style_t *new_style(DWORD or_mask, DWORD and_mask) st->and_mask = and_mask; return st; } + diff --git a/tools/wrc/parser.h b/tools/wrc/parser.h index 58a9b7992ab..494362ccb24 100644 --- a/tools/wrc/parser.h +++ b/tools/wrc/parser.h @@ -9,8 +9,7 @@ /* From parser.y */ extern int yydebug; -extern int indialog; /* Set when parsing dialogs */ -extern int want_rscname; /* Set when a resource's name is required */ +extern int want_nl; /* Set when getting line-numers */ int yyparse(void); void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico); @@ -19,15 +18,10 @@ void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur); /* From parser.l */ extern FILE *yyin; extern char *yytext; -extern int line_number; -extern int char_number; +extern int yy_flex_debug; int yylex(void); -void set_yywf(void); void set_pp_ignore(int state); -void push_to(int start); -void pop_start(void); -void strip_extern(void); void strip_til_semicolon(void); void strip_til_parenthesis(void); diff --git a/tools/wrc/parser.l b/tools/wrc/parser.l index ee7492a7633..99fd2755d23 100644 --- a/tools/wrc/parser.l +++ b/tools/wrc/parser.l @@ -1,8 +1,14 @@ /* -*-C-*- * - * Copyright 1994 Martin von Loewis - * Copyright 1998 Bertho A. Stultiens (BS) + * Copyright 1998-2000 Bertho A. Stultiens (BS) * + * 30-Apr-2000 BS - Reintegration into the wine-tree + * 11-Jan-2000 BS - Very drastic cleanup because we don't have a + * preprocessor in here anymore. + * 02-Jan-2000 BS - Removed the preprocessor code + * 23-Dec-1999 BS - Removed the copyright for Martin von Loewis. + * There is really nothing left of his code in + * this parser. * 20-Jun-1998 BS - Changed the filename conversion. Filenames are * case-sensitive inder *nix, but not under dos. * default behaviour is to convert to lower case. @@ -44,9 +50,6 @@ * escaped '\0'. */ -/* Exclusive rules when looking for a filename */ -%x yywf -%x yywf_s /* Exclusive string handling */ %x yystr /* Exclusive unicode string handling */ @@ -55,44 +58,21 @@ %x yyrcd /* Exclusive comment eating... */ %x comment -/* Preprocessor exclusives */ -%x pp_incl -%x pp_def -%x pp_undef -%x pp_if -%x pp_ifdef -%x pp_ifndef -%x pp_elif -%x pp_else -%x pp_endif -%x pp_error -/* Set when accumulating #define's expansion text */ -%x pp_def_s -/* Set when processing function type defines */ -%x pp_ignore -/* Set when need to strip to eol */ -%x pp_ignore_eol -/* Set when handling a false #if case */ -%x pp_false /* Set when stripping c-junk */ %x pp_stripe %x pp_strips %x pp_stripp %x pp_stripp_final -/*%option stack*/ +%option stack %option never-interactive -/*%option noyywrap */ + /* Some shortcut definitions */ ws [ \f\t\r] cident [a-zA-Z_][0-9a-zA-Z_]* %{ -#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 LEX_DEBUG*/ #include "config.h" @@ -101,6 +81,7 @@ cident [a-zA-Z_][0-9a-zA-Z_]* #include #include #include +#include #include "wrc.h" #include "utils.h" @@ -112,227 +93,116 @@ cident [a-zA-Z_][0-9a-zA-Z_]* #define YY_USE_PROTOS #define YY_NO_UNPUT +#define YY_NO_TOP_STATE /* Always update the current character position within a line */ #define YY_USER_ACTION char_number+=yyleng; -raw_data_t *new_raw_data(void); +static void addcchar(char c); +static void addwchar(short s); +static string_t *get_buffered_cstring(void); +static string_t *get_buffered_wstring(void); +static string_t *make_string(char *s); -void addcchar(char c); -void addwchar(short s); -string_t *get_buffered_cstring(void); -string_t *get_buffered_wstring(void); -string_t *make_string(char *s); -string_t *make_filename(char *s, int len); - -int line_number = 1; /* The current line */ -int char_number = 1; /* The current char pos within the line */ static char *cbuffer; /* Buffers for string collection */ static int cbufidx; static int cbufalloc = 0; static short *wbuffer; static int wbufidx; static int wbufalloc = 0; -static int want_nl = 0; /* Set when newline needs to go to parser */ -static int want_ident = 0; /* Set is #ifdef, #ifndef or defined is seen */ static int stripslevel = 0; /* Count {} during pp_strips/pp_stripe mode */ static int stripplevel = 0; /* Count () during pp_strips mode */ -static char *substtext = NULL; /* Holds the substition text while getting a define */ static int cjunk_tagline; /* Where did we start stripping (helps error tracking) */ -#ifdef YY_USE_STACK -void push_to(int start) { yy_push_state(start); } -void pop_start(void) { yy_pop_state(start); } -#else -#define MAXSTARTSTACK 32 -static int startstack[MAXSTARTSTACK]; -static int startstackidx = 0; - -void push_to(int start) -{ - if(yydebug) - printf("push_to(%d): %d -> %d\n", line_number, YY_START, start); - if(startstackidx >= MAXSTARTSTACK-1) - internal_error(__FILE__, __LINE__, "Start condition stack overflow"); - startstack[startstackidx++] = YY_START; - BEGIN(start); -} - -void pop_start(void) -{ - if(yydebug) - printf("pop_start(%d): %d <- %d\n", line_number, startstack[startstackidx-1], YY_START); - if(startstackidx <= 0) - internal_error(__FILE__, __LINE__, "Start condition stack underflow"); - --startstackidx; - BEGIN(startstack[startstackidx]); -} -#endif - - -struct bufferstackentry { - YY_BUFFER_STATE bufferstate; /* Buffer to switch back to */ - struct pp_entry *define; /* Points to expanding define - or NULL if handling includes - */ - int line_number; /* Line that we were handling */ - int char_number; /* The current position */ - char *filename; /* Filename that we were handling */ -}; - -#define MAXBUFFERSTACK 128 -static struct bufferstackentry bufferstack[MAXBUFFERSTACK]; -static int bufferstackidx = 0; - -void push_buffer(YY_BUFFER_STATE buf, struct pp_entry *ppp, char *filename) -{ - if(yydebug) - printf("push_buffer: %p %p %p\n", buf, ppp, filename); - if(bufferstackidx >= MAXBUFFERSTACK-1) - internal_error(__FILE__, __LINE__, "Buffer stack overflow"); - memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0])); - bufferstack[bufferstackidx].bufferstate = buf; - bufferstack[bufferstackidx].define = ppp; - if(ppp) - ppp->expanding = 1; - else if(filename) - { - /* These will track the yyerror to the correct file and line */ - bufferstack[bufferstackidx].line_number = line_number; - bufferstack[bufferstackidx].char_number = char_number; - line_number = 1; - char_number = 1; - bufferstack[bufferstackidx].filename = input_name; - input_name = filename; - } - else - internal_error(__FILE__, __LINE__, "Pushing buffer without knowing where to go to"); - bufferstackidx++; -} - -YY_BUFFER_STATE pop_buffer(void) -{ - if(bufferstackidx <= 0) - return (YY_BUFFER_STATE)0; - bufferstackidx--; - if(bufferstack[bufferstackidx].define) - bufferstack[bufferstackidx].define->expanding = 0; - else - { - line_number = bufferstack[bufferstackidx].line_number; - char_number = bufferstack[bufferstackidx].char_number; - input_name = bufferstack[bufferstackidx].filename; - fclose(yyin); - } - if(yydebug) - printf("pop_buffer: %p %p (%d, %d) %p\n", - bufferstack[bufferstackidx].bufferstate, - bufferstack[bufferstackidx].define, - bufferstack[bufferstackidx].line_number, - bufferstack[bufferstackidx].char_number, - bufferstack[bufferstackidx].filename); - yy_switch_to_buffer(bufferstack[bufferstackidx].bufferstate); - return bufferstack[bufferstackidx].bufferstate; -} - -void do_include(char *name, int namelen) -{ - char *cpy = (char *)xmalloc(namelen); - strcpy(cpy, name+1); /* strip leading " or < */ - cpy[namelen-2] = '\0'; /* strip trailing " or > */ - if((yyin = open_include(cpy, name[0] == '"')) == NULL) - yyerror("Unable to open include file %s", cpy); - push_buffer(YY_CURRENT_BUFFER, NULL, cpy); - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); -} - struct keyword { char *keyword; int token; int isextension; int needcase; - int alwayskeyword; }; static struct keyword keywords[] = { - { "ACCELERATORS", ACCELERATORS, 0, 0, 0}, - { "ALT", ALT, 0, 0, 0}, - { "ASCII", ASCII, 0, 0, 0}, - { "AUTO3STATE", AUTO3STATE, 1, 0, 0}, - { "AUTOCHECKBOX", AUTOCHECKBOX, 1, 0, 0}, - { "AUTORADIOBUTTON", AUTORADIOBUTTON, 1, 0, 0}, - { "BEGIN", tBEGIN, 0, 0, 1}, - { "BITMAP", tBITMAP, 0, 0, 0}, - { "BLOCK", BLOCK, 0, 0, 1}, - { "BUTTON", BUTTON, 1, 0, 0}, - { "CAPTION", CAPTION, 0, 0, 0}, - { "CHARACTERISTICS", CHARACTERISTICS, 1, 0, 0}, - { "CHECKBOX", CHECKBOX, 0, 0, 0}, - { "CHECKED", CHECKED, 0, 0, 0}, - { "CLASS", CLASS, 0, 0, 0}, - { "COMBOBOX", COMBOBOX, 0, 0, 0}, - { "CONTROL", CONTROL, 0, 0, 0}, - { "CTEXT", CTEXT, 0, 0, 0}, - { "CURSOR", CURSOR, 0, 0, 0}, - { "defined", tDEFINED, 0, 1, 1}, - { "DEFPUSHBUTTON", DEFPUSHBUTTON, 0, 0, 1}, - { "DIALOG", DIALOG, 0, 0, 0}, - { "DIALOGEX", DIALOGEX, 1, 0, 0}, - { "DISCARDABLE", DISCARDABLE, 0, 0, 0}, - { "DLGINIT", DLGINIT, 0, 0, 0}, - { "EDITTEXT", EDITTEXT, 0, 0, 0}, - { "END", tEND, 0, 0, 1}, - { "EXSTYLE", EXSTYLE, 0, 0, 0}, - { "extern", tEXTERN, 0, 1, 1}, - { "FILEFLAGS", FILEFLAGS, 0, 0, 0}, - { "FILEFLAGSMASK", FILEFLAGSMASK, 0, 0, 0}, - { "FILEOS", FILEOS, 0, 0, 0}, - { "FILESUBTYPE", FILESUBTYPE, 0, 0, 0}, - { "FILETYPE", FILETYPE, 0, 0, 0}, - { "FILEVERSION", FILEVERSION, 0, 0, 0}, - { "FIXED", tFIXED, 0, 0, 0}, - { "FONT", FONT, 0, 0, 0}, - { "GRAYED", GRAYED, 0, 0, 0}, - { "GROUPBOX", GROUPBOX, 0, 0, 0}, - { "HELP", HELP, 0, 0, 0}, - { "ICON", ICON, 0, 0, 0}, - { "IMPURE", IMPURE, 0, 0, 0}, - { "INACTIVE", INACTIVE, 0, 0, 0}, - { "LANGUAGE", LANGUAGE, 1, 0, 1}, - { "LISTBOX", LISTBOX, 0, 0, 0}, - { "LOADONCALL", LOADONCALL, 0, 0, 0}, - { "LTEXT", LTEXT, 0, 0, 0}, - { "MENU", MENU, 0, 0, 0}, - { "MENUBARBREAK", MENUBARBREAK, 0, 0, 0}, - { "MENUBREAK", MENUBREAK, 0, 0, 0}, - { "MENUEX", MENUEX, 1, 0, 0}, - { "MENUITEM", MENUITEM, 0, 0, 0}, - { "MESSAGETABLE", MESSAGETABLE, 1, 0, 0}, - { "MOVEABLE", MOVEABLE, 0, 0, 0}, - { "NOINVERT", NOINVERT, 0, 0, 0}, - { "NOT", NOT, 0, 0, 0}, - { "POPUP", POPUP, 0, 0, 0}, - { "PRELOAD", PRELOAD, 0, 0, 0}, - { "PRODUCTVERSION", PRODUCTVERSION, 0, 0, 0}, - { "PURE", tPURE, 0, 0, 0}, - { "PUSHBUTTON", PUSHBUTTON, 0, 0, 0}, - { "RADIOBUTTON", RADIOBUTTON, 0, 0, 0}, - { "RCDATA", RCDATA, 0, 0, 0}, - { "RTEXT", RTEXT, 0, 0, 0}, - { "SCROLLBAR", SCROLLBAR, 0, 0, 0}, - { "SEPARATOR", SEPARATOR, 0, 0, 0}, - { "SHIFT", SHIFT, 0, 0, 0}, - { "STATE3", STATE3, 1, 0, 0}, - { "STRING", tSTRING, 0, 0, 0}, - { "STRINGTABLE", STRINGTABLE, 0, 0, 1}, - { "STYLE", STYLE, 0, 0, 0}, - { "TOOLBAR", TOOLBAR, 1, 0, 0}, - { "typedef", tTYPEDEF, 0, 1, 1}, - { "VALUE", VALUE, 0, 0, 0}, - { "VERSION", VERSION, 1, 0, 0}, - { "VERSIONINFO", VERSIONINFO, 0, 0, 0}, - { "VIRTKEY", VIRTKEY, 0, 0, 0} + { "ACCELERATORS", tACCELERATORS, 0, 0}, + { "ALT", tALT, 0, 0}, + { "ASCII", tASCII, 0, 0}, + { "AUTO3STATE", tAUTO3STATE, 1, 0}, + { "AUTOCHECKBOX", tAUTOCHECKBOX, 1, 0}, + { "AUTORADIOBUTTON", tAUTORADIOBUTTON, 1, 0}, + { "BEGIN", tBEGIN, 0, 0}, + { "BITMAP", tBITMAP, 0, 0}, + { "BLOCK", tBLOCK, 0, 0}, + { "BUTTON", tBUTTON, 1, 0}, + { "CAPTION", tCAPTION, 0, 0}, + { "CHARACTERISTICS", tCHARACTERISTICS, 1, 0}, + { "CHECKBOX", tCHECKBOX, 0, 0}, + { "CHECKED", tCHECKED, 0, 0}, + { "CLASS", tCLASS, 0, 0}, + { "COMBOBOX", tCOMBOBOX, 0, 0}, + { "CONTROL", tCONTROL, 0, 0}, + { "CTEXT", tCTEXT, 0, 0}, + { "CURSOR", tCURSOR, 0, 0}, + { "DEFPUSHBUTTON", tDEFPUSHBUTTON, 0, 0}, + { "DIALOG", tDIALOG, 0, 0}, + { "DIALOGEX", tDIALOGEX, 1, 0}, + { "DISCARDABLE", tDISCARDABLE, 0, 0}, + { "DLGINIT", tDLGINIT, 0, 0}, + { "EDITTEXT", tEDITTEXT, 0, 0}, + { "END", tEND, 0, 0}, + { "enum", tENUM, 0, 1}, + { "EXSTYLE", tEXSTYLE, 0, 0}, + { "extern", tEXTERN, 0, 1}, + { "FILEFLAGS", tFILEFLAGS, 0, 0}, + { "FILEFLAGSMASK", tFILEFLAGSMASK, 0, 0}, + { "FILEOS", tFILEOS, 0, 0}, + { "FILESUBTYPE", tFILESUBTYPE, 0, 0}, + { "FILETYPE", tFILETYPE, 0, 0}, + { "FILEVERSION", tFILEVERSION, 0, 0}, + { "FIXED", tFIXED, 0, 0}, + { "FONT", tFONT, 0, 0}, + { "GRAYED", tGRAYED, 0, 0}, + { "GROUPBOX", tGROUPBOX, 0, 0}, + { "HELP", tHELP, 0, 0}, + { "ICON", tICON, 0, 0}, + { "IMPURE", tIMPURE, 0, 0}, + { "INACTIVE", tINACTIVE, 0, 0}, + { "inline", tINLINE, 0, 1}, + { "LANGUAGE", tLANGUAGE, 1, 0}, + { "LISTBOX", tLISTBOX, 0, 0}, + { "LOADONCALL", tLOADONCALL, 0, 0}, + { "LTEXT", tLTEXT, 0, 0}, + { "MENU", tMENU, 0, 0}, + { "MENUBARBREAK", tMENUBARBREAK, 0, 0}, + { "MENUBREAK", tMENUBREAK, 0, 0}, + { "MENUEX", tMENUEX, 1, 0}, + { "MENUITEM", tMENUITEM, 0, 0}, + { "MESSAGETABLE", tMESSAGETABLE, 1, 0}, + { "MOVEABLE", tMOVEABLE, 0, 0}, + { "NOINVERT", tNOINVERT, 0, 0}, + { "NOT", tNOT, 0, 0}, + { "POPUP", tPOPUP, 0, 0}, + { "PRELOAD", tPRELOAD, 0, 0}, + { "PRODUCTVERSION", tPRODUCTVERSION, 0, 0}, + { "PURE", tPURE, 0, 0}, + { "PUSHBUTTON", tPUSHBUTTON, 0, 0}, + { "RADIOBUTTON", tRADIOBUTTON, 0, 0}, + { "RCDATA", tRCDATA, 0, 0}, + { "RTEXT", tRTEXT, 0, 0}, + { "SCROLLBAR", tSCROLLBAR, 0, 0}, + { "SEPARATOR", tSEPARATOR, 0, 0}, + { "SHIFT", tSHIFT, 0, 0}, + { "STATE3", tSTATE3, 1, 0}, + { "static", tSTATIC, 0, 1}, + { "STRING", tSTRING, 0, 0}, + { "STRINGTABLE", tSTRINGTABLE, 0, 0}, + { "struct", tSTRUCT, 0, 1}, + { "STYLE", tSTYLE, 0, 0}, + { "TOOLBAR", tTOOLBAR, 1, 0}, + { "typedef", tTYPEDEF, 0, 1}, + { "VALUE", tVALUE, 0, 0}, + { "VERSION", tVERSION, 1, 0}, + { "VERSIONINFO", tVERSIONINFO, 0, 0}, + { "VIRTKEY", tVIRTKEY, 0, 0} }; #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) @@ -383,326 +253,97 @@ struct keyword *iskeyword(char *kw) } #endif -#ifdef LEX_DEBUG - if(kwp && !strcmp(kwp->keyword, "LANGUAGE")) - printf("Got Language\n"); -#endif if(kwp == NULL || (kwp->isextension && !extensions)) return NULL; else return kwp; } -void add_to_substtext(char *text, int len) -{ - if(!substtext) - { - substtext = xstrdup(text); - } - else - { - substtext = (char *)xrealloc(substtext, strlen(substtext)+len+1); - strcat(substtext, text); - } -} - %} +/* + ************************************************************************** + * The flexer starts here + ************************************************************************** + */ %% - /* #include handling */ -^{ws}*#{ws}*include{ws}* push_to(pp_incl); -\<[^\n\>]+\> do_include(yytext, yyleng); pop_start(); -\"[^\n\>]+\" do_include(yytext, yyleng); pop_start(); -. yyerror("Malformed #include"); - - /* #define handling */ -^{ws}*#{ws}*define{ws}* push_to(pp_def); -{cident} { - set_define(yytext); - push_to(pp_def_s); - } -{cident}\( push_to(pp_ignore); /* Ignore function-like defines for now*/ -. yyerror("Malformed #define"); - -[^\/\\\n]* { - if(YY_START == pp_def_s) - add_to_substtext(yytext, yyleng); - } -\/[^\/\*][^\/\\\n]* { /* Comment is handled in normal handling */ - if(YY_START == pp_def_s) - add_to_substtext(yytext, yyleng); - } -\\{ws}*\n line_number++; char_number = 1; /* Line continuation */ -\n { - if(YY_START == pp_def_s) - { - add_define(substtext ? substtext : ""); - free(substtext); - substtext = NULL; - } - line_number++; - char_number = 1; - pop_start(); - pop_start(); - } - - /* #undef handling */ -^{ws}*#{ws}*undef{ws}* push_to(pp_undef); -{cident} { - del_define(yytext); - pop_start(); - /*push_to(pp_ignore);*/ - } - - /* Conditional handling */ -^{ws}*#{ws}*if{ws}* { - if(YY_START == pp_false) - { - if(yydebug) - printf("(%d)#if ignored\n", line_number); - push_if(0, 0, 1); - push_to(pp_ignore_eol); - } - else - { - push_to(INITIAL); - want_nl = 1; - return tIF; - } - } -^{ws}*#{ws}*ifdef{ws}* { - if(YY_START == pp_false) - { - if(yydebug) - printf("(%d)#ifdef ignored\n", line_number); - push_if(0, 0, 1); - push_to(pp_ignore_eol); - } - else - { - push_to(INITIAL); - want_nl = 1; - want_ident = 1; - return tIFDEF; - } - } -^{ws}*#{ws}*ifndef{ws}* { - if(YY_START == pp_false) - { - if(yydebug) - printf("(%d)#ifndef ignored\n", line_number); - push_if(0, 0, 1); - push_to(pp_ignore_eol); - } - else - { - push_to(INITIAL); - want_nl = 1; - want_ident = 1; - return tIFNDEF; - } - } -^{ws}*#{ws}*elif{ws}* { - if(!isnevertrue_if()) - { - push_to(INITIAL); - want_nl = 1; - return tELIF; - } - else if(YY_START == pp_false) - push_to(pp_ignore_eol); - if(yydebug) - printf("(%d)#elif ignored\n", line_number); - } -^{ws}*#{ws}*else{ws}* { - if(!isnevertrue_if()) - { - push_to(INITIAL); - want_nl = 1; - return tELSE; - } - if(yydebug) - printf("(%d)#else ignored\n", line_number); - } -^{ws}*#{ws}*endif{ws}* { - if(!isnevertrue_if()) - { - want_nl = 1; - return tENDIF; - } - else - { - if(yydebug) - printf("(%d)#endif ignored\n", line_number); - pop_if(); - } - } - - /* The error directive */ -^{ws}*#{ws}*error{ws}* push_to(pp_error); -[^\n]* yyerror("Error directive: %s", yytext); -^{ws}*#{ws}*error[^\n]* { - if(yydebug) - printf("(%d)#error ignored\n", line_number); - } - - /* preprocessor junk */ -^{ws}*#{ws}*pragma[^\n]* ; /* Ignore #pragma */ -^{ws}*#{ws}*ident[^\n]* ; /* Ignore #ident */ -^{ws}*#{ws}*line[^\n]* ; /* Ignore #line */ - /* We'll get an error on malformed #xxx statements - * by not recognising '#' at all. This helps tracking - * preprocessor errors. - */ - /*^{ws}*#{ws}* ; Ignore # */ - -\{ stripslevel++; -\} stripslevel--; -; if(!stripslevel) pop_start(); + /* + * Strip everything until a ';' taking + * into account braces {} for structures, + * classes and enums. + */ +\{ stripslevel++; +\} stripslevel--; +; if(!stripslevel) yy_pop_state(); \/[^*\n] ; /* To catch comments */ [^\{\};\n#/]* ; /* Ignore rest */ +\n line_number++; char_number = 1; -\{ stripslevel++; -\} { - stripslevel--; - if(!stripslevel) pop_start(); - } -; if(!stripslevel) pop_start(); -\/[^*\n] ; /* To catch comments */ -[^\{\};\n#/]* ; /* Ignore rest */ - -\( stripplevel++; -\) { - stripplevel--; - if(!stripplevel) - { - pop_start(); - push_to(pp_stripp_final); +\( stripplevel++; +\) { + stripplevel--; + if(!stripplevel) + { + yy_pop_state(); + yy_push_state(pp_stripp_final); + } } - } \/[^*\n] ; /* To catch comments */ [^\(\);\n#/]* ; /* Ignore rest */ +\n line_number++; char_number = 1; -{ws}* ; /* Ignore */ -; pop_start(); /* Kill the semicolon */ -\n line_number++; char_number = 1; pop_start(); -. yyless(0); pop_start(); - -. ; /* Ignore everything except #xxx during false #if state */ - -[^\n]* pop_start(); - - /* These are special cases due to filename scanning */ -[Dd][Ii][Ss][Cc][Aa][Rr][Dd][Aa][Bb][Ll][Ee] return DISCARDABLE; -[Ff][Ii][Xx][Ee][Dd] return tFIXED; -[Ii][Mm][Pp][Uu][Rr][Ee] return IMPURE; -[Mm][Oo][Vv][Ee][Aa][Bb][Ll][Ee] return MOVEABLE; -[Ll][Oo][Aa][Dd][Oo][Nn][Cc][Aa][Ll][Ll] return LOADONCALL; -[Pp][Rr][Ee][Ll][Oo][Aa][Dd] return PRELOAD; -[Pp][Uu][Rr][Ee] return tPURE; +{ws}* ; /* Ignore */ +; yy_pop_state(); /* Kill the semicolon */ +\n line_number++; char_number = 1; yy_pop_state(); +. yyless(0); yy_pop_state(); \{ return tBEGIN; \} return tEND; -[0-9]+[lL]? { yylval.num = strtoul(yytext, 0, 10); return toupper(yytext[yyleng-1]) == 'L' ? LNUMBER : NUMBER; } -0[xX][0-9A-Fa-f]+[lL]? { yylval.num = strtoul(yytext, 0, 16); return toupper(yytext[yyleng-1]) == 'L' ? LNUMBER : NUMBER; } -0[oO][0-7]+[lL]? { yylval.num = strtoul(yytext+2, 0, 8); return toupper(yytext[yyleng-1]) == 'L' ? LNUMBER : NUMBER; } -[A-Za-z_0-9]+ { - struct keyword *token; - struct pp_entry *ppp; +[0-9]+[lL]? { yylval.num = strtoul(yytext, 0, 10); return toupper(yytext[yyleng-1]) == 'L' ? tLNUMBER : tNUMBER; } +0[xX][0-9A-Fa-f]+[lL]? { yylval.num = strtoul(yytext, 0, 16); return toupper(yytext[yyleng-1]) == 'L' ? tLNUMBER : tNUMBER; } +0[oO][0-7]+[lL]? { yylval.num = strtoul(yytext+2, 0, 8); return toupper(yytext[yyleng-1]) == 'L' ? tLNUMBER : tNUMBER; } - want_rscname = 0; - - if(want_ident) + /* + * The next to rules scan identifiers and filenames. + * This is achieved by using the priority ruling + * of the scanner where a '.' is valid in a filename + * and *only* in a filename. In this case, the second + * rule will be reduced because it is longer. + */ +[A-Za-z_0-9]+ { + struct keyword *tok = iskeyword(yytext); + + if(tok) { - /* Prevent preprocessor subst */ - want_ident = 0; - yylval.str = make_string(yytext); - #ifdef LEX_DEBUG - printf("want IDENT (%s, %d, %d): <%s>\n", input_name, line_number, char_number, yytext); - #endif - return IDENT; - } - else if((ppp = pp_lookup(yytext)) != NULL) - { - /* Do preprocessor substitution, - * but expand only if macro is not - * already expanding. - */ - if(!ppp->expanding) - { - #ifdef LEX_DEBUG - printf("expand IDENT (%s, %d, %d): <%s>\n", input_name, line_number, char_number, yytext); - #endif - push_buffer(YY_CURRENT_BUFFER, ppp, NULL); - yy_scan_string(ppp->subst); - } - } - else if((token = iskeyword(yytext)) != NULL - && !(!token->alwayskeyword && want_rscname)) - { - switch(token->token) - { - case tDEFINED: - want_ident = 1; - break; - /*case RCDATA:*/ - case CURSOR: - case tBITMAP: - case MESSAGETABLE: - case DLGINIT: - push_to(yywf); - break; - case FONT: - case ICON: - if(!indialog) - push_to(yywf); - break; - case DIALOG: - case DIALOGEX: - indialog = 1; - break; - } - return token->token; + if(tok->token == tCLASS && !strcmp(yytext, "class")) + return tCPPCLASS; + else + return tok->token; } else { yylval.str = make_string(yytext); - #ifdef LEX_DEBUG - printf("%s IDENT (%s, %d, %d): <%s>\n", - want_rscname ? "rscname" : "just", - input_name, - line_number, - char_number, - yytext); - #endif - return IDENT; + return tIDENT; } } -\|\| return LOGOR; -\&\& return LOGAND; -\=\= return EQ; -\!\= return NE; -\<\= return LTE; -\>\= return GTE; - -[^ \f\t\r\n\"]* { pop_start(); yylval.str = make_filename(yytext, yyleng); return FILENAME; } -\" push_to(yywf_s); -[^\"\n]*\" { pop_start(); pop_start(); yylval.str = make_filename(yytext, yyleng-1); return FILENAME; } -\n yyerror("Newline in filename"); +[A-Za-z_0-9.]+ yylval.str = make_string(yytext); return tFILENAME; + /* + * Wide string scanning + */ L\" { - push_to(yylstr); + yy_push_state(yylstr); wbufidx = 0; if(!win32) yywarning("16bit resource contains unicode strings\n"); } +\"{ws}+ | \" { - pop_start(); + yy_pop_state(); yylval.str = get_buffered_wstring(); return tSTRING; } -\n yyerror("Unterminated string"); \\[0-7]{1,6} { /* octal escape sequence */ int result; result = strtol(yytext+1, 0, 8); @@ -715,6 +356,8 @@ L\" { result = strtol(yytext+2, 0, 16); addwchar((short)result); } +\\x[0-9a-fA-F]{1,3} { yyerror("Invalid hex escape sequence '%s'", yytext); } + \\[0-9]+ yyerror("Bad escape secuence"); \\a addwchar('\a'); \\b addwchar('\b'); @@ -723,7 +366,7 @@ L\" { \\r addwchar('\r'); \\t addwchar('\t'); \\v addwchar('\v'); -\\(.|\n) addwchar(yytext[1]); +\\. if(yytext[1] != '\n') addwchar(yytext[1]); \"\" addcchar('\"'); /* "bla""bla" -> "bla\"bla" */ \\\"\" addcchar('\"'); /* "bla\""bla" -> "bla\"bla" */ \"{ws}+\" ; /* "bla" "bla" -> "blabla" */ @@ -732,17 +375,18 @@ L\" { while(*yptr) /* FIXME: codepage translation */ addwchar(*yptr++ & 0xff); } +\n yyerror("Unterminated string"); -\" { - push_to(yystr); - cbufidx = 0; - } + /* + * Normal string scanning + */ +\" yy_push_state(yystr); cbufidx = 0; +\"{ws}+ | \" { - pop_start(); + yy_pop_state(); yylval.str = get_buffered_cstring(); return tSTRING; } -\n yyerror("Unterminated string"); \\[0-7]{1,3} { /* octal escape sequence */ int result; result = strtol(yytext+1, 0, 8); @@ -755,6 +399,8 @@ L\" { result = strtol(yytext+2, 0, 16); addcchar((char)result); } +\\x[0-9a-fA-F] { yyerror("Invalid hex escape sequence '%s'", yytext); } + \\[0-9]+ yyerror("Bad escape secuence"); \\a addcchar('\a'); \\b addcchar('\b'); @@ -763,7 +409,7 @@ L\" { \\r addcchar('\r'); \\t addcchar('\t'); \\v addcchar('\v'); -\\(.|\n) addcchar(yytext[1]); +\\. if(yytext[1] != '\n') addcchar(yytext[1]); [^\\\n\"]+ { char *yptr = yytext; while(*yptr) @@ -772,20 +418,19 @@ L\" { \"\" addcchar('\"'); /* "bla""bla" -> "bla\"bla" */ \\\"\" addcchar('\"'); /* "bla\""bla" -> "bla\"bla" */ \"{ws}+\" ; /* "bla" "bla" -> "blabla" */ -. yywarning("Matched %c", *yytext); +\n yyerror("Unterminated string"); - -\' { - push_to(yyrcd); - cbufidx = 0; - } + /* + * Raw data scanning + */ +\' yy_push_state(yyrcd); cbufidx = 0; \' { - pop_start(); + yy_pop_state(); yylval.raw = new_raw_data(); yylval.raw->size = cbufidx; yylval.raw->data = xmalloc(yylval.raw->size); memcpy(yylval.raw->data, cbuffer, yylval.raw->size); - return RAWDATA; + return tRAWDATA; } [0-9a-fA-F]{2} { int result; @@ -796,18 +441,22 @@ L\" { \n line_number++; char_number = 1; . yyerror("Malformed data-line"); -"/*" push_to(comment); /* Eat comment */ + /* + * Comment stripping + * Should never occur after preprocessing + */ +"/*" { + yy_push_state(comment); if(!no_preprocess) yywarning("Found comments after preprocessing, please report"); + } [^*\n]* ; "*"+[^*/\n]* ; \n line_number++; char_number = 1; -"*"+"/" pop_start(); +"*"+"/" yy_pop_state(); -;[^\n]* ; /* Eat comment */ -"//"[^\n]* ; /* Eat comment */ +;[^\n]* ; /* not really comment, but left-over c-junk */ +"//"[^\n]* if(!no_preprocess) yywarning("Found comments after preprocessing, please report"); -\n { - if(YY_START == yywf) - pop_start(); +\n { line_number++; char_number = 1; if(want_nl) @@ -816,19 +465,15 @@ L\" { return tNL; } } -{ws}+ ; /* Eat whitespace */ +{ws}+ ; /* Eat whitespace */ . return yytext[0]; + <> { - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - if(!pop_buffer()) - { - if(YY_START == pp_strips || YY_START == pp_stripe || YY_START == pp_stripp || YY_START == pp_stripp_final) - yyerror("Unexpected end of file during c-junk scanning (started at %d)", cjunk_tagline); - else - yyterminate(); - } - yy_delete_buffer(b); + if(YY_START == pp_strips || YY_START == pp_stripe || YY_START == pp_stripp || YY_START == pp_stripp_final) + yyerror("Unexpected end of file during c-junk scanning (started at %d)", cjunk_tagline); + else + yyterminate(); } <*>.|\n { @@ -860,7 +505,7 @@ int yywrap(void) /* These dup functions copy the enclosed '\0' from * the resource string. */ -void addcchar(char c) +static void addcchar(char c) { if(cbufidx >= cbufalloc) { @@ -872,7 +517,7 @@ void addcchar(char c) cbuffer[cbufidx++] = c; } -void addwchar(short s) +static void addwchar(short s) { if(wbufidx >= wbufalloc) { @@ -893,7 +538,7 @@ void addwchar(short s) wbuffer[wbufidx++] = (short)(s & 0xff); } -string_t *get_buffered_cstring(void) +static string_t *get_buffered_cstring(void) { string_t *str = new_string(); str->size = cbufidx; @@ -901,11 +546,10 @@ string_t *get_buffered_cstring(void) str->str.cstr = (char *)xmalloc(cbufidx+1); memcpy(str->str.cstr, cbuffer, cbufidx); str->str.cstr[cbufidx] = '\0'; -/* printf("got cstring \"%s\"\n", str->str.cstr); */ return str; } -string_t *get_buffered_wstring(void) +static string_t *get_buffered_wstring(void) { string_t *str = new_string(); str->size = wbufidx; @@ -916,7 +560,7 @@ string_t *get_buffered_wstring(void) return str; } -string_t *make_string(char *s) +static string_t *make_string(char *s) { string_t *str = new_string(); str->size = strlen(s); @@ -926,69 +570,23 @@ string_t *make_string(char *s) return str; } -string_t *make_filename(char *s, int len) -{ - char *cptr; - string_t *str = new_string(); - - str->size = len; - str->type = str_char; - str->str.cstr = (char *)xmalloc(str->size+1); - memcpy(str->str.cstr, s, str->size); - str->str.cstr[str->size] = '\0'; - - /* Remove escaped backslash and convert to forward */ - cptr = str->str.cstr; - for(cptr = str->str.cstr; (cptr = strchr(cptr, '\\')) != NULL; cptr++) - { - if(cptr[1] == '\\') - { - memmove(cptr, cptr+1, strlen(cptr)); - str->size--; - } - *cptr = '/'; - } - - /* Convert to lower case. Seems to be reasonable to do */ - for(cptr = str->str.cstr; !leave_case && *cptr; cptr++) - { - *cptr = tolower(*cptr); - } - return str; -} - -/* Called from the parser to signal filename request */ -void set_yywf(void) -{ - push_to(yywf); -} - -/* Called from the parser to signal preprocessor if case */ -void set_pp_ignore(int state) -{ - if(state) - push_to(pp_false); - else - pop_start(); -} - /* Called from the parser to kill c-junk */ void strip_extern(void) { cjunk_tagline = line_number; - push_to(pp_stripe); + yy_push_state(pp_stripe); } void strip_til_semicolon(void) { cjunk_tagline = line_number; - push_to(pp_strips); + yy_push_state(pp_strips); } void strip_til_parenthesis(void) { cjunk_tagline = line_number; stripplevel = 1; /* One scanned already */ - push_to(pp_stripp); + yy_push_state(pp_stripp); } diff --git a/tools/wrc/parser.y b/tools/wrc/parser.y index 1710fca38b4..a79c40fd28b 100644 --- a/tools/wrc/parser.y +++ b/tools/wrc/parser.y @@ -1,10 +1,16 @@ %{ /* - * Copyright Martin von Loewis, 1994 - * Copyright 1998 Bertho A. Stultiens (BS) - * 1999 Juergen Schmied (JS) + * Copyright 1994 Martin von Loewis + * Copyright 1998-2000 Bertho A. Stultiens (BS) + * 1999 Juergen Schmied (JS) * - * 6-Nov-1999 JS - see CHANGES + * 30-Apr-2000 BS - Reintegration into the wine-tree + * 14-Jan-2000 BS - Redid the usertype resources so that they + * are compatible. + * 02-Jan-2000 BS - Removed the preprocessor from the grammar + * expect for the # command (line numbers). + * + * 06-Nov-1999 JS - see CHANGES * * 29-Dec-1998 AdH - Grammar and function extensions. * grammar: TOOLBAR resources, Named ICONs in @@ -110,12 +116,7 @@ #include "wingdi.h" #include "winuser.h" -#ifdef __BORLANDC__ -#pragma warn -sig -#endif - -int indialog = 0; /* Signal flex that we're parsing a dialog */ -int want_rscname = 0; /* Set when a resource's name is required */ +int want_nl = 0; /* Signal flex that we need the next newline */ stringtable_t *tagstt; /* Stringtable tag. * It is set while parsing a stringtable to one of * the stringtables in the sttres list or a new one @@ -130,60 +131,58 @@ static characts_t *tagstt_characts; static version_t *tagstt_version; /* Prototypes of here defined functions */ -void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur); -void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico); -int alloc_cursor_id(language_t *); -int alloc_icon_id(language_t *); -void ins_stt_entry(stt_entry_t *ste); -int check_stt_entry(stringtable_t *tabs, stt_entry_t *ste); -event_t *get_event_head(event_t *p); -control_t *get_control_head(control_t *p); -ver_value_t *get_ver_value_head(ver_value_t *p); -ver_block_t *get_ver_block_head(ver_block_t *p); -resource_t *get_resource_head(resource_t *p); -menuex_item_t *get_itemex_head(menuex_item_t *p); -menu_item_t *get_item_head(menu_item_t *p); -raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str); -raw_data_t *merge_raw_data_int(raw_data_t *r1, int i); -raw_data_t *merge_raw_data_long(raw_data_t *r1, int i); -raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2); -raw_data_t *str2raw_data(string_t *str); -raw_data_t *int2raw_data(int i); -raw_data_t *long2raw_data(int i); -raw_data_t *load_file(string_t *name); -itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid); -event_t *add_string_event(string_t *key, int id, int flags, event_t *prev); -event_t *add_event(int key, int id, int flags, event_t *prev); -dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg); -dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg); -dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg); -dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg); -dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg); -dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg); -dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg); -dialogex_t *dialogex_exstyle(style_t *st, dialogex_t *dlg); -dialogex_t *dialogex_style(style_t *st, dialogex_t *dlg); -name_id_t *convert_ctlclass(name_id_t *cls); -control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev); -dialog_t *dialog_version(version_t *v, dialog_t *dlg); -dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg); -dialog_t *dialog_language(language_t *l, dialog_t *dlg); -dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg); -dialog_t *dialog_class(name_id_t *n, dialog_t *dlg); -dialog_t *dialog_font(font_id_t *f, dialog_t *dlg); -dialog_t *dialog_caption(string_t *s, dialog_t *dlg); -dialog_t *dialog_exstyle(style_t * st, dialog_t *dlg); -dialog_t *dialog_style(style_t * st, dialog_t *dlg); -resource_t *build_stt_resources(stringtable_t *stthead); -stringtable_t *find_stringtable(lvc_t *lvc); -toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec); -toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); +static int alloc_cursor_id(language_t *); +static int alloc_icon_id(language_t *); +static event_t *get_event_head(event_t *p); +static control_t *get_control_head(control_t *p); +static ver_value_t *get_ver_value_head(ver_value_t *p); +static ver_block_t *get_ver_block_head(ver_block_t *p); +static resource_t *get_resource_head(resource_t *p); +static menuex_item_t *get_itemex_head(menuex_item_t *p); +static menu_item_t *get_item_head(menu_item_t *p); +static raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str); +static raw_data_t *merge_raw_data_int(raw_data_t *r1, int i); +static raw_data_t *merge_raw_data_long(raw_data_t *r1, int i); +static raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2); +static raw_data_t *str2raw_data(string_t *str); +static raw_data_t *int2raw_data(int i); +static raw_data_t *long2raw_data(int i); +static raw_data_t *load_file(string_t *name); +static itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid); +static event_t *add_string_event(string_t *key, int id, int flags, event_t *prev); +static event_t *add_event(int key, int id, int flags, event_t *prev); +static dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg); +static dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg); +static dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg); +static dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg); +static dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg); +static dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg); +static dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg); +static dialogex_t *dialogex_exstyle(style_t *st, dialogex_t *dlg); +static dialogex_t *dialogex_style(style_t *st, dialogex_t *dlg); +static name_id_t *convert_ctlclass(name_id_t *cls); +static control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev); +static dialog_t *dialog_version(version_t *v, dialog_t *dlg); +static dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg); +static dialog_t *dialog_language(language_t *l, dialog_t *dlg); +static dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg); +static dialog_t *dialog_class(name_id_t *n, dialog_t *dlg); +static dialog_t *dialog_font(font_id_t *f, dialog_t *dlg); +static dialog_t *dialog_caption(string_t *s, dialog_t *dlg); +static dialog_t *dialog_exstyle(style_t * st, dialog_t *dlg); +static dialog_t *dialog_style(style_t * st, dialog_t *dlg); +static resource_t *build_stt_resources(stringtable_t *stthead); +static stringtable_t *find_stringtable(lvc_t *lvc); +static toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec); +static toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); +static string_t *make_filename(string_t *s); %} %union{ string_t *str; int num; int *iptr; + char *cptr; resource_t *res; accelerator_t *acc; bitmap_t *bmp; @@ -224,39 +223,35 @@ toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); style_t *style; } -%token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL -%token tTYPEDEF tEXTERN -%token NUMBER LNUMBER -%token tSTRING IDENT FILENAME -%token RAWDATA -%token ACCELERATORS tBITMAP CURSOR DIALOG DIALOGEX MENU MENUEX MESSAGETABLE -%token RCDATA VERSIONINFO STRINGTABLE FONT ICON -%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX DEFPUSHBUTTON -%token PUSHBUTTON RADIOBUTTON STATE3 /* PUSHBOX */ -%token GROUPBOX COMBOBOX LISTBOX SCROLLBAR -%token CONTROL EDITTEXT -%token RTEXT CTEXT LTEXT -%token BLOCK VALUE -%token SHIFT ALT ASCII VIRTKEY GRAYED CHECKED INACTIVE NOINVERT -%token tPURE IMPURE DISCARDABLE LOADONCALL PRELOAD tFIXED MOVEABLE -%token CLASS CAPTION CHARACTERISTICS EXSTYLE STYLE VERSION LANGUAGE -%token FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEOS FILETYPE FILEFLAGS FILESUBTYPE -%token MENUBARBREAK MENUBREAK MENUITEM POPUP SEPARATOR -%token HELP -%token tSTRING IDENT RAWDATA -%token TOOLBAR BUTTON +%token tTYPEDEF tEXTERN tSTRUCT tENUM tCPPCLASS tINLINE tSTATIC tNL +%token tNUMBER tLNUMBER +%token tSTRING tIDENT tFILENAME +%token tRAWDATA +%token tACCELERATORS tBITMAP tCURSOR tDIALOG tDIALOGEX tMENU tMENUEX tMESSAGETABLE +%token tRCDATA tVERSIONINFO tSTRINGTABLE tFONT tICON +%token tAUTO3STATE tAUTOCHECKBOX tAUTORADIOBUTTON tCHECKBOX tDEFPUSHBUTTON +%token tPUSHBUTTON tRADIOBUTTON tSTATE3 /* PUSHBOX */ +%token tGROUPBOX tCOMBOBOX tLISTBOX tSCROLLBAR +%token tCONTROL tEDITTEXT +%token tRTEXT tCTEXT tLTEXT +%token tBLOCK tVALUE +%token tSHIFT tALT tASCII tVIRTKEY tGRAYED tCHECKED tINACTIVE tNOINVERT +%token tPURE tIMPURE tDISCARDABLE tLOADONCALL tPRELOAD tFIXED tMOVEABLE +%token tCLASS tCAPTION tCHARACTERISTICS tEXSTYLE tSTYLE tVERSION tLANGUAGE +%token tFILEVERSION tPRODUCTVERSION tFILEFLAGSMASK tFILEOS tFILETYPE tFILEFLAGS tFILESUBTYPE +%token tMENUBARBREAK tMENUBREAK tMENUITEM tPOPUP tSEPARATOR +%token tHELP +%token tSTRING tIDENT tRAWDATA +%token tTOOLBAR tBUTTON %token tBEGIN tEND -%token DLGINIT -%left LOGOR -%left LOGAND +%token tDLGINIT %left '|' %left '^' %left '&' -%left EQ NE -%left '<' LTE '>' GTE %left '+' '-' %left '*' '/' -%right '~' '!' NOT +%right '~' tNOT +%left pUPM %type resource_file resource resources resource_definition %type stringtable strings @@ -286,7 +281,7 @@ toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); %type userres %type item_options %type nameid nameid_s ctlclass usertype -%type acc_opt +%type acc_opt acc accs %type loadmemopts lamo lama %type opt_font opt_exfont opt_expr %type opt_lvc @@ -295,14 +290,14 @@ toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); %type opt_version %type expr xpr %type e_expr -%type pp_expr pp_constant %type toolbar %type toolbar_items %type dlginit %type optional_style_pair -%type any_num +%type any_num any_nums %type