Merged changes r1927-r1963 from the trunk into multiarch branch.
svn path=/branches/multiarch/; revision=1964
diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c
index acbf6ab..9397615 100644
--- a/frontends/yasm/yasm.c
+++ b/frontends/yasm/yasm.c
@@ -220,7 +220,7 @@
static constcharparam_head preproc_options;
static int
-do_preproc_only(FILE *in)
+do_preproc_only()
{
yasm_linemap *linemap;
char *preproc_buf = yasm_xmalloc(PREPROC_BUF_SIZE);
@@ -241,7 +241,7 @@
/* determine the object filename if not specified, but we need a
file name for the makefile rule */
if (generate_make_dependencies && !obj_filename) {
- if (in == stdin)
+ if (in_filename == NULL)
/* Default to yasm.out if no obj filename specified */
obj_filename = yasm__xstrdup("yasm.out");
else {
@@ -264,7 +264,7 @@
}
/* Pre-process until done */
- cur_preproc = yasm_preproc_create(cur_preproc_module, in, in_filename,
+ cur_preproc = yasm_preproc_create(cur_preproc_module, in_filename,
linemap, errwarns);
apply_preproc_builtins();
@@ -293,9 +293,6 @@
fwrite(preproc_buf, got, 1, out);
}
- if (in != stdin)
- fclose(in);
-
if (out != stdout)
fclose(out);
@@ -321,7 +318,7 @@
}
static int
-do_assemble(FILE *in)
+do_assemble()
{
yasm_object *object;
const char *base_filename;
@@ -337,7 +334,7 @@
/* determine the object filename if not specified */
if (!obj_filename) {
- if (in == stdin)
+ if (in_filename == NULL)
/* Default to yasm.out if no obj filename specified */
obj_filename = yasm__xstrdup("yasm.out");
else {
@@ -366,9 +363,8 @@
yasm__xstrdup(cur_arch_module->default_machine_keyword);
}
- cur_arch = cur_arch_module->create(machine_name,
- cur_parser_module->keyword,
- &arch_error);
+ cur_arch = yasm_arch_create(cur_arch_module, machine_name,
+ cur_parser_module->keyword, &arch_error);
if (!cur_arch) {
switch (arch_error) {
case YASM_ARCH_CREATE_BAD_MACHINE:
@@ -402,8 +398,6 @@
yasm_xfree(estr);
yasm_xfree(xrefstr);
- if (in != stdin)
- fclose(in);
cleanup(object);
return EXIT_FAILURE;
}
@@ -423,14 +417,12 @@
print_error(_("%s: `%s' is not a valid %s for %s `%s'"), _("FATAL"),
cur_preproc_module->keyword, _("preprocessor"),
_("parser"), cur_parser_module->keyword);
- if (in != stdin)
- fclose(in);
cleanup(object);
return EXIT_FAILURE;
}
- cur_preproc = cur_preproc_module->create(in, in_filename, linemap,
- errwarns);
+ cur_preproc = yasm_preproc_create(cur_preproc_module, in_filename,
+ linemap, errwarns);
apply_preproc_builtins();
apply_preproc_saved_options();
@@ -444,13 +436,9 @@
yasm_arch_set_var(cur_arch, "force_strict", force_strict);
/* Parse! */
- cur_parser_module->do_parse(object, cur_preproc, in, list_filename != NULL,
+ cur_parser_module->do_parse(object, cur_preproc, list_filename != NULL,
linemap, errwarns);
- /* Close input file */
- if (in != stdin)
- fclose(in);
-
check_errors(errwarns, object, linemap);
/* Finalize parse */
@@ -576,7 +564,7 @@
/* Initialize intnum and floatnum */
yasm_intnum_initialize();
yasm_floatnum_initialize();
-
+
/* If not already specified, default to bin as the object format. */
if (!cur_objfmt_module) {
if (!objfmt_keyword)
@@ -638,20 +626,6 @@
if (!in_filename) {
print_error(_("No input files specified"));
return EXIT_FAILURE;
- } else if (strcmp(in_filename, "-") != 0) {
- /* Open the input file (if not standard input) */
- in = fopen(in_filename, "rt");
- if (!in) {
- print_error(_("%s: could not open file `%s'"), _("FATAL"),
- in_filename);
- yasm_xfree(in_filename);
- if (obj_filename)
- yasm_xfree(obj_filename);
- return EXIT_FAILURE;
- }
- } else {
- /* Filename was "-", read stdin */
- in = stdin;
}
/* handle preproc-only case here */
@@ -1086,7 +1060,7 @@
/* Also set preproc_only to 1, we don't want to generate code */
preproc_only = 1;
generate_make_dependencies = 1;
-
+
return 0;
}
diff --git a/libyasm/file.c b/libyasm/file.c
index cd2e002..48cb6f2 100644
--- a/libyasm/file.c
+++ b/libyasm/file.c
@@ -518,6 +518,23 @@
STAILQ_INIT(&incpaths);
}
+const char *
+yasm_get_include_dir(void **iter)
+{
+ incpath *p = (incpath *)*iter;
+
+ if (!p)
+ p = STAILQ_FIRST(&incpaths);
+ else
+ p = STAILQ_NEXT(p, link);
+
+ *iter = p;
+ if (p)
+ return p->path;
+ else
+ return NULL;
+}
+
void
yasm_add_include_path(const char *path)
{
diff --git a/libyasm/file.h b/libyasm/file.h
index c706994..21676cd 100644
--- a/libyasm/file.h
+++ b/libyasm/file.h
@@ -210,6 +210,10 @@
*/
void yasm_delete_include_paths(void);
+/** Iterate through include paths.
+*/
+const char * yasm_get_include_dir(void **iter);
+
/** Add an include path for use by yasm_fopen_include().
* If path is relative, it is treated by yasm_fopen_include() as relative to
* the current working directory.
diff --git a/libyasm/parser.h b/libyasm/parser.h
index 2ed5ce1..fcbb20c 100644
--- a/libyasm/parser.h
+++ b/libyasm/parser.h
@@ -54,7 +54,6 @@
/** Parse a source file into an object.
* \param object object to parse into (already created)
* \param pp preprocessor
- * \param f initial starting file
* \param save_input nonzero if the parser should save the original
* lines of source into the object's linemap (via
* yasm_linemap_add_data()).
@@ -62,7 +61,7 @@
* \note Parse errors and warnings are stored into errwarns.
*/
void (*do_parse)
- (yasm_object *object, yasm_preproc *pp, FILE *f, int save_input,
+ (yasm_object *object, yasm_preproc *pp, int save_input,
yasm_linemap *linemap, yasm_errwarns *errwarns);
} yasm_parser_module;
diff --git a/libyasm/preproc.h b/libyasm/preproc.h
index f93a838..98f56e8 100644
--- a/libyasm/preproc.h
+++ b/libyasm/preproc.h
@@ -56,15 +56,15 @@
* Module-level implementation of yasm_preproc_create().
* Call yasm_preproc_create() instead of calling this function.
*
- * \param f initial starting file
- * \param in_filename initial starting filename
+ * \param in_filename initial starting filename, or "-" to read from
+ * stdin
* \param lm line mapping repository
* \param errwarns error/warnning set.
* \return New preprocessor.
*
* \note Any preprocessor errors and warnings are stored into errwarns.
*/
- /*@only@*/ yasm_preproc * (*create) (FILE *f, const char *in_filename,
+ /*@only@*/ yasm_preproc * (*create) (const char *in_filename,
yasm_linemap *lm,
yasm_errwarns *errwarns);
@@ -110,15 +110,14 @@
* The preprocessor needs access to the object format module to find out
* any output format specific macros.
* \param module preprocessor module
- * \param f initial starting file
- * \param in_filename initial starting file filename
+ * \param in_filename initial starting filename, or "-" to read from stdin
* \param lm line mapping repository
* \param errwarns error/warning set
* \return New preprocessor.
* \note Errors/warnings are stored into errwarns.
*/
/*@only@*/ yasm_preproc *yasm_preproc_create
- (yasm_preproc_module *module, FILE *f, const char *in_filename,
+ (yasm_preproc_module *module, const char *in_filename,
yasm_linemap *lm, yasm_errwarns *errwarns);
/** Cleans up any allocated preproc memory.
@@ -176,8 +175,8 @@
/* Inline macro implementations for preproc functions */
-#define yasm_preproc_create(module, f, in_filename, lm, ews) \
- module->create(f, in_filename, lm, ews)
+#define yasm_preproc_create(module, in_filename, lm, ews) \
+ module->create(in_filename, lm, ews)
#define yasm_preproc_destroy(preproc) \
((yasm_preproc_base *)preproc)->module->destroy(preproc)
diff --git a/modules/parsers/gas/gas-parse.c b/modules/parsers/gas/gas-parse.c
index ef64c16..2c402f1 100644
--- a/modules/parsers/gas/gas-parse.c
+++ b/modules/parsers/gas/gas-parse.c
@@ -44,6 +44,7 @@
enum gas_parser_state newstate;
} dir_lookup;
+static yasm_bytecode * cpp_line_marker(yasm_parser_gas *parser_gas);
static yasm_bytecode *parse_instr(yasm_parser_gas *parser_gas);
static int parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps);
static int parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
@@ -85,7 +86,7 @@
{
char savech = parser_gas->tokch;
if (parser_gas->peek_token != NONE)
- yasm_internal_error(N_("only can have one token of lookahead"));
+ yasm_internal_error(N_("can only have one token of lookahead"));
parser_gas->peek_token =
gas_parser_lex(&parser_gas->peek_tokval, parser_gas);
parser_gas->peek_tokch = parser_gas->tokch;
@@ -247,6 +248,9 @@
define_label(parser_gas, LABEL_val, 0);
get_next_token(); /* LABEL */
return parse_line(parser_gas);
+ case LINE_MARKER:
+ get_next_token();
+ return cpp_line_marker(parser_gas);
default:
yasm_error_set(YASM_ERROR_SYNTAX,
N_("label or instruction expected at start of line"));
@@ -254,6 +258,110 @@
}
}
+/*
+ Handle line markers generated by cpp.
+
+ We expect a positive integer (line) followed by a string (filename). If we
+ fail to find either of these, we treat the line as a comment. There is a
+ possibility of false positives (mistaking a comment for a line marker, when
+ the comment is not intended as a line marker) but this cannot be avoided
+ without adding a filter to the input before passing it to cpp.
+
+ This function is only called if the preprocessor was 'cpp', since the
+ LINE_MARKER token isn't generated for any other preprocessor. With any other
+ preprocessor, anything after a '#' is always treated as a comment.
+*/
+static yasm_bytecode *
+cpp_line_marker(yasm_parser_gas *parser_gas)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ unsigned long line;
+ char *filename;
+
+ /* Line number. */
+ if (curtok != INTNUM) {
+ /* Skip over a comment. */
+ while (curtok != '\n')
+ get_next_token();
+
+ return NULL;
+ }
+
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line number is negative"));
+ return NULL;
+ }
+
+ line = yasm_intnum_get_uint(INTNUM_val);
+
+ /*
+ Set to (line - 1) since the directive indicates that the *next* line
+ will have the number given.
+
+ cpp should never produce line=0, but the if keeps us safe just incase.
+ */
+ if (line != 0)
+ line--;
+
+ yasm_intnum_destroy(INTNUM_val);
+ get_next_token(); /* INTNUM */
+
+ /* File name, in quotes. */
+ if (curtok != STRING) {
+ /* Skip over a comment. */
+ while (curtok != '\n')
+ get_next_token();
+
+ return NULL;
+ }
+
+ filename = STRING_val.contents;
+ get_next_token();
+
+ /* Set linemap. */
+ yasm_linemap_set(parser_gas->linemap, filename, line, 1);
+
+ /*
+ The first line marker in the file (which should be on the first line
+ of the file) will give us the name of the source file. This information
+ needs to be passed on to the debug format module.
+ */
+ if (parser_gas->seen_line_marker == 0) {
+ parser_gas->seen_line_marker = 1;
+
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, filename);
+ yasm_vps_append(&vps, vp);
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
+
+ yasm_vps_delete(&vps);
+ }
+
+ /* Skip flags. */
+ while (1) {
+ switch (curtok) {
+ case INTNUM:
+ break;
+
+ case '\n':
+ return NULL;
+
+ default:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("junk at end of cpp line marker"));
+ return NULL;
+ }
+ get_next_token();
+ }
+
+ /* Never reached. */
+ return NULL;
+}
+
/* Line directive */
static yasm_bytecode *
dir_line(yasm_parser_gas *parser_gas, unsigned int param)
@@ -1516,7 +1624,7 @@
while (get_next_token() != 0) {
yasm_bytecode *bc = NULL, *temp_bc;
-
+
if (!is_eol()) {
bc = parse_line(parser_gas);
demand_eol();
diff --git a/modules/parsers/gas/gas-parser.c b/modules/parsers/gas/gas-parser.c
index 9cc6138..521851c 100644
--- a/modules/parsers/gas/gas-parser.c
+++ b/modules/parsers/gas/gas-parser.c
@@ -36,7 +36,7 @@
static void
-gas_parser_do_parse(yasm_object *object, yasm_preproc *pp, FILE *f,
+gas_parser_do_parse(yasm_object *object, yasm_preproc *pp,
int save_input, yasm_linemap *linemap,
yasm_errwarns *errwarns)
{
@@ -46,14 +46,13 @@
parser_gas.object = object;
parser_gas.linemap = linemap;
- parser_gas.in = f;
-
parser_gas.locallabel_base = (char *)NULL;
parser_gas.locallabel_base_len = 0;
parser_gas.dir_fileline = 0;
parser_gas.dir_file = NULL;
parser_gas.dir_line = 0;
+ parser_gas.seen_line_marker = 0;
parser_gas.preproc = pp;
parser_gas.errwarns = errwarns;
@@ -112,6 +111,7 @@
/* Define valid preprocessors to use with this parser */
static const char *gas_parser_preproc_keywords[] = {
"raw",
+ "cpp",
NULL
};
diff --git a/modules/parsers/gas/gas-parser.h b/modules/parsers/gas/gas-parser.h
index 8d683e0..eece2a2 100644
--- a/modules/parsers/gas/gas-parser.h
+++ b/modules/parsers/gas/gas-parser.h
@@ -48,6 +48,7 @@
RIGHT_OP,
ID,
LABEL,
+ LINE_MARKER,
NONE
};
@@ -93,7 +94,6 @@
};
typedef struct yasm_parser_gas {
- FILE *in;
int debug;
/*@only@*/ yasm_object *object;
@@ -107,6 +107,9 @@
/*@null@*/ char *dir_file;
unsigned long dir_line;
+ /* Have we seen a line marker? */
+ int seen_line_marker;
+
/*@dependent@*/ yasm_preproc *preproc;
/*@dependent@*/ yasm_errwarns *errwarns;
diff --git a/modules/parsers/gas/gas-token.re b/modules/parsers/gas/gas-token.re
index c3b19e9..1251225 100644
--- a/modules/parsers/gas/gas-token.re
+++ b/modules/parsers/gas/gas-token.re
@@ -42,8 +42,8 @@
#define YYMARKER (s->ptr)
#define YYFILL(n) {cursor = fill(parser_gas, cursor);}
-#define RETURN(i) {s->cur = cursor; parser_gas->tokch = s->tok[0]; \
- return i;}
+#define RETURN(i) do {s->cur = cursor; parser_gas->tokch = s->tok[0]; \
+ return i;} while (0)
#define SCANINIT() {s->tok = cursor;}
@@ -445,7 +445,14 @@
}
"/*" { parser_gas->state = COMMENT; goto comment; }
- "#" (any \ [\n])* { goto scan; }
+ "#" {
+ if (strcmp(((yasm_preproc_base*)parser_gas->preproc)->module->keyword,
+ "cpp") == 0)
+ {
+ RETURN(LINE_MARKER);
+ } else
+ goto line_comment;
+ }
ws+ { goto scan; }
@@ -485,6 +492,12 @@
}
*/
+ /* Single line comment. */
+line_comment:
+ /*!re2c
+ (any \ [\n])* { goto scan; }
+ */
+
/* .section directive (the section name portion thereof) */
section_directive:
SCANINIT();
diff --git a/modules/parsers/nasm/nasm-parser.c b/modules/parsers/nasm/nasm-parser.c
index 8cdc63a..7138c9d 100644
--- a/modules/parsers/nasm/nasm-parser.c
+++ b/modules/parsers/nasm/nasm-parser.c
@@ -33,7 +33,7 @@
static void
-nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp, FILE *f,
+nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
int save_input, yasm_linemap *linemap,
yasm_errwarns *errwarns)
{
@@ -42,8 +42,6 @@
parser_nasm.object = object;
parser_nasm.linemap = linemap;
- parser_nasm.in = f;
-
parser_nasm.locallabel_base = (char *)NULL;
parser_nasm.locallabel_base_len = 0;
diff --git a/modules/parsers/nasm/nasm-parser.h b/modules/parsers/nasm/nasm-parser.h
index 4c8de41..2f14522 100644
--- a/modules/parsers/nasm/nasm-parser.h
+++ b/modules/parsers/nasm/nasm-parser.h
@@ -81,7 +81,6 @@
#define YYSTYPE yystype
typedef struct yasm_parser_nasm {
- FILE *in;
int debug;
/*@only@*/ yasm_object *object;
diff --git a/modules/preprocs/Makefile.inc b/modules/preprocs/Makefile.inc
index 0414558..8d3f7cf 100644
--- a/modules/preprocs/Makefile.inc
+++ b/modules/preprocs/Makefile.inc
@@ -2,6 +2,8 @@
EXTRA_DIST += modules/preprocs/nasm/Makefile.inc
EXTRA_DIST += modules/preprocs/raw/Makefile.inc
+EXTRA_DIST += modules/preprocs/cpp/Makefile.inc
include modules/preprocs/nasm/Makefile.inc
include modules/preprocs/raw/Makefile.inc
+include modules/preprocs/cpp/Makefile.inc
diff --git a/modules/preprocs/cpp/Makefile.inc b/modules/preprocs/cpp/Makefile.inc
new file mode 100644
index 0000000..30bd24b
--- /dev/null
+++ b/modules/preprocs/cpp/Makefile.inc
@@ -0,0 +1,6 @@
+# Makefile for cpp module.
+# Copied from raw preprocessor module.
+
+libyasm_a_SOURCES += modules/preprocs/cpp/cpp-preproc.c
+
+YASM_MODULES += preproc_cpp
diff --git a/modules/preprocs/cpp/cpp-preproc.c b/modules/preprocs/cpp/cpp-preproc.c
new file mode 100644
index 0000000..c28e6e6
--- /dev/null
+++ b/modules/preprocs/cpp/cpp-preproc.c
@@ -0,0 +1,356 @@
+/*
+ * Invoke an external C preprocessor
+ *
+ * Copyright (C) 2007 Paul Barker
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <util.h>
+#include <libyasm.h>
+
+/* TODO: Use autoconf to get the limit on the command line length. */
+#define CMDLINE_SIZE 32770
+
+/* Pre-declare the preprocessor module object. */
+yasm_preproc_module yasm_cpp_LTX_preproc;
+
+/*******************************************************************************
+ Structures.
+*******************************************************************************/
+
+/* An entry in a list of arguments to pass to cpp. */
+typedef struct cpp_arg_entry {
+ TAILQ_ENTRY(cpp_arg_entry) entry;
+
+ /*
+ The operator (eg "-I") and the parameter (eg "include/"). op is expected
+ to point to a string literal, whereas param is expected to be a copy of
+ the parameter which is free'd when no-longer needed (in
+ cpp_preproc_destroy()).
+ */
+ const char *op;
+ char *param;
+} cpp_arg_entry;
+
+typedef struct yasm_preproc_cpp {
+ yasm_preproc_base preproc; /* base structure */
+
+ /* List of arguments to pass to cpp. */
+ TAILQ_HEAD(, cpp_arg_entry) cpp_args;
+
+ char *filename;
+ FILE *f, *f_deps;
+ yasm_linemap *cur_lm;
+ yasm_errwarns *errwarns;
+
+ int flags;
+} yasm_preproc_cpp;
+
+/* Flag values for yasm_preproc_cpp->flags. */
+#define CPP_HAS_BEEN_INVOKED 0x01
+#define CPP_HAS_GENERATED_DEPS 0x02
+
+/*******************************************************************************
+ Internal functions and helpers.
+*******************************************************************************/
+
+/*
+ Append a string to the command line, ensuring that we don't overflow the
+ buffer.
+*/
+#define APPEND(s) do { \
+ size_t _len = strlen(s); \
+ if (p + _len >= limit) \
+ yasm__fatal(N_("command line too long!")); \
+ strcpy(p, s); \
+ p += _len; \
+} while (0)
+
+/*
+ Put all the options together into a command line that can be used to invoke
+ cpp.
+*/
+static char *
+cpp_build_cmdline(yasm_preproc_cpp *pp, const char *extra)
+{
+ char *cmdline, *p, *limit;
+ cpp_arg_entry *arg;
+
+ /*
+ Initialize command line. We can assume there will be enough space to
+ store "cpp".
+ */
+ cmdline = p = yasm_xmalloc(CMDLINE_SIZE);
+ limit = p + CMDLINE_SIZE;
+ strcpy(p, "cpp");
+ p += 3;
+
+ arg = TAILQ_FIRST(&pp->cpp_args);
+
+ /* Append arguments from the list. */
+ while ( arg ) {
+ APPEND(" ");
+ APPEND(arg->op);
+ APPEND(" ");
+ APPEND(arg->param);
+
+ arg = TAILQ_NEXT(arg, entry);
+ }
+
+ /* Append extra arguments. */
+ if (extra) {
+ APPEND(" ");
+ APPEND(extra);
+ }
+ /* Append final arguments. */
+ APPEND(" -x assembler-with-cpp ");
+ APPEND(pp->filename);
+
+ return cmdline;
+}
+
+/* Invoke the c preprocessor. */
+static void
+cpp_invoke(yasm_preproc_cpp *pp)
+{
+ char *cmdline;
+
+ cmdline = cpp_build_cmdline(pp, NULL);
+
+ pp->f = popen(cmdline, "r");
+ if (!pp->f)
+ yasm__fatal( N_("Failed to execute preprocessor") );
+
+ yasm_xfree(cmdline);
+}
+
+/* Free memory used by the list of arguments. */
+static void
+cpp_destroy_args(yasm_preproc_cpp *pp)
+{
+ cpp_arg_entry *arg;
+
+ while ( (arg = TAILQ_FIRST(&pp->cpp_args)) ) {
+ TAILQ_REMOVE(&pp->cpp_args, arg, entry);
+ yasm_xfree(arg->param);
+ yasm_xfree(arg);
+ }
+}
+
+/* Invoke the c preprocessor to generate dependency info. */
+static void
+cpp_generate_deps(yasm_preproc_cpp *pp)
+{
+ char *cmdline;
+
+ cmdline = cpp_build_cmdline(pp, "-M");
+
+ pp->f_deps = popen(cmdline, "r");
+ if (!pp->f_deps)
+ yasm__fatal( N_("Failed to execute preprocessor") );
+
+ yasm_xfree(cmdline);
+}
+
+/*******************************************************************************
+ Interface functions.
+*******************************************************************************/
+static yasm_preproc *
+cpp_preproc_create(const char *in, yasm_linemap *lm, yasm_errwarns *errwarns)
+{
+ yasm_preproc_cpp *pp = yasm_xmalloc(sizeof(yasm_preproc_cpp));
+ void * iter;
+ const char * inc_dir;
+
+ pp->preproc.module = &yasm_cpp_LTX_preproc;
+ pp->f = pp->f_deps = NULL;
+ pp->cur_lm = lm;
+ pp->errwarns = errwarns;
+ pp->flags = 0;
+ pp->filename = yasm__xstrdup(in);
+
+ TAILQ_INIT(&pp->cpp_args);
+
+ /* Iterate through the list of include dirs. */
+ iter = NULL;
+ while ((inc_dir = yasm_get_include_dir(&iter)) != NULL) {
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-I";
+ arg->param = yasm__xstrdup(inc_dir);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+ }
+
+ return (yasm_preproc *)pp;
+}
+
+static void
+cpp_preproc_destroy(yasm_preproc *preproc)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ if (pp->f) {
+ if (pclose(pp->f) != 0)
+ yasm__fatal( N_("Preprocessor exited with failure") );
+ }
+
+ cpp_destroy_args(pp);
+
+ yasm_xfree(pp->filename);
+ yasm_xfree(pp);
+}
+
+static size_t
+cpp_preproc_input(yasm_preproc *preproc, char *buf, size_t max_size)
+{
+ size_t n;
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ if (! (pp->flags & CPP_HAS_BEEN_INVOKED) ) {
+ pp->flags |= CPP_HAS_BEEN_INVOKED;
+
+ cpp_invoke(pp);
+ }
+
+ /*
+ Once the preprocessor has been run, we're just dealing with a normal
+ file.
+ */
+ if (((n = fread(buf, 1, max_size, pp->f)) == 0) &&
+ ferror(pp->f)) {
+ yasm_error_set(YASM_ERROR_IO, N_("error reading from pipe"));
+ yasm_errwarn_propagate(pp->errwarns,
+ yasm_linemap_get_current(pp->cur_lm));
+ }
+
+ return n;
+}
+
+static size_t
+cpp_preproc_get_included_file(yasm_preproc *preproc, char *buf,
+ size_t max_size)
+{
+ char *p = buf;
+ int ch = '\0';
+ size_t n = 0;
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ if (! (pp->flags & CPP_HAS_GENERATED_DEPS) ) {
+ pp->flags |= CPP_HAS_GENERATED_DEPS;
+
+ cpp_generate_deps(pp);
+
+ /* Skip target name and first dependency. */
+ while (ch != ':')
+ ch = fgetc(pp->f_deps);
+
+ fgetc(pp->f_deps); /* Discard space after colon. */
+
+ while (ch != ' ' && ch != EOF)
+ ch = fgetc(pp->f_deps);
+
+ if (ch == EOF)
+ return 0;
+ }
+
+ while (n < max_size) {
+ ch = fgetc(pp->f_deps);
+
+ if (ch == ' ' || ch == EOF) {
+ *p = '\0';
+ return n;
+ }
+
+ /* Eat any silly characters. */
+ if (ch < ' ')
+ continue;
+
+ *p++ = ch;
+ n++;
+ }
+
+ /* Ensure the buffer is null-terminated. */
+ *(p - 1) = '\0';
+ return n;
+}
+
+static void
+cpp_preproc_add_include_file(yasm_preproc *preproc, const char *filename)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-include";
+ arg->param = yasm__xstrdup(filename);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+}
+
+static void
+cpp_preproc_predefine_macro(yasm_preproc *preproc, const char *macronameval)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-D";
+ arg->param = yasm__xstrdup(macronameval);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+}
+
+static void
+cpp_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-U";
+ arg->param = yasm__xstrdup(macroname);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+}
+
+static void
+cpp_preproc_define_builtin(yasm_preproc *preproc, const char *macronameval)
+{
+ /* Handle a builtin as if it were a predefine. */
+ cpp_preproc_predefine_macro(preproc, macronameval);
+}
+
+/*******************************************************************************
+ Preprocessor module object.
+*******************************************************************************/
+
+yasm_preproc_module yasm_cpp_LTX_preproc = {
+ "Run input through enternal C preprocessor",
+ "cpp",
+ cpp_preproc_create,
+ cpp_preproc_destroy,
+ cpp_preproc_input,
+ cpp_preproc_get_included_file,
+ cpp_preproc_add_include_file,
+ cpp_preproc_predefine_macro,
+ cpp_preproc_undefine_macro,
+ cpp_preproc_define_builtin
+};
diff --git a/modules/preprocs/nasm/nasm-preproc.c b/modules/preprocs/nasm/nasm-preproc.c
index 9670026..78993b5 100644
--- a/modules/preprocs/nasm/nasm-preproc.c
+++ b/modules/preprocs/nasm/nasm-preproc.c
@@ -128,13 +128,22 @@
}
static yasm_preproc *
-nasm_preproc_create(FILE *f, const char *in_filename, yasm_linemap *lm,
+nasm_preproc_create(const char *in_filename, yasm_linemap *lm,
yasm_errwarns *errwarns)
{
+ FILE *f;
yasm_preproc_nasm *preproc_nasm = yasm_xmalloc(sizeof(yasm_preproc_nasm));
preproc_nasm->preproc.module = &yasm_nasm_LTX_preproc;
+ if (strcmp(in_filename, "-") != 0) {
+ f = fopen(in_filename, "r");
+ if (!f)
+ yasm__fatal( N_("Could not open input file") );
+ }
+ else
+ f = stdin;
+
preproc_nasm->in = f;
cur_lm = lm;
cur_errwarns = errwarns;
diff --git a/modules/preprocs/raw/raw-preproc.c b/modules/preprocs/raw/raw-preproc.c
index 4e80cff..869cbec 100644
--- a/modules/preprocs/raw/raw-preproc.c
+++ b/modules/preprocs/raw/raw-preproc.c
@@ -44,11 +44,20 @@
int isatty(int);
static yasm_preproc *
-raw_preproc_create(FILE *f, const char *in_filename, yasm_linemap *lm,
+raw_preproc_create(const char *in_filename, yasm_linemap *lm,
yasm_errwarns *errwarns)
{
+ FILE *f;
yasm_preproc_raw *preproc_raw = yasm_xmalloc(sizeof(yasm_preproc_raw));
+ if (strcmp(in_filename, "-") != 0) {
+ f = fopen(in_filename, "r");
+ if (!f)
+ yasm__fatal( N_("Could not open input file") );
+ }
+ else
+ f = stdin;
+
preproc_raw->preproc.module = &yasm_raw_LTX_preproc;
preproc_raw->in = f;
preproc_raw->cur_lm = lm;
diff --git a/modules/preprocs/yapp/yapp-preproc.c b/modules/preprocs/yapp/yapp-preproc.c
index c775644..e1215a7 100644
--- a/modules/preprocs/yapp/yapp-preproc.c
+++ b/modules/preprocs/yapp/yapp-preproc.c
@@ -241,11 +241,20 @@
expand_token_list(struct source_head *paramexp, struct source_head *to_head, source **to_tail);
static yasm_preproc *
-yapp_preproc_create(FILE *f, const char *in_filename, yasm_linemap *lm,
+yapp_preproc_create(const char *in_filename, yasm_linemap *lm,
yasm_errwarns *errwarns)
{
+ FILE *f;
yasm_preproc_yapp *preproc_yapp = yasm_xmalloc(sizeof(yasm_preproc_yapp));
+ if (strcmp(in_filename, "-") != 0) {
+ f = fopen(in_filename, "r");
+ if (!f)
+ yasm__fatal( N_("Could not open input file") );
+ }
+ else
+ f = stdin;
+
preproc_yapp->preproc.module = &yasm_yapp_LTX_preproc;
yapp_preproc_linemap = lm;
@@ -468,7 +477,7 @@
return 0;
append_token(token, to_head, to_tail);
token = yapp_preproc_lex();
- }
+ }
return '\n';
}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4dc46a9..34438fa 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,7 +6,6 @@
frontends/yasm/yasm-options.c
frontends/yasm/yasm.c
-#lc3bid.c
libyasm/bc-align.c
libyasm/bc-data.c
libyasm/bc-incbin.c
@@ -23,10 +22,11 @@
libyasm/intnum.c
libyasm/section.c
libyasm/symrec.c
+libyasm/valparam.c
libyasm/value.c
libyasm/xmalloc.c
-#modules/arch/lc3b/lc3barch.c
-#modules/arch/lc3b/lc3bbc.c
+modules/arch/lc3b/lc3barch.c
+modules/arch/lc3b/lc3bbc.c
modules/arch/x86/x86arch.c
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
@@ -54,5 +54,8 @@
modules/parsers/gas/gas-token.re
modules/parsers/nasm/nasm-parse.c
modules/parsers/nasm/nasm-token.re
+modules/preprocs/cpp/cpp-preproc.c
+modules/preprocs/yapp/yapp-preproc.c
+modules/preprocs/nasm/nasm-preproc.c
modules/preprocs/nasm/nasm-pp.c
modules/preprocs/raw/raw-preproc.c