diff --git a/tools/qfcc/include/debug.h b/tools/qfcc/include/debug.h index b6a283dea..fc8be97a4 100644 --- a/tools/qfcc/include/debug.h +++ b/tools/qfcc/include/debug.h @@ -33,7 +33,10 @@ #include "QF/progs/pr_debug.h" -void line_info (const char *text); +typedef struct expr_s expr_t; + +void line_info (const expr_t *line_expr, const char *text, + const expr_t *flags_epxr); pr_lineno_t *new_lineno (void); void add_source_file (const char *file); void debug_finish_module (const char *modname); diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index 939a27cdc..6808f7bd0 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -97,27 +97,19 @@ add_source_file (const char *file) } void -line_info (const char *text) +line_info (const expr_t *line_expr, const char *file, const expr_t *flags_expr) { - const char *p; - char *s; - const char *str; - int line; - int flags; + int line = expr_long (line_expr); + int flags = flags_expr ? expr_long (flags_expr) : 0; - p = text; - line = strtol (p, &s, 10); - p = s; - while (isspace ((unsigned char)*p)) - p++; - if (!*p) - error (0, "Unexpected end of file"); - str = make_string (p, &s); // grab the filename - p = s; - while (isspace ((unsigned char) *p)) - p++; - flags = strtol (p, &s, 10); - switch (flags) { + if (file) { + if (*file != '"') { + error (0, "\"%s\" is not a valid filename", file); + return; + } + file = make_string (file, 0); + } + switch (flags & 3) { case 1: push_source_file (); break; @@ -125,10 +117,10 @@ line_info (const char *text) pop_source_file (); break; } - while (*p && *p != '\n') // ignore rest - p++; - pr.source_line = line - 1; - add_source_file (str); + pr.source_line = line; + if (file) { + add_source_file (file); + } } pr_lineno_t * diff --git a/tools/qfcc/source/pre-parse.y b/tools/qfcc/source/pre-parse.y index 98eb226cd..4be1de1b7 100644 --- a/tools/qfcc/source/pre-parse.y +++ b/tools/qfcc/source/pre-parse.y @@ -43,6 +43,7 @@ #include "QF/dstring.h" +#include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/pragma.h" @@ -119,7 +120,7 @@ parse_error (void *scanner) %token TOKEN // end of tokens comment between qc and preprocessor -%token QSTRING HSTRING +%token QSTRING HSTRING %token INCLUDE EMBED %token DEFINE UNDEF @@ -130,13 +131,32 @@ parse_error (void *scanner) %token DEFINED EOD %token CONCAT ARGS +%type string %type params body arg arg_list %type text text_text -%type unary_expr expr id defined defined_id +%type unary_expr expr id defined defined_id line_expr %{ #define BEXPR(a,op,b) new_long_expr (expr_long (a) op expr_long (b), false) #define UEXPR(op,a) new_long_expr (op expr_long (a), false) + +static const expr_t * +get_long (const expr_t *expr, const char *text, int defl) +{ + auto type = expr ? get_type (expr) : 0; + if (!type || !is_long (type)) { + if (type && is_double (type)) { + error (0, "floating constant in preprocessor expression"); + expr = new_long_expr (expr_double (expr), false); + } else { + error (0, "token \"%s\" is not valid in preprocessor" + " expressions", text); + expr= new_long_expr (defl, false); + } + } + return expr; +} + %} %% @@ -169,7 +189,8 @@ directive | WARNING text { warning (0, "%s", $text->str); dstring_delete ($text); } | PRAGMA expand { rua_start_pragma (scanner); } pragma_params { pragma_process (); } - | LINE expand expr QSTRING extra_warn + | LINE expand expr extra_warn { line_info ($3, 0, 0); } + | LINE expand expr string line_expr extra_warn { line_info ($3, $4, $5); } | IF expand expr { rua_if (expr_long ($3), scanner); } | IFDEF ID extra_warn { rua_if (rua_defined ($2, scanner), scanner); } | IFNDEF ID extra_warn { rua_if (!rua_defined ($2, scanner), scanner); } @@ -218,8 +239,8 @@ pragma_params ; string - : HSTRING - | QSTRING + : HSTRING { $$ = save_string ($1); } + | QSTRING { $$ = save_string ($1); } ; params @@ -263,27 +284,8 @@ defined_id unary_expr : id - | VALUE - { - auto type = get_type ($1); - if (!is_long (type)) { - if (is_double (type)) { - error (0, "floating constant in preprocessor expression"); - $1 = new_long_expr (expr_double ($1), false); - } else { - error (0, "token \"%s\" is not valid in preprocessor" - " expressions", $1); - $1 = new_long_expr (1, false); - } - } - $$ = $1; - } - | QSTRING - { - error (0, "token \"%s\" is not valid in preprocessor" - " expressions", $1); - $$ = new_long_expr (1, false); - } + | VALUE { $$ = get_long ($1, $1, 1); } + | QSTRING { $$ = get_long (0, $1, 1); } | '(' expr ')' { $$ = $2; } | DEFINED { rua_expand_off (scanner); } defined { rua_expand_on (scanner); $$ = $3; } @@ -315,4 +317,18 @@ expr | expr '%' expr { $$ = BEXPR ($1, % , $3); } ; +line_expr + : /* empty */ { $$ = new_long_expr (0, false); } + | line_expr VALUE + { + pr_long_t flags = expr_long ($1); + pr_long_t bit = expr_long (get_long ($2, $2, 0)) - 1; + if (bit >= 0) { + flags |= 1 << bit; + $1 = new_long_expr (flags, false); + } + $$ = $1; + } + ; + %% diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 044763e4e..6cf03ecc0 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -198,6 +198,11 @@ pp_vnumber '({s}*{m}?{pp_number}){2,4}{s}*'{ULFD}? [\\]* /* consume \ */ ^# { return '#'; } +^#{s}+/{D} { + yy_push_state (PREPROC, yyscanner); + extra->preprocessor = true; + return PRE_LINE; + } <*>^# { yy_push_state (DIRECTIVE, yyscanner); extra->preprocessor = true; @@ -243,9 +248,6 @@ pp_vnumber '({s}*{m}?{pp_number}){2,4}{s}*'{ULFD}? defined { return PRE_DEFINED; } {ID} { return PRE_ID; } -^#{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); } -^#line{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 5); } - { {ID} | @{ID} { return -rua_id; } diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index 0bf98ef2c..0bb6ae8ac 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -135,8 +135,8 @@ FRAMEID {ID}(\.{ID})* <> { error (0, "EOF in comment"); return 0; } "//".* /* nothing to do, with people like you */ -^#{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); } -^#line{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); } +^#{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { /*line_info (yytext + 1);FIXME*/ } +^#line{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { /*line_info (yytext + 1);FIXME*/ } {INTEGER} { int i;