[1/6] wpp: Add I/O hooks

Matteo Bruni matteo.mystral at gmail.com
Thu Sep 10 10:40:10 CDT 2009


Hi,
this patch series modifies wpp to allow its use from wine dlls, as
needed by the d3d shader assembler.

Specifically this is mostly the same patch as the last send, with just
some adjustments to fit better in the series.
Again, you can look at
[http://www.winehq.org/pipermail/wine-patches/2009-August/077205.html]
and [http://www.winehq.org/pipermail/wine-patches/2009-August/077206.html]
for a couple of use cases for this patch (they are based on an old
version of this patch but they should be understandable).
-------------- next part --------------
From 0cd6fe3fec0000c8bf5b20890115fce310c74bf4 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Mon, 24 Aug 2009 00:38:53 +0200
Subject: wpp: Add I/O hooks

---
 include/wine/wpp.h     |   19 ++++++
 libs/wpp/ppl.l         |   65 +++++++++++++++++--
 libs/wpp/ppy.y         |   16 +++---
 libs/wpp/preproc.c     |  163 +++++++++++++++++++++++++++++-------------------
 libs/wpp/wpp.c         |   16 ++++-
 libs/wpp/wpp_private.h |    6 ++-
 6 files changed, 200 insertions(+), 85 deletions(-)

diff --git a/include/wine/wpp.h b/include/wine/wpp.h
index 10b71e0..525db81 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 **include_path, int include_path_count );
+    /* 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_io_callback( struct wpp_io_callback *callback );
+
 #endif  /* __WINE_WPP_H */
diff --git a/libs/wpp/ppl.l b/libs/wpp/ppl.l
index e71bf6e..6091d3f 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,50 @@ 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);	\
+/*if(result < max_size) ((char *)buf)[result] = YY_NULL;*/		\
+	}
+
+#define BUFFERINITIALCAPACITY 256
+
+void writestring(const char *format, ...)
+{
+	va_list valist;
+	int len;
+	static char *buffer;
+	static int buffercapacity;
+
+	if(buffercapacity == 0)
+	{
+		buffer = pp_xmalloc(BUFFERINITIALCAPACITY);
+		buffercapacity = BUFFERINITIALCAPACITY;
+	}
+
+	va_start(valist, format);
+	len = vsnprintf(buffer, buffercapacity,
+			format, valist);
+        /* If the string is longer than buffersize, vsnprintf returns
+         * the string length with glibc >= 2.1, -1 with glibc < 2.1 */
+	while(len > buffercapacity || len < 0)
+	{
+		do
+		{
+			buffercapacity *= 2;
+		} while(len > buffercapacity);
+
+		buffer = pp_xrealloc(buffer, buffercapacity);
+		len = vsnprintf(buffer, buffercapacity,
+				format, valist);
+	}
+	va_end(valist);
+
+	io_callback->write(buffer, len);
+}
+
 %}
 
 /*
@@ -1214,6 +1261,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 +1307,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);
+			writestring("# %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 +1348,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 +1490,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 +1504,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 +1527,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 +1539,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");
+	writestring("# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3");
 }
 
 /*
diff --git a/libs/wpp/ppy.y b/libs/wpp/ppy.y
index fc94bb5..c5723ef 100644
--- a/libs/wpp/ppy.y
+++ b/libs/wpp/ppy.y
@@ -264,27 +264,27 @@ preprocessor
 		}
 		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);
+				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); }
 	| 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	{ writestring("# %d %s\n", $2 , $3); free($3); }
+	| tGCCLINE tSINT tDQSTRING tNL	{ writestring("# %d %s\n", $2 , $3); free($3); }
 	| tGCCLINE tSINT tDQSTRING tSINT tNL
-		{ fprintf(ppy_out, "# %d %s %d\n", $2, $3, $4); free($3); }
+		{ writestring("# %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); }
+		{ writestring("# %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); }
+		{ writestring("# %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); }
+		{ writestring("# %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	{ writestring("#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..c3e5ff0 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 **include_path, int include_path_count)
+{
+    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 < include_path_count; i++)
+    {
+        path = pp_xmalloc(strlen(include_path[i]) + strlen(cpy) + 2);
+        strcpy(path, include_path[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..0a16a02 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,11 @@ int wpp_parse( const char *input, FILE *output )
     pp_status.input = input;
 
     ppy_out = output;
-    fprintf(ppy_out, "# 1 \"%s\" 1\n", input ? input : "");
+    writestring("# 1 \"%s\" 1\n", input ? input : "");
 
     ret = ppy_parse();
 
-    if (input) fclose(ppy_in);
+    if (input) io_callback->close(currentfile);
     pp_pop_define_state();
     return ret;
 }
@@ -199,3 +199,11 @@ int wpp_parse_temp( const char *input, const char *output_base, char **output_na
     fclose( output );
     return ret;
 }
+
+void wpp_set_io_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..d04fab8 100644
--- a/libs/wpp/wpp_private.h
+++ b/libs/wpp/wpp_private.h
@@ -195,6 +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);
@@ -206,7 +209,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 +252,7 @@ void pp_do_include(char *fname, int type);
 void pp_push_ignore_state(void);
 void pp_pop_ignore_state(void);
 
+void writestring(const char *format, ...);
 
 /*
  * From ppy.y
-- 
1.6.3.3


More information about the wine-patches mailing list