]> granicus.if.org Git - yasm/commitdiff
Revamp object format functional interface a bit. Now, only the output()
authorPeter Johnson <peter@tortall.net>
Wed, 27 Feb 2002 05:43:16 +0000 (05:43 -0000)
committerPeter Johnson <peter@tortall.net>
Wed, 27 Feb 2002 05:43:16 +0000 (05:43 -0000)
function gets a FILE *, and it's the only function that can write to a file.
The object file is thus not opened until AFTER parsing and most error checking
is complete.  Necessitated adding a special case for the dbg object format
because it needs to output to the "object" (debug) file from essentially every
function.  Added a global (debug_file) to support this.

svn path=/trunk/yasm/; revision=476

12 files changed:
frontends/yasm/yasm.c
libyasm/linemgr.c
libyasm/linemgr.h
libyasm/objfmt.h
modules/objfmts/dbg/dbg-objfmt.c
src/globals.c
src/globals.h
src/linemgr.c
src/linemgr.h
src/main.c
src/objfmt.h
src/objfmts/dbg/dbg-objfmt.c

index df46632c1e46db1a1f1863f87f87ee8d7c95ed28..87f1fea542d7d9902ade2a96edc9c82a9196c4e4 100644 (file)
@@ -51,6 +51,9 @@ static int files_open = 0;
 /*@null@*/ static FILE *in = NULL, *obj = NULL;
 static int special_options = 0;
 
+static int open_obj(void);
+static void cleanup(sectionhead *sections);
+
 /* Forward declarations: cmd line parser handlers */
 static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_format_handler(char *cmd, /*@null@*/ char *param, int extra);
@@ -154,12 +157,10 @@ main(int argc, char *argv[])
     /* Set x86 as the architecture */
     cur_arch = &x86_arch;
 
-    /* Set dbg as the object format */
-    cur_objfmt = find_objfmt("dbg");
-    if (!cur_objfmt) {
-       ErrorNow(_("unrecognized output format `%s'"), "dbg");
-       return EXIT_FAILURE;
-    }
+    /* If not already specified, default to dbg as the object format. */
+    if (!cur_objfmt)
+       cur_objfmt = find_objfmt("dbg");
+    assert(cur_objfmt != NULL);
 
     /* open the object file if not specified */
     if (!obj) {
@@ -170,17 +171,19 @@ main(int argc, char *argv[])
        /* replace (or add) extension */
        obj_filename = replace_extension(in_filename, cur_objfmt->extension,
                                         "yasm.out");
+    }
 
-       /* open the built filename */
-       obj = fopen(obj_filename, "wb");
-       if (!obj) {
-           ErrorNow(_("could not open file `%s'"), obj_filename);
+    /* Pre-open the object file as debug_file if we're using a debug-type
+     * format.  (This is so the format can output ALL function call info).
+     */
+    if (strcmp(cur_objfmt->keyword, "dbg") == 0) {
+       if (!open_obj())
            return EXIT_FAILURE;
-       }
+       debug_file = obj;
     }
 
     /* Initialize the object format */
-    cur_objfmt->initialize(obj);
+    cur_objfmt->initialize(in_filename, obj_filename);
 
     /* Set NASM as the parser */
     cur_parser = find_parser("nasm");
@@ -200,53 +203,69 @@ main(int argc, char *argv[])
        xfree(in_filename);
 
     if (OutputAllErrorWarning() > 0) {
-       sections_delete(sections);
-       symrec_delete_all();
-       line_shutdown();
-       floatnum_shutdown();
-       intnum_shutdown();
-       BitVector_Shutdown();
+       cleanup(sections);
        return EXIT_FAILURE;
     }
 
-    /* XXX  Only for temporary debugging! */
-    fprintf(obj, "\nSections after parsing:\n");
-    indent_level++;
-    sections_print(obj, sections);
-    indent_level--;
-
-    fprintf(obj, "\nSymbol Table:\n");
-    indent_level++;
-    symrec_print_all(obj);
-    indent_level--;
-
     symrec_parser_finalize();
     basic_optimizer.optimize(sections);
 
     if (OutputAllErrorWarning() > 0) {
-       sections_delete(sections);
-       symrec_delete_all();
-       line_shutdown();
-       floatnum_shutdown();
-       intnum_shutdown();
-       BitVector_Shutdown();
+       cleanup(sections);
        return EXIT_FAILURE;
     }
 
-    fprintf(obj, "\nSections after optimization:\n");
-    indent_level++;
-    sections_print(obj, sections);
-    indent_level--;
+    /* open the object file for output (if not already opened above) */
+    if (!debug_file) {
+       if (!open_obj())
+           return EXIT_FAILURE;
+    }
+
+    /* Write the object file */
+    cur_objfmt->output(obj, sections);
 
     /* Finalize the object output */
-    cur_objfmt->finalize();
+    cur_objfmt->cleanup();
 
     if (obj != stdout)
        fclose(obj);
 
+    /* If we had an error at this point, we also need to delete the output
+     * object file (to make sure it's not left newer than the source).
+     */
+    if (OutputAllErrorWarning() > 0) {
+       cleanup(sections);
+       if (obj != stdout)
+           remove(obj_filename);
+       return EXIT_FAILURE;
+    }
+
     if (obj_filename)
        xfree(obj_filename);
 
+    cleanup(sections);
+    return EXIT_SUCCESS;
+}
+/*@=globstate =unrecog@*/
+
+/* Open the object file.  Returns 0 on failure. */
+static int
+open_obj(void)
+{
+    if (obj != stdout) {
+       obj = fopen(obj_filename, "wb");
+       if (!obj) {
+           ErrorNow(_("could not open file `%s'"), obj_filename);
+           return 0;
+       }
+    }
+    return 1;
+}
+
+/* Cleans up all allocated structures. */
+static void
+cleanup(sectionhead *sections)
+{
     sections_delete(sections);
     symrec_delete_all();
     line_shutdown();
@@ -255,9 +274,7 @@ main(int argc, char *argv[])
     intnum_shutdown();
 
     BitVector_Shutdown();
-    return EXIT_SUCCESS;
 }
-/*@=globstate =unrecog@*/
 
 /*
  *  Command line options handlers
@@ -296,7 +313,11 @@ static int
 opt_format_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
 {
     assert(param != NULL);
-    printf("selected format: %s\n", param);
+    cur_objfmt = find_objfmt(param);
+    if (!cur_objfmt) {
+       ErrorNow(_("unrecognized object format `%s'"), param);
+       return 1;
+    }
     return 0;
 }
 
@@ -305,22 +326,22 @@ opt_objfile_handler(/*@unused@*/ char *cmd, char *param,
                    /*@unused@*/ int extra)
 {
     assert(param != NULL);
-    if (strcasecmp(param, "stdout") == 0)
+    if (strcmp(param, "-") == 0)
        obj = stdout;
-    else if (strcasecmp(param, "stderr") == 0)
-       obj = stderr;
     else {
        if (obj) {
            WarningNow("can open only one output file, last specified used");
-           if (obj != stdout && obj != stderr && fclose(obj))
+           if (obj != stdout && fclose(obj))
                ErrorNow("could not close old output file");
        }
     }
 
-    obj = fopen(param, "wb");
-    if (!obj) {
-       ErrorNow(_("could not open file `%s'"), param);
-       return 1;
+    if (obj != stdout) {
+       obj = fopen(param, "wb");
+       if (!obj) {
+           ErrorNow(_("could not open file `%s'"), param);
+           return 1;
+       }
     }
 
     if (obj_filename)
index f91a26f34dd1a37acca68f4f57057f4ff7f8689c..0e90638f478a1543b409cf65f83298b3ce66bd17 100644 (file)
 #include "globals.h"
 
 
+/* Output file for debugging-type formats.  This is so that functions that are
+ * called before the object file is usually opened can still write data out to
+ * it (whereas for "normal" formats the object file is not opened until later
+ * in the assembly process).  Opening the file early is special-cased in
+ * main().
+ */
+/*@null@*/ FILE *debug_file = NULL;
+
 /* Current (selected) parser */
 /*@null@*/ parser *cur_parser = NULL;
 
index 54ffec47e99d9c295f28ba318b7456f786a24ce0..72b693752cc65334fe27b168c0f6f44cc8eaae9d 100644 (file)
 #ifndef YASM_GLOBALS_H
 #define YASM_GLOBALS_H
 
+/* Output file for debugging-type formats.  This is so that functions that are
+ * called before the object file is usually opened can still write data out to
+ * it (whereas for "normal" formats the object file is not opened until later
+ * in the assembly process).  Opening the file early is special-cased in
+ * main().
+ */
+extern /*@null@*/ FILE *debug_file;
+
 /* Current (selected) parser */
 extern /*@null@*/ parser *cur_parser;
 
index d0e7750ba3ab05410b4686727f3f5024b80e5f23..ae409a006a611036948f11ba12e2d67b28b0a682 100644 (file)
@@ -50,12 +50,19 @@ struct objfmt {
 /*    debugfmt *default_df;*/
 
     /* Initializes object output.  Must be called before any other object
-     * format functions.
+     * format functions.  Should NOT open the object file; the filenames are
+     * provided solely for informational purposes.
      */
-    void (*initialize) (/*@dependent@*/ FILE *f);
+    void (*initialize) (const char *in_filename, const char *obj_filename);
 
-    /* Finishes object output, and cleans up anything created by initialize. */
-    void (*finalize) (void);
+    /* Write out (post-optimized) sections to the object file.
+     * This function may call symrec functions as necessary (including
+     * symrec_traverse) to retrieve symbolic information.
+     */
+    void (*output) (FILE *f, sectionhead *sections);
+
+    /* Cleans up anything allocated by initialize. */
+    void (*cleanup) (void);
 
     /* Switch object file sections.  The first val of the valparams should
      * be the section name.  Returns NULL if something's wrong, otherwise
index aa58ca364e342c8f3c78609d695534482a31fe05..9866b67d00dd916fb6d98e108f6edb45e6f2d7d9 100644 (file)
 #include "objfmt.h"
 
 
-/*@dependent@*/ FILE *dbg_f;
+/* Note that the functions here write to debug_file.  This is NOT legal for
+ * other object formats to do--only the output() function can write to a file,
+ * and only the file it's passed in its f parameter!
+ */
+
+static void
+dbg_objfmt_initialize(const char *in_filename, const char *obj_filename)
+{
+    fprintf(debug_file, "%*sinitialize(\"%s\", \"%s\")\n", indent_level, "",
+           in_filename, obj_filename);
+}
 
 static void
-dbg_objfmt_initialize(/*@dependent@*/ FILE *f)
+dbg_objfmt_output(FILE *f, sectionhead *sections)
 {
-    dbg_f = f;
-    fprintf(dbg_f, "%*sinitialize(f)\n", indent_level, "");
+    fprintf(f, "%*soutput(f, sections->\n", indent_level, "");
+    indent_level++;
+    sections_print(f, sections);
+    indent_level--;
+    fprintf(f, "%*s)\n", indent_level, "");
+    indent_level++;
+    fprintf(f, "%*sSymbol Table:\n", indent_level, "");
+    symrec_print_all(f);
+    indent_level--;
 }
 
 static void
-dbg_objfmt_finalize(void)
+dbg_objfmt_cleanup(void)
 {
-    fprintf(dbg_f, "%*sfinalize()\n", indent_level, "");
+    fprintf(debug_file, "%*scleanup()\n", indent_level, "");
 }
 
 static /*@dependent@*/ /*@null@*/ section *
@@ -55,22 +72,22 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
     section *retval;
     int isnew;
 
-    fprintf(dbg_f, "%*ssections_switch(headp, ", indent_level, "");
-    vps_print(dbg_f, valparams);
-    fprintf(dbg_f, ", ");
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning ");
+    fprintf(debug_file, "%*ssections_switch(headp, ", indent_level, "");
+    vps_print(debug_file, valparams);
+    fprintf(debug_file, ", ");
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning ");
 
     if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) {
        retval = sections_switch_general(headp, vp->val, NULL, 0, &isnew);
        if (isnew) {
-           fprintf(dbg_f, "(new) ");
+           fprintf(debug_file, "(new) ");
            symrec_define_label(vp->val, retval, (bytecode *)NULL, 1);
        }
-       fprintf(dbg_f, "\"%s\" section\n", vp->val);
+       fprintf(debug_file, "\"%s\" section\n", vp->val);
        return retval;
     } else {
-       fprintf(dbg_f, "NULL\n");
+       fprintf(debug_file, "NULL\n");
        return NULL;
     }
 }
@@ -78,7 +95,7 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
 static void
 dbg_objfmt_section_data_delete(/*@only@*/ void *data)
 {
-    fprintf(dbg_f, "%*ssection_data_delete(%p)\n", indent_level, "", data);
+    fprintf(debug_file, "%*ssection_data_delete(%p)\n", indent_level, "", data);
     xfree(data);
 }
 
@@ -95,9 +112,9 @@ static /*@null@*/ void *
 dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/
                           valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*sextern_data_new(\"%s\", ", indent_level, "", name);
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning NULL\n");
+    fprintf(debug_file, "%*sextern_data_new(\"%s\", ", indent_level, "", name);
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning NULL\n");
     return NULL;
 }
 
@@ -105,9 +122,9 @@ static /*@null@*/ void *
 dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/
                           valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*sglobal_data_new(\"%s\", ", indent_level, "", name);
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning NULL\n");
+    fprintf(debug_file, "%*sglobal_data_new(\"%s\", ", indent_level, "", name);
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning NULL\n");
     return NULL;
 }
 
@@ -116,13 +133,13 @@ dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size,
                           /*@unused@*/ /*@null@*/
                           valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*scommon_data_new(\"%s\", ", indent_level, "", name);
-    expr_print(dbg_f, size);
-    fprintf(dbg_f, ", ");
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning ");
-    expr_print(dbg_f, size);
-    fprintf(dbg_f, "\n");
+    fprintf(debug_file, "%*scommon_data_new(\"%s\", ", indent_level, "", name);
+    expr_print(debug_file, size);
+    fprintf(debug_file, ", ");
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning ");
+    expr_print(debug_file, size);
+    fprintf(debug_file, "\n");
     return size;
 }
 
@@ -131,29 +148,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data)
 {
     void *retval;
 
-    fprintf(dbg_f, "%*sdeclare_data_copy(", indent_level, "");
+    fprintf(debug_file, "%*sdeclare_data_copy(", indent_level, "");
     switch (vis) {
        case SYM_LOCAL:
-           fprintf(dbg_f, "Local, ");
+           fprintf(debug_file, "Local, ");
            break;
        case SYM_GLOBAL:
-           fprintf(dbg_f, "Global, ");
+           fprintf(debug_file, "Global, ");
            break;
        case SYM_COMMON:
-           fprintf(dbg_f, "Common, ");
+           fprintf(debug_file, "Common, ");
            break;
        case SYM_EXTERN:
-           fprintf(dbg_f, "Extern, ");
+           fprintf(debug_file, "Extern, ");
            break;
     }
     if (vis == SYM_COMMON) {
-       expr_print(dbg_f, data);
+       expr_print(debug_file, data);
        retval = expr_copy(data);
     } else {
-       fprintf(dbg_f, "%p", data);
+       fprintf(debug_file, "%p", data);
        InternalError(_("Trying to copy unrecognized objfmt data"));
     }
-    fprintf(dbg_f, "), returning copy\n");
+    fprintf(debug_file, "), returning copy\n");
 
     return retval;
 }
@@ -161,29 +178,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data)
 static void
 dbg_objfmt_declare_data_delete(SymVisibility vis, /*@only@*/ void *data)
 {
-    fprintf(dbg_f, "%*sdeclare_data_delete(", indent_level, "");
+    fprintf(debug_file, "%*sdeclare_data_delete(", indent_level, "");
     switch (vis) {
        case SYM_LOCAL:
-           fprintf(dbg_f, "Local, ");
+           fprintf(debug_file, "Local, ");
            break;
        case SYM_GLOBAL:
-           fprintf(dbg_f, "Global, ");
+           fprintf(debug_file, "Global, ");
            break;
        case SYM_COMMON:
-           fprintf(dbg_f, "Common, ");
+           fprintf(debug_file, "Common, ");
            break;
        case SYM_EXTERN:
-           fprintf(dbg_f, "Extern, ");
+           fprintf(debug_file, "Extern, ");
            break;
     }
     if (vis == SYM_COMMON) {
-       expr_print(dbg_f, data);
+       expr_print(debug_file, data);
        expr_delete(data);
     } else {
-       fprintf(dbg_f, "%p", data);
+       fprintf(debug_file, "%p", data);
        xfree(data);
     }
-    fprintf(dbg_f, ")\n");
+    fprintf(debug_file, ")\n");
 }
 
 static void
@@ -203,11 +220,11 @@ static int
 dbg_objfmt_directive(const char *name, valparamhead *valparams,
                     /*@null@*/ valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*sdirective(\"%s\", ", indent_level, "", name);
-    vps_print(dbg_f, valparams);
-    fprintf(dbg_f, ", ");
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning 0 (recognized)\n");
+    fprintf(debug_file, "%*sdirective(\"%s\", ", indent_level, "", name);
+    vps_print(debug_file, valparams);
+    fprintf(debug_file, ", ");
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning 0 (recognized)\n");
     return 0;      /* dbg format "recognizes" all directives */
 }
 
@@ -219,7 +236,8 @@ objfmt dbg_objfmt = {
     ".text",
     32,
     dbg_objfmt_initialize,
-    dbg_objfmt_finalize,
+    dbg_objfmt_output,
+    dbg_objfmt_cleanup,
     dbg_objfmt_sections_switch,
     dbg_objfmt_section_data_delete,
     dbg_objfmt_section_data_print,
index f91a26f34dd1a37acca68f4f57057f4ff7f8689c..0e90638f478a1543b409cf65f83298b3ce66bd17 100644 (file)
 #include "globals.h"
 
 
+/* Output file for debugging-type formats.  This is so that functions that are
+ * called before the object file is usually opened can still write data out to
+ * it (whereas for "normal" formats the object file is not opened until later
+ * in the assembly process).  Opening the file early is special-cased in
+ * main().
+ */
+/*@null@*/ FILE *debug_file = NULL;
+
 /* Current (selected) parser */
 /*@null@*/ parser *cur_parser = NULL;
 
index 54ffec47e99d9c295f28ba318b7456f786a24ce0..72b693752cc65334fe27b168c0f6f44cc8eaae9d 100644 (file)
 #ifndef YASM_GLOBALS_H
 #define YASM_GLOBALS_H
 
+/* Output file for debugging-type formats.  This is so that functions that are
+ * called before the object file is usually opened can still write data out to
+ * it (whereas for "normal" formats the object file is not opened until later
+ * in the assembly process).  Opening the file early is special-cased in
+ * main().
+ */
+extern /*@null@*/ FILE *debug_file;
+
 /* Current (selected) parser */
 extern /*@null@*/ parser *cur_parser;
 
index f91a26f34dd1a37acca68f4f57057f4ff7f8689c..0e90638f478a1543b409cf65f83298b3ce66bd17 100644 (file)
 #include "globals.h"
 
 
+/* Output file for debugging-type formats.  This is so that functions that are
+ * called before the object file is usually opened can still write data out to
+ * it (whereas for "normal" formats the object file is not opened until later
+ * in the assembly process).  Opening the file early is special-cased in
+ * main().
+ */
+/*@null@*/ FILE *debug_file = NULL;
+
 /* Current (selected) parser */
 /*@null@*/ parser *cur_parser = NULL;
 
index 54ffec47e99d9c295f28ba318b7456f786a24ce0..72b693752cc65334fe27b168c0f6f44cc8eaae9d 100644 (file)
 #ifndef YASM_GLOBALS_H
 #define YASM_GLOBALS_H
 
+/* Output file for debugging-type formats.  This is so that functions that are
+ * called before the object file is usually opened can still write data out to
+ * it (whereas for "normal" formats the object file is not opened until later
+ * in the assembly process).  Opening the file early is special-cased in
+ * main().
+ */
+extern /*@null@*/ FILE *debug_file;
+
 /* Current (selected) parser */
 extern /*@null@*/ parser *cur_parser;
 
index df46632c1e46db1a1f1863f87f87ee8d7c95ed28..87f1fea542d7d9902ade2a96edc9c82a9196c4e4 100644 (file)
@@ -51,6 +51,9 @@ static int files_open = 0;
 /*@null@*/ static FILE *in = NULL, *obj = NULL;
 static int special_options = 0;
 
+static int open_obj(void);
+static void cleanup(sectionhead *sections);
+
 /* Forward declarations: cmd line parser handlers */
 static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_format_handler(char *cmd, /*@null@*/ char *param, int extra);
@@ -154,12 +157,10 @@ main(int argc, char *argv[])
     /* Set x86 as the architecture */
     cur_arch = &x86_arch;
 
-    /* Set dbg as the object format */
-    cur_objfmt = find_objfmt("dbg");
-    if (!cur_objfmt) {
-       ErrorNow(_("unrecognized output format `%s'"), "dbg");
-       return EXIT_FAILURE;
-    }
+    /* If not already specified, default to dbg as the object format. */
+    if (!cur_objfmt)
+       cur_objfmt = find_objfmt("dbg");
+    assert(cur_objfmt != NULL);
 
     /* open the object file if not specified */
     if (!obj) {
@@ -170,17 +171,19 @@ main(int argc, char *argv[])
        /* replace (or add) extension */
        obj_filename = replace_extension(in_filename, cur_objfmt->extension,
                                         "yasm.out");
+    }
 
-       /* open the built filename */
-       obj = fopen(obj_filename, "wb");
-       if (!obj) {
-           ErrorNow(_("could not open file `%s'"), obj_filename);
+    /* Pre-open the object file as debug_file if we're using a debug-type
+     * format.  (This is so the format can output ALL function call info).
+     */
+    if (strcmp(cur_objfmt->keyword, "dbg") == 0) {
+       if (!open_obj())
            return EXIT_FAILURE;
-       }
+       debug_file = obj;
     }
 
     /* Initialize the object format */
-    cur_objfmt->initialize(obj);
+    cur_objfmt->initialize(in_filename, obj_filename);
 
     /* Set NASM as the parser */
     cur_parser = find_parser("nasm");
@@ -200,53 +203,69 @@ main(int argc, char *argv[])
        xfree(in_filename);
 
     if (OutputAllErrorWarning() > 0) {
-       sections_delete(sections);
-       symrec_delete_all();
-       line_shutdown();
-       floatnum_shutdown();
-       intnum_shutdown();
-       BitVector_Shutdown();
+       cleanup(sections);
        return EXIT_FAILURE;
     }
 
-    /* XXX  Only for temporary debugging! */
-    fprintf(obj, "\nSections after parsing:\n");
-    indent_level++;
-    sections_print(obj, sections);
-    indent_level--;
-
-    fprintf(obj, "\nSymbol Table:\n");
-    indent_level++;
-    symrec_print_all(obj);
-    indent_level--;
-
     symrec_parser_finalize();
     basic_optimizer.optimize(sections);
 
     if (OutputAllErrorWarning() > 0) {
-       sections_delete(sections);
-       symrec_delete_all();
-       line_shutdown();
-       floatnum_shutdown();
-       intnum_shutdown();
-       BitVector_Shutdown();
+       cleanup(sections);
        return EXIT_FAILURE;
     }
 
-    fprintf(obj, "\nSections after optimization:\n");
-    indent_level++;
-    sections_print(obj, sections);
-    indent_level--;
+    /* open the object file for output (if not already opened above) */
+    if (!debug_file) {
+       if (!open_obj())
+           return EXIT_FAILURE;
+    }
+
+    /* Write the object file */
+    cur_objfmt->output(obj, sections);
 
     /* Finalize the object output */
-    cur_objfmt->finalize();
+    cur_objfmt->cleanup();
 
     if (obj != stdout)
        fclose(obj);
 
+    /* If we had an error at this point, we also need to delete the output
+     * object file (to make sure it's not left newer than the source).
+     */
+    if (OutputAllErrorWarning() > 0) {
+       cleanup(sections);
+       if (obj != stdout)
+           remove(obj_filename);
+       return EXIT_FAILURE;
+    }
+
     if (obj_filename)
        xfree(obj_filename);
 
+    cleanup(sections);
+    return EXIT_SUCCESS;
+}
+/*@=globstate =unrecog@*/
+
+/* Open the object file.  Returns 0 on failure. */
+static int
+open_obj(void)
+{
+    if (obj != stdout) {
+       obj = fopen(obj_filename, "wb");
+       if (!obj) {
+           ErrorNow(_("could not open file `%s'"), obj_filename);
+           return 0;
+       }
+    }
+    return 1;
+}
+
+/* Cleans up all allocated structures. */
+static void
+cleanup(sectionhead *sections)
+{
     sections_delete(sections);
     symrec_delete_all();
     line_shutdown();
@@ -255,9 +274,7 @@ main(int argc, char *argv[])
     intnum_shutdown();
 
     BitVector_Shutdown();
-    return EXIT_SUCCESS;
 }
-/*@=globstate =unrecog@*/
 
 /*
  *  Command line options handlers
@@ -296,7 +313,11 @@ static int
 opt_format_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
 {
     assert(param != NULL);
-    printf("selected format: %s\n", param);
+    cur_objfmt = find_objfmt(param);
+    if (!cur_objfmt) {
+       ErrorNow(_("unrecognized object format `%s'"), param);
+       return 1;
+    }
     return 0;
 }
 
@@ -305,22 +326,22 @@ opt_objfile_handler(/*@unused@*/ char *cmd, char *param,
                    /*@unused@*/ int extra)
 {
     assert(param != NULL);
-    if (strcasecmp(param, "stdout") == 0)
+    if (strcmp(param, "-") == 0)
        obj = stdout;
-    else if (strcasecmp(param, "stderr") == 0)
-       obj = stderr;
     else {
        if (obj) {
            WarningNow("can open only one output file, last specified used");
-           if (obj != stdout && obj != stderr && fclose(obj))
+           if (obj != stdout && fclose(obj))
                ErrorNow("could not close old output file");
        }
     }
 
-    obj = fopen(param, "wb");
-    if (!obj) {
-       ErrorNow(_("could not open file `%s'"), param);
-       return 1;
+    if (obj != stdout) {
+       obj = fopen(param, "wb");
+       if (!obj) {
+           ErrorNow(_("could not open file `%s'"), param);
+           return 1;
+       }
     }
 
     if (obj_filename)
index d0e7750ba3ab05410b4686727f3f5024b80e5f23..ae409a006a611036948f11ba12e2d67b28b0a682 100644 (file)
@@ -50,12 +50,19 @@ struct objfmt {
 /*    debugfmt *default_df;*/
 
     /* Initializes object output.  Must be called before any other object
-     * format functions.
+     * format functions.  Should NOT open the object file; the filenames are
+     * provided solely for informational purposes.
      */
-    void (*initialize) (/*@dependent@*/ FILE *f);
+    void (*initialize) (const char *in_filename, const char *obj_filename);
 
-    /* Finishes object output, and cleans up anything created by initialize. */
-    void (*finalize) (void);
+    /* Write out (post-optimized) sections to the object file.
+     * This function may call symrec functions as necessary (including
+     * symrec_traverse) to retrieve symbolic information.
+     */
+    void (*output) (FILE *f, sectionhead *sections);
+
+    /* Cleans up anything allocated by initialize. */
+    void (*cleanup) (void);
 
     /* Switch object file sections.  The first val of the valparams should
      * be the section name.  Returns NULL if something's wrong, otherwise
index aa58ca364e342c8f3c78609d695534482a31fe05..9866b67d00dd916fb6d98e108f6edb45e6f2d7d9 100644 (file)
 #include "objfmt.h"
 
 
-/*@dependent@*/ FILE *dbg_f;
+/* Note that the functions here write to debug_file.  This is NOT legal for
+ * other object formats to do--only the output() function can write to a file,
+ * and only the file it's passed in its f parameter!
+ */
+
+static void
+dbg_objfmt_initialize(const char *in_filename, const char *obj_filename)
+{
+    fprintf(debug_file, "%*sinitialize(\"%s\", \"%s\")\n", indent_level, "",
+           in_filename, obj_filename);
+}
 
 static void
-dbg_objfmt_initialize(/*@dependent@*/ FILE *f)
+dbg_objfmt_output(FILE *f, sectionhead *sections)
 {
-    dbg_f = f;
-    fprintf(dbg_f, "%*sinitialize(f)\n", indent_level, "");
+    fprintf(f, "%*soutput(f, sections->\n", indent_level, "");
+    indent_level++;
+    sections_print(f, sections);
+    indent_level--;
+    fprintf(f, "%*s)\n", indent_level, "");
+    indent_level++;
+    fprintf(f, "%*sSymbol Table:\n", indent_level, "");
+    symrec_print_all(f);
+    indent_level--;
 }
 
 static void
-dbg_objfmt_finalize(void)
+dbg_objfmt_cleanup(void)
 {
-    fprintf(dbg_f, "%*sfinalize()\n", indent_level, "");
+    fprintf(debug_file, "%*scleanup()\n", indent_level, "");
 }
 
 static /*@dependent@*/ /*@null@*/ section *
@@ -55,22 +72,22 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
     section *retval;
     int isnew;
 
-    fprintf(dbg_f, "%*ssections_switch(headp, ", indent_level, "");
-    vps_print(dbg_f, valparams);
-    fprintf(dbg_f, ", ");
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning ");
+    fprintf(debug_file, "%*ssections_switch(headp, ", indent_level, "");
+    vps_print(debug_file, valparams);
+    fprintf(debug_file, ", ");
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning ");
 
     if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) {
        retval = sections_switch_general(headp, vp->val, NULL, 0, &isnew);
        if (isnew) {
-           fprintf(dbg_f, "(new) ");
+           fprintf(debug_file, "(new) ");
            symrec_define_label(vp->val, retval, (bytecode *)NULL, 1);
        }
-       fprintf(dbg_f, "\"%s\" section\n", vp->val);
+       fprintf(debug_file, "\"%s\" section\n", vp->val);
        return retval;
     } else {
-       fprintf(dbg_f, "NULL\n");
+       fprintf(debug_file, "NULL\n");
        return NULL;
     }
 }
@@ -78,7 +95,7 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
 static void
 dbg_objfmt_section_data_delete(/*@only@*/ void *data)
 {
-    fprintf(dbg_f, "%*ssection_data_delete(%p)\n", indent_level, "", data);
+    fprintf(debug_file, "%*ssection_data_delete(%p)\n", indent_level, "", data);
     xfree(data);
 }
 
@@ -95,9 +112,9 @@ static /*@null@*/ void *
 dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/
                           valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*sextern_data_new(\"%s\", ", indent_level, "", name);
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning NULL\n");
+    fprintf(debug_file, "%*sextern_data_new(\"%s\", ", indent_level, "", name);
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning NULL\n");
     return NULL;
 }
 
@@ -105,9 +122,9 @@ static /*@null@*/ void *
 dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/
                           valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*sglobal_data_new(\"%s\", ", indent_level, "", name);
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning NULL\n");
+    fprintf(debug_file, "%*sglobal_data_new(\"%s\", ", indent_level, "", name);
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning NULL\n");
     return NULL;
 }
 
@@ -116,13 +133,13 @@ dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size,
                           /*@unused@*/ /*@null@*/
                           valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*scommon_data_new(\"%s\", ", indent_level, "", name);
-    expr_print(dbg_f, size);
-    fprintf(dbg_f, ", ");
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning ");
-    expr_print(dbg_f, size);
-    fprintf(dbg_f, "\n");
+    fprintf(debug_file, "%*scommon_data_new(\"%s\", ", indent_level, "", name);
+    expr_print(debug_file, size);
+    fprintf(debug_file, ", ");
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning ");
+    expr_print(debug_file, size);
+    fprintf(debug_file, "\n");
     return size;
 }
 
@@ -131,29 +148,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data)
 {
     void *retval;
 
-    fprintf(dbg_f, "%*sdeclare_data_copy(", indent_level, "");
+    fprintf(debug_file, "%*sdeclare_data_copy(", indent_level, "");
     switch (vis) {
        case SYM_LOCAL:
-           fprintf(dbg_f, "Local, ");
+           fprintf(debug_file, "Local, ");
            break;
        case SYM_GLOBAL:
-           fprintf(dbg_f, "Global, ");
+           fprintf(debug_file, "Global, ");
            break;
        case SYM_COMMON:
-           fprintf(dbg_f, "Common, ");
+           fprintf(debug_file, "Common, ");
            break;
        case SYM_EXTERN:
-           fprintf(dbg_f, "Extern, ");
+           fprintf(debug_file, "Extern, ");
            break;
     }
     if (vis == SYM_COMMON) {
-       expr_print(dbg_f, data);
+       expr_print(debug_file, data);
        retval = expr_copy(data);
     } else {
-       fprintf(dbg_f, "%p", data);
+       fprintf(debug_file, "%p", data);
        InternalError(_("Trying to copy unrecognized objfmt data"));
     }
-    fprintf(dbg_f, "), returning copy\n");
+    fprintf(debug_file, "), returning copy\n");
 
     return retval;
 }
@@ -161,29 +178,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data)
 static void
 dbg_objfmt_declare_data_delete(SymVisibility vis, /*@only@*/ void *data)
 {
-    fprintf(dbg_f, "%*sdeclare_data_delete(", indent_level, "");
+    fprintf(debug_file, "%*sdeclare_data_delete(", indent_level, "");
     switch (vis) {
        case SYM_LOCAL:
-           fprintf(dbg_f, "Local, ");
+           fprintf(debug_file, "Local, ");
            break;
        case SYM_GLOBAL:
-           fprintf(dbg_f, "Global, ");
+           fprintf(debug_file, "Global, ");
            break;
        case SYM_COMMON:
-           fprintf(dbg_f, "Common, ");
+           fprintf(debug_file, "Common, ");
            break;
        case SYM_EXTERN:
-           fprintf(dbg_f, "Extern, ");
+           fprintf(debug_file, "Extern, ");
            break;
     }
     if (vis == SYM_COMMON) {
-       expr_print(dbg_f, data);
+       expr_print(debug_file, data);
        expr_delete(data);
     } else {
-       fprintf(dbg_f, "%p", data);
+       fprintf(debug_file, "%p", data);
        xfree(data);
     }
-    fprintf(dbg_f, ")\n");
+    fprintf(debug_file, ")\n");
 }
 
 static void
@@ -203,11 +220,11 @@ static int
 dbg_objfmt_directive(const char *name, valparamhead *valparams,
                     /*@null@*/ valparamhead *objext_valparams)
 {
-    fprintf(dbg_f, "%*sdirective(\"%s\", ", indent_level, "", name);
-    vps_print(dbg_f, valparams);
-    fprintf(dbg_f, ", ");
-    vps_print(dbg_f, objext_valparams);
-    fprintf(dbg_f, "), returning 0 (recognized)\n");
+    fprintf(debug_file, "%*sdirective(\"%s\", ", indent_level, "", name);
+    vps_print(debug_file, valparams);
+    fprintf(debug_file, ", ");
+    vps_print(debug_file, objext_valparams);
+    fprintf(debug_file, "), returning 0 (recognized)\n");
     return 0;      /* dbg format "recognizes" all directives */
 }
 
@@ -219,7 +236,8 @@ objfmt dbg_objfmt = {
     ".text",
     32,
     dbg_objfmt_initialize,
-    dbg_objfmt_finalize,
+    dbg_objfmt_output,
+    dbg_objfmt_cleanup,
     dbg_objfmt_sections_switch,
     dbg_objfmt_section_data_delete,
     dbg_objfmt_section_data_print,