From 413d109000b3f8f20e4701fcf6179003e5f9290f Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Wed, 29 Jul 2009 14:49:23 +0000 Subject: [PATCH] Implemented simple word substitution --- src/parser.c | 97 ++++++++++++++++++++++++++++++++++++++++++-- src/parser.h | 1 + src/scanner.c | 11 +++++ src/test/defines.txt | 3 +- 4 files changed, 107 insertions(+), 5 deletions(-) diff --git a/src/parser.c b/src/parser.c index c1aa54c..060bf39 100644 --- a/src/parser.c +++ b/src/parser.c @@ -32,9 +32,12 @@ #include "common.h" #ifdef DEBUG +# define DEBUG_FILTER() fprintf(stderr, "DEBUG: %s('%c' 0x%x)\n", __func__, \ + *c, *c); # define DEBUG_CALLBACK() fprintf(stderr, "DEBUG: %s('%c' 0x%x)\n", __func__, \ c, c); #else +# define DEBUG_FILTER() # define DEBUG_CALLBACK() #endif @@ -56,6 +59,9 @@ struct _CppParser Parser * parser; int filters; + /* for cpp_filter_inject */ + char * inject; + int inject_first; /* for cpp_filter_newlines */ int newlines_last; int newlines_last_cnt; @@ -151,10 +157,13 @@ static int _cpp_token_set(CppParser * cp, Token * token, TokenCode code, char const * string); /* filters */ +static int _cpp_filter_inject(int * c, void * data); static int _cpp_filter_newlines(int * c, void * data); static int _cpp_filter_trigraphs(int * c, void * data); /* callbacks */ +static int _cpp_callback_inject(Parser * parser, Token * token, int c, + void * data); static int _cpp_callback_dequeue(Parser * parser, Token * token, int c, void * data); static int _cpp_callback_header(Parser * parser, Token * token, int c, @@ -230,7 +239,7 @@ static int _cpp_token_set(CppParser * cp, Token * token, TokenCode code, /* we are parsing a directive */ token_set_code(token, CPP_CODE_META_DATA); if(code == CPP_CODE_COMMENT) - /* comments really are whitespaces */ + /* comments within directives are whitespaces */ string = " "; if(cp->queue_string == NULL) { @@ -244,6 +253,36 @@ static int _cpp_token_set(CppParser * cp, Token * token, TokenCode code, /* filters */ +/* cpp_filter_inject */ +static int _cpp_filter_inject(int * c, void * data) +{ + CppParser * cp = data; + size_t len; + int d; + + if(cp->inject == NULL) + return 0; + DEBUG_FILTER(); + if((len = strlen(cp->inject)) > 0) + { + d = *c; + *c = cp->inject[0]; + memmove(cp->inject, &cp->inject[1], len--); + if(cp->inject_first && d != EOF && d != '\0') + { + cp->inject[len++] = d; + cp->inject[len] = '\0'; + cp->inject_first = 0; + } + } + if(len > 0) + return 1; + free(cp->inject); + cp->inject = NULL; + return 0; +} + + /* cpp_filter_newlines */ static int _cpp_filter_newlines(int * c, void * data) { @@ -498,6 +537,27 @@ static int _cpp_callback_comment(Parser * parser, Token * token, int c, } +/* cpp_callback_inject */ +static int _cpp_callback_inject(Parser * parser, Token * token, int c, + void * data) +{ + CppParser * cp = data; + char buf[2] = "\0"; + + if(cp->inject_first == 0) + return 1; + DEBUG_CALLBACK(); + if(c == EOF) + return 1; + /* the current character actually goes after the substitution */ + buf[0] = c; + if(string_append(&cp->inject, buf) != 0) + return -1; + parser_scan_filter(parser); + return 1; +} + + /* cpp_callback_dequeue */ static int _dequeue_include(CppParser * cpp, Token * token, char const * str); static char * _include_path(CppParser * cpp, char const * str); @@ -882,7 +942,7 @@ static int _cpp_callback_unknown(Parser * parser, Token * token, int c, return 1; DEBUG_CALLBACK(); buf[0] = c; - parser_scan(parser); + parser_scan_filter(parser); return _cpp_token_set(cp, token, CPP_CODE_UNKNOWN, buf); } @@ -901,6 +961,8 @@ CppParser * cppparser_new(Cpp * cpp, CppParser * parent, char const * filename, cp->parent = parent; cp->parser = parser_new(filename); cp->filters = filters; + cp->inject = NULL; + cp->inject_first = 0; cp->newlines_last = 0; cp->newlines_last_cnt = 0; cp->trigraphs_last = 0; @@ -916,9 +978,11 @@ CppParser * cppparser_new(Cpp * cpp, CppParser * parent, char const * filename, cppparser_delete(cp); return NULL; } + parser_add_filter(cp->parser, _cpp_filter_inject, cp); parser_add_filter(cp->parser, _cpp_filter_newlines, cp); if(cp->filters & CPP_FILTER_TRIGRAPH) parser_add_filter(cp->parser, _cpp_filter_trigraphs, cp); + parser_add_callback(cp->parser, _cpp_callback_inject, cp); parser_add_callback(cp->parser, _cpp_callback_dequeue, cp); if(cp->filters & CPP_FILTER_WHITESPACE) parser_add_callback(cp->parser, _cpp_callback_whitespace, cp); @@ -944,10 +1008,11 @@ CppParser * cppparser_new(Cpp * cpp, CppParser * parent, char const * filename, void cppparser_delete(CppParser * cp) { string_delete(cp->queue_string); - if(cp->parser != NULL) - parser_delete(cp->parser); if(cp->subparser != NULL) cppparser_delete(cp->subparser); + if(cp->parser != NULL) + parser_delete(cp->parser); + string_delete(cp->inject); object_delete(cp); } @@ -961,6 +1026,30 @@ char const * cppparser_get_filename(CppParser * cpp) /* useful */ +/* cppparser_inject */ +/* FIXME should take a buffer as input? */ +int cppparser_inject(CppParser * cp, char const * string) +{ + if(string == NULL || string[0] == '\0') + return 0; /* don't bother */ + for(; cp->subparser != NULL; cp = cp->subparser); + if(cp->inject == NULL) + { + if((cp->inject = string_new(string)) == NULL) + return 1; + } + else if(string_append(&cp->inject, string) != 0) + return 1; + cp->inject_first = 1; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%p, \"%s\") => \"%s\"\n", __func__, cp, + string, cp->inject); +#endif + return 0; +} + + +/* cppparser_scan */ int cppparser_scan(CppParser * cp, Token ** token) { if(cp->subparser != NULL) diff --git a/src/parser.h b/src/parser.h index 2cb3e79..6eaf2eb 100644 --- a/src/parser.h +++ b/src/parser.h @@ -36,6 +36,7 @@ char const * cppparser_get_filename(CppParser * cppparser); /* useful */ +int cppparser_inject(CppParser * cppparser, char const * string); int cppparser_scan(CppParser * cppparser, Token ** token); #endif /* !_CPP_PARSER_H */ diff --git a/src/scanner.c b/src/scanner.c index e702f3b..e606247 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -122,6 +122,7 @@ int cpp_scan(Cpp * cpp, Token ** token) { int ret; TokenCode code; + char const * str; for(; (ret = cppparser_scan(cpp->parser, token)) == 0; token_delete(*token)) @@ -156,6 +157,16 @@ int cpp_scan(Cpp * cpp, Token ** token) return _scan_define(cpp, token); case CPP_CODE_META_UNDEF: return _scan_undef(cpp, token); + case CPP_CODE_WORD: + str = token_get_string(*token); + if((str = cpp_define_get(cpp, str)) != NULL) + { + if(cppparser_inject(cpp->parser, str) + != 0) + return -1; + continue; + } + return 0; default: return 0; } diff --git a/src/test/defines.txt b/src/test/defines.txt index 22585b1..cc76a06 100644 --- a/src/test/defines.txt +++ b/src/test/defines.txt @@ -2,5 +2,6 @@ #define a b #define def123 #define df2 some text -#define df2 +now "df2" is df2 +#define def123 #undef def123