mirror of
git://source.winehq.org/git/wine.git
synced 2024-08-31 07:34:06 +00:00
- 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.
This commit is contained in:
parent
5b4f3e8d6d
commit
27337af65c
|
@ -1,3 +1,4 @@
|
||||||
|
#include "windef.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "comctl32.h"
|
#include "comctl32.h"
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
#include "cdlg.h"
|
#include "cdlg.h"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
1 "OEMBIN"
|
1 OEMBIN
|
||||||
{
|
{
|
||||||
0x11, /* vertical thumb height (in pixels) */
|
0x11, /* vertical thumb height (in pixels) */
|
||||||
0x11, /* horizontal thumb width (in pixels) */
|
0x11, /* horizontal thumb width (in pixels) */
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
#include "shlobj.h"
|
#include "shlobj.h"
|
||||||
|
|
|
@ -25,10 +25,6 @@ all: check_wrc $(PROGRAMS)
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
# Override resource compiler rules
|
|
||||||
.rc.s:
|
|
||||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
|
||||||
|
|
||||||
|
|
||||||
clock: $(OBJS)
|
clock: $(OBJS)
|
||||||
$(CC) -o clock $(OBJS) $(DLL_LINK) $(LIBS)
|
$(CC) -o clock $(OBJS) $(DLL_LINK) $(LIBS)
|
||||||
|
|
|
@ -26,10 +26,6 @@ all: check_wrc $(PROGRAMS)
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
# Override resource compiler rules
|
|
||||||
.rc.s:
|
|
||||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
|
||||||
|
|
||||||
notepad: $(OBJS)
|
notepad: $(OBJS)
|
||||||
$(CC) -o notepad $(OBJS) $(DLL_LINK) $(LIBS)
|
$(CC) -o notepad $(OBJS) $(DLL_LINK) $(LIBS)
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,6 @@ all: check_wrc $(PROGRAMS)
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
# Override resource compiler rules
|
|
||||||
.rc.s:
|
|
||||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
|
||||||
|
|
||||||
progman: $(OBJS)
|
progman: $(OBJS)
|
||||||
$(CC) -o progman $(OBJS) $(DLL_LINK) $(LIBS)
|
$(CC) -o progman $(OBJS) $(DLL_LINK) $(LIBS)
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,6 @@ all: check_wrc $(PROGRAMS)
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
# Override resource compiler rules
|
|
||||||
.rc.s:
|
|
||||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
|
||||||
|
|
||||||
winemine: $(OBJS)
|
winemine: $(OBJS)
|
||||||
$(CC) -o winemine $(OBJS) $(DLL_LINK) $(LIBS)
|
$(CC) -o winemine $(OBJS) $(DLL_LINK) $(LIBS)
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,6 @@ depend: y.tab.h
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
# Override resource compiler rules
|
|
||||||
.rc.s:
|
|
||||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
|
||||||
|
|
||||||
winhelp: $(OBJS)
|
winhelp: $(OBJS)
|
||||||
$(CC) -o winhelp $(OBJS) $(DLL_LINK) $(LIBS)
|
$(CC) -o winhelp $(OBJS) $(DLL_LINK) $(LIBS)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
#include "dlgs.h"
|
#include "dlgs.h"
|
||||||
|
|
|
@ -19,7 +19,7 @@ EXTRASUBDIRS = \
|
||||||
winapi_check/win32 \
|
winapi_check/win32 \
|
||||||
wineconf.libs
|
wineconf.libs
|
||||||
|
|
||||||
all: $(PROGRAMS)
|
all: $(PROGRAMS) wrc
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
Makefile
|
Makefile
|
||||||
|
lex.ppl.c
|
||||||
lex.yy.c
|
lex.yy.c
|
||||||
|
ppy.tab.c
|
||||||
|
ppy.tab.h
|
||||||
wrc
|
wrc
|
||||||
y.tab.c
|
y.tab.c
|
||||||
y.tab.h
|
y.tab.h
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Version 1.1.0 (01-May-2000)
|
||||||
|
|
||||||
|
Bertho Stultiens <bertho@akhphd.au.dk>
|
||||||
|
- 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)
|
Version 1.0.18 (28-Dec-1999)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ TOPSRCDIR = @top_srcdir@
|
||||||
TOPOBJDIR = ../..
|
TOPOBJDIR = ../..
|
||||||
SRCDIR = @srcdir@
|
SRCDIR = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
|
LEXOPT = -Cf #-w -b
|
||||||
|
YACCOPT = #-v
|
||||||
|
|
||||||
PROGRAMS = wrc@PROGEXT@
|
PROGRAMS = wrc@PROGEXT@
|
||||||
MODULE = none
|
MODULE = none
|
||||||
|
@ -17,12 +19,12 @@ C_SRCS = \
|
||||||
wrc.c \
|
wrc.c \
|
||||||
writeres.c
|
writeres.c
|
||||||
|
|
||||||
EXTRA_SRCS = parser.y parser.l
|
EXTRA_SRCS = parser.y parser.l ppl.l ppy.y ppy.tab.c lex.ppl.c
|
||||||
EXTRA_OBJS = y.tab.o lex.yy.o
|
EXTRA_OBJS = y.tab.o lex.yy.o ppy.tab.o lex.ppl.o
|
||||||
|
|
||||||
all: $(PROGRAMS)
|
all: $(PROGRAMS)
|
||||||
|
|
||||||
depend: y.tab.h
|
depend: y.tab.h ppy.tab.h ppy.tab.c lex.ppl.c
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
|
@ -30,12 +32,18 @@ wrc@PROGEXT@: $(OBJS)
|
||||||
$(CC) $(CFLAGS) -o wrc@PROGEXT@ $(OBJS) $(LEXLIB)
|
$(CC) $(CFLAGS) -o wrc@PROGEXT@ $(OBJS) $(LEXLIB)
|
||||||
|
|
||||||
y.tab.c y.tab.h: parser.y
|
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.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::
|
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:
|
### Dependencies:
|
||||||
|
|
|
@ -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
|
See the file CHANGES for differences between the version and what has been
|
||||||
corrected in the current version.
|
corrected in the current version.
|
||||||
|
|
||||||
Wrc features:
|
Wrc features:
|
||||||
|
|
||||||
- source preprocessing
|
- full source preprocessing
|
||||||
- 16 and 32 bit support
|
- 16 and 32 bit support
|
||||||
- LANGUAGE support (32 bit only)
|
- LANGUAGE support (32 bit only)
|
||||||
- almost all resource types are supported
|
- most resource types are supported
|
||||||
- enhanced expression capabilities and resource naming
|
- enhanced expression capabilities and resource naming
|
||||||
- indirect loadable resources
|
- indirect loadable resources
|
||||||
- NE/PE resource directory generation
|
- NE/PE resource directory generation
|
||||||
|
@ -34,13 +34,15 @@ Usage: wrc [options...] [infile[.rc|.res]]
|
||||||
-d n Set debug level to 'n'
|
-d n Set debug level to 'n'
|
||||||
-D id[=val] Define preprocessor identifier id=val
|
-D id[=val] Define preprocessor identifier id=val
|
||||||
-e Disable recognition of win32 keywords in 16bit compile
|
-e Disable recognition of win32 keywords in 16bit compile
|
||||||
|
-E Preprocess only
|
||||||
-g Add symbols to the global c namespace
|
-g Add symbols to the global c namespace
|
||||||
-h Also generate a .h file
|
-h Also generate a .h file
|
||||||
-H file Same as -h but written to file
|
-H file Same as -h but written to file
|
||||||
-I path Set include search dir to path (multiple -I allowed)
|
-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
|
-L Leave case of embedded filenames as is
|
||||||
-n Do not generate .s file
|
-n Do not generate .s file
|
||||||
|
-N Do not preprocess input
|
||||||
-o file Output to file (default is infile.[res|s|h]
|
-o file Output to file (default is infile.[res|s|h]
|
||||||
-p prefix Give a prefix for the generated names
|
-p prefix Give a prefix for the generated names
|
||||||
-r Create binary .res file (compile only)
|
-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)
|
* 0x01 Tell which resource is parsed (verbose mode)
|
||||||
* 0x02 Dump internal structures
|
* 0x02 Dump internal structures
|
||||||
* 0x04 Create a parser trace (yydebug=1)
|
* 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
|
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'
|
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
|
Preprocessing
|
||||||
-------------
|
-------------
|
||||||
The build-in preprocessor is not a full implementation of the C counterpart.
|
The preprocessor is a fully operational C preprocessor. It handles all
|
||||||
Wrc does not understand function-type macros. These are discarded as they
|
directives supported by ANSI-C. It also includes some additions from
|
||||||
are scanned. This will be a future project. Wrc does understand these:
|
gcc/egcs.
|
||||||
#define
|
Wrc understands these directives:
|
||||||
|
#define (both simple and macro)
|
||||||
|
#undef
|
||||||
#if
|
#if
|
||||||
#ifdef
|
#ifdef
|
||||||
#ifndef
|
#ifndef
|
||||||
|
@ -78,13 +85,42 @@ are scanned. This will be a future project. Wrc does understand these:
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
#error
|
#error
|
||||||
|
#warning
|
||||||
|
#line
|
||||||
|
#
|
||||||
|
#pragma (ignored)
|
||||||
|
#ident (ignored)
|
||||||
|
|
||||||
Also 'defined' is supported as operator (both with and without parenthesis).
|
The extensions include '#'-line directives.
|
||||||
'#if' expressions can be anything valid that evaluates to an integer
|
Not handled at the moment are variable argument macros. They are parsed,
|
||||||
expression (where 0 is false and anything else is true). Others (#pragma,
|
but not expanded properly. This will be corrected in the future.
|
||||||
#line) are ignored. A special case '#' generates an error. This is due to
|
|
||||||
the implementation to enable generation of errors on preprocessing and will
|
The preprocessor handles the special defines and aditionally defines an
|
||||||
be improved in the future.
|
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
|
16 and 32 bit support
|
||||||
|
@ -115,35 +151,15 @@ statement before (and evt. after) the code in the resource file.
|
||||||
Resource types supported
|
Resource types supported
|
||||||
------------------------
|
------------------------
|
||||||
All types are supported except for:
|
All types are supported except for:
|
||||||
- FONT
|
- FONT (RT_FONT, RT_FONTDIR)
|
||||||
- MESSAGETABLE
|
- MESSAGETABLE (RT_MESSAGETABLE)
|
||||||
- extensions like TOOLBAR and the like (is this a user-type?)
|
- 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
|
These types will be implemented as soon as I get a proper specification of
|
||||||
the layout.
|
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
|
Expression capabilities and resource names
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
@ -152,22 +168,19 @@ expects a number (except usertype type). Operators supported:
|
||||||
() parenthesis
|
() parenthesis
|
||||||
* multiply
|
* multiply
|
||||||
/ divide
|
/ divide
|
||||||
+ add
|
+ plus/add
|
||||||
- minus/substract
|
- minus/substract
|
||||||
| binary or
|
| binary or
|
||||||
& binary and
|
& binary and
|
||||||
~ binary not (unary operator though)
|
~ binary not (unary operator though)
|
||||||
NOT ... (sigh)
|
NOT ... (sigh)
|
||||||
|
|
||||||
Minus (-) can both be unary and binary. The NOT operator is (primarily)
|
Plus (+) and minus (-) can both be unary and binary. The NOT operator is
|
||||||
used to disable window styles but I strongly suggest to refrain from using
|
(primarily) used to disable window styles but I strongly suggest to refrain
|
||||||
this operator.
|
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.
|
|
||||||
|
|
||||||
Resource names can be both numerical (expressions) and character typed. Wrc
|
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
|
MENU MENU
|
||||||
{
|
{
|
||||||
|
@ -250,9 +263,8 @@ though):
|
||||||
- No documentation ('wrc -?' gives command-line options though)
|
- No documentation ('wrc -?' gives command-line options though)
|
||||||
- grep for FIXME in the source
|
- grep for FIXME in the source
|
||||||
- Memory options are wrong under some conditions. There seems to be a
|
- Memory options are wrong under some conditions. There seems to be a
|
||||||
different action for win32 and win16.
|
different action for win32 and win16
|
||||||
- User-type resources have slightly different layout.
|
- Little/big-endian
|
||||||
- Filename scanning is still hopeless.
|
|
||||||
|
|
||||||
Reporting bugs and patches
|
Reporting bugs and patches
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
|
@ -293,3 +293,4 @@ style_t *new_style(DWORD or_mask, DWORD and_mask)
|
||||||
st->and_mask = and_mask;
|
st->and_mask = and_mask;
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
|
|
||||||
/* From parser.y */
|
/* From parser.y */
|
||||||
extern int yydebug;
|
extern int yydebug;
|
||||||
extern int indialog; /* Set when parsing dialogs */
|
extern int want_nl; /* Set when getting line-numers */
|
||||||
extern int want_rscname; /* Set when a resource's name is required */
|
|
||||||
|
|
||||||
int yyparse(void);
|
int yyparse(void);
|
||||||
void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico);
|
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 */
|
/* From parser.l */
|
||||||
extern FILE *yyin;
|
extern FILE *yyin;
|
||||||
extern char *yytext;
|
extern char *yytext;
|
||||||
extern int line_number;
|
extern int yy_flex_debug;
|
||||||
extern int char_number;
|
|
||||||
|
|
||||||
int yylex(void);
|
int yylex(void);
|
||||||
void set_yywf(void);
|
|
||||||
void set_pp_ignore(int state);
|
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_semicolon(void);
|
||||||
void strip_til_parenthesis(void);
|
void strip_til_parenthesis(void);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1407
tools/wrc/ppl.l
Normal file
1407
tools/wrc/ppl.l
Normal file
File diff suppressed because it is too large
Load diff
624
tools/wrc/ppy.y
Normal file
624
tools/wrc/ppy.y
Normal file
|
@ -0,0 +1,624 @@
|
||||||
|
/*
|
||||||
|
* Wrc preprocessor syntax analysis
|
||||||
|
*
|
||||||
|
* Copyright 1999-2000 Bertho A. Stultiens (BS)
|
||||||
|
*
|
||||||
|
* 24-Apr-2000 BS Restructured the lot to fit the new scanner
|
||||||
|
* and reintegrate into the wine-tree.
|
||||||
|
* 01-Jan-2000 BS FIXME: win16 preprocessor calculates with
|
||||||
|
* 16 bit ints and overflows...?
|
||||||
|
* 26-Dec-1999 BS Started this file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "newstruc.h"
|
||||||
|
#include "wrc.h"
|
||||||
|
#include "preproc.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define UNARY_OP(r, v, OP) \
|
||||||
|
switch(v.type) \
|
||||||
|
{ \
|
||||||
|
case cv_sint: r.val.si = OP v.val.si; break; \
|
||||||
|
case cv_uint: r.val.ui = OP v.val.ui; break; \
|
||||||
|
case cv_slong: r.val.sl = OP v.val.sl; break; \
|
||||||
|
case cv_ulong: r.val.ul = OP v.val.ul; break; \
|
||||||
|
case cv_sll: r.val.sll = OP v.val.sll; break; \
|
||||||
|
case cv_ull: r.val.ull = OP v.val.ull; break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define cv_signed(v) ((v.type & FLAG_SIGNED) != 0)
|
||||||
|
|
||||||
|
#define BIN_OP_INT(r, v1, v2, OP) \
|
||||||
|
r.type = v1.type; \
|
||||||
|
if(cv_signed(v1) && cv_signed(v2)) \
|
||||||
|
r.val.si = v1.val.si OP v2.val.si; \
|
||||||
|
else if(cv_signed(v1) && !cv_signed(v2)) \
|
||||||
|
r.val.si = v1.val.si OP v2.val.ui; \
|
||||||
|
else if(!cv_signed(v1) && cv_signed(v2)) \
|
||||||
|
r.val.ui = v1.val.ui OP v2.val.si; \
|
||||||
|
else \
|
||||||
|
r.val.ui = v1.val.ui OP v2.val.ui;
|
||||||
|
|
||||||
|
#define BIN_OP_LONG(r, v1, v2, OP) \
|
||||||
|
r.type = v1.type; \
|
||||||
|
if(cv_signed(v1) && cv_signed(v2)) \
|
||||||
|
r.val.sl = v1.val.sl OP v2.val.sl; \
|
||||||
|
else if(cv_signed(v1) && !cv_signed(v2)) \
|
||||||
|
r.val.sl = v1.val.sl OP v2.val.ul; \
|
||||||
|
else if(!cv_signed(v1) && cv_signed(v2)) \
|
||||||
|
r.val.ul = v1.val.ul OP v2.val.sl; \
|
||||||
|
else \
|
||||||
|
r.val.ul = v1.val.ul OP v2.val.ul;
|
||||||
|
|
||||||
|
#define BIN_OP_LONGLONG(r, v1, v2, OP) \
|
||||||
|
r.type = v1.type; \
|
||||||
|
if(cv_signed(v1) && cv_signed(v2)) \
|
||||||
|
r.val.sll = v1.val.sll OP v2.val.sll; \
|
||||||
|
else if(cv_signed(v1) && !cv_signed(v2)) \
|
||||||
|
r.val.sll = v1.val.sll OP v2.val.ull; \
|
||||||
|
else if(!cv_signed(v1) && cv_signed(v2)) \
|
||||||
|
r.val.ull = v1.val.ull OP v2.val.sll; \
|
||||||
|
else \
|
||||||
|
r.val.ull = v1.val.ull OP v2.val.ull;
|
||||||
|
|
||||||
|
#define BIN_OP(r, v1, v2, OP) \
|
||||||
|
switch(v1.type & SIZE_MASK) \
|
||||||
|
{ \
|
||||||
|
case SIZE_INT: BIN_OP_INT(r, v1, v2, OP); break; \
|
||||||
|
case SIZE_LONG: BIN_OP_LONG(r, v1, v2, OP); break; \
|
||||||
|
case SIZE_LONGLONG: BIN_OP_LONGLONG(r, v1, v2, OP); break; \
|
||||||
|
default: internal_error(__FILE__, __LINE__, "Invalid type indicator (0x%04x)", v1.type); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prototypes
|
||||||
|
*/
|
||||||
|
static int boolean(cval_t *v);
|
||||||
|
static void promote_equal_size(cval_t *v1, cval_t *v2);
|
||||||
|
static void cast_to_sint(cval_t *v);
|
||||||
|
static void cast_to_uint(cval_t *v);
|
||||||
|
static void cast_to_slong(cval_t *v);
|
||||||
|
static void cast_to_ulong(cval_t *v);
|
||||||
|
static void cast_to_sll(cval_t *v);
|
||||||
|
static void cast_to_ull(cval_t *v);
|
||||||
|
static marg_t *new_marg(char *str, def_arg_t type);
|
||||||
|
static marg_t *add_new_marg(char *str, def_arg_t type);
|
||||||
|
static int marg_index(char *id);
|
||||||
|
static mtext_t *new_mtext(char *str, int idx, def_exp_t type);
|
||||||
|
static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp);
|
||||||
|
static char *merge_text(char *s1, char *s2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables
|
||||||
|
*/
|
||||||
|
static marg_t **macro_args; /* Macro parameters array while parsing */
|
||||||
|
static int nmacro_args;
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union{
|
||||||
|
int sint;
|
||||||
|
unsigned int uint;
|
||||||
|
long slong;
|
||||||
|
unsigned long ulong;
|
||||||
|
wrc_sll_t sll;
|
||||||
|
wrc_ull_t ull;
|
||||||
|
int *iptr;
|
||||||
|
char *cptr;
|
||||||
|
cval_t cval;
|
||||||
|
marg_t *marg;
|
||||||
|
mtext_t *mtext;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL
|
||||||
|
%token tINCLUDE tLINE tGCCLINE tERROR tWARNING tPRAGMA tPPIDENT
|
||||||
|
%token tUNDEF tMACROEND tCONCAT tELIPSIS tSTRINGIZE
|
||||||
|
%token <cptr> tIDENT tLITERAL tMACRO tDEFINE
|
||||||
|
%token <cptr> tDQSTRING tSQSTRING tIQSTRING
|
||||||
|
%token <uint> tUINT
|
||||||
|
%token <sint> tSINT
|
||||||
|
%token <ulong> tULONG
|
||||||
|
%token <slong> tSLONG
|
||||||
|
%token <ull> tULONGLONG
|
||||||
|
%token <sll> tSLONGLONG
|
||||||
|
%right '?' ':'
|
||||||
|
%left tLOGOR
|
||||||
|
%left tLOGAND
|
||||||
|
%left '|'
|
||||||
|
%left '^'
|
||||||
|
%left '&'
|
||||||
|
%left tEQ tNE
|
||||||
|
%left '<' tLTE '>' tGTE
|
||||||
|
%left tLSHIFT tRSHIFT
|
||||||
|
%left '+' '-'
|
||||||
|
%left '*' '/'
|
||||||
|
%right '~' '!'
|
||||||
|
|
||||||
|
%type <cval> pp_expr
|
||||||
|
%type <marg> emargs margs
|
||||||
|
%type <mtext> opt_mtexts mtexts mtext
|
||||||
|
%type <sint> nums allmargs
|
||||||
|
%type <cptr> opt_text text
|
||||||
|
|
||||||
|
/*
|
||||||
|
**************************************************************************
|
||||||
|
* The parser starts here
|
||||||
|
**************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
pp_file : /* Empty */
|
||||||
|
| pp_file preprocessor
|
||||||
|
;
|
||||||
|
|
||||||
|
preprocessor
|
||||||
|
: tINCLUDE tDQSTRING tNL { do_include($2, 1); }
|
||||||
|
| tINCLUDE tIQSTRING tNL { do_include($2, 0); }
|
||||||
|
| tIF pp_expr tNL { next_if_state(boolean(&$2)); }
|
||||||
|
| tIFDEF tIDENT tNL { next_if_state(pplookup($2) != NULL); free($2); }
|
||||||
|
| tIFNDEF tIDENT tNL {
|
||||||
|
int t = pplookup($2) == NULL;
|
||||||
|
if(include_state == 0 && t && !seen_junk)
|
||||||
|
{
|
||||||
|
include_state = 1;
|
||||||
|
include_ppp = $2;
|
||||||
|
include_ifdepth = get_if_depth();
|
||||||
|
}
|
||||||
|
else if(include_state != 1)
|
||||||
|
{
|
||||||
|
include_state = -1;
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
free($2);
|
||||||
|
next_if_state(t);
|
||||||
|
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||||
|
fprintf(stderr, "tIFNDEF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n", input_name, line_number, include_state, include_ppp, include_ifdepth);
|
||||||
|
}
|
||||||
|
| tELIF pp_expr tNL {
|
||||||
|
if_state_t s = pop_if();
|
||||||
|
switch(s)
|
||||||
|
{
|
||||||
|
case if_true:
|
||||||
|
case if_elif:
|
||||||
|
push_if(if_elif);
|
||||||
|
break;
|
||||||
|
case if_false:
|
||||||
|
push_if(boolean(&$2) ? if_true : if_false);
|
||||||
|
break;
|
||||||
|
case if_ignore:
|
||||||
|
push_if(if_ignore);
|
||||||
|
break;
|
||||||
|
case if_elsetrue:
|
||||||
|
case if_elsefalse:
|
||||||
|
pperror("#elif cannot follow #else");
|
||||||
|
default:
|
||||||
|
internal_error(__FILE__, __LINE__, "Invalid if_state (%d) in #elif directive", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| tELSE tNL {
|
||||||
|
if_state_t s = pop_if();
|
||||||
|
switch(s)
|
||||||
|
{
|
||||||
|
case if_true:
|
||||||
|
push_if(if_elsefalse);
|
||||||
|
break;
|
||||||
|
case if_elif:
|
||||||
|
push_if(if_elif);
|
||||||
|
break;
|
||||||
|
case if_false:
|
||||||
|
push_if(if_elsetrue);
|
||||||
|
break;
|
||||||
|
case if_ignore:
|
||||||
|
push_if(if_ignore);
|
||||||
|
break;
|
||||||
|
case if_elsetrue:
|
||||||
|
case if_elsefalse:
|
||||||
|
pperror("#else clause already defined");
|
||||||
|
default:
|
||||||
|
internal_error(__FILE__, __LINE__, "Invalid if_state (%d) in #else directive", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| tENDIF tNL {
|
||||||
|
pop_if();
|
||||||
|
if(include_ifdepth == get_if_depth() && include_state == 1)
|
||||||
|
{
|
||||||
|
include_state = 2;
|
||||||
|
seen_junk = 0;
|
||||||
|
}
|
||||||
|
else if(include_state != 1)
|
||||||
|
{
|
||||||
|
include_state = -1;
|
||||||
|
}
|
||||||
|
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||||
|
fprintf(stderr, "tENDIF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n", input_name, line_number, include_state, include_ppp, include_ifdepth);
|
||||||
|
}
|
||||||
|
| tUNDEF tIDENT tNL { del_define($2); free($2); }
|
||||||
|
| tDEFINE opt_text tNL { add_define($1, $2); }
|
||||||
|
| tMACRO res_arg allmargs tMACROEND opt_mtexts tNL {
|
||||||
|
add_macro($1, macro_args, nmacro_args, $5);
|
||||||
|
}
|
||||||
|
| tLINE tSINT tDQSTRING tNL { fprintf(ppout, "# %d %s\n", $2 - 1, $3); free($3); }
|
||||||
|
| tGCCLINE tDQSTRING nums tNL { fprintf(ppout, "# %d %s\n", $3 - 1, $2); free($2); }
|
||||||
|
| tGCCLINE tNL /* The null-token */
|
||||||
|
| tERROR opt_text tNL { pperror("#error directive: '%s'", $2); if($2) free($2); }
|
||||||
|
| tWARNING opt_text tNL { ppwarning("#warning directive: '%s'", $2); if($2) free($2); }
|
||||||
|
| tPRAGMA opt_text tNL { if(pedantic) ppwarning("#pragma ignored (arg: '%s')", $2); if($2) free($2); }
|
||||||
|
| tPPIDENT opt_text tNL { if(pedantic) ppwarning("#ident ignored (arg: '%s')", $2); if($2) free($2); }
|
||||||
|
/*| tNL*/
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_text: /* Empty */ { $$ = NULL; }
|
||||||
|
| text { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
text : tLITERAL { $$ = $1; }
|
||||||
|
| tDQSTRING { $$ = $1; }
|
||||||
|
| tSQSTRING { $$ = $1; }
|
||||||
|
| text tLITERAL { $$ = merge_text($1, $2); }
|
||||||
|
| text tDQSTRING { $$ = merge_text($1, $2); }
|
||||||
|
| text tSQSTRING { $$ = merge_text($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
res_arg : /* Empty */ { macro_args = NULL; nmacro_args = 0; }
|
||||||
|
;
|
||||||
|
|
||||||
|
nums : tSINT { $$ = $1; }
|
||||||
|
| nums tSINT /* Ignore */
|
||||||
|
;
|
||||||
|
|
||||||
|
allmargs: /* Empty */ { $$ = 0; macro_args = NULL; nmacro_args = 0; }
|
||||||
|
| emargs { $$ = nmacro_args; }
|
||||||
|
;
|
||||||
|
|
||||||
|
emargs : margs { $$ = $1; }
|
||||||
|
| margs ',' tELIPSIS { $$ = add_new_marg(NULL, arg_list); nmacro_args *= -1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
margs : margs ',' tIDENT { $$ = add_new_marg($3, arg_single); }
|
||||||
|
| tIDENT { $$ = add_new_marg($1, arg_single); }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_mtexts
|
||||||
|
: /* Empty */ { $$ = NULL; }
|
||||||
|
| mtexts {
|
||||||
|
for($$ = $1; $$ && $$->prev; $$ = $$->prev)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
mtexts : mtext { $$ = $1; }
|
||||||
|
| mtexts mtext { $$ = combine_mtext($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
mtext : tLITERAL { $$ = new_mtext($1, 0, exp_text); }
|
||||||
|
| tDQSTRING { $$ = new_mtext($1, 0, exp_text); }
|
||||||
|
| tSQSTRING { $$ = new_mtext($1, 0, exp_text); }
|
||||||
|
| tCONCAT { $$ = new_mtext(NULL, 0, exp_concat); }
|
||||||
|
| tSTRINGIZE tIDENT {
|
||||||
|
int mat = marg_index($2);
|
||||||
|
if(mat < 0)
|
||||||
|
pperror("Stringification identifier must be an argument parameter");
|
||||||
|
$$ = new_mtext(NULL, mat, exp_stringize);
|
||||||
|
}
|
||||||
|
| tIDENT {
|
||||||
|
int mat = marg_index($1);
|
||||||
|
if(mat >= 0)
|
||||||
|
$$ = new_mtext(NULL, mat, exp_subst);
|
||||||
|
else
|
||||||
|
$$ = new_mtext($1, 0, exp_text);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
pp_expr : tSINT { $$.type = cv_sint; $$.val.si = $1; }
|
||||||
|
| tUINT { $$.type = cv_uint; $$.val.ui = $1; }
|
||||||
|
| tSLONG { $$.type = cv_slong; $$.val.sl = $1; }
|
||||||
|
| tULONG { $$.type = cv_ulong; $$.val.ul = $1; }
|
||||||
|
| tSLONGLONG { $$.type = cv_sll; $$.val.sl = $1; }
|
||||||
|
| tULONGLONG { $$.type = cv_ull; $$.val.ul = $1; }
|
||||||
|
| tDEFINED tIDENT { $$.type = cv_sint; $$.val.si = pplookup($2) != NULL; }
|
||||||
|
| tDEFINED '(' tIDENT ')' { $$.type = cv_sint; $$.val.si = pplookup($3) != NULL; }
|
||||||
|
| tIDENT { $$.type = cv_sint; $$.val.si = 0; }
|
||||||
|
| pp_expr tLOGOR pp_expr { $$.type = cv_sint; $$.val.si = boolean(&$1) || boolean(&$3); }
|
||||||
|
| pp_expr tLOGAND pp_expr { $$.type = cv_sint; $$.val.si = boolean(&$1) && boolean(&$3); }
|
||||||
|
| pp_expr tEQ pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, ==) }
|
||||||
|
| pp_expr tNE pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, !=) }
|
||||||
|
| pp_expr '<' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, <) }
|
||||||
|
| pp_expr '>' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, >) }
|
||||||
|
| pp_expr tLTE pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, <=) }
|
||||||
|
| pp_expr tGTE pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, >=) }
|
||||||
|
| pp_expr '+' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, +) }
|
||||||
|
| pp_expr '-' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, -) }
|
||||||
|
| pp_expr '^' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, ^) }
|
||||||
|
| pp_expr '&' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, &) }
|
||||||
|
| pp_expr '|' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, |) }
|
||||||
|
| pp_expr '*' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, *) }
|
||||||
|
| pp_expr '/' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, /) }
|
||||||
|
| pp_expr tLSHIFT pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, <<) }
|
||||||
|
| pp_expr tRSHIFT pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, >>) }
|
||||||
|
| '+' pp_expr { $$ = $2; }
|
||||||
|
| '-' pp_expr { UNARY_OP($$, $2, -) }
|
||||||
|
| '~' pp_expr { UNARY_OP($$, $2, ~) }
|
||||||
|
| '!' pp_expr { $$.type = cv_sint; $$.val.si = !boolean(&$2) }
|
||||||
|
| '(' pp_expr ')' { $$ = $2; }
|
||||||
|
| pp_expr '?' pp_expr ':' pp_expr { $$ = boolean(&$1) ? $3 : $5; }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
/*
|
||||||
|
**************************************************************************
|
||||||
|
* Support functions
|
||||||
|
**************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void cast_to_sint(cval_t *v)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case cv_sint: break;
|
||||||
|
case cv_uint: break;
|
||||||
|
case cv_slong: v->val.si = v->val.sl; break;
|
||||||
|
case cv_ulong: v->val.si = v->val.ul; break;
|
||||||
|
case cv_sll: v->val.si = v->val.sll; break;
|
||||||
|
case cv_ull: v->val.si = v->val.ull; break;
|
||||||
|
}
|
||||||
|
v->type = cv_sint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cast_to_uint(cval_t *v)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case cv_sint: break;
|
||||||
|
case cv_uint: break;
|
||||||
|
case cv_slong: v->val.ui = v->val.sl; break;
|
||||||
|
case cv_ulong: v->val.ui = v->val.ul; break;
|
||||||
|
case cv_sll: v->val.ui = v->val.sll; break;
|
||||||
|
case cv_ull: v->val.ui = v->val.ull; break;
|
||||||
|
}
|
||||||
|
v->type = cv_uint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cast_to_slong(cval_t *v)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case cv_sint: v->val.sl = v->val.si; break;
|
||||||
|
case cv_uint: v->val.sl = v->val.ui; break;
|
||||||
|
case cv_slong: break;
|
||||||
|
case cv_ulong: break;
|
||||||
|
case cv_sll: v->val.sl = v->val.sll; break;
|
||||||
|
case cv_ull: v->val.sl = v->val.ull; break;
|
||||||
|
}
|
||||||
|
v->type = cv_slong;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cast_to_ulong(cval_t *v)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case cv_sint: v->val.ul = v->val.si; break;
|
||||||
|
case cv_uint: v->val.ul = v->val.ui; break;
|
||||||
|
case cv_slong: break;
|
||||||
|
case cv_ulong: break;
|
||||||
|
case cv_sll: v->val.ul = v->val.sll; break;
|
||||||
|
case cv_ull: v->val.ul = v->val.ull; break;
|
||||||
|
}
|
||||||
|
v->type = cv_ulong;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cast_to_sll(cval_t *v)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case cv_sint: v->val.sll = v->val.si; break;
|
||||||
|
case cv_uint: v->val.sll = v->val.ui; break;
|
||||||
|
case cv_slong: v->val.sll = v->val.sl; break;
|
||||||
|
case cv_ulong: v->val.sll = v->val.ul; break;
|
||||||
|
case cv_sll: break;
|
||||||
|
case cv_ull: break;
|
||||||
|
}
|
||||||
|
v->type = cv_sll;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cast_to_ull(cval_t *v)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case cv_sint: v->val.ull = v->val.si; break;
|
||||||
|
case cv_uint: v->val.ull = v->val.ui; break;
|
||||||
|
case cv_slong: v->val.ull = v->val.sl; break;
|
||||||
|
case cv_ulong: v->val.ull = v->val.ul; break;
|
||||||
|
case cv_sll: break;
|
||||||
|
case cv_ull: break;
|
||||||
|
}
|
||||||
|
v->type = cv_ull;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void promote_equal_size(cval_t *v1, cval_t *v2)
|
||||||
|
{
|
||||||
|
#define cv_sizeof(v) ((int)(v->type & SIZE_MASK))
|
||||||
|
int s1 = cv_sizeof(v1);
|
||||||
|
int s2 = cv_sizeof(v2);
|
||||||
|
#undef cv_sizeof
|
||||||
|
|
||||||
|
if(s1 == s2)
|
||||||
|
return;
|
||||||
|
else if(s1 > s2)
|
||||||
|
{
|
||||||
|
switch(v1->type)
|
||||||
|
{
|
||||||
|
case cv_sint: cast_to_sint(v2); break;
|
||||||
|
case cv_uint: cast_to_uint(v2); break;
|
||||||
|
case cv_slong: cast_to_slong(v2); break;
|
||||||
|
case cv_ulong: cast_to_ulong(v2); break;
|
||||||
|
case cv_sll: cast_to_sll(v2); break;
|
||||||
|
case cv_ull: cast_to_ull(v2); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(v2->type)
|
||||||
|
{
|
||||||
|
case cv_sint: cast_to_sint(v1); break;
|
||||||
|
case cv_uint: cast_to_uint(v1); break;
|
||||||
|
case cv_slong: cast_to_slong(v1); break;
|
||||||
|
case cv_ulong: cast_to_ulong(v1); break;
|
||||||
|
case cv_sll: cast_to_sll(v1); break;
|
||||||
|
case cv_ull: cast_to_ull(v1); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int boolean(cval_t *v)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case cv_sint: return v->val.si != (int)0;
|
||||||
|
case cv_uint: return v->val.ui != (unsigned int)0;
|
||||||
|
case cv_slong: return v->val.sl != (long)0;
|
||||||
|
case cv_ulong: return v->val.ul != (unsigned long)0;
|
||||||
|
case cv_sll: return v->val.sll != (wrc_sll_t)0;
|
||||||
|
case cv_ull: return v->val.ull != (wrc_ull_t)0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static marg_t *new_marg(char *str, def_arg_t type)
|
||||||
|
{
|
||||||
|
marg_t *ma = (marg_t *)xmalloc(sizeof(marg_t));
|
||||||
|
ma->arg = str;
|
||||||
|
ma->type = type;
|
||||||
|
return ma;
|
||||||
|
}
|
||||||
|
|
||||||
|
static marg_t *add_new_marg(char *str, def_arg_t type)
|
||||||
|
{
|
||||||
|
marg_t *ma = new_marg(str, type);
|
||||||
|
nmacro_args++;
|
||||||
|
macro_args = (marg_t **)xrealloc(macro_args, nmacro_args * sizeof(macro_args[0]));
|
||||||
|
macro_args[nmacro_args-1] = ma;
|
||||||
|
return ma;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int marg_index(char *id)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
for(t = 0; t < nmacro_args; t++)
|
||||||
|
{
|
||||||
|
if(!strcmp(id, macro_args[t]->arg))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return t < nmacro_args ? t : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mtext_t *new_mtext(char *str, int idx, def_exp_t type)
|
||||||
|
{
|
||||||
|
mtext_t *mt = (mtext_t *)xmalloc(sizeof(mtext_t));
|
||||||
|
if(str == NULL)
|
||||||
|
mt->subst.argidx = idx;
|
||||||
|
else
|
||||||
|
mt->subst.text = str;
|
||||||
|
mt->type = type;
|
||||||
|
return mt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp)
|
||||||
|
{
|
||||||
|
if(!tail)
|
||||||
|
return mtp;
|
||||||
|
|
||||||
|
if(!mtp)
|
||||||
|
return tail;
|
||||||
|
|
||||||
|
if(tail->type == exp_text && mtp->type == exp_text)
|
||||||
|
{
|
||||||
|
tail->subst.text = xrealloc(tail->subst.text, strlen(tail->subst.text)+strlen(mtp->subst.text)+1);
|
||||||
|
strcat(tail->subst.text, mtp->subst.text);
|
||||||
|
free(mtp->subst.text);
|
||||||
|
free(mtp);
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tail->type == exp_concat && mtp->type == exp_concat)
|
||||||
|
{
|
||||||
|
free(mtp);
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tail->type == exp_concat && mtp->type == exp_text)
|
||||||
|
{
|
||||||
|
int len = strlen(mtp->subst.text);
|
||||||
|
while(len)
|
||||||
|
{
|
||||||
|
/* FIXME: should delete space from head of string */
|
||||||
|
if(isspace(mtp->subst.text[len-1]))
|
||||||
|
mtp->subst.text[--len] = '\0';
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!len)
|
||||||
|
{
|
||||||
|
free(mtp->subst.text);
|
||||||
|
free(mtp);
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tail->type == exp_text && mtp->type == exp_concat)
|
||||||
|
{
|
||||||
|
int len = strlen(tail->subst.text);
|
||||||
|
while(len)
|
||||||
|
{
|
||||||
|
if(isspace(tail->subst.text[len-1]))
|
||||||
|
tail->subst.text[--len] = '\0';
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!len)
|
||||||
|
{
|
||||||
|
mtp->prev = tail->prev;
|
||||||
|
mtp->next = tail->next;
|
||||||
|
if(tail->prev)
|
||||||
|
tail->prev->next = mtp;
|
||||||
|
free(tail->subst.text);
|
||||||
|
free(tail);
|
||||||
|
return mtp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tail->next = mtp;
|
||||||
|
mtp->prev = tail;
|
||||||
|
|
||||||
|
return mtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *merge_text(char *s1, char *s2)
|
||||||
|
{
|
||||||
|
int l1 = strlen(s1);
|
||||||
|
int l2 = strlen(s2);
|
||||||
|
s1 = xrealloc(s1, l1+l2+1);
|
||||||
|
memcpy(s1+l1, s2, l2+1);
|
||||||
|
free(s2);
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
|
@ -8,48 +8,46 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "wrc.h"
|
#include "wrc.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "preproc.h"
|
#include "preproc.h"
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern void set_pp_ignore(int); /* From parser.l */
|
extern void set_pp_ignore(int); /* From parser.l */
|
||||||
|
|
||||||
static char *current_define;
|
|
||||||
|
|
||||||
#define HASHKEY 2039
|
#define HASHKEY 2039
|
||||||
static struct pp_entry *pp_defines[HASHKEY];
|
static pp_entry_t *pp_defines[HASHKEY];
|
||||||
|
|
||||||
#define MAXIFSTACK 64
|
#define MAXIFSTACK 64
|
||||||
static struct if_state ifstack[MAXIFSTACK];
|
static if_state_t if_stack[MAXIFSTACK];
|
||||||
static int ifstackidx = 0;
|
static int if_stack_idx = 0;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
void pp_status(void) __attribute__((destructor));
|
||||||
void pp_status(void)
|
void pp_status(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int sum;
|
int sum;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
struct pp_entry *ppp;
|
pp_entry_t *ppp;
|
||||||
|
|
||||||
printf("Defines statistics:\n");
|
fprintf(stderr, "Defines statistics:\n");
|
||||||
for(i = 0; i < HASHKEY; i++)
|
for(i = 0; i < HASHKEY; i++)
|
||||||
{
|
{
|
||||||
sum = 0;
|
sum = 0;
|
||||||
for(ppp = pp_defines[i]; ppp; ppp = ppp->next)
|
for(ppp = pp_defines[i]; ppp; ppp = ppp->next)
|
||||||
sum++;
|
sum++;
|
||||||
total += sum;
|
total += sum;
|
||||||
printf("%4d, %3d\n", i, sum);
|
fprintf(stderr, "%4d, %3d\n", i, sum);
|
||||||
}
|
}
|
||||||
printf("Total defines: %d\n", total);
|
fprintf(stderr, "Total defines: %d\n", total);
|
||||||
}
|
}
|
||||||
#pragma exit pp_status
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Don't comment on the hash, its primitive but functional... */
|
/* Don't comment on the hash, its primitive but functional... */
|
||||||
int pp_hash(char *str)
|
int pphash(char *str)
|
||||||
{
|
{
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
while(*str)
|
while(*str)
|
||||||
|
@ -57,11 +55,12 @@ int pp_hash(char *str)
|
||||||
return sum % HASHKEY;
|
return sum % HASHKEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pp_entry *pp_lookup(char *ident)
|
pp_entry_t *pplookup(char *ident)
|
||||||
{
|
{
|
||||||
int index = pp_hash(ident);
|
int idx = pphash(ident);
|
||||||
struct pp_entry *ppp;
|
pp_entry_t *ppp;
|
||||||
for(ppp = pp_defines[index]; ppp; ppp = ppp->next)
|
|
||||||
|
for(ppp = pp_defines[idx]; ppp; ppp = ppp->next)
|
||||||
{
|
{
|
||||||
if(!strcmp(ident, ppp->ident))
|
if(!strcmp(ident, ppp->ident))
|
||||||
return ppp;
|
return ppp;
|
||||||
|
@ -69,29 +68,44 @@ struct pp_entry *pp_lookup(char *ident)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_define(char *name)
|
|
||||||
{
|
|
||||||
current_define = xstrdup(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void del_define(char *name)
|
void del_define(char *name)
|
||||||
{
|
{
|
||||||
int index;
|
int idx;
|
||||||
struct pp_entry *ppp;
|
pp_entry_t *ppp;
|
||||||
|
|
||||||
if((ppp = pp_lookup(name)) == NULL)
|
if((ppp = pplookup(name)) == NULL)
|
||||||
{
|
{
|
||||||
if(pedantic)
|
if(pedantic)
|
||||||
yywarning("%s was not defined", name);
|
yywarning("%s was not defined", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = pp_hash(name);
|
if(ppp->iep)
|
||||||
if(pp_defines[index] == ppp)
|
|
||||||
{
|
{
|
||||||
pp_defines[index] = ppp->next;
|
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||||
if(pp_defines[index])
|
fprintf(stderr, "del_define: %s:%d: includelogic removed, include_ppp='%s', file=%s\n", input_name, line_number, name, ppp->iep->filename);
|
||||||
pp_defines[index]->prev = NULL;
|
if(ppp->iep == includelogiclist)
|
||||||
|
{
|
||||||
|
includelogiclist = ppp->iep->next;
|
||||||
|
if(includelogiclist)
|
||||||
|
includelogiclist->prev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ppp->iep->prev->next = ppp->iep->next;
|
||||||
|
if(ppp->iep->next)
|
||||||
|
ppp->iep->next->prev = ppp->iep->prev;
|
||||||
|
}
|
||||||
|
free(ppp->iep->filename);
|
||||||
|
free(ppp->iep);
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = pphash(name);
|
||||||
|
if(pp_defines[idx] == ppp)
|
||||||
|
{
|
||||||
|
pp_defines[idx] = ppp->next;
|
||||||
|
if(pp_defines[idx])
|
||||||
|
pp_defines[idx]->prev = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -99,54 +113,128 @@ void del_define(char *name)
|
||||||
if(ppp->next)
|
if(ppp->next)
|
||||||
ppp->next->prev = ppp->prev;
|
ppp->next->prev = ppp->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ppp);
|
free(ppp);
|
||||||
|
|
||||||
|
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||||
|
printf("Deleted (%s, %d) <%s>\n", input_name, line_number, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_define(char *text)
|
pp_entry_t *add_define(char *def, char *text)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
char *cptr;
|
char *cptr;
|
||||||
int index = pp_hash(current_define);
|
int idx = pphash(def);
|
||||||
struct pp_entry *ppp;
|
pp_entry_t *ppp;
|
||||||
if(pp_lookup(current_define) != NULL)
|
|
||||||
|
if((ppp = pplookup(def)) != NULL)
|
||||||
{
|
{
|
||||||
if(pedantic)
|
if(pedantic)
|
||||||
yywarning("Redefinition of %s", current_define);
|
yywarning("Redefinition of %s\n\tPrevious definition: %s:%d", def, ppp->filename, ppp->linenumber);
|
||||||
del_define(current_define);
|
del_define(def);
|
||||||
}
|
}
|
||||||
ppp = (struct pp_entry *)xmalloc(sizeof(struct pp_entry));
|
ppp = (pp_entry_t *)xmalloc(sizeof(pp_entry_t));
|
||||||
ppp->ident = current_define;
|
ppp->ident = def;
|
||||||
ppp->subst = xstrdup(text);
|
ppp->type = def_define;
|
||||||
ppp->next = pp_defines[index];
|
ppp->subst.text = text;
|
||||||
pp_defines[index] = ppp;
|
ppp->filename = input_name ? xstrdup(input_name) : "<internal or cmdline>";
|
||||||
|
ppp->linenumber = input_name ? line_number : 0;
|
||||||
|
ppp->next = pp_defines[idx];
|
||||||
|
pp_defines[idx] = ppp;
|
||||||
if(ppp->next)
|
if(ppp->next)
|
||||||
ppp->next->prev = ppp;
|
ppp->next->prev = ppp;
|
||||||
/* Strip trailing white space from subst text */
|
if(text)
|
||||||
len = strlen(ppp->subst);
|
|
||||||
while(len && strchr(" \t\r\n", ppp->subst[len-1]))
|
|
||||||
{
|
{
|
||||||
ppp->subst[--len] = '\0';
|
/* Strip trailing white space from subst text */
|
||||||
}
|
len = strlen(text);
|
||||||
/* Strip leading white space from subst text */
|
while(len && strchr(" \t\r\n", text[len-1]))
|
||||||
for(cptr = ppp->subst; *cptr && strchr(" \t\r", *cptr); cptr++)
|
{
|
||||||
|
text[--len] = '\0';
|
||||||
|
}
|
||||||
|
/* Strip leading white space from subst text */
|
||||||
|
for(cptr = text; *cptr && strchr(" \t\r", *cptr); cptr++)
|
||||||
;
|
;
|
||||||
if(ppp->subst != cptr)
|
if(text != cptr)
|
||||||
memmove(ppp->subst, cptr, strlen(cptr)+1);
|
memmove(text, cptr, strlen(cptr)+1);
|
||||||
if(yydebug)
|
}
|
||||||
printf("Added (%s, %d) <%s> to <%s>\n", input_name, line_number, ppp->ident, ppp->subst);
|
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||||
|
printf("Added define (%s, %d) <%s> to <%s>\n", input_name, line_number, ppp->ident, text ? text : "(null)");
|
||||||
|
|
||||||
|
return ppp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_cmdline_define(char *set)
|
pp_entry_t *add_cmdline_define(char *set)
|
||||||
{
|
{
|
||||||
char *cpy = xstrdup(set); /* Because gcc passes a R/O string */
|
char *cpy = xstrdup(set); /* Because gcc passes a R/O string */
|
||||||
char *cptr = strchr(cpy, '=');
|
char *cptr = strchr(cpy, '=');
|
||||||
if(cptr)
|
if(cptr)
|
||||||
*cptr = '\0';
|
*cptr = '\0';
|
||||||
set_define(cpy);
|
return add_define(cpy, xstrdup(cptr ? cptr+1 : ""));
|
||||||
add_define(cptr ? cptr+1 : "");
|
|
||||||
free(cpy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp_entry_t *add_special_define(char *id)
|
||||||
|
{
|
||||||
|
pp_entry_t *ppp = add_define(xstrdup(id), xstrdup(""));
|
||||||
|
ppp->type = def_special;
|
||||||
|
return ppp;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp_entry_t *add_macro(char *id, marg_t *args[], int nargs, mtext_t *exp)
|
||||||
|
{
|
||||||
|
int idx = pphash(id);
|
||||||
|
pp_entry_t *ppp;
|
||||||
|
|
||||||
|
if((ppp = pplookup(id)) != NULL)
|
||||||
|
{
|
||||||
|
if(pedantic)
|
||||||
|
yywarning("Redefinition of %s\n\tPrevious definition: %s:%d", id, ppp->filename, ppp->linenumber);
|
||||||
|
del_define(id);
|
||||||
|
}
|
||||||
|
ppp = (pp_entry_t *)xmalloc(sizeof(pp_entry_t));
|
||||||
|
ppp->ident = id;
|
||||||
|
ppp->type = def_macro;
|
||||||
|
ppp->margs = args;
|
||||||
|
ppp->nargs = nargs;
|
||||||
|
ppp->subst.mtext= exp;
|
||||||
|
ppp->filename = input_name ? xstrdup(input_name) : "<internal or cmdline>";
|
||||||
|
ppp->linenumber = input_name ? line_number : 0;
|
||||||
|
ppp->next = pp_defines[idx];
|
||||||
|
pp_defines[idx] = ppp;
|
||||||
|
if(ppp->next)
|
||||||
|
ppp->next->prev = ppp;
|
||||||
|
|
||||||
|
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Added macro (%s, %d) <%s(%d)> to <", input_name, line_number, ppp->ident, nargs);
|
||||||
|
for(; exp; exp = exp->next)
|
||||||
|
{
|
||||||
|
switch(exp->type)
|
||||||
|
{
|
||||||
|
case exp_text:
|
||||||
|
fprintf(stderr, " \"%s\" ", exp->subst.text);
|
||||||
|
break;
|
||||||
|
case exp_stringize:
|
||||||
|
fprintf(stderr, " #(%d) ", exp->subst.argidx);
|
||||||
|
break;
|
||||||
|
case exp_concat:
|
||||||
|
fprintf(stderr, "##");
|
||||||
|
break;
|
||||||
|
case exp_subst:
|
||||||
|
fprintf(stderr, " <%d> ", exp->subst.argidx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, ">\n");
|
||||||
|
}
|
||||||
|
return ppp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* Include management
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
#if defined(_Windows) || defined(__MSDOS__)
|
#if defined(_Windows) || defined(__MSDOS__)
|
||||||
#define INCLUDESEPARATOR ";"
|
#define INCLUDESEPARATOR ";"
|
||||||
#else
|
#else
|
||||||
|
@ -188,7 +276,7 @@ void add_include_path(char *path)
|
||||||
free(cpy);
|
free(cpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *open_include(const char *name, int search)
|
FILE *open_include(const char *name, int search, char **newpath)
|
||||||
{
|
{
|
||||||
char *cpy = xstrdup(name);
|
char *cpy = xstrdup(name);
|
||||||
char *cptr;
|
char *cptr;
|
||||||
|
@ -208,12 +296,15 @@ FILE *open_include(const char *name, int search)
|
||||||
if(search)
|
if(search)
|
||||||
{
|
{
|
||||||
/* Search current dir and then -I path */
|
/* Search current dir and then -I path */
|
||||||
fp = fopen(name, "rt");
|
fp = fopen(cpy, "rt");
|
||||||
if(fp)
|
if(fp)
|
||||||
{
|
{
|
||||||
if(yydebug)
|
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||||
printf("Going to include <%s>\n", name);
|
printf("Going to include <%s>\n", name);
|
||||||
free(cpy);
|
if(newpath)
|
||||||
|
*newpath = cpy;
|
||||||
|
else
|
||||||
|
free(cpy);
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,57 +317,166 @@ FILE *open_include(const char *name, int search)
|
||||||
strcat(path, "/");
|
strcat(path, "/");
|
||||||
strcat(path, cpy);
|
strcat(path, cpy);
|
||||||
fp = fopen(path, "rt");
|
fp = fopen(path, "rt");
|
||||||
if(fp && yydebug)
|
if(fp && (debuglevel & DEBUGLEVEL_PPMSG))
|
||||||
printf("Going to include <%s>\n", path);
|
printf("Going to include <%s>\n", path);
|
||||||
free(path);
|
|
||||||
if(fp)
|
if(fp)
|
||||||
{
|
{
|
||||||
|
if(newpath)
|
||||||
|
*newpath = path;
|
||||||
|
else
|
||||||
|
free(path);
|
||||||
free(cpy);
|
free(cpy);
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
free(cpy);
|
free(cpy);
|
||||||
|
if(newpath)
|
||||||
|
*newpath = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_if(int truecase, int wastrue, int nevertrue)
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* #if, #ifdef, #ifndef, #else, #elif and #endif state management
|
||||||
|
*
|
||||||
|
* #if state transitions are made on basis of the current TOS and the next
|
||||||
|
* required state. The state transitions are required to housekeep because
|
||||||
|
* #if:s can be nested. The ignore case is activated to prevent output from
|
||||||
|
* within a false clause.
|
||||||
|
* Some special cases come from the fact that the #elif cases are not
|
||||||
|
* binary, but three-state. The problem is that all other elif-cases must
|
||||||
|
* be false when one true one has been found. A second problem is that the
|
||||||
|
* #else clause is a final clause. No extra #else:s may follow.
|
||||||
|
*
|
||||||
|
* The states mean:
|
||||||
|
* if_true Process input to output
|
||||||
|
* if_false Process input but no output
|
||||||
|
* if_ignore Process input but no output
|
||||||
|
* if_elif Process input but no output
|
||||||
|
* if_elsefalse Process input but no output
|
||||||
|
* if_elsettrue Process input to output
|
||||||
|
*
|
||||||
|
* The possible state-sequences are [state(stack depth)] (rest can be deduced):
|
||||||
|
* TOS #if 1 #else #endif
|
||||||
|
* if_true(n) if_true(n+1) if_elsefalse(n+1)
|
||||||
|
* if_false(n) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_elsetrue(n) if_true(n+1) if_elsefalse(n+1)
|
||||||
|
* if_elsefalse(n) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_elif(n) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_ignore(n) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
*
|
||||||
|
* TOS #if 1 #elif 0 #else #endif
|
||||||
|
* if_true(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
|
||||||
|
* if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_elsetrue(n) if_true(n+1) if_elif(n+1) if_elif(n+1)
|
||||||
|
* if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
*
|
||||||
|
* TOS #if 0 #elif 1 #else #endif
|
||||||
|
* if_true(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
|
||||||
|
* if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_elsetrue(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1)
|
||||||
|
* if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
* if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1)
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
static char *if_state_str[] = {
|
||||||
|
"if_false",
|
||||||
|
"if_true",
|
||||||
|
"if_elif",
|
||||||
|
"if_elsefalse",
|
||||||
|
"if_elsetrue",
|
||||||
|
"if_ignore"
|
||||||
|
};
|
||||||
|
|
||||||
|
void push_if(if_state_t s)
|
||||||
{
|
{
|
||||||
if(ifstackidx >= MAXIFSTACK-1)
|
if(if_stack_idx >= MAXIFSTACK)
|
||||||
internal_error(__FILE__, __LINE__, "#if stack overflow");
|
internal_error(__FILE__, __LINE__, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK);
|
||||||
ifstack[ifstackidx].current = truecase && !wastrue;
|
|
||||||
ifstack[ifstackidx].hasbeentrue = wastrue;
|
if(debuglevel & DEBUGLEVEL_PPLEX)
|
||||||
ifstack[ifstackidx].nevertrue = nevertrue;
|
fprintf(stderr, "Push if %s:%d: %s(%d) -> %s(%d)\n", input_name, line_number, if_state_str[if_state()], if_stack_idx, if_state_str[s], if_stack_idx+1);
|
||||||
if(nevertrue || !(truecase && !wastrue))
|
|
||||||
set_pp_ignore(1);
|
if_stack[if_stack_idx++] = s;
|
||||||
if(yydebug)
|
|
||||||
printf("push_if: %d %d %d (%d %d %d)\n",
|
switch(s)
|
||||||
truecase,
|
{
|
||||||
wastrue,
|
case if_true:
|
||||||
nevertrue,
|
case if_elsetrue:
|
||||||
ifstack[ifstackidx].current,
|
break;
|
||||||
ifstack[ifstackidx].hasbeentrue,
|
case if_false:
|
||||||
ifstack[ifstackidx].nevertrue);
|
case if_elsefalse:
|
||||||
ifstackidx++;
|
case if_elif:
|
||||||
|
case if_ignore:
|
||||||
|
push_ignore_state();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pop_if(void)
|
if_state_t pop_if(void)
|
||||||
{
|
{
|
||||||
if(ifstackidx <= 0)
|
if(if_stack_idx <= 0)
|
||||||
yyerror("#endif without #if|#ifdef|#ifndef (#if stack underflow)");
|
yyerror("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
|
||||||
ifstackidx--;
|
|
||||||
if(yydebug)
|
switch(if_state())
|
||||||
printf("pop_if: %d %d %d\n",
|
{
|
||||||
ifstack[ifstackidx].current,
|
case if_true:
|
||||||
ifstack[ifstackidx].hasbeentrue,
|
case if_elsetrue:
|
||||||
ifstack[ifstackidx].nevertrue);
|
break;
|
||||||
if(ifstack[ifstackidx].nevertrue || !ifstack[ifstackidx].current)
|
case if_false:
|
||||||
set_pp_ignore(0);
|
case if_elsefalse:
|
||||||
return ifstack[ifstackidx].hasbeentrue || ifstack[ifstackidx].current;
|
case if_elif:
|
||||||
|
case if_ignore:
|
||||||
|
pop_ignore_state();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(debuglevel & DEBUGLEVEL_PPLEX)
|
||||||
|
fprintf(stderr, "Pop if %s:%d: %s(%d) -> %s(%d)\n",
|
||||||
|
input_name,
|
||||||
|
line_number,
|
||||||
|
if_state_str[if_state()],
|
||||||
|
if_stack_idx,
|
||||||
|
if_state_str[if_stack[if_stack_idx <= 1 ? if_true : if_stack_idx-2]],
|
||||||
|
if_stack_idx-1);
|
||||||
|
|
||||||
|
return if_stack[--if_stack_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
int isnevertrue_if(void)
|
if_state_t if_state(void)
|
||||||
{
|
{
|
||||||
return ifstackidx > 0 && ifstack[ifstackidx-1].nevertrue;
|
if(!if_stack_idx)
|
||||||
|
return if_true;
|
||||||
|
else
|
||||||
|
return if_stack[if_stack_idx-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void next_if_state(int i)
|
||||||
|
{
|
||||||
|
switch(if_state())
|
||||||
|
{
|
||||||
|
case if_true:
|
||||||
|
case if_elsetrue:
|
||||||
|
push_if(i ? if_true : if_false);
|
||||||
|
break;
|
||||||
|
case if_false:
|
||||||
|
case if_elsefalse:
|
||||||
|
case if_elif:
|
||||||
|
case if_ignore:
|
||||||
|
push_if(if_ignore);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
internal_error(__FILE__, __LINE__, "Invalid if_state (%d) in #{if,ifdef,ifndef} directive", (int)if_state());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_if_depth(void)
|
||||||
|
{
|
||||||
|
return if_stack_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,30 +6,193 @@
|
||||||
#ifndef __WRC_PREPROC_H
|
#ifndef __WRC_PREPROC_H
|
||||||
#define __WRC_PREPROC_H
|
#define __WRC_PREPROC_H
|
||||||
|
|
||||||
struct pp_entry {
|
struct pp_entry; /* forward */
|
||||||
|
/*
|
||||||
|
* Include logic
|
||||||
|
* A stack of files which are already included and
|
||||||
|
* are protected in the #ifndef/#endif way.
|
||||||
|
*/
|
||||||
|
typedef struct includelogicentry {
|
||||||
|
struct includelogicentry *next;
|
||||||
|
struct includelogicentry *prev;
|
||||||
|
struct pp_entry *ppp; /* The define which protects the file */
|
||||||
|
char *filename; /* The filename of the include */
|
||||||
|
} includelogicentry_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The arguments of a macrodefinition
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
arg_single,
|
||||||
|
arg_list
|
||||||
|
} def_arg_t;
|
||||||
|
|
||||||
|
typedef struct marg {
|
||||||
|
def_arg_t type; /* Normal or ... argument */
|
||||||
|
char *arg; /* The textual argument */
|
||||||
|
int nnl; /* Number of newlines in the text to subst */
|
||||||
|
} marg_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The expansiontext of a macro
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
exp_text, /* Simple text substitution */
|
||||||
|
exp_concat, /* Concat (##) operator requested */
|
||||||
|
exp_stringize, /* Stringize (#) operator requested */
|
||||||
|
exp_subst /* Substitute argument */
|
||||||
|
} def_exp_t;
|
||||||
|
|
||||||
|
typedef struct mtext {
|
||||||
|
struct mtext *next;
|
||||||
|
struct mtext *prev;
|
||||||
|
def_exp_t type;
|
||||||
|
union {
|
||||||
|
char *text;
|
||||||
|
int argidx; /* For exp_subst and exp_stringize reference */
|
||||||
|
} subst;
|
||||||
|
} mtext_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The define descriptor
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
def_none, /* Not-a-define; used as return value */
|
||||||
|
def_define, /* Simple defines */
|
||||||
|
def_macro, /* Macro defines */
|
||||||
|
def_special /* Special expansions like __LINE__ and __FILE__ */
|
||||||
|
} def_type_t;
|
||||||
|
|
||||||
|
typedef struct pp_entry {
|
||||||
struct pp_entry *next;
|
struct pp_entry *next;
|
||||||
struct pp_entry *prev;
|
struct pp_entry *prev;
|
||||||
char *ident;
|
def_type_t type; /* Define or macro */
|
||||||
char *subst;
|
char *ident; /* The key */
|
||||||
int expanding;
|
marg_t **margs; /* Macro arguments array or NULL if none */
|
||||||
};
|
int nargs;
|
||||||
|
union {
|
||||||
|
mtext_t *mtext; /* The substitution sequence or NULL if none */
|
||||||
|
char *text;
|
||||||
|
} subst;
|
||||||
|
int expanding; /* Set when feeding substitution into the input */
|
||||||
|
char *filename; /* Filename where it was defined */
|
||||||
|
int linenumber; /* Linenumber where it was defined */
|
||||||
|
includelogicentry_t *iep; /* Points to the include it protects */
|
||||||
|
} pp_entry_t;
|
||||||
|
|
||||||
struct if_state {
|
|
||||||
int current;
|
|
||||||
int hasbeentrue;
|
|
||||||
int nevertrue;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pp_entry *pp_lookup(char *ident);
|
/*
|
||||||
void set_define(char *name);
|
* If logic
|
||||||
|
*/
|
||||||
|
#define MAXIFSTACK 64 /* If this isn't enough you should alter the source... */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
if_false,
|
||||||
|
if_true,
|
||||||
|
if_elif,
|
||||||
|
if_elsefalse,
|
||||||
|
if_elsetrue,
|
||||||
|
if_ignore
|
||||||
|
} if_state_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I assume that 'long long' exists in the compiler when it has a size
|
||||||
|
* of 8 or bigger. If not, then we revert to a simple 'long' for now.
|
||||||
|
* This should prevent most unexpected things with other compilers than
|
||||||
|
* gcc and egcs for now.
|
||||||
|
* In the future it should be possible to use another way, like a
|
||||||
|
* structure, so that we can emulate the MS compiler.
|
||||||
|
*/
|
||||||
|
#if defined(SIZEOF_LONGLONG) && SIZEOF_LONGLONG >= 8
|
||||||
|
typedef long long wrc_sll_t;
|
||||||
|
typedef unsigned long long wrc_ull_t;
|
||||||
|
#else
|
||||||
|
typedef long wrc_sll_t;
|
||||||
|
typedef unsigned long wrc_ull_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SIZE_CHAR 1
|
||||||
|
#define SIZE_SHORT 2
|
||||||
|
#define SIZE_INT 3
|
||||||
|
#define SIZE_LONG 4
|
||||||
|
#define SIZE_LONGLONG 5
|
||||||
|
#define SIZE_MASK 0x00ff
|
||||||
|
#define FLAG_SIGNED 0x0100
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
#if 0
|
||||||
|
cv_schar = SIZE_CHAR + FLAG_SIGNED,
|
||||||
|
cv_uchar = SIZE_CHAR,
|
||||||
|
cv_sshort = SIZE_SHORT + FLAG_SIGNED,
|
||||||
|
cv_ushort = SIZE_SHORT,
|
||||||
|
#endif
|
||||||
|
cv_sint = SIZE_INT + FLAG_SIGNED,
|
||||||
|
cv_uint = SIZE_INT,
|
||||||
|
cv_slong = SIZE_LONG + FLAG_SIGNED,
|
||||||
|
cv_ulong = SIZE_LONG,
|
||||||
|
cv_sll = SIZE_LONGLONG + FLAG_SIGNED,
|
||||||
|
cv_ull = SIZE_LONGLONG
|
||||||
|
} ctype_t;
|
||||||
|
|
||||||
|
typedef struct cval {
|
||||||
|
ctype_t type;
|
||||||
|
union {
|
||||||
|
#if 0
|
||||||
|
signed char sc; /* Explicitely signed because compilers are stupid */
|
||||||
|
unsigned char uc;
|
||||||
|
short ss;
|
||||||
|
unsigned short us;
|
||||||
|
#endif
|
||||||
|
int si;
|
||||||
|
unsigned int ui;
|
||||||
|
long sl;
|
||||||
|
unsigned long ul;
|
||||||
|
wrc_sll_t sll;
|
||||||
|
wrc_ull_t ull;
|
||||||
|
} val;
|
||||||
|
} cval_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pp_entry_t *pplookup(char *ident);
|
||||||
|
pp_entry_t *add_define(char *def, char *text);
|
||||||
|
pp_entry_t *add_cmdline_define(char *set);
|
||||||
|
pp_entry_t *add_special_define(char *id);
|
||||||
|
pp_entry_t *add_macro(char *ident, marg_t *args[], int nargs, mtext_t *exp);
|
||||||
void del_define(char *name);
|
void del_define(char *name);
|
||||||
void add_define(char *text);
|
FILE *open_include(const char *name, int search, char **newpath);
|
||||||
void add_cmdline_define(char *set);
|
|
||||||
FILE *open_include(const char *name, int search);
|
|
||||||
void add_include_path(char *path);
|
void add_include_path(char *path);
|
||||||
void push_if(int truecase, int wastrue, int nevertrue);
|
void push_if(if_state_t s);
|
||||||
int pop_if(void);
|
void next_if_state(int);
|
||||||
int isnevertrue_if(void);
|
if_state_t pop_if(void);
|
||||||
|
if_state_t if_state(void);
|
||||||
|
int get_if_depth(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From ppl.l
|
||||||
|
*/
|
||||||
|
extern FILE *ppin;
|
||||||
|
extern FILE *ppout;
|
||||||
|
extern char *pptext;
|
||||||
|
extern int pp_flex_debug;
|
||||||
|
int pplex(void);
|
||||||
|
|
||||||
|
void do_include(char *fname, int type);
|
||||||
|
void push_ignore_state(void);
|
||||||
|
void pop_ignore_state(void);
|
||||||
|
|
||||||
|
extern int include_state;
|
||||||
|
extern char *include_ppp;
|
||||||
|
extern char *include_filename;
|
||||||
|
extern int include_ifdepth;
|
||||||
|
extern int seen_junk;
|
||||||
|
extern includelogicentry_t *includelogiclist;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From ppy.y
|
||||||
|
*/
|
||||||
|
int ppparse(void);
|
||||||
|
extern int ppdebug;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,9 @@
|
||||||
#include "wrc.h"
|
#include "wrc.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "preproc.h"
|
||||||
|
|
||||||
#define WANT_NEAR_INDICATION
|
/* #define WANT_NEAR_INDICATION */
|
||||||
|
|
||||||
|
|
||||||
#ifdef WANT_NEAR_INDICATION
|
#ifdef WANT_NEAR_INDICATION
|
||||||
|
@ -33,22 +34,31 @@ void make_print(char *str)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s %s: %d, %d: ", t, input_name ? input_name : "stdin", line_number, char_number);
|
||||||
|
vfprintf(stderr, s, ap);
|
||||||
|
#ifdef WANT_NEAR_INDICATION
|
||||||
|
{
|
||||||
|
char *cpy;
|
||||||
|
if(n)
|
||||||
|
{
|
||||||
|
cpy = xstrdup(n);
|
||||||
|
make_print(cpy);
|
||||||
|
fprintf(stderr, " near '%s'", cpy);
|
||||||
|
free(cpy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int yyerror(const char *s, ...)
|
int yyerror(const char *s, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, s);
|
va_start(ap, s);
|
||||||
fprintf(stderr, "Error %s: %d, %d: ", input_name ? input_name : "stdin", line_number, char_number);
|
generic_msg(s, "Error", yytext, ap);
|
||||||
vfprintf(stderr, s, ap);
|
|
||||||
#ifdef WANT_NEAR_INDICATION
|
|
||||||
{
|
|
||||||
char *cpy = xstrdup(yytext);
|
|
||||||
make_print(cpy);
|
|
||||||
fprintf(stderr, " near '%s'\n", cpy);
|
|
||||||
free(cpy);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
#endif
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
exit(1);
|
exit(1);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -58,22 +68,31 @@ int yywarning(const char *s, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, s);
|
va_start(ap, s);
|
||||||
fprintf(stderr, "Warning %s: %d, %d: ", input_name ? input_name : "stdin", line_number, char_number);
|
generic_msg(s, "Warning", yytext, ap);
|
||||||
vfprintf(stderr, s, ap);
|
|
||||||
#ifdef WANT_NEAR_INDICATION
|
|
||||||
{
|
|
||||||
char *cpy = xstrdup(yytext);
|
|
||||||
make_print(cpy);
|
|
||||||
fprintf(stderr, " near '%s'\n", cpy);
|
|
||||||
free(cpy);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
#endif
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pperror(const char *s, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, s);
|
||||||
|
generic_msg(s, "Error", pptext, ap);
|
||||||
|
va_end(ap);
|
||||||
|
exit(1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ppwarning(const char *s, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, s);
|
||||||
|
generic_msg(s, "Warning", pptext, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void internal_error(const char *file, int line, const char *s, ...)
|
void internal_error(const char *file, int line, const char *s, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -156,6 +175,11 @@ void *xmalloc(size_t size)
|
||||||
{
|
{
|
||||||
error("Virtual memory exhausted.\n");
|
error("Virtual memory exhausted.\n");
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* We set it to 0.
|
||||||
|
* This is *paramount* because we depend on it
|
||||||
|
* just about everywhere in the rest of the code.
|
||||||
|
*/
|
||||||
memset(res, 0, size);
|
memset(res, 0, size);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +201,10 @@ void *xrealloc(void *p, size_t size)
|
||||||
|
|
||||||
char *xstrdup(const char *str)
|
char *xstrdup(const char *str)
|
||||||
{
|
{
|
||||||
char *s = (char *)xmalloc(strlen(str)+1);
|
char *s;
|
||||||
|
|
||||||
|
assert(str != NULL);
|
||||||
|
s = (char *)xmalloc(strlen(str)+1);
|
||||||
return strcpy(s, str);
|
return strcpy(s, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,14 @@ void *xmalloc(size_t);
|
||||||
void *xrealloc(void *, size_t);
|
void *xrealloc(void *, size_t);
|
||||||
char *xstrdup(const char *str);
|
char *xstrdup(const char *str);
|
||||||
|
|
||||||
int yyerror(const char *s, ...);
|
int pperror(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||||
int yywarning(const char *s, ...);
|
int ppwarning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||||
void internal_error(const char *file, int line, const char *s, ...);
|
int yyerror(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||||
void error(const char *s, ...);
|
int yywarning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||||
void warning(const char *s, ...);
|
void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4)));
|
||||||
void chat(const char *s, ...);
|
void error(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||||
|
void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||||
|
void chat(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||||
|
|
||||||
char *dup_basename(const char *name, const char *ext);
|
char *dup_basename(const char *name, const char *ext);
|
||||||
int string_compare(const string_t *s1, const string_t *s2);
|
int string_compare(const string_t *s1, const string_t *s2);
|
||||||
|
|
206
tools/wrc/wrc.c
206
tools/wrc/wrc.c
|
@ -3,6 +3,7 @@
|
||||||
* Copyright Martin von Loewis, 1994
|
* Copyright Martin von Loewis, 1994
|
||||||
* Copyrignt 1998 Bertho A. Stultiens (BS)
|
* Copyrignt 1998 Bertho A. Stultiens (BS)
|
||||||
*
|
*
|
||||||
|
* 30-Apr-2000 BS - Integrated a new preprocessor (-E and -N)
|
||||||
* 20-Jun-1998 BS - Added -L option to prevent case conversion
|
* 20-Jun-1998 BS - Added -L option to prevent case conversion
|
||||||
* of embedded filenames.
|
* of embedded filenames.
|
||||||
*
|
*
|
||||||
|
@ -36,9 +37,11 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include "wrc.h"
|
#include "wrc.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -59,13 +62,15 @@ char usage[] = "Usage: wrc [options...] [infile[.rc|.res]]\n"
|
||||||
" -d n Set debug level to 'n'\n"
|
" -d n Set debug level to 'n'\n"
|
||||||
" -D id[=val] Define preprocessor identifier id=val\n"
|
" -D id[=val] Define preprocessor identifier id=val\n"
|
||||||
" -e Disable recognition of win32 keywords in 16bit compile\n"
|
" -e Disable recognition of win32 keywords in 16bit compile\n"
|
||||||
|
" -E Preprocess only\n"
|
||||||
" -g Add symbols to the global c namespace\n"
|
" -g Add symbols to the global c namespace\n"
|
||||||
" -h Also generate a .h file\n"
|
" -h Also generate a .h file\n"
|
||||||
" -H file Same as -h but written to file\n"
|
" -H file Same as -h but written to file\n"
|
||||||
" -I path Set include search dir to path (multiple -I allowed)\n"
|
" -I path Set include search dir to path (multiple -I allowed)\n"
|
||||||
" -l lan Set default language to lan (default is neutral {0})\n"
|
" -l lan Set default language to lan (default is neutral {0, 0})\n"
|
||||||
" -L Leave case of embedded filenames as is\n"
|
" -L Leave case of embedded filenames as is\n"
|
||||||
" -n Do not generate .s file\n"
|
" -n Do not generate .s file\n"
|
||||||
|
" -N Do not preprocess input\n"
|
||||||
" -o file Output to file (default is infile.[res|s|h]\n"
|
" -o file Output to file (default is infile.[res|s|h]\n"
|
||||||
" -p prefix Give a prefix for the generated names\n"
|
" -p prefix Give a prefix for the generated names\n"
|
||||||
" -r Create binary .res file (compile only)\n"
|
" -r Create binary .res file (compile only)\n"
|
||||||
|
@ -80,6 +85,9 @@ char usage[] = "Usage: wrc [options...] [infile[.rc|.res]]\n"
|
||||||
" * 0x01 Tell which resource is parsed (verbose mode)\n"
|
" * 0x01 Tell which resource is parsed (verbose mode)\n"
|
||||||
" * 0x02 Dump internal structures\n"
|
" * 0x02 Dump internal structures\n"
|
||||||
" * 0x04 Create a parser trace (yydebug=1)\n"
|
" * 0x04 Create a parser trace (yydebug=1)\n"
|
||||||
|
" * 0x08 Preprocessor messages\n"
|
||||||
|
" * 0x10 Preprocessor lex messages\n"
|
||||||
|
" * 0x20 Preprocessor yacc trace\n"
|
||||||
"The -o option only applies to the final destination file, which is\n"
|
"The -o option only applies to the final destination file, which is\n"
|
||||||
"in case of normal compile a .s file. You must use the '-H header.h'\n"
|
"in case of normal compile a .s file. You must use the '-H header.h'\n"
|
||||||
"option to override the header-filename.\n"
|
"option to override the header-filename.\n"
|
||||||
|
@ -88,7 +96,7 @@ char usage[] = "Usage: wrc [options...] [infile[.rc|.res]]\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
char version_string[] = "Wine Resource Compiler Version " WRC_FULLVERSION "\n"
|
char version_string[] = "Wine Resource Compiler Version " WRC_FULLVERSION "\n"
|
||||||
"Copyright 1998,1999 Bertho A. Stultiens\n"
|
"Copyright 1998-2000 Bertho A. Stultiens\n"
|
||||||
" 1994 Martin von Loewis\n";
|
" 1994 Martin von Loewis\n";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -121,6 +129,9 @@ int create_res = 0;
|
||||||
* debuglevel & DEBUGLEVEL_CHAT Say whats done
|
* debuglevel & DEBUGLEVEL_CHAT Say whats done
|
||||||
* debuglevel & DEBUGLEVEL_DUMP Dump internal structures
|
* debuglevel & DEBUGLEVEL_DUMP Dump internal structures
|
||||||
* debuglevel & DEBUGLEVEL_TRACE Create parser trace
|
* debuglevel & DEBUGLEVEL_TRACE Create parser trace
|
||||||
|
* debuglevel & DEBUGLEVEL_PPMSG Preprocessor messages
|
||||||
|
* debuglevel & DEBUGLEVEL_PPLEX Preprocessor lex trace
|
||||||
|
* debuglevel & DEBUGLEVEL_PPTRACE Preprocessor yacc trace
|
||||||
*/
|
*/
|
||||||
int debuglevel = DEBUGLEVEL_NONE;
|
int debuglevel = DEBUGLEVEL_NONE;
|
||||||
|
|
||||||
|
@ -198,15 +209,32 @@ int auto_register = 0;
|
||||||
*/
|
*/
|
||||||
int leave_case = 0;
|
int leave_case = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set when _only_ to run the preprocessor (-E option)
|
||||||
|
*/
|
||||||
|
int preprocess_only = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set when _not_ to run the preprocessor (-N option)
|
||||||
|
*/
|
||||||
|
int no_preprocess = 0;
|
||||||
|
|
||||||
char *output_name; /* The name given by the -o option */
|
char *output_name; /* The name given by the -o option */
|
||||||
char *input_name; /* The name given on the command-line */
|
char *input_name; /* The name given on the command-line */
|
||||||
char *header_name; /* The name given by the -H option */
|
char *header_name; /* The name given by the -H option */
|
||||||
|
char *temp_name; /* Temporary file for preprocess pipe */
|
||||||
|
|
||||||
|
int line_number = 1; /* The current line */
|
||||||
|
int char_number = 1; /* The current char pos within the line */
|
||||||
|
|
||||||
char *cmdline; /* The entire commandline */
|
char *cmdline; /* The entire commandline */
|
||||||
|
time_t now; /* The time of start of wrc */
|
||||||
|
|
||||||
resource_t *resource_top; /* The top of the parsed resources */
|
resource_t *resource_top; /* The top of the parsed resources */
|
||||||
|
|
||||||
int getopt (int argc, char *const *argv, const char *optstring);
|
int getopt (int argc, char *const *argv, const char *optstring);
|
||||||
|
static void rm_tempfile(void);
|
||||||
|
static void segvhandler(int sig);
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
int main(int argc,char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -219,6 +247,10 @@ int main(int argc,char *argv[])
|
||||||
int i;
|
int i;
|
||||||
int cmdlen;
|
int cmdlen;
|
||||||
|
|
||||||
|
signal(SIGSEGV, segvhandler);
|
||||||
|
|
||||||
|
now = time(NULL);
|
||||||
|
|
||||||
/* First rebuild the commandline to put in destination */
|
/* First rebuild the commandline to put in destination */
|
||||||
/* Could be done through env[], but not all OS-es support it */
|
/* Could be done through env[], but not all OS-es support it */
|
||||||
cmdlen = 4; /* for "wrc " */
|
cmdlen = 4; /* for "wrc " */
|
||||||
|
@ -233,7 +265,7 @@ int main(int argc,char *argv[])
|
||||||
strcat(cmdline, " ");
|
strcat(cmdline, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
while((optc = getopt(argc, argv, "a:AbcC:d:D:eghH:I:l:Lno:p:rstTVw:W")) != EOF)
|
while((optc = getopt(argc, argv, "a:AbcC:d:D:eEghH:I:l:LnNo:p:rstTVw:W")) != EOF)
|
||||||
{
|
{
|
||||||
switch(optc)
|
switch(optc)
|
||||||
{
|
{
|
||||||
|
@ -261,6 +293,9 @@ int main(int argc,char *argv[])
|
||||||
case 'e':
|
case 'e':
|
||||||
extensions = 0;
|
extensions = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'E':
|
||||||
|
preprocess_only = 1;
|
||||||
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
global = 1;
|
global = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -286,6 +321,9 @@ int main(int argc,char *argv[])
|
||||||
case 'n':
|
case 'n':
|
||||||
create_s = 0;
|
create_s = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'N':
|
||||||
|
no_preprocess = 1;
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
output_name = strdup(optarg);
|
output_name = strdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -390,6 +428,62 @@ int main(int argc,char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(preprocess_only)
|
||||||
|
{
|
||||||
|
if(constant)
|
||||||
|
{
|
||||||
|
warning("Option -c ignored with preprocess only\n");
|
||||||
|
constant = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(create_header)
|
||||||
|
{
|
||||||
|
warning("Option -[h|H] ignored with preprocess only\n");
|
||||||
|
create_header = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(indirect)
|
||||||
|
{
|
||||||
|
warning("Option -l ignored with preprocess only\n");
|
||||||
|
indirect = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(indirect_only)
|
||||||
|
{
|
||||||
|
error("Option -E and -L cannot be used together\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(global)
|
||||||
|
{
|
||||||
|
warning("Option -g ignored with preprocess only\n");
|
||||||
|
global = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(create_dir)
|
||||||
|
{
|
||||||
|
warning("Option -s ignored with preprocess only\n");
|
||||||
|
create_dir = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(binary)
|
||||||
|
{
|
||||||
|
error("Option -E and -b cannot be used together\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(no_preprocess)
|
||||||
|
{
|
||||||
|
error("Option -E and -N cannot be used together\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(HAVE_WINE_CONSTRUCTOR)
|
||||||
|
if(auto_register)
|
||||||
|
{
|
||||||
|
warning("Autoregister code non-operable (HAVE_WINE_CONSTRUCTOR not defined)");
|
||||||
|
auto_register = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set alignment power */
|
/* Set alignment power */
|
||||||
a = alignment;
|
a = alignment;
|
||||||
for(alignment_pwr = 0; alignment_pwr < 10 && a > 1; alignment_pwr++)
|
for(alignment_pwr = 0; alignment_pwr < 10 && a > 1; alignment_pwr++)
|
||||||
|
@ -413,16 +507,29 @@ int main(int argc,char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
yydebug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
|
yydebug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
|
||||||
|
yy_flex_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
|
||||||
|
ppdebug = debuglevel & DEBUGLEVEL_PPTRACE ? 1 : 0;
|
||||||
|
pp_flex_debug = debuglevel & DEBUGLEVEL_PPLEX ? 1 : 0;
|
||||||
|
|
||||||
/* Set the default defined stuff */
|
/* Set the default defined stuff */
|
||||||
|
add_cmdline_define("__WRC__=" WRC_STRINGIZE(WRC_MAJOR_VERSION));
|
||||||
|
add_cmdline_define("__WRC_MINOR__=" WRC_STRINGIZE(WRC_MINOR_VERSION));
|
||||||
|
add_cmdline_define("__WRC_MICRO__=" WRC_STRINGIZE(WRC_MICRO_VERSION));
|
||||||
|
add_cmdline_define("__WRC_PATCH__=" WRC_STRINGIZE(WRC_MICRO_VERSION));
|
||||||
|
|
||||||
add_cmdline_define("RC_INVOKED=1");
|
add_cmdline_define("RC_INVOKED=1");
|
||||||
add_cmdline_define("__WRC__=1");
|
|
||||||
if(win32)
|
if(win32)
|
||||||
{
|
{
|
||||||
add_cmdline_define("__WIN32__=1");
|
add_cmdline_define("__WIN32__=1");
|
||||||
add_cmdline_define("__FLAT__=1");
|
add_cmdline_define("__FLAT__=1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_special_define("__FILE__");
|
||||||
|
add_special_define("__LINE__");
|
||||||
|
add_special_define("__DATE__");
|
||||||
|
add_special_define("__TIME__");
|
||||||
|
|
||||||
/* Check if the user set a language, else set default */
|
/* Check if the user set a language, else set default */
|
||||||
if(!currentlanguage)
|
if(!currentlanguage)
|
||||||
currentlanguage = new_language(0, 0);
|
currentlanguage = new_language(0, 0);
|
||||||
|
@ -431,23 +538,15 @@ int main(int argc,char *argv[])
|
||||||
if(optind < argc)
|
if(optind < argc)
|
||||||
{
|
{
|
||||||
input_name = argv[optind];
|
input_name = argv[optind];
|
||||||
yyin = fopen(input_name, "rb");
|
|
||||||
if(!yyin)
|
|
||||||
{
|
|
||||||
error("Could not open %s\n", input_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
yyin = stdin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(binary && !input_name)
|
if(binary && !input_name)
|
||||||
{
|
{
|
||||||
error("Binary mode requires .res file as input");
|
error("Binary mode requires .res file as input\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!output_name)
|
/* Generate appropriate outfile names */
|
||||||
|
if(!output_name && !preprocess_only)
|
||||||
{
|
{
|
||||||
output_name = dup_basename(input_name, binary ? ".res" : ".rc");
|
output_name = dup_basename(input_name, binary ? ".res" : ".rc");
|
||||||
strcat(output_name, create_res ? ".res" : ".s");
|
strcat(output_name, create_res ? ".res" : ".s");
|
||||||
|
@ -459,10 +558,75 @@ int main(int argc,char *argv[])
|
||||||
strcat(header_name, ".h");
|
strcat(header_name, ".h");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Run the preprocessor on the input */
|
||||||
|
if(!no_preprocess && !binary)
|
||||||
|
{
|
||||||
|
char *real_name;
|
||||||
|
/*
|
||||||
|
* Preprocess the input to a temp-file, or stdout if
|
||||||
|
* no output was given.
|
||||||
|
*/
|
||||||
|
|
||||||
|
chat("Starting preprocess");
|
||||||
|
|
||||||
|
if(preprocess_only && !output_name)
|
||||||
|
{
|
||||||
|
ppout = stdout;
|
||||||
|
}
|
||||||
|
else if(preprocess_only && output_name)
|
||||||
|
{
|
||||||
|
if(!(ppout = fopen(output_name, "wb")))
|
||||||
|
error("Could not open %s for writing\n", output_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!(temp_name = tmpnam(NULL)))
|
||||||
|
error("Could nor generate a temp-name\n");
|
||||||
|
temp_name = xstrdup(temp_name);
|
||||||
|
if(!(ppout = fopen(temp_name, "wb")))
|
||||||
|
error("Could not create a temp-file\n");
|
||||||
|
|
||||||
|
atexit(rm_tempfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
real_name = input_name; /* Because it gets overwritten */
|
||||||
|
|
||||||
|
if(!input_name)
|
||||||
|
ppin = stdin;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!(ppin = fopen(input_name, "rb")))
|
||||||
|
error("Could not open %s\n", input_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(ppout, "# 1 \"%s\" 1\n", input_name ? input_name : "");
|
||||||
|
|
||||||
|
ret = ppparse();
|
||||||
|
|
||||||
|
input_name = real_name;
|
||||||
|
|
||||||
|
if(input_name)
|
||||||
|
fclose(ppin);
|
||||||
|
|
||||||
|
fclose(ppout);
|
||||||
|
|
||||||
|
input_name = temp_name;
|
||||||
|
|
||||||
|
if(ret)
|
||||||
|
exit(1); /* Error during preprocess */
|
||||||
|
|
||||||
|
if(preprocess_only)
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if(!binary)
|
if(!binary)
|
||||||
{
|
{
|
||||||
/* Go from .rc to .res or .s */
|
/* Go from .rc to .res or .s */
|
||||||
chat("Starting parse");
|
chat("Starting parse");
|
||||||
|
|
||||||
|
if(!(yyin = fopen(input_name, "rb")))
|
||||||
|
error("Could not open %s for input\n", input_name);
|
||||||
|
|
||||||
ret = yyparse();
|
ret = yyparse();
|
||||||
|
|
||||||
if(input_name)
|
if(input_name)
|
||||||
|
@ -521,5 +685,17 @@ int main(int argc,char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void rm_tempfile(void)
|
||||||
|
{
|
||||||
|
if(temp_name)
|
||||||
|
unlink(temp_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void segvhandler(int sig)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,17 @@
|
||||||
#include "wrctypes.h"
|
#include "wrctypes.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WRC_VERSION "1.0.18"
|
#include <time.h> /* For time_t */
|
||||||
#define WRC_RELEASEDATE "(28-Dec-1999)"
|
|
||||||
#define WRC_FULLVERSION WRC_VERSION " " WRC_RELEASEDATE
|
#define WRC_MAJOR_VERSION 1
|
||||||
|
#define WRC_MINOR_VERSION 1
|
||||||
|
#define WRC_MICRO_VERSION 0
|
||||||
|
#define WRC_RELEASEDATE "(01-May-2000)"
|
||||||
|
|
||||||
|
#define WRC_STRINGIZE(a) #a
|
||||||
|
#define WRC_VERSIONIZE(a,b,c) WRC_STRINGIZE(a) "." WRC_STRINGIZE(b) "." WRC_STRINGIZE(c)
|
||||||
|
#define WRC_VERSION WRC_VERSIONIZE(WRC_MAJOR_VERSION, WRC_MINOR_VERSION, WRC_MICRO_VERSION)
|
||||||
|
#define WRC_FULLVERSION WRC_VERSION " " WRC_RELEASEDATE
|
||||||
|
|
||||||
/* Only used in heavy debugging sessions */
|
/* Only used in heavy debugging sessions */
|
||||||
#define HEAPCHECK()
|
#define HEAPCHECK()
|
||||||
|
@ -25,6 +33,9 @@ extern int debuglevel;
|
||||||
#define DEBUGLEVEL_CHAT 0x0001
|
#define DEBUGLEVEL_CHAT 0x0001
|
||||||
#define DEBUGLEVEL_DUMP 0x0002
|
#define DEBUGLEVEL_DUMP 0x0002
|
||||||
#define DEBUGLEVEL_TRACE 0x0004
|
#define DEBUGLEVEL_TRACE 0x0004
|
||||||
|
#define DEBUGLEVEL_PPMSG 0x0008
|
||||||
|
#define DEBUGLEVEL_PPLEX 0x0010
|
||||||
|
#define DEBUGLEVEL_PPTRACE 0x0020
|
||||||
|
|
||||||
extern int win32;
|
extern int win32;
|
||||||
extern int constant;
|
extern int constant;
|
||||||
|
@ -43,12 +54,18 @@ extern DWORD codepage;
|
||||||
extern int pedantic;
|
extern int pedantic;
|
||||||
extern int auto_register;
|
extern int auto_register;
|
||||||
extern int leave_case;
|
extern int leave_case;
|
||||||
|
extern int preprocess_only;
|
||||||
|
extern int no_preprocess;
|
||||||
|
|
||||||
extern char *prefix;
|
extern char *prefix;
|
||||||
extern char *output_name;
|
extern char *output_name;
|
||||||
extern char *input_name;
|
extern char *input_name;
|
||||||
extern char *header_name;
|
extern char *header_name;
|
||||||
extern char *cmdline;
|
extern char *cmdline;
|
||||||
|
extern time_t now;
|
||||||
|
|
||||||
|
extern int line_number;
|
||||||
|
extern int char_number;
|
||||||
|
|
||||||
extern resource_t *resource_top;
|
extern resource_t *resource_top;
|
||||||
extern language_t *currentlanguage;
|
extern language_t *currentlanguage;
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "wrc.h"
|
#include "wrc.h"
|
||||||
#include "writeres.h"
|
#include "writeres.h"
|
||||||
|
@ -91,8 +90,6 @@ int n_name_entries = 0; /* win32 only: Nr of unique namess in the type-level ar
|
||||||
|
|
||||||
static int direntries; /* win32 only: Total number of unique resources */
|
static int direntries; /* win32 only: Total number of unique resources */
|
||||||
|
|
||||||
time_t now;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
* Function : write_resfile
|
* Function : write_resfile
|
||||||
|
@ -940,7 +937,6 @@ void write_s_file(char *outname, resource_t *top)
|
||||||
|
|
||||||
{
|
{
|
||||||
char *s, *p;
|
char *s, *p;
|
||||||
now = time(NULL);
|
|
||||||
s = ctime(&now);
|
s = ctime(&now);
|
||||||
p = strchr(s, '\n');
|
p = strchr(s, '\n');
|
||||||
if(p) *p = '\0';
|
if(p) *p = '\0';
|
||||||
|
@ -1127,7 +1123,6 @@ void write_h_file(char *outname, resource_t *top)
|
||||||
error("Could not open %s\n", outname);
|
error("Could not open %s\n", outname);
|
||||||
}
|
}
|
||||||
|
|
||||||
time(&now);
|
|
||||||
fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
|
fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
|
||||||
cmdline, ctime(&now), (long)now, (long)now);
|
cmdline, ctime(&now), (long)now, (long)now);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue