2001-09-28 07:09:38 +00:00
|
|
|
|
/*
|
2002-11-06 16:32:28 +00:00
|
|
|
|
qc-lex.l
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
2002-11-06 16:32:28 +00:00
|
|
|
|
lexer for quakec
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
2002-11-06 16:32:28 +00:00
|
|
|
|
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
2002-11-06 16:32:28 +00:00
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
|
|
|
Date: 2001/06/12
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
|
|
*/
|
2023-10-08 01:57:57 +00:00
|
|
|
|
%option bison-locations
|
2023-10-10 17:34:39 +00:00
|
|
|
|
%option bison-bridge
|
|
|
|
|
%option reentrant
|
2023-10-08 01:57:57 +00:00
|
|
|
|
%option prefix="qc_yy"
|
|
|
|
|
%option noyywrap
|
|
|
|
|
%option debug
|
2023-10-21 01:12:41 +00:00
|
|
|
|
%option stack
|
2023-10-08 01:57:57 +00:00
|
|
|
|
|
2023-10-20 11:31:15 +00:00
|
|
|
|
%top{
|
2002-06-01 04:41:25 +00:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
# include "config.h"
|
|
|
|
|
#endif
|
2003-01-14 20:18:29 +00:00
|
|
|
|
|
2002-06-01 04:41:25 +00:00
|
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
|
# include <string.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
|
# include <strings.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
2002-06-27 22:48:28 +00:00
|
|
|
|
#include <QF/dstring.h>
|
2001-06-13 07:16:39 +00:00
|
|
|
|
#include <QF/hash.h>
|
2001-10-24 22:50:06 +00:00
|
|
|
|
#include <QF/sys.h>
|
2023-10-24 06:58:37 +00:00
|
|
|
|
#include <QF/va.h>
|
2002-06-27 22:48:28 +00:00
|
|
|
|
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/class.h"
|
2023-10-25 12:07:50 +00:00
|
|
|
|
#include "tools/qfcc/include/cpp.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/debug.h"
|
|
|
|
|
#include "tools/qfcc/include/diagnostic.h"
|
|
|
|
|
#include "tools/qfcc/include/expr.h"
|
|
|
|
|
#include "tools/qfcc/include/grab.h"
|
|
|
|
|
#include "tools/qfcc/include/options.h"
|
|
|
|
|
#include "tools/qfcc/include/pragma.h"
|
|
|
|
|
#include "tools/qfcc/include/qfcc.h"
|
2023-10-20 11:31:15 +00:00
|
|
|
|
#include "tools/qfcc/include/rua-lang.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/shared.h"
|
|
|
|
|
#include "tools/qfcc/include/strpool.h"
|
|
|
|
|
#include "tools/qfcc/include/struct.h"
|
|
|
|
|
#include "tools/qfcc/include/symtab.h"
|
|
|
|
|
#include "tools/qfcc/include/type.h"
|
|
|
|
|
#include "tools/qfcc/include/value.h"
|
2023-10-20 11:31:15 +00:00
|
|
|
|
}
|
2020-06-21 14:15:17 +00:00
|
|
|
|
|
2023-10-20 11:31:15 +00:00
|
|
|
|
%{
|
2003-04-16 19:41:52 +00:00
|
|
|
|
#ifndef YY_PROTO
|
|
|
|
|
# define YY_PROTO(x) x
|
|
|
|
|
#else
|
|
|
|
|
# define YY_FLEX_REALLOC_HACK
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-10-19 14:05:47 +00:00
|
|
|
|
#define YY_NO_INPUT // debian flex
|
|
|
|
|
#define YY_NO_UNPUT // debian flex
|
|
|
|
|
#define YY_NO_YYINPUT
|
|
|
|
|
#define YY_NO_YYUNPUT
|
2023-10-08 01:57:57 +00:00
|
|
|
|
|
2023-10-20 11:31:15 +00:00
|
|
|
|
#define YYSTYPE rua_tok_t
|
|
|
|
|
#define YYLTYPE rua_loc_t
|
2001-06-12 21:06:28 +00:00
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
bool saw_true;
|
|
|
|
|
bool saw_else;
|
|
|
|
|
bool own_state;
|
|
|
|
|
bool enabled;
|
2023-10-26 11:31:54 +00:00
|
|
|
|
int line;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
} rua_cond_t;
|
|
|
|
|
|
|
|
|
|
typedef struct DARRAY_TYPE (rua_cond_t) rua_cond_stack_t;
|
2023-10-31 01:48:11 +00:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
YY_BUFFER_STATE buffer;
|
|
|
|
|
rua_cond_stack_t cond_stack;
|
2023-11-06 04:41:17 +00:00
|
|
|
|
rua_loc_t location;
|
2023-10-31 01:48:11 +00:00
|
|
|
|
} rua_incl_t;
|
|
|
|
|
|
2023-10-24 14:32:13 +00:00
|
|
|
|
typedef struct DARRAY_TYPE (rua_macro_t *) rua_macro_list_t;
|
2023-10-31 01:48:11 +00:00
|
|
|
|
typedef struct DARRAY_TYPE (rua_incl_t) rua_include_stack_t;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
2023-10-20 11:31:15 +00:00
|
|
|
|
typedef struct rua_extra_s {
|
|
|
|
|
int start_state;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
bool preprocessor;
|
|
|
|
|
bool recording;
|
2023-10-24 05:01:21 +00:00
|
|
|
|
bool params;
|
2023-10-24 06:58:37 +00:00
|
|
|
|
bool expand;
|
2023-10-26 11:31:54 +00:00
|
|
|
|
bool suppressed;
|
2023-11-18 09:08:23 +00:00
|
|
|
|
bool no_lex;
|
2023-11-18 17:10:44 +00:00
|
|
|
|
bool did_space;
|
2024-04-18 15:49:47 +00:00
|
|
|
|
rua_parser_t *parser;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
pre_yypstate *pre_state;
|
2023-10-29 15:41:06 +00:00
|
|
|
|
pre_yypstate *args_state;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
rua_cond_stack_t cond_stack;
|
2023-10-25 12:07:50 +00:00
|
|
|
|
rua_include_stack_t include_stack;
|
2023-10-24 15:20:12 +00:00
|
|
|
|
dstring_t *dstr;
|
2023-10-23 09:32:06 +00:00
|
|
|
|
symtab_t *macro_tab;
|
2023-10-29 15:41:06 +00:00
|
|
|
|
rua_macro_t *pending_macro; // function-type waiting for args
|
2023-11-03 04:54:08 +00:00
|
|
|
|
rua_macro_t *macro; // macro being expanded
|
2023-10-24 06:58:37 +00:00
|
|
|
|
yyscan_t subscanner;
|
2023-11-06 04:41:17 +00:00
|
|
|
|
rua_loc_t location;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
char str_text[8]; // EPHEMERAL! for short token strings
|
2023-10-20 11:31:15 +00:00
|
|
|
|
} rua_extra_t;
|
|
|
|
|
#define YY_EXTRA_TYPE rua_extra_t *
|
|
|
|
|
|
|
|
|
|
rua_extra_t *qc_yyget_extra (yyscan_t yyscanner) __attribute__((pure));
|
2023-10-10 17:34:39 +00:00
|
|
|
|
int yyget_lineno (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
int yyget_column (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
YYSTYPE *yyget_lval (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
YYLTYPE *yyget_lloc (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
int yyget_leng (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
char *yyget_text (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
int yyget_debug (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
FILE *yyget_in (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
FILE *yyget_out (yyscan_t yyscanner) __attribute__((pure));
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
static int directive (const char *token, yyscan_t scanner);
|
2023-10-26 11:31:54 +00:00
|
|
|
|
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,
|
2023-11-11 13:32:29 +00:00
|
|
|
|
int state, rua_extra_t *extra);
|
2023-10-24 13:06:01 +00:00
|
|
|
|
static void next_line (rua_loc_t *loc, yyscan_t scanner);
|
2023-11-22 02:43:39 +00:00
|
|
|
|
static void dump_state_stack (yyscan_t scanner);
|
2023-10-26 11:31:54 +00:00
|
|
|
|
static void dump_token (rua_tok_t *tok, rua_loc_t *loc, int state);
|
|
|
|
|
static void dump_debug (int act, const char *text, int state);
|
2001-06-25 22:11:20 +00:00
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
typedef enum {
|
2023-10-20 12:15:17 +00:00
|
|
|
|
rua_eof = 1,
|
2023-10-24 04:23:06 +00:00
|
|
|
|
rua_ignore,
|
2023-10-20 12:15:17 +00:00
|
|
|
|
rua_error,
|
2023-10-24 04:23:06 +00:00
|
|
|
|
rua_id,
|
2023-10-20 12:15:17 +00:00
|
|
|
|
rua_number,
|
|
|
|
|
rua_vector,
|
2023-10-20 16:13:32 +00:00
|
|
|
|
rua_string,
|
|
|
|
|
rua_char,
|
2023-10-23 13:00:14 +00:00
|
|
|
|
rua_space,
|
2023-10-30 04:25:48 +00:00
|
|
|
|
rua_ellipsis,
|
2023-10-31 01:37:02 +00:00
|
|
|
|
rua_asx,
|
|
|
|
|
rua_incop,
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_grab,
|
2023-11-18 04:39:29 +00:00
|
|
|
|
rua_va_opt,
|
2023-10-20 12:15:17 +00:00
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
rua_num_term,
|
|
|
|
|
} rua_term;
|
|
|
|
|
|
2024-04-18 01:34:18 +00:00
|
|
|
|
// for debian flex
|
|
|
|
|
#ifndef yystart
|
|
|
|
|
#define yystart() YY_START
|
|
|
|
|
#define yybuffer YY_BUFFER_STATE
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-10-26 11:31:54 +00:00
|
|
|
|
#define YY_USER_ACTION \
|
|
|
|
|
update_loc (yylloc, yyleng); \
|
2023-11-11 13:32:29 +00:00
|
|
|
|
save_text (yylval, yytext, yyleng, yystart(), extra); \
|
2023-10-26 11:31:54 +00:00
|
|
|
|
if (0) { dump_debug (yy_act, yytext, yystart()); } \
|
|
|
|
|
if (0) { dump_token (yylval, yylloc, yystart ()); } \
|
|
|
|
|
if (0) { dump_state_stack(yyscanner); }
|
2001-06-13 07:16:39 +00:00
|
|
|
|
|
2001-06-12 21:06:28 +00:00
|
|
|
|
%}
|
|
|
|
|
|
2011-01-14 03:10:28 +00:00
|
|
|
|
s [ \t]
|
|
|
|
|
m [\-+]
|
|
|
|
|
D [0-9]
|
2023-10-20 12:15:17 +00:00
|
|
|
|
IDs [a-zA-Z_]
|
|
|
|
|
IDc [a-zA-Z_0-9]
|
|
|
|
|
ID {IDs}{IDc}*
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
FD [fFdD]
|
|
|
|
|
UL ([uU]?([lL][lL]?)?)
|
|
|
|
|
ULFD ({UL}|{FD})
|
2011-01-14 03:10:28 +00:00
|
|
|
|
RANGE \.\.
|
|
|
|
|
ELLIPSIS \.\.\.
|
|
|
|
|
FRAMEID {ID}(\.{ID})*
|
2012-11-22 11:42:00 +00:00
|
|
|
|
PRAGMAID {ID}(-{ID})*
|
2023-10-20 16:13:32 +00:00
|
|
|
|
s_string \"(\\.|[^"\\])*\"
|
|
|
|
|
c_string '(\\.|[^'\\])*'
|
2023-10-22 11:56:12 +00:00
|
|
|
|
h_string <[^>]*>
|
|
|
|
|
q_string \"[^\"]*\"
|
2001-06-12 21:06:28 +00:00
|
|
|
|
|
2023-10-20 12:15:17 +00:00
|
|
|
|
pp_number \.?{D}({IDc}|'{IDc}|[eEpP]{m}|\.)*
|
2023-10-20 16:17:11 +00:00
|
|
|
|
pp_vnumber '({s}*{m}?{pp_number}){2,4}{s}*'{ULFD}?
|
2023-10-20 12:15:17 +00:00
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
%x GRAB_FRAME GRAB_OTHER GRAB_WRITE
|
|
|
|
|
%x COMMENT LCOMMENT
|
2023-10-28 14:51:12 +00:00
|
|
|
|
%x DIRECTIVE TEXT
|
|
|
|
|
%x PRAGMA VECTOR
|
|
|
|
|
%s PREPROC PREEXPR
|
|
|
|
|
%s MACRO ARGS
|
2023-10-26 11:31:54 +00:00
|
|
|
|
%x CONT
|
2001-06-13 18:35:41 +00:00
|
|
|
|
|
2001-06-12 21:06:28 +00:00
|
|
|
|
%%
|
2023-10-22 11:56:12 +00:00
|
|
|
|
auto extra = qc_yyget_extra (yyscanner);
|
2023-10-20 16:17:11 +00:00
|
|
|
|
yyset_debug (0, yyscanner);
|
|
|
|
|
grab_frame = GRAB_FRAME;
|
|
|
|
|
grab_other = GRAB_OTHER;
|
|
|
|
|
grab_write = GRAB_WRITE;
|
|
|
|
|
|
2023-10-26 11:31:54 +00:00
|
|
|
|
<COMMENT>"/*" { warning (0, "nested /* in comment"); yymore();}
|
2023-10-23 13:00:14 +00:00
|
|
|
|
<COMMENT>\*+"/" { yy_pop_state (yyscanner); return -rua_space; }
|
2023-10-26 11:31:54 +00:00
|
|
|
|
<COMMENT>\r*\n { next_line (yylloc, yyscanner); yymore();}
|
|
|
|
|
<COMMENT>[^*/\n]* { yymore(); }/* munch on anything but possible end of comment */
|
|
|
|
|
<COMMENT>\/+[^*\n]* { yymore(); }/* handle /s not followed by * */
|
2023-10-30 04:22:57 +00:00
|
|
|
|
<COMMENT>\*+/[^/] { yymore(); }/* handle *s not followed by / */
|
2023-10-20 16:17:11 +00:00
|
|
|
|
<COMMENT><<EOF>> { error (0, "EOF in comment"); return 0; }
|
2023-10-26 11:31:54 +00:00
|
|
|
|
<*>"/*" { yy_push_state (COMMENT, yyscanner); yymore(); }
|
2023-10-30 05:32:11 +00:00
|
|
|
|
<*>"//" {
|
2023-10-26 11:31:54 +00:00
|
|
|
|
yymore();
|
2023-10-30 05:32:11 +00:00
|
|
|
|
yy_push_state (LCOMMENT, yyscanner);
|
|
|
|
|
}
|
|
|
|
|
<LCOMMENT>[^\\\r\n]+ /* consume all but \ and EOL (see line continuation) */
|
|
|
|
|
<LCOMMENT>[\\]+/[^\r\n] /* consume \ */
|
|
|
|
|
<LCOMMENT>\r*\n {
|
|
|
|
|
next_line (yylloc, yyscanner);
|
|
|
|
|
yy_pop_state (yyscanner);
|
2023-10-26 11:31:54 +00:00
|
|
|
|
int state = yystart ();
|
|
|
|
|
if (state == PREEXPR || state == PREPROC
|
2023-10-28 14:51:12 +00:00
|
|
|
|
|| state == DIRECTIVE || state == MACRO) {
|
2023-10-26 11:31:54 +00:00
|
|
|
|
return PRE_EOD;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-06-13 07:16:39 +00:00
|
|
|
|
|
2023-10-24 13:06:01 +00:00
|
|
|
|
<ARGS>^# { return '#'; }
|
2023-10-25 03:19:19 +00:00
|
|
|
|
^#{s}+/{D} {
|
|
|
|
|
yy_push_state (PREPROC, yyscanner);
|
|
|
|
|
extra->preprocessor = true;
|
|
|
|
|
return PRE_LINE;
|
|
|
|
|
}
|
2023-10-26 11:31:54 +00:00
|
|
|
|
<CONT>^. { yyless (yyleng - 1); yy_pop_state (yyscanner); }
|
2023-10-28 14:51:12 +00:00
|
|
|
|
<*>^{s}*#{s}* {
|
2023-10-22 11:56:12 +00:00
|
|
|
|
yy_push_state (DIRECTIVE, yyscanner);
|
|
|
|
|
extra->preprocessor = true;
|
|
|
|
|
}
|
2023-10-24 13:06:01 +00:00
|
|
|
|
<ARGS><<EOF>> { return 0; }
|
|
|
|
|
<ARGS>^{s}* { return -rua_space; }
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
|
|
|
|
<DIRECTIVE>{ID} { {
|
|
|
|
|
int tok = directive (yytext, yyscanner);
|
|
|
|
|
if (tok >= 0) {
|
|
|
|
|
return tok;
|
|
|
|
|
}
|
|
|
|
|
} }
|
2023-10-30 04:28:45 +00:00
|
|
|
|
<PREPROC>{ID} { return PRE_ID; }
|
2023-10-22 11:56:12 +00:00
|
|
|
|
<PREPROC>{ID}\( { return PRE_IDp; }
|
|
|
|
|
|
2023-10-30 04:25:48 +00:00
|
|
|
|
<ARGS>\r*\n { next_line (yylloc, yyscanner); return -rua_space; }
|
2023-10-22 11:56:12 +00:00
|
|
|
|
<DIRECTIVE>\r*\n |
|
|
|
|
|
<PREEXPR>\r*\n |
|
|
|
|
|
<MACRO,TEXT>\r*\n |
|
2023-10-24 13:06:01 +00:00
|
|
|
|
<PREPROC>\r*\n { next_line (yylloc, yyscanner); return PRE_EOD; }
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
|
|
|
|
<TEXT>[^\\\r\n]* { return PRE_TEXT; }
|
|
|
|
|
<TEXT>[\\]* { return PRE_TEXT; }
|
|
|
|
|
<MACRO>## { return PRE_CONCAT; }
|
|
|
|
|
<MACRO># { return '#'; }
|
2023-10-27 08:22:47 +00:00
|
|
|
|
<PREPROC>{h_string} { return PRE_HSTRING; }
|
|
|
|
|
<PREPROC>{q_string} { return PRE_QSTRING; }
|
2023-10-29 04:59:17 +00:00
|
|
|
|
<PREEXPR>{q_string} { return PRE_QSTRING; }
|
2023-10-23 09:32:06 +00:00
|
|
|
|
<PREEXPR>defined { return PRE_DEFINED; }
|
|
|
|
|
<PREEXPR>{ID} { return PRE_ID; }
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
2023-10-30 04:28:45 +00:00
|
|
|
|
<INITIAL,ARGS,MACRO>{
|
2023-10-24 13:06:01 +00:00
|
|
|
|
{ID} |
|
|
|
|
|
@{ID} { return -rua_id; }
|
|
|
|
|
}
|
2023-10-20 16:17:11 +00:00
|
|
|
|
@ { return '@'; }
|
|
|
|
|
|
|
|
|
|
{pp_number} { return -rua_number; }
|
|
|
|
|
{pp_vnumber} { return -rua_vector; }
|
2023-10-20 12:15:17 +00:00
|
|
|
|
<VECTOR>{pp_number} { return -rua_number; }
|
|
|
|
|
<VECTOR>{m} { return yytext[0]; }
|
|
|
|
|
<VECTOR>' { return -rua_eof; }
|
2002-01-04 08:45:24 +00:00
|
|
|
|
|
2023-10-20 16:13:32 +00:00
|
|
|
|
{s_string} { return -rua_string; };
|
|
|
|
|
{c_string} { return -rua_char; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
2023-10-31 01:37:02 +00:00
|
|
|
|
[+\-*/&|^%]= { return -rua_asx; }
|
|
|
|
|
"%%=" { return -rua_asx; }
|
|
|
|
|
"<<=" { return -rua_asx; }
|
|
|
|
|
">>=" { return -rua_asx; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
|
|
|
|
[!(){}.*/&|^~+\-=\[\];,#%?:] { return yytext[0]; }
|
|
|
|
|
|
2023-10-24 10:50:31 +00:00
|
|
|
|
"·" { return QC_DOT; }
|
|
|
|
|
"â‹€" { return QC_WEDGE; }
|
|
|
|
|
"•" { return QC_DOT; }
|
|
|
|
|
"∧" { return QC_WEDGE; }
|
|
|
|
|
"∨" { return QC_REGRESSIVE; }
|
|
|
|
|
"†" { return QC_REVERSE; }
|
|
|
|
|
"∗" { return QC_STAR; }
|
|
|
|
|
"×" { return QC_CROSS; }
|
|
|
|
|
"⋆" { return QC_DUAL; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
2023-10-24 10:50:31 +00:00
|
|
|
|
"%%" { return QC_MOD; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
2023-10-30 04:25:48 +00:00
|
|
|
|
{ELLIPSIS} { return -rua_ellipsis; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
2023-10-24 10:50:31 +00:00
|
|
|
|
"<<" { return QC_SHL; }
|
|
|
|
|
">>" { return QC_SHR; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
2023-10-24 10:50:31 +00:00
|
|
|
|
"&&" { return QC_AND; }
|
|
|
|
|
"||" { return QC_OR; }
|
|
|
|
|
"==" { return QC_EQ; }
|
|
|
|
|
"!=" { return QC_NE; }
|
|
|
|
|
"<=" { return QC_LE; }
|
|
|
|
|
">=" { return QC_GE; }
|
|
|
|
|
"<" { return QC_LT; }
|
|
|
|
|
">" { return QC_GT; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
2023-10-31 01:37:02 +00:00
|
|
|
|
"++" { return -rua_incop; }
|
|
|
|
|
"--" { return -rua_incop; }
|
2023-10-20 16:17:11 +00:00
|
|
|
|
|
2023-11-11 13:32:29 +00:00
|
|
|
|
"$"{s}*{FRAMEID} { return -rua_grab; }
|
2001-06-12 21:06:28 +00:00
|
|
|
|
|
2023-10-20 16:17:11 +00:00
|
|
|
|
<GRAB_FRAME>{FRAMEID} { add_frame_macro (yytext); }
|
2011-01-06 07:30:25 +00:00
|
|
|
|
<GRAB_OTHER>[^\r\n]* /* skip */
|
2023-10-20 16:13:32 +00:00
|
|
|
|
<GRAB_WRITE>{s_string} {
|
2012-11-21 11:50:45 +00:00
|
|
|
|
const char *s = make_string (yytext, 0);
|
|
|
|
|
write_frame_macros (s);
|
|
|
|
|
BEGIN (GRAB_OTHER); // ignore rest of line
|
|
|
|
|
}
|
2023-10-25 00:25:00 +00:00
|
|
|
|
<PRAGMA>{PRAGMAID} |
|
|
|
|
|
<PRAGMA>@{PRAGMAID} { return PRE_ID; }
|
|
|
|
|
<PRAGMA>\r*\n { next_line (yylloc, yyscanner); return PRE_EOD; }
|
2001-06-13 18:35:41 +00:00
|
|
|
|
|
2023-10-26 11:31:54 +00:00
|
|
|
|
<*>\\\r*\n {
|
|
|
|
|
/* line continuation */
|
|
|
|
|
next_line (yylloc, yyscanner);
|
|
|
|
|
}
|
|
|
|
|
<CONT><<EOF>> {
|
|
|
|
|
warning (0, "\\ at end of file");
|
|
|
|
|
yy_pop_state (yyscanner);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-10-20 16:17:11 +00:00
|
|
|
|
<*>\r*\n {
|
2023-10-24 13:06:01 +00:00
|
|
|
|
next_line (yylloc, yyscanner);
|
2023-10-21 01:12:41 +00:00
|
|
|
|
if (yyg->yy_start_stack_ptr) {
|
|
|
|
|
yy_pop_state (yyscanner);
|
2023-10-28 14:51:12 +00:00
|
|
|
|
extra->preprocessor = false;
|
2023-10-21 01:12:41 +00:00
|
|
|
|
}
|
2020-02-15 10:41:20 +00:00
|
|
|
|
}
|
2001-06-12 21:06:28 +00:00
|
|
|
|
|
2023-10-23 13:00:14 +00:00
|
|
|
|
<*>{s}+ { return -rua_space; }
|
2001-06-13 07:16:39 +00:00
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
<*>. {
|
|
|
|
|
error (0, "all your typo are belong to us:%d %d-%d",
|
|
|
|
|
yystart(),
|
2023-11-06 04:41:17 +00:00
|
|
|
|
yylloc->column, yylloc->last_column);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
2001-06-12 21:06:28 +00:00
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
static directive_t cond_directives[] = {
|
|
|
|
|
{"if", PRE_IF},
|
|
|
|
|
{"ifdef", PRE_IFDEF},
|
|
|
|
|
{"ifndef", PRE_IFNDEF},
|
|
|
|
|
{"else", PRE_ELSE},
|
|
|
|
|
{"elif", PRE_ELIF},
|
|
|
|
|
{"elifdef", PRE_ELIFDEF},
|
|
|
|
|
{"elifndef", PRE_ELIFNDEF},
|
|
|
|
|
{"endif", PRE_ENDIF},
|
|
|
|
|
};
|
|
|
|
|
|
2024-04-18 15:49:47 +00:00
|
|
|
|
const char *
|
|
|
|
|
rua_directive_get_key (const void *dir, void *unused)
|
2023-10-22 11:56:12 +00:00
|
|
|
|
{
|
|
|
|
|
return ((directive_t*)dir)->name;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-18 15:49:47 +00:00
|
|
|
|
const char *
|
|
|
|
|
rua_keyword_get_key (const void *kw, void *unused)
|
|
|
|
|
{
|
|
|
|
|
return ((keyword_t*)kw)->name;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
static int
|
|
|
|
|
directive (const char *token, yyscan_t scanner)
|
|
|
|
|
{
|
|
|
|
|
static hashtab_t *cond_directive_tab;
|
|
|
|
|
|
|
|
|
|
yy_pop_state (scanner); // pop DIRECTIVE off the stack
|
|
|
|
|
yy_push_state (PREPROC, scanner);
|
|
|
|
|
|
2024-04-18 15:49:47 +00:00
|
|
|
|
if (!cond_directive_tab) {
|
|
|
|
|
cond_directive_tab = Hash_NewTable (253, rua_directive_get_key,
|
|
|
|
|
0, 0, 0);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ARRCOUNT(cond_directives); i++) {
|
|
|
|
|
Hash_Add (cond_directive_tab, &cond_directives[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-28 14:51:12 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
directive_t *directive = Hash_Find (cond_directive_tab, token);
|
2024-04-18 15:49:47 +00:00
|
|
|
|
if (!directive && !extra->suppressed && extra->parser->directive) {
|
|
|
|
|
directive = extra->parser->directive (token);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
if (!directive) {
|
|
|
|
|
error (0, "invalid directive `%s`", token);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!directive) {
|
2023-10-30 05:32:11 +00:00
|
|
|
|
yy_pop_state (scanner);// suppressed non-conditional directive
|
|
|
|
|
yy_push_state (LCOMMENT, scanner);
|
|
|
|
|
extra->preprocessor = false;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
//auto lex = qc_yyget_extra (scanner);
|
|
|
|
|
//lex->current_lang = &lex->pre_lang;
|
|
|
|
|
return directive->value;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-20 12:15:17 +00:00
|
|
|
|
enum {
|
|
|
|
|
suff_error = -1,
|
|
|
|
|
suff_implicit,
|
|
|
|
|
suff_unsigned,
|
|
|
|
|
suff_long,
|
|
|
|
|
suff_unsigned_long,
|
|
|
|
|
suff_float,
|
|
|
|
|
suff_double,
|
|
|
|
|
suff_long_double,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_suffix (const char *suffix, bool fp)
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
{
|
2023-10-20 12:15:17 +00:00
|
|
|
|
int expl = suff_implicit;
|
|
|
|
|
bool unsign = false;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
|
2023-10-20 12:15:17 +00:00
|
|
|
|
if (!*suffix) {
|
|
|
|
|
return 0;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
if (fp) {
|
|
|
|
|
if (*suffix == 'f' || *suffix == 'F') {
|
|
|
|
|
expl = suff_float;
|
|
|
|
|
suffix++;
|
|
|
|
|
} else if (*suffix == 'd' || *suffix == 'D') {
|
|
|
|
|
// treat as explicit double unless it's a proper C decimal
|
|
|
|
|
// suffix, in which case the decimal part will be ignored
|
2023-10-28 14:51:12 +00:00
|
|
|
|
// (non-standard, but no decimal support)
|
2023-10-20 12:15:17 +00:00
|
|
|
|
expl = suff_double;
|
|
|
|
|
suffix++;
|
|
|
|
|
if (*suffix == 'f' || *suffix == 'F'
|
|
|
|
|
|| *suffix == 'd' || *suffix == 'D'
|
|
|
|
|
|| *suffix == 'l' || *suffix == 'L') {
|
|
|
|
|
warning (0, "decimal fp treated as binary fp");
|
|
|
|
|
expl = suff_double;
|
|
|
|
|
suffix++;
|
|
|
|
|
}
|
|
|
|
|
} else if (*suffix == 'l' || *suffix == 'L') {
|
|
|
|
|
expl = suff_long_double;
|
|
|
|
|
suffix++;
|
2022-11-12 11:04:19 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (*suffix == 'f' || *suffix == 'F') {
|
|
|
|
|
expl = suff_float;
|
|
|
|
|
suffix++;
|
|
|
|
|
} else if (*suffix == 'd' || *suffix == 'D') {
|
|
|
|
|
expl = suff_double;
|
|
|
|
|
suffix++;
|
|
|
|
|
} else {
|
|
|
|
|
if (*suffix == 'u' || *suffix == 'U') {
|
|
|
|
|
unsign = true;
|
|
|
|
|
expl = suff_unsigned;
|
|
|
|
|
suffix++;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
if (*suffix == 'l' || *suffix == 'L') {
|
|
|
|
|
expl = unsign ? suff_unsigned_long : suff_long;
|
|
|
|
|
suffix++;
|
|
|
|
|
if (*suffix == 'l' || *suffix == 'L') {
|
|
|
|
|
suffix++;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
if (!unsign && (*suffix == 'u' || *suffix == 'U')) {
|
|
|
|
|
expl = suff_unsigned_long;
|
|
|
|
|
suffix++;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*suffix) {
|
|
|
|
|
return suff_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return expl;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-11 13:32:29 +00:00
|
|
|
|
static const expr_t *
|
|
|
|
|
parse_number (const rua_tok_t *tok, yyscan_t scanner)
|
2023-10-20 12:15:17 +00:00
|
|
|
|
{
|
|
|
|
|
bool binary = false;
|
|
|
|
|
const char *type = "integer";
|
|
|
|
|
bool hex = false;
|
|
|
|
|
bool fp = false;
|
|
|
|
|
char buf[tok->textlen + 1], *dst = buf;
|
|
|
|
|
const char *src = tok->text;
|
|
|
|
|
if ((*dst = *src++) == '0') {
|
|
|
|
|
switch ((*++dst = *src++)) {
|
|
|
|
|
case 'b': case 'B':
|
|
|
|
|
binary = true;
|
|
|
|
|
type = "binary";
|
|
|
|
|
break;
|
|
|
|
|
case 'x': case 'X':
|
|
|
|
|
hex = true;
|
|
|
|
|
type = "hexadecimal";
|
|
|
|
|
break;
|
|
|
|
|
case '.':
|
|
|
|
|
fp = true;
|
|
|
|
|
break;
|
|
|
|
|
case '1' ... '9':
|
|
|
|
|
type = "octal"; // unless fp becomes true
|
|
|
|
|
break;
|
|
|
|
|
case '\'': case '_':
|
|
|
|
|
if (*src == 'b' || *src == 'B' || *src == 'x' || *src == 'X') {
|
|
|
|
|
error (0, "digit separator outside digit sequence");
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return 0;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (*dst) {
|
2024-04-18 14:52:52 +00:00
|
|
|
|
if (*dst == '.') {
|
|
|
|
|
dst++;
|
|
|
|
|
fp = true;
|
|
|
|
|
} else {
|
|
|
|
|
dst += (*dst != '\'' && *dst != '_');
|
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
while ((*dst = *src++)) {
|
|
|
|
|
if (hex && (*dst == 'p' || *dst == 'P')) {
|
|
|
|
|
fp = true;
|
|
|
|
|
}
|
|
|
|
|
if (!hex && (*dst == 'e' || *dst == 'E')) {
|
|
|
|
|
fp = true;
|
|
|
|
|
}
|
|
|
|
|
if (*dst == '.') {
|
|
|
|
|
fp = true;
|
|
|
|
|
}
|
|
|
|
|
// strip out digit separators (' is standard C, _ is a rust
|
|
|
|
|
// thing, but it does look a bit nicerer than ', so why not).
|
|
|
|
|
dst += (*dst != '\'' && *dst != '_');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// use long long to avoid bit-size issues on windows
|
|
|
|
|
long long lvalue = 0;
|
|
|
|
|
double fvalue = 0;
|
|
|
|
|
char *endptr = 0;
|
|
|
|
|
if (binary) {
|
|
|
|
|
// to get here, 0b (or 0B) was seen, so buf is guaranted to start with
|
|
|
|
|
// that
|
|
|
|
|
lvalue = strtoll (buf + 2, &endptr, 2);
|
|
|
|
|
} else {
|
|
|
|
|
if (fp) {
|
|
|
|
|
fvalue = strtod (buf, &endptr);
|
|
|
|
|
} else {
|
|
|
|
|
lvalue = strtoll (buf, &endptr, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int expl = parse_suffix (endptr, fp);
|
|
|
|
|
if (expl < 0) {
|
|
|
|
|
error (0, "invalid suffix \"%s\" on %s constant", endptr,
|
|
|
|
|
fp ? "floating" : type);
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return 0;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fp) {
|
|
|
|
|
if (expl == suff_float) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_float_expr (fvalue);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (expl == suff_long_double) {
|
|
|
|
|
warning (0, "long double treated as double");
|
|
|
|
|
expl = suff_double;
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_double_expr (fvalue, expl == suff_implicit);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (expl == suff_unsigned) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_uint_expr (lvalue);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else if (expl == suff_long || expl == suff_implicit) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_long_expr (lvalue, expl == suff_implicit);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else if (expl == suff_unsigned_long) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_ulong_expr (lvalue);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else if (expl == suff_float) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_float_expr (lvalue);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else if (expl == suff_double) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_double_expr (lvalue, false);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else {
|
|
|
|
|
internal_error (0, "invalid suffix enum: %d", expl);
|
|
|
|
|
}
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-20 12:15:17 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
yyscan_t scanner;
|
|
|
|
|
yybuffer buffer;
|
|
|
|
|
} buffer_raii_t;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
qc_restore_buffer (buffer_raii_t *raii)
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
{
|
2023-10-20 12:15:17 +00:00
|
|
|
|
yy_switch_to_buffer (raii->buffer, raii->scanner);
|
|
|
|
|
}
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
|
2023-10-20 12:15:17 +00:00
|
|
|
|
static void
|
|
|
|
|
qc_delete_buffer (buffer_raii_t *raii)
|
|
|
|
|
{
|
|
|
|
|
yy_delete_buffer (raii->buffer, raii->scanner);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-11 13:32:29 +00:00
|
|
|
|
static const expr_t *
|
|
|
|
|
parse_vector (const rua_tok_t *tok, yyscan_t scanner)
|
2023-10-20 12:15:17 +00:00
|
|
|
|
{
|
|
|
|
|
const char *end = tok->text + tok->textlen;
|
|
|
|
|
while (end > tok->text && *--end != '\'') continue;
|
|
|
|
|
|
|
|
|
|
const char *start = tok->text + 1;
|
|
|
|
|
auto yyg = (struct yyguts_t *)scanner;
|
|
|
|
|
auto __attribute__((cleanup (qc_restore_buffer)))
|
|
|
|
|
saved_buffer = (buffer_raii_t) {
|
|
|
|
|
.scanner = scanner,
|
|
|
|
|
.buffer = YY_CURRENT_BUFFER,
|
|
|
|
|
};
|
|
|
|
|
auto __attribute__((cleanup (qc_delete_buffer)))
|
|
|
|
|
buffer = (buffer_raii_t) {
|
|
|
|
|
.scanner = scanner,
|
|
|
|
|
.buffer = yy_scan_bytes (start, end - start, scanner),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int token;
|
|
|
|
|
rua_tok_t vtok = { .location = tok->location, };
|
2023-11-06 04:41:17 +00:00
|
|
|
|
vtok.location.column++;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
const expr_t *components[4+1] = {}; // currently, max of 4
|
|
|
|
|
bool negate[4] = {};
|
|
|
|
|
int width = 0;
|
|
|
|
|
|
2023-10-21 01:12:41 +00:00
|
|
|
|
yy_push_state (VECTOR, scanner);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
do {
|
|
|
|
|
token = yylex (&vtok, &vtok.location, scanner);
|
|
|
|
|
if (-token == rua_number) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
auto expr = parse_number (&vtok, scanner);
|
|
|
|
|
if (expr) {
|
|
|
|
|
if (width < 4) {
|
|
|
|
|
components[width] = expr;
|
|
|
|
|
}
|
|
|
|
|
width++;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
} else if (token == '-') {
|
|
|
|
|
if (width < 4) {
|
|
|
|
|
negate[width] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (token && token != -rua_eof);
|
2023-10-21 01:12:41 +00:00
|
|
|
|
yy_pop_state (scanner);
|
2023-10-20 12:15:17 +00:00
|
|
|
|
|
|
|
|
|
if (width > 4) {
|
|
|
|
|
error (0, "too many components in vector literal");
|
|
|
|
|
width = 4;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return 0;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
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 '.");
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return 0;
|
2022-11-12 11:04:19 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
fp |= is_double (get_type (components[i]));
|
2022-11-12 11:04:19 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
|
|
|
|
|
// end points at the final ' and thus any suffix is after that
|
|
|
|
|
int expl = parse_suffix (++end, fp);
|
|
|
|
|
if (expl < 0) {
|
|
|
|
|
error (0, "invalid suffix \"%s\" on %s vector constant", end,
|
|
|
|
|
fp ? "floating" : "integer");
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return 0;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
union {
|
|
|
|
|
pr_float_t f[4];
|
|
|
|
|
pr_int_t i[4];
|
|
|
|
|
pr_double_t d[4];
|
|
|
|
|
pr_long_t l[4];
|
|
|
|
|
pr_type_t t[PR_SIZEOF (lvec4)];
|
|
|
|
|
} data;
|
2024-04-18 00:46:10 +00:00
|
|
|
|
const type_t *type = nullptr;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
if (expl == suff_long_double) {
|
|
|
|
|
warning (0, "long double treated as double");
|
|
|
|
|
expl = suff_double;
|
|
|
|
|
}
|
|
|
|
|
if (expl == suff_float) {
|
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
|
auto c = components[i];
|
|
|
|
|
if (is_double (get_type (c))) {
|
|
|
|
|
data.f[i] = expr_double (c);
|
|
|
|
|
} else {
|
|
|
|
|
data.f[i] = expr_long (c);
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
if (negate[i]) {
|
|
|
|
|
data.f[i] = -data.f[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
type = &type_float;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else if (expl == suff_double) {
|
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
|
auto c = components[i];
|
|
|
|
|
if (is_double (get_type (c))) {
|
|
|
|
|
data.d[i] = expr_double (c);
|
|
|
|
|
} else {
|
|
|
|
|
data.d[i] = expr_long (c);
|
|
|
|
|
}
|
|
|
|
|
if (negate[i]) {
|
|
|
|
|
data.d[i] = -data.d[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
type = &type_double;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
} else if (expl == suff_implicit) {
|
|
|
|
|
if (fp) {
|
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
|
auto c = components[i];
|
|
|
|
|
if (is_double (get_type (c))) {
|
|
|
|
|
data.f[i] = expr_double (c);
|
|
|
|
|
} else {
|
|
|
|
|
data.f[i] = expr_long (c);
|
|
|
|
|
}
|
|
|
|
|
if (negate[i]) {
|
|
|
|
|
data.f[i] = -data.f[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
type = &type_float;
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
|
auto c = components[i];
|
|
|
|
|
data.i[i] = expr_long (c);
|
|
|
|
|
if (negate[i]) {
|
|
|
|
|
data.i[i] = -data.i[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
type = &type_int;
|
|
|
|
|
}
|
|
|
|
|
} else if (expl == suff_unsigned) {
|
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
|
auto c = components[i];
|
|
|
|
|
data.i[i] = fp ? expr_double (c) : expr_long (c);
|
|
|
|
|
if (negate[i]) {
|
|
|
|
|
data.i[i] = -data.i[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
type = &type_uint;
|
|
|
|
|
} else if (expl == suff_long || expl == suff_unsigned_long) {
|
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
|
auto c = components[i];
|
|
|
|
|
data.l[i] = expr_long (c);
|
|
|
|
|
if (negate[i]) {
|
|
|
|
|
data.l[i] = -data.l[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
type = expl == suff_unsigned_long ? &type_ulong : &type_long;
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
|
|
|
|
type = vector_type (type, width);
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return new_value_expr (new_type_value (type, data.t),
|
|
|
|
|
expl == suff_implicit);
|
[qfcc] Extend vector literal processing
With this, all vector widths and types are supported: 2, 3, 4 and int,
uint, long, ulong, float and double, along with support for suffixes to
make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u
is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for
literals with float-type components, and int (ivec2...) for those with
integer-type components.
2022-04-29 02:49:45 +00:00
|
|
|
|
}
|
2023-10-10 17:34:39 +00:00
|
|
|
|
|
2023-10-20 16:13:32 +00:00
|
|
|
|
static int
|
2024-04-19 03:44:57 +00:00
|
|
|
|
parse_string (rua_val_t *lval, const rua_tok_t *tok, int type,
|
2023-11-11 13:32:29 +00:00
|
|
|
|
yyscan_t scanner)
|
2023-10-20 16:13:32 +00:00
|
|
|
|
{
|
|
|
|
|
const char *str = make_string (tok->text, 0);
|
|
|
|
|
if (type == rua_char) {
|
|
|
|
|
if (str[1]) {
|
|
|
|
|
warning (0, "multibyte char constant");
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
lval->expr = new_int_expr (*str, false);
|
2023-10-24 10:50:31 +00:00
|
|
|
|
return QC_VALUE;
|
2023-10-20 16:13:32 +00:00
|
|
|
|
} else {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
lval->expr = new_string_expr (str);
|
2023-10-24 10:50:31 +00:00
|
|
|
|
return QC_STRING;
|
2023-10-20 16:13:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-20 11:31:15 +00:00
|
|
|
|
static void
|
2023-10-24 13:06:01 +00:00
|
|
|
|
next_line (rua_loc_t *loc, yyscan_t scanner)
|
2023-10-20 11:31:15 +00:00
|
|
|
|
{
|
2023-10-24 13:06:01 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-11-06 04:41:17 +00:00
|
|
|
|
loc->line = loc->last_line;
|
|
|
|
|
loc->column = loc->last_column;
|
2023-10-21 02:35:58 +00:00
|
|
|
|
loc->last_column = 1;
|
|
|
|
|
loc->last_line++;
|
2023-10-30 23:42:28 +00:00
|
|
|
|
if (!extra->recording && options.preprocess_output) {
|
2023-10-26 11:31:54 +00:00
|
|
|
|
puts ("");
|
|
|
|
|
}
|
2023-10-21 02:35:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-10-26 11:31:54 +00:00
|
|
|
|
update_loc (rua_loc_t *loc, size_t textlen)
|
|
|
|
|
{
|
2023-11-06 04:41:17 +00:00
|
|
|
|
loc->line = loc->last_line;
|
|
|
|
|
loc->column = loc->last_column;
|
2023-10-26 11:31:54 +00:00
|
|
|
|
// \n handling rules will take care of the column and line
|
|
|
|
|
loc->last_column += textlen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-11-11 13:32:29 +00:00
|
|
|
|
save_text (rua_tok_t *tok, const char *text, size_t textlen, int state,
|
|
|
|
|
rua_extra_t *extra)
|
2023-10-21 02:35:58 +00:00
|
|
|
|
{
|
2023-10-26 11:31:54 +00:00
|
|
|
|
/*if (state == TEXT) {
|
2023-10-24 13:18:23 +00:00
|
|
|
|
while (isspace (*text)) {
|
|
|
|
|
text++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-23 13:00:14 +00:00
|
|
|
|
if (state == COMMENT || state == LCOMMENT || isspace (*text)) {
|
|
|
|
|
tok->str_text[0] = ' ';
|
|
|
|
|
tok->str_text[1] = 0;
|
|
|
|
|
tok->text = tok->str_text;
|
|
|
|
|
textlen = 1;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
} else */if (extra && textlen < sizeof (extra->str_text)) {
|
|
|
|
|
strncpy (extra->str_text, text, textlen);
|
|
|
|
|
extra->str_text[textlen] = 0;
|
|
|
|
|
tok->text = extra->str_text;
|
2023-10-23 13:00:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
tok->text = save_string (text);
|
2023-10-20 11:31:15 +00:00
|
|
|
|
}
|
2023-10-23 13:00:14 +00:00
|
|
|
|
tok->textlen = textlen;
|
2023-10-20 11:31:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 04:54:08 +00:00
|
|
|
|
static bool
|
2023-11-11 13:32:29 +00:00
|
|
|
|
join_tokens (rua_tok_t *out, const rua_tok_t *p1, const rua_tok_t *p2,
|
2023-11-03 04:54:08 +00:00
|
|
|
|
rua_extra_t *extra)
|
2023-10-24 06:58:37 +00:00
|
|
|
|
{
|
2023-11-19 05:08:09 +00:00
|
|
|
|
if (!p1 || p1->token == -rua_space || p1->token == -rua_ignore) {
|
|
|
|
|
if (!p2 || p2->token == -rua_space || p2->token == -rua_ignore) {
|
|
|
|
|
*out = (rua_tok_t) {
|
|
|
|
|
.token = -rua_ignore,
|
|
|
|
|
.text = "",
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
*out = *p2;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (!p2 || p2->token == -rua_space || p1->token == -rua_ignore) {
|
|
|
|
|
// p1 cannot be null, space or ignore here
|
|
|
|
|
*out = *p1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
auto str = va (0, "%s%s", p1->text, p2->text);
|
2023-11-03 04:54:08 +00:00
|
|
|
|
yy_scan_string (str, extra->subscanner);
|
2023-11-07 03:26:37 +00:00
|
|
|
|
rua_tok_t tok = { .text = str, };
|
2023-11-03 04:54:08 +00:00
|
|
|
|
int token = yylex (&tok, &tok.location, extra->subscanner);
|
|
|
|
|
if (token && yylex (&tok, &tok.location, extra->subscanner)) {
|
|
|
|
|
error (0, "pasting \"%s\" and \"%s\" does not give a valid"
|
|
|
|
|
" preprocessing token", p1->text, p2->text);
|
2023-11-06 02:28:17 +00:00
|
|
|
|
out->token = -rua_space;
|
|
|
|
|
out->text = " ";
|
2023-11-03 04:54:08 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
tok.token = token;
|
|
|
|
|
*out = tok;
|
2023-11-03 04:54:08 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2023-10-24 06:58:37 +00:00
|
|
|
|
|
2023-11-03 04:54:08 +00:00
|
|
|
|
static bool
|
2023-11-11 13:32:29 +00:00
|
|
|
|
stringize_arg (rua_tok_t *out, rua_macro_t *arg, rua_extra_t *extra)
|
2023-11-03 04:54:08 +00:00
|
|
|
|
{
|
|
|
|
|
dstring_copystr (extra->dstr, "\"");
|
|
|
|
|
for (auto e = arg->tokens; e; e = e->next) {
|
|
|
|
|
auto str = quote_string (e->text);
|
|
|
|
|
dstring_appendstr (extra->dstr, str);
|
|
|
|
|
}
|
|
|
|
|
dstring_appendstr (extra->dstr, "\"");
|
2023-11-11 13:32:29 +00:00
|
|
|
|
*out = (rua_tok_t) {
|
2023-11-03 04:54:08 +00:00
|
|
|
|
.textlen = extra->dstr->size - 1,
|
|
|
|
|
.token = -rua_string,
|
|
|
|
|
.text = save_string (extra->dstr->str),
|
|
|
|
|
};
|
|
|
|
|
return true;
|
2023-10-24 06:58:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-20 12:15:17 +00:00
|
|
|
|
static int
|
2023-11-11 13:32:29 +00:00
|
|
|
|
preproc_token (rua_extra_t *extra, PRE_YYSTYPE *lval, const rua_tok_t *tok,
|
2023-11-22 02:43:39 +00:00
|
|
|
|
yyscan_t scanner)
|
2023-10-24 04:23:06 +00:00
|
|
|
|
{
|
2023-11-11 13:32:29 +00:00
|
|
|
|
int token = tok->token;
|
2023-10-24 13:06:01 +00:00
|
|
|
|
if (!token) {
|
|
|
|
|
return token;
|
|
|
|
|
}
|
2023-10-24 04:23:06 +00:00
|
|
|
|
if (token < 0) {
|
|
|
|
|
rua_term term = -token;
|
|
|
|
|
switch (term) {
|
|
|
|
|
case rua_ignore:
|
|
|
|
|
case rua_num_term:
|
2023-11-11 13:32:29 +00:00
|
|
|
|
case rua_grab:
|
2023-11-18 04:39:29 +00:00
|
|
|
|
case rua_va_opt:
|
2023-10-24 04:23:06 +00:00
|
|
|
|
internal_error (0, "unexpected rua token: %d", term);
|
|
|
|
|
case rua_eof:
|
|
|
|
|
case rua_error:
|
2023-10-24 13:06:01 +00:00
|
|
|
|
case rua_id:
|
2023-10-30 04:25:48 +00:00
|
|
|
|
case rua_ellipsis:
|
2023-10-31 01:37:02 +00:00
|
|
|
|
case rua_asx:
|
|
|
|
|
case rua_incop:
|
2023-10-24 04:23:06 +00:00
|
|
|
|
break;
|
|
|
|
|
case rua_number:
|
2023-10-24 12:51:57 +00:00
|
|
|
|
if (!extra->recording) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
token = -rua_error;
|
|
|
|
|
if ((lval->expr = parse_number (tok, scanner))) {
|
|
|
|
|
token = PRE_VALUE;
|
|
|
|
|
}
|
2023-10-24 12:51:57 +00:00
|
|
|
|
}
|
2023-10-24 04:23:06 +00:00
|
|
|
|
break;
|
|
|
|
|
case rua_vector:
|
2023-10-31 01:37:02 +00:00
|
|
|
|
if (!extra->recording) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
token = -rua_error;
|
|
|
|
|
if (!(lval->expr = parse_vector (tok, scanner))) {
|
|
|
|
|
token = PRE_VALUE;
|
|
|
|
|
}
|
2023-10-31 01:37:02 +00:00
|
|
|
|
}
|
2023-10-24 04:23:06 +00:00
|
|
|
|
break;
|
|
|
|
|
case rua_string:
|
|
|
|
|
case rua_char:
|
|
|
|
|
break;
|
|
|
|
|
case rua_space:
|
2023-10-24 05:01:21 +00:00
|
|
|
|
if (!extra->recording || extra->params) {
|
2023-10-24 04:23:06 +00:00
|
|
|
|
token = -rua_ignore;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-24 05:01:21 +00:00
|
|
|
|
if (-token != rua_ignore && extra->recording) {
|
2023-10-24 16:09:36 +00:00
|
|
|
|
if (token == PRE_ID) {
|
|
|
|
|
token = -rua_id;
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
lval->t.token = token;
|
2023-10-24 13:06:01 +00:00
|
|
|
|
if (token != PRE_EOD && token != ',' && token != '(' && token != ')') {
|
2023-10-24 04:23:06 +00:00
|
|
|
|
token = PRE_TOKEN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return token;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 09:52:02 +00:00
|
|
|
|
static const expr_t *
|
|
|
|
|
convert_long (const expr_t *value)
|
|
|
|
|
{
|
|
|
|
|
pr_long_t v = expr_long (value);
|
|
|
|
|
if (is_int (type_default)) {
|
|
|
|
|
if (v < INT32_MIN || v > UINT32_MAX) {
|
|
|
|
|
warning (0, "integer value truncated");
|
|
|
|
|
}
|
|
|
|
|
return new_int_expr (v, true);
|
|
|
|
|
} else {
|
|
|
|
|
float f = v;
|
|
|
|
|
if (f != v) {
|
|
|
|
|
warning (0, "cannot represent value");
|
|
|
|
|
}
|
|
|
|
|
return new_float_expr (f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 04:23:06 +00:00
|
|
|
|
static int
|
2024-04-19 03:44:57 +00:00
|
|
|
|
qc_token (rua_extra_t *extra, rua_val_t *lval, const rua_tok_t *tok,
|
2023-11-22 02:43:39 +00:00
|
|
|
|
yyscan_t scanner)
|
2023-10-20 12:15:17 +00:00
|
|
|
|
{
|
2023-11-11 13:32:29 +00:00
|
|
|
|
int token = tok->token;
|
2023-10-20 12:15:17 +00:00
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
if (token < 0) {
|
|
|
|
|
rua_term term = -token;
|
|
|
|
|
switch (term) {
|
2023-10-24 04:23:06 +00:00
|
|
|
|
case rua_ignore:
|
|
|
|
|
case rua_num_term:
|
2023-11-18 04:39:29 +00:00
|
|
|
|
case rua_va_opt:
|
2023-10-24 04:23:06 +00:00
|
|
|
|
internal_error (0, "unexpected rua token: %d", term);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
case rua_eof:
|
|
|
|
|
case rua_error:
|
2023-10-24 04:23:06 +00:00
|
|
|
|
break;
|
|
|
|
|
case rua_id:
|
2024-04-18 15:49:47 +00:00
|
|
|
|
token = extra->parser->keyword_or_id (lval, tok->text);
|
2023-11-11 13:32:29 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-22 11:56:12 +00:00
|
|
|
|
break;
|
|
|
|
|
case rua_number:
|
2023-11-11 13:32:29 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-22 11:56:12 +00:00
|
|
|
|
break;
|
|
|
|
|
case rua_vector:
|
2023-11-11 13:32:29 +00:00
|
|
|
|
token = -rua_error;
|
|
|
|
|
if ((lval->expr = parse_vector (tok, scanner))) {
|
|
|
|
|
token = QC_VALUE;
|
|
|
|
|
}
|
2023-10-22 11:56:12 +00:00
|
|
|
|
break;
|
|
|
|
|
case rua_string:
|
|
|
|
|
case rua_char:
|
2023-11-11 13:32:29 +00:00
|
|
|
|
token = parse_string (lval, tok, -token, scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
break;
|
2023-10-23 13:00:14 +00:00
|
|
|
|
case rua_space:
|
2023-10-30 23:42:28 +00:00
|
|
|
|
if (options.preprocess_output) {
|
2023-10-23 13:00:14 +00:00
|
|
|
|
printf (" ");
|
|
|
|
|
}
|
|
|
|
|
break;
|
2023-10-30 04:25:48 +00:00
|
|
|
|
case rua_ellipsis:
|
|
|
|
|
token = QC_ELLIPSIS;
|
|
|
|
|
break;
|
2023-10-31 01:37:02 +00:00
|
|
|
|
case rua_asx:
|
|
|
|
|
token = QC_ASX;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
lval->op = tok->text[0];
|
2023-10-31 01:37:02 +00:00
|
|
|
|
switch (tok->text[1]) {
|
|
|
|
|
case '=': break;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
case '%': lval->op = QC_MOD; break;
|
|
|
|
|
case '<': lval->op = QC_SHL; break;
|
|
|
|
|
case '>': lval->op = QC_SHR; break;
|
2023-10-31 01:37:02 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case rua_incop:
|
|
|
|
|
token = QC_INCOP;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
lval->op = tok->text[0];
|
2023-10-31 01:37:02 +00:00
|
|
|
|
break;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
2023-10-24 04:23:06 +00:00
|
|
|
|
return token;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 13:06:01 +00:00
|
|
|
|
static void
|
2023-11-04 12:08:40 +00:00
|
|
|
|
rua_reset_args (rua_macro_t *macro)
|
2023-10-24 13:06:01 +00:00
|
|
|
|
{
|
2023-11-03 04:54:08 +00:00
|
|
|
|
macro->num_args = 0;
|
|
|
|
|
|
|
|
|
|
int num_params = macro->num_params;
|
|
|
|
|
if (num_params < 0) {
|
|
|
|
|
num_params = -num_params;
|
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
if (num_params && !macro->args) {
|
2023-11-03 04:54:08 +00:00
|
|
|
|
macro->args = calloc (num_params, sizeof (rua_macro_t *));
|
|
|
|
|
for (int i = 0; i < num_params; i++) {
|
|
|
|
|
macro->args[i] = malloc (sizeof (rua_macro_t));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < num_params; i++) {
|
|
|
|
|
auto arg = macro->args[i];
|
|
|
|
|
*arg = (rua_macro_t) {
|
|
|
|
|
.tail = &arg->tokens,
|
|
|
|
|
};
|
|
|
|
|
}
|
2023-11-04 12:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-11-22 02:43:39 +00:00
|
|
|
|
rua_start_args (yyscan_t scanner)
|
2023-11-04 12:08:40 +00:00
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
extra->recording = true;
|
|
|
|
|
|
|
|
|
|
rua_reset_args (extra->pending_macro);
|
2023-10-24 13:06:01 +00:00
|
|
|
|
yy_push_state (ARGS, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-11-22 02:43:39 +00:00
|
|
|
|
rua_end_args (yyscan_t scanner)
|
2023-10-24 13:06:01 +00:00
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
extra->recording = false;
|
|
|
|
|
yy_pop_state (scanner);
|
2023-11-18 17:10:44 +00:00
|
|
|
|
|
|
|
|
|
auto macro = extra->pending_macro;
|
|
|
|
|
if (macro->num_params < 0) {
|
|
|
|
|
auto arg = macro->args[~macro->num_params];
|
|
|
|
|
auto t = arg->tokens;
|
|
|
|
|
while (t && (t->token == -rua_space || t->token == -rua_ignore)) {
|
|
|
|
|
t = t->next;
|
|
|
|
|
}
|
|
|
|
|
if (!t) {
|
|
|
|
|
arg->tokens = 0;
|
|
|
|
|
arg->tail = &arg->tokens;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-24 13:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-04 12:08:40 +00:00
|
|
|
|
static void __attribute__((used))
|
|
|
|
|
dump_macro (rua_macro_t *macro)
|
|
|
|
|
{
|
|
|
|
|
printf ("\n%s: ", macro->name);
|
|
|
|
|
for (auto t = macro->tokens; t; t = t->next) {
|
|
|
|
|
printf ("%s", t->text);
|
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
if (macro->args) {
|
|
|
|
|
for (int i = 0; i < macro->num_args; i++) {
|
|
|
|
|
dump_macro (macro->args[i]);
|
|
|
|
|
}
|
2023-11-04 12:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 04:23:06 +00:00
|
|
|
|
static int
|
|
|
|
|
qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
|
|
|
|
{
|
|
|
|
|
auto loc = &tok->location;
|
|
|
|
|
|
2023-10-24 06:58:37 +00:00
|
|
|
|
if (-token == rua_ignore) {
|
|
|
|
|
return YYPUSH_MORE;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 04:41:17 +00:00
|
|
|
|
pr.loc = *loc;
|
|
|
|
|
|
2023-10-24 04:23:06 +00:00
|
|
|
|
if (extra->preprocessor) {
|
|
|
|
|
auto state = extra->pre_state;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
PRE_YYSTYPE lval = { .t = *tok };
|
|
|
|
|
|
|
|
|
|
token = preproc_token (extra, &lval, tok, scanner);
|
2023-10-24 04:23:06 +00:00
|
|
|
|
if (-token == rua_ignore) {
|
|
|
|
|
return YYPUSH_MORE;
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return pre_yypush_parse (state, token, &lval, loc, scanner);
|
2023-10-24 04:23:06 +00:00
|
|
|
|
} else {
|
2023-10-28 14:51:12 +00:00
|
|
|
|
if (!extra->suppressed) {
|
2023-10-30 23:42:28 +00:00
|
|
|
|
if (options.preprocess_only) {
|
|
|
|
|
if (options.preprocess_output) {
|
2023-11-18 17:10:44 +00:00
|
|
|
|
if (token != -rua_space || !extra->did_space) {
|
|
|
|
|
printf ("%s", tok->text);
|
|
|
|
|
}
|
|
|
|
|
extra->did_space = token == -rua_space;
|
2023-10-30 23:42:28 +00:00
|
|
|
|
}
|
2023-10-28 14:51:12 +00:00
|
|
|
|
return token ? YYPUSH_MORE : 0;
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
QC_YYSTYPE lval = {};
|
|
|
|
|
token = qc_token (extra, &lval, tok, scanner);
|
2023-10-28 14:51:12 +00:00
|
|
|
|
if (token >= 0) {
|
2024-04-18 15:49:47 +00:00
|
|
|
|
auto p = extra->parser;
|
|
|
|
|
return p->parse (p->state, token, &lval, loc, scanner);
|
2023-10-28 14:51:12 +00:00
|
|
|
|
}
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
2023-10-20 12:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
return YYPUSH_MORE;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-11 13:32:29 +00:00
|
|
|
|
static rua_tok_t
|
2023-11-15 16:16:39 +00:00
|
|
|
|
next_macro_token (rua_macro_t *macro)
|
2023-11-03 04:54:08 +00:00
|
|
|
|
{
|
2023-11-15 16:16:39 +00:00
|
|
|
|
auto e = *macro->cursor;
|
|
|
|
|
macro->cursor = e.next;
|
2023-11-03 04:54:08 +00:00
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-19 05:08:09 +00:00
|
|
|
|
static const rua_tok_t *
|
|
|
|
|
get_arg_token (bool last, const rua_tok_t *arg, const rua_macro_t *macro,
|
2023-11-22 02:43:39 +00:00
|
|
|
|
yyscan_t scanner)
|
2023-11-06 02:28:17 +00:00
|
|
|
|
{
|
|
|
|
|
symbol_t *sym;
|
|
|
|
|
|
2023-11-19 05:08:09 +00:00
|
|
|
|
if (arg->token == -rua_va_opt) {
|
|
|
|
|
sym = symtab_lookup (macro->params, arg->text);
|
2024-08-16 07:48:11 +00:00
|
|
|
|
auto m = sym->macro;
|
2023-11-19 05:08:09 +00:00
|
|
|
|
m->update (m, scanner);
|
|
|
|
|
if (last) {
|
|
|
|
|
if (m->tokens) {
|
|
|
|
|
return (rua_tok_t *) m->tail;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
return m->tokens;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-06 02:28:17 +00:00
|
|
|
|
if (arg->token == -rua_id && macro->params
|
|
|
|
|
&& (sym = symtab_lookup (macro->params, arg->text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !macro->args[sym->offset]->next) {
|
|
|
|
|
auto a = macro->args[sym->offset];
|
2023-11-06 02:28:17 +00:00
|
|
|
|
if (last) {
|
|
|
|
|
if (a->tokens) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
return (rua_tok_t *) a->tail;
|
2023-11-06 02:28:17 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
return a->tokens;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return arg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-11-11 13:32:29 +00:00
|
|
|
|
copy_token (rua_macro_t *dst, const rua_tok_t *t)
|
2023-11-06 02:28:17 +00:00
|
|
|
|
{
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_tok_t *e = malloc (sizeof (*e));
|
2023-11-06 02:28:17 +00:00
|
|
|
|
*e = *t;
|
|
|
|
|
e->next = 0;
|
|
|
|
|
*dst->tail = e;
|
|
|
|
|
dst->tail = &e->next;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-19 05:08:09 +00:00
|
|
|
|
static void
|
|
|
|
|
do_arg_copy (rua_macro_t *dst, const rua_macro_t *a,
|
|
|
|
|
bool skip_first, bool skip_last)
|
|
|
|
|
{
|
|
|
|
|
if (!a->tokens) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (auto t = skip_first ? a->tokens->next : a->tokens;
|
|
|
|
|
t; t = t->next) {
|
|
|
|
|
if (skip_last && !t->next) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
copy_token (dst, t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 02:28:17 +00:00
|
|
|
|
static void
|
|
|
|
|
copy_arg_token (rua_macro_t *dst, bool skip_first, bool skip_last,
|
2023-11-11 13:32:29 +00:00
|
|
|
|
const rua_tok_t *arg, const rua_macro_t *macro)
|
2023-11-06 02:28:17 +00:00
|
|
|
|
{
|
|
|
|
|
symbol_t *sym;
|
|
|
|
|
|
2023-11-19 05:08:09 +00:00
|
|
|
|
if (arg->token == -rua_va_opt) {
|
|
|
|
|
sym = symtab_lookup (macro->params, arg->text);
|
|
|
|
|
// __VA_OPT__'s macro was updated by get_arg_token
|
2024-08-16 07:48:11 +00:00
|
|
|
|
do_arg_copy (dst, sym->macro, skip_first, skip_last);
|
2023-11-19 05:08:09 +00:00
|
|
|
|
} else if (arg->token == -rua_id && macro->params
|
2023-11-06 02:28:17 +00:00
|
|
|
|
&& (sym = symtab_lookup (macro->params, arg->text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !macro->args[sym->offset]->next) {
|
|
|
|
|
do_arg_copy (dst, macro->args[sym->offset], skip_first, skip_last);
|
2023-11-06 02:28:17 +00:00
|
|
|
|
} else if (!skip_first && !skip_last) {
|
|
|
|
|
copy_token (dst, arg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-21 15:31:54 +00:00
|
|
|
|
static void
|
2023-11-22 02:43:39 +00:00
|
|
|
|
collect_args (rua_macro_t *m, rua_macro_t *macro, yyscan_t scanner)
|
2023-11-07 03:26:37 +00:00
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
m->next = extra->pending_macro;
|
|
|
|
|
extra->pending_macro = m;
|
|
|
|
|
auto t = macro->cursor;
|
|
|
|
|
for (; t && t->token == -rua_space; t = t->next) continue;
|
|
|
|
|
// to be in an arg, a function-like macro must either have
|
|
|
|
|
// both open and close parans, or none
|
|
|
|
|
if (t && t->token == '(') {
|
|
|
|
|
rua_reset_args (m);
|
|
|
|
|
int paren = 1;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
auto a = rua_macro_arg (t, scanner);
|
2023-11-07 03:26:37 +00:00
|
|
|
|
for (t = t->next; t; t = t->next) {
|
|
|
|
|
if (t->token == '(') {
|
|
|
|
|
paren++;
|
|
|
|
|
} else if (t->token == ')') {
|
|
|
|
|
if (!(--paren)) {
|
|
|
|
|
t = t->next;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (t->token == ',' && paren == 1) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
a = rua_macro_arg (t, scanner);
|
2023-11-07 03:26:37 +00:00
|
|
|
|
} else {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_macro_append (a, t, scanner);
|
2023-11-07 03:26:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-22 02:43:39 +00:00
|
|
|
|
macro->cursor = t;
|
2023-11-07 03:26:37 +00:00
|
|
|
|
}
|
|
|
|
|
extra->pending_macro = m->next;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 16:16:39 +00:00
|
|
|
|
static rua_macro_t *
|
|
|
|
|
alloc_macro (const char *name, bool params)
|
|
|
|
|
{
|
|
|
|
|
rua_macro_t *macro = malloc (sizeof (*macro));
|
|
|
|
|
*macro = (rua_macro_t) {
|
|
|
|
|
.name = name,
|
|
|
|
|
.params = params ? new_symtab (0, stab_param) : 0,
|
|
|
|
|
.tail = ¯o->tokens,
|
|
|
|
|
};
|
|
|
|
|
return macro;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
append_token (rua_macro_t *macro, const rua_tok_t *token)
|
|
|
|
|
{
|
2023-11-18 17:10:44 +00:00
|
|
|
|
if (token->token == -rua_space) {
|
|
|
|
|
if (!macro->tokens) {
|
|
|
|
|
// ignore leading space
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto t = (rua_tok_t *) macro->tail;
|
|
|
|
|
if (t->token == '#' || t->token == PRE_CONCAT) {
|
|
|
|
|
// ignore space after '#' and '##'
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (t->token == -rua_space) {
|
|
|
|
|
// ignore space after space
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 16:16:39 +00:00
|
|
|
|
auto t = (rua_tok_t *) macro->tail;
|
|
|
|
|
if (token->token != PRE_CONCAT
|
|
|
|
|
|| !macro->tokens
|
|
|
|
|
|| t->token != -rua_space) {
|
|
|
|
|
t = malloc (sizeof (*t));
|
|
|
|
|
macro->num_tokens++;
|
|
|
|
|
}
|
|
|
|
|
*t = *token;
|
|
|
|
|
t->next = 0;
|
|
|
|
|
*macro->tail = t;
|
|
|
|
|
macro->tail = &t->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-11-18 04:39:29 +00:00
|
|
|
|
queue_macro (rua_extra_t *extra, rua_macro_t *macro)
|
2023-11-15 16:16:39 +00:00
|
|
|
|
{
|
|
|
|
|
macro->next = extra->macro;
|
|
|
|
|
extra->macro = macro;
|
|
|
|
|
macro->cursor = macro->tokens;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
check_macro (rua_macro_t *macro)
|
|
|
|
|
{
|
|
|
|
|
int num_args = macro->num_args;
|
|
|
|
|
if (num_args == 1 && !macro->args) {
|
|
|
|
|
num_args = 0;
|
|
|
|
|
}
|
|
|
|
|
if (macro->num_params >= 0) {
|
|
|
|
|
if (num_args != macro->num_params) {
|
|
|
|
|
error (0, "macro \"%s\" passed %d arguments, but takes just %d",
|
|
|
|
|
macro->name, num_args, macro->num_params);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (num_args < ~macro->num_params) {
|
|
|
|
|
error (0, "macro \"%s\" requires %d arguments, but only %d given",
|
|
|
|
|
macro->name, ~macro->num_params, num_args);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-04 12:08:40 +00:00
|
|
|
|
static int
|
|
|
|
|
next_token (rua_tok_t *tok, yyscan_t scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
rescan:
|
|
|
|
|
while (extra->macro && !extra->macro->cursor) {
|
|
|
|
|
auto macro = extra->macro;
|
|
|
|
|
extra->macro = macro->next;
|
|
|
|
|
macro->next = 0;
|
|
|
|
|
}
|
2023-11-18 09:08:23 +00:00
|
|
|
|
rua_tok_t e = {};
|
2023-11-15 16:16:39 +00:00
|
|
|
|
if (extra->macro) {
|
|
|
|
|
e = next_macro_token (extra->macro);
|
2023-11-18 09:08:23 +00:00
|
|
|
|
} else if (!extra->no_lex) {
|
2023-11-15 16:16:39 +00:00
|
|
|
|
tok->token = yylex (tok, &extra->location, scanner);
|
|
|
|
|
tok->location = extra->location;
|
|
|
|
|
if ((extra->pending_macro || extra->recording)
|
|
|
|
|
&& tok->text == extra->str_text) {
|
|
|
|
|
tok->text = save_string (tok->text);
|
|
|
|
|
}
|
|
|
|
|
e = *tok;
|
|
|
|
|
}
|
|
|
|
|
int token = e.token;
|
2023-11-23 04:26:02 +00:00
|
|
|
|
if (extra->pending_macro && !extra->recording) {
|
|
|
|
|
if (token != -rua_space && token != '(') {
|
|
|
|
|
auto pending_macro = extra->pending_macro;
|
|
|
|
|
append_token (pending_macro, &e);
|
|
|
|
|
extra->pending_macro = pending_macro->next;
|
|
|
|
|
if (extra->macro) {
|
|
|
|
|
auto macro = extra->macro;
|
|
|
|
|
pending_macro->params = macro->params;
|
|
|
|
|
pending_macro->args = macro->args;
|
|
|
|
|
}
|
|
|
|
|
queue_macro (extra, pending_macro);
|
|
|
|
|
// get the token that looked like a macro
|
|
|
|
|
e = next_macro_token (extra->macro);
|
|
|
|
|
*tok = e;
|
|
|
|
|
return e.token;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
if (extra->macro) {
|
2023-11-04 12:08:40 +00:00
|
|
|
|
symbol_t *sym;
|
|
|
|
|
auto macro = extra->macro;
|
|
|
|
|
if (token == '#') {
|
2023-11-07 03:26:37 +00:00
|
|
|
|
auto n = e.next;
|
|
|
|
|
rua_macro_t *arg;
|
|
|
|
|
macro->cursor = macro->cursor->next; // consume arg
|
2023-11-18 04:39:29 +00:00
|
|
|
|
if (n->token == -rua_va_opt) {
|
|
|
|
|
sym = symtab_lookup (macro->params, n->text);
|
2024-08-16 07:48:11 +00:00
|
|
|
|
auto m = sym->macro;
|
2023-11-18 07:34:36 +00:00
|
|
|
|
m->update (m, scanner);
|
2023-11-18 04:39:29 +00:00
|
|
|
|
arg = m;
|
2023-11-07 03:26:37 +00:00
|
|
|
|
} else {
|
|
|
|
|
sym = symtab_lookup (macro->params, n->text);
|
2024-08-16 07:48:11 +00:00
|
|
|
|
arg = macro->args[sym->offset];
|
2023-11-07 03:26:37 +00:00
|
|
|
|
}
|
2023-11-04 12:08:40 +00:00
|
|
|
|
stringize_arg (&e, arg, extra);
|
2023-11-06 02:28:17 +00:00
|
|
|
|
} else if (e.next && e.next->token == PRE_CONCAT) {
|
|
|
|
|
rua_macro_t *m = malloc (sizeof (*m));
|
|
|
|
|
*m = (rua_macro_t) {
|
|
|
|
|
.tail = &m->tokens,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool sf = false;
|
|
|
|
|
bool sl;
|
|
|
|
|
do {
|
2023-11-19 05:08:09 +00:00
|
|
|
|
auto p = get_arg_token (true, &e, macro, scanner);
|
|
|
|
|
auto n = get_arg_token (false, e.next->next, macro, scanner);
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_tok_t cat;
|
2023-11-06 02:28:17 +00:00
|
|
|
|
if (!(sl = join_tokens (&cat, p, n, extra))) {
|
|
|
|
|
cat.location = e.next->location;
|
|
|
|
|
cat.token = -rua_space;
|
|
|
|
|
cat.text = " ";
|
|
|
|
|
}
|
|
|
|
|
copy_arg_token (m, sf, sl, &e, macro);
|
2023-11-07 03:26:37 +00:00
|
|
|
|
if (cat.token) {
|
|
|
|
|
copy_token (m, &cat);
|
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
next_macro_token (extra->macro); // consume ##
|
|
|
|
|
e = next_macro_token (extra->macro);
|
2023-11-06 02:28:17 +00:00
|
|
|
|
sf = sl;
|
|
|
|
|
} while (e.next && e.next->token == PRE_CONCAT);
|
|
|
|
|
copy_arg_token (m, sl, false, &e, macro);
|
|
|
|
|
m->cursor = m->tokens;
|
|
|
|
|
m->next = extra->macro;
|
|
|
|
|
extra->macro = m;
|
|
|
|
|
goto rescan;
|
2023-11-18 04:39:29 +00:00
|
|
|
|
} else if (token == -rua_va_opt) {
|
2023-11-18 10:56:19 +00:00
|
|
|
|
if (!macro->params || !macro->args[~macro->num_params]
|
2023-11-18 04:39:29 +00:00
|
|
|
|
|| !macro->args[~macro->num_params]->tokens) {
|
|
|
|
|
goto rescan;
|
|
|
|
|
}
|
|
|
|
|
sym = symtab_lookup (macro->params, e.text);
|
2024-08-16 07:48:11 +00:00
|
|
|
|
auto m = sym->macro;
|
2023-11-18 07:34:36 +00:00
|
|
|
|
m->update (m, scanner);
|
2023-11-18 04:39:29 +00:00
|
|
|
|
queue_macro (extra, m);
|
2023-11-04 12:08:40 +00:00
|
|
|
|
goto rescan;
|
2023-11-18 07:34:36 +00:00
|
|
|
|
} else if (token == -rua_id && macro->params
|
|
|
|
|
&& (sym = symtab_lookup (macro->params, e.text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !macro->args[sym->offset]->next) {
|
|
|
|
|
auto arg = macro->args[sym->offset];
|
2023-11-18 07:34:36 +00:00
|
|
|
|
queue_macro (extra, arg);
|
|
|
|
|
goto rescan;
|
2023-11-21 15:31:54 +00:00
|
|
|
|
} else if (token == -rua_id && !macro->name // in an arg
|
|
|
|
|
&& (sym = symtab_lookup (extra->macro_tab, e.text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !sym->macro->next
|
|
|
|
|
&& !sym->macro->params) {
|
2023-11-21 15:31:54 +00:00
|
|
|
|
// force object-type macros in macro arguments to be expanded
|
2024-08-16 07:48:11 +00:00
|
|
|
|
auto m = sym->macro;
|
2023-11-21 15:31:54 +00:00
|
|
|
|
if (m->update) {
|
|
|
|
|
m->update (m, scanner);
|
|
|
|
|
}
|
|
|
|
|
queue_macro (extra, m);
|
|
|
|
|
goto rescan;
|
2023-11-23 04:28:48 +00:00
|
|
|
|
#if 0 // causes preproc-1.r to fail (see XXX below)
|
|
|
|
|
} else if (token == -rua_id && !macro->name // in an arg
|
|
|
|
|
&& (sym = symtab_lookup (extra->macro_tab, e.text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !sym->macro->next
|
|
|
|
|
&& sym->macro->params) {
|
2023-11-23 04:28:48 +00:00
|
|
|
|
// force function-type macros in macro arguments to be expanded
|
2024-08-16 07:48:11 +00:00
|
|
|
|
auto m = sym->macro;
|
2023-11-23 04:28:48 +00:00
|
|
|
|
auto c = macro->cursor;
|
|
|
|
|
// XXX breakage for preproc-1.r: collect_args assumes the macro
|
|
|
|
|
// is complete, but in the case of preproc-1.r, it is not. In fact,
|
|
|
|
|
// with the final ) removed from the F macro, tokens are consumed
|
|
|
|
|
// to the end of the file. Thus, nt x = F(LPAREN(), 0, <:-);
|
|
|
|
|
// expands to int x = 42 ); instead of int x = 42;
|
|
|
|
|
// However, this block is needed for the H5C(H5A()) test
|
|
|
|
|
collect_args (m, macro, scanner);
|
|
|
|
|
if (macro->cursor != c) {
|
|
|
|
|
if (m->update) {
|
|
|
|
|
m->update (m, scanner);
|
|
|
|
|
}
|
|
|
|
|
queue_macro (extra, m);
|
|
|
|
|
goto rescan;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2023-11-04 12:08:40 +00:00
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
*tok = e;
|
2023-11-15 16:16:39 +00:00
|
|
|
|
}
|
2023-11-18 07:34:36 +00:00
|
|
|
|
if (extra->pending_macro) {
|
|
|
|
|
PRE_YYSTYPE lval = { .t = e };
|
|
|
|
|
auto pending_macro = extra->pending_macro;
|
|
|
|
|
if (extra->recording) {
|
|
|
|
|
token = preproc_token (extra, &lval, &e, scanner);
|
|
|
|
|
int s = pre_yypush_parse (extra->args_state, token, &lval,
|
|
|
|
|
&e.location, scanner);
|
|
|
|
|
if (s == YYPUSH_MORE) {
|
|
|
|
|
goto rescan;
|
|
|
|
|
}
|
|
|
|
|
rua_end_args (scanner);
|
|
|
|
|
extra->pending_macro = pending_macro->next;
|
|
|
|
|
if (check_macro (pending_macro)) {
|
|
|
|
|
queue_macro (extra, pending_macro);
|
|
|
|
|
}
|
|
|
|
|
goto rescan;
|
|
|
|
|
} else if (token == -rua_space) {
|
|
|
|
|
append_token (pending_macro, &e);
|
|
|
|
|
goto rescan;
|
|
|
|
|
} else if (token == '(') {
|
|
|
|
|
extra->pending_macro = (rua_macro_t *) pending_macro->args;
|
|
|
|
|
pending_macro->args = 0;
|
|
|
|
|
rua_start_args (scanner);
|
|
|
|
|
int s = pre_yypush_parse (extra->args_state, PRE_ARGS, &lval,
|
|
|
|
|
&e.location, scanner);
|
|
|
|
|
if (s != YYPUSH_MORE) {
|
|
|
|
|
internal_error (0, "can't start parsing macro args");
|
|
|
|
|
}
|
|
|
|
|
goto rescan;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
symbol_t *sym;
|
|
|
|
|
if (extra->preprocessor && extra->expand && token == PRE_ID) {
|
|
|
|
|
token = -rua_id;
|
|
|
|
|
}
|
|
|
|
|
if ((extra->expand || !(extra->preprocessor || extra->suppressed))
|
|
|
|
|
&& token == -rua_id
|
|
|
|
|
&& (sym = symtab_lookup (extra->macro_tab, e.text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !sym->macro->next) {
|
|
|
|
|
auto macro = sym->macro;
|
2023-11-18 17:10:44 +00:00
|
|
|
|
if (macro->update) {
|
|
|
|
|
macro->update (macro, scanner);
|
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
if (macro->params) {
|
|
|
|
|
// function-type macro, need to check for ( so set up a temporary
|
|
|
|
|
// macro to hold the tokens before the first non-space token
|
|
|
|
|
auto pending_macro = alloc_macro (0, false);
|
|
|
|
|
pending_macro->args = (rua_macro_t **) macro;
|
|
|
|
|
pending_macro->next = extra->pending_macro;
|
|
|
|
|
extra->pending_macro = pending_macro;
|
|
|
|
|
// record the token with the macro name
|
|
|
|
|
if (e.text == extra->str_text) {
|
|
|
|
|
e.text = save_string (e.text);
|
|
|
|
|
}
|
|
|
|
|
append_token (pending_macro, &e);
|
|
|
|
|
} else {
|
|
|
|
|
// object-type macro, just expand
|
2023-11-18 04:39:29 +00:00
|
|
|
|
queue_macro (extra, macro);
|
2023-11-11 13:32:29 +00:00
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
goto rescan;
|
2023-11-04 12:08:40 +00:00
|
|
|
|
}
|
2023-11-15 16:16:39 +00:00
|
|
|
|
return token;
|
2023-11-04 12:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-10 17:34:39 +00:00
|
|
|
|
int
|
2024-04-18 15:49:47 +00:00
|
|
|
|
rua_parse (FILE *in, rua_parser_t *parser)
|
2023-10-10 17:34:39 +00:00
|
|
|
|
{
|
2023-10-22 11:56:12 +00:00
|
|
|
|
rua_extra_t extra = {
|
2024-04-18 15:49:47 +00:00
|
|
|
|
.parser = parser,
|
2023-10-22 11:56:12 +00:00
|
|
|
|
.pre_state = pre_yypstate_new (),
|
2023-10-29 15:41:06 +00:00
|
|
|
|
.args_state = pre_yypstate_new (),
|
2023-10-22 11:56:12 +00:00
|
|
|
|
.cond_stack = DARRAY_STATIC_INIT (8),
|
2023-10-25 12:07:50 +00:00
|
|
|
|
.include_stack = DARRAY_STATIC_INIT (8),
|
2023-10-24 15:20:12 +00:00
|
|
|
|
.dstr = dstring_new (),
|
2023-10-29 09:19:03 +00:00
|
|
|
|
.macro_tab = cpp_macros ? cpp_macros : new_symtab (0, stab_global),
|
2023-11-06 04:41:17 +00:00
|
|
|
|
.location = { 1, 1, 1, 1, pr.loc.file },
|
2023-10-22 11:56:12 +00:00
|
|
|
|
};
|
2023-10-10 17:34:39 +00:00
|
|
|
|
|
2023-11-06 04:41:17 +00:00
|
|
|
|
yyscan_t scanner;
|
2023-10-20 11:31:15 +00:00
|
|
|
|
yylex_init_extra (&extra, &scanner);
|
2023-10-24 06:58:37 +00:00
|
|
|
|
yylex_init (&extra.subscanner);
|
2023-10-10 17:34:39 +00:00
|
|
|
|
yyset_in (in, scanner);
|
2023-11-03 04:54:08 +00:00
|
|
|
|
|
|
|
|
|
int status;
|
2023-11-06 04:41:17 +00:00
|
|
|
|
rua_tok_t tok = {};
|
2023-10-10 17:34:39 +00:00
|
|
|
|
do {
|
2023-11-04 12:08:40 +00:00
|
|
|
|
int token = next_token (&tok, scanner);
|
2023-10-31 01:48:11 +00:00
|
|
|
|
if (!token && extra.cond_stack.size) {
|
|
|
|
|
int ind = extra.cond_stack.size - 1;
|
|
|
|
|
auto cond = extra.cond_stack.a[ind];
|
|
|
|
|
error (0, "end of file in conditional started on %d", cond.line);
|
|
|
|
|
}
|
2023-10-25 12:07:50 +00:00
|
|
|
|
if (!token && extra.include_stack.size) {
|
2023-10-31 01:48:11 +00:00
|
|
|
|
//printf ("*** pop include %d\n", (int) extra.include_stack.size);
|
|
|
|
|
auto incl = DARRAY_REMOVE (&extra.include_stack);
|
2023-11-06 04:41:17 +00:00
|
|
|
|
extra.location = incl.location;
|
2023-11-12 04:20:35 +00:00
|
|
|
|
struct yyguts_t *yyg = (struct yyguts_t*) scanner;//FIXME
|
2023-10-25 12:07:50 +00:00
|
|
|
|
yy_delete_buffer (YY_CURRENT_BUFFER, scanner);
|
|
|
|
|
set_line_file (-1, 0, 2);
|
2023-10-31 01:48:11 +00:00
|
|
|
|
yy_switch_to_buffer (incl.buffer, scanner);
|
|
|
|
|
DARRAY_CLEAR (&extra.cond_stack);
|
|
|
|
|
extra.cond_stack = incl.cond_stack;
|
2023-10-25 12:07:50 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2023-11-03 04:54:08 +00:00
|
|
|
|
status = qc_process (&extra, token, &tok, scanner);
|
2023-10-10 17:34:39 +00:00
|
|
|
|
} while (status == YYPUSH_MORE);
|
|
|
|
|
|
2023-10-24 06:58:37 +00:00
|
|
|
|
yylex_destroy (extra.subscanner);
|
2023-10-10 17:34:39 +00:00
|
|
|
|
yylex_destroy (scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
pre_yypstate_delete (extra.pre_state);
|
2023-10-29 15:41:06 +00:00
|
|
|
|
pre_yypstate_delete (extra.args_state);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
free (extra.cond_stack.a);
|
2023-10-25 12:07:50 +00:00
|
|
|
|
free (extra.include_stack.a);
|
2023-10-24 15:20:12 +00:00
|
|
|
|
dstring_delete (extra.dstr);
|
2023-10-10 17:34:39 +00:00
|
|
|
|
return status;
|
|
|
|
|
}
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
|
|
|
|
rua_macro_t *
|
2023-10-24 05:01:21 +00:00
|
|
|
|
rua_start_macro (const char *name, bool params, void *scanner)
|
2023-10-22 11:56:12 +00:00
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-27 08:26:00 +00:00
|
|
|
|
if (extra->suppressed) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-10-28 14:51:12 +00:00
|
|
|
|
extra->recording = true;
|
2023-10-27 08:26:00 +00:00
|
|
|
|
extra->params = params;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
2023-10-24 14:32:13 +00:00
|
|
|
|
if (name) {
|
|
|
|
|
int len = strlen (name);
|
|
|
|
|
if (name[len - 1] == '(') {
|
|
|
|
|
name = save_substring (name, len - 1);
|
|
|
|
|
} else {
|
|
|
|
|
name = save_string (name);
|
|
|
|
|
}
|
2023-10-23 09:32:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
yy_push_state (MACRO, scanner);
|
2023-10-23 09:32:06 +00:00
|
|
|
|
|
2023-11-15 16:16:39 +00:00
|
|
|
|
return alloc_macro (name, params);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 05:01:21 +00:00
|
|
|
|
rua_macro_t *
|
|
|
|
|
rua_end_params (rua_macro_t *macro, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-27 08:26:00 +00:00
|
|
|
|
if (extra->suppressed) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-10-24 05:01:21 +00:00
|
|
|
|
extra->params = false;
|
2023-10-24 15:20:12 +00:00
|
|
|
|
//macro->params->parent = extra->macro_tab;
|
2023-10-24 05:01:21 +00:00
|
|
|
|
return macro;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
rua_macro_t *
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_macro_append (rua_macro_t *macro, const rua_tok_t *token, void *scanner)
|
2023-10-22 11:56:12 +00:00
|
|
|
|
{
|
2023-10-27 08:26:00 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-11-03 04:54:08 +00:00
|
|
|
|
if (extra->suppressed || !macro) {
|
2023-10-27 08:26:00 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-15 03:46:38 +00:00
|
|
|
|
append_token (macro, token);
|
2023-10-23 09:32:06 +00:00
|
|
|
|
return macro;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rua_macro_t *
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_macro_param (rua_macro_t *macro, const rua_tok_t *token, void *scanner)
|
2023-10-23 09:32:06 +00:00
|
|
|
|
{
|
2023-10-27 08:26:00 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
if (extra->suppressed) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-10-24 05:01:21 +00:00
|
|
|
|
if (token->token == -rua_space) {
|
|
|
|
|
// ignore spaces
|
|
|
|
|
return macro;
|
|
|
|
|
}
|
2023-10-30 04:25:48 +00:00
|
|
|
|
if (token->token != -rua_id && token->token != -rua_ellipsis) {
|
2023-10-23 09:32:06 +00:00
|
|
|
|
error (0, "expected parameter name, found \"%s\"", token->text);
|
|
|
|
|
return macro;
|
|
|
|
|
}
|
2023-10-30 04:25:48 +00:00
|
|
|
|
if (macro->num_params < 0) {
|
|
|
|
|
error (0, "... must be the last parameter");
|
|
|
|
|
return macro;
|
|
|
|
|
} else if (symtab_lookup (macro->params, token->text)) {
|
2023-10-23 09:32:06 +00:00
|
|
|
|
error (0, "duplicate macro parameter \"%s\"", token->text);
|
|
|
|
|
return macro;
|
|
|
|
|
}
|
|
|
|
|
auto sym = new_symbol (token->text);
|
2023-10-24 14:32:13 +00:00
|
|
|
|
sym->sy_type = sy_var;
|
2024-08-16 07:48:11 +00:00
|
|
|
|
sym->offset = macro->num_params++;
|
2023-10-23 09:32:06 +00:00
|
|
|
|
symtab_addsymbol (macro->params, sym);
|
2023-10-30 04:25:48 +00:00
|
|
|
|
if (token->token == -rua_ellipsis) {
|
|
|
|
|
macro->num_params = -macro->num_params;
|
|
|
|
|
}
|
2023-10-22 11:56:12 +00:00
|
|
|
|
return macro;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-18 04:39:29 +00:00
|
|
|
|
static rua_tok_t
|
|
|
|
|
build_va_opt (rua_macro_t *macro, rua_tok_t *t, rua_tok_t *u, int va_opt_ind)
|
|
|
|
|
{
|
|
|
|
|
const char *va_opt_name = va (0, "__va_opt__.%d", va_opt_ind);
|
|
|
|
|
rua_tok_t va_opt_tok = {
|
|
|
|
|
.next = u->next,
|
|
|
|
|
.location = t->location,
|
|
|
|
|
.textlen = strlen (va_opt_name),
|
|
|
|
|
.token = -rua_va_opt,
|
|
|
|
|
.text = save_string (va_opt_name),
|
|
|
|
|
};
|
|
|
|
|
va_opt_tok.location.last_line = u->location.last_line;
|
|
|
|
|
va_opt_tok.location.last_column = u->location.last_column;
|
|
|
|
|
|
|
|
|
|
while (t->token != '(') {
|
|
|
|
|
t = t->next;
|
|
|
|
|
}
|
|
|
|
|
auto e = u;
|
|
|
|
|
for (u = t; u->next != e; u = u->next) continue;
|
|
|
|
|
u->next = 0;
|
2023-11-18 07:34:36 +00:00
|
|
|
|
auto va_opt = alloc_macro (0, false);
|
|
|
|
|
*va_opt = (rua_macro_t) {
|
|
|
|
|
.tail = &va_opt->tokens,
|
|
|
|
|
.update = rua_macro_va_opt,
|
|
|
|
|
.args = malloc (sizeof (rua_macro_t *)),
|
|
|
|
|
};
|
|
|
|
|
va_opt->args[0] = alloc_macro (0, false);
|
|
|
|
|
*va_opt->args[0] = (rua_macro_t) {
|
|
|
|
|
.tokens = t->next,
|
|
|
|
|
.tail = &u->next,
|
|
|
|
|
};
|
2023-11-18 04:39:29 +00:00
|
|
|
|
|
|
|
|
|
auto sym = new_symbol (va_opt_name);
|
|
|
|
|
sym->sy_type = sy_macro;
|
2024-08-16 07:48:11 +00:00
|
|
|
|
sym->macro = va_opt;
|
2023-11-18 04:39:29 +00:00
|
|
|
|
symtab_addsymbol (macro->params, sym);
|
|
|
|
|
return va_opt_tok;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
void
|
|
|
|
|
rua_macro_finish (rua_macro_t *macro, void *scanner)
|
|
|
|
|
{
|
2023-10-27 08:26:00 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
if (extra->suppressed) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-10-23 09:32:06 +00:00
|
|
|
|
if (macro->tokens) {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
while (((rua_tok_t *) macro->tail)->token == -rua_space) {
|
2023-10-24 05:01:21 +00:00
|
|
|
|
// space is never added as the first token, so it's guaranteed
|
|
|
|
|
// there is always at least two tokens
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_tok_t *t;
|
2023-10-24 05:01:21 +00:00
|
|
|
|
for (t = macro->tokens; t->next->next; t = t->next) continue;
|
|
|
|
|
free (t->next);
|
|
|
|
|
t->next = 0;
|
|
|
|
|
macro->tail = &t->next;
|
2023-10-24 06:58:37 +00:00
|
|
|
|
macro->num_tokens--;
|
2023-10-24 05:01:21 +00:00
|
|
|
|
}
|
2023-10-23 09:32:06 +00:00
|
|
|
|
if (macro->tokens->token == PRE_CONCAT
|
2023-11-11 13:32:29 +00:00
|
|
|
|
|| ((rua_tok_t *) macro->tail)->token == PRE_CONCAT) {
|
2023-10-23 09:32:06 +00:00
|
|
|
|
error (0, "'##' cannot appear at either end of a macro expansion");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-11-18 04:39:29 +00:00
|
|
|
|
int va_opt_ind = -1;
|
2023-10-23 09:32:06 +00:00
|
|
|
|
for (auto t = macro->tokens; t; t = t->next) {
|
|
|
|
|
if (t->token == '#'
|
|
|
|
|
&& (!t->next
|
2023-10-24 16:09:36 +00:00
|
|
|
|
|| t->next->token != -rua_id
|
2023-11-07 03:26:37 +00:00
|
|
|
|
|| (!symtab_lookup (macro->params, t->next->text)
|
|
|
|
|
&& strcmp (t->next->text, "__VA_OPT__") != 0))) {
|
2023-10-23 09:32:06 +00:00
|
|
|
|
error (0, "'#' is not followed by a macro parameter");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-11-07 03:26:37 +00:00
|
|
|
|
if (t->token == -rua_id && strcmp (t->text, "__VA_OPT__") == 0) {
|
|
|
|
|
auto u = t->next;
|
|
|
|
|
for (; u && u->token == -rua_space; u = u->next) continue;
|
|
|
|
|
if (!u) {
|
|
|
|
|
unterminated_va_opt:
|
|
|
|
|
error (0, "unterminated __VA_OPT__");
|
|
|
|
|
return;
|
|
|
|
|
} else if (u->token != '(') {
|
|
|
|
|
error (0, "__VA_OPT__ must be followed by an open "
|
|
|
|
|
"parenthesis");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (u->next && u->next->token == PRE_CONCAT) {
|
|
|
|
|
hashhash_error:
|
|
|
|
|
error (0, "'##' cannot appear at either end of __VA_OPT__");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int paren = 1;
|
|
|
|
|
for (u = u->next; u; u = u->next) {
|
|
|
|
|
if (u->token == '(') {
|
|
|
|
|
paren++;
|
|
|
|
|
} else if (u->token == ')') {
|
|
|
|
|
if (!(--paren)) {
|
2023-11-18 04:39:29 +00:00
|
|
|
|
*t = build_va_opt (macro, t, u, ++va_opt_ind);
|
2023-11-07 03:26:37 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else if (u->token == -rua_id
|
|
|
|
|
&& strcmp (u->text, "__VA_OPT__") == 0) {
|
|
|
|
|
error (0, "__VA_OPT__ may not appear in a __VA_OPT__");
|
|
|
|
|
return;
|
|
|
|
|
} else if (u->token == PRE_CONCAT && paren == 1
|
|
|
|
|
&& u->next && u->next->token == ')') {
|
|
|
|
|
goto hashhash_error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!u) {
|
|
|
|
|
goto unterminated_va_opt;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-23 09:32:06 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto macro_tab = extra->macro_tab;
|
|
|
|
|
auto sym = symtab_lookup (macro_tab, macro->name);
|
|
|
|
|
if (sym) {
|
2024-08-16 07:48:11 +00:00
|
|
|
|
auto o = sym->macro->tokens;
|
2023-10-23 09:32:06 +00:00
|
|
|
|
auto n = macro->tokens;
|
|
|
|
|
while (o && n && o->text == n->text) {
|
|
|
|
|
o = o->next;
|
|
|
|
|
n = n->next;
|
|
|
|
|
}
|
|
|
|
|
if (o || n) {
|
|
|
|
|
error (0, "\"%s\" redefined", macro->name);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sym = new_symbol (macro->name);
|
|
|
|
|
sym->sy_type = sy_macro;
|
2024-08-16 07:48:11 +00:00
|
|
|
|
sym->macro = macro;
|
2023-10-23 09:32:06 +00:00
|
|
|
|
symtab_addsymbol (macro_tab, sym);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 14:32:13 +00:00
|
|
|
|
rua_macro_t *
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_macro_arg (const rua_tok_t *token, void *scanner)
|
2023-10-24 14:32:13 +00:00
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-11-03 04:54:08 +00:00
|
|
|
|
auto macro = extra->pending_macro;
|
2023-10-30 04:25:48 +00:00
|
|
|
|
rua_macro_t *arg;
|
2023-11-03 04:54:08 +00:00
|
|
|
|
if (macro->num_params < 0 && macro->num_args == -macro->num_params) {
|
|
|
|
|
arg = macro->args[macro->num_args - 1];
|
2023-10-30 04:25:48 +00:00
|
|
|
|
rua_macro_append (arg, token, scanner);
|
|
|
|
|
} else {
|
2023-11-03 04:54:08 +00:00
|
|
|
|
if (macro->num_args < macro->num_params
|
|
|
|
|
|| macro->num_args < -macro->num_params) {
|
|
|
|
|
arg = macro->args[macro->num_args++];
|
|
|
|
|
} else {
|
|
|
|
|
// count the excess args for error reporting
|
|
|
|
|
macro->num_args++;
|
|
|
|
|
arg = 0;
|
|
|
|
|
}
|
2023-10-30 04:25:48 +00:00
|
|
|
|
}
|
2023-10-24 14:32:13 +00:00
|
|
|
|
return arg;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-25 00:25:00 +00:00
|
|
|
|
void
|
|
|
|
|
rua_start_pragma (void *scanner)
|
|
|
|
|
{
|
2023-10-30 23:42:28 +00:00
|
|
|
|
if (options.preprocess_output) {
|
2023-10-25 00:25:00 +00:00
|
|
|
|
printf ("#pragma");
|
|
|
|
|
}
|
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
yy_push_state (PRAGMA, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
void
|
|
|
|
|
rua_start_text (void *scanner)
|
|
|
|
|
{
|
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
yy_push_state (TEXT, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-27 08:22:47 +00:00
|
|
|
|
void
|
|
|
|
|
rua_start_include (void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
extra->expand = true;
|
|
|
|
|
|
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
yy_push_state (PREPROC, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
void
|
|
|
|
|
rua_start_expr (void *scanner)
|
|
|
|
|
{
|
2023-10-24 06:58:37 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-28 14:51:12 +00:00
|
|
|
|
extra->expand = !extra->suppressed;
|
2023-10-24 06:58:37 +00:00
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
yy_push_state (PREEXPR, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 06:58:37 +00:00
|
|
|
|
void
|
|
|
|
|
rua_expand_on (void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-28 14:51:12 +00:00
|
|
|
|
extra->expand = !extra->suppressed;
|
2023-10-24 06:58:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_expand_off (void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
extra->expand = false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
void
|
|
|
|
|
rua_end_directive (void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
extra->preprocessor = false;
|
|
|
|
|
extra->recording = false;
|
2023-10-24 06:58:37 +00:00
|
|
|
|
extra->expand = false;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-26 11:31:54 +00:00
|
|
|
|
static void
|
|
|
|
|
dump_debug (int act, const char *text, int start)
|
|
|
|
|
{
|
|
|
|
|
if (act == 0) {
|
|
|
|
|
printf("--scanner backing up\n" );
|
|
|
|
|
} else if (act < YY_NUM_RULES) {
|
|
|
|
|
printf("--accepting rule at line %ld\n",
|
|
|
|
|
(long)yy_rule_linenum[act]);
|
|
|
|
|
} else if (act == YY_NUM_RULES) {
|
|
|
|
|
printf("--accepting default rule\n");
|
|
|
|
|
} else if (act == YY_NUM_RULES + 1 ) {
|
|
|
|
|
printf("--(end of buffer or a NUL)\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("--EOF (start condition %d)\n", start);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
static void
|
2023-11-22 02:43:39 +00:00
|
|
|
|
dump_state_stack (yyscan_t scanner)
|
2023-10-22 11:56:12 +00:00
|
|
|
|
{
|
2023-10-28 14:51:12 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
auto yyg = (struct yyguts_t *)scanner;
|
|
|
|
|
for (int i = 0; i < yyg->yy_start_stack_ptr; i++) {
|
|
|
|
|
printf ("%d ", yyg->yy_start_stack[i]);
|
|
|
|
|
}
|
2023-10-28 14:51:12 +00:00
|
|
|
|
printf (": %d s:%s p:%s r:%s e:%s a:%s %s:%d\n", yystart (),
|
|
|
|
|
extra ? extra->suppressed ? "true" : "false" : "n/a",
|
|
|
|
|
extra ? extra->preprocessor ? "true" : "false" : "n/a",
|
|
|
|
|
extra ? extra->recording ? "true" : "false" : "n/a",
|
|
|
|
|
extra ? extra->expand ? "true" : "false" : "n/a",
|
|
|
|
|
extra ? extra->params ? "true" : "false" : "n/a",
|
2023-11-06 04:41:17 +00:00
|
|
|
|
pr.strings ? GETSTR(pr.loc.file) : "", pr.loc.line);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-26 11:31:54 +00:00
|
|
|
|
static void
|
|
|
|
|
dump_token (rua_tok_t *tok, rua_loc_t *loc, int state)
|
|
|
|
|
{
|
2023-11-07 03:26:37 +00:00
|
|
|
|
printf ("start: %2d [%3d %3d] [%3d %3d] %d '%s'\n", state,
|
2023-11-06 04:41:17 +00:00
|
|
|
|
loc->line, loc->column,
|
2023-10-26 11:31:54 +00:00
|
|
|
|
loc->last_line, loc->last_column,
|
2023-11-07 03:26:37 +00:00
|
|
|
|
tok->token, quote_string (tok->text));
|
2023-10-26 11:31:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
void
|
2023-10-28 14:51:12 +00:00
|
|
|
|
rua_start_if (bool expand, void *scanner)
|
2023-10-22 11:56:12 +00:00
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
rua_cond_t cond = {
|
2023-10-28 14:51:12 +00:00
|
|
|
|
.saw_true = false,
|
2023-10-22 11:56:12 +00:00
|
|
|
|
.saw_else = false,
|
|
|
|
|
.own_state = true,
|
2023-10-28 14:51:12 +00:00
|
|
|
|
.enabled = false,
|
2023-11-06 04:41:17 +00:00
|
|
|
|
.line = pr.loc.line,
|
2023-10-22 11:56:12 +00:00
|
|
|
|
};
|
|
|
|
|
if (extra->cond_stack.size) {
|
|
|
|
|
auto c = extra->cond_stack.a[extra->cond_stack.size - 1];
|
|
|
|
|
cond.own_state = c.own_state & c.enabled;
|
|
|
|
|
}
|
|
|
|
|
DARRAY_APPEND (&extra->cond_stack, cond);
|
2023-11-03 04:48:38 +00:00
|
|
|
|
extra->expand = expand;
|
|
|
|
|
|
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
yy_push_state (PREEXPR, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_start_else (bool expand, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
extra->expand = expand;
|
2023-10-28 14:51:12 +00:00
|
|
|
|
|
|
|
|
|
yy_pop_state (scanner);
|
|
|
|
|
yy_push_state (PREEXPR, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_if (bool pass, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
if (!extra->cond_stack.size) {
|
|
|
|
|
internal_error (0, "#if without start_if");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto cond = &extra->cond_stack.a[extra->cond_stack.size - 1];
|
|
|
|
|
cond->saw_true = cond->enabled = pass;
|
|
|
|
|
//yy_pop_state (scanner); // remove DIRECTIVE/PREEXPR state
|
|
|
|
|
if (cond->own_state && !cond->enabled) {
|
2023-10-26 11:31:54 +00:00
|
|
|
|
extra->suppressed = true;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
2023-11-06 04:41:17 +00:00
|
|
|
|
//printf ("#if on %s:%d %d\n", GETSTR(pr.loc.file),
|
2023-10-28 14:51:12 +00:00
|
|
|
|
// cond->line, extra->suppressed);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
// put PREEXPR on the stack for EOD to pop
|
2023-10-28 14:51:12 +00:00
|
|
|
|
//yy_push_state (PREEXPR, scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_else (bool pass, const char *tok, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
if (!extra->cond_stack.size) {
|
|
|
|
|
error (0, "#else without #if");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-10-28 14:51:12 +00:00
|
|
|
|
//yy_pop_state (scanner); // remove DIRECTIVE state
|
2023-10-22 11:56:12 +00:00
|
|
|
|
auto cond = &extra->cond_stack.a[extra->cond_stack.size - 1];
|
|
|
|
|
if (cond->saw_else) {
|
|
|
|
|
error (0, "#%s after #else", tok);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (cond->own_state && !cond->enabled) {
|
2023-10-26 11:31:54 +00:00
|
|
|
|
extra->suppressed = false;
|
2023-10-28 14:51:12 +00:00
|
|
|
|
//yy_pop_state (scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
pass &= !cond->saw_true;
|
|
|
|
|
cond->enabled = pass;
|
|
|
|
|
cond->saw_true |= pass;
|
|
|
|
|
cond->saw_else = strcmp (tok, "else") == 0;
|
2023-11-06 04:41:17 +00:00
|
|
|
|
//printf ("#else on %s:%d for %d %d\n", GETSTR(pr.loc.file),
|
|
|
|
|
// pr.loc.line, cond->line, extra->suppressed);
|
|
|
|
|
cond->line = pr.loc.line;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
if (cond->own_state && !cond->enabled) {
|
2023-10-26 11:31:54 +00:00
|
|
|
|
extra->suppressed = true;
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
// put PREEXPR on the stack for EOD to pop
|
2023-10-28 14:51:12 +00:00
|
|
|
|
//yy_push_state (PREEXPR, scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_endif (void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
if (!extra->cond_stack.size) {
|
|
|
|
|
error (0, "#endif without #if");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-10-28 14:51:12 +00:00
|
|
|
|
//yy_pop_state (scanner); // remove DIRECTIVE state
|
2023-10-22 11:56:12 +00:00
|
|
|
|
auto cond = DARRAY_REMOVE (&extra->cond_stack);
|
2023-11-06 04:41:17 +00:00
|
|
|
|
//printf ("#endif on %s:%d for %d %d\n", GETSTR(pr.loc.file),
|
|
|
|
|
// pr.loc.line, cond.line, extra->suppressed);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
if (cond.own_state && !cond.enabled) {
|
2023-10-26 11:31:54 +00:00
|
|
|
|
extra->suppressed = false;
|
2023-10-28 14:51:12 +00:00
|
|
|
|
//yy_pop_state (scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
|
|
|
|
// put PREEXPR on the stack for EOD to pop
|
2023-10-28 14:51:12 +00:00
|
|
|
|
//yy_push_state (PREEXPR, scanner);
|
2023-10-22 11:56:12 +00:00
|
|
|
|
}
|
2023-10-23 09:32:06 +00:00
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
rua_defined (const char *name, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
auto macro_tab = extra->macro_tab;
|
|
|
|
|
return symtab_lookup (macro_tab, name);
|
|
|
|
|
}
|
2023-10-23 10:00:37 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_undefine (const char *name, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-26 11:31:54 +00:00
|
|
|
|
if (extra->suppressed) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-10-23 10:00:37 +00:00
|
|
|
|
auto macro_tab = extra->macro_tab;
|
|
|
|
|
auto sym = symtab_lookup (macro_tab, name);
|
|
|
|
|
if (sym) {
|
|
|
|
|
symtab_removesymbol (macro_tab, sym);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-25 12:07:50 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_include_file (const char *name, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-10-26 11:31:54 +00:00
|
|
|
|
if (extra->suppressed) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-10-25 12:07:50 +00:00
|
|
|
|
struct yyguts_t * yyg = (struct yyguts_t*)scanner;//FIXME
|
|
|
|
|
int quote = *name;
|
|
|
|
|
name = make_string (name, 0);
|
|
|
|
|
bool is_system;
|
|
|
|
|
auto found = cpp_find_file (name, quote, &is_system);
|
|
|
|
|
if (!found || !(yyin = fopen (found, "rb"))) {
|
|
|
|
|
error (0, "fatal error: %s: %s", name, strerror (errno));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
2023-10-26 11:31:54 +00:00
|
|
|
|
//printf ("*** push include %s\n", name);
|
2023-10-25 12:07:50 +00:00
|
|
|
|
set_line_file (1, found, 1);
|
2023-10-31 01:48:11 +00:00
|
|
|
|
DARRAY_APPEND (&extra->include_stack, ((rua_incl_t) {
|
|
|
|
|
.buffer = YY_CURRENT_BUFFER,
|
|
|
|
|
.cond_stack = extra->cond_stack,
|
2023-11-06 04:41:17 +00:00
|
|
|
|
.location = extra->location,
|
2023-10-31 01:48:11 +00:00
|
|
|
|
}));
|
|
|
|
|
extra->cond_stack = (rua_cond_stack_t) DARRAY_STATIC_INIT (8);
|
2023-11-06 04:41:17 +00:00
|
|
|
|
auto buffer = yy_create_buffer (yyin, YY_BUF_SIZE, scanner);
|
|
|
|
|
yy_switch_to_buffer (buffer, scanner);
|
|
|
|
|
extra->location = (rua_loc_t) {
|
|
|
|
|
.line = 1,
|
|
|
|
|
.column = 1,
|
|
|
|
|
.last_line = 1,
|
|
|
|
|
.last_column = 1,
|
|
|
|
|
.file = ReuseString (found),
|
|
|
|
|
};
|
2023-10-25 12:07:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_embed_file (const char *name, void *scanner)
|
|
|
|
|
{
|
2023-10-26 11:31:54 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
if (extra->suppressed) {
|
|
|
|
|
return;
|
2023-10-25 12:07:50 +00:00
|
|
|
|
}
|
2023-10-26 11:31:54 +00:00
|
|
|
|
internal_error (0, "not implemented");
|
2023-10-28 14:51:12 +00:00
|
|
|
|
(void)yy_top_state;
|
2023-10-25 12:07:50 +00:00
|
|
|
|
}
|
2023-10-29 09:19:03 +00:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
rua_parse_define (const char *def)
|
|
|
|
|
{
|
|
|
|
|
int status;
|
|
|
|
|
yyscan_t scanner;
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_tok_t tok = { .location = { 1, 1, 1, 1 }, .token = -1, };
|
2023-10-29 09:19:03 +00:00
|
|
|
|
rua_extra_t extra = {
|
|
|
|
|
.preprocessor = true,
|
|
|
|
|
.pre_state = pre_yypstate_new (),
|
|
|
|
|
.macro_tab = cpp_macros,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
yylex_init_extra (&extra, &scanner);
|
|
|
|
|
yy_scan_string (def, scanner);
|
|
|
|
|
|
|
|
|
|
yy_push_state (PREPROC, scanner);
|
|
|
|
|
|
|
|
|
|
do {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
if (tok.token == -1) {
|
|
|
|
|
tok.token = PRE_DEFINE;
|
2023-10-29 09:19:03 +00:00
|
|
|
|
} else {
|
2023-11-11 13:32:29 +00:00
|
|
|
|
tok.token = yylex (&tok, &tok.location, scanner);
|
2023-11-12 04:20:35 +00:00
|
|
|
|
if (tok.text == extra.str_text) {
|
|
|
|
|
tok.text = save_string (tok.text);
|
|
|
|
|
}
|
2023-10-29 09:19:03 +00:00
|
|
|
|
status = 0;
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
while (tok.token) {
|
|
|
|
|
status = qc_process (&extra, tok.token, &tok, scanner);
|
2023-11-03 04:54:08 +00:00
|
|
|
|
if (status != YYPUSH_MORE || !extra.macro) {
|
2023-10-29 09:19:03 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2023-11-11 13:32:29 +00:00
|
|
|
|
tok = *extra.macro->cursor;
|
2023-11-03 04:54:08 +00:00
|
|
|
|
extra.macro->cursor = extra.macro->cursor->next;
|
|
|
|
|
if (!extra.macro->cursor) {
|
|
|
|
|
extra.macro = extra.macro->next;
|
|
|
|
|
}
|
2023-10-29 09:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
} while (status == YYPUSH_MORE);
|
|
|
|
|
|
|
|
|
|
yylex_destroy (scanner);
|
|
|
|
|
pre_yypstate_delete (extra.pre_state);
|
|
|
|
|
dstring_delete (extra.dstr);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
2023-11-01 07:07:12 +00:00
|
|
|
|
|
2023-11-06 04:41:17 +00:00
|
|
|
|
void
|
|
|
|
|
rua_line_info (const expr_t *line_expr, const char *file,
|
|
|
|
|
const expr_t *flags_expr, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
|
|
|
|
|
int line = expr_long (line_expr);
|
|
|
|
|
int flags = flags_expr ? expr_long (flags_expr) : 0;
|
|
|
|
|
|
|
|
|
|
if (file) {
|
|
|
|
|
if (*file != '"') {
|
|
|
|
|
error (0, "\"%s\" is not a valid filename", file);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
file = make_string (file, 0);
|
|
|
|
|
}
|
|
|
|
|
set_line_file (line, file, flags);
|
|
|
|
|
extra->location = pr.loc;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-01 07:07:12 +00:00
|
|
|
|
void
|
|
|
|
|
rua_macro_file (rua_macro_t *macro, void *scanner)
|
|
|
|
|
{
|
2023-11-06 04:41:17 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
int file = extra->location.file;
|
2023-11-01 07:07:12 +00:00
|
|
|
|
if (macro->tokens && macro->tokens->location.file == file) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
macro->tokens = 0;
|
|
|
|
|
macro->tail = ¯o->tokens;
|
|
|
|
|
macro->num_tokens = 0;
|
|
|
|
|
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_tok_t *expr = malloc (sizeof (*expr));
|
2023-11-01 07:07:12 +00:00
|
|
|
|
macro->num_tokens++;
|
|
|
|
|
const char *file_str = save_string (va (0, "\"%s\"",
|
|
|
|
|
quote_string (GETSTR (file))));
|
2023-11-11 13:32:29 +00:00
|
|
|
|
*expr = (rua_tok_t) {
|
2023-11-06 04:41:17 +00:00
|
|
|
|
.location = extra->location,
|
2023-11-01 07:07:12 +00:00
|
|
|
|
.textlen = strlen (file_str),
|
|
|
|
|
.token = -rua_string,
|
|
|
|
|
.text = file_str,
|
|
|
|
|
};
|
|
|
|
|
*macro->tail = expr;
|
|
|
|
|
macro->tail = &expr->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_macro_line (rua_macro_t *macro, void *scanner)
|
|
|
|
|
{
|
2023-11-06 04:41:17 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
int line = extra->location.line;
|
2023-11-01 07:07:12 +00:00
|
|
|
|
|
2023-11-06 04:41:17 +00:00
|
|
|
|
if (macro->tokens && macro->tokens->location.line == line) {
|
2023-11-01 07:07:12 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
macro->tokens = 0;
|
|
|
|
|
macro->tail = ¯o->tokens;
|
|
|
|
|
macro->num_tokens = 0;
|
|
|
|
|
|
2023-11-11 13:32:29 +00:00
|
|
|
|
rua_tok_t *expr = malloc (sizeof (*expr));
|
2023-11-01 07:07:12 +00:00
|
|
|
|
macro->num_tokens++;
|
|
|
|
|
const char *line_str = save_string (va (0, "%d", line));
|
2023-11-11 13:32:29 +00:00
|
|
|
|
*expr = (rua_tok_t) {
|
2023-11-06 04:41:17 +00:00
|
|
|
|
.location = extra->location,
|
2023-11-01 07:07:12 +00:00
|
|
|
|
.textlen = strlen (line_str),
|
|
|
|
|
.token = -rua_number,
|
|
|
|
|
.text = line_str,
|
|
|
|
|
};
|
|
|
|
|
*macro->tail = expr;
|
|
|
|
|
macro->tail = &expr->next;
|
|
|
|
|
}
|
2023-11-07 03:26:37 +00:00
|
|
|
|
|
2023-11-18 17:10:44 +00:00
|
|
|
|
static void
|
2023-11-22 02:43:39 +00:00
|
|
|
|
expand_arg (rua_macro_t *macro, rua_macro_t *arg, yyscan_t scanner)
|
2023-11-18 17:10:44 +00:00
|
|
|
|
{
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
2023-11-21 15:31:54 +00:00
|
|
|
|
rua_extra_t arg_extra = *extra;
|
|
|
|
|
arg_extra.macro = 0;
|
|
|
|
|
arg_extra.no_lex = true;
|
|
|
|
|
queue_macro (&arg_extra, arg);
|
|
|
|
|
qc_yyset_extra (&arg_extra, scanner);
|
2023-11-18 17:10:44 +00:00
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
rua_tok_t e;
|
|
|
|
|
if (next_token (&e, scanner)) {
|
2023-11-19 05:08:09 +00:00
|
|
|
|
if (macro->tokens
|
|
|
|
|
|| (e.token != -rua_space && e.token != -rua_ignore)) {
|
|
|
|
|
append_token (macro, &e);
|
|
|
|
|
}
|
2023-11-18 17:10:44 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qc_yyset_extra (extra, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
2023-11-22 02:43:39 +00:00
|
|
|
|
macro_empty (rua_macro_t *macro, yyscan_t scanner)
|
2023-11-18 17:10:44 +00:00
|
|
|
|
{
|
2023-11-22 02:43:39 +00:00
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
|
2023-11-18 17:10:44 +00:00
|
|
|
|
for (auto t = macro->tokens; t; t = t->next) {
|
|
|
|
|
if (t->token != -rua_id) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
symbol_t *sym;
|
|
|
|
|
if (macro->params
|
|
|
|
|
&& (sym = symtab_lookup (macro->params, t->text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !macro->args[sym->offset]->next) {
|
|
|
|
|
auto arg = macro->args[sym->offset];
|
2023-11-18 17:10:44 +00:00
|
|
|
|
arg->next = macro;
|
2023-11-22 02:43:39 +00:00
|
|
|
|
bool empty = macro_empty (arg, scanner);
|
2023-11-18 17:10:44 +00:00
|
|
|
|
arg->next = 0;
|
|
|
|
|
if (!empty) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ((sym = symtab_lookup (extra->macro_tab, t->text))
|
2024-08-16 07:48:11 +00:00
|
|
|
|
&& !sym->macro->next) {
|
|
|
|
|
auto m = sym->macro;
|
2023-11-18 17:10:44 +00:00
|
|
|
|
if (m->params) {
|
2023-11-19 05:08:09 +00:00
|
|
|
|
macro->cursor = t;
|
2023-11-22 02:43:39 +00:00
|
|
|
|
collect_args (m, macro, scanner);
|
2023-11-19 05:08:09 +00:00
|
|
|
|
if (t == macro->cursor) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-11-18 17:10:44 +00:00
|
|
|
|
}
|
|
|
|
|
m->next = macro;
|
2023-11-22 02:43:39 +00:00
|
|
|
|
bool empty = macro_empty (m, scanner);
|
2023-11-18 17:10:44 +00:00
|
|
|
|
m->next = 0;
|
|
|
|
|
if (!empty) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-07 03:26:37 +00:00
|
|
|
|
void
|
|
|
|
|
rua_macro_va_opt (rua_macro_t *macro, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
macro->tokens = 0;
|
|
|
|
|
macro->tail = ¯o->tokens;
|
|
|
|
|
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
auto cur = extra->macro;
|
|
|
|
|
if (!cur || !cur->params || cur->num_params >= 0) {
|
|
|
|
|
warning (0, "__VA_OPT__ can appear only in the expansion of a "
|
|
|
|
|
"variadic macro");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-11-22 02:43:39 +00:00
|
|
|
|
if (macro_empty (cur->args[~cur->num_params], scanner)) {
|
2023-11-15 03:46:38 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2023-11-18 09:08:23 +00:00
|
|
|
|
auto arg = macro->args[0];
|
|
|
|
|
arg->params = cur->params;
|
|
|
|
|
arg->num_params = cur->num_params;
|
|
|
|
|
arg->num_args = cur->num_args;
|
|
|
|
|
arg->args = cur->args;
|
|
|
|
|
|
2023-11-21 15:31:54 +00:00
|
|
|
|
expand_arg (macro, arg, scanner);
|
2023-11-07 03:26:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rua_macro_va_args (rua_macro_t *macro, void *scanner)
|
|
|
|
|
{
|
|
|
|
|
macro->tokens = 0;
|
|
|
|
|
macro->tail = ¯o->tokens;
|
|
|
|
|
|
|
|
|
|
auto extra = qc_yyget_extra (scanner);
|
|
|
|
|
auto cur = extra->macro;
|
|
|
|
|
if (!cur || !cur->params || cur->num_params >= 0) {
|
|
|
|
|
warning (0, "__VA_ARGS__ can appear only in the expansion of a "
|
|
|
|
|
"variadic macro");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto arg = cur->args[~cur->num_params];
|
|
|
|
|
if (arg->tokens) {
|
|
|
|
|
macro->tokens = arg->tokens;
|
|
|
|
|
macro->tail = arg->tail;
|
|
|
|
|
}
|
|
|
|
|
}
|