diff --git a/tools/qfcc/include/cpp.h b/tools/qfcc/include/cpp.h index 46bb64e9e..8a1ba69e4 100644 --- a/tools/qfcc/include/cpp.h +++ b/tools/qfcc/include/cpp.h @@ -49,6 +49,7 @@ void intermediate_file (struct dstring_s *ifile, const char *filename, FILE *preprocess_file (const char *filename, const char *ext); extern const char *cpp_name; extern struct dstring_s *tempname; +extern struct symtab_s *cpp_macros; void cpp_write_dependencies (const char *sourcefile); diff --git a/tools/qfcc/include/rua-lang.h b/tools/qfcc/include/rua-lang.h index d22186914..efcd13b1c 100644 --- a/tools/qfcc/include/rua-lang.h +++ b/tools/qfcc/include/rua-lang.h @@ -95,6 +95,7 @@ bool rua_defined (const char *sym, void *scanner); void rua_undefine (const char *sym, void *scanner); void rua_include_file (const char *name, void *scanner); void rua_embed_file (const char *name, void *scanner); +int rua_parse_define (const char *def); #include "tools/qfcc/source/pre-parse.h" diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index 5f8c05867..c2b0d9ed5 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -62,7 +62,9 @@ #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/rua-lang.h" #include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" typedef struct cpp_arg_s { struct cpp_arg_s *next; @@ -97,6 +99,7 @@ static bool cpp_dep_generate = false; static bool cpp_dep_phony = false; static bool cpp_dep_quote = false; +symtab_t *cpp_macros; const char *cpp_name = CPP_NAME; dstring_t *tempname; @@ -382,25 +385,38 @@ cpp_include (const char *opt, const char *arg) void cpp_define (const char *arg) { -#if 0 if (!cpp_macros) { - cpp_macros = new_symtab (stab_global); + cpp_macros = new_symtab (0, stab_global); } -#endif + size_t len = strlen (arg); + if (len > 0x10000) { + error (0, "command line define too long: %zd", len); + return; + } + char argstr[len + 4]; + strcpy (argstr, arg); + argstr[len] = '\n'; + argstr[len + 1] = 0; + char *eq = strchr (argstr, '='); + if (eq) { + *eq = ' '; + } else { + strcpy (argstr + len, " 1\n"); + } + rua_parse_define (argstr); + arg = va (0, "-D%s", arg); CPP_ADD (def, arg); } void cpp_undefine (const char *arg) { -#if 0 if (cpp_macros) { auto sym = symtab_lookup (cpp_macros, arg); if (sym) { symtab_removesymbol (cpp_macros, sym); } } -#endif arg = va (0, "-D%s", arg); CPP_ADD (undef, arg); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index f45540489..409663d3d 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -1110,7 +1110,7 @@ expand_macro (rua_extra_t *extra, rua_macro_t *macro) { int num_tokens = macro->num_tokens; for (auto t = macro->tokens; t; t = t->next) { - if (t->token == -rua_id) { + if (t->token == -rua_id && macro->params) { auto sym = symtab_lookup (macro->params, t->text); if (sym) { num_tokens += extra->arg_list.a[sym->s.offset]->num_tokens - 1; @@ -1124,7 +1124,7 @@ expand_macro (rua_extra_t *extra, rua_macro_t *macro) int argid = 0; for (auto t = macro->tokens; t; t = t->next) { auto e = t; - if (t->token == -rua_id) { + if (t->token == -rua_id && macro->params) { auto sym = symtab_lookup (macro->params, t->text); if (sym) { int param = sym->s.offset; @@ -1419,7 +1419,7 @@ qc_yyparse (FILE *in) .arg_list = DARRAY_STATIC_INIT (8), .include_stack = DARRAY_STATIC_INIT (8), .dstr = dstring_new (), - .macro_tab = new_symtab (0, stab_global), + .macro_tab = cpp_macros ? cpp_macros : new_symtab (0, stab_global), }; yylex_init_extra (&extra, &scanner); @@ -1718,7 +1718,7 @@ dump_state_stack (void *scanner) extra ? extra->recording ? "true" : "false" : "n/a", extra ? extra->expand ? "true" : "false" : "n/a", extra ? extra->params ? "true" : "false" : "n/a", - GETSTR(pr.source_file), pr.source_line); + pr.strings ? GETSTR(pr.source_file) : "", pr.source_line); } static void @@ -1878,3 +1878,52 @@ rua_embed_file (const char *name, void *scanner) internal_error (0, "not implemented"); (void)yy_top_state; } + +int +rua_parse_define (const char *def) +{ + int status; + yyscan_t scanner; + rua_tok_t tok = { .location = { 1, 1, 1, 1 }, }; + rua_extra_t extra = { + .preprocessor = true, + .pre_state = pre_yypstate_new (), + .expr_stack = DARRAY_STATIC_INIT (32), + .macro_tab = cpp_macros, + }; + + yylex_init_extra (&extra, &scanner); + yy_scan_string (def, scanner); + + yy_push_state (PREPROC, scanner); + + int token = -1; + do { + if (token == -1) { + token = PRE_DEFINE; + } else { + token = yylex (&tok, &tok.location, scanner); + status = 0; + } + while (token) { + status = qc_process (&extra, token, &tok, scanner); + if (status != YYPUSH_MORE || !extra.expr_stack.size) { + break; + } + auto expr = DARRAY_REMOVE (&extra.expr_stack); + token = expr.token; + tok = (rua_tok_t) { + .location = expr.location, + .textlen = expr.textlen, + .text = expr.text, // macro token strings use save_string + .token = token, + }; + } + } while (status == YYPUSH_MORE); + + yylex_destroy (scanner); + pre_yypstate_delete (extra.pre_state); + free (extra.expr_stack.a); + dstring_delete (extra.dstr); + return status; +}