]> granicus.if.org Git - yasm/commitdiff
Initial version of cpp module (on multiarch branch).
authorpaulbarker <paulbarker@localhost>
Wed, 29 Aug 2007 11:33:05 +0000 (11:33 -0000)
committerpaulbarker <paulbarker@localhost>
Wed, 29 Aug 2007 11:33:05 +0000 (11:33 -0000)
svn path=/branches/multiarch/; revision=1916

modules/parsers/gas/gas-parser.c
modules/preprocs/Makefile.inc
modules/preprocs/cpp/Makefile.inc [new file with mode: 0644]
modules/preprocs/cpp/cpp-preproc.c [new file with mode: 0644]

index 9cc61382e237826f8bb402b56c52d4e0f751d397..df51dc5991ddf626597383707c13f39d3a199ce0 100644 (file)
@@ -112,6 +112,7 @@ gas_parser_do_parse(yasm_object *object, yasm_preproc *pp, FILE *f,
 /* Define valid preprocessors to use with this parser */
 static const char *gas_parser_preproc_keywords[] = {
     "raw",
+    "cpp",
     NULL
 };
 
index 041455814cfa68589413c6f103448f4b28542bb2..8d3f7cfd9a3a4f9ca2f98f16c367abed64f9cedc 100644 (file)
@@ -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 (file)
index 0000000..30bd24b
--- /dev/null
@@ -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 (file)
index 0000000..bd0f4a4
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * 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: Find some non-arbitrary values for these constants. */
+#define TMP_BUF_SIZE 4096
+#define CMDLINE_SIZE 32770
+
+extern int isatty(int);
+
+/* Flags. */
+#define CPP_HAS_BEEN_INVOKED 0x01
+
+typedef struct cpp_arg_entry {
+    TAILQ_ENTRY(cpp_arg_entry) entry;
+
+    char *op;
+    char *param;
+} cpp_arg_entry;
+
+typedef struct yasm_preproc_cpp {
+    yasm_preproc_base preproc;   /* base structure */
+
+    TAILQ_HEAD(, cpp_arg_entry) cpp_args;
+    cpp_arg_entry *pos;
+
+    FILE *f_in, *f_out;
+    yasm_linemap *cur_lm;
+    yasm_errwarns *errwarns;
+
+    int flags;
+} yasm_preproc_cpp;
+
+yasm_preproc_module yasm_cpp_LTX_preproc;
+
+/* TODO: Make these filenames safer and more portable, maybe using tmpnam()? */
+static const char *in_filename = ".cpp.in";
+static const char *out_filename = ".cpp.out";
+
+/* Invoke the c preprocessor. */
+static void
+cpp_invoke(yasm_preproc_cpp *pp)
+{
+    int r;
+    char *cmdline, *p, *limit, *tmp;
+    cpp_arg_entry *arg;
+    size_t op_len, param_len, sz;
+
+    /* Initialize command line. */
+    cmdline = p = yasm_xmalloc(CMDLINE_SIZE);
+    limit = p + CMDLINE_SIZE;
+    strcpy(p, "cpp");
+    p += 3;
+
+    /* Append arguments from the list. */
+    TAILQ_FOREACH(arg, (&pp->cpp_args), entry) {
+        /*
+            We need a space before arg->op and a space before arg->param, so
+            2 extra characters.
+        */
+        op_len = strlen(arg->op);
+        param_len = strlen(arg->param);
+        sz = op_len + param_len + 2;
+
+        if (p + sz >= limit)
+            yasm__fatal("command line too long");
+
+        *p++ = ' ';
+        strcpy(p, arg->op);
+        p += op_len;
+        *p++ = ' ';
+        strcpy(p, arg->param);
+        p += param_len;
+
+        yasm_xfree(arg->param);
+    }
+
+    /* Append final arguments. */
+    r = asprintf(&tmp, " -x assembler-with-cpp -o %s %s",
+                      out_filename, in_filename);
+    if (r == -1)
+        yasm__fatal("failed to construct command line for cpp");
+
+    /* r is the length of the string stored in tmp. */
+    if (p + r + 1 >= limit)
+        yasm__fatal("command line too long");
+
+    strcpy(p, tmp);
+    yasm_xfree(tmp);
+    p += r;
+    *p = '\0';
+
+#if 0
+    /* Print the command line before executing. */
+    printf("%s\n", cmdline);
+#endif
+    r = system(cmdline);
+    if (r)
+        yasm__fatal("C preprocessor failed");
+
+    yasm_xfree(cmdline);
+}
+
+static yasm_preproc *
+cpp_preproc_create(FILE *f, const char *in, yasm_linemap *lm,
+                   yasm_errwarns *errwarns)
+{
+    yasm_preproc_cpp *pp = yasm_xmalloc(sizeof(yasm_preproc_cpp));
+
+    pp->preproc.module = &yasm_cpp_LTX_preproc;
+    pp->f_in = f;
+    pp->f_out = NULL;
+    pp->cur_lm = lm;
+    pp->errwarns = errwarns;
+    pp->flags = 0;
+
+    pp->pos = NULL;
+    TAILQ_INIT(&pp->cpp_args);
+
+    return (yasm_preproc *)pp;
+}
+
+static void
+cpp_preproc_destroy(yasm_preproc *preproc)
+{
+    yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+    if (pp->f_out) {
+        fclose(pp->f_out);
+    }
+
+    /* Remove both temporary files. */
+    remove(in_filename);
+    remove(out_filename);
+
+    yasm_xfree(preproc);
+}
+
+static size_t
+cpp_preproc_input(yasm_preproc *preproc, char *buf, size_t max_size)
+{
+    size_t n;
+    FILE *f_tmp;
+    int tty;
+    char *tmp_buf;
+    yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+    if (! (pp->flags & CPP_HAS_BEEN_INVOKED) ) {
+        pp->flags |= CPP_HAS_BEEN_INVOKED;
+
+        tmp_buf = (char *)yasm_xmalloc(TMP_BUF_SIZE);
+
+        f_tmp = fopen(in_filename, "w");
+
+        tty = (isatty(fileno(f_tmp)) > 0);
+        while (!feof(pp->f_in)) {
+            if (tty) {
+                /* TODO: Handle reading from tty into tmp_buf. */
+                yasm__fatal("incapable of reading from a tty");
+            } else {
+                if (((n = fread(tmp_buf, 1, TMP_BUF_SIZE, pp->f_in)) == 0) &&
+                        ferror(pp->f_in)) {
+                    yasm_error_set(YASM_ERROR_IO,
+                                   N_("error when reading from input file"));
+                    yasm_errwarn_propagate(pp->errwarns,
+                                          yasm_linemap_get_current(pp->cur_lm));
+                }
+            }
+
+            if (fwrite(tmp_buf, 1, n, f_tmp) != n) {
+                yasm__fatal("error writing to temporary file");
+            }
+        }
+
+        yasm_xfree(tmp_buf);
+        fclose(f_tmp);
+
+        cpp_invoke(pp);
+
+        pp->f_out = fopen(out_filename, "r");
+
+        if (!pp->f_out) {
+            yasm__fatal("Could not open preprocessed file \"%s\"", out_filename);
+        }
+    }
+
+    /*
+        Once the preprocessor has been run, we're just dealing with a normal
+        file.
+    */
+    if (((n = fread(buf, 1, max_size, pp->f_out)) == 0) &&
+               ferror(pp->f_out)) {
+        yasm_error_set(YASM_ERROR_IO, N_("error when reading from preprocessed file"));
+        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)
+{
+    /* TODO */
+
+    return 0;
+}
+
+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);
+}
+
+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
+};
+
+/*
+    TODO: We will need to pass the list of include directories to the external
+            preprocessor.
+*/