wpp: Add I/O callbacks.

This commit is contained in:
Matteo Bruni 2009-09-30 20:15:38 +02:00 committed by Alexandre Julliard
parent 17c1881953
commit e773c516ba
6 changed files with 199 additions and 96 deletions

View File

@ -26,6 +26,23 @@
struct wpp_callbacks 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 */ /* Error callbacks */
void (*error)( const char *file, int line, int col, const char *near, const char *msg, va_list ap ); 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 ); void (*warning)( const char *file, int line, int col, const char *near, const char *msg, va_list ap );

View File

@ -178,6 +178,7 @@ ul [uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL]
#define YY_NO_UNISTD_H #define YY_NO_UNISTD_H
#endif #endif
#include "wine/wpp.h"
#include "wpp_private.h" #include "wpp_private.h"
#include "ppy.tab.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 { typedef struct bufferstackentry {
YY_BUFFER_STATE bufferstate; /* Buffer to switch back to */ 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 */ pp_entry_t *define; /* Points to expanding define or NULL if handling includes */
int line_number; /* Line that we were handling */ int line_number; /* Line that we were handling */
int char_number; /* The current position on that line */ int char_number; /* The current position on that line */
@ -298,6 +300,56 @@ include_state_t pp_incl_state =
includelogicentry_t *pp_includelogiclist = NULL; 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])); memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0]));
bufferstack[bufferstackidx].bufferstate = YY_CURRENT_BUFFER; bufferstack[bufferstackidx].bufferstate = YY_CURRENT_BUFFER;
bufferstack[bufferstackidx].filehandle = pp_status.file;
bufferstack[bufferstackidx].define = ppp; bufferstack[bufferstackidx].define = ppp;
bufferstack[bufferstackidx].line_number = pp_status.line_number; bufferstack[bufferstackidx].line_number = pp_status.line_number;
bufferstack[bufferstackidx].char_number = pp_status.char_number; bufferstack[bufferstackidx].char_number = pp_status.char_number;
@ -1284,8 +1337,8 @@ static bufferstackentry_t *pop_buffer(void)
{ {
if(!bufferstack[bufferstackidx].should_pop) if(!bufferstack[bufferstackidx].should_pop)
{ {
fclose(ppy_in); wpp_callbacks->close(pp_status.file);
fprintf(ppy_out, "# %d \"%s\" 2\n", bufferstack[bufferstackidx].line_number, bufferstack[bufferstackidx].filename); pp_writestring("# %d \"%s\" 2\n", bufferstack[bufferstackidx].line_number, bufferstack[bufferstackidx].filename);
/* We have EOF, check the include logic */ /* We have EOF, check the include logic */
if(pp_incl_state.state == 2 && !pp_incl_state.seen_junk && pp_incl_state.ppp) if(pp_incl_state.state == 2 && !pp_incl_state.seen_junk && pp_incl_state.ppp)
@ -1332,6 +1385,7 @@ static bufferstackentry_t *pop_buffer(void)
bufferstack[bufferstackidx].filename, bufferstack[bufferstackidx].filename,
bufferstack[bufferstackidx].should_pop); bufferstack[bufferstackidx].should_pop);
pp_status.file = bufferstack[bufferstackidx].filehandle;
ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate); ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate);
if(bufferstack[bufferstackidx].should_pop) if(bufferstack[bufferstackidx].should_pop)
@ -1499,7 +1553,7 @@ static void put_buffer(const char *s, int len)
if(top_macro()) if(top_macro())
add_text_to_macro(s, len); add_text_to_macro(s, len);
else 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; char *newpath;
int n; int n;
includelogicentry_t *iep; includelogicentry_t *iep;
void *fp;
if(!fname) if(!fname)
return; return;
@ -1541,7 +1596,7 @@ void pp_do_include(char *fname, int type)
/* Undo the effect of the quotation */ /* Undo the effect of the quotation */
fname[n-1] = '\0'; 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); ppy_error("Unable to open include file %s", fname+1);
return; return;
@ -1556,9 +1611,10 @@ void pp_do_include(char *fname, int type)
if(pp_status.debug) if(pp_status.debug)
fprintf(stderr, "pp_do_include: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n", 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); 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");
} }
/* /*

View File

@ -279,20 +279,20 @@ preprocessor
| tMACRO res_arg allmargs tMACROEND opt_mtexts tNL { | tMACRO res_arg allmargs tMACROEND opt_mtexts tNL {
pp_add_macro($1, macro_args, nmacro_args, $5); 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); } | tLINE tSINT tDQSTRING tNL { if($3) pp_writestring("# %d %s\n", $2 , $3); free($3); }
| tGCCLINE tSINT tDQSTRING tNL { if($3) fprintf(ppy_out, "# %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 | 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 | 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 | 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 | 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 */ | tGCCLINE tNL /* The null-token */
| tERROR opt_text tNL { ppy_error("#error directive: '%s'", $2); free($2); } | tERROR opt_text tNL { ppy_error("#error directive: '%s'", $2); free($2); }
| tWARNING opt_text tNL { ppy_warning("#warning 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); } | tPPIDENT opt_text tNL { if(pp_status.pedantic) ppy_warning("#ident ignored (arg: '%s')", $2); free($2); }
| tRCINCLUDE tRCINCLUDEPATH { | tRCINCLUDE tRCINCLUDEPATH {
if($2) if($2)

View File

@ -115,6 +115,100 @@ char *pp_xstrdup(const char *str)
return memcpy(s, str, len); 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... */ /* Don't comment on the hash, its primitive but functional... */
static int pphash(const char *str) 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 *wpp_find_include(const char *name, const char *parent_name)
{ {
char *cpy; return wpp_default_lookup(name, parent_name, includepath, nincludepath);
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;
} }
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; char *path;
FILE *fp; void *fp;
if (!(path = wpp_find_include( name, parent_name ))) return NULL; if (!(path = wpp_callbacks->lookup(name, parent_name, includepath,
fp = fopen(path, "rt"); nincludepath))) return NULL;
fp = wpp_callbacks->open(path, parent_name == NULL ? 1 : 0);
if (fp) 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 = 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_error,
wpp_default_warning, wpp_default_warning,
}; };

View File

@ -176,8 +176,8 @@ int wpp_parse( const char *input, FILE *output )
add_cmdline_defines(); add_cmdline_defines();
add_special_defines(); add_special_defines();
if (!input) ppy_in = stdin; if (!input) pp_status.file = stdin;
else if (!(ppy_in = fopen(input, "rt"))) else if (!(pp_status.file = wpp_callbacks->open(input, 1)))
{ {
ppy_error("Could not open %s\n", input); ppy_error("Could not open %s\n", input);
return 2; return 2;
@ -186,13 +186,13 @@ int wpp_parse( const char *input, FILE *output )
pp_status.input = input; pp_status.input = input;
ppy_out = output; ppy_out = output;
fprintf(ppy_out, "# 1 \"%s\" 1\n", input ? input : ""); pp_writestring("# 1 \"%s\" 1\n", input ? input : "");
ret = ppy_parse(); ret = ppy_parse();
/* If there were errors during processing, return an error code */ /* If there were errors during processing, return an error code */
if(!ret && pp_status.state) ret = pp_status.state; 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(); pp_pop_define_state();
return ret; return ret;
} }

View File

@ -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_define(char *def, char *text);
pp_entry_t *pp_add_macro(char *ident, marg_t *args[], int nargs, mtext_t *exp); pp_entry_t *pp_add_macro(char *ident, marg_t *args[], int nargs, mtext_t *exp);
void pp_del_define(const char *name); 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_push_if(pp_if_state_t s);
void pp_next_if_state(int); void pp_next_if_state(int);
pp_if_state_t pp_pop_if(void); 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 struct pp_status
{ {
const char *input; /* current input file name */ const char *input; /* current input file name */
void *file; /* current input file descriptor */
int line_number; /* current line number */ int line_number; /* current line number */
int char_number; /* current char number in line */ int char_number; /* current char number in line */
int state; /* current error state */ 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_push_ignore_state(void);
void pp_pop_ignore_state(void); void pp_pop_ignore_state(void);
void pp_writestring(const char *format, ...) __attribute__((format (printf, 1, 2)));
/* /*
* From ppy.y * From ppy.y