wpp: add I/O hooks [try 2]

Matteo Bruni matteo.mystral at gmail.com
Tue Jul 14 17:13:43 CDT 2009


Interface reworked to have read()/write() as the two fundamental
callbacks. Also uses a (void *) variable to store the generic file
descriptor.
It now uses a dynamically resized buffer to prepare the strings to
write to output, in the pp_write_string function. Is it ok? Or better
to simply use a fixed size array?

Regards,
Matteo Bruni
-------------- next part --------------
From d57556c2cb1b95b4934d1321076583120ceba96b Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Tue, 14 Jul 2009 23:21:14 +0200
Subject: wpp: add I/O hooks

---
 include/wine/wpp.h     |   19 ++++++
 libs/wpp/ppl.l         |   75 ++++++++++++++++++++--
 libs/wpp/ppy.y         |   14 ++--
 libs/wpp/preproc.c     |  163 +++++++++++++++++++++++++++++-------------------
 libs/wpp/wpp.c         |   17 ++++-
 libs/wpp/wpp_private.h |    8 ++-
 6 files changed, 211 insertions(+), 85 deletions(-)

diff --git a/include/wine/wpp.h b/include/wine/wpp.h
index 10b71e0..0743d2f 100644
--- a/include/wine/wpp.h
+++ b/include/wine/wpp.h
@@ -33,4 +33,23 @@ extern char *wpp_find_include( const char *name, const char *parent_name );
 extern int wpp_parse( const char *input, FILE *output );
 extern int wpp_parse_temp( const char *input, const char *output_base, char **output_name );
 
+struct wpp_io_callback {
+    /* looks for a file to include, returning the path where it is found */
+    /* parent_name is the directory of the parent source file (for local
+     * includes), includepath is an array of additional include paths */
+    char *(*lookup)( const char *filename, const char *parent_name,
+                      char **includepath, int nincludepath );
+    /* opens an include file */
+    /* the type param is true if it is a local ("...") include */
+    void *(*open)( const char *filename, int type );
+    /* closes a previously opened file */
+    void (*close)( void *file );
+    /* reads buffer from the input */
+    int (*read)( void *file, char *buffer, unsigned int len );
+    /* writes buffer to the output */
+    void (*write)( const char *buffer, unsigned int len );
+};
+
+void wpp_set_callback( struct wpp_io_callback *callback );
+
 #endif  /* __WINE_WPP_H */
diff --git a/libs/wpp/ppl.l b/libs/wpp/ppl.l
index e71bf6e..c377a61 100644
--- a/libs/wpp/ppl.l
+++ b/libs/wpp/ppl.l
@@ -160,6 +160,7 @@ ul	[uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL]
 #include "wine/port.h"
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include <ctype.h>
 #include <assert.h>
@@ -178,6 +179,7 @@ ul	[uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL]
 #define YY_NO_UNISTD_H
 #endif
 
+#include "wine/wpp.h"
 #include "wpp_private.h"
 #include "ppy.tab.h"
 
@@ -205,6 +207,7 @@ ul	[uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL]
 
 typedef struct bufferstackentry {
 	YY_BUFFER_STATE	bufferstate;	/* Buffer to switch back to */
+	void *filehandle;               /* Handle to be used for io_callback->read */
 	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 */
@@ -298,6 +301,60 @@ include_state_t pp_incl_state =
 
 includelogicentry_t *pp_includelogiclist = NULL;
 
+void *currentfile;
+
+#define YY_INPUT(buf,result,max_size)				        \
+	{							        \
+		result = io_callback->read(currentfile,buf,max_size);	\
+	}
+
+#define BUFFERINITIALCAPACITY 256
+
+char *stringbuffer;
+int stringbuffercapacity;
+
+void pp_write_string(const char *format, ...)
+{
+	va_list valist;
+	int len;
+
+	if(stringbuffercapacity == 0){
+		stringbuffer = pp_xmalloc( BUFFERINITIALCAPACITY );
+		if(!stringbuffer){
+			fprintf(stderr, "Error allocating memory\n");
+			exit(2);
+		}
+		stringbuffercapacity = BUFFERINITIALCAPACITY;
+	}
+
+	/* This use of vsprintf requires glibc ver >= 2.1 */
+	va_start(valist, format);
+	len=vsnprintf(stringbuffer, stringbuffercapacity,
+		      format, valist);
+    
+	if(len > stringbuffercapacity){
+		while(len > stringbuffercapacity){
+			stringbuffercapacity *= 2;
+		}
+		stringbuffer = pp_xrealloc(stringbuffer, stringbuffercapacity);
+		if(!stringbuffer){
+			fprintf(stderr, "Error allocating memory\n");
+			exit(2);
+		}
+		vsnprintf(stringbuffer, stringbuffercapacity,
+			  format, valist);
+	}
+	va_end(valist);
+
+	io_callback->write(stringbuffer, len);
+}
+
+void pp_end_parsing(void){
+	free(stringbuffer);
+	stringbuffer=0;
+	stringbuffercapacity=0;
+}
+
 %}
 
 /*
@@ -1214,6 +1271,7 @@ static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop)
 
 	memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0]));
 	bufferstack[bufferstackidx].bufferstate	= YY_CURRENT_BUFFER;
+	bufferstack[bufferstackidx].filehandle  = currentfile;
 	bufferstack[bufferstackidx].define	= ppp;
 	bufferstack[bufferstackidx].line_number	= pp_status.line_number;
 	bufferstack[bufferstackidx].char_number	= pp_status.char_number;
@@ -1259,8 +1317,8 @@ static bufferstackentry_t *pop_buffer(void)
 		ncontinuations = bufferstack[bufferstackidx].ncontinuations;
 		if(!bufferstack[bufferstackidx].should_pop)
 		{
-			fclose(ppy_in);
-			fprintf(ppy_out, "# %d \"%s\" 2\n", pp_status.line_number, pp_status.input);
+			io_callback->close(currentfile);
+			pp_write_string("# %d \"%s\" 2\n", pp_status.line_number, pp_status.input);
 
 			/* We have EOF, check the include logic */
 			if(pp_incl_state.state == 2 && !pp_incl_state.seen_junk && pp_incl_state.ppp)
@@ -1300,7 +1358,8 @@ static bufferstackentry_t *pop_buffer(void)
 			bufferstack[bufferstackidx].filename,
 			bufferstack[bufferstackidx].should_pop);
 
-        ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate);
+	currentfile = bufferstack[bufferstackidx].filehandle;
+	ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate);
 
 	if(bufferstack[bufferstackidx].should_pop)
 	{
@@ -1441,7 +1500,7 @@ static void put_buffer(const char *s, int len)
 	if(top_macro())
 		add_text_to_macro(s, len);
 	else
-           fwrite(s, 1, len, ppy_out);
+		io_callback->write(s, len);
 }
 
 
@@ -1455,6 +1514,7 @@ void pp_do_include(char *fname, int type)
 	char *newpath;
 	int n;
 	includelogicentry_t *iep;
+	void *fp;
 
 	for(iep = pp_includelogiclist; iep; iep = iep->next)
 	{
@@ -1477,7 +1537,7 @@ void pp_do_include(char *fname, int type)
 	/* Undo the effect of the quotation */
 	fname[n-1] = '\0';
 
-	if((ppy_in = pp_open_include(fname+1, type ? pp_status.input : NULL, &newpath)) == NULL)
+	if((fp = pp_open_include(fname+1, type ? pp_status.input : NULL, &newpath)) == NULL)
 		ppy_error("Unable to open include file %s", fname+1);
 
 	fname[n-1] = *fname;	/* Redo the quotes */
@@ -1489,9 +1549,10 @@ void pp_do_include(char *fname, int type)
 	if(pp_status.debug)
 		fprintf(stderr, "pp_do_include: %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);
-        ppy__switch_to_buffer(ppy__create_buffer(ppy_in, YY_BUF_SIZE));
+	currentfile = fp;
+	ppy__switch_to_buffer(ppy__create_buffer(NULL, YY_BUF_SIZE));
 
-	fprintf(ppy_out, "# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3");
+	pp_write_string("# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3");
 }
 
 /*
diff --git a/libs/wpp/ppy.y b/libs/wpp/ppy.y
index fc94bb5..576b408 100644
--- a/libs/wpp/ppy.y
+++ b/libs/wpp/ppy.y
@@ -271,20 +271,20 @@ preprocessor
 	| tMACRO res_arg allmargs tMACROEND opt_mtexts tNL	{
 		pp_add_macro($1, macro_args, nmacro_args, $5);
 		}
-	| tLINE tSINT tDQSTRING	tNL	{ fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); }
-	| tGCCLINE tSINT tDQSTRING tNL	{ fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); }
+	| tLINE tSINT tDQSTRING	tNL	{ pp_write_string("# %d %s\n", $2 , $3); free($3); }
+	| tGCCLINE tSINT tDQSTRING tNL	{ pp_write_string("# %d %s\n", $2 , $3); free($3); }
 	| tGCCLINE tSINT tDQSTRING tSINT tNL
-		{ fprintf(ppy_out, "# %d %s %d\n", $2, $3, $4); free($3); }
+		{ pp_write_string("# %d %s %d\n", $2, $3, $4); free($3); }
 	| tGCCLINE tSINT tDQSTRING tSINT tSINT tNL
-		{ fprintf(ppy_out, "# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); }
+		{ pp_write_string("# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); }
 	| tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT  tNL
-		{ fprintf(ppy_out, "# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); }
+		{ pp_write_string("# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); }
 	| tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tSINT tNL
-		{ fprintf(ppy_out, "# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free($3); }
+		{ pp_write_string("# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free($3); }
 	| tGCCLINE tNL		/* The null-token */
 	| tERROR opt_text tNL	{ ppy_error("#error directive: '%s'", $2); free($2); }
 	| tWARNING opt_text tNL	{ ppy_warning("#warning directive: '%s'", $2); free($2); }
-	| tPRAGMA opt_text tNL	{ fprintf(ppy_out, "#pragma %s\n", $2 ? $2 : ""); free($2); }
+	| tPRAGMA opt_text tNL	{ pp_write_string("#pragma %s\n", $2 ? $2 : ""); free($2); }
 	| tPPIDENT opt_text tNL	{ if(pp_status.pedantic) ppy_warning("#ident ignored (arg: '%s')", $2); free($2); }
         | tRCINCLUDE tRCINCLUDEPATH {
                 int nl=strlen($2) +3;
diff --git a/libs/wpp/preproc.c b/libs/wpp/preproc.c
index 63455ce..f2bda1e 100644
--- a/libs/wpp/preproc.c
+++ b/libs/wpp/preproc.c
@@ -113,6 +113,98 @@ char *pp_xstrdup(const char *str)
 	return memcpy(s, str, len);
 }
 
+char *wpp_default_lookup( const char *name, const char *parent_name,
+                          char **includepath, int nincludepath )
+{
+    char *cpy;
+    char *cptr;
+    char *path;
+    const char *ccptr;
+    int i, fd;
+
+    cpy = pp_xmalloc(strlen(name)+1);
+    cptr = cpy;
+
+    for(ccptr = name; *ccptr; ccptr++)
+    {
+        /* Convert to forward slash */
+        if(*ccptr == '\\') {
+            /* kill double backslash */
+            if(ccptr[1] == '\\')
+                ccptr++;
+            *cptr = '/';
+        }else {
+            *cptr = *ccptr;
+        }
+        cptr++;
+    }
+    *cptr = '\0';
+
+    if(parent_name)
+    {
+        /* Search directory of parent include and then -I path */
+        const char *p;
+
+        if ((p = strrchr( parent_name, '/' ))) p++;
+        else p = parent_name;
+        path = pp_xmalloc( (p - parent_name) + strlen(cpy) + 1 );
+        memcpy( path, parent_name, p - parent_name );
+        strcpy( path + (p - parent_name), cpy );
+        fd = open( path, O_RDONLY );
+        if (fd != -1)
+        {
+            close( fd );
+            free( cpy );
+            return path;
+        }
+        free( path );
+    }
+    /* Search -I path */
+    for(i = 0; i < nincludepath; i++)
+    {
+        path = pp_xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
+        strcpy(path, includepath[i]);
+        strcat(path, "/");
+        strcat(path, cpy);
+        fd = open( path, O_RDONLY );
+        if (fd != -1)
+        {
+            close( fd );
+            free( cpy );
+            return path;
+        }
+        free( path );
+    }
+    free( cpy );
+    return NULL;
+}
+
+void *wpp_default_open(const char *filename, int type) {
+    return fopen(filename,"rt");
+}
+
+void wpp_default_close(void *file) {
+    fclose(file);
+}
+
+int wpp_default_read(void *file, char *buffer, unsigned int len){
+    return fread(buffer, 1, len, file);
+}
+
+void wpp_default_write( const char *buffer, unsigned int len ) {
+    fwrite(buffer, 1, len, ppy_out);
+}
+
+struct wpp_io_callback default_callback = {
+    wpp_default_lookup,
+    wpp_default_open,
+    wpp_default_close,
+    wpp_default_read,
+    wpp_default_write,
+};
+
+struct wpp_io_callback *io_callback = &default_callback;
+
 /* Don't comment on the hash, its primitive but functional... */
 static int pphash(const char *str)
 {
@@ -358,76 +450,17 @@ void wpp_add_include_path(const char *path)
 
 char *wpp_find_include(const char *name, const char *parent_name)
 {
-    char *cpy;
-    char *cptr;
-    char *path;
-    const char *ccptr;
-    int i, fd;
-
-    cpy = pp_xmalloc(strlen(name)+1);
-    cptr = cpy;
-
-    for(ccptr = name; *ccptr; ccptr++)
-    {
-        /* Convert to forward slash */
-        if(*ccptr == '\\') {
-            /* kill double backslash */
-            if(ccptr[1] == '\\')
-                ccptr++;
-            *cptr = '/';
-        }else {
-            *cptr = *ccptr;
-        }
-        cptr++;
-    }
-    *cptr = '\0';
-
-    if(parent_name)
-    {
-        /* Search directory of parent include and then -I path */
-        const char *p;
-
-        if ((p = strrchr( parent_name, '/' ))) p++;
-        else p = parent_name;
-        path = pp_xmalloc( (p - parent_name) + strlen(cpy) + 1 );
-        memcpy( path, parent_name, p - parent_name );
-        strcpy( path + (p - parent_name), cpy );
-        fd = open( path, O_RDONLY );
-        if (fd != -1)
-        {
-            close( fd );
-            free( cpy );
-            return path;
-        }
-        free( path );
-    }
-    /* Search -I path */
-    for(i = 0; i < nincludepath; i++)
-    {
-        path = pp_xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
-        strcpy(path, includepath[i]);
-        strcat(path, "/");
-        strcat(path, cpy);
-        fd = open( path, O_RDONLY );
-        if (fd != -1)
-        {
-            close( fd );
-            free( cpy );
-            return path;
-        }
-        free( path );
-    }
-    free( cpy );
-    return NULL;
+    return wpp_default_lookup(name, parent_name, includepath, nincludepath);
 }
 
-FILE *pp_open_include(const char *name, const char *parent_name, char **newpath)
+void *pp_open_include(const char *name, const char *parent_name, char **newpath)
 {
     char *path;
-    FILE *fp;
+    void *fp;
 
-    if (!(path = wpp_find_include( name, parent_name ))) return NULL;
-    fp = fopen(path, "rt");
+    if (!(path = io_callback->lookup( name, parent_name, includepath,
+				      nincludepath))) return NULL;
+    fp = io_callback->open(path, parent_name==NULL ? 1 : 0);
 
     if (fp)
     {
diff --git a/libs/wpp/wpp.c b/libs/wpp/wpp.c
index d149591..5314e91 100644
--- a/libs/wpp/wpp.c
+++ b/libs/wpp/wpp.c
@@ -149,8 +149,8 @@ int wpp_parse( const char *input, FILE *output )
     add_cmdline_defines();
     add_special_defines();
 
-    if (!input) ppy_in = stdin;
-    else if (!(ppy_in = fopen(input, "rt")))
+    if (!input) currentfile = stdin;
+    else if (!(currentfile = io_callback->open(input, 1)))
     {
         fprintf(stderr,"Could not open %s\n", input);
         exit(2);
@@ -159,11 +159,12 @@ int wpp_parse( const char *input, FILE *output )
     pp_status.input = input;
 
     ppy_out = output;
-    fprintf(ppy_out, "# 1 \"%s\" 1\n", input ? input : "");
+    pp_write_string("# 1 \"%s\" 1\n", input ? input : "");
 
     ret = ppy_parse();
 
-    if (input) fclose(ppy_in);
+    pp_end_parsing();
+    if (input) io_callback->close(currentfile);
     pp_pop_define_state();
     return ret;
 }
@@ -199,3 +200,11 @@ int wpp_parse_temp( const char *input, const char *output_base, char **output_na
     fclose( output );
     return ret;
 }
+
+void wpp_set_callback( struct wpp_io_callback *callback )
+{
+    if(callback == NULL){
+        io_callback = &default_callback;
+    }
+    else io_callback = callback;
+}
diff --git a/libs/wpp/wpp_private.h b/libs/wpp/wpp_private.h
index 24ed6b8..8f9d61c 100644
--- a/libs/wpp/wpp_private.h
+++ b/libs/wpp/wpp_private.h
@@ -195,7 +195,9 @@ typedef struct cval {
 	} val;
 } cval_t;
 
-
+extern struct wpp_io_callback *io_callback;
+extern struct wpp_io_callback default_callback;
+extern void *currentfile;
 
 void *pp_xmalloc(size_t);
 void *pp_xrealloc(void *, size_t);
@@ -206,7 +208,7 @@ void pp_pop_define_state(void);
 pp_entry_t *pp_add_define(char *def, char *text);
 pp_entry_t *pp_add_macro(char *ident, marg_t *args[], int nargs, mtext_t *exp);
 void pp_del_define(const char *name);
-FILE *pp_open_include(const char *name, const char *parent_name, char **newpath);
+void *pp_open_include(const char *name, const char *parent_name, char **newpath);
 void pp_push_if(pp_if_state_t s);
 void pp_next_if_state(int);
 pp_if_state_t pp_pop_if(void);
@@ -249,6 +251,8 @@ void pp_do_include(char *fname, int type);
 void pp_push_ignore_state(void);
 void pp_pop_ignore_state(void);
 
+void pp_write_string(const char *format, ...);
+void pp_end_parsing(void);
 
 /*
  * From ppy.y
-- 
1.6.3.3


More information about the wine-patches mailing list