mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-19 07:51:08 +00:00
[qfcc] Rework preprocessor tokens
I got tired of the way the separate token types for macro expansion and the rest of the preprocessor parser were handled. This makes them a little more unified. Macro expansion seems to be slightly broken again in that min/max/bound mess up badly, and __VA_OPT__ does things in the wrong order, but I wanted to get this in as a checkpoint.
This commit is contained in:
parent
881b6626e4
commit
8de214c782
3 changed files with 197 additions and 201 deletions
|
@ -28,25 +28,26 @@
|
|||
#ifndef __rua_lang_h
|
||||
#define __rua_lang_h
|
||||
|
||||
#include "QF/dstring.h"
|
||||
|
||||
typedef struct rua_loc_s {
|
||||
int line, column;
|
||||
int last_line, last_column;
|
||||
int file;
|
||||
} rua_loc_t;
|
||||
|
||||
#include "tools/qfcc/source/qc-parse.h"
|
||||
|
||||
typedef struct expr_s expr_t;
|
||||
typedef struct symtab_s symtab_t;
|
||||
|
||||
typedef struct rua_expr_s {
|
||||
struct rua_expr_s *next;
|
||||
typedef struct rua_tok_s {
|
||||
struct rua_tok_s *next;
|
||||
rua_loc_t location;
|
||||
int textlen;
|
||||
int token;
|
||||
int id; // arg expansion id (1...)
|
||||
const char *text;
|
||||
} rua_expr_t;
|
||||
} rua_tok_t;
|
||||
|
||||
#include "tools/qfcc/source/qc-parse.h"
|
||||
|
||||
typedef struct rua_macro_s rua_macro_t;
|
||||
typedef void (*rua_macro_f) (rua_macro_t *macro, void *scanner);
|
||||
|
@ -55,41 +56,34 @@ typedef struct rua_macro_s {
|
|||
rua_macro_t *next;
|
||||
const char *name;
|
||||
symtab_t *params;
|
||||
rua_expr_t *tokens;
|
||||
rua_expr_t **tail;
|
||||
rua_tok_t *tokens;
|
||||
rua_tok_t **tail;
|
||||
int num_tokens;
|
||||
int num_params;
|
||||
rua_expr_t *cursor;
|
||||
rua_tok_t *cursor;
|
||||
rua_macro_f update;
|
||||
|
||||
int num_args;
|
||||
rua_macro_t **args;
|
||||
} rua_macro_t;
|
||||
|
||||
typedef struct rua_tok_s {
|
||||
rua_loc_t location;
|
||||
int textlen;
|
||||
const char *text;
|
||||
typedef struct rua_val_s {
|
||||
rua_tok_t t;
|
||||
union {
|
||||
struct {
|
||||
void *pointer; // mirrors pointer in QC_YYSTYPE
|
||||
char str_text[8];// if len < 8 and spec not used
|
||||
int token; // when recording macros
|
||||
};
|
||||
QC_YYSTYPE value;
|
||||
struct dstring_s *dstr;
|
||||
rua_macro_t *macro;
|
||||
const expr_t *expr;
|
||||
dstring_t *dstr;
|
||||
rua_macro_t *macro;
|
||||
};
|
||||
} rua_tok_t;
|
||||
} rua_val_t;
|
||||
|
||||
rua_macro_t *rua_start_macro (const char *name, bool params, void *scanner);
|
||||
rua_macro_t *rua_macro_param (rua_macro_t *macro, rua_tok_t *token,
|
||||
rua_macro_t *rua_macro_param (rua_macro_t *macro, const rua_tok_t *token,
|
||||
void *scanner);
|
||||
rua_macro_t *rua_end_params (rua_macro_t *macro, void *scanner);
|
||||
rua_macro_t *rua_macro_append (rua_macro_t *macro, rua_tok_t *token,
|
||||
rua_macro_t *rua_macro_append (rua_macro_t *macro, const rua_tok_t *token,
|
||||
void *scanner);
|
||||
void rua_macro_finish (rua_macro_t *macro, void *scanner);
|
||||
rua_macro_t *rua_macro_arg (rua_tok_t *token, void *scanner);
|
||||
rua_macro_t *rua_macro_arg (const rua_tok_t *token, void *scanner);
|
||||
void rua_start_pragma (void *scanner);
|
||||
void rua_start_text (void *scanner);
|
||||
void rua_start_expr (void *scanner);
|
||||
|
|
|
@ -87,7 +87,7 @@ parse_error (void *scanner)
|
|||
%code requires {
|
||||
#include "tools/qfcc/include/rua-lang.h"
|
||||
}
|
||||
%define api.value.type {rua_tok_t}
|
||||
%define api.value.type {rua_val_t}
|
||||
%define api.location.type {rua_loc_t}
|
||||
|
||||
%left LOW
|
||||
|
@ -115,29 +115,30 @@ parse_error (void *scanner)
|
|||
%left '+' '-'
|
||||
%left '*' '/' '%' MOD SCALE GEOMETRIC
|
||||
%left HADAMARD CROSS DOT WEDGE REGRESSIVE
|
||||
%right <op> SIZEOF UNARY INCOP REVERSE STAR DUAL
|
||||
%right SIZEOF UNARY INCOP REVERSE STAR DUAL
|
||||
%left HYPERUNARY
|
||||
%left '.' '(' '['
|
||||
|
||||
%token <value.expr> VALUE STRING
|
||||
%token TOKEN
|
||||
%token <expr> VALUE STRING
|
||||
%token <t> TOKEN
|
||||
// end of tokens comment between qc and preprocessor
|
||||
|
||||
%token <text> QSTRING HSTRING
|
||||
%token <t.text> QSTRING HSTRING
|
||||
|
||||
%token INCLUDE EMBED
|
||||
%token DEFINE UNDEF
|
||||
%token <text> TEXT ID IDp
|
||||
%token <t.text> TEXT ID IDp
|
||||
%token ERROR WARNING NOTICE
|
||||
%token PRAGMA LINE
|
||||
%token IF IFDEF IFNDEF ELSE ELIF ELIFDEF ELIFNDEF ENDIF
|
||||
%token DEFINED EOD
|
||||
%token CONCAT ARGS
|
||||
|
||||
%type <text> string
|
||||
%type <t.text> string
|
||||
%type <macro> params opt_params body arg arg_list arg_clist
|
||||
%type <dstr> text text_text
|
||||
%type <value.expr> unary_expr expr id defined defined_id line_expr
|
||||
%type <expr> unary_expr expr id defined defined_id line_expr
|
||||
%type <t> body_token
|
||||
|
||||
%{
|
||||
#define TEXPR(c,t,f) new_long_expr (expr_long (c) ? expr_long (t) \
|
||||
|
@ -170,7 +171,7 @@ start
|
|||
: directive_list
|
||||
| ARGS
|
||||
<macro>{
|
||||
$$ = rua_macro_arg (yyvsp, scanner);
|
||||
$$ = rua_macro_arg (&$<t>1, scanner);
|
||||
}
|
||||
args ')' { YYACCEPT; }
|
||||
;
|
||||
|
@ -248,10 +249,15 @@ text_text
|
|||
;
|
||||
|
||||
body: /* empty */ { $$ = $<macro>0; }
|
||||
| body body_token { $$ = rua_macro_append ($1, yyvsp, scanner); }
|
||||
| body body_token { $$ = rua_macro_append ($1, &$2, scanner); }
|
||||
;
|
||||
|
||||
body_token : TOKEN | ',' | '(' | ')' ;
|
||||
body_token
|
||||
: TOKEN
|
||||
| ',' { $$ = $<t>1; }
|
||||
| '(' { $$ = $<t>1; }
|
||||
| ')' { $$ = $<t>1; }
|
||||
;
|
||||
|
||||
incexp
|
||||
: { rua_start_include (scanner); }
|
||||
|
@ -277,14 +283,14 @@ opt_params
|
|||
;
|
||||
|
||||
params
|
||||
: TOKEN { $$ = rua_macro_param ($<macro>0, yyvsp, scanner); }
|
||||
| params ',' TOKEN { $$ = rua_macro_param ($1, yyvsp, scanner); }
|
||||
: TOKEN { $$ = rua_macro_param ($<macro>0, &$1, scanner); }
|
||||
| params ',' TOKEN { $$ = rua_macro_param ($1, &$3, scanner); }
|
||||
;
|
||||
|
||||
args: arg_list
|
||||
| args ','
|
||||
<macro>{
|
||||
$$ = rua_macro_arg (yyvsp, scanner);
|
||||
$$ = rua_macro_arg (&$<t>2, scanner);
|
||||
}
|
||||
arg_list
|
||||
;
|
||||
|
@ -294,18 +300,18 @@ arg_list
|
|||
| arg_list arg { $$ = $2; }
|
||||
;
|
||||
|
||||
arg : '(' <macro> { $$ = rua_macro_append ($<macro>0, yyvsp, scanner); }
|
||||
arg : '(' <macro> { $$ = rua_macro_append ($<macro>0, &$<t>1, scanner); }
|
||||
arg_clist <macro> { $$ = $<macro>2; }
|
||||
')' { $$ = rua_macro_append ($<macro>4, yyvsp, scanner); }
|
||||
| TOKEN { $$ = rua_macro_append ($<macro>0, yyvsp, scanner); }
|
||||
| VALUE { $$ = rua_macro_append ($<macro>0, yyvsp, scanner); }
|
||||
| ID { $$ = rua_macro_append ($<macro>0, yyvsp, scanner); }
|
||||
')' { $$ = rua_macro_append ($<macro>4, &$<t>5, scanner); }
|
||||
| TOKEN { $$ = rua_macro_append ($<macro>0, &$1, scanner); }
|
||||
| VALUE { $$ = rua_macro_append ($<macro>0, &$<t>1, scanner); }
|
||||
| ID { $$ = rua_macro_append ($<macro>0, &$<t>1, scanner); }
|
||||
;
|
||||
|
||||
arg_clist
|
||||
: /* emtpy */ { $$ = $<macro>0; }
|
||||
| arg_clist arg { $$ = $2; }
|
||||
| arg_clist ',' { $$ = rua_macro_append ($1, yyvsp, scanner); }
|
||||
| arg_clist ',' { $$ = rua_macro_append ($1, &$<t>2, scanner); }
|
||||
;
|
||||
|
||||
id : ID { $$ = new_long_expr (0, false); }
|
||||
|
@ -324,8 +330,8 @@ defined_id
|
|||
|
||||
unary_expr
|
||||
: id
|
||||
| VALUE { $$ = get_long ($1, $<text>1, 1); }
|
||||
| QSTRING { $$ = get_long (0, $<text>1, 1); }
|
||||
| VALUE { $$ = get_long ($1, $<t.text>1, 1); }
|
||||
| QSTRING { $$ = get_long (0, $<t.text>1, 1); }
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
| DEFINED { rua_expand_off (scanner); }
|
||||
defined { rua_expand_on (scanner); $$ = $3; }
|
||||
|
@ -363,7 +369,7 @@ line_expr
|
|||
| line_expr VALUE
|
||||
{
|
||||
pr_long_t flags = expr_long ($1);
|
||||
pr_long_t bit = expr_long (get_long ($2, $<text>2, 0)) - 1;
|
||||
pr_long_t bit = expr_long (get_long ($2, $<t.text>2, 0)) - 1;
|
||||
if (bit >= 0) {
|
||||
flags |= 1 << bit;
|
||||
$1 = new_long_expr (flags, false);
|
||||
|
|
|
@ -124,6 +124,7 @@ typedef struct rua_extra_s {
|
|||
rua_macro_t *macro; // macro being expanded
|
||||
yyscan_t subscanner;
|
||||
rua_loc_t location;
|
||||
char str_text[8]; // EPHEMERAL! for short token strings
|
||||
} rua_extra_t;
|
||||
#define YY_EXTRA_TYPE rua_extra_t *
|
||||
|
||||
|
@ -139,10 +140,10 @@ FILE *yyget_in (yyscan_t yyscanner) __attribute__((pure));
|
|||
FILE *yyget_out (yyscan_t yyscanner) __attribute__((pure));
|
||||
|
||||
static int directive (const char *token, yyscan_t scanner);
|
||||
static int keyword_or_id (YYSTYPE *lval, const char *token);
|
||||
static int keyword_or_id (QC_YYSTYPE *lval, const char *token);
|
||||
static void update_loc (rua_loc_t *loc, size_t textlen);
|
||||
static void save_text (rua_tok_t *tok, const char *text, size_t textlen,
|
||||
int state);
|
||||
int state, rua_extra_t *extra);
|
||||
static void next_line (rua_loc_t *loc, yyscan_t scanner);
|
||||
static void dump_state_stack (void *scanner);
|
||||
static void dump_token (rua_tok_t *tok, rua_loc_t *loc, int state);
|
||||
|
@ -161,13 +162,14 @@ typedef enum {
|
|||
rua_ellipsis,
|
||||
rua_asx,
|
||||
rua_incop,
|
||||
rua_grab,
|
||||
|
||||
rua_num_term,
|
||||
} rua_term;
|
||||
|
||||
#define YY_USER_ACTION \
|
||||
update_loc (yylloc, yyleng); \
|
||||
save_text (yylval, yytext, yyleng, yystart()); \
|
||||
save_text (yylval, yytext, yyleng, yystart(), extra); \
|
||||
if (0) { dump_debug (yy_act, yytext, yystart()); } \
|
||||
if (0) { dump_token (yylval, yylloc, yystart ()); } \
|
||||
if (0) { dump_state_stack(yyscanner); }
|
||||
|
@ -209,7 +211,6 @@ pp_vnumber '({s}*{m}?{pp_number}){2,4}{s}*'{ULFD}?
|
|||
grab_frame = GRAB_FRAME;
|
||||
grab_other = GRAB_OTHER;
|
||||
grab_write = GRAB_WRITE;
|
||||
yylval->pointer = 0; // ensure pointer vals are null
|
||||
|
||||
<COMMENT>"/*" { warning (0, "nested /* in comment"); yymore();}
|
||||
<COMMENT>\*+"/" { yy_pop_state (yyscanner); return -rua_space; }
|
||||
|
@ -325,15 +326,7 @@ pp_vnumber '({s}*{m}?{pp_number}){2,4}{s}*'{ULFD}?
|
|||
"++" { return -rua_incop; }
|
||||
"--" { return -rua_incop; }
|
||||
|
||||
"$"{s}*{FRAMEID} {
|
||||
int ret = do_grab (yytext);
|
||||
if (ret >= 0) {
|
||||
yylval->value.expr = new_int_expr (ret, false);
|
||||
return QC_VALUE;
|
||||
} else {
|
||||
yy_push_state (-ret, yyscanner);
|
||||
}
|
||||
}
|
||||
"$"{s}*{FRAMEID} { return -rua_grab; }
|
||||
|
||||
<GRAB_FRAME>{FRAMEID} { add_frame_macro (yytext); }
|
||||
<GRAB_OTHER>[^\r\n]* /* skip */
|
||||
|
@ -576,31 +569,28 @@ keyword_get_key (const void *kw, void *unused)
|
|||
}
|
||||
|
||||
static int
|
||||
process_keyword (YYSTYPE *lval, keyword_t *keyword, const char *token)
|
||||
process_keyword (QC_YYSTYPE *lval, keyword_t *keyword, const char *token)
|
||||
{
|
||||
if (lval->text == lval->str_text) {
|
||||
lval->text = save_string (lval->str_text);
|
||||
}
|
||||
if (keyword->value == QC_STRUCT) {
|
||||
lval->value.op = token[0];
|
||||
lval->op = token[0];
|
||||
} else if (keyword->value == QC_OBJECT_NAME) {
|
||||
symbol_t *sym;
|
||||
|
||||
sym = symtab_lookup (current_symtab, token);
|
||||
lval->value.symbol = sym;
|
||||
lval->symbol = sym;
|
||||
// the global id symbol is always just a name so attempts to redefine
|
||||
// it globally can be caught and treated as an error, but it needs to
|
||||
// be redefinable when in an enclosing scope.
|
||||
if (sym->sy_type == sy_name) {
|
||||
// this is the global id (object)
|
||||
lval->value.spec = (specifier_t) {
|
||||
lval->spec = (specifier_t) {
|
||||
.type = sym->type,
|
||||
.sym = sym,
|
||||
};
|
||||
return QC_OBJECT_NAME;
|
||||
} else if (sym->sy_type == sy_type) {
|
||||
// id has been redeclared via a typedef
|
||||
lval->value.spec = (specifier_t) {
|
||||
lval->spec = (specifier_t) {
|
||||
.type = sym->type,
|
||||
.sym = sym,
|
||||
};
|
||||
|
@ -609,13 +599,13 @@ process_keyword (YYSTYPE *lval, keyword_t *keyword, const char *token)
|
|||
// id has been redelcared as a variable (hopefully)
|
||||
return QC_NAME;
|
||||
} else {
|
||||
lval->value.spec = keyword->spec;
|
||||
lval->spec = keyword->spec;
|
||||
}
|
||||
return keyword->value;
|
||||
}
|
||||
|
||||
static int
|
||||
keyword_or_id (YYSTYPE *lval, const char *token)
|
||||
keyword_or_id (QC_YYSTYPE *lval, const char *token)
|
||||
{
|
||||
static hashtab_t *keyword_tab;
|
||||
static hashtab_t *qf_keyword_tab;
|
||||
|
@ -677,9 +667,9 @@ keyword_or_id (YYSTYPE *lval, const char *token)
|
|||
sym = symtab_lookup (current_symtab, token);
|
||||
if (!sym)
|
||||
sym = new_symbol (token);
|
||||
lval->value.symbol = sym;
|
||||
lval->symbol = sym;
|
||||
if (sym->sy_type == sy_type) {
|
||||
lval->value.spec = (specifier_t) {
|
||||
lval->spec = (specifier_t) {
|
||||
.type = sym->type,
|
||||
.sym = sym,
|
||||
};
|
||||
|
@ -765,8 +755,8 @@ parse_suffix (const char *suffix, bool fp)
|
|||
return expl;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_number (rua_tok_t *tok, yyscan_t scanner)
|
||||
static const expr_t *
|
||||
parse_number (const rua_tok_t *tok, yyscan_t scanner)
|
||||
{
|
||||
bool binary = false;
|
||||
const char *type = "integer";
|
||||
|
@ -793,7 +783,7 @@ parse_number (rua_tok_t *tok, yyscan_t scanner)
|
|||
case '\'': case '_':
|
||||
if (*src == 'b' || *src == 'B' || *src == 'x' || *src == 'X') {
|
||||
error (0, "digit separator outside digit sequence");
|
||||
return -rua_error;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -835,35 +825,34 @@ parse_number (rua_tok_t *tok, yyscan_t scanner)
|
|||
if (expl < 0) {
|
||||
error (0, "invalid suffix \"%s\" on %s constant", endptr,
|
||||
fp ? "floating" : type);
|
||||
return -rua_error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
if (expl == suff_float) {
|
||||
tok->value.expr = new_float_expr (fvalue);
|
||||
return new_float_expr (fvalue);
|
||||
} else {
|
||||
if (expl == suff_long_double) {
|
||||
warning (0, "long double treated as double");
|
||||
expl = suff_double;
|
||||
}
|
||||
tok->value.expr = new_double_expr (fvalue, expl == suff_implicit);
|
||||
return new_double_expr (fvalue, expl == suff_implicit);
|
||||
}
|
||||
} else {
|
||||
if (expl == suff_unsigned) {
|
||||
tok->value.expr = new_uint_expr (lvalue);
|
||||
return new_uint_expr (lvalue);
|
||||
} else if (expl == suff_long || expl == suff_implicit) {
|
||||
tok->value.expr = new_long_expr (lvalue, expl == suff_implicit);
|
||||
return new_long_expr (lvalue, expl == suff_implicit);
|
||||
} else if (expl == suff_unsigned_long) {
|
||||
tok->value.expr = new_ulong_expr (lvalue);
|
||||
return new_ulong_expr (lvalue);
|
||||
} else if (expl == suff_float) {
|
||||
tok->value.expr = new_float_expr (lvalue);
|
||||
return new_float_expr (lvalue);
|
||||
} else if (expl == suff_double) {
|
||||
tok->value.expr = new_double_expr (lvalue, false);
|
||||
return new_double_expr (lvalue, false);
|
||||
} else {
|
||||
internal_error (0, "invalid suffix enum: %d", expl);
|
||||
}
|
||||
}
|
||||
return QC_VALUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -883,8 +872,8 @@ qc_delete_buffer (buffer_raii_t *raii)
|
|||
yy_delete_buffer (raii->buffer, raii->scanner);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_vector (rua_tok_t *tok, yyscan_t scanner)
|
||||
static const expr_t *
|
||||
parse_vector (const rua_tok_t *tok, yyscan_t scanner)
|
||||
{
|
||||
const char *end = tok->text + tok->textlen;
|
||||
while (end > tok->text && *--end != '\'') continue;
|
||||
|
@ -913,13 +902,13 @@ parse_vector (rua_tok_t *tok, yyscan_t scanner)
|
|||
do {
|
||||
token = yylex (&vtok, &vtok.location, scanner);
|
||||
if (-token == rua_number) {
|
||||
token = parse_number (&vtok, scanner);
|
||||
}
|
||||
if (token == QC_VALUE) {
|
||||
if (width < 4) {
|
||||
components[width] = vtok.value.expr;
|
||||
auto expr = parse_number (&vtok, scanner);
|
||||
if (expr) {
|
||||
if (width < 4) {
|
||||
components[width] = expr;
|
||||
}
|
||||
width++;
|
||||
}
|
||||
width++;
|
||||
} else if (token == '-') {
|
||||
if (width < 4) {
|
||||
negate[width] = true;
|
||||
|
@ -931,14 +920,14 @@ parse_vector (rua_tok_t *tok, yyscan_t scanner)
|
|||
if (width > 4) {
|
||||
error (0, "too many components in vector literal");
|
||||
width = 4;
|
||||
return -rua_error;
|
||||
return 0;
|
||||
}
|
||||
bool fp = false;
|
||||
for (int i = 0; i < width; i++) {
|
||||
if (!components[i]->implicit) {
|
||||
error (0, "explict numeric constant in vector literal."
|
||||
" Suggest suffix after closing '.");
|
||||
return -rua_error;
|
||||
return 0;
|
||||
}
|
||||
fp |= is_double (get_type (components[i]));
|
||||
}
|
||||
|
@ -948,7 +937,7 @@ parse_vector (rua_tok_t *tok, yyscan_t scanner)
|
|||
if (expl < 0) {
|
||||
error (0, "invalid suffix \"%s\" on %s vector constant", end,
|
||||
fp ? "floating" : "integer");
|
||||
return -rua_error;
|
||||
return 0;
|
||||
}
|
||||
union {
|
||||
pr_float_t f[4];
|
||||
|
@ -1032,24 +1021,23 @@ parse_vector (rua_tok_t *tok, yyscan_t scanner)
|
|||
type = expl == suff_unsigned_long ? &type_ulong : &type_long;
|
||||
}
|
||||
type = vector_type (type, width);
|
||||
tok->value.expr = new_value_expr (new_type_value (type, data.t),
|
||||
expl == suff_implicit);
|
||||
|
||||
return QC_VALUE;
|
||||
return new_value_expr (new_type_value (type, data.t),
|
||||
expl == suff_implicit);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_string (rua_tok_t *tok, int type, yyscan_t scanner)
|
||||
parse_string (QC_YYSTYPE *lval, const rua_tok_t *tok, int type,
|
||||
yyscan_t scanner)
|
||||
{
|
||||
const char *str = make_string (tok->text, 0);
|
||||
if (type == rua_char) {
|
||||
if (str[1]) {
|
||||
warning (0, "multibyte char constant");
|
||||
}
|
||||
tok->value.expr = new_int_expr (*str, false);
|
||||
lval->expr = new_int_expr (*str, false);
|
||||
return QC_VALUE;
|
||||
} else {
|
||||
tok->value.expr = new_string_expr (str);
|
||||
lval->expr = new_string_expr (str);
|
||||
return QC_STRING;
|
||||
}
|
||||
}
|
||||
|
@ -1077,7 +1065,8 @@ update_loc (rua_loc_t *loc, size_t textlen)
|
|||
}
|
||||
|
||||
static void
|
||||
save_text (rua_tok_t *tok, const char *text, size_t textlen, int state)
|
||||
save_text (rua_tok_t *tok, const char *text, size_t textlen, int state,
|
||||
rua_extra_t *extra)
|
||||
{
|
||||
/*if (state == TEXT) {
|
||||
while (isspace (*text)) {
|
||||
|
@ -1089,40 +1078,18 @@ save_text (rua_tok_t *tok, const char *text, size_t textlen, int state)
|
|||
tok->str_text[1] = 0;
|
||||
tok->text = tok->str_text;
|
||||
textlen = 1;
|
||||
} else */if (textlen < sizeof (tok->text)) {
|
||||
strncpy (tok->str_text, text, textlen);
|
||||
tok->str_text[textlen] = 0;
|
||||
tok->text = tok->str_text;
|
||||
} else */if (extra && textlen < sizeof (extra->str_text)) {
|
||||
strncpy (extra->str_text, text, textlen);
|
||||
extra->str_text[textlen] = 0;
|
||||
tok->text = extra->str_text;
|
||||
} else {
|
||||
tok->text = save_string (text);
|
||||
}
|
||||
tok->textlen = textlen;
|
||||
}
|
||||
|
||||
static rua_expr_t
|
||||
token_expr (int token, const rua_tok_t *tok)
|
||||
{
|
||||
return (rua_expr_t) {
|
||||
.location = tok->location,
|
||||
.textlen = tok->textlen,
|
||||
.token = token,
|
||||
.text = save_string (tok->text),
|
||||
};
|
||||
}
|
||||
|
||||
static rua_tok_t
|
||||
expr_token (const rua_expr_t *e)
|
||||
{
|
||||
return (rua_tok_t) {
|
||||
.location = e->location,
|
||||
.textlen = e->textlen,
|
||||
.text = e->text, // macro token strings use save_string
|
||||
.token = e->token,
|
||||
};
|
||||
}
|
||||
|
||||
static bool
|
||||
join_tokens (rua_expr_t *out, const rua_expr_t *p1, const rua_expr_t *p2,
|
||||
join_tokens (rua_tok_t *out, const rua_tok_t *p1, const rua_tok_t *p2,
|
||||
rua_extra_t *extra)
|
||||
{
|
||||
auto str = va (0, "%s%s", p1 ? p1->text : "", p2 ? p2->text : "");
|
||||
|
@ -1139,12 +1106,13 @@ join_tokens (rua_expr_t *out, const rua_expr_t *p1, const rua_expr_t *p2,
|
|||
out->text = " ";
|
||||
return false;
|
||||
}
|
||||
*out = token_expr (token, &tok);
|
||||
tok.token = token;
|
||||
*out = tok;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
stringize_arg (rua_expr_t *out, rua_macro_t *arg, rua_extra_t *extra)
|
||||
stringize_arg (rua_tok_t *out, rua_macro_t *arg, rua_extra_t *extra)
|
||||
{
|
||||
dstring_copystr (extra->dstr, "\"");
|
||||
for (auto e = arg->tokens; e; e = e->next) {
|
||||
|
@ -1152,7 +1120,7 @@ stringize_arg (rua_expr_t *out, rua_macro_t *arg, rua_extra_t *extra)
|
|||
dstring_appendstr (extra->dstr, str);
|
||||
}
|
||||
dstring_appendstr (extra->dstr, "\"");
|
||||
*out = (rua_expr_t) {
|
||||
*out = (rua_tok_t) {
|
||||
.textlen = extra->dstr->size - 1,
|
||||
.token = -rua_string,
|
||||
.text = save_string (extra->dstr->str),
|
||||
|
@ -1161,8 +1129,10 @@ stringize_arg (rua_expr_t *out, rua_macro_t *arg, rua_extra_t *extra)
|
|||
}
|
||||
|
||||
static int
|
||||
preproc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
||||
preproc_token (rua_extra_t *extra, PRE_YYSTYPE *lval, const rua_tok_t *tok,
|
||||
yyscan_t *scanner)
|
||||
{
|
||||
int token = tok->token;
|
||||
if (!token) {
|
||||
return token;
|
||||
}
|
||||
|
@ -1171,6 +1141,7 @@ preproc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
|||
switch (term) {
|
||||
case rua_ignore:
|
||||
case rua_num_term:
|
||||
case rua_grab:
|
||||
internal_error (0, "unexpected rua token: %d", term);
|
||||
case rua_eof:
|
||||
case rua_error:
|
||||
|
@ -1181,12 +1152,18 @@ preproc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
|||
break;
|
||||
case rua_number:
|
||||
if (!extra->recording) {
|
||||
token = parse_number (tok, scanner);
|
||||
token = -rua_error;
|
||||
if ((lval->expr = parse_number (tok, scanner))) {
|
||||
token = PRE_VALUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case rua_vector:
|
||||
if (!extra->recording) {
|
||||
token = parse_vector (tok, scanner);
|
||||
token = -rua_error;
|
||||
if (!(lval->expr = parse_vector (tok, scanner))) {
|
||||
token = PRE_VALUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case rua_string:
|
||||
|
@ -1203,7 +1180,7 @@ preproc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
|||
if (token == PRE_ID) {
|
||||
token = -rua_id;
|
||||
}
|
||||
tok->token = token;
|
||||
lval->t.token = token;
|
||||
if (token != PRE_EOD && token != ',' && token != '(' && token != ')') {
|
||||
token = PRE_TOKEN;
|
||||
}
|
||||
|
@ -1230,9 +1207,10 @@ convert_long (const expr_t *value)
|
|||
}
|
||||
|
||||
static int
|
||||
qc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
||||
qc_token (rua_extra_t *extra, QC_YYSTYPE *lval, const rua_tok_t *tok,
|
||||
yyscan_t *scanner)
|
||||
{
|
||||
auto value = &tok->value;
|
||||
int token = tok->token;
|
||||
|
||||
if (token < 0) {
|
||||
rua_term term = -token;
|
||||
|
@ -1244,22 +1222,40 @@ qc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
|||
case rua_error:
|
||||
break;
|
||||
case rua_id:
|
||||
token = keyword_or_id (tok, tok->text);
|
||||
token = keyword_or_id (lval, tok->text);
|
||||
break;
|
||||
case rua_grab:
|
||||
{
|
||||
int ret = do_grab (tok->text);
|
||||
if (ret >= 0) {
|
||||
lval->expr = new_int_expr (ret, false);
|
||||
token = QC_VALUE;
|
||||
} else {
|
||||
yy_push_state (-ret, scanner);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case rua_number:
|
||||
token = parse_number (tok, scanner);
|
||||
if (token == QC_VALUE && value->expr->implicit) {
|
||||
if (is_long (get_type (value->expr))) {
|
||||
value->expr = convert_long (value->expr);
|
||||
token = -rua_error;
|
||||
lval->expr = parse_number (tok, scanner);
|
||||
if (lval->expr) {
|
||||
token = QC_VALUE;
|
||||
if (lval->expr->implicit) {
|
||||
if (is_long (get_type (lval->expr))) {
|
||||
lval->expr = convert_long (lval->expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case rua_vector:
|
||||
token = parse_vector (tok, scanner);
|
||||
token = -rua_error;
|
||||
if ((lval->expr = parse_vector (tok, scanner))) {
|
||||
token = QC_VALUE;
|
||||
}
|
||||
break;
|
||||
case rua_string:
|
||||
case rua_char:
|
||||
token = parse_string (tok, -token, scanner);
|
||||
token = parse_string (lval, tok, -token, scanner);
|
||||
break;
|
||||
case rua_space:
|
||||
if (options.preprocess_output) {
|
||||
|
@ -1271,17 +1267,17 @@ qc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
|||
break;
|
||||
case rua_asx:
|
||||
token = QC_ASX;
|
||||
tok->value.op = tok->text[0];
|
||||
lval->op = tok->text[0];
|
||||
switch (tok->text[1]) {
|
||||
case '=': break;
|
||||
case '%': tok->value.op = QC_MOD; break;
|
||||
case '<': tok->value.op = QC_SHL; break;
|
||||
case '>': tok->value.op = QC_SHR; break;
|
||||
case '%': lval->op = QC_MOD; break;
|
||||
case '<': lval->op = QC_SHL; break;
|
||||
case '>': lval->op = QC_SHR; break;
|
||||
}
|
||||
break;
|
||||
case rua_incop:
|
||||
token = QC_INCOP;
|
||||
tok->value.op = tok->text[0];
|
||||
lval->op = tok->text[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1354,10 +1350,12 @@ qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
|||
|
||||
rua_macro_t *macro = 0;
|
||||
if (extra->pending_macro) {
|
||||
PRE_YYSTYPE lval = { .t = *tok };
|
||||
|
||||
if (extra->recording) {
|
||||
token = preproc_token (extra, token, tok, scanner);
|
||||
token = preproc_token (extra, &lval, tok, scanner);
|
||||
int status = pre_yypush_parse (extra->args_state, token,
|
||||
tok, &tok->location, scanner);
|
||||
&lval, &tok->location, scanner);
|
||||
if (status == YYPUSH_MORE) {
|
||||
return YYPUSH_MORE;
|
||||
}
|
||||
|
@ -1397,7 +1395,7 @@ qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
|||
rua_start_args (scanner);
|
||||
token = PRE_ARGS;
|
||||
int status = pre_yypush_parse (extra->args_state, token,
|
||||
tok, &tok->location, scanner);
|
||||
&lval, &tok->location, scanner);
|
||||
if (status != YYPUSH_MORE) {
|
||||
internal_error (0, "can't start parsing macro args");
|
||||
}
|
||||
|
@ -1434,11 +1432,13 @@ qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
|||
}
|
||||
if (extra->preprocessor) {
|
||||
auto state = extra->pre_state;
|
||||
token = preproc_token (extra, token, tok, scanner);
|
||||
PRE_YYSTYPE lval = { .t = *tok };
|
||||
|
||||
token = preproc_token (extra, &lval, tok, scanner);
|
||||
if (-token == rua_ignore) {
|
||||
return YYPUSH_MORE;
|
||||
}
|
||||
return pre_yypush_parse (state, token, tok, loc, scanner);
|
||||
return pre_yypush_parse (state, token, &lval, loc, scanner);
|
||||
} else {
|
||||
if (!extra->suppressed) {
|
||||
if (options.preprocess_only) {
|
||||
|
@ -1447,18 +1447,18 @@ qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
|||
}
|
||||
return token ? YYPUSH_MORE : 0;
|
||||
}
|
||||
token = qc_token (extra, token, tok, scanner);
|
||||
QC_YYSTYPE lval = {};
|
||||
token = qc_token (extra, &lval, tok, scanner);
|
||||
if (token >= 0) {
|
||||
auto state = extra->qc_state;
|
||||
auto value = &tok->value;
|
||||
return qc_yypush_parse (state, token, value, loc, scanner);
|
||||
return qc_yypush_parse (state, token, &lval, loc, scanner);
|
||||
}
|
||||
}
|
||||
}
|
||||
return YYPUSH_MORE;
|
||||
}
|
||||
|
||||
static rua_expr_t
|
||||
static rua_tok_t
|
||||
next_macro_token (rua_extra_t *extra)
|
||||
{
|
||||
auto e = *extra->macro->cursor;
|
||||
|
@ -1466,8 +1466,8 @@ next_macro_token (rua_extra_t *extra)
|
|||
return e;
|
||||
}
|
||||
|
||||
static rua_expr_t *
|
||||
get_arg_token (bool last, rua_expr_t *arg, const rua_macro_t *macro)
|
||||
static rua_tok_t *
|
||||
get_arg_token (bool last, rua_tok_t *arg, const rua_macro_t *macro)
|
||||
{
|
||||
symbol_t *sym;
|
||||
|
||||
|
@ -1477,7 +1477,7 @@ get_arg_token (bool last, rua_expr_t *arg, const rua_macro_t *macro)
|
|||
auto a = macro->args[sym->s.offset];
|
||||
if (last) {
|
||||
if (a->tokens) {
|
||||
return (rua_expr_t *) a->tail;
|
||||
return (rua_tok_t *) a->tail;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -1488,9 +1488,9 @@ get_arg_token (bool last, rua_expr_t *arg, const rua_macro_t *macro)
|
|||
}
|
||||
|
||||
static void
|
||||
copy_token (rua_macro_t *dst, const rua_expr_t *t)
|
||||
copy_token (rua_macro_t *dst, const rua_tok_t *t)
|
||||
{
|
||||
rua_expr_t *e = malloc (sizeof (*e));
|
||||
rua_tok_t *e = malloc (sizeof (*e));
|
||||
*e = *t;
|
||||
e->next = 0;
|
||||
*dst->tail = e;
|
||||
|
@ -1499,7 +1499,7 @@ copy_token (rua_macro_t *dst, const rua_expr_t *t)
|
|||
|
||||
static void
|
||||
copy_arg_token (rua_macro_t *dst, bool skip_first, bool skip_last,
|
||||
const rua_expr_t *arg, const rua_macro_t *macro)
|
||||
const rua_tok_t *arg, const rua_macro_t *macro)
|
||||
{
|
||||
symbol_t *sym;
|
||||
|
||||
|
@ -1535,8 +1535,7 @@ collect_args (rua_macro_t *m, rua_macro_t *macro, void *scanner)
|
|||
if (t && t->token == '(') {
|
||||
rua_reset_args (m);
|
||||
int paren = 1;
|
||||
auto tk = expr_token (t);
|
||||
auto a = rua_macro_arg (&tk, scanner);
|
||||
auto a = rua_macro_arg (t, scanner);
|
||||
for (t = t->next; t; t = t->next) {
|
||||
if (t->token == '(') {
|
||||
paren++;
|
||||
|
@ -1546,11 +1545,10 @@ collect_args (rua_macro_t *m, rua_macro_t *macro, void *scanner)
|
|||
break;
|
||||
}
|
||||
}
|
||||
tk = expr_token (t);
|
||||
if (t->token == ',' && paren == 1) {
|
||||
a = rua_macro_arg (&tk, scanner);
|
||||
a = rua_macro_arg (t, scanner);
|
||||
} else {
|
||||
rua_macro_append (a, &tk, scanner);
|
||||
rua_macro_append (a, t, scanner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1600,7 +1598,7 @@ rescan:
|
|||
do {
|
||||
auto p = get_arg_token (true, &e, macro);
|
||||
auto n = get_arg_token (false, e.next->next, macro);
|
||||
rua_expr_t cat;
|
||||
rua_tok_t cat;
|
||||
if (!(sl = join_tokens (&cat, p, n, extra))) {
|
||||
cat.location = e.next->location;
|
||||
cat.token = -rua_space;
|
||||
|
@ -1646,14 +1644,15 @@ rescan:
|
|||
extra->macro = m;
|
||||
goto rescan;
|
||||
}
|
||||
*tok = expr_token (&e);
|
||||
token = tok->token;
|
||||
*tok = e;
|
||||
} else {
|
||||
token = yylex (tok, &extra->location, scanner);
|
||||
tok->token = yylex (tok, &extra->location, scanner);
|
||||
tok->location = extra->location;
|
||||
if (extra->recording && tok->text == extra->str_text) {
|
||||
tok->text = save_string (tok->text);
|
||||
}
|
||||
}
|
||||
tok->token = token;
|
||||
return token;
|
||||
return tok->token;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1754,7 +1753,7 @@ rua_end_params (rua_macro_t *macro, void *scanner)
|
|||
}
|
||||
|
||||
rua_macro_t *
|
||||
rua_macro_append (rua_macro_t *macro, rua_tok_t *token, void *scanner)
|
||||
rua_macro_append (rua_macro_t *macro, const rua_tok_t *token, void *scanner)
|
||||
{
|
||||
auto extra = qc_yyget_extra (scanner);
|
||||
if (extra->suppressed || !macro) {
|
||||
|
@ -1765,27 +1764,27 @@ rua_macro_append (rua_macro_t *macro, rua_tok_t *token, void *scanner)
|
|||
// ignore leading space
|
||||
return macro;
|
||||
}
|
||||
auto t = (rua_expr_t *) macro->tail;
|
||||
auto t = (rua_tok_t *) macro->tail;
|
||||
if (t->token == '#' || t->token == PRE_CONCAT) {
|
||||
// ignore space after '#' and '##'
|
||||
return macro;
|
||||
}
|
||||
}
|
||||
rua_expr_t *expr = (rua_expr_t *) macro->tail;
|
||||
auto expr = (rua_tok_t *) macro->tail;
|
||||
if (token->token != PRE_CONCAT
|
||||
|| !macro->tokens
|
||||
|| expr->token != -rua_space) {
|
||||
expr = malloc (sizeof (*expr));
|
||||
macro->num_tokens++;
|
||||
}
|
||||
*expr = token_expr (token->token, token);
|
||||
*expr = *token;
|
||||
*macro->tail = expr;
|
||||
macro->tail = &expr->next;
|
||||
return macro;
|
||||
}
|
||||
|
||||
rua_macro_t *
|
||||
rua_macro_param (rua_macro_t *macro, rua_tok_t *token, void *scanner)
|
||||
rua_macro_param (rua_macro_t *macro, const rua_tok_t *token, void *scanner)
|
||||
{
|
||||
auto extra = qc_yyget_extra (scanner);
|
||||
if (extra->suppressed) {
|
||||
|
@ -1824,10 +1823,10 @@ rua_macro_finish (rua_macro_t *macro, void *scanner)
|
|||
return;
|
||||
}
|
||||
if (macro->tokens) {
|
||||
while (((rua_expr_t *) macro->tail)->token == -rua_space) {
|
||||
while (((rua_tok_t *) macro->tail)->token == -rua_space) {
|
||||
// space is never added as the first token, so it's guaranteed
|
||||
// there is always at least two tokens
|
||||
rua_expr_t *t;
|
||||
rua_tok_t *t;
|
||||
for (t = macro->tokens; t->next->next; t = t->next) continue;
|
||||
free (t->next);
|
||||
t->next = 0;
|
||||
|
@ -1835,7 +1834,7 @@ rua_macro_finish (rua_macro_t *macro, void *scanner)
|
|||
macro->num_tokens--;
|
||||
}
|
||||
if (macro->tokens->token == PRE_CONCAT
|
||||
|| ((rua_expr_t *) macro->tail)->token == PRE_CONCAT) {
|
||||
|| ((rua_tok_t *) macro->tail)->token == PRE_CONCAT) {
|
||||
error (0, "'##' cannot appear at either end of a macro expansion");
|
||||
return;
|
||||
}
|
||||
|
@ -1910,7 +1909,7 @@ hashhash_error:
|
|||
}
|
||||
|
||||
rua_macro_t *
|
||||
rua_macro_arg (rua_tok_t *token, void *scanner)
|
||||
rua_macro_arg (const rua_tok_t *token, void *scanner)
|
||||
{
|
||||
auto extra = qc_yyget_extra (scanner);
|
||||
auto macro = extra->pending_macro;
|
||||
|
@ -2212,7 +2211,7 @@ rua_parse_define (const char *def)
|
|||
{
|
||||
int status;
|
||||
yyscan_t scanner;
|
||||
rua_tok_t tok = { .location = { 1, 1, 1, 1 }, };
|
||||
rua_tok_t tok = { .location = { 1, 1, 1, 1 }, .token = -1, };
|
||||
rua_extra_t extra = {
|
||||
.preprocessor = true,
|
||||
.pre_state = pre_yypstate_new (),
|
||||
|
@ -2224,26 +2223,23 @@ rua_parse_define (const char *def)
|
|||
|
||||
yy_push_state (PREPROC, scanner);
|
||||
|
||||
int token = -1;
|
||||
do {
|
||||
if (token == -1) {
|
||||
token = PRE_DEFINE;
|
||||
if (tok.token == -1) {
|
||||
tok.token = PRE_DEFINE;
|
||||
} else {
|
||||
token = yylex (&tok, &tok.location, scanner);
|
||||
tok.token = yylex (&tok, &tok.location, scanner);
|
||||
status = 0;
|
||||
}
|
||||
while (token) {
|
||||
status = qc_process (&extra, token, &tok, scanner);
|
||||
while (tok.token) {
|
||||
status = qc_process (&extra, tok.token, &tok, scanner);
|
||||
if (status != YYPUSH_MORE || !extra.macro) {
|
||||
break;
|
||||
}
|
||||
auto expr = *extra.macro->cursor;
|
||||
tok = *extra.macro->cursor;
|
||||
extra.macro->cursor = extra.macro->cursor->next;
|
||||
if (!extra.macro->cursor) {
|
||||
extra.macro = extra.macro->next;
|
||||
}
|
||||
token = expr.token;
|
||||
tok = expr_token (&expr);
|
||||
}
|
||||
} while (status == YYPUSH_MORE);
|
||||
|
||||
|
@ -2285,11 +2281,11 @@ rua_macro_file (rua_macro_t *macro, void *scanner)
|
|||
macro->tail = ¯o->tokens;
|
||||
macro->num_tokens = 0;
|
||||
|
||||
rua_expr_t *expr = malloc (sizeof (*expr));
|
||||
rua_tok_t *expr = malloc (sizeof (*expr));
|
||||
macro->num_tokens++;
|
||||
const char *file_str = save_string (va (0, "\"%s\"",
|
||||
quote_string (GETSTR (file))));
|
||||
*expr = (rua_expr_t) {
|
||||
*expr = (rua_tok_t) {
|
||||
.location = extra->location,
|
||||
.textlen = strlen (file_str),
|
||||
.token = -rua_string,
|
||||
|
@ -2312,10 +2308,10 @@ rua_macro_line (rua_macro_t *macro, void *scanner)
|
|||
macro->tail = ¯o->tokens;
|
||||
macro->num_tokens = 0;
|
||||
|
||||
rua_expr_t *expr = malloc (sizeof (*expr));
|
||||
rua_tok_t *expr = malloc (sizeof (*expr));
|
||||
macro->num_tokens++;
|
||||
const char *line_str = save_string (va (0, "%d", line));
|
||||
*expr = (rua_expr_t) {
|
||||
*expr = (rua_tok_t) {
|
||||
.location = extra->location,
|
||||
.textlen = strlen (line_str),
|
||||
.token = -rua_number,
|
||||
|
|
Loading…
Reference in a new issue