PATCH: widl compiler from the rewind tree (Part 1)

Steven Edwards Steven_Ed4153 at yahoo.com
Sun Jun 30 15:03:40 CDT 2002


I saved you the trouble and added the LGPL license statement to the files.
 
Changelog: Merge of widl compiler from X11 fork.
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ ppl.l	Sun Jun 30 02:58:24 2002
@@ -0,0 +1,1510 @@
+/*
+ * Wrc preprocessor lexical analysis
+ *
+ * Copyright 1999-2000	Bertho A. Stultiens (BS)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * 24-Apr-2000 BS	- Started from scratch to restructure everything
+ *			  and reintegrate the source into the wine-tree.
+ * 04-Jan-2000 BS	- Added comments about the lexicographical
+ *			  grammar to give some insight in the complexity.
+ * 28-Dec-1999 BS	- Eliminated backing-up of the flexer by running
+ *			  `flex -b' on the source. This results in some
+ *			  weirdo extra rules, but a much faster scanner.
+ * 23-Dec-1999 BS	- Started this file
+ *
+ *-------------------------------------------------------------------------
+ * The preprocessor's lexographical grammar (approximately):
+ *
+ * pp		:= {ws} # {ws} if {ws} {expr} {ws} \n
+ *		|  {ws} # {ws} ifdef {ws} {id} {ws} \n
+ *		|  {ws} # {ws} ifndef {ws} {id} {ws} \n
+ *		|  {ws} # {ws} elif {ws} {expr} {ws} \n
+ *		|  {ws} # {ws} else {ws} \n
+ *		|  {ws} # {ws} endif {ws} \n
+ *		|  {ws} # {ws} include {ws} < {anytext} > \n
+ *		|  {ws} # {ws} include {ws} " {anytext} " \n
+ *		|  {ws} # {ws} define {ws} {anytext} \n
+ *		|  {ws} # {ws} define( {arglist} ) {ws} {expansion} \n
+ *		|  {ws} # {ws} pragma {ws} {anytext} \n
+ *		|  {ws} # {ws} ident {ws} {anytext} \n
+ *		|  {ws} # {ws} error {ws} {anytext} \n
+ *		|  {ws} # {ws} warning {ws} {anytext} \n
+ *		|  {ws} # {ws} line {ws} " {anytext} " {number} \n
+ *		|  {ws} # {ws} {number} " {anytext} " {number} [{number} [{number}]] \n
+ *		|  {ws} # {ws} \n
+ *
+ * ws		:= [ \t\r\f\v]*
+ *
+ * expr		:= {expr} [+-*%^/|&] {expr}
+ *		|  {expr} {logor|logand} {expr}
+ *		|  [!~+-] {expr}
+ *		|  {expr} ? {expr} : {expr}
+ *
+ * logor	:= ||
+ *
+ * logand	:= &&
+ *
+ * id		:= [a-zA-Z_][a-zA-Z0-9_]*
+ *
+ * anytext	:= [^\n]*	(see note)
+ *
+ * arglist	:=
+ *		|  {id}
+ *		|  {arglist} , {id}
+ *		|  {arglist} , {id} ...
+ *
+ * expansion	:= {id}
+ *		|  # {id}
+ *		|  {anytext}
+ *		|  {anytext} ## {anytext}
+ *
+ * number	:= [0-9]+
+ *
+ * Note: "anytext" is not always "[^\n]*". This is because the
+ *	 trailing context must be considered as well.
+ *
+ * The only certain assumption for the preprocessor to make is that
+ * directives start at the beginning of the line, followed by a '#'
+ * and end with a newline.
+ * Any directive may be suffixed with a line-continuation. Also
+ * classical comment / *...* / (note: no comments within comments,
+ * therefore spaces) is considered to be a line-continuation
+ * (according to gcc and egcs AFAIK, ANSI is a bit vague).
+ * Comments have not been added to the above grammer for simplicity
+ * reasons. However, it is allowed to enter comment anywhere within
+ * the directives as long as they do not interfere with the context.
+ * All comments are considered to be deletable whitespace (both
+ * classical form "/ *...* /" and C++ form "//...\n").
+ *
+ * All recursive scans, except for macro-expansion, are done by the
+ * parser, whereas the simple state transitions of non-recursive
+ * directives are done in the scanner. This results in the many
+ * exclusive start-conditions of the scanner.
+ *
+ * Macro expansions are slightly more difficult because they have to
+ * prescan the arguments. Parameter substitution is literal if the
+ * substitution is # or ## (either side). This enables new identifiers
+ * to be created (see 'info cpp' node Macro|Pitfalls|Prescan for more
+ * information).
+ *
+ * FIXME: Variable macro parameters is recognized, but not yet
+ * expanded. I have to reread the ANSI standard on the subject (yes,
+ * ANSI defines it).
+ *
+ * The following special defines are supported:
+ * __FILE__	-> "thissource.c"
+ * __LINE__	-> 123
+ * __DATE__	-> "May  1 2000"
+ * __TIME__	-> "23:59:59"
+ * These macros expand, as expected, into their ANSI defined values.
+ *
+ * The same include prevention is implemented as gcc and egcs does.
+ * This results in faster processing because we do not read the text
+ * at all. Some wine-sources attempt to include the same file 4 or 5
+ * times. This strategy also saves a lot blank output-lines, which in
+ * its turn improves the real resource scanner/parser.
+ *
+ */
+
+/*
+ * Special flex options and exclusive scanner start-conditions
+ */
+%option stack
+%option never-interactive
+
+%x pp_pp
+%x pp_eol
+%x pp_inc
+%x pp_dqs
+%x pp_sqs
+%x pp_iqs
+%x pp_comment
+%x pp_def
+%x pp_define
+%x pp_macro
+%x pp_mbody
+%x pp_macign
+%x pp_macscan
+%x pp_macexp
+%x pp_if
+%x pp_ifd
+%x pp_line
+%x pp_defined
+%x pp_ignore
+%x RCINCL
+
+ws	[ \v\f\t\r]
+cident	[a-zA-Z_][0-9a-zA-Z_]*
+ul	[uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL]
+
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "utils.h"
+#include "widl.h"
+#include "preproc.h"
+
+#include "ppy.tab.h"
+
+/*
+ * Make sure that we are running an appropriate version of flex.
+ */
+#if !defined(YY_FLEX_MAJOR_VERSION) || (1000 * YY_FLEX_MAJOR_VERSION + YY_FLEX_MINOR_VERSION < 2005)
+#error Must use flex version 2.5.1 or higher (yy_scan_* routines are required).
+#endif
+
+#define YY_USE_PROTOS
+#define YY_NO_UNPUT
+#define YY_READ_BUF_SIZE	65536		/* So we read most of a file at once */
+
+#define yy_current_state()	YY_START
+#define yy_pp_state(x)		yy_pop_state(); yy_push_state(x)
+
+/*
+ * Always update the current character position within a line
+ */
+#define YY_USER_ACTION	char_number+=ppleng;
+
+/*
+ * Buffer management for includes and expansions
+ */
+#define MAXBUFFERSTACK	128	/* Nesting more than 128 includes or macro expansion textss is insane */
+
+typedef struct bufferstackentry {
+	YY_BUFFER_STATE	bufferstate;	/* Buffer to switch back to */
+	pp_entry_t	*define;	/* Points to expanding define or NULL if handling includes */
+	int		line_number;	/* Line that we were handling */
+	int		char_number;	/* The current position on that line */
+	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;
+	int 		pass_data;
+} bufferstackentry_t;
+
+#define ALLOCBLOCKSIZE	(1 << 10)	/* Allocate these chunks at a time for string-buffers */
+
+/*
+ * Macro expansion nesting
+ * We need the stack to handle expansions while scanning
+ * a macro's arguments. The TOS must always be the macro
+ * that receives the current expansion from the scanner.
+ */
+#define MAXMACEXPSTACK	128	/* Nesting more than 128 macro expansions is insane */
+
+typedef struct macexpstackentry {
+	pp_entry_t	*ppp;		/* This macro we are scanning */
+	char		**args;		/* With these arguments */
+	char		**ppargs;	/* Resulting in these preprocessed arguments */
+	int		*nnls;		/* Number of newlines per argument */
+	int		nargs;		/* And this many arguments scanned */
+	int		parentheses;	/* Nesting level of () */
+	int		curargsize;	/* Current scanning argument's size */
+	int		curargalloc;	/* Current scanning argument's block allocated */
+	char		*curarg;	/* Current scanning argument's content */
+} macexpstackentry_t;
+
+#define MACROPARENTHESES()	(top_macro()->parentheses)
+
+/*
+ * Prototypes
+ */
+static void newline(int);
+static int make_number(int radix, YYSTYPE *val, char *str, int len);
+static void put_buffer(char *s, int len);
+/* Buffer management */
+static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop);
+static bufferstackentry_t *pop_buffer(void);
+/* String functions */
+static void new_string(void);
+static void add_string(char *str, int len);
+static char *get_string(void);
+static void put_string(void);
+static int string_start(void);
+/* Macro functions */
+static void push_macro(pp_entry_t *ppp);
+static macexpstackentry_t *top_macro(void);
+static macexpstackentry_t *pop_macro(void);
+static void free_macro(macexpstackentry_t *mep);
+static void add_text_to_macro(char *text, int len);
+static void macro_add_arg(int last);
+static void macro_add_expansion(void);
+/* Expansion */
+static void expand_special(pp_entry_t *ppp);
+static void expand_define(pp_entry_t *ppp);
+static void expand_macro(macexpstackentry_t *mep);
+
+/*
+ * Local variables
+ */
+static int ncontinuations;
+
+static int strbuf_idx = 0;
+static int strbuf_alloc = 0;
+static char *strbuffer = NULL;
+static int str_startline;
+
+static macexpstackentry_t *macexpstack[MAXMACEXPSTACK];
+static int macexpstackidx = 0;
+
+static bufferstackentry_t bufferstack[MAXBUFFERSTACK];
+static int bufferstackidx = 0;
+
+static int pass_data=1;
+
+/*
+ * Global variables
+ */
+/*
+ * 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;
+
+%}
+
+/*
+ **************************************************************************
+ * The scanner starts here
+ **************************************************************************
+ */
+
+%%
+	/*
+	 * Catch line-continuations.
+	 * Note: Gcc keeps the line-continuations in, for example, strings
+	 * intact. However, I prefer to remove them all so that the next
+	 * scanner will not need to reduce the continuation state.
+	 *
+	 * <*>\\\n		newline(0);
+	 */
+
+	/*
+	 * Detect the leading # of a preprocessor directive.
+	 */
+<INITIAL,pp_ignore>^{ws}*#	seen_junk++; yy_push_state(pp_pp);
+
+	/*
+	 * Scan for the preprocessor directives
+	 */
+<pp_pp>{ws}*include{ws}*	if(yy_top_state() != pp_ignore) {yy_pp_state(pp_inc); return tINCLUDE;} else {yy_pp_state(pp_eol);}
+<pp_pp>{ws}*define{ws}*		yy_pp_state(yy_current_state() != pp_ignore ? pp_def : pp_eol);
+<pp_pp>{ws}*error{ws}*		yy_pp_state(pp_eol);	if(yy_top_state() != pp_ignore) return tERROR;
+<pp_pp>{ws}*warning{ws}*	yy_pp_state(pp_eol);	if(yy_top_state() != pp_ignore) return tWARNING;
+<pp_pp>{ws}*pragma{ws}*		yy_pp_state(pp_eol);	if(yy_top_state() != pp_ignore) return tPRAGMA;
+<pp_pp>{ws}*ident{ws}*		yy_pp_state(pp_eol);	if(yy_top_state() != pp_ignore) return tPPIDENT;
+<pp_pp>{ws}*undef{ws}*		if(yy_top_state() != pp_ignore) {yy_pp_state(pp_ifd); return tUNDEF;} else {yy_pp_state(pp_eol);}
+<pp_pp>{ws}*ifdef{ws}*		yy_pp_state(pp_ifd);	return tIFDEF;
+<pp_pp>{ws}*ifndef{ws}*		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;
+<pp_pp>{ws}*endif{ws}*		return tENDIF;
+<pp_pp>{ws}*line{ws}*		if(yy_top_state() != pp_ignore) {yy_pp_state(pp_line); return tLINE;} else {yy_pp_state(pp_eol);}
+<pp_pp>{ws}+			if(yy_top_state() != pp_ignore) {yy_pp_state(pp_line); return tGCCLINE;} else {yy_pp_state(pp_eol);}
+<pp_pp>{ws}*[a-z]+		pperror("Invalid preprocessor token '%s'", pptext);
+<pp_pp>\r?\n			newline(1); yy_pop_state(); return tNL;	/* This could be the null-token */
+<pp_pp>\\\r?\n			newline(0);
+<pp_pp>\\\r?			pperror("Preprocessor junk '%s'", pptext);
+<pp_pp>.			return *pptext;
+
+	/*
+	 * Handle #include and #line
+	 */
+<pp_line>[0-9]+			return make_number(10, &pplval, pptext, ppleng);
+<pp_inc>\<			new_string(); add_string(pptext, ppleng); yy_push_state(pp_iqs);
+<pp_inc,pp_line>\"		new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs);
+<pp_inc,pp_line>{ws}+		;
+<pp_inc,pp_line>\n		newline(1); yy_pop_state(); return tNL;
+<pp_inc,pp_line>\\\r?\n		newline(0);
+<pp_inc,pp_line>(\\\r?)|(.)	pperror(yy_current_state() == pp_inc ? "Trailing junk in #include" : "Trailing junk in #line");
+
+	/*
+	 * Ignore all input when a false clause is parsed
+	 */
+<pp_ignore>[^#/\\\n]+		;
+<pp_ignore>\n			newline(1);
+<pp_ignore>\\\r?\n		newline(0);
+<pp_ignore>(\\\r?)|(.)		;
+
+	/*
+	 * Handle #if and #elif.
+	 * These require conditionals to be evaluated, but we do not
+	 * want to jam the scanner normally when we see these tokens.
+	 * Note: tIDENT is handled below.
+	 */
+
+<pp_if>0[0-7]*{ul}?		return make_number(8, &pplval, pptext, ppleng);
+<pp_if>0[0-7]*[8-9]+{ul}?	pperror("Invalid octal digit");
+<pp_if>[1-9][0-9]*{ul}?		return make_number(10, &pplval, pptext, ppleng);
+<pp_if>0[xX][0-9a-fA-F]+{ul}?	return make_number(16, &pplval, pptext, ppleng);
+<pp_if>0[xX]			pperror("Invalid hex number");
+<pp_if>defined			yy_push_state(pp_defined); return tDEFINED;
+<pp_if>"<<"			return tLSHIFT;
+<pp_if>">>"			return tRSHIFT;
+<pp_if>"&&"			return tLOGAND;
+<pp_if>"||"			return tLOGOR;
+<pp_if>"=="			return tEQ;
+<pp_if>"!="			return tNE;
+<pp_if>"<="			return tLTE;
+<pp_if>">="			return tGTE;
+<pp_if>\n			newline(1); yy_pop_state(); return tNL;
+<pp_if>\\\r?\n			newline(0);
+<pp_if>\\\r?			pperror("Junk in conditional expression");
+<pp_if>{ws}+			;
+<pp_if>\'			new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
+<pp_if>\"			pperror("String constants not allowed in conditionals");
+<pp_if>.			return *pptext;
+
+	/*
+	 * Handle #ifdef, #ifndef and #undef
+	 * to get only an untranslated/unexpanded identifier
+	 */
+<pp_ifd>{cident}	pplval.cptr = xstrdup(pptext); return tIDENT;
+<pp_ifd>{ws}+		;
+<pp_ifd>\n		newline(1); yy_pop_state(); return tNL;
+<pp_ifd>\\\r?\n		newline(0);
+<pp_ifd>(\\\r?)|(.)	pperror("Identifier expected");
+
+	/*
+	 * Handle the special 'defined' keyword.
+	 * 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>{ws}+		;
+<pp_defined>(\()|(\))		return *pptext;
+<pp_defined>\\\r?\n		newline(0);
+<pp_defined>(\\.)|(\n)|(.)	pperror("Identifier expected");
+
+	/*
+	 * Handle #error, #warning, #pragma and #ident.
+	 * Pass everything literally to the parser, which
+	 * will act appropriately.
+	 * Comments are stripped from the literal text.
+	 */
+<pp_eol>[^/\\\n]+		if(yy_top_state() != pp_ignore) { pplval.cptr = 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			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>{ws}+			;
+<pp_def>\\\r?\n			newline(0);
+<pp_def>(\\\r?)|(\n)|(.)	perror("Identifier expected");
+
+	/*
+	 * Scan the substitution of a define
+	 */
+<pp_define>[^'"/\\\n]+		pplval.cptr = 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>\\\r?\n		newline(0);
+<pp_define>\n			newline(1); yy_pop_state(); return tNL;
+<pp_define>\'			new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
+<pp_define>\"			new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs);
+
+	/*
+	 * Scan the definition macro arguments
+	 */
+<pp_macro>\){ws}*		yy_pp_state(pp_mbody); return tMACROEND;
+<pp_macro>{ws}+			;
+<pp_macro>{cident}		pplval.cptr = xstrdup(pptext); return tIDENT;
+<pp_macro>,			return ',';
+<pp_macro>"..."			return tELIPSIS;
+<pp_macro>(\\\r?)|(\n)|(.)|(\.\.?)	pperror("Argument identifier expected");
+<pp_macro>\\\r?\n		newline(0);
+
+	/*
+	 * Scan the substitution of a macro
+	 */
+<pp_mbody>[^a-zA-Z0-9'"#/\\\n]+	pplval.cptr = xstrdup(pptext); return tLITERAL;
+<pp_mbody>{cident}		pplval.cptr = 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>\\\r?\n		newline(0);
+<pp_mbody>\n			newline(1); yy_pop_state(); return tNL;
+<pp_mbody>\'			new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
+<pp_mbody>\"			new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs);
+
+	/*
+	 * Macro expansion text scanning.
+	 * This state is active just after the identifier is scanned
+	 * that triggers an expansion. We *must* delete the leading
+	 * whitespace before we can start scanning for arguments.
+	 *
+	 * If we do not see a '(' as next trailing token, then we have
+	 * a false alarm. We just continue with a nose-bleed...
+	 */
+<pp_macign>{ws}*/\(	yy_pp_state(pp_macscan);
+<pp_macign>{ws}*\n	{
+		if(yy_top_state() != pp_macscan)
+			newline(0);
+	}
+<pp_macign>{ws}*\\\r?\n	newline(0);
+<pp_macign>{ws}+|{ws}*\\\r?|.	{
+		macexpstackentry_t *mac = pop_macro();
+		yy_pop_state();
+		put_buffer(mac->ppp->ident, strlen(mac->ppp->ident));
+		put_buffer(pptext, ppleng);
+		free_macro(mac);
+	}
+
+	/*
+	 * Macro expansion argument text scanning.
+	 * This state is active when a macro's arguments are being read for expansion.
+	 */
+<pp_macscan>\(	{
+		if(++MACROPARENTHESES() > 1)
+			add_text_to_macro(pptext, ppleng);
+	}
+<pp_macscan>\)	{
+		if(--MACROPARENTHESES() == 0)
+		{
+			yy_pop_state();
+			macro_add_arg(1);
+		}
+		else
+			add_text_to_macro(pptext, ppleng);
+	}
+<pp_macscan>,		{
+		if(MACROPARENTHESES() > 1)
+			add_text_to_macro(pptext, ppleng);
+		else
+			macro_add_arg(0);
+	}
+<pp_macscan>\"		new_string(); add_string(pptext, ppleng); yy_push_state(pp_dqs);
+<pp_macscan>\'		new_string(); add_string(pptext, ppleng); yy_push_state(pp_sqs);
+<pp_macscan>"/*"	yy_push_state(pp_comment); add_text_to_macro(" ", 1);
+<pp_macscan>\n		line_number++; char_number = 1; add_text_to_macro(pptext, ppleng);
+<pp_macscan>([^/(),\\\n"']+)|(\/[^/*(),\\\n'"]*)|(\\\r?)|(.)	add_text_to_macro(pptext, ppleng);
+<pp_macscan>\\\r?\n	newline(0);
+
+	/*
+	 * Comment handling (almost all start-conditions)
+	 */
+<INITIAL,pp_pp,pp_ignore,pp_eol,pp_inc,pp_if,pp_ifd,pp_defined,pp_def,pp_define,pp_macro,pp_mbody,RCINCL>"/*" yy_push_state(pp_comment);
+<pp_comment>[^*\n]*|"*"+[^*/\n]*	;
+<pp_comment>\n				newline(0);
+<pp_comment>"*"+"/"			yy_pop_state();
+
+	/*
+	 * Remove C++ style comment (almost all start-conditions)
+	 */
+<INITIAL,pp_pp,pp_ignore,pp_eol,pp_inc,pp_if,pp_ifd,pp_defined,pp_def,pp_define,pp_macro,pp_mbody,pp_macscan,RCINCL>"//"[^\n]*	{
+		if(pptext[ppleng-1] == '\\')
+			ppwarning("C++ style comment ends with an escaped newline (escape ignored)");
+	}
+
+	/*
+	 * Single, double and <> quoted constants
+	 */
+<INITIAL,pp_macexp>\"		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);
+<pp_dqs>[^"\\\n]+		add_string(pptext, ppleng);
+<pp_dqs>\"			{
+		add_string(pptext, ppleng);
+		yy_pop_state();
+		switch(yy_current_state())
+		{
+		case pp_pp:
+		case pp_define:
+		case pp_mbody:
+		case pp_inc:
+		case pp_line:
+		case RCINCL:
+			if (yy_current_state()==RCINCL) yy_pop_state();
+			pplval.cptr = get_string();
+			return tDQSTRING;
+		default:
+			put_string();
+		}
+	}
+<pp_sqs>[^'\\\n]+		add_string(pptext, ppleng);
+<pp_sqs>\'			{
+		add_string(pptext, ppleng);
+		yy_pop_state();
+		switch(yy_current_state())
+		{
+		case pp_if:
+		case pp_define:
+		case pp_mbody:
+			pplval.cptr = get_string();
+			return tSQSTRING;
+		default:
+			put_string();
+		}
+	}
+<pp_iqs>[^\>\\\n]+		add_string(pptext, ppleng);
+<pp_iqs>\>			{
+		add_string(pptext, ppleng);
+		yy_pop_state();
+		pplval.cptr = get_string();
+		return tIQSTRING;
+	}
+<pp_dqs>\\\r?\n		{
+		/*
+		 * This is tricky; we need to remove the line-continuation
+		 * from preprocessor strings, but OTOH retain them in all
+		 * other strings. This is because the resource grammar is
+		 * even more braindead than initially analysed and line-
+		 * continuations in strings introduce, sigh, newlines in
+		 * the output. There goes the concept of non-breaking, non-
+		 * spacing whitespace.
+		 */
+		switch(yy_top_state())
+		{
+		case pp_pp:
+		case pp_define:
+		case pp_mbody:
+		case pp_inc:
+		case pp_line:
+			newline(0);
+			break;
+		default:
+			add_string(pptext, ppleng);
+			newline(-1);
+		}
+	}
+<pp_iqs,pp_dqs,pp_sqs>\\.	add_string(pptext, ppleng);
+<pp_iqs,pp_dqs,pp_sqs>\n	{
+		newline(1);
+		add_string(pptext, ppleng);
+		ppwarning("Newline in string constant encounterd (started line %d)", string_start());
+	}
+
+	/*
+	 * Identifier scanning
+	 */
+<INITIAL,pp_if,pp_inc,pp_macexp>{cident}	{
+		pp_entry_t *ppp;
+		seen_junk++;
+		if(!(ppp = pplookup(pptext)))
+		{
+			if(yy_current_state() == pp_inc)
+				pperror("Expected include filename");
+
+			if(yy_current_state() == pp_if)
+			{
+				pplval.cptr = xstrdup(pptext);
+				return tIDENT;
+			}
+			else {
+				if((yy_current_state()==INITIAL) && (strcasecmp(pptext,"RCINCLUDE")==0)){
+					yy_push_state(RCINCL);
+					return tRCINCLUDE;
+				}
+				else put_buffer(pptext, ppleng);
+			}
+		}
+		else if(!ppp->expanding)
+		{
+			switch(ppp->type)
+			{
+			case def_special:
+				expand_special(ppp);
+				break;
+			case def_define:
+				expand_define(ppp);
+				break;
+			case def_macro:
+				yy_push_state(pp_macign);
+				push_macro(ppp);
+				break;
+			default:
+				internal_error(__FILE__, __LINE__, "Invalid define type %d\n", ppp->type);
+			}
+		}
+	}
+
+	/*
+	 * Everything else that needs to be passed and
+	 * newline and continuation handling
+	 */
+<INITIAL,pp_macexp>[^a-zA-Z_#'"/\\\n \r\t\f\v]+|(\/|\\)[^a-zA-Z_/*'"\\\n \r\t\v\f]*	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);
+
+	/*
+	 * Special catcher for macro argmument expansion to prevent
+	 * newlines to propagate to the output or admin.
+	 */
+<pp_macexp>(\n)|(.)|(\\\r?(\n|.))	put_buffer(pptext, ppleng);
+
+<RCINCL>[A-Za-z0-9_\.\\/]+ {
+		pplval.cptr=xstrdup(pptext);
+        	yy_pop_state();
+		return tRCINCLUDEPATH;
+	}
+
+<RCINCL>{ws}+ ;
+
+<RCINCL>\"		{
+		new_string(); add_string(pptext,ppleng);yy_push_state(pp_dqs);
+	}
+
+	/*
+	 * This is a 'catch-all' rule to discover errors in the scanner
+	 * in an orderly manner.
+	 */
+<*>.		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))
+			ppwarning("Unmatched #if/#endif at end of file");
+
+		if(!bep)
+		{
+			if(YY_START != INITIAL)
+				pperror("Unexpected end of file during preprocessing");
+			yyterminate();
+		}
+		else if(bep->should_pop == 2)
+		{
+			macexpstackentry_t *mac;
+			mac = pop_macro();
+			expand_macro(mac);
+		}
+		pp_delete_buffer(b);
+	}
+
+%%
+/*
+ **************************************************************************
+ * Support functions
+ **************************************************************************
+ */
+
+#ifndef ppwrap
+int ppwrap(void)
+{
+	return 1;
+}
+#endif
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Output newlines or set them as continuations
+ *
+ * Input: -1 - Don't count this one, but update local position (see pp_dqs)
+ *	   0 - Line-continuation seen and cache output
+ *	   1 - Newline seen and flush output
+ *-------------------------------------------------------------------------
+ */
+static void newline(int dowrite)
+{
+	line_number++;
+	char_number = 1;
+
+	if(dowrite == -1)
+		return;
+
+	ncontinuations++;
+	if(dowrite)
+	{
+		for(;ncontinuations; ncontinuations--)
+			put_buffer("\n", 1);
+	}
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Make a number out of an any-base and suffixed string
+ *
+ * Possible number extensions:
+ * - ""		int
+ * - "L"	long int
+ * - "LL"	long long int
+ * - "U"	unsigned int
+ * - "UL"	unsigned long int
+ * - "ULL"	unsigned long long int
+ * - "LU"	unsigned long int
+ * - "LLU"	unsigned long long int
+ * - "LUL"	invalid
+ *
+ * FIXME:
+ * The sizes of resulting 'int' and 'long' are compiler specific.
+ * I depend on sizeof(int) > 2 here (although a relatively safe
+ * assumption).
+ * Long longs are not yet implemented because this is very compiler
+ * specific and I don't want to think too much about the problems.
+ *
+ *-------------------------------------------------------------------------
+ */
+static int make_number(int radix, YYSTYPE *val, char *str, int len)
+{
+	int is_l  = 0;
+	int is_ll = 0;
+	int is_u  = 0;
+	char ext[4];
+
+	ext[3] = '\0';
+	ext[2] = toupper(str[len-1]);
+	ext[1] = len > 1 ? toupper(str[len-2]) : ' ';
+	ext[0] = len > 2 ? toupper(str[len-3]) : ' ';
+
+	if(!strcmp(ext, "LUL"))
+		pperror("Invalid constant suffix");
+	else if(!strcmp(ext, "LLU") || !strcmp(ext, "ULL"))
+	{
+		is_ll++;
+		is_u++;
+	}
+	else if(!strcmp(ext+1, "LU") || !strcmp(ext+1, "UL"))
+	{
+		is_l++;
+		is_u++;
+	}
+	else if(!strcmp(ext+1, "LL"))
+	{
+		is_ll++;
+	}
+	else if(!strcmp(ext+2, "L"))
+	{
+		is_l++;
+	}
+	else if(!strcmp(ext+2, "U"))
+	{
+		is_u++;
+	}
+
+	if(is_ll)
+		internal_error(__FILE__, __LINE__, "long long constants not implemented yet");
+
+	if(is_u && is_l)
+	{
+		val->ulong = strtoul(str, NULL, radix);
+		return tULONG;
+	}
+	else if(!is_u && is_l)
+	{
+		val->slong = strtol(str, NULL, radix);
+		return tSLONG;
+	}
+	else if(is_u && !is_l)
+	{
+		val->uint = (unsigned int)strtoul(str, NULL, radix);
+		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;
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Macro and define expansion support
+ *
+ * FIXME: Variable macro arguments.
+ *-------------------------------------------------------------------------
+ */
+static void expand_special(pp_entry_t *ppp)
+{
+	char *dbgtext = "?";
+	static char *buf = NULL;
+
+	assert(ppp->type == def_special);
+
+	if(!strcmp(ppp->ident, "__LINE__"))
+	{
+		dbgtext = "def_special(__LINE__)";
+		buf = xrealloc(buf, 32);
+		sprintf(buf, "%d", 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));
+	}
+	else
+		internal_error(__FILE__, __LINE__, "Special macro '%s' not found...\n", ppp->ident);
+
+	if(debuglevel & DEBUGLEVEL_PPLEX)
+		fprintf(stderr, "expand_special(%d): %s:%d: '%s' -> '%s'\n",
+			macexpstackidx,
+			input_name,
+			line_number,
+			ppp->ident,
+			buf ? buf : "");
+
+	if(buf && buf[0])
+	{
+		push_buffer(ppp, NULL, NULL, 0);
+		yy_scan_string(buf);
+	}
+}
+
+static void expand_define(pp_entry_t *ppp)
+{
+	assert(ppp->type == def_define);
+
+	if(debuglevel & DEBUGLEVEL_PPLEX)
+		fprintf(stderr, "expand_define(%d): %s:%d: '%s' -> '%s'\n",
+			macexpstackidx,
+			input_name,
+			line_number,
+			ppp->ident,
+			ppp->subst.text);
+	if(ppp->subst.text && ppp->subst.text[0])
+	{
+		push_buffer(ppp, NULL, NULL, 0);
+		yy_scan_string(ppp->subst.text);
+	}
+}
+
+static int curdef_idx = 0;
+static int curdef_alloc = 0;
+static char *curdef_text = NULL;
+
+static void add_text(char *str, int len)
+{
+	if(len == 0)
+		return;
+	if(curdef_idx >= curdef_alloc || curdef_alloc - curdef_idx < len)
+	{
+		curdef_alloc += (len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1);
+		curdef_text = xrealloc(curdef_text, curdef_alloc * sizeof(curdef_text[0]));
+		if(curdef_alloc > 65536)
+			ppwarning("Reallocating macro-expansion buffer larger than 64kB");
+	}
+	memcpy(&curdef_text[curdef_idx], str, len);
+	curdef_idx += len;
+}
+
+static mtext_t *add_expand_text(mtext_t *mtp, macexpstackentry_t *mep, int *nnl)
+{
+	char *cptr;
+	char *exp;
+	int tag;
+	int n;
+
+	if(mtp == NULL)
+		return NULL;
+
+	switch(mtp->type)
+	{
+	case exp_text:
+		if(debuglevel & DEBUGLEVEL_PPLEX)
+			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)
+			fprintf(stderr, "add_expand_text: exp_stringize(%d): '%s'\n",
+				mtp->subst.argidx,
+				mep->args[mtp->subst.argidx]);
+		cptr = mep->args[mtp->subst.argidx];
+		add_text("\"", 1);
+		while(*cptr)
+		{
+			if(*cptr == '"' || *cptr == '\\')
+				add_text("\\", 1);
+			add_text(cptr, 1);
+			cptr++;
+		}
+		add_text("\"", 1);
+		break;
+
+	case exp_concat:
+		if(debuglevel & DEBUGLEVEL_PPLEX)
+			fprintf(stderr, "add_expand_text: exp_concat\n");
+		/* Remove trailing whitespace from current expansion text */
+		while(curdef_idx)
+		{
+			if(isspace(curdef_text[curdef_idx-1] & 0xff))
+				curdef_idx--;
+			else
+				break;
+		}
+		/* tag current position and recursively expand the next part */
+		tag = curdef_idx;
+		mtp = add_expand_text(mtp->next, mep, nnl);
+
+		/* Now get rid of the leading space of the expansion */
+		cptr = &curdef_text[tag];
+		n = curdef_idx - tag;
+		while(n)
+		{
+			if(isspace(*cptr & 0xff))
+			{
+				cptr++;
+				n--;
+			}
+			else
+				break;
+		}
+		if(cptr != &curdef_text[tag])
+		{	
+			memmove(&curdef_text[tag], cptr, n);
+			curdef_idx -= (curdef_idx - tag) - n;
+		}
+		break;
+
+	case exp_subst:
+		if((mtp->next && mtp->next->type == exp_concat) || (mtp->prev && mtp->prev->type == exp_concat))
+			exp = mep->args[mtp->subst.argidx];
+		else
+			exp = mep->ppargs[mtp->subst.argidx];
+		if(exp)
+		{
+			add_text(exp, strlen(exp));
+			*nnl -= mep->nnls[mtp->subst.argidx];
+			cptr = strchr(exp, '\n');
+			while(cptr)
+			{
+				*cptr = ' ';
+				cptr = strchr(cptr+1, '\n');
+			}
+			mep->nnls[mtp->subst.argidx] = 0;
+		}
+		if(debuglevel & DEBUGLEVEL_PPLEX)
+			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);
+	}
+	return mtp;
+}
+
+static void expand_macro(macexpstackentry_t *mep)
+{
+	mtext_t *mtp;
+	int n, k;
+	char *cptr;
+	int nnl = 0;
+	pp_entry_t *ppp = mep->ppp;
+	int nargs = mep->nargs;
+
+	assert(ppp->type == def_macro);
+	assert(ppp->expanding == 0);
+
+	if((ppp->nargs >= 0 && nargs != ppp->nargs) || (ppp->nargs < 0 && nargs < -ppp->nargs))
+		pperror("Too %s macro arguments (%d)", nargs < abs(ppp->nargs) ? "few" : "many", nargs);
+
+	for(n = 0; n < nargs; n++)
+		nnl += mep->nnls[n];
+
+	if(debuglevel & DEBUGLEVEL_PPLEX)
+		fprintf(stderr, "expand_macro(%d): %s:%d: '%s'(%d,%d) -> ...\n",
+			macexpstackidx,
+			input_name,
+			line_number,
+			ppp->ident,
+			mep->nargs,
+			nnl);
+
+	curdef_idx = 0;
+
+	for(mtp = ppp->subst.mtext; mtp; mtp = mtp->next)
+	{
+		if(!(mtp = add_expand_text(mtp, mep, &nnl)))
+			break;
+	}
+
+	for(n = 0; n < nnl; n++)
+		add_text("\n", 1);
+
+	/* To make sure there is room and termination (see below) */
+	add_text(" \0", 2);
+
+	/* Strip trailing whitespace from expansion */
+	for(k = curdef_idx, cptr = &curdef_text[curdef_idx-1]; k > 0; k--, cptr--)
+	{
+		if(!isspace(*cptr & 0xff))
+			break;
+	}
+
+	/*
+	 * We must add *one* whitespace to make sure that there
+	 * is a token-seperation after the expansion.
+	 */
+	*(++cptr) = ' ';
+	*(++cptr) = '\0';
+	k++;
+
+	/* Strip leading whitespace from expansion */
+	for(n = 0, cptr = curdef_text; n < k; n++, cptr++)
+	{
+		if(!isspace(*cptr & 0xff))
+			break;
+	}
+
+	if(k - n > 0)
+	{
+		if(debuglevel & DEBUGLEVEL_PPLEX)
+			fprintf(stderr, "expand_text: '%s'\n", curdef_text + n);
+		push_buffer(ppp, NULL, NULL, 0);
+		/*yy_scan_bytes(curdef_text + n, k - n);*/
+		yy_scan_string(curdef_text + n);
+	}
+}
+
+/*
+ *-------------------------------------------------------------------------
+ * String collection routines
+ *-------------------------------------------------------------------------
+ */
+static void new_string(void)
+{
+#ifdef DEBUG
+	if(strbuf_idx)
+		ppwarning("new_string: strbuf_idx != 0");
+#endif
+	strbuf_idx = 0;
+	str_startline = line_number;
+}
+
+static void add_string(char *str, int len)
+{
+	if(len == 0)
+		return;
+	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]));
+		if(strbuf_alloc > 65536)
+			ppwarning("Reallocating string buffer larger than 64kB");
+	}
+	memcpy(&strbuffer[strbuf_idx], str, len);
+	strbuf_idx += len;
+}
+
+static char *get_string(void)
+{
+	char *str = (char *)xmalloc(strbuf_idx + 1);
+	memcpy(str, strbuffer, strbuf_idx);
+	str[strbuf_idx] = '\0';
+#ifdef DEBUG
+	strbuf_idx = 0;
+#endif
+	return str;
+}
+
+static void put_string(void)
+{
+	put_buffer(strbuffer, strbuf_idx);
+#ifdef DEBUG
+	strbuf_idx = 0;
+#endif
+}
+
+static int string_start(void)
+{
+	return str_startline;
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Buffer management
+ *-------------------------------------------------------------------------
+ */
+static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop)
+{
+	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");
+
+	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].should_pop	= pop;
+	bufferstack[bufferstackidx].filename	= input_name;
+	bufferstack[bufferstackidx].ncontinuations	= ncontinuations;
+	bufferstack[bufferstackidx].include_state	= include_state;
+	bufferstack[bufferstackidx].include_ppp		= include_ppp;
+	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)
+		ppp->expanding = 1;
+	else if(filename)
+	{
+		/* These will track the pperror to the correct file and line */
+		line_number = 1;
+		char_number = 1;
+		input_name  = filename;
+		ncontinuations = 0;
+	}
+	else if(!pop)
+		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?");
+
+	if(bufferstackidx == 0)
+		return NULL;
+
+	bufferstackidx--;
+
+	if(bufferstack[bufferstackidx].define)
+		bufferstack[bufferstackidx].define->expanding = 0;
+	else
+	{
+		line_number = bufferstack[bufferstackidx].line_number;
+		char_number = bufferstack[bufferstackidx].char_number;
+		input_name  = bufferstack[bufferstackidx].filename;
+		ncontinuations = bufferstack[bufferstackidx].ncontinuations;
+		if(!bufferstack[bufferstackidx].should_pop)
+		{
+			fclose(ppin);
+			fprintf(ppout, "# %d \"%s\" 2\n", line_number, input_name);
+
+			/* We have EOF, check the include logic */
+			if(include_state == 2 && !seen_junk && include_ppp)
+			{
+				pp_entry_t *ppp = pplookup(include_ppp);
+				if(ppp)
+				{
+					includelogicentry_t *iep = xmalloc(sizeof(includelogicentry_t));
+					iep->ppp = ppp;
+					ppp->iep = iep;
+					iep->filename = bufferstack[bufferstackidx].include_filename;
+					iep->next = 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);
+				}
+				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;
+			pass_data	= bufferstack[bufferstackidx].pass_data;
+
+		}
+	}
+
+	if(ppdebug)
+		printf("pop_buffer(%d): %p %p (%d, %d, %d) %p %d\n",
+			bufferstackidx,
+			bufferstack[bufferstackidx].bufferstate,
+			bufferstack[bufferstackidx].define,
+			bufferstack[bufferstackidx].line_number,
+			bufferstack[bufferstackidx].char_number,
+			bufferstack[bufferstackidx].if_depth,
+			bufferstack[bufferstackidx].filename,
+			bufferstack[bufferstackidx].should_pop);
+
+	pp_switch_to_buffer(bufferstack[bufferstackidx].bufferstate);
+
+	if(bufferstack[bufferstackidx].should_pop)
+	{
+		if(yy_current_state() == pp_macexp)
+			macro_add_expansion();
+		else
+			internal_error(__FILE__, __LINE__, "Pop buffer and state without macro expansion state"); 
+		yy_pop_state();
+	}
+
+	return &bufferstack[bufferstackidx];
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Macro nestng support
+ *-------------------------------------------------------------------------
+ */
+static void push_macro(pp_entry_t *ppp)
+{
+	if(macexpstackidx >= MAXMACEXPSTACK)
+		pperror("Too many nested macros");
+
+	macexpstack[macexpstackidx] = xmalloc(sizeof(macexpstack[0][0]));
+
+	macexpstack[macexpstackidx]->ppp = ppp;
+	macexpstackidx++;
+}
+
+static macexpstackentry_t *top_macro(void)
+{
+	return macexpstackidx > 0 ? macexpstack[macexpstackidx-1] : NULL;
+}
+
+static macexpstackentry_t *pop_macro(void)
+{
+	if(macexpstackidx <= 0)
+		internal_error(__FILE__, __LINE__, "Macro expansion stack underflow\n");
+	return macexpstack[--macexpstackidx];
+}
+
+static void free_macro(macexpstackentry_t *mep)
+{
+	int i;
+
+	for(i = 0; i < mep->nargs; i++)
+		free(mep->args[i]);
+	if(mep->args)
+		free(mep->args);
+	if(mep->nnls)
+		free(mep->nnls);
+	if(mep->curarg)
+		free(mep->curarg);
+	free(mep);
+}
+
+static void add_text_to_macro(char *text, int len)
+{
+	macexpstackentry_t *mep = top_macro();
+
+	assert(mep->ppp->expanding == 0);
+
+	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]));
+	}
+	memcpy(mep->curarg + mep->curargsize, text, len);
+	mep->curargsize += len;
+	mep->curarg[mep->curargsize] = '\0';
+}
+
+static void macro_add_arg(int last)
+{
+	int nnl = 0;
+	char *cptr;
+	macexpstackentry_t *mep = top_macro();
+
+	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 : "");
+	cptr = mep->args[mep->nargs]-1;
+	while((cptr = strchr(cptr+1, '\n')))
+	{
+		nnl++;
+	}
+	mep->nnls[mep->nargs] = nnl;
+	mep->nargs++;
+	free(mep->curarg);
+	mep->curargalloc = mep->curargsize = 0;
+	mep->curarg = NULL;
+
+	if(debuglevel & DEBUGLEVEL_PPLEX)
+		fprintf(stderr, "macro_add_arg: %s:%d: %d -> '%s'\n",
+			input_name,
+			line_number,
+			mep->nargs-1,
+			mep->args[mep->nargs-1]);
+
+	/* Each macro argument must be expanded to cope with stingize */
+	if(last || mep->args[mep->nargs-1][0])
+	{
+		yy_push_state(pp_macexp);
+		push_buffer(NULL, NULL, NULL, last ? 2 : 1);
+		yy_scan_string(mep->args[mep->nargs-1]);
+		/*mep->bufferstackidx = bufferstackidx;	 But not nested! */
+	}
+}
+
+static void macro_add_expansion(void)
+{
+	macexpstackentry_t *mep = top_macro();
+
+	assert(mep->ppp->expanding == 0);
+
+	mep->ppargs[mep->nargs-1] = xstrdup(mep->curarg ? mep->curarg : "");
+	free(mep->curarg);
+	mep->curargalloc = mep->curargsize = 0;
+	mep->curarg = NULL;
+
+	if(debuglevel & DEBUGLEVEL_PPLEX)
+		fprintf(stderr, "macro_add_expansion: %s:%d: %d -> '%s'\n",
+			input_name,
+			line_number,
+			mep->nargs-1,
+			mep->ppargs[mep->nargs-1]);
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Output management
+ *-------------------------------------------------------------------------
+ */
+static void put_buffer(char *s, int len)
+{
+	if(top_macro())
+		add_text_to_macro(s, len);
+	else {
+           if(pass_data)
+           fwrite(s, 1, len, ppout);           
+        }
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Include management
+ *-------------------------------------------------------------------------
+ */
+int is_c_h_include(char *fname)  
+{        
+	int sl=strlen(fname);
+	if (sl < 2) return 0;
+	if ((toupper(fname[sl-1])!='H') && (toupper(fname[sl-1])!='C')) return 0;
+        if (fname[sl-2]!='.') return 0;
+	return 1;
+}
+
+void do_include(char *fname, int type)
+{
+	char *newpath;
+	int n;
+	includelogicentry_t *iep;
+
+	for(iep = includelogiclist; iep; iep = iep->next)
+	{
+		if(!strcmp(iep->filename, fname))
+		{
+			/*
+			 * We are done. The file was included before.
+			 * If the define was deleted, then this entry would have
+			 * been deleted too.
+			 */
+			return;
+		}
+	}
+
+	n = strlen(fname);
+
+	if(n <= 2)
+		pperror("Empty include filename");
+
+	/* Undo the effect of the quotation */
+	fname[n-1] = '\0';
+
+	if((ppin = 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;
+	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);
+	pp_switch_to_buffer(pp_create_buffer(ppin, YY_BUF_SIZE));
+
+	fprintf(ppout, "# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3"); 
+}
+
+/*
+ *-------------------------------------------------------------------------
+ * Push/pop preprocessor ignore state when processing conditionals
+ * which are false.
+ *-------------------------------------------------------------------------
+ */
+void push_ignore_state(void)
+{
+	yy_push_state(pp_ignore);
+}
+
+void pop_ignore_state(void)
+{
+	yy_pop_state();
+}
+
+
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ header.h	Sun Jun 30 02:38:06 2002
@@ -0,0 +1,36 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 __WIDL_HEADER_H
+#define __WIDL_HEADER_H
+
+extern int is_void(type_t *t, var_t *v);
+extern void write_name(FILE *h, var_t *v);
+extern char* get_name(var_t *v);
+extern void write_type(FILE *h, type_t *t, var_t *v, char *n);
+extern int is_object(attr_t *a);
+extern int is_local(attr_t *a);
+extern var_t *is_callas(attr_t *a);
+extern void write_method_args(FILE *h, var_t *arg, char *name);
+extern void write_forward(type_t *iface);
+extern void write_interface(type_t *iface);
+extern void write_typedef(type_t *type, var_t *names);
+
+#endif
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ Makefile.in	Sat Jun 29 20:56:44 2002
@@ -0,0 +1,60 @@
+DEFS      = -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+LEXOPT    = -Cf #-w -b
+YACCOPT   = #-v
+EXEEXT    = @EXEEXT@
+
+PROGRAMS = widl$(EXEEXT)
+MODULE   = none
+
+C_SRCS = \
+	header.c \
+	preproc.c \
+	proxy.c \
+	utils.c \
+	widl.c
+
+GEN_C_SRCS = ppy.tab.c lex.ppl.c
+EXTRA_SRCS = parser.y parser.l
+EXTRA_OBJS = y.tab.o @LEX_OUTPUT_ROOT at .o
+
+all: $(PROGRAMS)
+
+ at MAKE_RULES@
+
+widl: $(OBJS)
+	$(CC) $(CFLAGS) -o widl $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) $(LDFLAGS)
+
+widl.exe: $(OBJS)
+	$(CC) $(CFLAGS) -o widl.exe $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) -liberty $(LDFLAGS)
+
+$(TOPOBJDIR)/unicode/libwine_unicode.$(LIBEXT):
+	cd `dirname $@` && $(MAKE) `basename $@`
+
+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
+
+ at 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) parser.output parser.tab.h lex.backup y.output
+
+install:: $(PROGRAMS)
+	$(MKINSTALLDIRS) $(bindir) $(mandir)/man$(prog_manext)
+	$(INSTALL_DATA) $(SRCDIR)/widl.man $(mandir)/man$(prog_manext)/widl.$(prog_manext)
+	$(INSTALL_PROGRAM) widl$(EXEEXT) $(bindir)/widl$(EXEEXT)
+
+uninstall::
+	$(RM) $(bindir)/widl$(EXEEXT) $(mandir)/man$(prog_manext)/widl.$(prog_manext)
+
+### Dependencies:
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ parser.h	Sun Jun 30 02:39:50 2002
@@ -0,0 +1,41 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 __WIDL_PARSER_H
+#define __WIDL_PARSER_H
+
+int yyparse(void);
+
+extern FILE *yyin;
+extern char *yytext;
+extern int yydebug;
+extern int yy_flex_debug;
+
+int yylex(void);
+
+extern int import_stack_ptr;
+void do_import(char *fname);
+void abort_import(void);
+
+#define parse_only import_stack_ptr
+
+int is_type(const char *name);
+
+#endif
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ parser.l	Sun Jun 30 02:44:54 2002
@@ -0,0 +1,317 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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
+ */
+
+%option stack
+%option never-interactive
+
+nl	\r?\n
+ws	[ \f\t\r]
+cident	[a-zA-Z_][0-9a-zA-Z_]*
+int	[0-9]+
+hexd	[0-9a-fA-F]
+hex	0x{hexd}+
+uuid	{hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12}
+
+%x QUOTE
+
+%{
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "widl.h"
+#include "utils.h"
+#include "preproc.h"
+#include "parser.h"
+
+#include "y.tab.h"
+
+#define YY_USE_PROTOS
+#define YY_NO_UNPUT
+#define YY_NO_TOP_STATE
+
+extern char *temp_name;
+
+static void addcchar(char c);
+static char *get_buffered_cstring(void);
+
+static char *cbuffer;
+static int cbufidx;
+static int cbufalloc = 0;
+
+static int kw_token(const char *kw);
+
+#define MAX_IMPORT_DEPTH 10
+struct {
+  YY_BUFFER_STATE state;
+  char *temp_name;
+} import_stack[MAX_IMPORT_DEPTH];
+int import_stack_ptr = 0;
+
+static void pop_import(void);
+
+%}
+
+/*
+ **************************************************************************
+ * The flexer starts here
+ **************************************************************************
+ */
+%%
+^#.*			
+\"			yy_push_state(QUOTE); cbufidx = 0;
+<QUOTE>\"		{
+				yy_pop_state();
+				yylval.str = get_buffered_cstring();
+				return aSTRING;
+			}
+<QUOTE>\\\\		|
+<QUOTE>\\\"		addcchar(yytext[1]);
+<QUOTE>\\.		addcchar('\\'); addcchar(yytext[1]);
+<QUOTE>.		addcchar(yytext[0]);
+{uuid}			return aUUID;
+{hex}			return aNUM;
+{int}			return aNUM;
+{cident}		return kw_token(yytext);
+\n
+{ws}			
+\<\<			return SHL;
+\>\>			return SHR;
+.			return yytext[0];
+<<EOF>>			{
+				if (import_stack_ptr) pop_import();
+				else yyterminate();
+			}
+%%
+
+#ifndef yywrap
+int yywrap(void)
+{
+	return 1;
+}
+#endif
+
+static struct {
+	const char *kw;
+	int token;
+	int val;
+} keywords[] = {
+	{"__cdecl",			tCDECL},
+	{"__int64",			tINT64},
+	{"__stdcall",			tSTDCALL},
+	{"_stdcall",			tSTDCALL},
+	{"aggregatable",		tAGGREGATABLE},
+	{"allocate",			tALLOCATE},
+	{"appobject",			tAPPOBJECT},
+	{"arrays",			tARRAYS},
+	{"async",			tASYNC},
+	{"async_uuid",			tASYNCUUID},
+	{"auto_handle",			tAUTOHANDLE},
+	{"bindable",			tBINDABLE},
+	{"boolean",			tBOOLEAN},
+	{"broadcast",			tBROADCAST},
+	{"byte",			tBYTE},
+	{"byte_count",			tBYTECOUNT},
+	{"call_as",			tCALLAS},
+	{"callback",			tCALLBACK},
+	{"case",			tCASE},
+	{"char",			tCHAR},
+	{"coclass",			tCOCLASS},
+	{"code",			tCODE},
+	{"comm_status",			tCOMMSTATUS},
+	{"const",			tCONST},
+	{"context_handle",		tCONTEXTHANDLE},
+	{"context_handle_noserialize",	tCONTEXTHANDLENOSERIALIZE},
+	{"context_handle_serialize",	tCONTEXTHANDLENOSERIALIZE},
+	{"control",			tCONTROL},
+	{"cpp_quote",			tCPPQUOTE},
+/* ... */
+	{"default",			tDEFAULT},
+/* ... */
+	{"double",			tDOUBLE},
+/* ... */
+	{"enum",			tENUM},
+/* ... */
+	{"extern",			tEXTERN},
+/* ... */
+	{"float",			tFLOAT},
+/* ... */
+	{"hyper",			tHYPER},
+/* ... */
+	{"iid_is",			tIIDIS},
+/* ... */
+	{"import",			tIMPORT},
+	{"importlib",			tIMPORTLIB},
+	{"in",				tIN},
+	{"include",			tINCLUDE},
+	{"in_line",			tINLINE},
+	{"int",				tINT},
+/* ... */
+	{"interface",			tINTERFACE},
+/* ... */
+	{"length_is",			tLENGTHIS},
+/* ... */
+	{"local",			tLOCAL},
+	{"long",			tLONG},
+/* ... */
+	{"object",			tOBJECT},
+	{"odl",				tODL},
+	{"oleautomation",		tOLEAUTOMATION},
+/* ... */
+	{"out",				tOUT},
+/* ... */
+	{"pointer_default",		tPOINTERDEFAULT},
+/* ... */
+	{"ref",				tREF},
+/* ... */
+	{"short",			tSHORT},
+	{"signed",			tSIGNED},
+	{"size_is",			tSIZEIS},
+	{"sizeof",			tSIZEOF},
+/* ... */	
+	{"string",			tSTRING},
+	{"struct",			tSTRUCT},
+	{"switch",			tSWITCH},
+	{"switch_is",			tSWITCHIS},
+	{"switch_type",			tSWITCHTYPE},
+/* ... */
+	{"typedef",			tTYPEDEF},
+	{"union",			tUNION},
+/* ... */
+	{"unique",			tUNIQUE},
+	{"unsigned",			tUNSIGNED},
+/* ... */
+	{"uuid",			tUUID},
+	{"v1_enum",			tV1ENUM},
+/* ... */
+	{"version",			tVERSION},
+	{"void",			tVOID},
+	{"wchar_t",			tWCHAR},
+	{"wire_marshal",		tWIREMARSHAL},
+	{NULL}
+};
+
+static int kw_token(const char *kw)
+{
+	int i;
+	for (i=0; keywords[i].kw; i++)
+		if (strcmp(kw, keywords[i].kw) == 0)
+			return keywords[i].token;
+	yylval.str = xstrdup(kw);
+	return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
+}
+
+static void addcchar(char c)
+{
+	if(cbufidx >= cbufalloc)
+	{
+		cbufalloc += 1024;
+		cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0]));
+		if(cbufalloc > 65536)
+			yywarning("Reallocating string buffer larger than 64kB");
+	}
+	cbuffer[cbufidx++] = c;
+}
+
+static char *get_buffered_cstring(void)
+{
+	addcchar(0);
+	return xstrdup(cbuffer);
+}
+
+static void pop_import(void)
+{
+	int ptr = import_stack_ptr-1;
+
+	fclose(yyin);
+	yy_delete_buffer( YY_CURRENT_BUFFER );
+	yy_switch_to_buffer( import_stack[ptr].state );
+	if (temp_name) {
+		unlink(temp_name);
+		free(temp_name);
+	}
+	temp_name = import_stack[ptr].temp_name;
+	import_stack_ptr--;
+}
+
+struct imports {
+	char *name;
+	struct imports *next;
+} *first_import;
+
+void do_import(char *fname)
+{
+	FILE *f;
+	char *hname;
+	struct imports *import;
+	int ptr = import_stack_ptr;
+	int ret;
+
+	if (!parse_only) {
+		hname = dup_basename(fname, ".idl");
+		strcat(hname, ".h");
+
+		fprintf(header, "#include \"%s\"\n", hname);
+		free(hname);
+	}
+
+	import = first_import;
+	while (import && strcmp(import->name, fname))
+		import = import->next;
+	if (import) return; /* already imported */
+
+	import = xmalloc(sizeof(struct imports));
+	import->name = xstrdup(fname);
+	import->next = first_import;
+	first_import = import;
+
+	if((ppin = open_include(fname, 1, NULL)) == NULL)
+		yyerror("Unable to open include file %s", fname);
+
+	import_stack[ptr].temp_name = temp_name;
+	import_stack_ptr++;
+
+	if(!(temp_name = tmpnam(NULL)))
+		error("Could not generate a temp-name\n");
+	temp_name = xstrdup(temp_name);
+	if(!(ppout = fopen(temp_name, "wb")))
+		error("Could not create a temp-file\n");
+	fprintf(ppout, "# 1 \"%s\" 1\n", fname ? fname : "");
+	ret = ppparse();
+	fclose(ppin);
+	fclose(ppout);
+
+	if((f = fopen(temp_name, "r")) == NULL)
+		yyerror("Unable to open %s", temp_name);
+
+	import_stack[ptr].state = YY_CURRENT_BUFFER;
+	yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
+}
+
+void abort_import(void)
+{
+	int ptr;
+
+	for (ptr=0; ptr<import_stack_ptr; ptr++)
+		unlink(import_stack[ptr].temp_name);
+}
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ parser.y	Sun Jun 30 02:42:28 2002
@@ -0,0 +1,680 @@
+%{
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include "widl.h"
+#include "utils.h"
+#include "parser.h"
+#include "header.h"
+
+#if defined(YYBYACC)
+	/* Berkeley yacc (byacc) doesn't seem to know about these */
+	/* Some *BSD supplied versions do define these though */
+# ifndef YYEMPTY
+#  define YYEMPTY	(-1)	/* Empty lookahead value of yychar */
+# endif
+# ifndef YYLEX
+#  define YYLEX		yylex()
+# endif
+
+#elif defined(YYBISON)
+	/* Bison was used for original development */
+	/* #define YYEMPTY -2 */
+	/* #define YYLEX   yylex() */
+
+#else	
+	/* No yacc we know yet */
+# if !defined(YYEMPTY) || !defined(YYLEX)
+#  error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX.
+# elif defined(__GNUC__)	/* gcc defines the #warning directive */
+#  warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested
+  /* #else we just take a chance that it works... */
+# endif
+#endif
+
+static attr_t *make_attr(int type);
+static attr_t *make_attrv(int type, DWORD val);
+static attr_t *make_attrp(int type, void *val);
+static type_t *make_type(BYTE type, type_t *ref);
+static typeref_t *make_tref(char *name, type_t *ref);
+static typeref_t *uniq_tref(typeref_t *ref);
+static type_t *type_ref(typeref_t *ref);
+static void set_type(var_t *v, typeref_t *ref);
+static var_t *make_var(char *name);
+static func_t *make_func(var_t *def, var_t *args);
+
+static type_t *reg_type(type_t *type, char *name, int t);
+static type_t *reg_types(type_t *type, var_t *names, int t);
+static type_t *find_type(char *name, int t);
+static type_t *find_type2(char *name, int t);
+static type_t *get_type(BYTE type, char *name, int t);
+static type_t *get_typev(BYTE type, var_t *name, int t);
+
+#define tsENUM   1
+#define tsSTRUCT 2
+#define tsUNION  3
+
+static type_t std_int = { "int" };
+
+%}
+%union {
+	attr_t *attr;
+	type_t *type;
+	typeref_t *tref;
+	var_t *var;
+	func_t *func;
+	char *str;
+	int num;
+}
+
+%token <str> aIDENTIFIER
+%token <str> aKNOWNTYPE
+%token <num> aNUM
+%token <str> aSTRING
+%token <uuid> aUUID
+%token SHL SHR
+%token tAGGREGATABLE tALLOCATE tAPPOBJECT tARRAYS tASYNC tASYNCUUID
+%token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
+%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
+%token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
+%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
+%token tDEFAULT
+%token tDOUBLE
+%token tENUM
+%token tEXTERN
+%token tFLOAT
+%token tHYPER
+%token tIIDIS
+%token tIMPORT tIMPORTLIB
+%token tIN tINCLUDE tINLINE
+%token tINT tINT64
+%token tINTERFACE
+%token tLENGTHIS
+%token tLOCAL
+%token tLONG
+%token tOBJECT tODL tOLEAUTOMATION
+%token tOUT
+%token tPOINTERDEFAULT
+%token tREF
+%token tSHORT
+%token tSIGNED
+%token tSIZEIS tSIZEOF
+%token tSTDCALL
+%token tSTRING tSTRUCT
+%token tSWITCH tSWITCHIS tSWITCHTYPE
+%token tTYPEDEF
+%token tUNION
+%token tUNIQUE
+%token tUNSIGNED
+%token tUUID
+%token tV1ENUM
+%token tVERSION
+%token tVOID
+%token tWCHAR tWIREMARSHAL
+
+/* used in attr_t */
+%token tPOINTERTYPE
+
+%type <attr> m_attributes attributes attrib_list attribute
+%type <type> inherit interface interfacedef
+%type <type> base_type int_std
+%type <type> enumdef structdef typedef uniondef
+%type <tref> type
+%type <var> m_args no_args args arg
+%type <var> fields field
+%type <var> m_ident t_ident ident p_ident pident pident_list
+%type <func> funcdef statements
+%type <num> expr pointer_type
+
+%left ','
+%left '|'
+%left '&'
+%left '-' '+'
+%left '*' '/'
+%left SHL SHR
+%right CAST
+%right PPTR
+%right NEG
+
+%%
+
+statements:					{ $$ = NULL; }
+	| statements funcdef ';'		{ LINK($2, $1); $$ = $2; }
+	| statements statement
+	;
+
+statement: ';'					{}
+	| constdef				{}
+	| cppquote				{}
+	| enumdef ';'				{ if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } }
+	| externdef ';'				{}
+	| import				{}
+	| interface ';'				{}
+	| interfacedef				{}
+	| structdef ';'				{ if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } }
+	| typedef ';'				{}
+	| uniondef ';'				{ if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } }
+	;
+
+cppquote:	tCPPQUOTE '(' aSTRING ')'	{ if (!parse_only) fprintf(header, "%s\n", $3); }
+;
+import:		tIMPORT aSTRING ';'		{ do_import($2); }
+;
+
+m_args:						{ $$ = NULL; }
+	| args
+	;
+
+no_args:  tVOID					{ $$ = NULL; }
+	;
+
+args:	  arg
+	| args ',' arg				{ LINK($3, $1); $$ = $3; }
+	| no_args
+	;
+
+/* split into two rules to get bison to resolve a tVOID conflict */
+arg:	  attributes type pident array		{ $$ = $3;
+						  set_type($$, $2);
+						  $$->attrs = $1; /* FIXME: array */
+						}
+	| type pident array			{ $$ = $2;
+						  set_type($$, $1); /* FIXME: array */
+						}
+	;
+
+aexprs:
+	| aexpr_list
+	;
+
+aexpr_list: aexpr
+	| aexprs ',' aexpr
+	;
+
+aexpr:	  aNUM					{}
+	| aIDENTIFIER				{}
+	| aexpr '|' aexpr
+	| aexpr '&' aexpr
+	| aexpr '+' aexpr
+	| aexpr '-' aexpr
+	| aexpr '*' aexpr
+	| aexpr '/' aexpr
+	| '-' aexpr %prec NEG
+	| '*' aexpr %prec PPTR
+	| '(' type ')' aexpr %prec CAST
+	| '(' aexpr ')'
+	| tSIZEOF '(' type ')'
+	;
+
+array:
+	| '[' aexprs ']'
+	| '[' '*' ']'
+	;
+
+m_attributes:					{ $$ = NULL; }
+	| attributes
+	;
+
+attributes:
+	  m_attributes '[' attrib_list ']'	{ LINK_LAST($3, $1); $$ = $3; }
+	;
+
+attrib_list: attribute
+	| attrib_list ',' attribute		{ LINK_SAFE($3, $1); $$ = $3; /* FIXME: don't use SAFE */ }
+	;
+
+attribute:
+	  tASYNC				{ $$ = make_attr(tASYNC); }
+	| tCALLAS '(' ident ')'			{ $$ = make_attrp(tCALLAS, $3); }
+	| tCASE '(' expr_list ')'		{ $$ = NULL; }
+	| tCONTEXTHANDLE			{ $$ = NULL; }
+	| tCONTEXTHANDLENOSERIALIZE		{ $$ = NULL; }
+	| tCONTEXTHANDLESERIALIZE		{ $$ = NULL; }
+	| tDEFAULT				{ $$ = make_attr(tDEFAULT); }
+	| tIIDIS '(' ident ')'			{ $$ = make_attrp(tIIDIS, $3); }
+	| tIN					{ $$ = make_attr(tIN); }
+	| tLENGTHIS '(' aexprs ')'		{ $$ = NULL; }
+	| tLOCAL				{ $$ = make_attr(tLOCAL); }
+	| tOBJECT				{ $$ = make_attr(tOBJECT); }
+	| tOLEAUTOMATION			{ $$ = make_attr(tOLEAUTOMATION); }
+	| tOUT					{ $$ = make_attr(tOUT); }
+	| tPOINTERDEFAULT '(' pointer_type ')'	{ $$ = make_attrv(tPOINTERDEFAULT, $3); }
+	| tSIZEIS '(' aexprs ')'		{ $$ = NULL; }
+	| tSTRING				{ $$ = make_attr(tSTRING); }
+	| tSWITCHIS '(' aexpr ')'		{ $$ = NULL; }
+	| tSWITCHTYPE '(' type ')'		{ $$ = NULL; }
+	| tUUID '(' aUUID ')'			{ $$ = NULL; }
+	| tV1ENUM				{ $$ = make_attr(tV1ENUM); }
+	| tVERSION '(' version ')'		{ $$ = NULL; }
+	| tWIREMARSHAL '(' type ')'		{ $$ = make_attrp(tWIREMARSHAL, type_ref($3)); }
+	| pointer_type				{ $$ = make_attrv(tPOINTERTYPE, $1); }
+	;
+
+callconv:
+	| tSTDCALL
+	;
+
+cases:
+	| cases case
+	;
+
+case:	  tCASE expr ':' field
+	| tDEFAULT ':' field
+	;
+
+constdef: tCONST type ident '=' expr
+	;
+
+enums:
+	| enum_list ','
+	| enum_list
+	;
+
+enum_list: enum
+	| enum_list ',' enum
+	;
+
+enum:	  ident '=' expr			{}
+	| ident					{}
+	;
+
+enumdef: tENUM t_ident '{' enums '}'		{ $$ = get_typev(RPC_FC_SHORT /* FIXME */, $2, tsENUM);
+						  $$->defined = TRUE;
+						}
+	;
+
+expr_list: expr					{}
+	| expr_list ',' expr			{}
+	;
+
+expr:	  aNUM
+	| aIDENTIFIER				{}
+	| expr '|' expr				{}
+	| expr SHL expr				{}
+	| expr SHR expr				{}
+	| '-' expr %prec NEG			{}
+	;
+
+externdef: tEXTERN tCONST type ident
+	;
+
+fields:						{ $$ = NULL; }
+	| fields field				{ LINK($2, $1); $$ = $2; }
+	;
+
+field:	  m_attributes type pident array ';'	{ $$ = $3; set_type($$, $2); $$->attrs = $1; /* FIXME: array */ }
+	| m_attributes uniondef ';'		{ $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
+	| attributes ';'			{ $$ = make_var(NULL); $$->attrs = $1; }
+	| ';'					{ $$ = NULL; }
+	;
+
+funcdef:
+	  m_attributes type callconv pident
+	  '(' m_args ')'			{ set_type($4, $2);
+						  $4->attrs = $1;
+						  $$ = make_func($4, $6);
+						}
+	;
+
+m_ident:					{ $$ = NULL; }
+	| ident
+	;
+
+t_ident:					{ $$ = NULL; }
+	| aIDENTIFIER				{ $$ = make_var($1); }
+	| aKNOWNTYPE				{ $$ = make_var($1); }
+	;
+
+ident:	  aIDENTIFIER				{ $$ = make_var($1); }
+	;
+
+base_type: tBYTE				{ $$ = make_type(RPC_FC_BYTE, NULL); }
+	| tCHAR					{ $$ = make_type(RPC_FC_CHAR, NULL); }
+	| tUNSIGNED tCHAR			{ $$ = make_type(RPC_FC_CHAR, NULL); }
+	| tWCHAR				{ $$ = make_type(RPC_FC_WCHAR, NULL); }
+	| int_std
+	| tSIGNED int_std			{ $$ = $2; /* FIXME */ }
+	| tUNSIGNED int_std			{ $$ = $2; /* FIXME */ }
+	| tFLOAT				{ $$ = make_type(RPC_FC_FLOAT, NULL); }
+	| tDOUBLE				{ $$ = make_type(RPC_FC_DOUBLE, NULL); }
+	| tBOOLEAN				{ $$ = make_type(RPC_FC_BYTE, NULL); /* ? */ }
+	;
+
+m_int:
+	| tINT
+	;
+
+int_std:  tINT					{ $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */
+	| tSHORT m_int				{ $$ = make_type(RPC_FC_SHORT, NULL); }
+	| tLONG m_int				{ $$ = make_type(RPC_FC_LONG, NULL); }
+	| tHYPER m_int				{ $$ = make_type(RPC_FC_HYPER, NULL); }
+	| tINT64				{ $$ = make_type(RPC_FC_HYPER, NULL); }
+	;
+
+inherit:					{ $$ = NULL; }
+	| ':' aKNOWNTYPE			{ $$ = find_type2($2, 0); }
+	;
+
+interface: tINTERFACE aIDENTIFIER		{ $$ = get_type(RPC_FC_IP, $2, 0); if (!parse_only) write_forward($$); }
+	|  tINTERFACE aKNOWNTYPE		{ $$ = get_type(RPC_FC_IP, $2, 0); if (!parse_only) write_forward($$); }
+	;
+
+interfacedef: attributes interface inherit
+	  '{' statements '}'			{ $$ = $2;
+						  if ($$->defined) yyerror("multiple definition error\n");
+						  $$->ref = $3;
+						  $$->attrs = $1;
+						  $$->funcs = $5;
+						  $$->defined = TRUE;
+						  if (!parse_only) write_interface($$);
+						}
+	;
+
+p_ident:  '*' pident %prec PPTR			{ $$ = $2; $$->ptr_level++; }
+	| tCONST p_ident			{ $$ = $2; }
+	;
+
+pident:	  ident
+	| p_ident
+	| '(' pident ')'			{ $$ = $2; }
+	;
+
+pident_list:
+	  pident
+	| pident_list ',' pident		{ LINK($3, $1); $$ = $3; }
+	;
+
+pointer_type:
+	  tREF					{ $$ = RPC_FC_RP; }
+	| tUNIQUE				{ $$ = RPC_FC_UP; }
+	;
+
+structdef: tSTRUCT t_ident '{' fields '}'	{ $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
+						  $$->fields = $4;
+						  $$->defined = TRUE;
+						}
+	;
+
+type:	  tVOID					{ $$ = make_tref(NULL, make_type(0, NULL)); }
+	| aKNOWNTYPE				{ $$ = make_tref($1, find_type($1, 0)); }
+	| base_type				{ $$ = make_tref(NULL, $1); }
+	| tCONST type				{ $$ = uniq_tref($2); $$->ref->is_const = TRUE; }
+	| enumdef				{ $$ = make_tref(NULL, $1); }
+	| tENUM aIDENTIFIER			{ $$ = make_tref(NULL, find_type2($2, tsENUM)); }
+	| structdef				{ $$ = make_tref(NULL, $1); }
+	| tSTRUCT aIDENTIFIER			{ $$ = make_tref(NULL, get_type(RPC_FC_STRUCT, $2, tsSTRUCT)); }
+	| uniondef				{ $$ = make_tref(NULL, $1); }
+	| tUNION aIDENTIFIER			{ $$ = make_tref(NULL, find_type2($2, tsUNION)); }
+	;
+
+typedef: tTYPEDEF m_attributes type pident_list	{ typeref_t *tref = uniq_tref($3);
+						  $4->tname = tref->name;
+						  tref->name = NULL;
+						  $$ = type_ref(tref);
+						  $$->attrs = $2;
+						  if (!parse_only) write_typedef($$, $4);
+						  reg_types($$, $4, 0);
+						}
+	;
+
+uniondef: tUNION t_ident '{' fields '}'		{ $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
+						  $$->fields = $4;
+						  $$->defined = TRUE;
+						}
+	| tUNION t_ident
+	  tSWITCH '(' type ident ')'
+	  m_ident '{' cases '}'			{ $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
+						  $$->defined = TRUE;
+						}
+	;
+
+version:
+	  aNUM					{}
+	| aNUM '.' aNUM				{}
+	;
+
+%%
+
+static attr_t *make_attr(int type)
+{
+  attr_t *a = xmalloc(sizeof(attr_t));
+  a->type = type;
+  a->u.ival = 0;
+  return a;
+}
+
+static attr_t *make_attrv(int type, DWORD val)
+{
+  attr_t *a = xmalloc(sizeof(attr_t));
+  a->type = type;
+  a->u.ival = val;
+  return a;
+}
+
+static attr_t *make_attrp(int type, void *val)
+{
+  attr_t *a = xmalloc(sizeof(attr_t));
+  a->type = type;
+  a->u.pval = val;
+  return a;
+}
+
+static type_t *make_type(BYTE type, type_t *ref)
+{
+  type_t *t = xmalloc(sizeof(type_t));
+  t->name = NULL;
+  t->type = type;
+  t->ref = ref;
+  t->rname = NULL;
+  t->attrs = NULL;
+  t->funcs = NULL;
+  t->fields = NULL;
+  t->ignore = parse_only;
+  t->is_const = FALSE;
+  t->defined = FALSE;
+  t->written = FALSE;
+  INIT_LINK(t);
+  return t;
+}
+
+static typeref_t *make_tref(char *name, type_t *ref)
+{
+  typeref_t *t = xmalloc(sizeof(typeref_t));
+  t->name = name;
+  t->ref = ref;
+  t->uniq = ref ? 0 : 1;
+  return t;
+}
+
+static typeref_t *uniq_tref(typeref_t *ref)
+{
+  typeref_t *t = ref;
+  type_t *tp;
+  if (t->uniq) return t;
+  tp = make_type(0, t->ref);
+  tp->name = t->name;
+  t->name = NULL;
+  t->ref = tp;
+  t->uniq = 1;
+  return t;
+}
+
+static type_t *type_ref(typeref_t *ref)
+{
+  type_t *t = ref->ref;
+  if (ref->name) free(ref->name);
+  free(ref);
+  return t;
+}
+
+static void set_type(var_t *v, typeref_t *ref)
+{
+  v->type = ref->ref;
+  v->tname = ref->name;
+  ref->name = NULL;
+  free(ref);
+}
+
+static var_t *make_var(char *name)
+{
+  var_t *v = xmalloc(sizeof(var_t));
+  v->name = name;
+  v->ptr_level = 0;
+  v->type = NULL;
+  v->tname = NULL;
+  v->attrs = NULL;
+  INIT_LINK(v);
+  return v;
+}
+
+static func_t *make_func(var_t *def, var_t *args)
+{
+  func_t *f = xmalloc(sizeof(func_t));
+  f->def = def;
+  f->args = args;
+  f->ignore = parse_only;
+  f->idx = -1;
+  INIT_LINK(f);
+  return f;
+}
+
+struct rtype {
+  char *name;
+  type_t *type;
+  int t;
+  struct rtype *next;
+};
+
+struct rtype *first;
+
+static type_t *reg_type(type_t *type, char *name, int t)
+{
+  struct rtype *nt;
+  if (!name) {
+    yyerror("registering named type without name\n");
+    return type;
+  }
+  nt = xmalloc(sizeof(struct rtype));
+  nt->name = name;
+  nt->type = type;
+  nt->t = t;
+  nt->next = first;
+  first = nt;
+  return type;
+}
+
+static type_t *reg_types(type_t *type, var_t *names, int t)
+{
+  type_t *ptr = type;
+  int ptrc = 0;
+
+  while (names) {
+    var_t *next = NEXT_LINK(names);
+    if (names->name) {
+      type_t *cur = ptr;
+      int cptr = names->ptr_level;
+      if (cptr > ptrc) {
+        while (cptr > ptrc) {
+          cur = ptr = make_type(RPC_FC_FP, cur); /* FIXME: pointer type from attrs? */
+          ptrc++;
+        }
+      } else {
+        while (cptr < ptrc) {
+          cur = cur->ref;
+          cptr++;
+        }
+      }
+      reg_type(cur, names->name, t);
+    }
+    free(names);
+    names = next;
+  }
+  return type;
+}
+
+static type_t *find_type(char *name, int t)
+{
+  struct rtype *cur = first;
+  while (cur && (cur->t != t || strcmp(cur->name, name)))
+    cur = cur->next;
+  if (!cur) {
+    yyerror("type %s not found\n", name);
+    return NULL;
+  }
+  return cur->type;
+}
+
+static type_t *find_type2(char *name, int t)
+{
+  type_t *tp = find_type(name, t);
+  free(name);
+  return tp;
+}
+
+int is_type(const char *name)
+{
+  struct rtype *cur = first;
+  while (cur && (cur->t || strcmp(cur->name, name)))
+    cur = cur->next;
+  if (cur) return TRUE;
+  return FALSE;
+}
+
+static type_t *get_type(BYTE type, char *name, int t)
+{
+  struct rtype *cur = NULL;
+  type_t *tp;
+  if (name) {
+    cur = first;
+    while (cur && (cur->t != t || strcmp(cur->name, name)))
+      cur = cur->next;
+  }
+  if (cur) {
+    free(name);
+    return cur->type;
+  }
+  tp = make_type(type, NULL);
+  tp->name = name;
+  if (!name) return tp;
+  return reg_type(tp, name, t);
+}
+
+static type_t *get_typev(BYTE type, var_t *name, int t)
+{
+  char *sname = NULL;
+  if (name) {
+    sname = name->name;
+    free(name);
+  }
+  return get_type(type, sname, t);
+}
+
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ header.c	Sun Jun 30 02:37:48 2002
@@ -0,0 +1,408 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "widl.h"
+#include "utils.h"
+#include "parser.h"
+#include "header.h"
+#include "proxy.h"
+#include "y.tab.h"
+
+static int indentation = 0;
+
+static void indent(int delta)
+{
+  int c;
+  if (delta < 0) indentation += delta;
+  for (c=0; c<indentation; c++) fprintf(header, "    ");
+  if (delta > 0) indentation += delta;
+}
+
+int is_void(type_t *t, var_t *v)
+{
+  if (v && v->ptr_level) return 0;
+  if (!t->type && !t->ref) return 1;
+  return 0;
+}
+
+static void write_pident(var_t *v)
+{
+  int c;
+  for (c=0; c<v->ptr_level; c++) {
+    fprintf(header, "*");
+  }
+  if (v->name) fprintf(header, "%s", v->name);
+}
+
+void write_name(FILE *h, var_t *v)
+{
+  fprintf(h, "%s", v->name);
+}
+
+char* get_name(var_t *v)
+{
+  return v->name;
+}
+
+static void write_fields(FILE *h, var_t *v)
+{
+  if (!v) return;
+  while (NEXT_LINK(v)) v = NEXT_LINK(v);
+  while (v) {
+    if (v->type) {
+      indent(0);
+      write_type(h, v->type, NULL, v->tname);
+      if (get_name(v)) {
+        fprintf(header, " ");
+        write_pident(v);
+      }
+      fprintf(header, ";\n");
+    }
+    v = PREV_LINK(v);
+  }
+}
+
+void write_type(FILE *h, type_t *t, var_t *v, char *n)
+{
+  int c;
+
+  if (n) fprintf(h, "%s", n);
+  else {
+    if (t->is_const) fprintf(h, "const ");
+    if (t->type) {
+      switch (t->type) {
+      case RPC_FC_BYTE:
+        fprintf(h, "byte");
+        break;
+      case RPC_FC_CHAR:
+        fprintf(h, "char");
+        break;
+      case RPC_FC_USHORT:
+        fprintf(h, "unsigned ");
+      case RPC_FC_SHORT:
+        if (t->ref) fprintf(h, t->ref->name);
+        fprintf(h, "short");
+        break;
+      case RPC_FC_ULONG:
+        fprintf(h, "unsigned ");
+      case RPC_FC_LONG:
+        if (t->ref) fprintf(h, t->ref->name);
+        else fprintf(h, "long");
+        break;
+      case RPC_FC_STRUCT:
+        if (t->defined && !t->written) {
+          if (t->name) fprintf(h, "struct %s {\n", t->name);
+          else fprintf(h, "struct {\n");
+          indentation++;
+          write_fields(h, t->fields);
+          indent(-1);
+          fprintf(h, "}");
+        }
+        else fprintf(h, "struct %s", t->name);
+        break;
+      case RPC_FC_NON_ENCAPSULATED_UNION:
+        if (t->defined && !t->written) {
+          if (t->name) fprintf(h, "union %s {\n", t->name);
+          else fprintf(h, "union {\n");
+          indentation++;
+          write_fields(h, t->fields);
+          indent(-1);
+          fprintf(h, "}");
+        }
+        else fprintf(h, "union %s", t->name);
+        break;
+      default:
+        fprintf(h, "(unknown-type:%d)", t->type);
+      }
+    }
+    else {
+      if (t->ref) {
+        write_type(h, t->ref, NULL, t->name);
+      }
+      else fprintf(h, "void");
+    }
+  }
+  if (v) {
+    for (c=0; c<v->ptr_level; c++) {
+      fprintf(h, "*");
+    }
+  }
+}
+
+void write_typedef(type_t *type, var_t *names)
+{
+  char *tname = names->tname;
+  while (NEXT_LINK(names)) names = NEXT_LINK(names);
+  fprintf(header, "typedef ");
+  write_type(header, type, NULL, tname);
+  fprintf(header, " ");
+  while (names) {
+    write_pident(names);
+    if (PREV_LINK(names))
+      fprintf(header, ", ");
+    names = PREV_LINK(names);
+  }
+  fprintf(header, ";\n");
+}
+
+/********** INTERFACES **********/
+
+int is_object(attr_t *a)
+{
+  while (a) {
+    if (a->type == tOBJECT) return 1;
+    a = NEXT_LINK(a);
+  }
+  return 0;
+}
+
+int is_local(attr_t *a)
+{
+  while (a) {
+    if (a->type == tLOCAL) return 1;
+    a = NEXT_LINK(a);
+  }
+  return 0;
+}
+
+var_t *is_callas(attr_t *a)
+{
+  while (a) {
+    if (a->type == tCALLAS) return a->u.pval;
+    a = NEXT_LINK(a);
+  }
+  return NULL;
+}
+
+static void write_method_def(type_t *iface)
+{
+  func_t *cur = iface->funcs;
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+  fprintf(header, "#define %s_METHODS", iface->name);
+  while (cur) {
+    var_t *def = cur->def;
+    if (!is_callas(def->attrs)) {
+      var_t *arg = cur->args;
+      int argc = 0;
+      if (arg) {
+	argc++;
+	while (NEXT_LINK(arg)) {
+	  arg = NEXT_LINK(arg);
+	  argc++;
+	}
+      }
+      fprintf(header, " \\\n");
+      if (!is_void(def->type, def)) {
+	if (argc)
+	  fprintf(header, "    ICOM_METHOD%d (", argc);
+	else
+	  fprintf(header, "    ICOM_METHOD  (");
+	write_type(header, def->type, def, def->tname);
+	fprintf(header, ",");
+      } else
+	if (argc)
+	  fprintf(header, "    ICOM_VMETHOD%d(", argc);
+	else
+	  fprintf(header, "    ICOM_VMETHOD (");
+      write_name(header, def);
+      while (arg) {
+	fprintf(header, ",");
+	write_type(header, arg->type, arg, arg->tname);
+	fprintf(header, ",");
+	write_name(header,arg);
+	arg = PREV_LINK(arg);
+      }
+      fprintf(header, ")");
+    }
+    cur = PREV_LINK(cur);
+  }
+  fprintf(header, "\n");
+}
+
+static int write_method_macro(type_t *iface, char *name)
+{
+  int idx;
+  func_t *cur = iface->funcs;
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+
+  if (iface->ref) idx = write_method_macro(iface->ref, name);
+  else idx = 0;
+  fprintf(header, "/*** %s methods ***/\n", iface->name);
+  while (cur) {
+    var_t *def = cur->def;
+    if (!is_callas(def->attrs)) {
+      var_t *arg = cur->args;
+      int argc = 0;
+      int c;
+      while (arg) {
+	arg = NEXT_LINK(arg);
+	argc++;
+      }
+
+      fprintf(header, "#define %s_", name);
+      write_name(header,def);
+      fprintf(header, "(p");
+      for (c=0; c<argc; c++)
+	fprintf(header, ",%c", c+'a');
+      fprintf(header, ") ");
+
+      if (argc)
+	fprintf(header, "ICOM_CALL%d(", argc);
+      else
+	fprintf(header, "ICOM_CALL(");
+      write_name(header,def);
+      fprintf(header, ",p");
+      for (c=0; c<argc; c++)
+	fprintf(header, ",%c", c+'a');
+      fprintf(header, ")\n");
+      if (cur->idx == -1) cur->idx = idx;
+      else if (cur->idx != idx) yyerror("BUG: method index mismatch in write_method_macro");
+      idx++;
+    }
+    cur = PREV_LINK(cur);
+  }
+  return idx;
+}
+
+void write_method_args(FILE *h, var_t *arg, char *name)
+{
+  if (arg) {
+    while (NEXT_LINK(arg))
+      arg = NEXT_LINK(arg);
+  }
+  fprintf(h, "    %s* This", name);
+  while (arg) {
+    fprintf(h, ",\n    ");
+    write_type(h, arg->type, arg, arg->tname);
+    fprintf(h, " ");
+    write_name(h,arg);
+    arg = PREV_LINK(arg);
+  }
+}
+
+static void write_method_proto(type_t *iface)
+{
+  func_t *cur = iface->funcs;
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+  while (cur) {
+    var_t *def = cur->def;
+    var_t *cas = is_callas(def->attrs);
+    if (!is_local(def->attrs)) {
+      /* proxy prototype */
+      write_type(header, def->type, def, def->tname);
+      fprintf(header, " CALLBACK %s_", iface->name);
+      write_name(header,def);
+      fprintf(header, "_Proxy(\n");
+      write_method_args(header, cur->args, iface->name);
+      fprintf(header, ");\n");
+      /* stub prototype */
+      fprintf(header, "void __RPC_STUB %s_", iface->name);
+      write_name(header,def);
+      fprintf(header, "_Stub(\n");
+      fprintf(header, "    IRpcStubBuffer* This,\n");
+      fprintf(header, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
+      fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
+      fprintf(header, "    DWORD* pdwStubPhase);\n");
+    }
+    if (cas) {
+      func_t *m = iface->funcs;
+      while (m && strcmp(get_name(m->def), cas->name))
+        m = NEXT_LINK(m);
+      if (m) {
+        var_t *mdef = m->def;
+        /* proxy prototype - use local prototype */
+        write_type(header, mdef->type, mdef, mdef->tname);
+        fprintf(header, " CALLBACK %s_", iface->name);
+        write_name(header, mdef);
+        fprintf(header, "_Proxy(\n");
+        write_method_args(header, m->args, iface->name);
+        fprintf(header, ");\n");
+        /* stub prototype - use remotable prototype */
+        write_type(header, def->type, def, def->tname);
+        fprintf(header, " __RPC_STUB %s_", iface->name);
+        write_name(header, mdef);
+        fprintf(header, "_Stub(\n");
+        write_method_args(header, cur->args, iface->name);
+        fprintf(header, ");\n");
+      }
+      else {
+        yywarning("invalid call_as attribute (%s -> %s)\n", get_name(def), cas->name);
+      }
+    }
+
+    cur = PREV_LINK(cur);
+  }
+}
+
+void write_forward(type_t *iface)
+{
+  if (!iface->written) {
+    fprintf(header, "typedef struct %s %s;\n", iface->name, iface->name);
+    iface->written = TRUE;
+  }
+}
+
+void write_interface(type_t *iface)
+{
+  if (!is_object(iface->attrs)) {
+    if (!iface->funcs) return;
+    yywarning("RPC interfaces not supported yet\n");
+    return;
+  }
+
+  if (!iface->funcs) {
+    yywarning("%s has no methods", iface->name);
+    return;
+  }
+
+  fprintf(header, "/*****************************************************************************\n");
+  fprintf(header, " * %s interface\n", iface->name);
+  fprintf(header, " */\n");
+  write_forward(iface);
+  if (iface->ref)
+    fprintf(header, "#define ICOM_INTERFACE %s\n", iface->name);
+  write_method_def(iface);
+  fprintf(header, "#define %s_IMETHODS \\\n", iface->name);
+  if (iface->ref)
+    fprintf(header, "    %s_IMETHODS \\\n", iface->ref->name);
+  fprintf(header, "    %s_METHODS \\\n", iface->name);
+  if (iface->ref) {
+    fprintf(header, "ICOM_DEFINE(%s,%s)\n", iface->name, iface->ref->name);
+    fprintf(header, "#undef ICOM_INTERFACE\n");
+  }
+  fprintf(header, "\n");
+  write_method_macro(iface, iface->name);
+  fprintf(header, "\n");
+  write_method_proto(iface);
+  fprintf(header, "\n");
+
+  if (!is_local(iface->attrs))
+    write_proxy(iface);
+}
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ ppy.tab.h	Sun Jun 30 02:59:04 2002
@@ -0,0 +1,84 @@
+/*
+ * 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 BISON_PPY_TAB_H
+# define BISON_PPY_TAB_H
+
+#ifndef YYSTYPE
+typedef 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;
+} yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define	tRCINCLUDE	257
+# define	tIF	258
+# define	tIFDEF	259
+# define	tIFNDEF	260
+# define	tELSE	261
+# define	tELIF	262
+# define	tENDIF	263
+# define	tDEFINED	264
+# define	tNL	265
+# define	tINCLUDE	266
+# define	tLINE	267
+# define	tGCCLINE	268
+# define	tERROR	269
+# define	tWARNING	270
+# define	tPRAGMA	271
+# define	tPPIDENT	272
+# define	tUNDEF	273
+# define	tMACROEND	274
+# define	tCONCAT	275
+# define	tELIPSIS	276
+# define	tSTRINGIZE	277
+# define	tIDENT	278
+# define	tLITERAL	279
+# define	tMACRO	280
+# define	tDEFINE	281
+# define	tDQSTRING	282
+# define	tSQSTRING	283
+# define	tIQSTRING	284
+# define	tUINT	285
+# define	tSINT	286
+# define	tULONG	287
+# define	tSLONG	288
+# define	tULONGLONG	289
+# define	tSLONGLONG	290
+# define	tRCINCLUDEPATH	291
+# define	tLOGOR	292
+# define	tLOGAND	293
+# define	tEQ	294
+# define	tNE	295
+# define	tLTE	296
+# define	tGTE	297
+# define	tLSHIFT	298
+# define	tRSHIFT	299
+
+
+extern YYSTYPE pplval;
+
+#endif /* not BISON_PPY_TAB_H */
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ ppy.y	Sun Jun 30 02:45:28 2002
@@ -0,0 +1,654 @@
+/*
+ * 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
+ *
+ * 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 "wine/port.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "utils.h"
+#include "widl.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 tRCINCLUDE
+%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
+%token <cptr> tRCINCLUDEPATH
+
+%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>	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 , $3); free($3); }
+	| tGCCLINE tSINT tDQSTRING tNL	{ fprintf(ppout, "# %d %s\n", $2 , $3); free($3); }
+	| tGCCLINE tSINT tDQSTRING tSINT tNL	
+		{ fprintf(ppout, "# %d %s %d\n", $2, $3, $4); free($3); }
+	| tGCCLINE tSINT tDQSTRING tSINT tSINT tNL	
+		{ fprintf(ppout, "# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); }
+	| tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT  tNL	
+		{ fprintf(ppout, "# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); }
+	| tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tSINT tNL	
+		{ fprintf(ppout, "# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free($3); }
+	| 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); }
+        | tRCINCLUDE tRCINCLUDEPATH {
+                int nl=strlen($2) +3;
+                char *fn=xmalloc(nl);
+                snprintf(fn,nl,"\"%s\"",$2);
+		free($2);
+		do_include(fn,1);
+	}
+	| tRCINCLUDE tDQSTRING {
+		do_include($2,1);
+	}
+	/*| 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; }
+	;
+
+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] & 0xff))
+				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] & 0xff))
+				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;
+}
+
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ preproc.c	Sun Jun 30 02:39:30 2002
@@ -0,0 +1,493 @@
+/*
+ * 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 "widl.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;
+}
+
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ preproc.h	Sun Jun 30 02:40:54 2002
@@ -0,0 +1,211 @@
+/*
+ * 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
+ */
+
+#ifndef __WIDL_PREPROC_H
+#define __WIDL_PREPROC_H
+
+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;
+	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;
+
+
+/*
+ * 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);
+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);
+
+/*
+ * 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
+
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ proxy.c	Sun Jun 30 02:41:16 2002
@@ -0,0 +1,368 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "widl.h"
+#include "utils.h"
+#include "parser.h"
+#include "header.h"
+#include "y.tab.h"
+
+/* FIXME: support generation of stubless proxies */
+
+static void write_stubdesc(void)
+{
+  fprintf(proxy, "const MIDL_STUB_DESC Object_StubDesc = {\n");
+  fprintf(proxy, "    0,\n");
+  fprintf(proxy, "    NdrOleAllocate,\n");
+  fprintf(proxy, "    NdrOleFree,\n");
+  fprintf(proxy, "    {0}, 0, 0, 0, 0,\n");
+  fprintf(proxy, "    0 /* __MIDL_TypeFormatString.Format */\n");
+  fprintf(proxy, "};\n");
+  fprintf(proxy, "\n");
+}
+
+static void init_proxy(void)
+{
+  if (proxy) return;
+  proxy = fopen(proxy_name, "w");
+  fprintf(proxy, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION);
+  fprintf(proxy, "#include \"rpcproxy.h\"\n");
+  fprintf(proxy, "#include \"%s\"\n", header_name);
+  fprintf(proxy, "\n");
+  write_stubdesc();
+}
+
+static void gen_proxy(type_t *iface, func_t *cur, int idx)
+{
+  var_t *def = cur->def;
+  int has_ret = !is_void(def->type, def);
+
+  write_type(proxy, def->type, def, def->tname);
+  fprintf(proxy, " CALLBACK %s_", iface->name);
+  write_name(proxy, def);
+  fprintf(proxy, "_Proxy(\n");
+  write_method_args(proxy, cur->args, iface->name);
+  fprintf(proxy, ")\n");
+  fprintf(proxy, "{\n");
+  /* local variables */
+  if (has_ret) {
+    fprintf(proxy, "    ");
+    write_type(proxy, def->type, def, def->tname);
+    fprintf(proxy, " _Ret;\n");
+  }
+  fprintf(proxy, "    RPC_MESSAGE _Msg;\n");
+  fprintf(proxy, "    MIDL_STUB_MESSAGE _StubMsg;\n");
+  fprintf(proxy, "\n");
+
+  /* FIXME: trace */
+  /* FIXME: clear output vars? */
+
+  fprintf(proxy, "    NdrProxyInitialize(This, &_Msg, &_StubMsg, &Object_StubDesc, %d);\n", idx);
+
+  /* FIXME: size buffer */
+
+  fprintf(proxy, "    NdrProxyGetBuffer(This, &_StubMsg);\n");
+
+  /* FIXME: marshall */
+
+  fprintf(proxy, "    NdrProxySendReceive(This, &_StubMsg);\n");
+
+  /* FIXME: unmarshall */
+
+  fprintf(proxy, "    NdrProxyFreeBuffer(This, &_StubMsg);\n");
+
+  if (has_ret) {
+    fprintf(proxy, "    return _Ret;\n");
+  }
+  fprintf(proxy, "}\n");
+  fprintf(proxy, "\n");
+}
+
+static void gen_stub(type_t *iface, func_t *cur, char *cas)
+{
+  var_t *def = cur->def;
+  var_t *arg;
+  int has_ret = !is_void(def->type, def);
+
+  fprintf(proxy, "void __RPC_STUB %s_", iface->name);
+  write_name(proxy, def);
+  fprintf(proxy, "_Stub(\n");
+  fprintf(proxy, "    IRpcStubBuffer* This,\n");
+  fprintf(proxy, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
+  fprintf(proxy, "    PRPC_MESSAGE pRpcMessage,\n");
+  fprintf(proxy, "    DWORD* pdwStubPhase)\n");
+  fprintf(proxy, "{\n");
+  /* local variables */
+  if (has_ret) {
+    fprintf(proxy, "    ");
+    write_type(proxy, def->type, def, def->tname);
+    fprintf(proxy, " _Ret;\n");
+  }
+  fprintf(proxy, "    %s* _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name);
+  fprintf(proxy, "    MIDL_STUB_MESSAGE _StubMsg;\n");
+  arg = cur->args;
+  while (arg) {
+    fprintf(proxy, "    ");
+    write_type(proxy, arg->type, arg, arg->tname);
+    fprintf(proxy, " ");
+    write_name(proxy, arg);
+    fprintf(proxy, ";\n");
+    arg = NEXT_LINK(arg);
+  }
+  fprintf(proxy, "\n");
+
+  /* FIXME: trace */
+  /* FIXME: clear output vars? */
+
+  fprintf(proxy, "    NdrStubInitialize(pRpcMessage, &_StubMsg, &Object_StubDesc, pRpcChannelBuffer);\n");
+
+  /* FIXME: unmarshall */
+
+  fprintf(proxy, "    *pdwStubPhase = STUB_CALL_SERVER;\n");
+  fprintf(proxy, "    ");
+  if (has_ret) fprintf(proxy, "_Ret = ");
+  fprintf(proxy, "%s_", iface->name);
+  if (cas) fprintf(proxy, "%s_Stub", cas);
+  else write_name(proxy, def);
+  fprintf(proxy, "(_This");
+  arg = cur->args;
+  if (arg) {
+    while (NEXT_LINK(arg)) arg = NEXT_LINK(arg);
+    while (arg) {
+      fprintf(proxy, ", ");
+      write_name(proxy, arg);
+      arg = PREV_LINK(arg);
+    }
+  }
+  fprintf(proxy, ");\n");
+  fprintf(proxy, "    *pdwStubPhase = STUB_MARSHAL;\n");
+
+  /* FIXME: size buffer */
+
+  fprintf(proxy, "    NdrStubGetBuffer(This, pRpcChannelBuffer, &_StubMsg);\n");
+
+  /* FIXME: marshall */
+
+  fprintf(proxy, "}\n");
+  fprintf(proxy, "\n");
+}
+
+static int write_proxy_methods(type_t *iface)
+{
+  func_t *cur = iface->funcs;
+  int i = 0;
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+
+  if (iface->ref) i = write_proxy_methods(iface->ref);
+  while (cur) {
+    var_t *def = cur->def;
+    if (!is_callas(def->attrs)) {
+      if (i) fprintf(proxy, ",\n     ");
+      fprintf(proxy, "%s_", iface->name);
+      write_name(proxy, def);
+      fprintf(proxy, "_Proxy");
+      i++;
+    }
+    cur = PREV_LINK(cur);
+  }
+  return i;
+}
+
+static int write_stub_methods(type_t *iface)
+{
+  func_t *cur = iface->funcs;
+  int i = 0;
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+
+  if (iface->ref) i = write_stub_methods(iface->ref);
+  else return i; /* skip IUnknown */
+  while (cur) {
+    var_t *def = cur->def;
+    if (!is_local(def->attrs)) {
+      if (i) fprintf(proxy, ",\n");
+      fprintf(proxy, "    %s_", iface->name);
+      write_name(proxy, def);
+      fprintf(proxy, "_Stub");
+      i++;
+    }
+    cur = PREV_LINK(cur);
+  }
+  return i;
+}
+
+typedef struct _if_list if_list;
+struct _if_list {
+  type_t *iface;
+  DECL_LINK(if_list)
+};
+
+if_list *if_first;
+
+void write_proxy(type_t *iface)
+{
+  int midx = -1, stubs;
+  func_t *cur = iface->funcs;
+  if_list *if_cur;
+
+  if (!cur) {
+    yywarning("%s has no methods", iface->name);
+    return;
+  }
+
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+
+  /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */
+
+  init_proxy();
+
+  if_cur = xmalloc(sizeof(if_list));
+  if_cur->iface = iface;
+  INIT_LINK(if_cur);
+  LINK(if_cur, if_first);
+  if_first = if_cur;
+
+  fprintf(proxy, "/*****************************************************************************\n");
+  fprintf(proxy, " * %s interface\n", iface->name);
+  fprintf(proxy, " */\n");
+  while (cur) {
+    var_t *def = cur->def;
+    if (!is_local(def->attrs)) {
+      var_t *cas = is_callas(def->attrs);
+      char *cname = cas ? cas->name : NULL;
+      int idx = cur->idx;
+      if (cname) {
+        func_t *m = iface->funcs;
+        while (m && strcmp(get_name(m->def), cname))
+          m = NEXT_LINK(m);
+        idx = m->idx;
+      }
+      gen_proxy(iface, cur, idx);
+      gen_stub(iface, cur, cname);
+      if (midx == -1) midx = idx;
+      else if (midx != idx) yyerror("method index mismatch in write_proxy");
+      midx++;
+    }
+    cur = PREV_LINK(cur);
+  }
+
+  /* proxy vtable */
+  fprintf(proxy, "const CINTERFACE_PROXY_VTABLE(%d) %sProxyVtbl = {\n", midx, iface->name);
+  fprintf(proxy, "    {&IID_%s},\n", iface->name);
+  fprintf(proxy, "    {");
+  write_proxy_methods(iface);
+  fprintf(proxy, "}\n");
+  fprintf(proxy, "};\n");
+  fprintf(proxy, "\n");
+
+  /* stub vtable */
+  fprintf(proxy, "static const PRPC_STUB_FUNCTION %s_table[] = {\n", iface->name);
+  stubs = write_stub_methods(iface);
+  fprintf(proxy, "\n");
+  fprintf(proxy, "};\n");
+  fprintf(proxy, "\n");
+  fprintf(proxy, "const CInterfaceStubVtbl %sStubVtbl = {\n", iface->name);
+  fprintf(proxy, "    {&IID_%s,\n", iface->name);
+  fprintf(proxy, "     0,\n");
+  fprintf(proxy, "     %d,\n", stubs+3);
+  fprintf(proxy, "     &%s_table[-3]},\n", iface->name);
+  fprintf(proxy, "    {CStdStubBuffer_METHODS}\n");
+  fprintf(proxy, "};\n");
+  fprintf(proxy, "\n");
+}
+
+void finish_proxy(void)
+{
+  if_list *lcur = if_first;
+  if_list *cur;
+  int c;
+
+  if (!lcur) return;
+  while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur);
+
+  fprintf(proxy, "const CInterfaceProxyVtbl* _XXX_ProxyVtblList[] = {\n");
+  cur = lcur;
+  while (cur) {
+    fprintf(proxy, "    (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name);
+    cur = PREV_LINK(cur);
+  }
+  fprintf(proxy, "    0\n");
+  fprintf(proxy, "};\n");
+  fprintf(proxy, "\n");
+
+  fprintf(proxy, "const CInterfaceStubVtbl* _XXX_StubVtblList[] = {\n");
+  cur = lcur;
+  while (cur) {
+    fprintf(proxy, "    (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name);
+    cur = PREV_LINK(cur);
+  }
+  fprintf(proxy, "    0\n");
+  fprintf(proxy, "};\n");
+  fprintf(proxy, "\n");
+
+  fprintf(proxy, "const PCInterfaceName _XXX_InterfaceNamesList[] = {\n");
+  cur = lcur;
+  while (cur) {
+    fprintf(proxy, "    \"%s\",\n", cur->iface->name);
+    cur = PREV_LINK(cur);
+  }
+  fprintf(proxy, "    0\n");
+  fprintf(proxy, "};\n");
+  fprintf(proxy, "\n");
+
+  fprintf(proxy, "#define _XXX_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n");
+  fprintf(proxy, "\n");
+  fprintf(proxy, "int __stdcall _XXX_IID_Lookup(const IID* pIID, int* pIndex)\n");
+  fprintf(proxy, "{\n");
+  cur = lcur;
+  c = 0;
+  while (cur) {
+    fprintf(proxy, "    if (!_XXX_CHECK_IID(%d)) {\n", c);
+    fprintf(proxy, "        *pIndex = %d\n", c);
+    fprintf(proxy, "        return 1;\n");
+    fprintf(proxy, "    }\n");
+    cur = PREV_LINK(cur);
+    c++;
+  }
+  fprintf(proxy, "    return 0;\n");
+  fprintf(proxy, "}\n");
+  fprintf(proxy, "\n");
+
+  fprintf(proxy, "const ExtendedProxyFileInfo XXX_ProxyFileInfo = {\n");
+  fprintf(proxy, "    (PCInterfaceProxyVtblList*)&_XXX_ProxyVtblList,\n");
+  fprintf(proxy, "    (PCInterfaceStubVtblList*)&_XXX_StubVtblList,\n");
+  fprintf(proxy, "    (const PCInterfaceName*)&_XXX_InterfaceNamesList,\n");
+  fprintf(proxy, "    0,\n");
+  fprintf(proxy, "    &_XXX_IID_Lookup,\n");
+  fprintf(proxy, "    %d,\n", c);
+  fprintf(proxy, "    1\n");
+  fprintf(proxy, "};\n");
+
+  fclose(proxy);
+}
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ proxy.h	Sun Jun 30 02:41:34 2002
@@ -0,0 +1,27 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 __WIDL_PROXY_H
+#define __WIDL_PROXY_H
+
+extern void write_proxy(type_t *iface);
+extern void finish_proxy(void);
+
+#endif
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ utils.c	Sun Jun 30 02:38:32 2002
@@ -0,0 +1,418 @@
+/*
+ * Utility routines
+ *
+ * Copyright 1998 Bertho A. Stultiens
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "wine/unicode.h"
+#include "widl.h"
+#include "utils.h"
+#include "parser.h"
+#include "preproc.h"
+
+/* #define WANT_NEAR_INDICATION */
+
+static const union cptable *current_codepage;
+
+#ifdef WANT_NEAR_INDICATION
+void make_print(char *str)
+{
+	while(*str)
+	{
+		if(!isprint(*str))
+			*str = ' ';
+		str++;
+	}
+}
+#endif
+
+static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
+{
+	fprintf(stderr, "%s:%d:%d: %s: ", input_name ? input_name : "stdin", line_number, char_number, t);
+	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);
+	generic_msg(s, "Error", yytext, ap);
+	va_end(ap);
+	exit(1);
+	return 1;
+}
+
+int yywarning(const char *s, ...)
+{
+	va_list ap;
+	va_start(ap, s);
+	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;
+	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);
+}
+
+void error(const char *s, ...)
+{
+	va_list ap;
+	va_start(ap, s);
+	fprintf(stderr, "Error: ");
+	vfprintf(stderr, s, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+	exit(2);
+}
+
+void warning(const char *s, ...)
+{
+	va_list ap;
+	va_start(ap, s);
+	fprintf(stderr, "Warning: ");
+	vfprintf(stderr, s, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+void chat(const char *s, ...)
+{
+	if(debuglevel & DEBUGLEVEL_CHAT)
+	{
+		va_list ap;
+		va_start(ap, s);
+		fprintf(stderr, "FYI: ");
+		vfprintf(stderr, s, ap);
+		fprintf(stderr, "\n");
+		va_end(ap);
+	}
+}
+
+char *dup_basename(const char *name, const char *ext)
+{
+	int namelen;
+	int extlen = strlen(ext);
+	char *base;
+	char *slash;
+
+	if(!name)
+		name = "widl.tab";
+
+	slash = strrchr(name, '/');
+	if (slash)
+		name = slash + 1;
+
+	namelen = strlen(name);
+
+	/* +4 for later extension and +1 for '\0' */
+	base = (char *)xmalloc(namelen +4 +1);
+	strcpy(base, name);
+	if(!strcasecmp(name + namelen-extlen, ext))
+	{
+		base[namelen - extlen] = '\0';
+	}
+	return base;
+}
+
+void *xmalloc(size_t size)
+{
+    void *res;
+
+    assert(size > 0);
+    res = malloc(size);
+    if(res == NULL)
+    {
+	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;
+}
+
+
+void *xrealloc(void *p, size_t size)
+{
+    void *res;
+
+    assert(size > 0);
+    res = realloc(p, size);
+    if(res == NULL)
+    {
+	error("Virtual memory exhausted.\n");
+    }
+    return res;
+}
+
+char *xstrdup(const char *str)
+{
+	char *s;
+
+	assert(str != NULL);
+	s = (char *)xmalloc(strlen(str)+1);
+	return strcpy(s, str);
+}
+
+short *dupcstr2wstr(const char *str)
+{
+	int len;
+	WCHAR *ws;
+
+	if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
+	len = cp_mbstowcs( current_codepage, 0, str, strlen(str), NULL, 0 );
+	ws = xmalloc( sizeof(WCHAR) * (len + 1) );
+	len = cp_mbstowcs( current_codepage, 0, str, strlen(str), ws, len );
+	ws[len] = 0;
+	return ws;
+}
+
+char *dupwstr2cstr(const short *str)
+{
+	int len;
+	char *cs;
+
+	if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
+	len = cp_wcstombs( current_codepage, 0, str, strlenW(str), NULL, 0, NULL, NULL );
+	cs = xmalloc( len + 1 );
+	len = cp_wcstombs( current_codepage, 0, str, strlenW(str),  cs, len, NULL, NULL );
+	cs[len] = 0;
+	return cs;
+}
+
+#if 0
+/*
+ *****************************************************************************
+ * Function	: compare_name_id
+ * Syntax	: int compare_name_id(name_id_t *n1, name_id_t *n2)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+int compare_name_id(name_id_t *n1, name_id_t *n2)
+{
+	if(n1->type == name_ord && n2->type == name_ord)
+	{
+		return n1->name.i_name - n2->name.i_name;
+	}
+	else if(n1->type == name_str && n2->type == name_str)
+	{
+		if(n1->name.s_name->type == str_char
+		&& n2->name.s_name->type == str_char)
+		{
+			return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
+		}
+		else if(n1->name.s_name->type == str_unicode
+		&& n2->name.s_name->type == str_unicode)
+		{
+			return strcmpiW(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
+		}
+		else
+		{
+			internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
+		}
+	}
+	else if(n1->type == name_ord && n2->type == name_str)
+		return 1;
+	else if(n1->type == name_str && n2->type == name_ord)
+		return -1;
+	else
+		internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
+				n1->type, n2->type);
+
+	return 0; /* Keep the compiler happy */
+}
+
+string_t *convert_string(const string_t *str, enum str_e type)
+{
+        string_t *ret = xmalloc(sizeof(*ret));
+
+        if((str->type == str_char) && (type == str_unicode))
+	{
+		ret->str.wstr = dupcstr2wstr(str->str.cstr);
+		ret->type     = str_unicode;
+		ret->size     = strlenW(ret->str.wstr);
+	}
+	else if((str->type == str_unicode) && (type == str_char))
+	{
+	        ret->str.cstr = dupwstr2cstr(str->str.wstr);
+	        ret->type     = str_char;
+	        ret->size     = strlen(ret->str.cstr);
+	}
+	else if(str->type == str_unicode)
+        {
+	        ret->type     = str_unicode;
+		ret->size     = strlenW(str->str.wstr);
+		ret->str.wstr = xmalloc(sizeof(WCHAR)*(ret->size+1));
+		strcpyW(ret->str.wstr, str->str.wstr);
+	}  
+	else /* str->type == str_char */
+        {
+	        ret->type     = str_char;
+		ret->size     = strlen(str->str.cstr);
+		ret->str.cstr = xmalloc( ret->size + 1 );
+		strcpy(ret->str.cstr, str->str.cstr);
+        }
+	return ret;
+}
+#endif
+
+
+struct lang2cp
+{
+    unsigned short lang;
+    unsigned short sublang;
+    unsigned int   cp;
+} lang2cp_t;
+
+/* language to codepage conversion table */
+/* specific sublanguages need only be specified if their codepage */
+/* differs from the default (SUBLANG_NEUTRAL) */
+static const struct lang2cp lang2cps[] =
+{
+    { LANG_AFRIKAANS,      SUBLANG_NEUTRAL,              1252 },
+    { LANG_ALBANIAN,       SUBLANG_NEUTRAL,              1250 },
+    { LANG_ARABIC,         SUBLANG_NEUTRAL,              1256 },
+    { LANG_BASQUE,         SUBLANG_NEUTRAL,              1252 },
+    { LANG_BRETON,         SUBLANG_NEUTRAL,              1252 },
+    { LANG_BULGARIAN,      SUBLANG_NEUTRAL,              1251 },
+    { LANG_BYELORUSSIAN,   SUBLANG_NEUTRAL,              1251 },
+    { LANG_CATALAN,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_CHINESE,        SUBLANG_NEUTRAL,              936  },
+    { LANG_CORNISH,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_CZECH,          SUBLANG_NEUTRAL,              1250 },
+    { LANG_DANISH,         SUBLANG_NEUTRAL,              1252 },
+    { LANG_DUTCH,          SUBLANG_NEUTRAL,              1252 },
+    { LANG_ENGLISH,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_ESPERANTO,      SUBLANG_NEUTRAL,              1252 },
+    { LANG_ESTONIAN,       SUBLANG_NEUTRAL,              1257 },
+    { LANG_FAEROESE,       SUBLANG_NEUTRAL,              1252 },
+    { LANG_FINNISH,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_FRENCH,         SUBLANG_NEUTRAL,              1252 },
+    { LANG_GAELIC,         SUBLANG_NEUTRAL,              1252 },
+    { LANG_GERMAN,         SUBLANG_NEUTRAL,              1252 },
+    { LANG_GREEK,          SUBLANG_NEUTRAL,              1253 },
+    { LANG_HEBREW,         SUBLANG_NEUTRAL,              1255 },
+    { LANG_HUNGARIAN,      SUBLANG_NEUTRAL,              1250 },
+    { LANG_ICELANDIC,      SUBLANG_NEUTRAL,              1252 },
+    { LANG_INDONESIAN,     SUBLANG_NEUTRAL,              1252 },
+    { LANG_ITALIAN,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_JAPANESE,       SUBLANG_NEUTRAL,              932  },
+    { LANG_KOREAN,         SUBLANG_NEUTRAL,              949  },
+    { LANG_LATVIAN,        SUBLANG_NEUTRAL,              1257 },
+    { LANG_LITHUANIAN,     SUBLANG_NEUTRAL,              1257 },
+    { LANG_MACEDONIAN,     SUBLANG_NEUTRAL,              1251 },
+    { LANG_MALAY,          SUBLANG_NEUTRAL,              1252 },
+    { LANG_NEUTRAL,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_NORWEGIAN,      SUBLANG_NEUTRAL,              1252 },
+    { LANG_POLISH,         SUBLANG_NEUTRAL,              1250 },
+    { LANG_PORTUGUESE,     SUBLANG_NEUTRAL,              1252 },
+    { LANG_ROMANIAN,       SUBLANG_NEUTRAL,              1250 },
+    { LANG_RUSSIAN,        SUBLANG_NEUTRAL,              1251 },
+    { LANG_SERBO_CROATIAN, SUBLANG_NEUTRAL,              1250 },
+    { LANG_SERBO_CROATIAN, SUBLANG_SERBIAN,              1251 },
+    { LANG_SLOVAK,         SUBLANG_NEUTRAL,              1250 },
+    { LANG_SLOVENIAN,      SUBLANG_NEUTRAL,              1250 },
+    { LANG_SPANISH,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_SWEDISH,        SUBLANG_NEUTRAL,              1252 },
+    { LANG_THAI,           SUBLANG_NEUTRAL,              874  },
+    { LANG_TURKISH,        SUBLANG_NEUTRAL,              1254 },
+    { LANG_UKRAINIAN,      SUBLANG_NEUTRAL,              1251 },
+    { LANG_VIETNAMESE,     SUBLANG_NEUTRAL,              1258 },
+    { LANG_WALON,          SUBLANG_NEUTRAL,              1252 },
+    { LANG_WELSH,          SUBLANG_NEUTRAL,              1252 }
+};
+
+void set_language( unsigned short lang, unsigned short sublang )
+{
+    unsigned int i;
+    unsigned int cp = 0, defcp = 0;
+
+    for (i = 0; i < sizeof(lang2cps)/sizeof(lang2cps[0]); i++)
+    {
+        if (lang2cps[i].lang != lang) continue;
+        if (lang2cps[i].sublang == sublang)
+        {
+            cp = lang2cps[i].cp;
+            break;
+        }
+        if (lang2cps[i].sublang == SUBLANG_NEUTRAL) defcp = lang2cps[i].cp;
+    }
+
+    if (!cp) cp = defcp;
+    if (!cp)
+        error( "No codepage value for language %04x", MAKELANGID(lang,sublang) );
+    if (!(current_codepage = cp_get_table( cp )))
+        error( "Bad codepage %d for language %04x", cp, MAKELANGID(lang,sublang) );
+}
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ utils.h	Sun Jun 30 02:39:08 2002
@@ -0,0 +1,48 @@
+/*
+ * Utility routines' prototypes etc.
+ *
+ * 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
+ */
+
+#ifndef __WIDL_UTILS_H
+#define __WIDL_UTILS_H
+
+#include "widltypes.h"
+
+#include <stddef.h>	/* size_t */
+
+void *xmalloc(size_t);
+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)));
+void error(const char *s, ...) __attribute__((format (printf, 1, 2)));
+void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
+void chat(const char *s, ...) __attribute__((format (printf, 1, 2)));
+
+char *dup_basename(const char *name, const char *ext);
+char *dupwstr2cstr(const short *str);
+short *dupcstr2wstr(const char *str);
+/* int compare_name_id(name_id_t *n1, name_id_t *n2);
+string_t *convert_string(const string_t *str, enum str_e type); */
+void set_language(unsigned short lang, unsigned short sublang);
+
+#endif
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ widl.c	Sun Jun 30 02:38:52 2002
@@ -0,0 +1,214 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ * based on WRC code by Bertho Stultiens
+ *
+ * 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 <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <signal.h>
+
+#define WIDL_FULLVERSION "0.1"
+
+#include "widl.h"
+#include "utils.h"
+#include "preproc.h"
+#include "parser.h"
+#include "proxy.h"
+
+static char usage[] =
+"Usage: widl [options...] infile.idl\n"
+"   -d n        Set debug level to 'n'\n"
+"   -D id[=val] Define preprocessor identifier id=val\n"
+"   -E          Preprocess only\n"
+"   -H file     Name of header file (default is infile.h)\n"
+"   -I path     Set include search dir to path (multiple -I allowed)\n"
+"   -N          Do not preprocess input\n"
+"   -V          Print version and exit\n"
+"   -W          Enable pedantic warnings\n"
+"Debug level 'n' is a bitmask with following meaning:\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"
+;
+
+char version_string[] = "Wine IDL Compiler Version " WIDL_FULLVERSION "\n"
+			"Copyright 2002 Ove Kaaven\n";
+
+int win32 = 1;
+int debuglevel = DEBUGLEVEL_NONE;
+
+int pedantic = 0;
+int preprocess_only = 0;
+int no_preprocess = 0;
+
+char *input_name;
+char *header_name;
+char *proxy_name;
+char *temp_name;
+
+int line_number = 1;
+int char_number = 1;
+
+FILE *header;
+FILE *proxy;
+
+time_t now;
+
+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[])
+{
+  extern char* optarg;
+  extern int   optind;
+  int optc;
+  int ret;
+
+  signal(SIGSEGV, segvhandler);
+
+  now = time(NULL);
+
+  while((optc = getopt(argc, argv, "d:D:EH:I:NVW")) != EOF) {
+    switch(optc) {
+    case 'd':
+      debuglevel = strtol(optarg, NULL, 0);
+      break;
+    case 'D':
+      add_cmdline_define(optarg);
+      break;
+    case 'E':
+      preprocess_only = 1;
+      break;
+    case 'H':
+      header_name = strdup(optarg);
+      break;
+    case 'I':
+      add_include_path(optarg);
+      break;
+    case 'N':
+      no_preprocess = 1;
+      break;
+    case 'V':
+      printf(version_string);
+      return 0;
+    case 'W':
+      pedantic = 1;
+      break;
+    default:
+      fprintf(stderr, usage);
+      return 1;
+    }
+  }
+
+  if(optind < argc) {
+    input_name = argv[optind];
+  }
+  else {
+    fprintf(stderr, usage);
+    return 1;
+  }
+
+  if(debuglevel)
+  {
+    setbuf(stdout,0);
+    setbuf(stderr,0);
+  }
+
+  yydebug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
+  yy_flex_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
+  ppdebug = debuglevel & DEBUGLEVEL_PPTRACE ? 1 : 0;
+  pp_flex_debug = debuglevel & DEBUGLEVEL_PPLEX ? 1 : 0;
+
+  if (!header_name) {
+    header_name = dup_basename(input_name, ".idl");
+    strcat(header_name, ".h");
+  }
+
+  if (!proxy_name) {
+    proxy_name = dup_basename(input_name, ".idl");
+    strcat(proxy_name, "_p.c");
+  }
+
+  atexit(rm_tempfile);
+  if (!no_preprocess) {
+    char *real_name;
+    chat("Starting preprocess");
+    if(!(temp_name = tmpnam(NULL)))
+      error("Could not generate a temp-name\n");
+    temp_name = xstrdup(temp_name);
+    if(!(ppout = fopen(temp_name, "wb")))
+      error("Could not create a temp-file\n");
+    real_name = input_name;
+    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;
+    fclose(ppin);
+    fclose(ppout);
+    input_name = temp_name;
+    if (ret)
+      exit(1);
+  }
+
+  if(!(yyin = fopen(input_name, "r"))) {
+    fprintf(stderr, "Could not open %s for input\n", input_name);
+    return 1;
+  }
+
+  header = fopen(header_name, "w");
+  fprintf(header, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION);
+
+  ret = yyparse();
+
+  finish_proxy();
+  fclose(header);
+  fclose(yyin);
+
+  if(ret) {
+    exit(1);
+  }
+
+  return 0;
+}
+
+static void rm_tempfile(void)
+{
+  abort_import();
+  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();
+}
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ widl.h	Sun Jun 30 02:46:10 2002
@@ -0,0 +1,53 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 __WIDL_WIDL_H
+#define __WIDL_WIDL_H
+
+#include "widltypes.h"
+
+#include <time.h>
+
+#define WIDL_FULLVERSION "0.1"
+
+extern int debuglevel;
+#define DEBUGLEVEL_NONE		0x0000
+#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 pedantic;
+
+extern char *input_name;
+extern char *header_name;
+extern char *proxy_name;
+extern time_t now;
+
+extern int line_number;
+extern int char_number;
+
+extern FILE* header;
+extern FILE* proxy;
+
+#endif
-------------- next part --------------
--- NUL	Wed Dec 31 19:00:00 1969
+++ widltypes.h	Sun Jun 30 02:46:28 2002
@@ -0,0 +1,97 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2002 Ove Kaaven
+ *
+ * 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 __WIDL_WIDLTYPES_H
+#define __WIDL_WIDLTYPES_H
+
+#include "windef.h"
+#include "oleauto.h"
+#include "wine/rpcfc.h"
+
+typedef struct _attr_t attr_t;
+typedef struct _type_t type_t;
+typedef struct _typeref_t typeref_t;
+typedef struct _var_t var_t;
+typedef struct _func_t func_t;
+
+#define DECL_LINK(type) \
+  type *l_next; \
+  type *l_prev;
+
+#define LINK(x,y) do { x->l_next = y; if (y) y->l_prev = x; } while (0)
+#define LINK_LAST(x,y) do { if (y) { typeof(x) _c = x; while (_c->l_next) _c = _c->l_next; LINK(_c, y); } } while (0)
+#define LINK_SAFE(x,y) do { if (x) LINK_LAST(x,y); else { x = y; } } while (0)
+
+#define INIT_LINK(x) do { x->l_next = NULL; x->l_prev = NULL; } while (0)
+#define NEXT_LINK(x) ((x)->l_next)
+#define PREV_LINK(x) ((x)->l_prev)
+
+struct _attr_t {
+  int type;
+  union {
+    DWORD ival;
+    void *pval;
+  } u;
+  /* parser-internal */
+  DECL_LINK(attr_t)
+};
+
+struct _type_t {
+  char *name;
+  BYTE type;
+  struct _type_t *ref;
+  char *rname;
+  attr_t *attrs;
+  func_t *funcs;
+  var_t *fields;
+  int ignore, is_const;
+  int defined, written;
+
+  /* parser-internal */
+  DECL_LINK(type_t)
+};
+
+struct _typeref_t {
+  char *name;
+  type_t *ref;
+  int uniq;
+};
+
+struct _var_t {
+  char *name;
+  int ptr_level;
+  type_t *type;
+  char *tname;
+  attr_t *attrs;
+
+  /* parser-internal */
+  DECL_LINK(var_t)
+};
+
+struct _func_t {
+  var_t *def;
+  var_t *args;
+  int ignore, idx;
+
+  /* parser-internal */
+  DECL_LINK(func_t)
+};
+
+#endif


More information about the wine-patches mailing list