diff --git a/tools/qfcc/include/cpp.h b/tools/qfcc/include/cpp.h index 81274c353..ecdff9169 100644 --- a/tools/qfcc/include/cpp.h +++ b/tools/qfcc/include/cpp.h @@ -34,9 +34,15 @@ struct dstring_s; void parse_cpp_name (void); -void add_cpp_sysinc (const char *arg); void add_cpp_undef (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, const char *ext, int local); FILE *preprocess_file (const char *filename, const char *ext); diff --git a/tools/qfcc/include/debug.h b/tools/qfcc/include/debug.h index fc8be97a4..3bb8de94a 100644 --- a/tools/qfcc/include/debug.h +++ b/tools/qfcc/include/debug.h @@ -35,6 +35,7 @@ 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, const expr_t *flags_epxr); pr_lineno_t *new_lineno (void); diff --git a/tools/qfcc/include/rua-lang.h b/tools/qfcc/include/rua-lang.h index bb299fa7b..034e8918c 100644 --- a/tools/qfcc/include/rua-lang.h +++ b/tools/qfcc/include/rua-lang.h @@ -91,6 +91,8 @@ void rua_else (bool pass, const char *tok, void *scanner); void rua_endif (void *scanner); bool rua_defined (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" diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index db2d95d55..c4f409da1 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -53,27 +53,44 @@ #include #include "QF/dstring.h" +#include "QF/sys.h" +#include "QF/va.h" #include "tools/qfcc/include/cpp.h" +#include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/strpool.h" typedef struct cpp_arg_s { struct cpp_arg_s *next; const char *arg; } cpp_arg_t; -cpp_arg_t *cpp_arg_list; -cpp_arg_t **cpp_arg_tail = &cpp_arg_list; -cpp_arg_t *cpp_def_list; -cpp_arg_t **cpp_def_tail = &cpp_def_list; -cpp_arg_t *cpp_undef_list; -cpp_arg_t **cpp_undef_tail = &cpp_undef_list; -cpp_arg_t *cpp_sysinc_list; -cpp_arg_t **cpp_sysinc_tail = &cpp_sysinc_list; -const char **cpp_argv; -const char *cpp_name = CPP_NAME; +typedef struct cpp_func_s { + const char *name; + int (*func) (const char *opt, const char *arg); +} cpp_func_t; + +static cpp_arg_t *cpp_quote_list, **cpp_quote_tail = &cpp_quote_list; +static cpp_arg_t *cpp_include_list,**cpp_include_tail= &cpp_include_list; +static cpp_arg_t *cpp_system_list, **cpp_system_tail = &cpp_system_list; +static cpp_arg_t *cpp_after_list, **cpp_after_tail = &cpp_after_list; + +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; + +const char *cpp_name = CPP_NAME; dstring_t *tempname; static const char ** @@ -86,66 +103,200 @@ append_cpp_args (const char **arg, cpp_arg_t *arg_list) 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 add_cpp_arg (const char *arg) { - cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); - cpp_arg->next = 0; - cpp_arg->arg = arg; - *cpp_arg_tail = cpp_arg; - cpp_arg_tail = &(*cpp_arg_tail)->next; + CPP_ADD (arg, arg); cpp_argc++; } -void +static void add_cpp_sysinc (const char *arg) { - cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); - cpp_arg->next = 0; - cpp_arg->arg = arg; - *cpp_sysinc_tail = cpp_arg; - cpp_sysinc_tail = &(*cpp_sysinc_tail)->next; + CPP_ADD (sysinc, arg); cpp_argc++; } void add_cpp_undef (const char *arg) { - cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); - cpp_arg->next = 0; - cpp_arg->arg = arg; - *cpp_undef_tail = cpp_arg; - cpp_undef_tail = &(*cpp_undef_tail)->next; + CPP_ADD (undef, arg); cpp_argc++; } void add_cpp_def (const char *arg) { - cpp_arg_t *cpp_def = malloc (sizeof (cpp_arg_t)); - cpp_def->next = 0; - cpp_def->arg = arg; - *cpp_def_tail = cpp_def; - cpp_def_tail = &(*cpp_def_tail)->next; + CPP_ADD (def, arg); 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 parse_cpp_name (void) { - char *n; + char *n, *e; - if (!cpp_name) + if (!cpp_name || !*cpp_name) { return; - n = strdup (cpp_name); - while (*n) { - while (*n && *n == ' ') - n++; + } + + for (n = strdup (cpp_name); *n; n = e) { + for (; *n && *n == ' '; n++) continue; + for (e = n; *e && *e != ' '; e++) continue; + *e++ = 0; 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 * -preprocess_file (const char *filename, const char *ext) +static FILE * +run_cpp (const char *filename, const char *ext) { + add_cpp_sysinc ("-isystem"); + add_cpp_sysinc (QFCC_INCLUDE_PATH); + #ifndef _WIN32 pid_t pid; int tempfd = 0; #endif - if (cpp_name) { - intermediate_file (tempname, filename, ext ? ext : "p", 0); - build_cpp_args (filename, tempname->str); - if (!cpp_argv[0]) { - internal_error(0, "cpp_argv[0] is null"); - } + intermediate_file (tempname, filename, ext ? ext : "p", 0); + build_cpp_args (filename, tempname->str); + if (!cpp_argv[0]) { + internal_error(0, "cpp_argv[0] is null"); + } #ifdef _WIN32 - if (!options.save_temps && !options.preprocess_only) - mktemp (tempname->str); + if (!options.save_temps && !options.preprocess_only) + mktemp (tempname->str); + } - { - FILE *tmp = fopen (tempname->str, "wb"); - if (tmp == NULL) { - fprintf (stderr, "%s: qfcc was unable to open\n", - tempname->str); - return 0; - } - fclose (tmp); - } + FILE *tmp = fopen (tempname->str, "wb"); + if (tmp == NULL) { + fprintf (stderr, "%s: qfcc was unable to open\n", + tempname->str); + return 0; + } + fclose (tmp); - { - int status; + int status; - if (options.verbosity > 1) { - const char **a; - for (a = cpp_argv; *a; a++) - printf ("%s ", *a); - puts(""); - } + if (options.verbosity > 1) { + const char **a; + for (a = cpp_argv; *a; a++) + printf ("%s ", *a); + puts(""); + } #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 - status = spawnvp (_P_WAIT, cpp_argv[0], cpp_argv); + status = spawnvp (_P_WAIT, cpp_argv[0], cpp_argv); #endif - if (status) { - fprintf (stderr, "%s: cpp returned error code %d\n", - filename, - status); - return 0; - } - } + if (status) { + fprintf (stderr, "%s: cpp returned error code %d\n", + filename, + status); + return 0; + } - if (options.preprocess_only) - return 0; - return fopen (tempname->str, "rb"); + if (options.preprocess_only) + return 0; + return fopen (tempname->str, "rb"); #else - if (!options.save_temps && !options.preprocess_only) - tempfd = mkstemp (tempname->str); + if (!options.save_temps && !options.preprocess_only) + tempfd = mkstemp (tempname->str); - if ((pid = fork ()) == -1) { - perror ("fork"); - return 0; + if ((pid = fork ()) == -1) { + perror ("fork"); + 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 - execvp (cpp_argv[0], (char **)cpp_argv); + execvp (cpp_argv[0], (char **)cpp_argv); #else - execve (cpp_argv[0], (char **)cpp_argv, environ); + execve (cpp_argv[0], (char **)cpp_argv, environ); #endif - perror (cpp_argv[0]); - exit (1); - } else { - // give parental guidance (or bury it in the back yard) - int status; - pid_t rc; + perror (cpp_argv[0]); + exit (1); + } else { + // give parental guidance (or bury it in the back yard) + int status; + pid_t rc; // printf ("pid = %d\n", pid); #ifdef HAVE_WAITPID - rc = waitpid (0, &status, 0 | WUNTRACED); + rc = waitpid (0, &status, 0 | WUNTRACED); #else - rc = wait (&status); + rc = wait (&status); #endif - if ((rc) != pid) { - if (rc == -1) { - 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); + if ((rc) != pid) { + if (rc == -1) { + perror ("wait"); return 0; } - if (WIFEXITED (status)) { - if (WEXITSTATUS (status)) { - fprintf (stderr, "%s: cpp returned error code %d\n", - filename, - WEXITSTATUS (status)); - return 0; - } - } else { - fprintf (stderr, "%s: cpp returned prematurely.\n", filename); - return 0; - } - } - if (options.preprocess_only) + fprintf (stderr, "%s: The wrong child (%ld) died. Don't ask me, I don't know either.\n", + this_program, + (long) rc); + return 0; + } + if (WIFEXITED (status)) { + if (WEXITSTATUS (status)) { + fprintf (stderr, "%s: cpp returned error code %d\n", + filename, + WEXITSTATUS (status)); + return 0; + } + } else { + fprintf (stderr, "%s: cpp returned prematurely.\n", filename); 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); } diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index 6808f7bd0..2ab4b2331 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -43,6 +43,7 @@ #include "QF/alloc.h" #include "QF/progs/pr_comp.h" +#include "tools/qfcc/include/cpp.h" #include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" @@ -81,6 +82,8 @@ pop_source_file (void) return; } tmp = pr.srcline_stack; + pr.source_file = tmp->source_file; + pr.source_line = tmp->source_line; pr.srcline_stack = tmp->next; 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 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); } - switch (flags & 3) { - case 1: - push_source_file (); - break; - case 2: - pop_source_file (); - break; - } - pr.source_line = line; - if (file) { - add_source_file (file); - } + set_line_file (line, file, flags); } pr_lineno_t * diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 5951405a0..59e33135e 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -140,6 +140,7 @@ static const char *short_options = "F" // generate files.dat "g" // debug "h" // help + "i::" // set includes "I:" // set includes "L:" // lib path "l:" // lib file @@ -607,8 +608,9 @@ DecodeArgs (int argc, char **argv) add_cpp_undef ("-undef"); add_cpp_undef ("-nostdinc"); 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 = ""; progs_src = "progs.src"; @@ -740,7 +742,7 @@ DecodeArgs (int argc, char **argv) options.save_temps = true; break; case 'D': // defines for cpp - add_cpp_def (nva ("%s%s", "-D", optarg)); + cpp_define (optarg); break; case 'E': // defines for cpp saw_E = 1; @@ -751,11 +753,21 @@ DecodeArgs (int argc, char **argv) add_cpp_def (nva ("%s", "-include")); add_cpp_def (nva ("%s", optarg)); break; + case 'i': // includes + { + int o = cpp_include (optarg, argv[optind]); + if (o < 0) { + usage (1); + } else { + optind += o; + } + } + break; case 'I': // includes - add_cpp_def (nva ("%s%s", "-I", optarg)); + cpp_include ("I", optarg); break; case 'U': // undefines - add_cpp_def (nva ("%s%s", "-U", optarg)); + cpp_undefine (optarg); break; case 'M': options.preprocess_only = 1; @@ -857,8 +869,6 @@ DecodeArgs (int argc, char **argv) // add the default paths if (!options.no_default_paths) { - add_cpp_sysinc ("-isystem"); - add_cpp_sysinc (QFCC_INCLUDE_PATH); linker_add_path (QFCC_LIB_PATH); } diff --git a/tools/qfcc/source/pre-parse.y b/tools/qfcc/source/pre-parse.y index 4be1de1b7..d21af382d 100644 --- a/tools/qfcc/source/pre-parse.y +++ b/tools/qfcc/source/pre-parse.y @@ -173,38 +173,53 @@ start directive_list : /*empty*/ - | directive EOD { rua_end_directive (scanner); } directive_list + | directive directive_list ; +eod : EOD { rua_end_directive (scanner); } ; + directive - : INCLUDE expand string extra_warn - | EMBED expand string extra_ignore + : INCLUDE expand string extra_warn eod { rua_include_file ($3, scanner); } + | EMBED expand string extra_ignore eod { rua_embed_file ($3, scanner); } | DEFINE ID { $$ = rua_start_macro ($2, false, scanner); } body { rua_macro_finish ($body, scanner); } + eod | DEFINE IDp { $$ = rua_start_macro ($2, true, scanner); } params ')' { $$ = rua_end_params ($3, scanner); } body { rua_macro_finish ($body, scanner); } + eod | UNDEF ID extra_warn { rua_undefine ($2, scanner); } + eod | ERROR text { error (0, "%s", $text->str); dstring_delete ($text); } + eod | WARNING text { warning (0, "%s", $text->str); dstring_delete ($text); } + eod | PRAGMA expand { rua_start_pragma (scanner); } pragma_params { pragma_process (); } + eod | LINE expand expr extra_warn { line_info ($3, 0, 0); } + eod | LINE expand expr string line_expr extra_warn { line_info ($3, $4, $5); } + eod | IF expand expr { rua_if (expr_long ($3), scanner); } + eod | IFDEF ID extra_warn { rua_if (rua_defined ($2, scanner), scanner); } + eod | IFNDEF ID extra_warn { rua_if (!rua_defined ($2, scanner), scanner); } + eod | ELSE extra_warn { rua_else (true, "else", scanner); } + eod | ELIF expand expr { rua_else (expr_long ($3), "elif", scanner); } + eod | 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 - { - rua_else (!rua_defined ($2, scanner), "elifndef", scanner); - } - | ENDIF extra_warn { rua_endif (scanner); } + { rua_else (!rua_defined ($2, scanner), "elifndef", scanner); } + eod + | ENDIF extra_warn + { rua_endif (scanner); } + eod ; extra_warn diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 6cf03ecc0..865356c24 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -55,6 +55,7 @@ #include #include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/cpp.h" #include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/diagnostic.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_expr_t) rua_expr_stack_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 { int start_state; @@ -108,6 +110,7 @@ typedef struct rua_extra_s { rua_cond_stack_t cond_stack; rua_expr_stack_t expr_stack; rua_macro_list_t arg_list; + rua_include_stack_t include_stack; dstring_t *dstr; symtab_t *macro_tab; yyscan_t subscanner; @@ -1403,6 +1406,7 @@ qc_yyparse (FILE *in) .cond_stack = DARRAY_STATIC_INIT (8), .expr_stack = DARRAY_STATIC_INIT (32), .arg_list = DARRAY_STATIC_INIT (8), + .include_stack = DARRAY_STATIC_INIT (8), .dstr = dstring_new (), .macro_tab = new_symtab (0, stab_global), }; @@ -1412,6 +1416,14 @@ qc_yyparse (FILE *in) yyset_in (in, scanner); do { 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) { status = qc_process (&extra, token, &tok, scanner); if (status != YYPUSH_MORE || !extra.expr_stack.size) { @@ -1435,6 +1447,7 @@ qc_yyparse (FILE *in) free (extra.cond_stack.a); free (extra.expr_stack.a); free (extra.arg_list.a); + free (extra.include_stack.a); dstring_delete (extra.dstr); return status; } @@ -1732,3 +1745,30 @@ rua_undefine (const char *name, void *scanner) 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"); +} diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index 76853c4d5..998d09e99 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -195,6 +195,9 @@ make_string (const char *token, char **end) unicount = 0; quote = *token++; + if (quote == '<') { + quote = '>'; // #include + } do { c = *token++; if (!c)