Split the C preprocessor from wrc into a separate library.
Prefixed exported functions by 'pp' to avoid namespace conflicts.

diff --git a/configure b/configure
index a029db0..58b1b15 100755
--- a/configure
+++ b/configure
@@ -13314,7 +13314,7 @@
 MAKE_PROG_RULES=programs/Makeprog.rules
 
 
-ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules programs/Makeprog.rules Makefile debugger/Makefile dlls/Makefile dlls/advapi32/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/d3d8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dsound/Makefile dlls/gdi/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/kernel/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt20/Makefile dlls/msvideo/Makefile dlls/netapi32/Makefile dlls/ntdll/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/user/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winspool/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile library/Makefile miscemu/Makefile ole/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineconsole/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wrc/Makefile tsx11/Makefile unicode/Makefile"
+ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules programs/Makeprog.rules Makefile debugger/Makefile dlls/Makefile dlls/advapi32/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/d3d8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dsound/Makefile dlls/gdi/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/kernel/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt20/Makefile dlls/msvideo/Makefile dlls/netapi32/Makefile dlls/ntdll/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/user/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winspool/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile library/Makefile miscemu/Makefile ole/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineconsole/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wpp/Makefile tools/wrc/Makefile tsx11/Makefile unicode/Makefile"
 
 
 cat >confcache <<\_ACEOF
@@ -13925,6 +13925,7 @@
   "tools/winebuild/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/winebuild/Makefile" ;;
   "tools/winedump/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/winedump/Makefile" ;;
   "tools/wmc/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/wmc/Makefile" ;;
+  "tools/wpp/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/wpp/Makefile" ;;
   "tools/wrc/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/wrc/Makefile" ;;
   "tsx11/Makefile" ) CONFIG_FILES="$CONFIG_FILES tsx11/Makefile" ;;
   "unicode/Makefile" ) CONFIG_FILES="$CONFIG_FILES unicode/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index f064a98..926e021 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1378,6 +1378,7 @@
 tools/winebuild/Makefile
 tools/winedump/Makefile
 tools/wmc/Makefile
+tools/wpp/Makefile
 tools/wrc/Makefile
 tsx11/Makefile
 unicode/Makefile])
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 2fdd45b..7af39fd 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -13,6 +13,7 @@
 	winebuild \
 	winedump \
 	wmc \
+	wpp \
 	wrc
 
 INSTALLSUBDIRS = $(SUBDIRS)
@@ -27,6 +28,8 @@
 
 @MAKE_RULES@
 
+wrc: wpp
+
 makedep: makedep.o
 	$(CC) $(CFLAGS) -o makedep makedep.o
 
diff --git a/tools/wpp/.cvsignore b/tools/wpp/.cvsignore
new file mode 100644
index 0000000..8e7a162
--- /dev/null
+++ b/tools/wpp/.cvsignore
@@ -0,0 +1,4 @@
+Makefile
+lex.yy.c
+y.tab.c
+y.tab.h
diff --git a/tools/wpp/Makefile.in b/tools/wpp/Makefile.in
new file mode 100644
index 0000000..5aca31f
--- /dev/null
+++ b/tools/wpp/Makefile.in
@@ -0,0 +1,32 @@
+DEFS      = -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+LEXOPT    = -Cf #-w -b
+YACCOPT   = #-v
+MODULE    = none
+
+C_SRCS = \
+	preproc.c \
+	wpp.c
+
+EXTRA_SRCS = ppy.y ppl.l
+EXTRA_OBJS = y.tab.o @LEX_OUTPUT_ROOT@.o
+
+all: libwpp.a
+
+@MAKE_RULES@
+
+libwpp.a: $(OBJS)
+	$(RM) $@
+	$(AR) $@ $(OBJS)
+	$(RANLIB) $@
+
+y.tab.c y.tab.h: ppy.y
+	$(YACC) $(YACCOPT) -ppp -d -t $(SRCDIR)/ppy.y
+
+@LEX_OUTPUT_ROOT@.c: ppl.l
+	$(LEX) $(LEXOPT) -d -Ppp -o$@ -8 $(SRCDIR)/ppl.l
+
+### Dependencies:
diff --git a/tools/wrc/ppl.l b/tools/wpp/ppl.l
similarity index 82%
rename from tools/wrc/ppl.l
rename to tools/wpp/ppl.l
index b7d2d06..b871626 100644
--- a/tools/wrc/ppl.l
+++ b/tools/wpp/ppl.l
@@ -159,11 +159,8 @@
 #include <ctype.h>
 #include <assert.h>
 
-#include "utils.h"
-#include "wrc.h"
-#include "preproc.h"
-
-#include "ppy.tab.h"
+#include "wpp_private.h"
+#include "y.tab.h"
 
 /*
  * Make sure that we are running an appropriate version of flex.
@@ -182,7 +179,7 @@
 /*
  * Always update the current character position within a line
  */
-#define YY_USER_ACTION	char_number+=ppleng;
+#define YY_USER_ACTION	pp_status.char_number+=ppleng;
 
 /*
  * Buffer management for includes and expansions
@@ -194,16 +191,13 @@
 	pp_entry_t	*define;	/* Points to expanding define or NULL if handling includes */
 	int		line_number;	/* Line that we were handling */
 	int		char_number;	/* The current position on that line */
-	char		*filename;	/* Filename that we were handling */
+	const char	*filename;	/* Filename that we were handling */
 	int		if_depth;	/* How many #if:s deep to check matching #endif:s */
 	int		ncontinuations;	/* Remember the continuation state */
 	int		should_pop;	/* Set if we must pop the start-state on EOF */
 	/* Include management */
-	int		include_state;
-	char		*include_ppp;
-	char		*include_filename;
-	int		include_ifdepth;
-	int		seen_junk;
+        include_state_t incl;
+	char 		*include_filename;
 	int 		pass_data;
 } bufferstackentry_t;
 
@@ -280,21 +274,15 @@
 /*
  * Global variables
  */
-/*
- * Trace the include files to prevent double reading.
- * This save 20..30% of processing time for most stuff
- * that uses complex includes.
- * States:
- * -1	Don't track or seen junk
- *  0	New include, waiting for "#ifndef __xxx_h"
- *  1	Seen #ifndef, waiting for "#define __xxx_h ..."
- *  2	Seen #endif, waiting for EOF
- */
-int include_state = -1;
-char *include_ppp = NULL;	/* The define to be set from the #ifndef */
-int include_ifdepth = 0;	/* The level of ifs at the #ifdef */
-int seen_junk = 0;		/* Set when junk is seen */
-includelogicentry_t *includelogiclist = NULL;
+include_state_t pp_incl_state =
+{
+    -1,    /* state */
+    NULL,  /* ppp */
+    0,     /* ifdepth */
+    0      /* seen_junk */
+};
+
+includelogicentry_t *pp_includelogiclist = NULL;
 
 %}
 
@@ -317,7 +305,7 @@
 	/*
 	 * Detect the leading # of a preprocessor directive.
 	 */
-<INITIAL,pp_ignore>^{ws}*#	seen_junk++; yy_push_state(pp_pp);
+<INITIAL,pp_ignore>^{ws}*#	pp_incl_state.seen_junk++; yy_push_state(pp_pp);
 
 	/*
 	 * Scan for the preprocessor directives
@@ -330,7 +318,7 @@
 <pp_pp>{ws}*ident{ws}*		yy_pp_state(pp_eol);	if(yy_top_state() != pp_ignore) return tPPIDENT;
 <pp_pp>{ws}*undef{ws}*		if(yy_top_state() != pp_ignore) {yy_pp_state(pp_ifd); return tUNDEF;} else {yy_pp_state(pp_eol);}
 <pp_pp>{ws}*ifdef{ws}*		yy_pp_state(pp_ifd);	return tIFDEF;
-<pp_pp>{ws}*ifndef{ws}*		seen_junk--; yy_pp_state(pp_ifd);	return tIFNDEF;
+<pp_pp>{ws}*ifndef{ws}*		pp_incl_state.seen_junk--; yy_pp_state(pp_ifd);	return tIFNDEF;
 <pp_pp>{ws}*if{ws}*		yy_pp_state(pp_if);	return tIF;
 <pp_pp>{ws}*elif{ws}*		yy_pp_state(pp_if);	return tELIF;
 <pp_pp>{ws}*else{ws}*		return tELSE;
@@ -395,7 +383,7 @@
 	 * Handle #ifdef, #ifndef and #undef
 	 * to get only an untranslated/unexpanded identifier
 	 */
-<pp_ifd>{cident}	pplval.cptr = xstrdup(pptext); return tIDENT;
+<pp_ifd>{cident}	pplval.cptr = pp_xstrdup(pptext); return tIDENT;
 <pp_ifd>{ws}+		;
 <pp_ifd>\n		newline(1); yy_pop_state(); return tNL;
 <pp_ifd>\\\r?\n		newline(0);
@@ -406,7 +394,7 @@
 	 * This is necessary to get the identifier prior to any
 	 * substitutions.
 	 */
-<pp_defined>{cident}		yy_pop_state(); pplval.cptr = xstrdup(pptext); return tIDENT;
+<pp_defined>{cident}		yy_pop_state(); pplval.cptr = pp_xstrdup(pptext); return tIDENT;
 <pp_defined>{ws}+		;
 <pp_defined>(\()|(\))		return *pptext;
 <pp_defined>\\\r?\n		newline(0);
@@ -418,17 +406,17 @@
 	 * will act appropriately.
 	 * Comments are stripped from the literal text.
 	 */
-<pp_eol>[^/\\\n]+		if(yy_top_state() != pp_ignore) { pplval.cptr = xstrdup(pptext); return tLITERAL; }
-<pp_eol>\/[^/\\\n*]*		if(yy_top_state() != pp_ignore) { pplval.cptr = xstrdup(pptext); return tLITERAL; }
-<pp_eol>(\\\r?)|(\/[^/*])	if(yy_top_state() != pp_ignore) { pplval.cptr = xstrdup(pptext); return tLITERAL; }
+<pp_eol>[^/\\\n]+		if(yy_top_state() != pp_ignore) { pplval.cptr = pp_xstrdup(pptext); return tLITERAL; }
+<pp_eol>\/[^/\\\n*]*		if(yy_top_state() != pp_ignore) { pplval.cptr = pp_xstrdup(pptext); return tLITERAL; }
+<pp_eol>(\\\r?)|(\/[^/*])	if(yy_top_state() != pp_ignore) { pplval.cptr = pp_xstrdup(pptext); return tLITERAL; }
 <pp_eol>\n			newline(1); yy_pop_state(); if(yy_current_state() != pp_ignore) { return tNL; }
 <pp_eol>\\\r?\n			newline(0);
 
 	/*
 	 * Handle left side of #define
 	 */
-<pp_def>{cident}\(		pplval.cptr = xstrdup(pptext); pplval.cptr[ppleng-1] = '\0'; yy_pp_state(pp_macro);  return tMACRO;
-<pp_def>{cident}		pplval.cptr = xstrdup(pptext); yy_pp_state(pp_define); return tDEFINE;
+<pp_def>{cident}\(		pplval.cptr = pp_xstrdup(pptext); pplval.cptr[ppleng-1] = '\0'; yy_pp_state(pp_macro);  return tMACRO;
+<pp_def>{cident}		pplval.cptr = pp_xstrdup(pptext); yy_pp_state(pp_define); return tDEFINE;
 <pp_def>{ws}+			;
 <pp_def>\\\r?\n			newline(0);
 <pp_def>(\\\r?)|(\n)|(.)	perror("Identifier expected");
@@ -436,9 +424,9 @@
 	/*
 	 * Scan the substitution of a define
 	 */
-<pp_define>[^'"/\\\n]+		pplval.cptr = xstrdup(pptext); return tLITERAL;
-<pp_define>(\\\r?)|(\/[^/*])	pplval.cptr = xstrdup(pptext); return tLITERAL;
-<pp_define>\\\r?\n{ws}+		newline(0); pplval.cptr = xstrdup(" "); return tLITERAL;
+<pp_define>[^'"/\\\n]+		pplval.cptr = pp_xstrdup(pptext); return tLITERAL;
+<pp_define>(\\\r?)|(\/[^/*])	pplval.cptr = pp_xstrdup(pptext); return tLITERAL;
+<pp_define>\\\r?\n{ws}+		newline(0); pplval.cptr = pp_xstrdup(" "); return tLITERAL;
 <pp_define>\\\r?\n		newline(0);
 <pp_define>\n			newline(1); yy_pop_state(); return tNL;
 <pp_define>\'			new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
@@ -449,7 +437,7 @@
 	 */
 <pp_macro>\){ws}*		yy_pp_state(pp_mbody); return tMACROEND;
 <pp_macro>{ws}+			;
-<pp_macro>{cident}		pplval.cptr = xstrdup(pptext); return tIDENT;
+<pp_macro>{cident}		pplval.cptr = pp_xstrdup(pptext); return tIDENT;
 <pp_macro>,			return ',';
 <pp_macro>"..."			return tELIPSIS;
 <pp_macro>(\\\r?)|(\n)|(.)|(\.\.?)	pperror("Argument identifier expected");
@@ -458,13 +446,13 @@
 	/*
 	 * Scan the substitution of a macro
 	 */
-<pp_mbody>[^a-zA-Z0-9'"#/\\\n]+	pplval.cptr = xstrdup(pptext); return tLITERAL;
-<pp_mbody>{cident}		pplval.cptr = xstrdup(pptext); return tIDENT;
+<pp_mbody>[^a-zA-Z0-9'"#/\\\n]+	pplval.cptr = pp_xstrdup(pptext); return tLITERAL;
+<pp_mbody>{cident}		pplval.cptr = pp_xstrdup(pptext); return tIDENT;
 <pp_mbody>\#\#			return tCONCAT;
 <pp_mbody>\#			return tSTRINGIZE;
-<pp_mbody>[0-9][^'"#/\\\n]*	pplval.cptr = xstrdup(pptext); return tLITERAL;
-<pp_mbody>(\\\r?)|(\/[^/*'"#\\\n]*)	pplval.cptr = xstrdup(pptext); return tLITERAL;
-<pp_mbody>\\\r?\n{ws}+		newline(0); pplval.cptr = xstrdup(" "); return tLITERAL;
+<pp_mbody>[0-9][^'"#/\\\n]*	pplval.cptr = pp_xstrdup(pptext); return tLITERAL;
+<pp_mbody>(\\\r?)|(\/[^/*'"#\\\n]*)	pplval.cptr = pp_xstrdup(pptext); return tLITERAL;
+<pp_mbody>\\\r?\n{ws}+		newline(0); pplval.cptr = pp_xstrdup(" "); return tLITERAL;
 <pp_mbody>\\\r?\n		newline(0);
 <pp_mbody>\n			newline(1); yy_pop_state(); return tNL;
 <pp_mbody>\'			new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
@@ -519,7 +507,7 @@
 <pp_macscan>\"		new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs);
 <pp_macscan>\'		new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
 <pp_macscan>"/*"	yy_push_state(pp_comment); add_text_to_macro(" ", 1);
-<pp_macscan>\n		line_number++; char_number = 1; add_text_to_macro(pptext, ppleng);
+<pp_macscan>\n		pp_status.line_number++; pp_status.char_number = 1; add_text_to_macro(pptext, ppleng);
 <pp_macscan>([^/(),\\\n"']+)|(\/[^/*(),\\\n'"]*)|(\\\r?)|(.)	add_text_to_macro(pptext, ppleng);
 <pp_macscan>\\\r?\n	newline(0);
 
@@ -542,8 +530,8 @@
 	/*
 	 * Single, double and <> quoted constants
 	 */
-<INITIAL,pp_macexp>\"		seen_junk++; new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs);
-<INITIAL,pp_macexp>\'		seen_junk++; new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
+<INITIAL,pp_macexp>\"		pp_incl_state.seen_junk++; new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs);
+<INITIAL,pp_macexp>\'		pp_incl_state.seen_junk++; new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
 <pp_dqs>[^"\\\n]+		add_string(pptext, ppleng);
 <pp_dqs>\"			{
 		add_string(pptext, ppleng);
@@ -621,7 +609,7 @@
 	 */
 <INITIAL,pp_if,pp_inc,pp_macexp>{cident}	{
 		pp_entry_t *ppp;
-		seen_junk++;
+		pp_incl_state.seen_junk++;
 		if(!(ppp = pplookup(pptext)))
 		{
 			if(yy_current_state() == pp_inc)
@@ -629,7 +617,7 @@
 
 			if(yy_current_state() == pp_if)
 			{
-				pplval.cptr = xstrdup(pptext);
+				pplval.cptr = pp_xstrdup(pptext);
 				return tIDENT;
 			}
 			else {
@@ -655,7 +643,7 @@
 				push_macro(ppp);
 				break;
 			default:
-				internal_error(__FILE__, __LINE__, "Invalid define type %d\n", ppp->type);
+				pp_internal_error(__FILE__, __LINE__, "Invalid define type %d\n", ppp->type);
 			}
 		}
 	}
@@ -664,11 +652,11 @@
 	 * Everything else that needs to be passed and
 	 * newline and continuation handling
 	 */
-<INITIAL,pp_macexp>[^a-zA-Z_#'"/\\\n \r\t\f\v]+|(\/|\\)[^a-zA-Z_/*'"\\\n \r\t\v\f]*	seen_junk++; put_buffer(pptext, ppleng);
+<INITIAL,pp_macexp>[^a-zA-Z_#'"/\\\n \r\t\f\v]+|(\/|\\)[^a-zA-Z_/*'"\\\n \r\t\v\f]*	pp_incl_state.seen_junk++; put_buffer(pptext, ppleng);
 <INITIAL,pp_macexp>{ws}+	put_buffer(pptext, ppleng);
 <INITIAL>\n			newline(1);
 <INITIAL>\\\r?\n		newline(0);
-<INITIAL>\\\r?			seen_junk++; put_buffer(pptext, ppleng);
+<INITIAL>\\\r?			pp_incl_state.seen_junk++; put_buffer(pptext, ppleng);
 
 	/*
 	 * Special catcher for macro argmument expansion to prevent
@@ -677,7 +665,7 @@
 <pp_macexp>(\n)|(.)|(\\\r?(\n|.))	put_buffer(pptext, ppleng);
 
 <RCINCL>[A-Za-z0-9_\.\\/]+ {
-		pplval.cptr=xstrdup(pptext);
+		pplval.cptr=pp_xstrdup(pptext);
         	yy_pop_state();
 		return tRCINCLUDEPATH;
 	}
@@ -692,13 +680,13 @@
 	 * This is a 'catch-all' rule to discover errors in the scanner
 	 * in an orderly manner.
 	 */
-<*>.		seen_junk++; ppwarning("Unmatched text '%c' (0x%02x); please report\n", isprint(*pptext & 0xff) ? *pptext : ' ', *pptext);
+<*>.		pp_incl_state.seen_junk++; ppwarning("Unmatched text '%c' (0x%02x); please report\n", isprint(*pptext & 0xff) ? *pptext : ' ', *pptext);
 
 <<EOF>>	{
 		YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
 		bufferstackentry_t *bep = pop_buffer();
 
-		if((!bep && get_if_depth()) || (bep && get_if_depth() != bep->if_depth))
+		if((!bep && pp_get_if_depth()) || (bep && pp_get_if_depth() != bep->if_depth))
 			ppwarning("Unmatched #if/#endif at end of file");
 
 		if(!bep)
@@ -742,8 +730,8 @@
  */
 static void newline(int dowrite)
 {
-	line_number++;
-	char_number = 1;
+	pp_status.line_number++;
+	pp_status.char_number = 1;
 
 	if(dowrite == -1)
 		return;
@@ -819,7 +807,7 @@
 	}
 
 	if(is_ll)
-		internal_error(__FILE__, __LINE__, "long long constants not implemented yet");
+		pp_internal_error(__FILE__, __LINE__, "long long constants not implemented yet");
 
 	if(is_u && is_l)
 	{
@@ -834,24 +822,11 @@
 	else if(is_u && !is_l)
 	{
 		val->uint = (unsigned int)strtoul(str, NULL, radix);
-		if(!win32 && val->uint > 65535)
-		{
-			pperror("Constant overflow");
-		}
 		return tUINT;
 	}
 
 	/* Else it must be an int... */
 	val->sint = (int)strtol(str, NULL, radix);
-	if(!win32 && (val->sint < -32768 || val->sint > 32768))
-	{
-		/*
-		 * Note: test must be > 32768 because unary minus
-		 * is handled as an expression! This can result in
-		 * failure and must be checked in the parser.
-		 */
-		pperror("Constant overflow");
-	}
 	return tSINT;
 }
 
@@ -873,35 +848,23 @@
 	if(!strcmp(ppp->ident, "__LINE__"))
 	{
 		dbgtext = "def_special(__LINE__)";
-		buf = xrealloc(buf, 32);
-		sprintf(buf, "%d", line_number);
+		buf = pp_xrealloc(buf, 32);
+		sprintf(buf, "%d", pp_status.line_number);
 	}
 	else if(!strcmp(ppp->ident, "__FILE__"))
 	{
 		dbgtext = "def_special(__FILE__)";
-		buf = xrealloc(buf, strlen(input_name) + 3);
-		sprintf(buf, "\"%s\"", input_name);
-	}
-	else if(!strcmp(ppp->ident, "__DATE__"))
-	{
-		dbgtext = "def_special(__DATE__)";
-		buf = xrealloc(buf, 32);
-		strftime(buf, 32, "\"%b %d %Y\"", localtime(&now));
-	}
-	else if(!strcmp(ppp->ident, "__TIME__"))
-	{
-		dbgtext = "def_special(__TIME__)";
-		buf = xrealloc(buf, 32);
-		strftime(buf, 32, "\"%H:%M:%S\"", localtime(&now));
+		buf = pp_xrealloc(buf, strlen(pp_status.input) + 3);
+		sprintf(buf, "\"%s\"", pp_status.input);
 	}
 	else
-		internal_error(__FILE__, __LINE__, "Special macro '%s' not found...\n", ppp->ident);
+		pp_internal_error(__FILE__, __LINE__, "Special macro '%s' not found...\n", ppp->ident);
 
-	if(debuglevel & DEBUGLEVEL_PPLEX)
+	if(pp_flex_debug)
 		fprintf(stderr, "expand_special(%d): %s:%d: '%s' -> '%s'\n",
 			macexpstackidx,
-			input_name,
-			line_number,
+			pp_status.input,
+			pp_status.line_number,
 			ppp->ident,
 			buf ? buf : "");
 
@@ -916,11 +879,11 @@
 {
 	assert(ppp->type == def_define);
 
-	if(debuglevel & DEBUGLEVEL_PPLEX)
+	if(pp_flex_debug)
 		fprintf(stderr, "expand_define(%d): %s:%d: '%s' -> '%s'\n",
 			macexpstackidx,
-			input_name,
-			line_number,
+			pp_status.input,
+			pp_status.line_number,
 			ppp->ident,
 			ppp->subst.text);
 	if(ppp->subst.text && ppp->subst.text[0])
@@ -941,7 +904,7 @@
 	if(curdef_idx >= curdef_alloc || curdef_alloc - curdef_idx < len)
 	{
 		curdef_alloc += (len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1);
-		curdef_text = xrealloc(curdef_text, curdef_alloc * sizeof(curdef_text[0]));
+		curdef_text = pp_xrealloc(curdef_text, curdef_alloc * sizeof(curdef_text[0]));
 		if(curdef_alloc > 65536)
 			ppwarning("Reallocating macro-expansion buffer larger than 64kB");
 	}
@@ -962,13 +925,13 @@
 	switch(mtp->type)
 	{
 	case exp_text:
-		if(debuglevel & DEBUGLEVEL_PPLEX)
+		if(pp_flex_debug)
 			fprintf(stderr, "add_expand_text: exp_text: '%s'\n", mtp->subst.text);
 		add_text(mtp->subst.text, strlen(mtp->subst.text));
 		break;
 
 	case exp_stringize:
-		if(debuglevel & DEBUGLEVEL_PPLEX)
+		if(pp_flex_debug)
 			fprintf(stderr, "add_expand_text: exp_stringize(%d): '%s'\n",
 				mtp->subst.argidx,
 				mep->args[mtp->subst.argidx]);
@@ -985,7 +948,7 @@
 		break;
 
 	case exp_concat:
-		if(debuglevel & DEBUGLEVEL_PPLEX)
+		if(pp_flex_debug)
 			fprintf(stderr, "add_expand_text: exp_concat\n");
 		/* Remove trailing whitespace from current expansion text */
 		while(curdef_idx)
@@ -1036,12 +999,12 @@
 			}
 			mep->nnls[mtp->subst.argidx] = 0;
 		}
-		if(debuglevel & DEBUGLEVEL_PPLEX)
+		if(pp_flex_debug)
 			fprintf(stderr, "add_expand_text: exp_subst(%d): '%s'\n", mtp->subst.argidx, exp);
 		break;
 
 	default:
-		internal_error(__FILE__, __LINE__, "Invalid expansion type (%d) in macro expansion\n", mtp->type);
+		pp_internal_error(__FILE__, __LINE__, "Invalid expansion type (%d) in macro expansion\n", mtp->type);
 	}
 	return mtp;
 }
@@ -1064,11 +1027,11 @@
 	for(n = 0; n < nargs; n++)
 		nnl += mep->nnls[n];
 
-	if(debuglevel & DEBUGLEVEL_PPLEX)
+	if(pp_flex_debug)
 		fprintf(stderr, "expand_macro(%d): %s:%d: '%s'(%d,%d) -> ...\n",
 			macexpstackidx,
-			input_name,
-			line_number,
+			pp_status.input,
+			pp_status.line_number,
 			ppp->ident,
 			mep->nargs,
 			nnl);
@@ -1111,7 +1074,7 @@
 
 	if(k - n > 0)
 	{
-		if(debuglevel & DEBUGLEVEL_PPLEX)
+		if(pp_flex_debug)
 			fprintf(stderr, "expand_text: '%s'\n", curdef_text + n);
 		push_buffer(ppp, NULL, NULL, 0);
 		/*yy_scan_bytes(curdef_text + n, k - n);*/
@@ -1131,7 +1094,7 @@
 		ppwarning("new_string: strbuf_idx != 0");
 #endif
 	strbuf_idx = 0;
-	str_startline = line_number;
+	str_startline = pp_status.line_number;
 }
 
 static void add_string(char *str, int len)
@@ -1141,7 +1104,7 @@
 	if(strbuf_idx >= strbuf_alloc || strbuf_alloc - strbuf_idx < len)
 	{
 		strbuf_alloc += (len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1);
-		strbuffer = xrealloc(strbuffer, strbuf_alloc * sizeof(strbuffer[0]));
+		strbuffer = pp_xrealloc(strbuffer, strbuf_alloc * sizeof(strbuffer[0]));
 		if(strbuf_alloc > 65536)
 			ppwarning("Reallocating string buffer larger than 64kB");
 	}
@@ -1151,7 +1114,7 @@
 
 static char *get_string(void)
 {
-	char *str = (char *)xmalloc(strbuf_idx + 1);
+	char *str = pp_xmalloc(strbuf_idx + 1);
 	memcpy(str, strbuffer, strbuf_idx);
 	str[strbuf_idx] = '\0';
 #ifdef DEBUG
@@ -1184,22 +1147,19 @@
 	if(ppdebug)
 		printf("push_buffer(%d): %p %p %p %d\n", bufferstackidx, ppp, filename, incname, pop);
 	if(bufferstackidx >= MAXBUFFERSTACK)
-		internal_error(__FILE__, __LINE__, "Buffer stack overflow");
+		pp_internal_error(__FILE__, __LINE__, "Buffer stack overflow");
 
 	memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0]));
 	bufferstack[bufferstackidx].bufferstate	= YY_CURRENT_BUFFER;
 	bufferstack[bufferstackidx].define	= ppp;
-	bufferstack[bufferstackidx].line_number	= line_number;
-	bufferstack[bufferstackidx].char_number	= char_number;
-	bufferstack[bufferstackidx].if_depth	= get_if_depth();
+	bufferstack[bufferstackidx].line_number	= pp_status.line_number;
+	bufferstack[bufferstackidx].char_number	= pp_status.char_number;
+	bufferstack[bufferstackidx].if_depth	= pp_get_if_depth();
 	bufferstack[bufferstackidx].should_pop	= pop;
-	bufferstack[bufferstackidx].filename	= input_name;
+	bufferstack[bufferstackidx].filename	= pp_status.input;
 	bufferstack[bufferstackidx].ncontinuations	= ncontinuations;
-	bufferstack[bufferstackidx].include_state	= include_state;
-	bufferstack[bufferstackidx].include_ppp		= include_ppp;
+	bufferstack[bufferstackidx].incl		= pp_incl_state;
 	bufferstack[bufferstackidx].include_filename	= incname;
-	bufferstack[bufferstackidx].include_ifdepth	= include_ifdepth;
-	bufferstack[bufferstackidx].seen_junk		= seen_junk;
 	bufferstack[bufferstackidx].pass_data		= pass_data;
 
 	if(ppp)
@@ -1207,20 +1167,20 @@
 	else if(filename)
 	{
 		/* These will track the pperror to the correct file and line */
-		line_number = 1;
-		char_number = 1;
-		input_name  = filename;
+		pp_status.line_number = 1;
+		pp_status.char_number = 1;
+		pp_status.input  = filename;
 		ncontinuations = 0;
 	}
 	else if(!pop)
-		internal_error(__FILE__, __LINE__, "Pushing buffer without knowing where to go to");
+		pp_internal_error(__FILE__, __LINE__, "Pushing buffer without knowing where to go to");
 	bufferstackidx++;
 }
 
 static bufferstackentry_t *pop_buffer(void)
 {
 	if(bufferstackidx < 0)
-		internal_error(__FILE__, __LINE__, "Bufferstack underflow?");
+		pp_internal_error(__FILE__, __LINE__, "Bufferstack underflow?");
 
 	if(bufferstackidx == 0)
 		return NULL;
@@ -1231,41 +1191,39 @@
 		bufferstack[bufferstackidx].define->expanding = 0;
 	else
 	{
-		line_number = bufferstack[bufferstackidx].line_number;
-		char_number = bufferstack[bufferstackidx].char_number;
-		input_name  = bufferstack[bufferstackidx].filename;
+		pp_status.line_number = bufferstack[bufferstackidx].line_number;
+		pp_status.char_number = bufferstack[bufferstackidx].char_number;
+		pp_status.input  = bufferstack[bufferstackidx].filename;
 		ncontinuations = bufferstack[bufferstackidx].ncontinuations;
 		if(!bufferstack[bufferstackidx].should_pop)
 		{
 			fclose(ppin);
-			fprintf(ppout, "# %d \"%s\" 2\n", line_number, input_name);
+			fprintf(ppout, "# %d \"%s\" 2\n", pp_status.line_number, pp_status.input);
 
 			/* We have EOF, check the include logic */
-			if(include_state == 2 && !seen_junk && include_ppp)
+			if(pp_incl_state.state == 2 && !pp_incl_state.seen_junk && pp_incl_state.ppp)
 			{
-				pp_entry_t *ppp = pplookup(include_ppp);
+				pp_entry_t *ppp = pplookup(pp_incl_state.ppp);
 				if(ppp)
 				{
-					includelogicentry_t *iep = xmalloc(sizeof(includelogicentry_t));
+					includelogicentry_t *iep = pp_xmalloc(sizeof(includelogicentry_t));
 					iep->ppp = ppp;
 					ppp->iep = iep;
 					iep->filename = bufferstack[bufferstackidx].include_filename;
-					iep->next = includelogiclist;
+                                        iep->prev = NULL;
+					iep->next = pp_includelogiclist;
 					if(iep->next)
 						iep->next->prev = iep;
-					includelogiclist = iep;
-					if(debuglevel & DEBUGLEVEL_PPMSG)
-						fprintf(stderr, "pop_buffer: %s:%d: includelogic added, include_ppp='%s', file='%s'\n", input_name, line_number, include_ppp, iep->filename);
+					pp_includelogiclist = iep;
+					if(pp_status.debug)
+						fprintf(stderr, "pop_buffer: %s:%d: includelogic added, include_ppp='%s', file='%s'\n", pp_status.input, pp_status.line_number, pp_incl_state.ppp, iep->filename);
 				}
 				else if(bufferstack[bufferstackidx].include_filename)
 					free(bufferstack[bufferstackidx].include_filename);
 			}
-			if(include_ppp)
-				free(include_ppp);
-			include_state	= bufferstack[bufferstackidx].include_state;
-			include_ppp	= bufferstack[bufferstackidx].include_ppp;
-			include_ifdepth	= bufferstack[bufferstackidx].include_ifdepth;
-			seen_junk	= bufferstack[bufferstackidx].seen_junk;
+			if(pp_incl_state.ppp)
+				free(pp_incl_state.ppp);
+			pp_incl_state	= bufferstack[bufferstackidx].incl;
 			pass_data	= bufferstack[bufferstackidx].pass_data;
 
 		}
@@ -1289,7 +1247,7 @@
 		if(yy_current_state() == pp_macexp)
 			macro_add_expansion();
 		else
-			internal_error(__FILE__, __LINE__, "Pop buffer and state without macro expansion state");
+			pp_internal_error(__FILE__, __LINE__, "Pop buffer and state without macro expansion state");
 		yy_pop_state();
 	}
 
@@ -1307,8 +1265,8 @@
 	if(macexpstackidx >= MAXMACEXPSTACK)
 		pperror("Too many nested macros");
 
-	macexpstack[macexpstackidx] = xmalloc(sizeof(macexpstack[0][0]));
-
+	macexpstack[macexpstackidx] = pp_xmalloc(sizeof(macexpstack[0][0]));
+        memset( macexpstack[macexpstackidx], 0, sizeof(macexpstack[0][0]));
 	macexpstack[macexpstackidx]->ppp = ppp;
 	macexpstackidx++;
 }
@@ -1321,7 +1279,7 @@
 static macexpstackentry_t *pop_macro(void)
 {
 	if(macexpstackidx <= 0)
-		internal_error(__FILE__, __LINE__, "Macro expansion stack underflow\n");
+		pp_internal_error(__FILE__, __LINE__, "Macro expansion stack underflow\n");
 	return macexpstack[--macexpstackidx];
 }
 
@@ -1348,8 +1306,8 @@
 
 	if(mep->curargalloc - mep->curargsize <= len+1)	/* +1 for '\0' */
 	{
-		mep->curargalloc += max(ALLOCBLOCKSIZE, len+1);
-		mep->curarg = xrealloc(mep->curarg, mep->curargalloc * sizeof(mep->curarg[0]));
+		mep->curargalloc += (ALLOCBLOCKSIZE > len+1) ? ALLOCBLOCKSIZE : len+1;
+		mep->curarg = pp_xrealloc(mep->curarg, mep->curargalloc * sizeof(mep->curarg[0]));
 	}
 	memcpy(mep->curarg + mep->curargsize, text, len);
 	mep->curargsize += len;
@@ -1364,10 +1322,10 @@
 
 	assert(mep->ppp->expanding == 0);
 
-	mep->args = xrealloc(mep->args, (mep->nargs+1) * sizeof(mep->args[0]));
-	mep->ppargs = xrealloc(mep->ppargs, (mep->nargs+1) * sizeof(mep->ppargs[0]));
-	mep->nnls = xrealloc(mep->nnls, (mep->nargs+1) * sizeof(mep->nnls[0]));
-	mep->args[mep->nargs] = xstrdup(mep->curarg ? mep->curarg : "");
+	mep->args = pp_xrealloc(mep->args, (mep->nargs+1) * sizeof(mep->args[0]));
+	mep->ppargs = pp_xrealloc(mep->ppargs, (mep->nargs+1) * sizeof(mep->ppargs[0]));
+	mep->nnls = pp_xrealloc(mep->nnls, (mep->nargs+1) * sizeof(mep->nnls[0]));
+	mep->args[mep->nargs] = pp_xstrdup(mep->curarg ? mep->curarg : "");
 	cptr = mep->args[mep->nargs]-1;
 	while((cptr = strchr(cptr+1, '\n')))
 	{
@@ -1379,10 +1337,10 @@
 	mep->curargalloc = mep->curargsize = 0;
 	mep->curarg = NULL;
 
-	if(debuglevel & DEBUGLEVEL_PPLEX)
+	if(pp_flex_debug)
 		fprintf(stderr, "macro_add_arg: %s:%d: %d -> '%s'\n",
-			input_name,
-			line_number,
+			pp_status.input,
+			pp_status.line_number,
 			mep->nargs-1,
 			mep->args[mep->nargs-1]);
 
@@ -1402,15 +1360,15 @@
 
 	assert(mep->ppp->expanding == 0);
 
-	mep->ppargs[mep->nargs-1] = xstrdup(mep->curarg ? mep->curarg : "");
+	mep->ppargs[mep->nargs-1] = pp_xstrdup(mep->curarg ? mep->curarg : "");
 	free(mep->curarg);
 	mep->curargalloc = mep->curargsize = 0;
 	mep->curarg = NULL;
 
-	if(debuglevel & DEBUGLEVEL_PPLEX)
+	if(pp_flex_debug)
 		fprintf(stderr, "macro_add_expansion: %s:%d: %d -> '%s'\n",
-			input_name,
-			line_number,
+			pp_status.input,
+			pp_status.line_number,
 			mep->nargs-1,
 			mep->ppargs[mep->nargs-1]);
 }
@@ -1437,7 +1395,7 @@
  * Include management
  *-------------------------------------------------------------------------
  */
-int is_c_h_include(char *fname)
+static int is_c_h_include(char *fname)
 {
 	int sl=strlen(fname);
 	if (sl < 2) return 0;
@@ -1446,13 +1404,13 @@
 	return 1;
 }
 
-void do_include(char *fname, int type)
+void pp_do_include(char *fname, int type)
 {
 	char *newpath;
 	int n;
 	includelogicentry_t *iep;
 
-	for(iep = includelogiclist; iep; iep = iep->next)
+	for(iep = pp_includelogiclist; iep; iep = iep->next)
 	{
 		if(!strcmp(iep->filename, fname))
 		{
@@ -1473,19 +1431,20 @@
 	/* Undo the effect of the quotation */
 	fname[n-1] = '\0';
 
-	if((ppin = open_include(fname+1, type, &newpath)) == NULL)
+	if((ppin = pp_open_include(fname+1, type, &newpath)) == NULL)
 		pperror("Unable to open include file %s", fname+1);
 
 	fname[n-1] = *fname;	/* Redo the quotes */
 	push_buffer(NULL, newpath, fname, 0);
-	seen_junk = 0;
-	include_state = 0;
-	include_ppp = NULL;
+	pp_incl_state.seen_junk = 0;
+	pp_incl_state.state = 0;
+	pp_incl_state.ppp = NULL;
 	if (is_c_h_include(newpath)) pass_data=0;
 	else pass_data=1;
 
-	if(debuglevel & DEBUGLEVEL_PPMSG)
-		fprintf(stderr, "do_include: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d ,pass_data=%d\n", input_name, line_number, include_state, include_ppp, include_ifdepth,pass_data);
+	if(pp_status.debug)
+		fprintf(stderr, "pp_do_include: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d ,pass_data=%d\n",
+                        pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth, pass_data);
 	pp_switch_to_buffer(pp_create_buffer(ppin, YY_BUF_SIZE));
 
 	fprintf(ppout, "# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3");
@@ -1497,12 +1456,12 @@
  * which are false.
  *-------------------------------------------------------------------------
  */
-void push_ignore_state(void)
+void pp_push_ignore_state(void)
 {
 	yy_push_state(pp_ignore);
 }
 
-void pop_ignore_state(void)
+void pp_pop_ignore_state(void)
 {
 	yy_pop_state();
 }
diff --git a/tools/wrc/ppy.y b/tools/wpp/ppy.y
similarity index 85%
rename from tools/wrc/ppy.y
rename to tools/wpp/ppy.y
index 099a12b..8186be5 100644
--- a/tools/wrc/ppy.y
+++ b/tools/wpp/ppy.y
@@ -38,10 +38,7 @@
 #include <ctype.h>
 #include <string.h>
 
-#include "utils.h"
-#include "newstruc.h"
-#include "wrc.h"
-#include "preproc.h"
+#include "wpp_private.h"
 
 
 #define UNARY_OP(r, v, OP)					\
@@ -96,7 +93,7 @@
 	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);	\
+	default: pp_internal_error(__FILE__, __LINE__, "Invalid type indicator (0x%04x)", v1.type);	\
 	}
 
 
@@ -186,91 +183,93 @@
 	;
 
 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); }
+	: tINCLUDE tDQSTRING tNL	{ pp_do_include($2, 1); }
+	| tINCLUDE tIQSTRING tNL	{ pp_do_include($2, 0); }
+	| tIF pp_expr tNL	{ pp_next_if_state(boolean(&$2)); }
+	| tIFDEF tIDENT tNL	{ pp_next_if_state(pplookup($2) != NULL); free($2); }
 	| tIFNDEF tIDENT tNL	{
 		int t = pplookup($2) == NULL;
-		if(include_state == 0 && t && !seen_junk)
+		if(pp_incl_state.state == 0 && t && !pp_incl_state.seen_junk)
 		{
-			include_state	= 1;
-			include_ppp	= $2;
-			include_ifdepth	= get_if_depth();
+			pp_incl_state.state	= 1;
+			pp_incl_state.ppp	= $2;
+			pp_incl_state.ifdepth	= pp_get_if_depth();
 		}
-		else if(include_state != 1)
+		else if(pp_incl_state.state != 1)
 		{
-			include_state = -1;
+			pp_incl_state.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);
+		pp_next_if_state(t);
+		if(pp_status.debug)
+			fprintf(stderr, "tIFNDEF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
+                                pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth);
 		}
 	| tELIF pp_expr tNL	{
-		if_state_t s = pop_if();
+		pp_if_state_t s = pp_pop_if();
 		switch(s)
 		{
 		case if_true:
 		case if_elif:
-			push_if(if_elif);
+			pp_push_if(if_elif);
 			break;
 		case if_false:
-			push_if(boolean(&$2) ? if_true : if_false);
+			pp_push_if(boolean(&$2) ? if_true : if_false);
 			break;
 		case if_ignore:
-			push_if(if_ignore);
+			pp_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);
+			pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #elif directive", s);
 		}
 		}
 	| tELSE tNL		{
-		if_state_t s = pop_if();
+		pp_if_state_t s = pp_pop_if();
 		switch(s)
 		{
 		case if_true:
-			push_if(if_elsefalse);
+			pp_push_if(if_elsefalse);
 			break;
 		case if_elif:
-			push_if(if_elif);
+			pp_push_if(if_elif);
 			break;
 		case if_false:
-			push_if(if_elsetrue);
+			pp_push_if(if_elsetrue);
 			break;
 		case if_ignore:
-			push_if(if_ignore);
+			pp_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);
+			pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #else directive", s);
 		}
 		}
 	| tENDIF tNL		{
-		pop_if();
-		if(include_ifdepth == get_if_depth() && include_state == 1)
+		pp_pop_if();
+		if(pp_incl_state.ifdepth == pp_get_if_depth() && pp_incl_state.state == 1)
 		{
-			include_state = 2;
-			seen_junk = 0;
+			pp_incl_state.state = 2;
+			pp_incl_state.seen_junk = 0;
 		}
-		else if(include_state != 1)
+		else if(pp_incl_state.state != 1)
 		{
-			include_state = -1;
+			pp_incl_state.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);
+		if(pp_status.debug)
+			fprintf(stderr, "tENDIF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
+                                pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth);
 		}
-	| tUNDEF tIDENT tNL	{ del_define($2); free($2); }
-	| tDEFINE opt_text tNL	{ add_define($1, $2); }
+	| tUNDEF tIDENT tNL	{ pp_del_define($2); free($2); }
+	| tDEFINE opt_text tNL	{ pp_add_define($1, $2); }
 	| tMACRO res_arg allmargs tMACROEND opt_mtexts tNL	{
-		add_macro($1, macro_args, nmacro_args, $5);
+		pp_add_macro($1, macro_args, nmacro_args, $5);
 		}
 	| tLINE tSINT tDQSTRING	tNL	{ fprintf(ppout, "# %d %s\n", $2 , $3); free($3); }
 	| tGCCLINE tSINT tDQSTRING tNL	{ fprintf(ppout, "# %d %s\n", $2 , $3); free($3); }
@@ -285,17 +284,17 @@
 	| 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); }
+	| tPRAGMA opt_text tNL	{ if(pp_status.pedantic) ppwarning("#pragma ignored (arg: '%s')", $2); if($2) free($2); }
+	| tPPIDENT opt_text tNL	{ if(pp_status.pedantic) ppwarning("#ident ignored (arg: '%s')", $2); if($2) free($2); }
         | tRCINCLUDE tRCINCLUDEPATH {
                 int nl=strlen($2) +3;
-                char *fn=xmalloc(nl);
-                snprintf(fn,nl,"\"%s\"",$2);
+                char *fn=pp_xmalloc(nl);
+                sprintf(fn,"\"%s\"",$2);
 		free($2);
-		do_include(fn,1);
+		pp_do_include(fn,1);
 	}
 	| tRCINCLUDE tDQSTRING {
-		do_include($2,1);
+		pp_do_include($2,1);
 	}
 	/*| tNL*/
 	;
@@ -537,9 +536,10 @@
 
 static marg_t *new_marg(char *str, def_arg_t type)
 {
-	marg_t *ma = (marg_t *)xmalloc(sizeof(marg_t));
+	marg_t *ma = pp_xmalloc(sizeof(marg_t));
 	ma->arg = str;
 	ma->type = type;
+	ma->nnl = 0;
 	return ma;
 }
 
@@ -547,7 +547,7 @@
 {
 	marg_t *ma = new_marg(str, type);
 	nmacro_args++;
-	macro_args = (marg_t **)xrealloc(macro_args, nmacro_args * sizeof(macro_args[0]));
+	macro_args = pp_xrealloc(macro_args, nmacro_args * sizeof(macro_args[0]));
 	macro_args[nmacro_args-1] = ma;
 	return ma;
 }
@@ -565,12 +565,13 @@
 
 static mtext_t *new_mtext(char *str, int idx, def_exp_t type)
 {
-	mtext_t *mt = (mtext_t *)xmalloc(sizeof(mtext_t));
+	mtext_t *mt = pp_xmalloc(sizeof(mtext_t));
 	if(str == NULL)
 		mt->subst.argidx = idx;
 	else
 		mt->subst.text = str;
 	mt->type = type;
+	mt->next = mt->prev = NULL;
 	return mt;
 }
 
@@ -584,7 +585,7 @@
 
 	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);
+		tail->subst.text = pp_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);
@@ -650,7 +651,7 @@
 {
 	int l1 = strlen(s1);
 	int l2 = strlen(s2);
-	s1 = xrealloc(s1, l1+l2+1);
+	s1 = pp_xrealloc(s1, l1+l2+1);
 	memcpy(s1+l1, s2, l2+1);
 	free(s2);
 	return s1;
diff --git a/tools/wpp/preproc.c b/tools/wpp/preproc.c
new file mode 100644
index 0000000..8978c25
--- /dev/null
+++ b/tools/wpp/preproc.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "wpp_private.h"
+
+struct pp_status pp_status;
+
+#define HASHKEY		2039
+static pp_entry_t *pp_defines[HASHKEY];
+
+#define MAXIFSTACK	64
+static pp_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;
+	pp_entry_t *ppp;
+
+	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;
+		fprintf(stderr, "%4d, %3d\n", i, sum);
+	}
+	fprintf(stderr, "Total defines: %d\n", total);
+}
+#endif
+
+void *pp_xmalloc(size_t size)
+{
+    void *res;
+
+    assert(size > 0);
+    res = malloc(size);
+    if(res == NULL)
+    {
+        fprintf(stderr, "Virtual memory exhausted.\n");
+        exit(2);
+    }
+    return res;
+}
+
+void *pp_xrealloc(void *p, size_t size)
+{
+    void *res;
+
+    assert(size > 0);
+    res = realloc(p, size);
+    if(res == NULL)
+    {
+        fprintf(stderr, "Virtual memory exhausted.\n");
+        exit(2);
+    }
+    return res;
+}
+
+char *pp_xstrdup(const char *str)
+{
+	char *s;
+
+	assert(str != NULL);
+	s = pp_xmalloc(strlen(str)+1);
+	return strcpy(s, str);
+}
+
+/* Don't comment on the hash, its primitive but functional... */
+int pphash(char *str)
+{
+	int sum = 0;
+	while(*str)
+		sum += *str++;
+	return sum % HASHKEY;
+}
+
+pp_entry_t *pplookup(char *ident)
+{
+	int idx = pphash(ident);
+	pp_entry_t *ppp;
+
+	for(ppp = pp_defines[idx]; ppp; ppp = ppp->next)
+	{
+		if(!strcmp(ident, ppp->ident))
+			return ppp;
+	}
+	return NULL;
+}
+
+void pp_del_define(char *name)
+{
+	int idx;
+	pp_entry_t *ppp;
+
+	if((ppp = pplookup(name)) == NULL)
+	{
+		if(pp_status.pedantic)
+			ppwarning("%s was not defined", name);
+		return;
+	}
+
+	if(ppp->iep)
+	{
+		if(pp_status.debug)
+			fprintf(stderr, "pp_del_define: %s:%d: includelogic removed, include_ppp='%s', file=%s\n", pp_status.input, pp_status.line_number, name, ppp->iep->filename);
+		if(ppp->iep == pp_includelogiclist)
+		{
+			pp_includelogiclist = ppp->iep->next;
+			if(pp_includelogiclist)
+				pp_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
+	{
+		ppp->prev->next = ppp->next;
+		if(ppp->next)
+			ppp->next->prev = ppp->prev;
+	}
+
+	free(ppp);
+
+	if(pp_status.debug)
+		printf("Deleted (%s, %d) <%s>\n", pp_status.input, pp_status.line_number, name);
+}
+
+pp_entry_t *pp_add_define(char *def, char *text)
+{
+	int len;
+	char *cptr;
+	int idx = pphash(def);
+	pp_entry_t *ppp;
+
+	if((ppp = pplookup(def)) != NULL)
+	{
+		if(pp_status.pedantic)
+			ppwarning("Redefinition of %s\n\tPrevious definition: %s:%d", def, ppp->filename, ppp->linenumber);
+		pp_del_define(def);
+	}
+	ppp = pp_xmalloc(sizeof(pp_entry_t));
+	memset( ppp, 0, sizeof(*ppp) );
+	ppp->ident = def;
+	ppp->type = def_define;
+	ppp->subst.text = text;
+	ppp->filename = pp_status.input ? pp_xstrdup(pp_status.input) : "<internal or cmdline>";
+	ppp->linenumber = pp_status.input ? pp_status.line_number : 0;
+	ppp->next = pp_defines[idx];
+	pp_defines[idx] = ppp;
+	if(ppp->next)
+		ppp->next->prev = ppp;
+	if(text)
+	{
+		/* 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(text != cptr)
+			memmove(text, cptr, strlen(cptr)+1);
+	}
+	if(pp_status.debug)
+		printf("Added define (%s, %d) <%s> to <%s>\n", pp_status.input, pp_status.line_number, ppp->ident, text ? text : "(null)");
+
+	return ppp;
+}
+
+pp_entry_t *pp_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(pp_status.pedantic)
+			ppwarning("Redefinition of %s\n\tPrevious definition: %s:%d", id, ppp->filename, ppp->linenumber);
+		pp_del_define(id);
+	}
+	ppp = pp_xmalloc(sizeof(pp_entry_t));
+	memset( ppp, 0, sizeof(*ppp) );
+	ppp->ident	= id;
+	ppp->type	= def_macro;
+	ppp->margs	= args;
+	ppp->nargs	= nargs;
+	ppp->subst.mtext= exp;
+	ppp->filename = pp_status.input ? pp_xstrdup(pp_status.input) : "<internal or cmdline>";
+	ppp->linenumber = pp_status.input ? pp_status.line_number : 0;
+	ppp->next	= pp_defines[idx];
+	pp_defines[idx] = ppp;
+	if(ppp->next)
+		ppp->next->prev = ppp;
+
+	if(pp_status.debug)
+	{
+		fprintf(stderr, "Added macro (%s, %d) <%s(%d)> to <", pp_status.input, pp_status.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
+#define INCLUDESEPARATOR	":"
+#endif
+
+static char **includepath;
+static int nincludepath = 0;
+
+void wpp_add_include_path(const char *path)
+{
+	char *tok;
+	char *cpy = pp_xstrdup(path);
+
+	tok = strtok(cpy, INCLUDESEPARATOR);
+	while(tok)
+	{
+		char *dir;
+		char *cptr;
+		if(strlen(tok) == 0)
+			continue;
+		dir = pp_xstrdup(tok);
+		for(cptr = dir; *cptr; cptr++)
+		{
+			/* Convert to forward slash */
+			if(*cptr == '\\')
+				*cptr = '/';
+		}
+		/* Kill eventual trailing '/' */
+		if(*(cptr = dir + strlen(dir)-1) == '/')
+			*cptr = '\0';
+
+		/* Add to list */
+		nincludepath++;
+		includepath = pp_xrealloc(includepath, nincludepath * sizeof(*includepath));
+		includepath[nincludepath-1] = dir;
+		tok = strtok(NULL, INCLUDESEPARATOR);
+	}
+	free(cpy);
+}
+
+char *wpp_find_include(const char *name, int search)
+{
+    char *cpy = pp_xstrdup(name);
+    char *cptr;
+    int i, fd;
+
+    for(cptr = cpy; *cptr; cptr++)
+    {
+        /* kill double backslash */
+        if(*cptr == '\\' && *(cptr+1) == '\\')
+            memmove(cptr, cptr+1, strlen(cptr));
+        /* Convert to forward slash */
+        if(*cptr == '\\')
+            *cptr = '/';
+    }
+
+    if(search)
+    {
+        /* Search current dir and then -I path */
+        fd = open( cpy, O_RDONLY );
+        if (fd != -1)
+        {
+            close( fd );
+            return cpy;
+        }
+    }
+    /* Search -I path */
+    for(i = 0; i < nincludepath; i++)
+    {
+        char *path;
+        path = pp_xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
+        strcpy(path, includepath[i]);
+        strcat(path, "/");
+        strcat(path, cpy);
+        fd = open( path, O_RDONLY );
+        if (fd != -1)
+        {
+            close( fd );
+            free( cpy );
+            return path;
+        }
+        free( path );
+    }
+    free( cpy );
+    return NULL;
+}
+
+FILE *pp_open_include(const char *name, int search, char **newpath)
+{
+    char *path;
+    FILE *fp;
+
+    if (!(path = wpp_find_include( name, search ))) return NULL;
+    fp = fopen(path, "rt");
+
+    if (fp)
+    {
+        if (pp_status.debug)
+            printf("Going to include <%s>\n", path);
+        if (newpath) *newpath = path;
+        else free( path );
+        return fp;
+    }
+    free( path );
+    return NULL;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ * #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 *pp_if_state_str[] = {
+	"if_false",
+	"if_true",
+	"if_elif",
+	"if_elsefalse",
+	"if_elsetrue",
+	"if_ignore"
+};
+
+void pp_push_if(pp_if_state_t s)
+{
+	if(if_stack_idx >= MAXIFSTACK)
+		pp_internal_error(__FILE__, __LINE__, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK);
+
+	if(pp_flex_debug)
+		fprintf(stderr, "Push if %s:%d: %s(%d) -> %s(%d)\n", pp_status.input, pp_status.line_number, pp_if_state_str[pp_if_state()], if_stack_idx, pp_if_state_str[s], if_stack_idx+1);
+
+	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:
+		pp_push_ignore_state();
+		break;
+	}
+}
+
+pp_if_state_t pp_pop_if(void)
+{
+	if(if_stack_idx <= 0)
+		pperror("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
+
+	switch(pp_if_state())
+	{
+	case if_true:
+	case if_elsetrue:
+		break;
+	case if_false:
+	case if_elsefalse:
+	case if_elif:
+	case if_ignore:
+		pp_pop_ignore_state();
+		break;
+	}
+
+	if(pp_flex_debug)
+		fprintf(stderr, "Pop if %s:%d: %s(%d) -> %s(%d)\n",
+				pp_status.input,
+				pp_status.line_number,
+				pp_if_state_str[pp_if_state()],
+				if_stack_idx,
+				pp_if_state_str[if_stack[if_stack_idx <= 1 ? if_true : if_stack_idx-2]],
+				if_stack_idx-1);
+
+	return if_stack[--if_stack_idx];
+}
+
+pp_if_state_t pp_if_state(void)
+{
+	if(!if_stack_idx)
+		return if_true;
+	else
+		return if_stack[if_stack_idx-1];
+}
+
+
+void pp_next_if_state(int i)
+{
+	switch(pp_if_state())
+	{
+	case if_true:
+	case if_elsetrue:
+		pp_push_if(i ? if_true : if_false);
+		break;
+	case if_false:
+	case if_elsefalse:
+	case if_elif:
+	case if_ignore:
+		pp_push_if(if_ignore);
+		break;
+	default:
+		pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #{if,ifdef,ifndef} directive", (int)pp_if_state());
+	}
+}
+
+int pp_get_if_depth(void)
+{
+	return if_stack_idx;
+}
+
+/* #define WANT_NEAR_INDICATION */
+
+static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
+{
+	fprintf(stderr, "%s:%d:%d: %s: ", pp_status.input ? pp_status.input : "stdin",
+                pp_status.line_number, pp_status.char_number, t);
+	vfprintf(stderr, s, ap);
+#ifdef WANT_NEAR_INDICATION
+	{
+		char *cpy, *p;
+		if(n)
+		{
+			cpy = pp_xstrdup(n);
+			for (p = cpy; *p; p++) if(!isprint(*p)) *p = ' ';
+			fprintf(stderr, " near '%s'", cpy);
+			free(cpy);
+		}
+	}
+#endif
+	fprintf(stderr, "\n");
+}
+
+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 pp_internal_error(const char *file, int line, const char *s, ...)
+{
+	va_list ap;
+	va_start(ap, s);
+	fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
+	vfprintf(stderr, s, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+	exit(3);
+}
diff --git a/tools/wpp/wpp.c b/tools/wpp/wpp.c
new file mode 100644
index 0000000..239734b
--- /dev/null
+++ b/tools/wpp/wpp.c
@@ -0,0 +1,131 @@
+/*
+ * Exported functions of the Wine preprocessor
+ *
+ * Copyrignt 1998 Bertho A. Stultiens
+ * Copyright 2002 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <time.h>
+
+#include "wpp_private.h"
+#include "wpp.h"
+
+static void add_special_defines(void)
+{
+    time_t now = time(NULL);
+    pp_entry_t *ppp;
+    char buf[32];
+
+    strftime(buf, sizeof(buf), "\"%b %d %Y\"", localtime(&now));
+    pp_add_define( pp_xstrdup("__DATE__"), pp_xstrdup(buf) );
+
+    strftime(buf, sizeof(buf), "\"%H:%M:%S\"", localtime(&now));
+    pp_add_define( pp_xstrdup("__TIME__"), pp_xstrdup(buf) );
+
+    ppp = pp_add_define( pp_xstrdup("__FILE__"), pp_xstrdup("") );
+    ppp->type = def_special;
+
+    ppp = pp_add_define( pp_xstrdup("__LINE__"), pp_xstrdup("") );
+    ppp->type = def_special;
+}
+
+
+/* add a define to the preprocessor list */
+void wpp_add_define( const char *name, const char *value )
+{
+    if (!value) value = "";
+    pp_add_define( pp_xstrdup(name), pp_xstrdup(value) );
+}
+
+
+/* add a command-line define of the form NAME=VALUE */
+void wpp_add_cmdline_define( const char *value )
+{
+    char *str = pp_xstrdup(value);
+    char *p = strchr( str, '=' );
+    if (p) *p++ = 0;
+    else p = "";
+    pp_add_define( str, pp_xstrdup(p) );
+}
+
+
+/* set the various debug flags */
+void wpp_set_debug( int lex_debug, int parser_debug, int msg_debug )
+{
+    pp_flex_debug   = lex_debug;
+    ppdebug         = parser_debug;
+    pp_status.debug = msg_debug;
+}
+
+
+/* set the pedantic mode */
+void wpp_set_pedantic( int on )
+{
+    pp_status.pedantic = on;
+}
+
+
+/* the main preprocessor parsing loop */
+int wpp_parse( const char *input, FILE *output )
+{
+    int ret;
+
+    add_special_defines();
+
+    if (!input) ppin = stdin;
+    else if (!(ppin = fopen(input, "rt")))
+    {
+        fprintf(stderr,"Could not open %s\n", input);
+        exit(2);
+    }
+
+    pp_status.input = input;
+
+    ppout = output;
+    fprintf(ppout, "# 1 \"%s\" 1\n", input ? input : "");
+
+    ret = ppparse();
+
+    if (input) fclose(ppin);
+    return ret;
+}
+
+
+/* parse into a temporary file */
+int wpp_parse_temp( const char *input, char **output_name )
+{
+    char *temp_name;
+    FILE *output;
+    int ret;
+
+    if(!(temp_name = tmpnam(NULL)))
+    {
+        fprintf(stderr, "Could not generate a temp-name\n");
+        temp_name = pp_xstrdup(temp_name);
+    }
+
+    if (!(output = fopen(temp_name, "wt")))
+    {
+        fprintf(stderr,"Could not open %s for writing\n", temp_name);
+        exit(2);
+    }
+
+    *output_name = temp_name;
+    ret = wpp_parse( input, output );
+    fclose( output );
+    return ret;
+}
diff --git a/tools/wpp/wpp.h b/tools/wpp/wpp.h
new file mode 100644
index 0000000..1815ad6
--- /dev/null
+++ b/tools/wpp/wpp.h
@@ -0,0 +1,35 @@
+/*
+ * Exported functions of the Wine preprocessor
+ *
+ * Copyright 2002 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_WPP_H
+#define __WINE_WPP_H
+
+#include <stdio.h>
+
+extern void wpp_add_define( const char *name, const char *value );
+extern void wpp_add_cmdline_define( const char *value );
+extern void wpp_set_debug( int lex_debug, int parser_debug, int msg_debug );
+extern void wpp_set_pedantic( int on );
+extern void wpp_add_include_path( const char *path );
+extern char *wpp_find_include( const char *name, int search );
+extern int wpp_parse( const char *input, FILE *output );
+extern int wpp_parse_temp( const char *input, char **output_name );
+
+#endif  /* __WINE_WPP_H */
diff --git a/tools/wrc/preproc.h b/tools/wpp/wpp_private.h
similarity index 67%
rename from tools/wrc/preproc.h
rename to tools/wpp/wpp_private.h
index 0573e39..19b7e51 100644
--- a/tools/wrc/preproc.h
+++ b/tools/wpp/wpp_private.h
@@ -1,5 +1,6 @@
 /*
  * Copyright 1998 Bertho A. Stultiens (BS)
+ * Copyright 2002 Alexandre Julliard
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,8 +17,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef __WRC_PREPROC_H
-#define __WRC_PREPROC_H
+#ifndef __WINE_WPP_PRIVATE_H
+#define __WINE_WPP_PRIVATE_H
+
+#include <stdio.h>
+#include <string.h>
 
 struct pp_entry;	/* forward */
 /*
@@ -106,7 +110,27 @@
 	if_elsefalse,
 	if_elsetrue,
 	if_ignore
-} if_state_t;
+} pp_if_state_t;
+
+
+/*
+ * Trace the include files to prevent double reading.
+ * This save 20..30% of processing time for most stuff
+ * that uses complex includes.
+ * States:
+ * -1	Don't track or seen junk
+ *  0	New include, waiting for "#ifndef __xxx_h"
+ *  1	Seen #ifndef, waiting for "#define __xxx_h ..."
+ *  2	Seen #endif, waiting for EOF
+ */
+typedef struct
+{
+    int state;
+    char *ppp;             /* The define to be set from the #ifndef */
+    int ifdepth;           /* The level of ifs at the #ifdef */
+    int seen_junk;         /* Set when junk is seen */
+} include_state_t;
+
 
 /*
  * I assume that 'long long' exists in the compiler when it has a size
@@ -167,19 +191,42 @@
 
 
 
+void *pp_xmalloc(size_t);
+void *pp_xrealloc(void *, size_t);
+char *pp_xstrdup(const char *str);
 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);
-FILE *open_include(const char *name, int search, char **newpath);
-void add_include_path(char *path);
-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);
+pp_entry_t *pp_add_define(char *def, char *text);
+pp_entry_t *pp_add_macro(char *ident, marg_t *args[], int nargs, mtext_t *exp);
+void pp_del_define(char *name);
+FILE *pp_open_include(const char *name, int search, char **newpath);
+void pp_push_if(pp_if_state_t s);
+void pp_next_if_state(int);
+pp_if_state_t pp_pop_if(void);
+pp_if_state_t pp_if_state(void);
+int pp_get_if_depth(void);
+
+#ifndef __GNUC__
+#define __attribute__(x)  /*nothing*/
+#endif
+
+int pperror(const char *s, ...) __attribute__((format (printf, 1, 2)));
+int ppwarning(const char *s, ...) __attribute__((format (printf, 1, 2)));
+void pp_internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4)));
+
+/* current preprocessor state */
+/* everything is in this structure to avoid polluting the global symbol space */
+struct pp_status
+{
+    const char *input;  /* current input file name */
+    int line_number;    /* current line number */
+    int char_number;    /* current char number in line */
+    int pedantic;       /* pedantic option */
+    int debug;          /* debug messages flag */
+};
+
+extern struct pp_status pp_status;
+extern include_state_t pp_incl_state;
+extern includelogicentry_t *pp_includelogiclist;
 
 /*
  * From ppl.l
@@ -190,16 +237,10 @@
 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);
+void pp_do_include(char *fname, int type);
+void pp_push_ignore_state(void);
+void pp_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
@@ -207,5 +248,4 @@
 int ppparse(void);
 extern int ppdebug;
 
-#endif
-
+#endif  /* __WINE_WPP_PRIVATE_H */
diff --git a/tools/wrc/.cvsignore b/tools/wrc/.cvsignore
index 5bb0841..3604ec7 100644
--- a/tools/wrc/.cvsignore
+++ b/tools/wrc/.cvsignore
@@ -1,13 +1,7 @@
 Makefile
-lex.ppl.c
 lex.yy.c
-ppy.tab.c
-ppy.tab.h
 wrc
 y.tab.c
 y.tab.h
-ppy.tab.c
-ppy.tab.h
 y.output
-ppy.output
 lex.backup
diff --git a/tools/wrc/Makefile.in b/tools/wrc/Makefile.in
index a101e78..8cbd6f6 100644
--- a/tools/wrc/Makefile.in
+++ b/tools/wrc/Makefile.in
@@ -6,6 +6,8 @@
 LEXOPT    = -Cf #-w -b
 YACCOPT   = #-v
 EXEEXT    = @EXEEXT@
+EXTRAINCL = -I$(TOPSRCDIR)/tools/wpp
+EXTRALIBS = -L$(TOPOBJDIR)/tools/wpp -lwpp
 
 PROGRAMS = wrc$(EXEEXT)
 MODULE   = none
@@ -14,13 +16,11 @@
 	dumpres.c \
 	genres.c \
 	newstruc.c \
-	preproc.c \
 	readres.c \
 	utils.c \
 	wrc.c \
 	writeres.c
 
-GEN_C_SRCS = ppy.tab.c lex.ppl.c
 EXTRA_SRCS = parser.y parser.l
 EXTRA_OBJS = y.tab.o @LEX_OUTPUT_ROOT@.o
 
@@ -28,26 +28,20 @@
 
 @MAKE_RULES@
 
-wrc: $(OBJS)
-	$(CC) $(CFLAGS) -o wrc $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) $(LDFLAGS)
+wrc: $(OBJS) $(TOPOBJDIR)/tools/wpp/libwpp.a
+	$(CC) $(CFLAGS) -o wrc $(OBJS) $(EXTRALIBS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) $(LDFLAGS)
 
-wrc.exe: $(OBJS)
-	$(CC) $(CFLAGS) -o wrc.exe $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) -liberty $(LDFLAGS)
+wrc.exe: $(OBJS) $(TOPOBJDIR)/tools/wpp/libwpp.a
+	$(CC) $(CFLAGS) -o wrc.exe $(OBJS) $(EXTRALIBS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) -liberty $(LDFLAGS)
 
 y.tab.c y.tab.h: 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_OUTPUT_ROOT@.c: 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) ppy.tab.h ppy.output parser.output parser.tab.h lex.backup y.output
+	$(RM) parser.output parser.tab.h lex.backup y.output
 
 install:: $(PROGRAMS)
 	$(MKINSTALLDIRS) $(bindir) $(mandir)/man$(prog_manext)
diff --git a/tools/wrc/parser.l b/tools/wrc/parser.l
index d254402..0e5329c 100644
--- a/tools/wrc/parser.l
+++ b/tools/wrc/parser.l
@@ -102,7 +102,6 @@
 
 #include "wrc.h"
 #include "utils.h"
-#include "preproc.h"
 #include "parser.h"
 #include "newstruc.h"
 
diff --git a/tools/wrc/parser.y b/tools/wrc/parser.y
index 4ad3bd7..7cdcb82 100644
--- a/tools/wrc/parser.y
+++ b/tools/wrc/parser.y
@@ -136,7 +136,7 @@
 #include "utils.h"
 #include "newstruc.h"
 #include "dumpres.h"
-#include "preproc.h"
+#include "wpp.h"
 #include "parser.h"
 #include "windef.h"
 #include "winbase.h"
@@ -2278,14 +2278,17 @@
 /* Raw data functions */
 static raw_data_t *load_file(string_t *name)
 {
-	FILE *fp;
+	FILE *fp = NULL;
+	char *path;
 	raw_data_t *rd;
 	if(name->type != str_char)
 		yyerror("Filename must be ASCII string");
 
-	fp = open_include(name->str.cstr, 1, NULL);
-	if(!fp)
+	if (!(path = wpp_find_include(name->str.cstr, 1)))
 		yyerror("Cannot open file %s", name->str.cstr);
+	if (!(fp = fopen( path, "rb" )))
+		yyerror("Cannot open file %s", name->str.cstr);
+	free( path );
 	rd = new_raw_data();
 	fseek(fp, 0, SEEK_END);
 	rd->size = ftell(fp);
diff --git a/tools/wrc/preproc.c b/tools/wrc/preproc.c
deleted file mode 100644
index 8fda4ce..0000000
--- a/tools/wrc/preproc.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright 1998 Bertho A. Stultiens (BS)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "wrc.h"
-#include "utils.h"
-#include "preproc.h"
-
-
-#define HASHKEY		2039
-static pp_entry_t *pp_defines[HASHKEY];
-
-#define MAXIFSTACK	64
-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;
-	pp_entry_t *ppp;
-
-	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;
-		fprintf(stderr, "%4d, %3d\n", i, sum);
-	}
-	fprintf(stderr, "Total defines: %d\n", total);
-}
-#endif
-
-/* Don't comment on the hash, its primitive but functional... */
-int pphash(char *str)
-{
-	int sum = 0;
-	while(*str)
-		sum += *str++;
-	return sum % HASHKEY;
-}
-
-pp_entry_t *pplookup(char *ident)
-{
-	int idx = pphash(ident);
-	pp_entry_t *ppp;
-
-	for(ppp = pp_defines[idx]; ppp; ppp = ppp->next)
-	{
-		if(!strcmp(ident, ppp->ident))
-			return ppp;
-	}
-	return NULL;
-}
-
-void del_define(char *name)
-{
-	int idx;
-	pp_entry_t *ppp;
-
-	if((ppp = pplookup(name)) == NULL)
-	{
-		if(pedantic)
-			yywarning("%s was not defined", name);
-		return;
-	}
-
-	if(ppp->iep)
-	{
-		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
-	{
-		ppp->prev->next = ppp->next;
-		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);
-}
-
-pp_entry_t *add_define(char *def, char *text)
-{
-	int len;
-	char *cptr;
-	int idx = pphash(def);
-	pp_entry_t *ppp;
-
-	if((ppp = pplookup(def)) != NULL)
-	{
-		if(pedantic)
-			yywarning("Redefinition of %s\n\tPrevious definition: %s:%d", def, ppp->filename, ppp->linenumber);
-		del_define(def);
-	}
-	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;
-	if(text)
-	{
-		/* 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(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;
-}
-
-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';
-	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
-#define INCLUDESEPARATOR	":"
-#endif
-
-static char **includepath;
-static int nincludepath = 0;
-
-void add_include_path(char *path)
-{
-	char *tok;
-	char *cpy = xstrdup(path);
-
-	tok = strtok(cpy, INCLUDESEPARATOR);
-	while(tok)
-	{
-		char *dir;
-		char *cptr;
-		if(strlen(tok) == 0)
-			continue;
-		dir = xstrdup(tok);
-		for(cptr = dir; *cptr; cptr++)
-		{
-			/* Convert to forward slash */
-			if(*cptr == '\\')
-				*cptr = '/';
-		}
-		/* Kill eventual trailing '/' */
-		if(*(cptr = dir + strlen(dir)-1) == '/')
-			*cptr = '\0';
-
-		/* Add to list */
-		nincludepath++;
-		includepath = (char **)xrealloc(includepath, nincludepath * sizeof(*includepath));
-		includepath[nincludepath-1] = dir;
-		tok = strtok(NULL, INCLUDESEPARATOR);
-	}
-	free(cpy);
-}
-
-FILE *open_include(const char *name, int search, char **newpath)
-{
-	char *cpy = xstrdup(name);
-	char *cptr;
-	FILE *fp;
-	int i;
-
-	for(cptr = cpy; *cptr; cptr++)
-	{
-		/* kill double backslash */
-		if(*cptr == '\\' && *(cptr+1) == '\\')
-			memmove(cptr, cptr+1, strlen(cptr));
-		/* Convert to forward slash */
-		if(*cptr == '\\')
-			*cptr = '/';
-	}
-
-	if(search)
-	{
-		/* Search current dir and then -I path */
-		fp = fopen(cpy, "rt");
-		if(fp)
-		{
-			if(debuglevel & DEBUGLEVEL_PPMSG)
-				printf("Going to include <%s>\n", name);
-			if(newpath)
-				*newpath = cpy;
-			else
-				free(cpy);
-			return fp;
-		}
-	}
-	/* Search -I path */
-	for(i = 0; i < nincludepath; i++)
-	{
-		char *path;
-		path = (char *)xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
-		strcpy(path, includepath[i]);
-		strcat(path, "/");
-		strcat(path, cpy);
-		fp = fopen(path, "rt");
-		if(fp && (debuglevel & DEBUGLEVEL_PPMSG))
-			printf("Going to include <%s>\n", path);
-		if(fp)
-		{
-			if(newpath)
-				*newpath = path;
-			else
-				free(path);
-			free(cpy);
-			return fp;
-		}
-		free(path);
-	}
-	free(cpy);
-	if(newpath)
-		*newpath = NULL;
-	return NULL;
-}
-
-/*
- *-------------------------------------------------------------------------
- * #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(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;
-	}
-}
-
-if_state_t pop_if(void)
-{
-	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];
-}
-
-if_state_t if_state(void)
-{
-	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;
-}
-
diff --git a/tools/wrc/utils.c b/tools/wrc/utils.c
index d8db7a6..ab13429 100644
--- a/tools/wrc/utils.c
+++ b/tools/wrc/utils.c
@@ -33,7 +33,6 @@
 #include "wrc.h"
 #include "utils.h"
 #include "parser.h"
-#include "preproc.h"
 
 /* #define WANT_NEAR_INDICATION */
 
@@ -90,26 +89,6 @@
 	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;
diff --git a/tools/wrc/utils.h b/tools/wrc/utils.h
index 86de946..1324205 100644
--- a/tools/wrc/utils.h
+++ b/tools/wrc/utils.h
@@ -31,8 +31,6 @@
 void *xrealloc(void *, size_t);
 char *xstrdup(const char *str);
 
-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)));
diff --git a/tools/wrc/wrc.c b/tools/wrc/wrc.c
index 89855b7..9041c13 100644
--- a/tools/wrc/wrc.c
+++ b/tools/wrc/wrc.c
@@ -64,8 +64,8 @@
 #include "dumpres.h"
 #include "genres.h"
 #include "newstruc.h"
-#include "preproc.h"
 #include "parser.h"
+#include "wpp.h"
 
 static char usage[] =
 	"Usage: wrc [options...] [infile[.rc|.res]]\n"
@@ -342,7 +342,7 @@
 			debuglevel = strtol(optarg, NULL, 0);
 			break;
 		case 'D':
-			add_cmdline_define(optarg);
+			wpp_add_cmdline_define(optarg);
 			break;
 		case 'e':
 			extensions = 0;
@@ -360,7 +360,7 @@
 			create_header = 1;
 			break;
 		case 'I':
-			add_include_path(optarg);
+			wpp_add_include_path(optarg);
 			break;
 		case 'l':
 			{
@@ -419,6 +419,7 @@
 			break;
 		case 'W':
 			pedantic = 1;
+			wpp_set_pedantic(1);
 			break;
 		default:
 			lose++;
@@ -571,28 +572,25 @@
 
 	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;
+
+        wpp_set_debug( (debuglevel & DEBUGLEVEL_PPLEX) != 0,
+                       (debuglevel & DEBUGLEVEL_PPTRACE) != 0,
+                       (debuglevel & DEBUGLEVEL_PPMSG) != 0 );
 
 	/* Set the default defined stuff */
-	add_cmdline_define("__WRC__=" WRC_EXP_STRINGIZE(WRC_MAJOR_VERSION));
-	add_cmdline_define("__WRC_MINOR__=" WRC_EXP_STRINGIZE(WRC_MINOR_VERSION));
-	add_cmdline_define("__WRC_MICRO__=" WRC_EXP_STRINGIZE(WRC_MICRO_VERSION));
-	add_cmdline_define("__WRC_PATCH__=" WRC_EXP_STRINGIZE(WRC_MICRO_VERSION));
+	wpp_add_cmdline_define("__WRC__=" WRC_EXP_STRINGIZE(WRC_MAJOR_VERSION));
+	wpp_add_cmdline_define("__WRC_MINOR__=" WRC_EXP_STRINGIZE(WRC_MINOR_VERSION));
+	wpp_add_cmdline_define("__WRC_MICRO__=" WRC_EXP_STRINGIZE(WRC_MICRO_VERSION));
+	wpp_add_cmdline_define("__WRC_PATCH__=" WRC_EXP_STRINGIZE(WRC_MICRO_VERSION));
 
-	add_cmdline_define("RC_INVOKED=1");
+	wpp_add_cmdline_define("RC_INVOKED=1");
 
 	if(win32)
 	{
-		add_cmdline_define("__WIN32__=1");
-		add_cmdline_define("__FLAT__=1");
+		wpp_add_cmdline_define("__WIN32__=1");
+		wpp_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);
@@ -624,7 +622,6 @@
 	/* 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.
@@ -632,54 +629,32 @@
 
 		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");
+                if (!preprocess_only)
+                {
+                    atexit(rm_tempfile);
+                    ret = wpp_parse_temp( input_name, &temp_name );
+                }
+                else if (output_name)
+                {
+                    FILE *output;
 
-			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 (!(output = fopen( output_name, "w" )))
+                        error( "Could not open %s for writing\n", output_name );
+                    ret = wpp_parse( input_name, output );
+                    fclose( output );
+                }
+                else
+                {
+                    ret = wpp_parse( input_name, stdout );
+                }
 
 		if(ret)
 			exit(1);	/* Error during preprocess */
 
 		if(preprocess_only)
 			exit(0);
+
+		input_name = temp_name;
 	}
 
 	if(!binary)
@@ -761,4 +736,3 @@
 	fflush(stderr);
 	abort();
 }
-