From e773c516baaf49b9aca0280be5a5bf3af3cca8cd Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Wed, 30 Sep 2009 20:15:38 +0200 Subject: [PATCH] wpp: Add I/O callbacks. --- include/wine/wpp.h | 17 ++++ libs/wpp/ppl.l | 70 ++++++++++++++-- libs/wpp/ppy.y | 14 ++-- libs/wpp/preproc.c | 182 ++++++++++++++++++++++++----------------- libs/wpp/wpp.c | 8 +- libs/wpp/wpp_private.h | 4 +- 6 files changed, 199 insertions(+), 96 deletions(-) diff --git a/include/wine/wpp.h b/include/wine/wpp.h index dd341bdee9..daba277fd2 100644 --- a/include/wine/wpp.h +++ b/include/wine/wpp.h @@ -26,6 +26,23 @@ struct wpp_callbacks { + /* I/O callbacks */ + + /* 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 ); + /* Error callbacks */ void (*error)( const char *file, int line, int col, const char *near, const char *msg, va_list ap ); void (*warning)( const char *file, int line, int col, const char *near, const char *msg, va_list ap ); diff --git a/libs/wpp/ppl.l b/libs/wpp/ppl.l index 48a6959689..05e7af265d 100644 --- a/libs/wpp/ppl.l +++ b/libs/wpp/ppl.l @@ -178,6 +178,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 +206,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 with wpp_callbacks->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 +300,56 @@ include_state_t pp_incl_state = includelogicentry_t *pp_includelogiclist = NULL; +#define YY_INPUT(buf,result,max_size) \ + { \ + result = wpp_callbacks->read(pp_status.file, buf, max_size); \ + } + +#define BUFFERINITIALCAPACITY 256 + +void pp_writestring(const char *format, ...) +{ + va_list valist; + int len; + static char *buffer; + static int buffercapacity; + char *new_buffer; + + if(buffercapacity == 0) + { + buffer = pp_xmalloc(BUFFERINITIALCAPACITY); + if(buffer == NULL) + return; + 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); + + new_buffer = pp_xrealloc(buffer, buffercapacity); + if(new_buffer == NULL) + { + va_end(valist); + return; + } + buffer = new_buffer; + len = vsnprintf(buffer, buffercapacity, + format, valist); + } + va_end(valist); + + wpp_callbacks->write(buffer, len); +} + %} /* @@ -1243,6 +1295,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 = pp_status.file; bufferstack[bufferstackidx].define = ppp; bufferstack[bufferstackidx].line_number = pp_status.line_number; bufferstack[bufferstackidx].char_number = pp_status.char_number; @@ -1284,8 +1337,8 @@ static bufferstackentry_t *pop_buffer(void) { if(!bufferstack[bufferstackidx].should_pop) { - fclose(ppy_in); - fprintf(ppy_out, "# %d \"%s\" 2\n", bufferstack[bufferstackidx].line_number, bufferstack[bufferstackidx].filename); + wpp_callbacks->close(pp_status.file); + pp_writestring("# %d \"%s\" 2\n", bufferstack[bufferstackidx].line_number, bufferstack[bufferstackidx].filename); /* We have EOF, check the include logic */ if(pp_incl_state.state == 2 && !pp_incl_state.seen_junk && pp_incl_state.ppp) @@ -1332,7 +1385,8 @@ static bufferstackentry_t *pop_buffer(void) bufferstack[bufferstackidx].filename, bufferstack[bufferstackidx].should_pop); - ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate); + pp_status.file = bufferstack[bufferstackidx].filehandle; + ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate); if(bufferstack[bufferstackidx].should_pop) { @@ -1499,7 +1553,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); + wpp_callbacks->write(s, len); } @@ -1513,6 +1567,7 @@ void pp_do_include(char *fname, int type) char *newpath; int n; includelogicentry_t *iep; + void *fp; if(!fname) return; @@ -1541,7 +1596,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); return; @@ -1556,9 +1611,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)); + pp_status.file = fp; + ppy__switch_to_buffer(ppy__create_buffer(NULL, YY_BUF_SIZE)); - fprintf(ppy_out, "# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3"); + pp_writestring("# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3"); } /* diff --git a/libs/wpp/ppy.y b/libs/wpp/ppy.y index b525e2fedc..5a63494278 100644 --- a/libs/wpp/ppy.y +++ b/libs/wpp/ppy.y @@ -279,20 +279,20 @@ preprocessor | tMACRO res_arg allmargs tMACROEND opt_mtexts tNL { pp_add_macro($1, macro_args, nmacro_args, $5); } - | tLINE tSINT tDQSTRING tNL { if($3) fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); } - | tGCCLINE tSINT tDQSTRING tNL { if($3) fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); } + | tLINE tSINT tDQSTRING tNL { if($3) pp_writestring("# %d %s\n", $2 , $3); free($3); } + | tGCCLINE tSINT tDQSTRING tNL { if($3) pp_writestring("# %d %s\n", $2 , $3); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tNL - { if($3) fprintf(ppy_out, "# %d %s %d\n", $2, $3, $4); free($3); } + { if($3) pp_writestring("# %d %s %d\n", $2, $3, $4); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tSINT tNL - { if($3) fprintf(ppy_out, "# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); } + { if($3) pp_writestring("# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tNL - { if($3) fprintf(ppy_out, "# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); } + { if($3) pp_writestring("# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tSINT tNL - { if($3) fprintf(ppy_out, "# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free($3); } + { if($3) pp_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 { pp_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 { if($2) diff --git a/libs/wpp/preproc.c b/libs/wpp/preproc.c index 874e54cd24..2eb313350b 100644 --- a/libs/wpp/preproc.c +++ b/libs/wpp/preproc.c @@ -115,6 +115,100 @@ char *pp_xstrdup(const char *str) return memcpy(s, str, len); } +static 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); + if(!cpy) + return NULL; + 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 ); + if(!path) + { + free(cpy); + return NULL; + } + 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); + if(!path) + { + free(cpy); + return NULL; + } + 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; +} + +static void *wpp_default_open(const char *filename, int type) { + return fopen(filename,"rt"); +} + +static void wpp_default_close(void *file) { + fclose(file); +} + +static int wpp_default_read(void *file, char *buffer, unsigned int len){ + return fread(buffer, 1, len, file); +} + +static void wpp_default_write( const char *buffer, unsigned int len ) { + fwrite(buffer, 1, len, ppy_out); +} + /* Don't comment on the hash, its primitive but functional... */ static int pphash(const char *str) { @@ -403,88 +497,17 @@ int 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); - if(!cpy) - return NULL; - 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 ); - if(!path) - { - free(cpy); - return NULL; - } - 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); - if(!path) - { - free(cpy); - return NULL; - } - 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 = wpp_callbacks->lookup(name, parent_name, includepath, + nincludepath))) return NULL; + fp = wpp_callbacks->open(path, parent_name == NULL ? 1 : 0); if (fp) { @@ -687,6 +710,11 @@ static void wpp_default_warning(const char *file, int line, int col, const char static const struct wpp_callbacks default_callbacks = { + wpp_default_lookup, + wpp_default_open, + wpp_default_close, + wpp_default_read, + wpp_default_write, wpp_default_error, wpp_default_warning, }; diff --git a/libs/wpp/wpp.c b/libs/wpp/wpp.c index afca1bb835..935bd49978 100644 --- a/libs/wpp/wpp.c +++ b/libs/wpp/wpp.c @@ -176,8 +176,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) pp_status.file = stdin; + else if (!(pp_status.file = wpp_callbacks->open(input, 1))) { ppy_error("Could not open %s\n", input); return 2; @@ -186,13 +186,13 @@ 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_writestring("# 1 \"%s\" 1\n", input ? input : ""); ret = ppy_parse(); /* If there were errors during processing, return an error code */ if(!ret && pp_status.state) ret = pp_status.state; - if (input) fclose(ppy_in); + if (input) wpp_callbacks->close(pp_status.file); pp_pop_define_state(); return ret; } diff --git a/libs/wpp/wpp_private.h b/libs/wpp/wpp_private.h index e08221351b..615a450920 100644 --- a/libs/wpp/wpp_private.h +++ b/libs/wpp/wpp_private.h @@ -207,7 +207,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); @@ -229,6 +229,7 @@ void pp_internal_error(const char *file, int line, const char *s, ...) __attribu struct pp_status { const char *input; /* current input file name */ + void *file; /* current input file descriptor */ int line_number; /* current line number */ int char_number; /* current char number in line */ int state; /* current error state */ @@ -253,6 +254,7 @@ void pp_do_include(char *fname, int type); void pp_push_ignore_state(void); void pp_pop_ignore_state(void); +void pp_writestring(const char *format, ...) __attribute__((format (printf, 1, 2))); /* * From ppy.y