[qfcc] Implement #include and search paths

Other than some trouble with line comments and continuation lines, it
seems to work nicely.
This commit is contained in:
Bill Currie 2023-10-25 21:07:50 +09:00
parent f1f0a4a260
commit ffb2514e75
9 changed files with 480 additions and 160 deletions

View file

@ -34,9 +34,15 @@
struct dstring_s; struct dstring_s;
void parse_cpp_name (void); void parse_cpp_name (void);
void add_cpp_sysinc (const char *arg);
void add_cpp_undef (const char *arg); void add_cpp_undef (const char *arg);
void add_cpp_def (const char *arg); void add_cpp_def (const char *arg);
int cpp_include (const char *opt, const char *arg);
void cpp_define (const char *arg);
void cpp_undefine (const char *arg);
const char *cpp_find_file (const char *name, int quote, bool *is_system);
void cpp_set_quote_file (const char *path);
void intermediate_file (struct dstring_s *ifile, const char *filename, void intermediate_file (struct dstring_s *ifile, const char *filename,
const char *ext, int local); const char *ext, int local);
FILE *preprocess_file (const char *filename, const char *ext); FILE *preprocess_file (const char *filename, const char *ext);

View file

@ -35,6 +35,7 @@
typedef struct expr_s expr_t; typedef struct expr_s expr_t;
void set_line_file (int line, const char *file, int flags);
void line_info (const expr_t *line_expr, const char *text, void line_info (const expr_t *line_expr, const char *text,
const expr_t *flags_epxr); const expr_t *flags_epxr);
pr_lineno_t *new_lineno (void); pr_lineno_t *new_lineno (void);

View file

@ -91,6 +91,8 @@ void rua_else (bool pass, const char *tok, void *scanner);
void rua_endif (void *scanner); void rua_endif (void *scanner);
bool rua_defined (const char *sym, void *scanner); bool rua_defined (const char *sym, void *scanner);
void rua_undefine (const char *sym, void *scanner); void rua_undefine (const char *sym, void *scanner);
void rua_include_file (const char *name, void *scanner);
void rua_embed_file (const char *name, void *scanner);
#include "tools/qfcc/source/pre-parse.h" #include "tools/qfcc/source/pre-parse.h"

View file

@ -53,27 +53,44 @@
#include <stdio.h> #include <stdio.h>
#include "QF/dstring.h" #include "QF/dstring.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "tools/qfcc/include/cpp.h" #include "tools/qfcc/include/cpp.h"
#include "tools/qfcc/include/debug.h"
#include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/options.h" #include "tools/qfcc/include/options.h"
#include "tools/qfcc/include/qfcc.h"
#include "tools/qfcc/include/strpool.h"
typedef struct cpp_arg_s { typedef struct cpp_arg_s {
struct cpp_arg_s *next; struct cpp_arg_s *next;
const char *arg; const char *arg;
} cpp_arg_t; } cpp_arg_t;
cpp_arg_t *cpp_arg_list; typedef struct cpp_func_s {
cpp_arg_t **cpp_arg_tail = &cpp_arg_list; const char *name;
cpp_arg_t *cpp_def_list; int (*func) (const char *opt, const char *arg);
cpp_arg_t **cpp_def_tail = &cpp_def_list; } cpp_func_t;
cpp_arg_t *cpp_undef_list;
cpp_arg_t **cpp_undef_tail = &cpp_undef_list; static cpp_arg_t *cpp_quote_list, **cpp_quote_tail = &cpp_quote_list;
cpp_arg_t *cpp_sysinc_list; static cpp_arg_t *cpp_include_list,**cpp_include_tail= &cpp_include_list;
cpp_arg_t **cpp_sysinc_tail = &cpp_sysinc_list; static cpp_arg_t *cpp_system_list, **cpp_system_tail = &cpp_system_list;
const char **cpp_argv; static cpp_arg_t *cpp_after_list, **cpp_after_tail = &cpp_after_list;
const char *cpp_name = CPP_NAME;
static const char *cpp_prefix = "";
static const char *cpp_sysroot = QFCC_INCLUDE_PATH;
static const char *cpp_quote_start = 0;
static cpp_arg_t *cpp_arg_list, **cpp_arg_tail = &cpp_arg_list;
static cpp_arg_t *cpp_def_list, **cpp_def_tail = &cpp_def_list;
static cpp_arg_t *cpp_undef_list, **cpp_undef_tail = &cpp_undef_list;
static cpp_arg_t *cpp_sysinc_list, **cpp_sysinc_tail = &cpp_sysinc_list;
static const char **cpp_argv;
static int cpp_argc = 0; static int cpp_argc = 0;
const char *cpp_name = CPP_NAME;
dstring_t *tempname; dstring_t *tempname;
static const char ** static const char **
@ -86,66 +103,200 @@ append_cpp_args (const char **arg, cpp_arg_t *arg_list)
return arg; return arg;
} }
#define CPP_ADD(list, a) \
do { \
cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); \
*(cpp_arg) = (cpp_arg_t) { .arg = save_string (a) }; \
*cpp_##list##_tail = cpp_arg; \
cpp_##list##_tail = &cpp_arg->next; \
} while (0)
static void static void
add_cpp_arg (const char *arg) add_cpp_arg (const char *arg)
{ {
cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); CPP_ADD (arg, arg);
cpp_arg->next = 0;
cpp_arg->arg = arg;
*cpp_arg_tail = cpp_arg;
cpp_arg_tail = &(*cpp_arg_tail)->next;
cpp_argc++; cpp_argc++;
} }
void static void
add_cpp_sysinc (const char *arg) add_cpp_sysinc (const char *arg)
{ {
cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); CPP_ADD (sysinc, arg);
cpp_arg->next = 0;
cpp_arg->arg = arg;
*cpp_sysinc_tail = cpp_arg;
cpp_sysinc_tail = &(*cpp_sysinc_tail)->next;
cpp_argc++; cpp_argc++;
} }
void void
add_cpp_undef (const char *arg) add_cpp_undef (const char *arg)
{ {
cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); CPP_ADD (undef, arg);
cpp_arg->next = 0;
cpp_arg->arg = arg;
*cpp_undef_tail = cpp_arg;
cpp_undef_tail = &(*cpp_undef_tail)->next;
cpp_argc++; cpp_argc++;
} }
void void
add_cpp_def (const char *arg) add_cpp_def (const char *arg)
{ {
cpp_arg_t *cpp_def = malloc (sizeof (cpp_arg_t)); CPP_ADD (def, arg);
cpp_def->next = 0;
cpp_def->arg = arg;
*cpp_def_tail = cpp_def;
cpp_def_tail = &(*cpp_def_tail)->next;
cpp_argc++; cpp_argc++;
} }
static int
cpp_include_I (const char *opt, const char *arg)
{
if (!arg) {
return -1;
}
if (!strcmp (arg, "-")) {
return -1;
}
CPP_ADD (include, arg);
add_cpp_def (save_string ("-I"));
add_cpp_def (save_string (arg));
return 1;
}
static int
cpp_include_dirafter (const char *opt, const char *arg)
{
if (!arg) {
return -1;
}
CPP_ADD (quote, arg);
add_cpp_def (save_string ("-idirafter"));
add_cpp_def (save_string (arg));
return 1;
}
static int
cpp_include_prefix (const char *opt, const char *arg)
{
cpp_prefix = save_string (arg);
add_cpp_def (save_string ("-iprefix"));
add_cpp_def (save_string (arg));
return 0;
}
static int
cpp_include_quote (const char *opt, const char *arg)
{
if (!arg) {
return -1;
}
CPP_ADD (quote, arg);
add_cpp_def (save_string ("-iquote"));
add_cpp_def (save_string (arg));
return 1;
}
static int
cpp_include_sysroot (const char *opt, const char *arg)
{
cpp_sysroot = save_string (arg);
add_cpp_def (save_string ("-isysroot"));
add_cpp_def (save_string (arg));
return 0;
}
static int
cpp_include_system (const char *opt, const char *arg)
{
if (!arg) {
return -1;
}
CPP_ADD (system, arg);
add_cpp_def (save_string ("-isystem"));
add_cpp_def (save_string (arg));
return 1;
}
static int
cpp_include_withprefix (const char *opt, const char *arg)
{
if (!arg) {
return -1;
}
arg = va (0, "%s%s", cpp_prefix, arg);
CPP_ADD (after, arg);
add_cpp_def (save_string ("-iwithprefix"));
add_cpp_def (save_string (arg));
return 0;
}
static int
cpp_include_withprefixbefore (const char *opt, const char *arg)
{
if (!arg) {
return -1;
}
arg = va (0, "%s%s", cpp_prefix, arg);
CPP_ADD (include, arg);
add_cpp_def (save_string ("-iwithprefixbefore"));
add_cpp_def (save_string (arg));
return 0;
}
#define CPP_INCLUDE(name) {#name, cpp_include_##name}
int
cpp_include (const char *opt, const char *arg)
{
static cpp_func_t include_funcs[] = {
CPP_INCLUDE (I),
CPP_INCLUDE (prefix),
CPP_INCLUDE (dirafter),
CPP_INCLUDE (quote),
CPP_INCLUDE (sysroot),
CPP_INCLUDE (system),
CPP_INCLUDE (withprefix),
CPP_INCLUDE (withprefixbefore),
{}
};
for (int i = 0; include_funcs[i].name; i++) {
if (!strcmp (opt, include_funcs[i].name)) {
return include_funcs[i].func (opt, arg);
}
}
return -1;
}
#undef CPP_INCLUDE
void cpp_define (const char *arg)
{
#if 0
if (!cpp_macros) {
cpp_macros = new_symtab (stab_global);
}
#endif
arg = va (0, "-D%s", arg);
CPP_ADD (def, arg);
}
void cpp_undefine (const char *arg)
{
#if 0
if (cpp_macros) {
auto sym = symtab_lookup (cpp_macros, arg);
if (sym) {
symtab_removesymbol (cpp_macros, sym);
}
}
#endif
arg = va (0, "-D%s", arg);
CPP_ADD (undef, arg);
}
void void
parse_cpp_name (void) parse_cpp_name (void)
{ {
char *n; char *n, *e;
if (!cpp_name) if (!cpp_name || !*cpp_name) {
return; return;
n = strdup (cpp_name); }
while (*n) {
while (*n && *n == ' ') for (n = strdup (cpp_name); *n; n = e) {
n++; for (; *n && *n == ' '; n++) continue;
for (e = n; *e && *e != ' '; e++) continue;
*e++ = 0;
add_cpp_arg (n); add_cpp_arg (n);
while (*n && *n != ' ')
n++;
if (*n)
*n++ = 0;
} }
} }
@ -230,126 +381,206 @@ intermediate_file (dstring_t *ifile, const char *filename, const char *ext,
} }
} }
FILE * static FILE *
preprocess_file (const char *filename, const char *ext) run_cpp (const char *filename, const char *ext)
{ {
add_cpp_sysinc ("-isystem");
add_cpp_sysinc (QFCC_INCLUDE_PATH);
#ifndef _WIN32 #ifndef _WIN32
pid_t pid; pid_t pid;
int tempfd = 0; int tempfd = 0;
#endif #endif
if (cpp_name) { intermediate_file (tempname, filename, ext ? ext : "p", 0);
intermediate_file (tempname, filename, ext ? ext : "p", 0); build_cpp_args (filename, tempname->str);
build_cpp_args (filename, tempname->str); if (!cpp_argv[0]) {
if (!cpp_argv[0]) { internal_error(0, "cpp_argv[0] is null");
internal_error(0, "cpp_argv[0] is null"); }
}
#ifdef _WIN32 #ifdef _WIN32
if (!options.save_temps && !options.preprocess_only) if (!options.save_temps && !options.preprocess_only)
mktemp (tempname->str); mktemp (tempname->str);
}
{ FILE *tmp = fopen (tempname->str, "wb");
FILE *tmp = fopen (tempname->str, "wb"); if (tmp == NULL) {
if (tmp == NULL) { fprintf (stderr, "%s: qfcc was unable to open\n",
fprintf (stderr, "%s: qfcc was unable to open\n", tempname->str);
tempname->str); return 0;
return 0; }
} fclose (tmp);
fclose (tmp);
}
{ int status;
int status;
if (options.verbosity > 1) { if (options.verbosity > 1) {
const char **a; const char **a;
for (a = cpp_argv; *a; a++) for (a = cpp_argv; *a; a++)
printf ("%s ", *a); printf ("%s ", *a);
puts(""); puts("");
} }
#if defined(_WIN64) || defined(_WIN32) #if defined(_WIN64) || defined(_WIN32)
status = spawnvp (_P_WAIT, cpp_argv[0], (char **) cpp_argv); status = spawnvp (_P_WAIT, cpp_argv[0], (char **) cpp_argv);
#else #else
status = spawnvp (_P_WAIT, cpp_argv[0], cpp_argv); status = spawnvp (_P_WAIT, cpp_argv[0], cpp_argv);
#endif #endif
if (status) { if (status) {
fprintf (stderr, "%s: cpp returned error code %d\n", fprintf (stderr, "%s: cpp returned error code %d\n",
filename, filename,
status); status);
return 0; return 0;
} }
}
if (options.preprocess_only) if (options.preprocess_only)
return 0; return 0;
return fopen (tempname->str, "rb"); return fopen (tempname->str, "rb");
#else #else
if (!options.save_temps && !options.preprocess_only) if (!options.save_temps && !options.preprocess_only)
tempfd = mkstemp (tempname->str); tempfd = mkstemp (tempname->str);
if ((pid = fork ()) == -1) { if ((pid = fork ()) == -1) {
perror ("fork"); perror ("fork");
return 0; return 0;
}
if (!pid) {
// we're a child, check for abuse
if (options.verbosity > 1) {
const char **a;
for (a = cpp_argv; *a; a++)
printf ("%s ", *a);
puts("");
} }
if (!pid) {
// we're a child, check for abuse
if (options.verbosity > 1) {
const char **a;
for (a = cpp_argv; *a; a++)
printf ("%s ", *a);
puts("");
}
#ifdef HAVE_EXECVP #ifdef HAVE_EXECVP
execvp (cpp_argv[0], (char **)cpp_argv); execvp (cpp_argv[0], (char **)cpp_argv);
#else #else
execve (cpp_argv[0], (char **)cpp_argv, environ); execve (cpp_argv[0], (char **)cpp_argv, environ);
#endif #endif
perror (cpp_argv[0]); perror (cpp_argv[0]);
exit (1); exit (1);
} else { } else {
// give parental guidance (or bury it in the back yard) // give parental guidance (or bury it in the back yard)
int status; int status;
pid_t rc; pid_t rc;
// printf ("pid = %d\n", pid); // printf ("pid = %d\n", pid);
#ifdef HAVE_WAITPID #ifdef HAVE_WAITPID
rc = waitpid (0, &status, 0 | WUNTRACED); rc = waitpid (0, &status, 0 | WUNTRACED);
#else #else
rc = wait (&status); rc = wait (&status);
#endif #endif
if ((rc) != pid) { if ((rc) != pid) {
if (rc == -1) { if (rc == -1) {
perror ("wait"); perror ("wait");
return 0;
}
fprintf (stderr, "%s: The wrong child (%ld) died. Don't ask me, I don't know either.\n",
this_program,
(long) rc);
return 0; return 0;
} }
if (WIFEXITED (status)) { fprintf (stderr, "%s: The wrong child (%ld) died. Don't ask me, I don't know either.\n",
if (WEXITSTATUS (status)) { this_program,
fprintf (stderr, "%s: cpp returned error code %d\n", (long) rc);
filename, return 0;
WEXITSTATUS (status)); }
return 0; if (WIFEXITED (status)) {
} if (WEXITSTATUS (status)) {
} else { fprintf (stderr, "%s: cpp returned error code %d\n",
fprintf (stderr, "%s: cpp returned prematurely.\n", filename); filename,
return 0; WEXITSTATUS (status));
} return 0;
} }
if (options.preprocess_only) } else {
fprintf (stderr, "%s: cpp returned prematurely.\n", filename);
return 0; return 0;
else if (options.save_temps)
return fopen (tempname->str, "rb");
else {
return fdopen (tempfd, "rb");
} }
#endif
} }
return fopen (filename, "rb"); if (options.preprocess_only) {
return 0;
} else if (options.save_temps) {
set_line_file (1, tempname->str, 0);
return fopen (tempname->str, "rb");
} else {
set_line_file (1, "1", 0);
return fdopen (tempfd, "rb");
}
#endif
}
FILE *
preprocess_file (const char *filename, const char *ext)
{
if (cpp_name) {
return run_cpp (filename, ext);
} else {
set_line_file (1, filename, 0);
return fopen (filename, "rb");
}
}
static const char *
test_path (const char *path, const char *name)
{
static dstring_t *fullpath;
if (!fullpath) {
fullpath = dstring_new ();
}
dstring_copystr (fullpath, path);
if (fullpath->size > 1 && fullpath->str[fullpath->size - 2] != '/') {
dstring_appendstr (fullpath, "/");
}
dstring_appendstr (fullpath, name);
if (Sys_FileExists (fullpath->str) == 0) {
return fullpath->str;
}
return 0;
}
const char *
cpp_find_file (const char *name, int quote, bool *is_system)
{
*is_system = false;
if (*name == '/') {
return name;
}
const char *path;
if (quote == '"') {
if (cpp_quote_start && (path = test_path (cpp_quote_start, name))) {
return path;
}
for (auto dir = cpp_quote_list; dir; dir = dir->next) {
if ((path = test_path (cpp_quote_start, dir->arg))) {
return path;
}
}
}
for (auto dir = cpp_include_list; dir; dir = dir->next) {
if ((path = test_path (dir->arg, name))) {
return path;
}
}
*is_system = true;
for (auto dir = cpp_system_list; dir; dir = dir->next) {
if ((path = test_path (dir->arg, name))) {
return path;
}
}
for (auto dir = cpp_after_list; dir; dir = dir->next) {
if ((path = test_path (dir->arg, name))) {
return path;
}
}
return 0;
}
void
cpp_set_quote_file (const char *path)
{
if (!path) {
cpp_quote_start = pr.comp_dir;
return;
}
const char *e = strrchr (path, '/');
if (!e) {
cpp_quote_start = pr.comp_dir;
return;
}
cpp_quote_start = save_substring (path, e - path);
} }

View file

@ -43,6 +43,7 @@
#include "QF/alloc.h" #include "QF/alloc.h"
#include "QF/progs/pr_comp.h" #include "QF/progs/pr_comp.h"
#include "tools/qfcc/include/cpp.h"
#include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/debug.h"
#include "tools/qfcc/include/def.h" #include "tools/qfcc/include/def.h"
#include "tools/qfcc/include/defspace.h" #include "tools/qfcc/include/defspace.h"
@ -81,6 +82,8 @@ pop_source_file (void)
return; return;
} }
tmp = pr.srcline_stack; tmp = pr.srcline_stack;
pr.source_file = tmp->source_file;
pr.source_line = tmp->source_line;
pr.srcline_stack = tmp->next; pr.srcline_stack = tmp->next;
FREE (srclines, tmp); FREE (srclines, tmp);
} }
@ -96,6 +99,26 @@ add_source_file (const char *file)
} }
} }
void
set_line_file (int line, const char *file, int flags)
{
switch (flags & 3) {
case 1:
push_source_file ();
break;
case 2:
pop_source_file ();
file = GETSTR (pr.source_file);
line = pr.source_line;
break;
}
pr.source_line = line;
if (file) {
add_source_file (file);
cpp_set_quote_file (file);
}
}
void void
line_info (const expr_t *line_expr, const char *file, const expr_t *flags_expr) line_info (const expr_t *line_expr, const char *file, const expr_t *flags_expr)
{ {
@ -109,18 +132,7 @@ line_info (const expr_t *line_expr, const char *file, const expr_t *flags_expr)
} }
file = make_string (file, 0); file = make_string (file, 0);
} }
switch (flags & 3) { set_line_file (line, file, flags);
case 1:
push_source_file ();
break;
case 2:
pop_source_file ();
break;
}
pr.source_line = line;
if (file) {
add_source_file (file);
}
} }
pr_lineno_t * pr_lineno_t *

View file

@ -140,6 +140,7 @@ static const char *short_options =
"F" // generate files.dat "F" // generate files.dat
"g" // debug "g" // debug
"h" // help "h" // help
"i::" // set includes
"I:" // set includes "I:" // set includes
"L:" // lib path "L:" // lib path
"l:" // lib file "l:" // lib file
@ -607,8 +608,9 @@ DecodeArgs (int argc, char **argv)
add_cpp_undef ("-undef"); add_cpp_undef ("-undef");
add_cpp_undef ("-nostdinc"); add_cpp_undef ("-nostdinc");
add_cpp_undef ("-fno-extended-identifiers"); add_cpp_undef ("-fno-extended-identifiers");
add_cpp_def ("-D__QFCC__=1");
add_cpp_def ("-D__QUAKEC__=1"); cpp_define ("__QFCC__");
cpp_define ("__QUAKEC__");
sourcedir = ""; sourcedir = "";
progs_src = "progs.src"; progs_src = "progs.src";
@ -740,7 +742,7 @@ DecodeArgs (int argc, char **argv)
options.save_temps = true; options.save_temps = true;
break; break;
case 'D': // defines for cpp case 'D': // defines for cpp
add_cpp_def (nva ("%s%s", "-D", optarg)); cpp_define (optarg);
break; break;
case 'E': // defines for cpp case 'E': // defines for cpp
saw_E = 1; saw_E = 1;
@ -751,11 +753,21 @@ DecodeArgs (int argc, char **argv)
add_cpp_def (nva ("%s", "-include")); add_cpp_def (nva ("%s", "-include"));
add_cpp_def (nva ("%s", optarg)); add_cpp_def (nva ("%s", optarg));
break; break;
case 'i': // includes
{
int o = cpp_include (optarg, argv[optind]);
if (o < 0) {
usage (1);
} else {
optind += o;
}
}
break;
case 'I': // includes case 'I': // includes
add_cpp_def (nva ("%s%s", "-I", optarg)); cpp_include ("I", optarg);
break; break;
case 'U': // undefines case 'U': // undefines
add_cpp_def (nva ("%s%s", "-U", optarg)); cpp_undefine (optarg);
break; break;
case 'M': case 'M':
options.preprocess_only = 1; options.preprocess_only = 1;
@ -857,8 +869,6 @@ DecodeArgs (int argc, char **argv)
// add the default paths // add the default paths
if (!options.no_default_paths) { if (!options.no_default_paths) {
add_cpp_sysinc ("-isystem");
add_cpp_sysinc (QFCC_INCLUDE_PATH);
linker_add_path (QFCC_LIB_PATH); linker_add_path (QFCC_LIB_PATH);
} }

View file

@ -173,38 +173,53 @@ start
directive_list directive_list
: /*empty*/ : /*empty*/
| directive EOD { rua_end_directive (scanner); } directive_list | directive directive_list
; ;
eod : EOD { rua_end_directive (scanner); } ;
directive directive
: INCLUDE expand string extra_warn : INCLUDE expand string extra_warn eod { rua_include_file ($3, scanner); }
| EMBED expand string extra_ignore | EMBED expand string extra_ignore eod { rua_embed_file ($3, scanner); }
| DEFINE ID <macro> { $$ = rua_start_macro ($2, false, scanner); } | DEFINE ID <macro> { $$ = rua_start_macro ($2, false, scanner); }
body { rua_macro_finish ($body, scanner); } body { rua_macro_finish ($body, scanner); }
eod
| DEFINE IDp <macro> { $$ = rua_start_macro ($2, true, scanner); } | DEFINE IDp <macro> { $$ = rua_start_macro ($2, true, scanner); }
params ')' <macro> { $$ = rua_end_params ($3, scanner); } params ')' <macro> { $$ = rua_end_params ($3, scanner); }
body { rua_macro_finish ($body, scanner); } body { rua_macro_finish ($body, scanner); }
eod
| UNDEF ID extra_warn { rua_undefine ($2, scanner); } | UNDEF ID extra_warn { rua_undefine ($2, scanner); }
eod
| ERROR text { error (0, "%s", $text->str); dstring_delete ($text); } | ERROR text { error (0, "%s", $text->str); dstring_delete ($text); }
eod
| WARNING text { warning (0, "%s", $text->str); dstring_delete ($text); } | WARNING text { warning (0, "%s", $text->str); dstring_delete ($text); }
eod
| PRAGMA expand { rua_start_pragma (scanner); } | PRAGMA expand { rua_start_pragma (scanner); }
pragma_params { pragma_process (); } pragma_params { pragma_process (); }
eod
| LINE expand expr extra_warn { line_info ($3, 0, 0); } | LINE expand expr extra_warn { line_info ($3, 0, 0); }
eod
| LINE expand expr string line_expr extra_warn { line_info ($3, $4, $5); } | LINE expand expr string line_expr extra_warn { line_info ($3, $4, $5); }
eod
| IF expand expr { rua_if (expr_long ($3), scanner); } | IF expand expr { rua_if (expr_long ($3), scanner); }
eod
| IFDEF ID extra_warn { rua_if (rua_defined ($2, scanner), scanner); } | IFDEF ID extra_warn { rua_if (rua_defined ($2, scanner), scanner); }
eod
| IFNDEF ID extra_warn { rua_if (!rua_defined ($2, scanner), scanner); } | IFNDEF ID extra_warn { rua_if (!rua_defined ($2, scanner), scanner); }
eod
| ELSE extra_warn { rua_else (true, "else", scanner); } | ELSE extra_warn { rua_else (true, "else", scanner); }
eod
| ELIF expand expr { rua_else (expr_long ($3), "elif", scanner); } | ELIF expand expr { rua_else (expr_long ($3), "elif", scanner); }
eod
| ELIFDEF ID extra_warn | ELIFDEF ID extra_warn
{ { rua_else (rua_defined ($2, scanner), "elifdef", scanner); }
rua_else (rua_defined ($2, scanner), "elifdef", scanner); eod
}
| ELIFNDEF ID extra_warn | ELIFNDEF ID extra_warn
{ { rua_else (!rua_defined ($2, scanner), "elifndef", scanner); }
rua_else (!rua_defined ($2, scanner), "elifndef", scanner); eod
} | ENDIF extra_warn
| ENDIF extra_warn { rua_endif (scanner); } { rua_endif (scanner); }
eod
; ;
extra_warn extra_warn

View file

@ -55,6 +55,7 @@
#include <QF/va.h> #include <QF/va.h>
#include "tools/qfcc/include/class.h" #include "tools/qfcc/include/class.h"
#include "tools/qfcc/include/cpp.h"
#include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/debug.h"
#include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/expr.h"
@ -96,6 +97,7 @@ typedef struct {
typedef struct DARRAY_TYPE (rua_cond_t) rua_cond_stack_t; typedef struct DARRAY_TYPE (rua_cond_t) rua_cond_stack_t;
typedef struct DARRAY_TYPE (rua_expr_t) rua_expr_stack_t; typedef struct DARRAY_TYPE (rua_expr_t) rua_expr_stack_t;
typedef struct DARRAY_TYPE (rua_macro_t *) rua_macro_list_t; typedef struct DARRAY_TYPE (rua_macro_t *) rua_macro_list_t;
typedef struct DARRAY_TYPE (YY_BUFFER_STATE) rua_include_stack_t;
typedef struct rua_extra_s { typedef struct rua_extra_s {
int start_state; int start_state;
@ -108,6 +110,7 @@ typedef struct rua_extra_s {
rua_cond_stack_t cond_stack; rua_cond_stack_t cond_stack;
rua_expr_stack_t expr_stack; rua_expr_stack_t expr_stack;
rua_macro_list_t arg_list; rua_macro_list_t arg_list;
rua_include_stack_t include_stack;
dstring_t *dstr; dstring_t *dstr;
symtab_t *macro_tab; symtab_t *macro_tab;
yyscan_t subscanner; yyscan_t subscanner;
@ -1403,6 +1406,7 @@ qc_yyparse (FILE *in)
.cond_stack = DARRAY_STATIC_INIT (8), .cond_stack = DARRAY_STATIC_INIT (8),
.expr_stack = DARRAY_STATIC_INIT (32), .expr_stack = DARRAY_STATIC_INIT (32),
.arg_list = DARRAY_STATIC_INIT (8), .arg_list = DARRAY_STATIC_INIT (8),
.include_stack = DARRAY_STATIC_INIT (8),
.dstr = dstring_new (), .dstr = dstring_new (),
.macro_tab = new_symtab (0, stab_global), .macro_tab = new_symtab (0, stab_global),
}; };
@ -1412,6 +1416,14 @@ qc_yyparse (FILE *in)
yyset_in (in, scanner); yyset_in (in, scanner);
do { do {
int token = yylex (&tok, &tok.location, scanner); int token = yylex (&tok, &tok.location, scanner);
if (!token && extra.include_stack.size) {
struct yyguts_t * yyg = (struct yyguts_t*)scanner;//FIXME
yy_delete_buffer (YY_CURRENT_BUFFER, scanner);
auto buffer = DARRAY_REMOVE (&extra.include_stack);
set_line_file (-1, 0, 2);
yy_switch_to_buffer (buffer, scanner);
continue;
}
while (true) { while (true) {
status = qc_process (&extra, token, &tok, scanner); status = qc_process (&extra, token, &tok, scanner);
if (status != YYPUSH_MORE || !extra.expr_stack.size) { if (status != YYPUSH_MORE || !extra.expr_stack.size) {
@ -1435,6 +1447,7 @@ qc_yyparse (FILE *in)
free (extra.cond_stack.a); free (extra.cond_stack.a);
free (extra.expr_stack.a); free (extra.expr_stack.a);
free (extra.arg_list.a); free (extra.arg_list.a);
free (extra.include_stack.a);
dstring_delete (extra.dstr); dstring_delete (extra.dstr);
return status; return status;
} }
@ -1732,3 +1745,30 @@ rua_undefine (const char *name, void *scanner)
symtab_removesymbol (macro_tab, sym); symtab_removesymbol (macro_tab, sym);
} }
} }
void
rua_include_file (const char *name, void *scanner)
{
auto extra = qc_yyget_extra (scanner);
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);
}
set_line_file (1, found, 1);
DARRAY_APPEND (&extra->include_stack, YY_CURRENT_BUFFER);
yy_switch_to_buffer (yy_create_buffer (yyin, YY_BUF_SIZE, scanner), scanner);
}
void
rua_embed_file (const char *name, void *scanner)
{
if (scanner) {
internal_error (0, "not implemented");
}
printf ("eh?\n");
}

View file

@ -195,6 +195,9 @@ make_string (const char *token, char **end)
unicount = 0; unicount = 0;
quote = *token++; quote = *token++;
if (quote == '<') {
quote = '>'; // #include <file>
}
do { do {
c = *token++; c = *token++;
if (!c) if (!c)