[qfcc] Update line directive handling

In addition to cleaning up the old flex line rules, this improves
handling of the '# num "file" flags' from cpp to at least parse the
additional flags (support for the system header flag might come later,
but I doubt the extern-c flag will have much meaning).

QuakePascal has lost its line directive handling (no errors, but dead
rules) for now. Eventually the lexers will be merged.
This commit is contained in:
Bill Currie 2023-10-25 12:19:19 +09:00
parent 717be4a12d
commit f1f0a4a260
5 changed files with 68 additions and 55 deletions

View file

@ -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);

View file

@ -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 *

View file

@ -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 <text> QSTRING HSTRING
%token INCLUDE EMBED
%token DEFINE UNDEF
@ -130,13 +131,32 @@ parse_error (void *scanner)
%token DEFINED EOD
%token CONCAT ARGS
%type <text> string
%type <macro> params body arg arg_list
%type <dstr> text text_text
%type <value.expr> unary_expr expr id defined defined_id
%type <value.expr> 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", $<text>1);
$1 = new_long_expr (1, false);
}
}
$$ = $1;
}
| QSTRING
{
error (0, "token \"%s\" is not valid in preprocessor"
" expressions", $<text>1);
$$ = new_long_expr (1, false);
}
| VALUE { $$ = get_long ($1, $<text>1, 1); }
| QSTRING { $$ = get_long (0, $<text>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, $<text>2, 0)) - 1;
if (bit >= 0) {
flags |= 1 << bit;
$1 = new_long_expr (flags, false);
}
$$ = $1;
}
;
%%

View file

@ -198,6 +198,11 @@ pp_vnumber '({s}*{m}?{pp_number}){2,4}{s}*'{ULFD}?
<LCOMMENT>[\\]* /* consume \ */
<ARGS>^# { 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}?
<PREEXPR>defined { return PRE_DEFINED; }
<PREEXPR>{ID} { return PRE_ID; }
^#{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); }
^#line{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 5); }
<INITIAL,ARGS>{
{ID} |
@{ID} { return -rua_id; }

View file

@ -135,8 +135,8 @@ FRAMEID {ID}(\.{ID})*
<COMMENT><<EOF>> { 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;