- 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 "comctl32.h"
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "windef.h"
|
||||
#include "winuser.h"
|
||||
#include "winnls.h"
|
||||
#include "cdlg.h"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
1 "OEMBIN"
|
||||
1 OEMBIN
|
||||
{
|
||||
0x11, /* vertical thumb height (in pixels) */
|
||||
0x11, /* horizontal thumb width (in pixels) */
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "windef.h"
|
||||
#include "winuser.h"
|
||||
#include "winnls.h"
|
||||
#include "shlobj.h"
|
||||
|
|
|
@ -25,10 +25,6 @@ all: check_wrc $(PROGRAMS)
|
|||
|
||||
@MAKE_RULES@
|
||||
|
||||
# Override resource compiler rules
|
||||
.rc.s:
|
||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
||||
|
||||
|
||||
clock: $(OBJS)
|
||||
$(CC) -o clock $(OBJS) $(DLL_LINK) $(LIBS)
|
||||
|
|
|
@ -26,10 +26,6 @@ all: check_wrc $(PROGRAMS)
|
|||
|
||||
@MAKE_RULES@
|
||||
|
||||
# Override resource compiler rules
|
||||
.rc.s:
|
||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
||||
|
||||
notepad: $(OBJS)
|
||||
$(CC) -o notepad $(OBJS) $(DLL_LINK) $(LIBS)
|
||||
|
||||
|
|
|
@ -28,10 +28,6 @@ all: check_wrc $(PROGRAMS)
|
|||
|
||||
@MAKE_RULES@
|
||||
|
||||
# Override resource compiler rules
|
||||
.rc.s:
|
||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
||||
|
||||
progman: $(OBJS)
|
||||
$(CC) -o progman $(OBJS) $(DLL_LINK) $(LIBS)
|
||||
|
||||
|
|
|
@ -22,10 +22,6 @@ all: check_wrc $(PROGRAMS)
|
|||
|
||||
@MAKE_RULES@
|
||||
|
||||
# Override resource compiler rules
|
||||
.rc.s:
|
||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
||||
|
||||
winemine: $(OBJS)
|
||||
$(CC) -o winemine $(OBJS) $(DLL_LINK) $(LIBS)
|
||||
|
||||
|
|
|
@ -27,10 +27,6 @@ depend: y.tab.h
|
|||
|
||||
@MAKE_RULES@
|
||||
|
||||
# Override resource compiler rules
|
||||
.rc.s:
|
||||
$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P -x c $< | $(WRC) $(WRCFLAGS) $(WRCEXTRA) -o $*.s
|
||||
|
||||
winhelp: $(OBJS)
|
||||
$(CC) -o winhelp $(OBJS) $(DLL_LINK) $(LIBS)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "windef.h"
|
||||
#include "winuser.h"
|
||||
#include "winnls.h"
|
||||
#include "dlgs.h"
|
||||
|
|
|
@ -19,7 +19,7 @@ EXTRASUBDIRS = \
|
|||
winapi_check/win32 \
|
||||
wineconf.libs
|
||||
|
||||
all: $(PROGRAMS)
|
||||
all: $(PROGRAMS) wrc
|
||||
|
||||
@MAKE_RULES@
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
Makefile
|
||||
lex.ppl.c
|
||||
lex.yy.c
|
||||
ppy.tab.c
|
||||
ppy.tab.h
|
||||
wrc
|
||||
y.tab.c
|
||||
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)
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ TOPSRCDIR = @top_srcdir@
|
|||
TOPOBJDIR = ../..
|
||||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
LEXOPT = -Cf #-w -b
|
||||
YACCOPT = #-v
|
||||
|
||||
PROGRAMS = wrc@PROGEXT@
|
||||
MODULE = none
|
||||
|
@ -17,12 +19,12 @@ C_SRCS = \
|
|||
wrc.c \
|
||||
writeres.c
|
||||
|
||||
EXTRA_SRCS = parser.y parser.l
|
||||
EXTRA_OBJS = y.tab.o lex.yy.o
|
||||
EXTRA_SRCS = parser.y parser.l ppl.l ppy.y ppy.tab.c lex.ppl.c
|
||||
EXTRA_OBJS = y.tab.o lex.yy.o ppy.tab.o lex.ppl.o
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
depend: y.tab.h
|
||||
depend: y.tab.h ppy.tab.h ppy.tab.c lex.ppl.c
|
||||
|
||||
@MAKE_RULES@
|
||||
|
||||
|
@ -30,12 +32,18 @@ wrc@PROGEXT@: $(OBJS)
|
|||
$(CC) $(CFLAGS) -o wrc@PROGEXT@ $(OBJS) $(LEXLIB)
|
||||
|
||||
y.tab.c y.tab.h: parser.y
|
||||
$(YACC) -d -t $(SRCDIR)/parser.y
|
||||
$(YACC) $(YACCOPT) -d -t $(SRCDIR)/parser.y
|
||||
|
||||
ppy.tab.c ppy.tab.h: ppy.y
|
||||
$(YACC) $(YACCOPT) -bppy -ppp -d -t $(SRCDIR)/ppy.y
|
||||
|
||||
lex.yy.c: parser.l
|
||||
$(LEX) -8 $(SRCDIR)/parser.l
|
||||
$(LEX) $(LEXOPT) -d -8 $(SRCDIR)/parser.l
|
||||
|
||||
lex.ppl.c: ppl.l
|
||||
$(LEX) $(LEXOPT) -d -Ppp -8 -olex.ppl.c $(SRCDIR)/ppl.l
|
||||
|
||||
clean::
|
||||
$(RM) y.tab.c y.tab.h lex.yy.c
|
||||
$(RM) y.tab.c y.tab.h lex.yy.c ppy.tab.c ppy.tab.h lex.ppl.c ppy.output lex.backup y.output
|
||||
|
||||
### Dependencies:
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
Release 1.0.2 of wrc (20-Jun-1998), the wine resource compiler.
|
||||
Release 1.1.0 of wrc (01-May-2000), the wine resource compiler.
|
||||
|
||||
See the file CHANGES for differences between the version and what has been
|
||||
corrected in the current version.
|
||||
|
||||
Wrc features:
|
||||
|
||||
- source preprocessing
|
||||
- full source preprocessing
|
||||
- 16 and 32 bit support
|
||||
- LANGUAGE support (32 bit only)
|
||||
- almost all resource types are supported
|
||||
- most resource types are supported
|
||||
- enhanced expression capabilities and resource naming
|
||||
- indirect loadable resources
|
||||
- NE/PE resource directory generation
|
||||
|
@ -34,13 +34,15 @@ Usage: wrc [options...] [infile[.rc|.res]]
|
|||
-d n Set debug level to 'n'
|
||||
-D id[=val] Define preprocessor identifier id=val
|
||||
-e Disable recognition of win32 keywords in 16bit compile
|
||||
-E Preprocess only
|
||||
-g Add symbols to the global c namespace
|
||||
-h Also generate a .h file
|
||||
-H file Same as -h but written to file
|
||||
-I path Set include search dir to path (multiple -I allowed)
|
||||
-l lan Set default language to lan (default is neutral {0})
|
||||
-l lan Set default language to lan (default is neutral {0, 0})
|
||||
-L Leave case of embedded filenames as is
|
||||
-n Do not generate .s file
|
||||
-N Do not preprocess input
|
||||
-o file Output to file (default is infile.[res|s|h]
|
||||
-p prefix Give a prefix for the generated names
|
||||
-r Create binary .res file (compile only)
|
||||
|
@ -57,6 +59,9 @@ Debug level 'n' is a bitmask with following meaning:
|
|||
* 0x01 Tell which resource is parsed (verbose mode)
|
||||
* 0x02 Dump internal structures
|
||||
* 0x04 Create a parser trace (yydebug=1)
|
||||
* 0x08 Preprocessor messages
|
||||
* 0x10 Preprocessor lex messages
|
||||
* 0x20 Preprocessor yacc trace
|
||||
|
||||
The -o option only applies to the final destination file, which is
|
||||
in case of normal compile a .s file. You must use the '-H header.h'
|
||||
|
@ -67,10 +72,12 @@ with -o and/or -H, then the output is written to "wrc.tab.[sh]"
|
|||
|
||||
Preprocessing
|
||||
-------------
|
||||
The build-in preprocessor is not a full implementation of the C counterpart.
|
||||
Wrc does not understand function-type macros. These are discarded as they
|
||||
are scanned. This will be a future project. Wrc does understand these:
|
||||
#define
|
||||
The preprocessor is a fully operational C preprocessor. It handles all
|
||||
directives supported by ANSI-C. It also includes some additions from
|
||||
gcc/egcs.
|
||||
Wrc understands these directives:
|
||||
#define (both simple and macro)
|
||||
#undef
|
||||
#if
|
||||
#ifdef
|
||||
#ifndef
|
||||
|
@ -78,13 +85,42 @@ are scanned. This will be a future project. Wrc does understand these:
|
|||
#else
|
||||
#endif
|
||||
#error
|
||||
#warning
|
||||
#line
|
||||
#
|
||||
#pragma (ignored)
|
||||
#ident (ignored)
|
||||
|
||||
Also 'defined' is supported as operator (both with and without parenthesis).
|
||||
'#if' expressions can be anything valid that evaluates to an integer
|
||||
expression (where 0 is false and anything else is true). Others (#pragma,
|
||||
#line) are ignored. A special case '#' generates an error. This is due to
|
||||
the implementation to enable generation of errors on preprocessing and will
|
||||
be improved in the future.
|
||||
The extensions include '#'-line directives.
|
||||
Not handled at the moment are variable argument macros. They are parsed,
|
||||
but not expanded properly. This will be corrected in the future.
|
||||
|
||||
The preprocessor handles the special defines and aditionally defines an
|
||||
extra set of defines:
|
||||
Define | Value | Comment
|
||||
-----------+-------------------+---------------
|
||||
RC_INVOKED | 1 | Always defined
|
||||
__FLAT__ | 1 | Only defined if win32 compile
|
||||
__WIN32__ | 1 | Only defined if win32 compile
|
||||
__FILE__ | "..." | Current filename as string
|
||||
__LINE__ | nnn | Current linenumber as integer
|
||||
__TIME__ | "23:59:59" | Timestring of compilation
|
||||
__DATE__ | "May 1 2000" | Datestring of compilation
|
||||
__WRC__ 1 | Wrc's major version
|
||||
__WRC_MINOR__ | 1 | Wrc's minor version
|
||||
__WRC_MICRO__ | 0 | Wrc's minor version
|
||||
__WRC_PATCH__ | 0 | Alias of __WRC_MICRO__
|
||||
|
||||
Include-files are not read twice if they are protected with this scheme:
|
||||
#ifndef SOME_DEFINE
|
||||
#define SOME_DEFINE
|
||||
...
|
||||
#endif
|
||||
This strategy has been borrowed from gcc/egcs and results in significantly
|
||||
reduced preprocessing times (20..30%). There must not be any junk before
|
||||
the first #ifndef and not after the last #endif; comments and whitespace
|
||||
excepted. Wrc will check the existance of the define prior to inclusion to
|
||||
detect "#undef SOME_DEFINE" (notably poppack.h) and act accordingly.
|
||||
|
||||
|
||||
16 and 32 bit support
|
||||
|
@ -115,35 +151,15 @@ statement before (and evt. after) the code in the resource file.
|
|||
Resource types supported
|
||||
------------------------
|
||||
All types are supported except for:
|
||||
- FONT
|
||||
- MESSAGETABLE
|
||||
- extensions like TOOLBAR and the like (is this a user-type?)
|
||||
- FONT (RT_FONT, RT_FONTDIR)
|
||||
- MESSAGETABLE (RT_MESSAGETABLE)
|
||||
- Animated cursors/icons (RT_ANIICON, RT_ANICURSOR)
|
||||
- RT_VXD
|
||||
- RT_PLUGPLAY
|
||||
|
||||
These types will be implemented as soon as I get a proper specification of
|
||||
the layout.
|
||||
|
||||
Note: Usertype resources with character strings as types have a different
|
||||
layout and do not accept expressions when a numerical type is specified. The
|
||||
must be enclosed in double quotes. These are examples of valid usertype
|
||||
resources:
|
||||
|
||||
MyName "MyType" mydata.bin
|
||||
MyName 12345 mydata.bin
|
||||
MyName "MyType" "mydata.bin"
|
||||
MyName 12345 "mydata.bin"
|
||||
|
||||
MyName "MyType"
|
||||
{
|
||||
..., data, ...
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
MyName 12345
|
||||
{
|
||||
..., data, ...
|
||||
}
|
||||
|
||||
|
||||
Expression capabilities and resource names
|
||||
------------------------------------------
|
||||
|
@ -152,22 +168,19 @@ expects a number (except usertype type). Operators supported:
|
|||
() parenthesis
|
||||
* multiply
|
||||
/ divide
|
||||
+ add
|
||||
+ plus/add
|
||||
- minus/substract
|
||||
| binary or
|
||||
& binary and
|
||||
~ binary not (unary operator though)
|
||||
NOT ... (sigh)
|
||||
|
||||
Minus (-) can both be unary and binary. The NOT operator is (primarily)
|
||||
used to disable window styles but I strongly suggest to refrain from using
|
||||
this operator.
|
||||
There is a shift/reduce conflict on the unary minus, but this is not
|
||||
problematic. I was too lazy to make a new expression parser (next version or
|
||||
so). Unary plus (+) would cause another confilct, so I let it out for now.
|
||||
Plus (+) and minus (-) can both be unary and binary. The NOT operator is
|
||||
(primarily) used to disable window styles but I strongly suggest to refrain
|
||||
from using this operator.
|
||||
|
||||
Resource names can be both numerical (expressions) and character typed. Wrc
|
||||
does supports this insane (deep sigh) construct:
|
||||
does support this insane (deep sigh) construct:
|
||||
|
||||
MENU MENU
|
||||
{
|
||||
|
@ -250,9 +263,8 @@ though):
|
|||
- No documentation ('wrc -?' gives command-line options though)
|
||||
- grep for FIXME in the source
|
||||
- Memory options are wrong under some conditions. There seems to be a
|
||||
different action for win32 and win16.
|
||||
- User-type resources have slightly different layout.
|
||||
- Filename scanning is still hopeless.
|
||||
different action for win32 and win16
|
||||
- Little/big-endian
|
||||
|
||||
Reporting bugs and patches
|
||||
--------------------------
|
||||
|
|
|
@ -293,3 +293,4 @@ style_t *new_style(DWORD or_mask, DWORD and_mask)
|
|||
st->and_mask = and_mask;
|
||||
return st;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
|
||||
/* From parser.y */
|
||||
extern int yydebug;
|
||||
extern int indialog; /* Set when parsing dialogs */
|
||||
extern int want_rscname; /* Set when a resource's name is required */
|
||||
extern int want_nl; /* Set when getting line-numers */
|
||||
|
||||
int yyparse(void);
|
||||
void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico);
|
||||
|
@ -19,15 +18,10 @@ void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur);
|
|||
/* From parser.l */
|
||||
extern FILE *yyin;
|
||||
extern char *yytext;
|
||||
extern int line_number;
|
||||
extern int char_number;
|
||||
extern int yy_flex_debug;
|
||||
|
||||
int yylex(void);
|
||||
void set_yywf(void);
|
||||
void set_pp_ignore(int state);
|
||||
void push_to(int start);
|
||||
void pop_start(void);
|
||||
void strip_extern(void);
|
||||
void strip_til_semicolon(void);
|
||||
void strip_til_parenthesis(void);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "wrc.h"
|
||||
#include "utils.h"
|
||||
#include "preproc.h"
|
||||
#include "parser.h"
|
||||
|
||||
|
||||
extern void set_pp_ignore(int); /* From parser.l */
|
||||
|
||||
static char *current_define;
|
||||
|
||||
#define HASHKEY 2039
|
||||
static struct pp_entry *pp_defines[HASHKEY];
|
||||
static pp_entry_t *pp_defines[HASHKEY];
|
||||
|
||||
#define MAXIFSTACK 64
|
||||
static struct if_state ifstack[MAXIFSTACK];
|
||||
static int ifstackidx = 0;
|
||||
static if_state_t if_stack[MAXIFSTACK];
|
||||
static int if_stack_idx = 0;
|
||||
|
||||
#if 0
|
||||
void pp_status(void) __attribute__((destructor));
|
||||
void pp_status(void)
|
||||
{
|
||||
int i;
|
||||
int sum;
|
||||
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++)
|
||||
{
|
||||
sum = 0;
|
||||
for(ppp = pp_defines[i]; ppp; ppp = ppp->next)
|
||||
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
|
||||
|
||||
/* Don't comment on the hash, its primitive but functional... */
|
||||
int pp_hash(char *str)
|
||||
int pphash(char *str)
|
||||
{
|
||||
int sum = 0;
|
||||
while(*str)
|
||||
|
@ -57,11 +55,12 @@ int pp_hash(char *str)
|
|||
return sum % HASHKEY;
|
||||
}
|
||||
|
||||
struct pp_entry *pp_lookup(char *ident)
|
||||
pp_entry_t *pplookup(char *ident)
|
||||
{
|
||||
int index = pp_hash(ident);
|
||||
struct pp_entry *ppp;
|
||||
for(ppp = pp_defines[index]; ppp; ppp = ppp->next)
|
||||
int idx = pphash(ident);
|
||||
pp_entry_t *ppp;
|
||||
|
||||
for(ppp = pp_defines[idx]; ppp; ppp = ppp->next)
|
||||
{
|
||||
if(!strcmp(ident, ppp->ident))
|
||||
return ppp;
|
||||
|
@ -69,29 +68,44 @@ struct pp_entry *pp_lookup(char *ident)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void set_define(char *name)
|
||||
{
|
||||
current_define = xstrdup(name);
|
||||
}
|
||||
|
||||
void del_define(char *name)
|
||||
{
|
||||
int index;
|
||||
struct pp_entry *ppp;
|
||||
int idx;
|
||||
pp_entry_t *ppp;
|
||||
|
||||
if((ppp = pp_lookup(name)) == NULL)
|
||||
if((ppp = pplookup(name)) == NULL)
|
||||
{
|
||||
if(pedantic)
|
||||
yywarning("%s was not defined", name);
|
||||
return;
|
||||
}
|
||||
|
||||
index = pp_hash(name);
|
||||
if(pp_defines[index] == ppp)
|
||||
if(ppp->iep)
|
||||
{
|
||||
pp_defines[index] = ppp->next;
|
||||
if(pp_defines[index])
|
||||
pp_defines[index]->prev = NULL;
|
||||
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||
fprintf(stderr, "del_define: %s:%d: includelogic removed, include_ppp='%s', file=%s\n", input_name, line_number, name, ppp->iep->filename);
|
||||
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
|
||||
{
|
||||
|
@ -99,54 +113,128 @@ void del_define(char *name)
|
|||
if(ppp->next)
|
||||
ppp->next->prev = ppp->prev;
|
||||
}
|
||||
|
||||
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;
|
||||
char *cptr;
|
||||
int index = pp_hash(current_define);
|
||||
struct pp_entry *ppp;
|
||||
if(pp_lookup(current_define) != NULL)
|
||||
int idx = pphash(def);
|
||||
pp_entry_t *ppp;
|
||||
|
||||
if((ppp = pplookup(def)) != NULL)
|
||||
{
|
||||
if(pedantic)
|
||||
yywarning("Redefinition of %s", current_define);
|
||||
del_define(current_define);
|
||||
yywarning("Redefinition of %s\n\tPrevious definition: %s:%d", def, ppp->filename, ppp->linenumber);
|
||||
del_define(def);
|
||||
}
|
||||
ppp = (struct pp_entry *)xmalloc(sizeof(struct pp_entry));
|
||||
ppp->ident = current_define;
|
||||
ppp->subst = xstrdup(text);
|
||||
ppp->next = pp_defines[index];
|
||||
pp_defines[index] = ppp;
|
||||
ppp = (pp_entry_t *)xmalloc(sizeof(pp_entry_t));
|
||||
ppp->ident = def;
|
||||
ppp->type = def_define;
|
||||
ppp->subst.text = text;
|
||||
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;
|
||||
/* Strip trailing white space from subst text */
|
||||
len = strlen(ppp->subst);
|
||||
while(len && strchr(" \t\r\n", ppp->subst[len-1]))
|
||||
if(text)
|
||||
{
|
||||
ppp->subst[--len] = '\0';
|
||||
}
|
||||
/* Strip leading white space from subst text */
|
||||
for(cptr = ppp->subst; *cptr && strchr(" \t\r", *cptr); cptr++)
|
||||
/* Strip trailing white space from subst text */
|
||||
len = strlen(text);
|
||||
while(len && strchr(" \t\r\n", text[len-1]))
|
||||
{
|
||||
text[--len] = '\0';
|
||||
}
|
||||
/* Strip leading white space from subst text */
|
||||
for(cptr = text; *cptr && strchr(" \t\r", *cptr); cptr++)
|
||||
;
|
||||
if(ppp->subst != cptr)
|
||||
memmove(ppp->subst, cptr, strlen(cptr)+1);
|
||||
if(yydebug)
|
||||
printf("Added (%s, %d) <%s> to <%s>\n", input_name, line_number, ppp->ident, ppp->subst);
|
||||
if(text != cptr)
|
||||
memmove(text, cptr, strlen(cptr)+1);
|
||||
}
|
||||
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 *cptr = strchr(cpy, '=');
|
||||
if(cptr)
|
||||
*cptr = '\0';
|
||||
set_define(cpy);
|
||||
add_define(cptr ? cptr+1 : "");
|
||||
free(cpy);
|
||||
return add_define(cpy, xstrdup(cptr ? cptr+1 : ""));
|
||||
}
|
||||
|
||||
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__)
|
||||
#define INCLUDESEPARATOR ";"
|
||||
#else
|
||||
|
@ -188,7 +276,7 @@ void add_include_path(char *path)
|
|||
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 *cptr;
|
||||
|
@ -208,12 +296,15 @@ FILE *open_include(const char *name, int search)
|
|||
if(search)
|
||||
{
|
||||
/* Search current dir and then -I path */
|
||||
fp = fopen(name, "rt");
|
||||
fp = fopen(cpy, "rt");
|
||||
if(fp)
|
||||
{
|
||||
if(yydebug)
|
||||
if(debuglevel & DEBUGLEVEL_PPMSG)
|
||||
printf("Going to include <%s>\n", name);
|
||||
free(cpy);
|
||||
if(newpath)
|
||||
*newpath = cpy;
|
||||
else
|
||||
free(cpy);
|
||||
return fp;
|
||||
}
|
||||
}
|
||||
|
@ -226,57 +317,166 @@ FILE *open_include(const char *name, int search)
|
|||
strcat(path, "/");
|
||||
strcat(path, cpy);
|
||||
fp = fopen(path, "rt");
|
||||
if(fp && yydebug)
|
||||
if(fp && (debuglevel & DEBUGLEVEL_PPMSG))
|
||||
printf("Going to include <%s>\n", path);
|
||||
free(path);
|
||||
if(fp)
|
||||
{
|
||||
if(newpath)
|
||||
*newpath = path;
|
||||
else
|
||||
free(path);
|
||||
free(cpy);
|
||||
return fp;
|
||||
}
|
||||
|
||||
free(path);
|
||||
}
|
||||
free(cpy);
|
||||
if(newpath)
|
||||
*newpath = 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)
|
||||
internal_error(__FILE__, __LINE__, "#if stack overflow");
|
||||
ifstack[ifstackidx].current = truecase && !wastrue;
|
||||
ifstack[ifstackidx].hasbeentrue = wastrue;
|
||||
ifstack[ifstackidx].nevertrue = nevertrue;
|
||||
if(nevertrue || !(truecase && !wastrue))
|
||||
set_pp_ignore(1);
|
||||
if(yydebug)
|
||||
printf("push_if: %d %d %d (%d %d %d)\n",
|
||||
truecase,
|
||||
wastrue,
|
||||
nevertrue,
|
||||
ifstack[ifstackidx].current,
|
||||
ifstack[ifstackidx].hasbeentrue,
|
||||
ifstack[ifstackidx].nevertrue);
|
||||
ifstackidx++;
|
||||
if(if_stack_idx >= MAXIFSTACK)
|
||||
internal_error(__FILE__, __LINE__, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK);
|
||||
|
||||
if(debuglevel & DEBUGLEVEL_PPLEX)
|
||||
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_stack[if_stack_idx++] = s;
|
||||
|
||||
switch(s)
|
||||
{
|
||||
case if_true:
|
||||
case if_elsetrue:
|
||||
break;
|
||||
case if_false:
|
||||
case if_elsefalse:
|
||||
case if_elif:
|
||||
case if_ignore:
|
||||
push_ignore_state();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int pop_if(void)
|
||||
if_state_t pop_if(void)
|
||||
{
|
||||
if(ifstackidx <= 0)
|
||||
yyerror("#endif without #if|#ifdef|#ifndef (#if stack underflow)");
|
||||
ifstackidx--;
|
||||
if(yydebug)
|
||||
printf("pop_if: %d %d %d\n",
|
||||
ifstack[ifstackidx].current,
|
||||
ifstack[ifstackidx].hasbeentrue,
|
||||
ifstack[ifstackidx].nevertrue);
|
||||
if(ifstack[ifstackidx].nevertrue || !ifstack[ifstackidx].current)
|
||||
set_pp_ignore(0);
|
||||
return ifstack[ifstackidx].hasbeentrue || ifstack[ifstackidx].current;
|
||||
if(if_stack_idx <= 0)
|
||||
yyerror("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
|
||||
|
||||
switch(if_state())
|
||||
{
|
||||
case if_true:
|
||||
case if_elsetrue:
|
||||
break;
|
||||
case if_false:
|
||||
case if_elsefalse:
|
||||
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
|
||||
#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 *prev;
|
||||
char *ident;
|
||||
char *subst;
|
||||
int expanding;
|
||||
};
|
||||
def_type_t type; /* Define or macro */
|
||||
char *ident; /* The key */
|
||||
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 add_define(char *text);
|
||||
void add_cmdline_define(char *set);
|
||||
FILE *open_include(const char *name, int search);
|
||||
FILE *open_include(const char *name, int search, char **newpath);
|
||||
void add_include_path(char *path);
|
||||
void push_if(int truecase, int wastrue, int nevertrue);
|
||||
int pop_if(void);
|
||||
int isnevertrue_if(void);
|
||||
void push_if(if_state_t s);
|
||||
void next_if_state(int);
|
||||
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
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
#include "wrc.h"
|
||||
#include "utils.h"
|
||||
#include "parser.h"
|
||||
#include "preproc.h"
|
||||
|
||||
#define WANT_NEAR_INDICATION
|
||||
/* #define WANT_NEAR_INDICATION */
|
||||
|
||||
|
||||
#ifdef WANT_NEAR_INDICATION
|
||||
|
@ -33,22 +34,31 @@ void make_print(char *str)
|
|||
}
|
||||
#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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
fprintf(stderr, "Error %s: %d, %d: ", input_name ? input_name : "stdin", line_number, char_number);
|
||||
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
|
||||
generic_msg(s, "Error", yytext, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
return 1;
|
||||
|
@ -58,22 +68,31 @@ int yywarning(const char *s, ...)
|
|||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
fprintf(stderr, "Warning %s: %d, %d: ", input_name ? input_name : "stdin", line_number, char_number);
|
||||
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
|
||||
generic_msg(s, "Warning", yytext, ap);
|
||||
va_end(ap);
|
||||
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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -156,6 +175,11 @@ void *xmalloc(size_t size)
|
|||
{
|
||||
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);
|
||||
return res;
|
||||
}
|
||||
|
@ -177,7 +201,10 @@ void *xrealloc(void *p, size_t size)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,14 @@ void *xmalloc(size_t);
|
|||
void *xrealloc(void *, size_t);
|
||||
char *xstrdup(const char *str);
|
||||
|
||||
int yyerror(const char *s, ...);
|
||||
int yywarning(const char *s, ...);
|
||||
void internal_error(const char *file, int line, const char *s, ...);
|
||||
void error(const char *s, ...);
|
||||
void warning(const char *s, ...);
|
||||
void chat(const char *s, ...);
|
||||
int pperror(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
int ppwarning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
int yyerror(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
int yywarning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4)));
|
||||
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);
|
||||
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
|
||||
* 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
|
||||
* of embedded filenames.
|
||||
*
|
||||
|
@ -36,9 +37,11 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "wrc.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 id[=val] Define preprocessor identifier id=val\n"
|
||||
" -e Disable recognition of win32 keywords in 16bit compile\n"
|
||||
" -E Preprocess only\n"
|
||||
" -g Add symbols to the global c namespace\n"
|
||||
" -h Also generate a .h file\n"
|
||||
" -H file Same as -h but written to file\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"
|
||||
" -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"
|
||||
" -p prefix Give a prefix for the generated names\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"
|
||||
" * 0x02 Dump internal structures\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"
|
||||
"in case of normal compile a .s file. You must use the '-H header.h'\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"
|
||||
"Copyright 1998,1999 Bertho A. Stultiens\n"
|
||||
"Copyright 1998-2000 Bertho A. Stultiens\n"
|
||||
" 1994 Martin von Loewis\n";
|
||||
|
||||
/*
|
||||
|
@ -121,6 +129,9 @@ int create_res = 0;
|
|||
* debuglevel & DEBUGLEVEL_CHAT Say whats done
|
||||
* debuglevel & DEBUGLEVEL_DUMP Dump internal structures
|
||||
* 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;
|
||||
|
||||
|
@ -198,15 +209,32 @@ int auto_register = 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 *input_name; /* The name given on the command-line */
|
||||
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 */
|
||||
time_t now; /* The time of start of wrc */
|
||||
|
||||
resource_t *resource_top; /* The top of the parsed resources */
|
||||
|
||||
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[])
|
||||
{
|
||||
|
@ -219,6 +247,10 @@ int main(int argc,char *argv[])
|
|||
int i;
|
||||
int cmdlen;
|
||||
|
||||
signal(SIGSEGV, segvhandler);
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
/* First rebuild the commandline to put in destination */
|
||||
/* Could be done through env[], but not all OS-es support it */
|
||||
cmdlen = 4; /* for "wrc " */
|
||||
|
@ -233,7 +265,7 @@ int main(int argc,char *argv[])
|
|||
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)
|
||||
{
|
||||
|
@ -261,6 +293,9 @@ int main(int argc,char *argv[])
|
|||
case 'e':
|
||||
extensions = 0;
|
||||
break;
|
||||
case 'E':
|
||||
preprocess_only = 1;
|
||||
break;
|
||||
case 'g':
|
||||
global = 1;
|
||||
break;
|
||||
|
@ -286,6 +321,9 @@ int main(int argc,char *argv[])
|
|||
case 'n':
|
||||
create_s = 0;
|
||||
break;
|
||||
case 'N':
|
||||
no_preprocess = 1;
|
||||
break;
|
||||
case 'o':
|
||||
output_name = strdup(optarg);
|
||||
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 */
|
||||
a = alignment;
|
||||
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;
|
||||
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 */
|
||||
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("__WRC__=1");
|
||||
|
||||
if(win32)
|
||||
{
|
||||
add_cmdline_define("__WIN32__=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 */
|
||||
if(!currentlanguage)
|
||||
currentlanguage = new_language(0, 0);
|
||||
|
@ -431,23 +538,15 @@ int main(int argc,char *argv[])
|
|||
if(optind < argc)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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");
|
||||
strcat(output_name, create_res ? ".res" : ".s");
|
||||
|
@ -459,10 +558,75 @@ int main(int argc,char *argv[])
|
|||
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)
|
||||
{
|
||||
/* Go from .rc to .res or .s */
|
||||
chat("Starting parse");
|
||||
|
||||
if(!(yyin = fopen(input_name, "rb")))
|
||||
error("Could not open %s for input\n", input_name);
|
||||
|
||||
ret = yyparse();
|
||||
|
||||
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"
|
||||
#endif
|
||||
|
||||
#define WRC_VERSION "1.0.18"
|
||||
#define WRC_RELEASEDATE "(28-Dec-1999)"
|
||||
#define WRC_FULLVERSION WRC_VERSION " " WRC_RELEASEDATE
|
||||
#include <time.h> /* For time_t */
|
||||
|
||||
#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 */
|
||||
#define HEAPCHECK()
|
||||
|
@ -25,6 +33,9 @@ extern int debuglevel;
|
|||
#define DEBUGLEVEL_CHAT 0x0001
|
||||
#define DEBUGLEVEL_DUMP 0x0002
|
||||
#define DEBUGLEVEL_TRACE 0x0004
|
||||
#define DEBUGLEVEL_PPMSG 0x0008
|
||||
#define DEBUGLEVEL_PPLEX 0x0010
|
||||
#define DEBUGLEVEL_PPTRACE 0x0020
|
||||
|
||||
extern int win32;
|
||||
extern int constant;
|
||||
|
@ -43,12 +54,18 @@ extern DWORD codepage;
|
|||
extern int pedantic;
|
||||
extern int auto_register;
|
||||
extern int leave_case;
|
||||
extern int preprocess_only;
|
||||
extern int no_preprocess;
|
||||
|
||||
extern char *prefix;
|
||||
extern char *output_name;
|
||||
extern char *input_name;
|
||||
extern char *header_name;
|
||||
extern char *cmdline;
|
||||
extern time_t now;
|
||||
|
||||
extern int line_number;
|
||||
extern int char_number;
|
||||
|
||||
extern resource_t *resource_top;
|
||||
extern language_t *currentlanguage;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "wrc.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 */
|
||||
|
||||
time_t now;
|
||||
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Function : write_resfile
|
||||
|
@ -940,7 +937,6 @@ void write_s_file(char *outname, resource_t *top)
|
|||
|
||||
{
|
||||
char *s, *p;
|
||||
now = time(NULL);
|
||||
s = ctime(&now);
|
||||
p = strchr(s, '\n');
|
||||
if(p) *p = '\0';
|
||||
|
@ -1127,7 +1123,6 @@ void write_h_file(char *outname, resource_t *top)
|
|||
error("Could not open %s\n", outname);
|
||||
}
|
||||
|
||||
time(&now);
|
||||
fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
|
||||
cmdline, ctime(&now), (long)now, (long)now);
|
||||
|
||||
|
|
Loading…
Reference in New Issue