[13/18] wpp: Add wpp_set_exit_on_error function

Matteo Bruni matteo.mystral at gmail.com
Sun Aug 16 12:53:45 CDT 2009


Currently wpp exits on errors (e.g. syntax errors, file not found).
This is not good when using wpp as a library for wine API, so this
patch adds a wpp_set_exit_on_error function to wpp to choose whether
the parser should exit or keep going when finding an error. Not sure
this is the correct approach tough.
-------------- next part --------------
From f9641c9dc060e7d083319dd43d93a6f47922a077 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Sun, 16 Aug 2009 16:04:07 +0200
Subject: wpp: Add wpp_set_exit_on_error function

Wpp until now exited when it found any error. This patch maintains the same
default behavior, but allows the preprocessor to keep going when it
finds errors (returning an error value if it is the case).
---
 include/wine/wpp.h     |    2 ++
 libs/wpp/ppl.l         |   36 +++++++++++++++++++++++++++---------
 libs/wpp/ppy.y         |   33 +++++++++++++++++++++------------
 libs/wpp/preproc.c     |   13 +++++++++++--
 libs/wpp/wpp.c         |   18 +++++++++++++++---
 libs/wpp/wpp_private.h |    5 ++++-
 6 files changed, 80 insertions(+), 27 deletions(-)

diff --git a/include/wine/wpp.h b/include/wine/wpp.h
index 763c348..a3e61ec 100644
--- a/include/wine/wpp.h
+++ b/include/wine/wpp.h
@@ -28,6 +28,8 @@ extern void wpp_del_define( const char *name );
 extern void wpp_add_cmdline_define( const char *value );
 extern void wpp_set_debug( int lex_debug, int parser_debug, int msg_debug );
 extern void wpp_set_pedantic( int on );
+/* Whether to exit the app on errors (default: true) */
+extern void wpp_set_exit_on_error( int exit );
 extern void wpp_add_include_path( const char *path );
 extern char *wpp_find_include( const char *name, const char *parent_name );
 extern int wpp_parse( const char *input, FILE *output );
diff --git a/libs/wpp/ppl.l b/libs/wpp/ppl.l
index b252d85..d3b3f1a 100644
--- a/libs/wpp/ppl.l
+++ b/libs/wpp/ppl.l
@@ -691,17 +691,20 @@ void writestring( const char *format, ... )
 			if(yy_current_state() == pp_inc)
 				ppy_error("Expected include filename");
 
-			if(yy_current_state() == pp_if)
+			else
 			{
-				ppy_lval.cptr = pp_xstrdup(ppy_text);
-				return tIDENT;
-			}
-			else {
-				if((yy_current_state()==INITIAL) && (strcasecmp(ppy_text,"RCINCLUDE")==0)){
-					yy_push_state(RCINCL);
-					return tRCINCLUDE;
+				if(yy_current_state() == pp_if)
+				{
+					ppy_lval.cptr = pp_xstrdup(ppy_text);
+					return tIDENT;
+				}
+				else {
+					if((yy_current_state()==INITIAL) && (strcasecmp(ppy_text,"RCINCLUDE")==0)){
+						yy_push_state(RCINCL);
+						return tRCINCLUDE;
+					}
+					else put_buffer(ppy_text, ppy_leng);
 				}
-				else put_buffer(ppy_text, ppy_leng);
 			}
 		}
 		else if(!ppp->expanding)
@@ -860,7 +863,10 @@ static int make_number(int radix, YYSTYPE *val, const char *str, int len)
 	ext[0] = len > 2 ? toupper(str[len-3]) : ' ';
 
 	if(!strcmp(ext, "LUL"))
+	{
 		ppy_error("Invalid constant suffix");
+		return 0;
+	}
 	else if(!strcmp(ext, "LLU") || !strcmp(ext, "ULL"))
 	{
 		is_ll++;
@@ -1137,7 +1143,10 @@ static void expand_macro(macexpstackentry_t *mep)
 	assert(ppp->expanding == 0);
 
 	if((ppp->nargs >= 0 && nargs != ppp->nargs) || (ppp->nargs < 0 && nargs < -ppp->nargs))
+	{
 		ppy_error("Too %s macro arguments (%d)", nargs < abs(ppp->nargs) ? "few" : "many", nargs);
+		return;
+	}
 
 	for(n = 0; n < nargs; n++)
 		nnl += mep->nnls[n];
@@ -1377,7 +1386,10 @@ static bufferstackentry_t *pop_buffer(void)
 static void push_macro(pp_entry_t *ppp)
 {
 	if(macexpstackidx >= MAXMACEXPSTACK)
+	{
 		ppy_error("Too many nested macros");
+		return;
+	}
 
 	macexpstack[macexpstackidx] = pp_xmalloc(sizeof(macexpstack[0][0]));
         memset( macexpstack[macexpstackidx], 0, sizeof(macexpstack[0][0]));
@@ -1527,13 +1539,19 @@ void pp_do_include(char *fname, int type)
 	n = strlen(fname);
 
 	if(n <= 2)
+	{
 		ppy_error("Empty include filename");
+		return;
+	}
 
 	/* Undo the effect of the quotation */
 	fname[n-1] = '\0';
 
 	if((fp = pp_open_include(fname+1, type ? pp_status.input : NULL, &newpath)) == NULL)
+	{
 		ppy_error("Unable to open include file %s", fname+1);
+		return;
+	}
 
 	fname[n-1] = *fname;	/* Redo the quotes */
 	push_buffer(NULL, newpath, fname, 0);
diff --git a/libs/wpp/ppy.y b/libs/wpp/ppy.y
index c5723ef..505987a 100644
--- a/libs/wpp/ppy.y
+++ b/libs/wpp/ppy.y
@@ -224,6 +224,9 @@ preprocessor
 		case if_elsetrue:
 		case if_elsefalse:
 			ppy_error("#elif cannot follow #else");
+			break;
+		case if_error:
+			break;
 		default:
 			pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #elif directive", s);
 		}
@@ -247,24 +250,29 @@ preprocessor
 		case if_elsetrue:
 		case if_elsefalse:
 			ppy_error("#else clause already defined");
+			break;
+		case if_error:
+			break;
 		default:
 			pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #else directive", s);
 		}
 		}
 	| tENDIF tNL		{
-		pp_pop_if();
-		if(pp_incl_state.ifdepth == pp_get_if_depth() && pp_incl_state.state == 1)
-		{
-			pp_incl_state.state = 2;
-			pp_incl_state.seen_junk = 0;
-		}
-		else if(pp_incl_state.state != 1)
+		if(pp_pop_if() != if_error)
 		{
-			pp_incl_state.state = -1;
+			if(pp_incl_state.ifdepth == pp_get_if_depth() && pp_incl_state.state == 1)
+			{
+				pp_incl_state.state = 2;
+				pp_incl_state.seen_junk = 0;
+			}
+			else if(pp_incl_state.state != 1)
+			{
+				pp_incl_state.state = -1;
+			}
+			if(pp_status.debug)
+				fprintf(stderr, "tENDIF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
+					pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth);
 		}
-		if(pp_status.debug)
-			fprintf(stderr, "tENDIF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
-				pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth);
 		}
 	| tUNDEF tIDENT tNL	{ pp_del_define($2); free($2); }
 	| tDEFINE opt_text tNL	{ pp_add_define($1, $2); }
@@ -346,7 +354,8 @@ mtext	: tLITERAL	{ $$ = new_mtext($1, 0, exp_text); }
 		int mat = marg_index($2);
 		if(mat < 0)
 			ppy_error("Stringification identifier must be an argument parameter");
-		$$ = new_mtext(NULL, mat, exp_stringize);
+		else
+			$$ = new_mtext(NULL, mat, exp_stringize);
 		}
 	| tIDENT	{
 		int mat = marg_index($1);
diff --git a/libs/wpp/preproc.c b/libs/wpp/preproc.c
index c3e5ff0..4fc9a91 100644
--- a/libs/wpp/preproc.c
+++ b/libs/wpp/preproc.c
@@ -36,7 +36,8 @@
 #include "wine/wpp.h"
 #include "wpp_private.h"
 
-struct pp_status pp_status;
+/* initialize pp_status, enabling exit_on_error by default */
+struct pp_status pp_status = {NULL, 0, 0, 0, 0, 0, 1};
 
 #define HASHKEY		2039
 
@@ -552,13 +553,18 @@ void pp_push_if(pp_if_state_t s)
 	case if_ignore:
 		pp_push_ignore_state();
 		break;
+	default:
+		pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d)", (int)pp_if_state());
 	}
 }
 
 pp_if_state_t pp_pop_if(void)
 {
 	if(if_stack_idx <= 0)
+	{
 		ppy_error("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
+		return if_error;
+	}
 
 	switch(pp_if_state())
 	{
@@ -571,6 +577,8 @@ pp_if_state_t pp_pop_if(void)
 	case if_ignore:
 		pp_pop_ignore_state();
 		break;
+	default:
+		pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d)", (int)pp_if_state());
 	}
 
 	if(pp_flex_debug)
@@ -646,7 +654,8 @@ int ppy_error(const char *s, ...)
 	va_start(ap, s);
 	generic_msg(s, "Error", ppy_text, ap);
 	va_end(ap);
-	exit(1);
+	if(pp_status.exit_on_error) exit(1);
+	else pp_status.state = 1;
 	return 1;
 }
 
diff --git a/libs/wpp/wpp.c b/libs/wpp/wpp.c
index 9130812..14fabd7 100644
--- a/libs/wpp/wpp.c
+++ b/libs/wpp/wpp.c
@@ -137,6 +137,12 @@ void wpp_set_pedantic( int on )
     pp_status.pedantic = on;
 }
 
+/* set the flag for exit-on-error */
+void wpp_set_exit_on_error( int exit )
+{
+    pp_status.exit_on_error = exit;
+}
+
 
 /* the main preprocessor parsing loop */
 int wpp_parse( const char *input, FILE *output )
@@ -144,6 +150,7 @@ int wpp_parse( const char *input, FILE *output )
     int ret;
 
     pp_status.input = NULL;
+    pp_status.state = 0;
 
     pp_push_define_state();
     add_cmdline_defines();
@@ -153,7 +160,8 @@ int wpp_parse( const char *input, FILE *output )
     else if (!(currentfile = io_callback->open(input, 1)))
     {
         fprintf(stderr,"Could not open %s\n", input);
-        exit(2);
+        if(pp_status.exit_on_error) exit(2);
+        else return 2;
     }
 
     pp_status.input = input;
@@ -162,6 +170,8 @@ int wpp_parse( const char *input, FILE *output )
     writestring("# 1 \"%s\" 1\n", input ? input : "");
 
     ret = ppy_parse();
+    /* if errors happened during the processing, return an error code */
+    if(!ret && pp_status.state) ret = pp_status.state;
 
     if (input) io_callback->close(currentfile);
     pp_pop_define_state();
@@ -185,13 +195,15 @@ int wpp_parse_temp( const char *input, const char *output_base, char **output_na
     if((fd = mkstemps( temp_name, 0 )) == -1)
     {
         fprintf(stderr, "Could not generate a temp name from %s\n", temp_name);
-        exit(2);
+        if(pp_status.exit_on_error) exit(2);
+        else return 2;
     }
 
     if (!(output = fdopen(fd, "wt")))
     {
         fprintf(stderr,"Could not open fd %s for writing\n", temp_name);
-        exit(2);
+        if(pp_status.exit_on_error) exit(2);
+        else return 2;
     }
 
     *output_name = temp_name;
diff --git a/libs/wpp/wpp_private.h b/libs/wpp/wpp_private.h
index d04fab8..f9c6acc 100644
--- a/libs/wpp/wpp_private.h
+++ b/libs/wpp/wpp_private.h
@@ -113,7 +113,8 @@ typedef enum {
 	if_elif,
 	if_elsefalse,
 	if_elsetrue,
-	if_ignore
+	if_ignore,
+	if_error
 } pp_if_state_t;
 
 
@@ -231,8 +232,10 @@ struct pp_status
     const char *input;  /* current input file name */
     int line_number;    /* current line number */
     int char_number;    /* current char number in line */
+    int state;          /* current error state */
     int pedantic;       /* pedantic option */
     int debug;          /* debug messages flag */
+    int exit_on_error;  /* whether to exit() on errors */
 };
 
 extern struct pp_status pp_status;
-- 
1.6.3.3


More information about the wine-patches mailing list