]> granicus.if.org Git - yasm/commitdiff
First part of list file support. This should accurately output all file
authorPeter Johnson <peter@tortall.net>
Sat, 2 Oct 2004 06:18:30 +0000 (06:18 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 2 Oct 2004 06:18:30 +0000 (06:18 -0000)
bytes and offsets, but relocations are not yet indicated.  Also, this
outputs post-preprocessed source, so no comments, etc, are visible in the
list file.

* listfmt.h: New header file describing listfmt module interface.
* coretype.h: Declare new yasm_listfmt typedef.
* libyasm.h: Include listfmt.h.
* libyasm/Makefile.inc (modinclude_HEADERS): Add listfmt.h.

* yasm-module.h (module_type): Add MODULE_LISTFMT for listfmts.
(load_listfmt_module, list_listfmts): New macros for listfmts.
* yasm-module.c (module_type_str): Add listfmt string for MODULE_LISTFMT.
(list_module_load): Add support for MODULE_LISTFMT.

* bytecode.h (yasm_bc_tobytes): Comment clarification on effect of calling
yasm_bc_tobytes twice on the same bytecode.

* linemgr.h: Replace support for associated data with support for bytecode
and source line information.
(yasm_linemap_get_data): Remove.
(yasm_linemap_get_source): Add.
(yasm_linemap_add_data): Remove.
(yasm_linemap_add_source): Add.
* linemgr.c (yasm_linemap, yasm_linemap_create, yasm_linemap_destroy)
(yasm_linemap_add_data, yasm_linemap_add_source, yasm_linemap_get_data)
(yasm_linemap_get_source): Likewise.

* nasm-token.re (fill): Save previous 2 lines instead of previous 1 line.
(destroy_line, print_line, line_assoc_data): Remove.
(save_line): Save line in structure instead of calling yasm_linemap_add_data.
* nasm-bison.y (input rule): Call yasm_linemap_add_source here.
* nasm-parser.h (yasm_parser_nasm): Add second line of storage and save_last
variable to toggle between the two lines.
* nasm-parser.c (nasm_parser_do_parse): Initialize save_last.

* modules/Makefile.inc: Include new modules/listfmts/Makefile.inc.
* modules/listfmts/Makefile.inc: New;
includes modules/listfmts/nasm/Makefile.inc.
* modules/listfmts/nasm/Makefile.inc: New build file for NASM-like listfmt.
* nasm-listfmt.c: New NASM-like listfmt.

* yasm.c: Enable use of listfmts, and default to NASM listfmt.
(list_filename, cur_listfmt, cur_listfmt_module): New listfmt variables.
(opt_listfmt_handler, opt_listfile_handler): New listfmt functions.
(options): Add --lformat (-L) and --list (-l) options.
(main): Load "nasm" listfmt as default if none selected.
Enable saving of input lines if list output file enabled.
Open and write to the list file.
(open_obj): Rename to open_file and make more generic.
(cleanup): Destroy listfmt and list filename if created.

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

18 files changed:
frontends/yasm/yasm-module.c
frontends/yasm/yasm-module.h
frontends/yasm/yasm.c
libyasm.h
libyasm/Makefile.inc
libyasm/bytecode.h
libyasm/coretype.h
libyasm/linemgr.c
libyasm/linemgr.h
libyasm/listfmt.h [new file with mode: 0644]
modules/Makefile.inc
modules/listfmts/Makefile.inc [new file with mode: 0644]
modules/listfmts/nasm/Makefile.inc [new file with mode: 0644]
modules/listfmts/nasm/nasm-listfmt.c [new file with mode: 0644]
modules/parsers/nasm/nasm-bison.y
modules/parsers/nasm/nasm-parser.c
modules/parsers/nasm/nasm-parser.h
modules/parsers/nasm/nasm-token.re

index 8833fda5b2ac4aa4d10a8c19df82f5c0b1ac5494..759cd1b54e09d276be82c29c8c99b6529a360e92 100644 (file)
@@ -53,6 +53,7 @@ static const char *module_type_str[] = {
     "arch",
     "dbgfmt",
     "objfmt",
+    "listfmt",
     "optimizer",
     "parser",
     "preproc"
@@ -158,6 +159,7 @@ list_module_load(const char *filename, lt_ptr data)
     yasm_arch_module *arch_module;
     yasm_dbgfmt_module *dbgfmt_module;
     yasm_objfmt_module *objfmt_module;
+    yasm_listfmt_module *listfmt_module;
     yasm_optimizer_module *optimizer_module;
     yasm_parser_module *parser_module;
     yasm_preproc_module *preproc_module;
@@ -219,6 +221,14 @@ list_module_load(const char *filename, lt_ptr data)
                module_name = objfmt_module->name;
            }
            break;
+       case MODULE_LISTFMT:
+           strncpy(name+3, "yasm", 4);
+           listfmt_module = lt_dlsym(handle, name+3);
+           if (listfmt_module) {
+               module_keyword = listfmt_module->keyword;
+               module_name = listfmt_module->name;
+           }
+           break;
        case MODULE_OPTIMIZER:
            strncpy(name+5, "yasm", 4);
            optimizer_module = lt_dlsym(handle, name+5);
index 64085707fd31de3247dac4473360489df198cf28..25042a773d76269ebf406806a3074d3d21f8ebc7 100644 (file)
@@ -31,6 +31,7 @@ typedef enum module_type {
     MODULE_ARCH = 0,
     MODULE_DBGFMT,
     MODULE_OBJFMT,
+    MODULE_LISTFMT,
     MODULE_OPTIMIZER,
     MODULE_PARSER,
     MODULE_PREPROC
@@ -46,6 +47,8 @@ void unload_modules(void);
     get_module_data(MODULE_DBGFMT, keyword, "dbgfmt")
 #define load_objfmt_module(keyword)    \
     get_module_data(MODULE_OBJFMT, keyword, "objfmt")
+#define load_listfmt_module(keyword)   \
+    get_module_data(MODULE_LISTFMT, keyword, "listfmt")
 #define load_optimizer_module(keyword) \
     get_module_data(MODULE_OPTIMIZER, keyword, "optimizer")
 #define load_parser_module(keyword)    \
@@ -59,6 +62,7 @@ void list_modules(module_type type,
 #define list_archs(func)       list_modules(MODULE_ARCH, func)
 #define list_dbgfmts(func)     list_modules(MODULE_DBGFMT, func)
 #define list_objfmts(func)     list_modules(MODULE_OBJFMT, func)
+#define list_listfmts(func)    list_modules(MODULE_LISTFMT, func)
 #define list_optimizers(func)  list_modules(MODULE_OPTIMIZER, func)
 #define list_parsers(func)     list_modules(MODULE_PARSER, func)
 #define list_preprocs(func)    list_modules(MODULE_PREPROC, func)
index 0d6a7767400eede7f9b47bb12e88571fe1c5b797..06f66c9cd3a83c5541b9ef7afec3f1b85098ded9 100644 (file)
@@ -65,6 +65,7 @@ do { \
 } while (0)
 
 /*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
+/*@null@*/ /*@only@*/ static char *list_filename = NULL;
 /*@null@*/ /*@only@*/ static char *machine_name = NULL;
 static int special_options = 0;
 /*@null@*/ /*@dependent@*/ static yasm_arch *cur_arch = NULL;
@@ -83,6 +84,9 @@ static int special_options = 0;
 /*@null@*/ /*@dependent@*/ static yasm_dbgfmt *cur_dbgfmt = NULL;
 /*@null@*/ /*@dependent@*/ static const yasm_dbgfmt_module *
     cur_dbgfmt_module = NULL;
+/*@null@*/ /*@dependent@*/ static yasm_listfmt *cur_listfmt = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_listfmt_module *
+    cur_listfmt_module = NULL;
 static int preproc_only = 0;
 static int warning_error = 0;  /* warnings being treated as errors */
 static enum {
@@ -90,7 +94,8 @@ static enum {
     EWSTYLE_VC
 } ewmsg_style = EWSTYLE_GNU;
 
-/*@null@*/ /*@dependent@*/ static FILE *open_obj(const char *mode);
+/*@null@*/ /*@dependent@*/ static FILE *open_file(const char *filename,
+                                                 const char *mode);
 static void cleanup(/*@null@*/ yasm_object *object);
 
 /* Forward declarations: cmd line parser handlers */
@@ -100,6 +105,8 @@ static int opt_parser_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_preproc_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_objfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_dbgfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listfile_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_objfile_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_machine_handler(char *cmd, /*@null@*/ char *param, int extra);
 static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
@@ -146,6 +153,10 @@ static opt_option options[] =
       N_("select object format (list with -f help)"), N_("format") },
     { 'g', "dformat", 1, opt_dbgfmt_handler, 0,
       N_("select debugging format (list with -g help)"), N_("debug") },
+    { 'L', "lformat", 1, opt_listfmt_handler, 0,
+      N_("select list format (list with -L help)"), N_("list") },
+    { 'l', "list", 1, opt_listfile_handler, 0,
+      N_("name of list-file output"), N_("listfile") },
     { 'o', "objfile", 1, opt_objfile_handler, 0,
       N_("name of object-file output"), N_("filename") },
     { 'm', "machine", 1, opt_machine_handler, 0,
@@ -351,7 +362,7 @@ main(int argc, char *argv[])
            obj = stdout;
        else {
            /* Open output (object) file */
-           obj = open_obj("wt");
+           obj = open_file(obj_filename, "wt");
            if (!obj) {
                yasm_xfree(preproc_buf);
                return EXIT_FAILURE;
@@ -449,6 +460,13 @@ main(int argc, char *argv[])
     }
     check_module_version(cur_optimizer_module, OPTIMIZER, optimizer);
 
+    /* If list file enabled, make sure we have a list format loaded. */
+    if (list_filename) {
+       /* If not already specified, default to nasm as the list format. */
+       if (!cur_listfmt_module)
+           cur_listfmt_module = load_listfmt_module("nasm");
+    }
+
     /* If not already specified, default to bin as the object format. */
     if (!cur_objfmt_module)
        cur_objfmt_module = load_objfmt_module("bin");
@@ -590,7 +608,7 @@ main(int argc, char *argv[])
 
     /* Parse! */
     cur_parser_module->do_parse(object, cur_preproc, cur_arch, cur_objfmt, in,
-                               in_filename, 0, def_sect);
+                               in_filename, list_filename != NULL, def_sect);
 
     /* Close input file */
     if (in != stdin)
@@ -618,7 +636,7 @@ main(int argc, char *argv[])
 
     /* open the object file for output (if not already opened by dbg objfmt) */
     if (!obj && strcmp(cur_objfmt_module->keyword, "dbg") != 0) {
-       obj = open_obj("wb");
+       obj = open_file(obj_filename, "wb");
        if (!obj) {
            cleanup(object);
            return EXIT_FAILURE;
@@ -644,6 +662,21 @@ main(int argc, char *argv[])
        return EXIT_FAILURE;
     }
 
+    /* Open and write the list file */
+    if (list_filename) {
+       FILE *list = open_file(list_filename, "wt");
+       if (!list) {
+           cleanup(object);
+           return EXIT_FAILURE;
+       }
+       /* Initialize the list format */
+       cur_listfmt = yasm_listfmt_create(cur_listfmt_module, in_filename,
+                                         obj_filename);
+       yasm_listfmt_output(cur_listfmt, list,
+                           yasm_object_get_linemap(object), cur_arch);
+       fclose(list);
+    }
+
     yasm_errwarn_output_all(yasm_object_get_linemap(object), warning_error,
                            print_yasm_error, print_yasm_warning);
 
@@ -654,16 +687,14 @@ main(int argc, char *argv[])
 
 /* Open the object file.  Returns 0 on failure. */
 static FILE *
-open_obj(const char *mode)
+open_file(const char *filename, const char *mode)
 {
-    FILE *obj;
+    FILE *f;
 
-    assert(obj_filename != NULL);
-
-    obj = fopen(obj_filename, mode);
-    if (!obj)
-       print_error(_("could not open file `%s'"), obj_filename);
-    return obj;
+    f = fopen(filename, mode);
+    if (!f)
+       print_error(_("could not open file `%s'"), filename);
+    return f;
 }
 
 /* Define DO_FREE to 1 to enable deallocation of all data structures.
@@ -681,6 +712,8 @@ cleanup(yasm_object *object)
            yasm_objfmt_destroy(cur_objfmt);
        if (cur_dbgfmt)
            yasm_dbgfmt_destroy(cur_dbgfmt);
+       if (cur_listfmt)
+           yasm_listfmt_destroy(cur_listfmt);
        if (cur_preproc)
            yasm_preproc_destroy(cur_preproc);
        if (object)
@@ -708,6 +741,8 @@ cleanup(yasm_object *object)
            yasm_xfree(in_filename);
        if (obj_filename)
            yasm_xfree(obj_filename);
+       if (list_filename)
+           yasm_xfree(list_filename);
        if (machine_name)
            yasm_xfree(machine_name);
     }
@@ -833,6 +868,42 @@ opt_dbgfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
     return 0;
 }
 
+static int
+opt_listfmt_handler(/*@unused@*/ char *cmd, char *param,
+                   /*@unused@*/ int extra)
+{
+    assert(param != NULL);
+    cur_listfmt_module = load_listfmt_module(param);
+    if (!cur_listfmt_module) {
+       if (!strcmp("help", param)) {
+           printf(_("Available yasm %s:\n"), _("list formats"));
+           list_listfmts(print_list_keyword_desc);
+           special_options = SPECIAL_LISTED;
+           return 0;
+       }
+       print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+                   _("list format"), param);
+       exit(EXIT_FAILURE);
+    }
+    return 0;
+}
+
+static int
+opt_listfile_handler(/*@unused@*/ char *cmd, char *param,
+                    /*@unused@*/ int extra)
+{
+    if (list_filename) {
+       print_error(
+           _("warning: can output to only one list file, last specified used"));
+       yasm_xfree(list_filename);
+    }
+
+    assert(param != NULL);
+    list_filename = yasm__xstrdup(param);
+
+    return 0;
+}
+
 static int
 opt_objfile_handler(/*@unused@*/ char *cmd, char *param,
                    /*@unused@*/ int extra)
index 3703850931eee1916d7045de1d0e8129fe0b5182..da5fa993368bb1a80d2860f89eb02d570bf86b38 100644 (file)
--- a/libyasm.h
+++ b/libyasm.h
@@ -68,6 +68,7 @@
 #include <libyasm/arch.h>
 #include <libyasm/dbgfmt.h>
 #include <libyasm/objfmt.h>
+#include <libyasm/listfmt.h>
 #include <libyasm/optimizer.h>
 #include <libyasm/parser.h>
 #include <libyasm/preproc.h>
index e85f195f145cb395afc7504f908af0f7a7e94fb8..86f9590ea9989e7632c542a1edb0e6baf36eb71d 100644 (file)
@@ -40,6 +40,7 @@ modinclude_HEADERS += libyasm/section.h
 modinclude_HEADERS += libyasm/arch.h
 modinclude_HEADERS += libyasm/dbgfmt.h
 modinclude_HEADERS += libyasm/objfmt.h
+modinclude_HEADERS += libyasm/listfmt.h
 modinclude_HEADERS += libyasm/optimizer.h
 modinclude_HEADERS += libyasm/parser.h
 modinclude_HEADERS += libyasm/preproc.h
index 720c19a1a0c935853a4e1c643ad14180eb543282..c4514811daec0380562a5cbcfbbebcaf280c5263 100644 (file)
@@ -226,8 +226,9 @@ yasm_bc_resolve_flags yasm_bc_resolve(yasm_bytecode *bc, int save,
  * \return Newly allocated buffer that should be used instead of buf for
  *        reading the byte representation, or NULL if buf was big enough to
  *        hold the entire byte representation.
- * \note Essentially destroys contents of bytecode, so it's \em not safe to
- *       call twice on the same bytecode.
+ * \note Calling twice on the same bytecode may \em not produce the same
+ *       results on the second call, as calling this function may result in
+ *       non-reversible changes to the bytecode.
  */
 /*@null@*/ /*@only@*/ unsigned char *yasm_bc_tobytes
     (yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
index 2e38ac8b179d49eff61df5989950bd178bc0b551..a1a39e1f25cfc6c968a24c544a62f85d3ad0d992 100644 (file)
@@ -46,6 +46,8 @@ typedef struct yasm_optimizer yasm_optimizer;
 typedef struct yasm_objfmt yasm_objfmt;
 /** Debug format interface.  \see dbgfmt.h for details. */
 typedef struct yasm_dbgfmt yasm_dbgfmt;
+/** List format interface.  \see listfmt.h for details. */
+typedef struct yasm_listfmt yasm_listfmt;
 
 /** YASM associated data callback structure.  Many data structures can have
  * arbitrary data associated with them.
index 059775175c6afff30c51ebc6f32cd7da92a64946..f92f1516fe2042f26a48c9fabaf085c03a296a6b 100644 (file)
@@ -55,16 +55,13 @@ typedef struct line_mapping {
     unsigned long line_inc;
 } line_mapping;
 
-typedef struct line_assoc_data_raw_head {
-    /*@only@*/ void **vector;
-    const yasm_assoc_data_callback *callback;
-    size_t size;
-} line_assoc_data_raw_head;
+typedef struct line_source_info {
+    /* first bytecode on line; NULL if no bytecodes on line */
+    /*@null@*/ /*@dependent@*/ yasm_bytecode *bc;
 
-typedef struct line_assoc_data {
-    /*@only@*/ void *data;
-    const yasm_assoc_data_callback *callback;
-} line_assoc_data;
+    /* source code line */
+    /*@owned@*/ char *source;
+} line_source_info;
 
 struct yasm_linemap {
     /* Shared storage for filenames */
@@ -76,12 +73,9 @@ struct yasm_linemap {
     /* Mappings from virtual to physical line numbers */
     /*@only@*/ /*@null@*/ line_mapping_head *map;
 
-    /* Associated data arrays for odd data types (those likely to have data
-     * associated for every line).
-     */
-    /*@null@*/ /*@only@*/ line_assoc_data_raw_head *assoc_data_array;
-    size_t assoc_data_array_size;
-    size_t assoc_data_array_alloc;
+    /* Bytecode and source line information */
+    /*@only@*/ line_source_info *source_info;
+    size_t source_info_size;
 };
 
 static void
@@ -138,11 +132,10 @@ yasm_linemap_create(void)
     linemap->map->size = 0;
     linemap->map->allocated = 8;
     
-    /* initialize associated data arrays */
-    linemap->assoc_data_array_size = 0;
-    linemap->assoc_data_array_alloc = 2;
-    linemap->assoc_data_array = yasm_xmalloc(linemap->assoc_data_array_alloc *
-                                            sizeof(line_assoc_data_raw_head));
+    /* initialize source line information array */
+    linemap->source_info_size = 2;
+    linemap->source_info = yasm_xmalloc(linemap->source_info_size *
+                                       sizeof(line_source_info));
 
     return linemap;
 }
@@ -150,21 +143,12 @@ yasm_linemap_create(void)
 void
 yasm_linemap_destroy(yasm_linemap *linemap)
 {
-    if (linemap->assoc_data_array) {
-       size_t i;
-       for (i=0; i<linemap->assoc_data_array_size; i++) {
-           line_assoc_data_raw_head *adrh = &linemap->assoc_data_array[i];
-           if (adrh->vector) {
-               size_t j;
-               for (j=0; j<adrh->size; j++) {
-                   if (adrh->vector[j])
-                       adrh->callback->destroy(adrh->vector[j]);
-               }
-               yasm_xfree(adrh->vector);
-           }
-       }
-       yasm_xfree(linemap->assoc_data_array);
+    size_t i;
+    for (i=0; i<linemap->source_info_size; i++) {
+       if (linemap->source_info[i].source)
+           yasm_xfree(linemap->source_info[i].source);
     }
+    yasm_xfree(linemap->source_info);
 
     if (linemap->map) {
        yasm_xfree(linemap->map->vector);
@@ -184,54 +168,28 @@ yasm_linemap_get_current(yasm_linemap *linemap)
 }
 
 void
-yasm_linemap_add_data(yasm_linemap *linemap,
-                     const yasm_assoc_data_callback *callback, void *data,
-                     /*@unused@*/ int every_hint)
+yasm_linemap_add_source(yasm_linemap *linemap, yasm_bytecode *bc,
+                       const char *source)
 {
-    /* FIXME: Hint not supported yet. */
-
-    line_assoc_data_raw_head *adrh = NULL;
     size_t i;
 
-    /* See if there's already associated data for this callback */
-    for (i=0; !adrh && i<linemap->assoc_data_array_size; i++) {
-       if (linemap->assoc_data_array[i].callback == callback)
-           adrh = &linemap->assoc_data_array[i];
-    }
-
-    /* No?  Then append a new one */
-    if (!adrh) {
-       linemap->assoc_data_array_size++;
-       if (linemap->assoc_data_array_size > linemap->assoc_data_array_alloc) {
-           linemap->assoc_data_array_alloc *= 2;
-           linemap->assoc_data_array =
-               yasm_xrealloc(linemap->assoc_data_array,
-                             linemap->assoc_data_array_alloc *
-                             sizeof(line_assoc_data_raw_head));
-       }
-       adrh = &linemap->assoc_data_array[linemap->assoc_data_array_size-1];
-
-       adrh->size = 4;
-       adrh->vector = yasm_xmalloc(adrh->size*sizeof(void *));
-       adrh->callback = callback;
-       for (i=0; i<adrh->size; i++)
-           adrh->vector[i] = NULL;
-    }
-
-    while (linemap->current > adrh->size) {
+    while (linemap->current > linemap->source_info_size) {
        /* allocate another size bins when full for 2x space */
-       adrh->vector = yasm_xrealloc(adrh->vector,
-                                    2*adrh->size*sizeof(void *));
-       for (i=adrh->size; i<adrh->size*2; i++)
-           adrh->vector[i] = NULL;
-       adrh->size *= 2;
+       linemap->source_info = yasm_xrealloc(linemap->source_info,
+           2*linemap->source_info_size*sizeof(line_source_info));
+       for (i=linemap->source_info_size; i<linemap->source_info_size*2; i++) {
+           linemap->source_info[i].bc = NULL;
+           linemap->source_info[i].source = NULL;
+       }
+       linemap->source_info_size *= 2;
     }
 
-    /* Delete existing data for that line (if any) */
-    if (adrh->vector[linemap->current-1])
-       adrh->callback->destroy(adrh->vector[linemap->current-1]);
+    /* Delete existing info for that line (if any) */
+    if (linemap->source_info[linemap->current-1].source)
+       yasm_xfree(linemap->source_info[linemap->current-1].source);
 
-    adrh->vector[linemap->current-1] = data;
+    linemap->source_info[linemap->current-1].bc = bc;
+    linemap->source_info[linemap->current-1].source = yasm__xstrdup(source);
 }
 
 unsigned long
@@ -268,24 +226,18 @@ yasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
     *file_line = mapping->file_line + mapping->line_inc*(line-mapping->line);
 }
 
-void *
-yasm_linemap_get_data(yasm_linemap *linemap, unsigned long line,
-                     const yasm_assoc_data_callback *callback)
+int
+yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
+                       yasm_bytecode **bcp, const char **sourcep)
 {
-    line_assoc_data_raw_head *adrh = NULL;
-    size_t i;
-
-    /* Linear search through data array */
-    for (i=0; !adrh && i<linemap->assoc_data_array_size; i++) {
-       if (linemap->assoc_data_array[i].callback == callback)
-           adrh = &linemap->assoc_data_array[i];
+    if (line > linemap->source_info_size) {
+       *bcp = NULL;
+       *sourcep = NULL;
+       return 1;
     }
 
-    if (!adrh)
-       return NULL;
-    
-    if (line > adrh->size)
-       return NULL;
+    *bcp = linemap->source_info[line-1].bc;
+    *sourcep = linemap->source_info[line-1].source;
 
-    return adrh->vector[line-1];
+    return (!(*sourcep));
 }
index e30501a1d8ebd5b8682b04394842f2cf7c8c3ebc..1beffc0e3fbf7f9429c5f5bc24c1a77dc63c6f46 100644 (file)
@@ -50,28 +50,30 @@ void yasm_linemap_destroy(yasm_linemap *linemap);
  */
 unsigned long yasm_linemap_get_current(yasm_linemap *linemap);
 
-/** Get associated data for a virtual line and data callback.
+/** Get bytecode and source line information, if any, for a virtual line.
  * \param linemap      line mapping repository
  * \param line         virtual line
- * \param callback     callback used when adding data
- * \return Associated data (NULL if none).
+ * \param bcp          pointer to return bytecode into
+ * \param sourcep      pointer to return source code line pointer into
+ * \return Zero if source line information available for line, nonzero if not.
+ * \note If source line information is not available, bcp and sourcep targets
+ * are set to NULL.
  */
-/*@dependent@*/ /*@null@*/ void *yasm_linemap_get_data
-    (yasm_linemap *linemap, unsigned long line,
-     const yasm_assoc_data_callback *callback);
+int yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
+                           /*@null@*/ yasm_bytecode **bcp,
+                           const char **sourcep);
 
-/** Add associated data to the current virtual line.
- * \attention Deletes any existing associated data for that data callback for
- *           the current virtual line.
+/** Add bytecode and source line information to the current virtual line.
+ * \attention Deletes any existing bytecode and source line information for
+ *            the current virtual line.
  * \param linemap      line mapping repository
- * \param callback     callback
- * \param data         data to associate
- * \param every_hint   non-zero if data is likely to be associated with every
- *                     line; zero if not.
+ * \param bc           bytecode (if any)
+ * \param source       source code line
+ * \note The source code line pointer is NOT kept, it is strdup'ed.
  */
-void yasm_linemap_add_data(yasm_linemap *linemap,
-                          const yasm_assoc_data_callback *callback,
-                          /*@only@*/ /*@null@*/ void *data, int every_hint);
+void yasm_linemap_add_source(yasm_linemap *linemap,
+                            /*@null@*/ yasm_bytecode *bc,
+                            const char *source);
 
 /** Go to the next line (increments the current virtual line)l
  * \param linemap      line mapping repository
diff --git a/libyasm/listfmt.h b/libyasm/listfmt.h
new file mode 100644 (file)
index 0000000..7abd92d
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ * \file libyasm/listfmt.h
+ * \brief YASM list format interface.
+ *
+ * \rcs
+ * $Id$
+ * \endrcs
+ *
+ * \license
+ *  Copyright (C) 2004  Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - 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.
+ * \endlicense
+ */
+#ifndef YASM_LISTFMT_H
+#define YASM_LISTFMT_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_listfmt structure.  Must be present as the first element in any
+ * #yasm_listfmt implementation.
+ */
+typedef struct yasm_listfmt_base {
+    /** #yasm_listfmt_module implementation for this list format. */
+    const struct yasm_listfmt_module *module;
+} yasm_listfmt_base;
+#endif
+
+/** Version number of #yasm_listfmt_module interface.  Any functional change
+ * to the #yasm_listfmt_module interface should simultaneously increment this
+ * number.  This version should be checked by #yasm_listfmt loaders to verify
+ * that the expected version (the version defined by its libyasm header files)
+ * matches the loaded module version (the version defined by the module's
+ * libyasm header files).  Doing this will ensure that the module version's
+ * function definitions match the module loader's function definitions.  The
+ * version number must never be decreased.
+ */
+#define YASM_LISTFMT_VERSION   0
+
+/** YASM list format module interface. */
+typedef struct yasm_listfmt_module {
+    /** Version (see #YASM_LISTFMT_VERSION).  Should always be set to
+     * #YASM_LISTFMT_VERSION by the module source and checked against
+     * #YASM_LISTFMT_VERSION by the module loader.
+     */
+    unsigned int version;
+
+    /** One-line description of the list format. */
+    const char *name;
+
+    /** Keyword used to select list format. */
+    const char *keyword;
+
+    /** Create list format.
+     * Module-level implementation of yasm_listfmt_create().
+     * The filenames are provided solely for informational purposes.
+     * \param in_filename   primary input filename
+     * \param obj_filename  object filename
+     * \return NULL if unable to initialize.
+     */
+    /*@null@*/ /*@only@*/ yasm_listfmt * (*create)
+       (const char *in_filename, const char *obj_filename);
+
+    /** Module-level implementation of yasm_listfmt_destroy().
+     * Call yasm_listfmt_destroy() instead of calling this function.
+     */
+    void (*destroy) (/*@only@*/ yasm_listfmt *listfmt);
+
+    /** Module-level implementation of yasm_listfmt_output().
+     * Call yasm_listfmt_output() instead of calling this function.
+     */
+    void (*output) (yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
+                   yasm_arch *arch);
+} yasm_listfmt_module;
+
+/** Get the keyword used to select a list format.
+ * \param listfmt   list format
+ * \return keyword
+ */
+const char *yasm_listfmt_keyword(const yasm_listfmt *listfmt);
+
+/** Initialize list format for use.  Must call before any other list
+ * format functions.  The filenames are provided solely for informational
+ * purposes.
+ * \param module       list format module
+ * \param in_filename   primary input filename
+ * \param obj_filename  object filename
+ * \return NULL if object format does not provide needed support.
+ */
+/*@null@*/ /*@only@*/ yasm_listfmt *yasm_listfmt_create
+    (const yasm_listfmt_module *module, const char *in_filename,
+     const char *obj_filename);
+
+/** Cleans up any allocated list format memory.
+ * \param listfmt      list format
+ */
+void yasm_listfmt_destroy(/*@only@*/ yasm_listfmt *listfmt);
+
+/** Write out list to the list file.
+ * This function may call all read-only yasm_* functions as necessary.
+ * \param listfmt      list format
+ * \param f            output list file
+ * \param linemap      line mapping repository
+ * \param arch         architecture
+ */
+void yasm_listfmt_output(yasm_listfmt *listfmt, FILE *f,
+                        yasm_linemap *linemap, yasm_arch *arch);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for listfmt functions */
+
+#define yasm_listfmt_keyword(listfmt) \
+    (((yasm_listfmt_base *)listfmt)->module->keyword)
+
+#define yasm_listfmt_create(module, in_filename, obj_filename) \
+    module->create(in_filename, obj_filename)
+
+#define yasm_listfmt_destroy(listfmt) \
+    ((yasm_listfmt_base *)listfmt)->module->destroy(listfmt)
+
+#define yasm_listfmt_output(listfmt, f, linemap, a) \
+    ((yasm_listfmt_base *)listfmt)->module->output(listfmt, f, linemap, a)
+
+#endif
+
+#endif
index b1240d2d9e592624552349c7b9ed209bbad73352..d78ef5e0ad78501629a470adec5704708600bd88 100644 (file)
@@ -1,12 +1,14 @@
 # $Id$
 
 EXTRA_DIST += modules/arch/Makefile.inc
+EXTRA_DIST += modules/listfmts/Makefile.inc
 EXTRA_DIST += modules/parsers/Makefile.inc
 EXTRA_DIST += modules/preprocs/Makefile.inc
 EXTRA_DIST += modules/optimizers/Makefile.inc
 EXTRA_DIST += modules/objfmts/Makefile.inc
 
 include modules/arch/Makefile.inc
+include modules/listfmts/Makefile.inc
 include modules/parsers/Makefile.inc
 include modules/preprocs/Makefile.inc
 include modules/optimizers/Makefile.inc
diff --git a/modules/listfmts/Makefile.inc b/modules/listfmts/Makefile.inc
new file mode 100644 (file)
index 0000000..2621412
--- /dev/null
@@ -0,0 +1,5 @@
+# $Id$
+
+EXTRA_DIST += modules/listfmts/nasm/Makefile.inc
+
+include modules/listfmts/nasm/Makefile.inc
diff --git a/modules/listfmts/nasm/Makefile.inc b/modules/listfmts/nasm/Makefile.inc
new file mode 100644 (file)
index 0000000..38569e0
--- /dev/null
@@ -0,0 +1,13 @@
+# $Id$
+
+pkglib_LTLIBRARIES += listfmt_nasm.la
+
+listfmt_nasm_la_SOURCES  = modules/listfmts/nasm/nasm-listfmt.c
+
+listfmt_nasm_la_LDFLAGS = -module -avoid-version -no-undefined
+listfmt_nasm_la_LIBADD = libyasm.la
+YASM_MODULES += -dlopen listfmt_nasm.la
+
+#EXTRA_DIST += modules/listfmts/nasm/tests/Makefile.inc
+
+#include modules/listfmts/nasm/tests/Makefile.inc
diff --git a/modules/listfmts/nasm/nasm-listfmt.c b/modules/listfmts/nasm/nasm-listfmt.c
new file mode 100644 (file)
index 0000000..90370c3
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * NASM-style list format
+ *
+ *  Copyright (C) 2004  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>
+/*@unused@*/ RCSID("$Id$");
+
+#define YASM_LIB_INTERNAL
+#define YASM_BC_INTERNAL
+#include <libyasm.h>
+
+
+#define REGULAR_BUF_SIZE    1024
+
+yasm_listfmt_module yasm_nasm_LTX_listfmt;
+
+typedef struct nasm_listfmt_output_info {
+    yasm_arch *arch;
+} nasm_listfmt_output_info;
+
+static /*@null@*/ /*@only@*/ yasm_listfmt *
+nasm_listfmt_create(const char *in_filename, const char *obj_filename)
+{
+    yasm_listfmt_base *listfmt = yasm_xmalloc(sizeof(yasm_listfmt_base));
+    listfmt->module = &yasm_nasm_LTX_listfmt;
+    return (yasm_listfmt *)listfmt;
+}
+
+static void
+nasm_listfmt_destroy(/*@only@*/ yasm_listfmt *listfmt)
+{
+    yasm_xfree(listfmt);
+}
+
+static int
+nasm_listfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
+                        size_t valsize, int shift, unsigned long offset,
+                        yasm_bytecode *bc, int rel, int warn,
+                        /*@null@*/ void *d)
+{
+    /*@null@*/ nasm_listfmt_output_info *info = (nasm_listfmt_output_info *)d;
+    /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
+    /*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;
+
+    assert(info != NULL);
+
+    flt = yasm_expr_get_floatnum(ep);
+    if (flt) {
+       if (shift < 0)
+           yasm_internal_error(N_("attempting to negative shift a float"));
+       return yasm_arch_floatnum_tobytes(info->arch, flt, buf, destsize,
+                                         valsize, (unsigned int)shift, warn,
+                                         bc->line);
+    }
+
+    intn = yasm_expr_get_intnum(ep, NULL);
+    if (intn)
+       return yasm_arch_intnum_tobytes(info->arch, intn, buf, destsize,
+                                       valsize, shift, bc, rel, warn,
+                                       bc->line);
+
+    return 0;
+}
+
+static void
+nasm_listfmt_output(yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
+                   yasm_arch *arch)
+{
+    yasm_bytecode *bc;
+    const char *source;
+    unsigned long line = 1;
+    unsigned long listline = 1;
+    /*@only@*/ unsigned char *buf;
+    nasm_listfmt_output_info info;
+
+    info.arch = arch;
+
+    buf = yasm_xmalloc(REGULAR_BUF_SIZE);
+
+    while (!yasm_linemap_get_source(linemap, line, &bc, &source)) {
+       if (!bc) {
+           fprintf(f, "%6lu %*s     %s\n", listline++, 28, "", source);
+       } else while (bc && bc->line == line) {
+           /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+           unsigned long size = REGULAR_BUF_SIZE;
+           unsigned long multiple;
+           unsigned long offset = bc->offset;
+           unsigned char *p;
+           int gap;
+
+           bigbuf = yasm_bc_tobytes(bc, buf, &size, &multiple, &gap, &info,
+                                    nasm_listfmt_output_expr, NULL);
+
+           p = bigbuf ? bigbuf : buf;
+           while (size > 0) {
+               int i;
+
+               fprintf(f, "%6lu %08lX ", listline++, offset);
+               for (i=0; i<18 && size > 0; i+=2, size--)
+                   fprintf(f, "%02X", *(p++));
+               if (size > 0)
+                   fprintf(f, "-");
+               else {
+                   if (multiple > 1) {
+                       fprintf(f, "<rept>");
+                       i += 6;
+                   }
+                   for (; i<18; i+=2)
+                       fprintf(f, "  ");
+                   fprintf(f, " ");
+               }
+               if (source) {
+                   fprintf(f, "    %s", source);
+                   source = NULL;
+               }
+               fprintf(f, "\n");
+           }
+           
+           if (bigbuf)
+               yasm_xfree(bigbuf);
+           bc = STAILQ_NEXT(bc, link);
+       }
+       line++;
+    }
+
+    yasm_xfree(buf);
+}
+
+/* Define listfmt structure -- see listfmt.h for details */
+yasm_listfmt_module yasm_nasm_LTX_listfmt = {
+    YASM_LISTFMT_VERSION,
+    "NASM-style list format",
+    "nasm",
+    nasm_listfmt_create,
+    nasm_listfmt_destroy,
+    nasm_listfmt_output
+};
index d8d73771183fb4c4a8add7ff4d44ce683a888354..80c5bd80a9548d355578ab83d86873ceeb5c8b9b 100644 (file)
@@ -127,6 +127,10 @@ input: /* empty */
            yasm_section_bcs_append(parser_nasm->cur_section, $2);
        if (parser_nasm->temp_bc)
            parser_nasm->prev_bc = parser_nasm->temp_bc;
+       if (parser_nasm->save_input)
+           yasm_linemap_add_source(parser_nasm->linemap,
+               parser_nasm->temp_bc,
+               parser_nasm->save_line[parser_nasm->save_last ^ 1]);
        yasm_linemap_goto_next(parser_nasm->linemap);
     }
 ;
index 95be27eeb64d27e110e14ad2a53e08ed1483483a..1671a08641fb0eb09df3007a5b22f318308bd8b6 100644 (file)
@@ -57,6 +57,7 @@ nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp, yasm_arch *a,
     parser_nasm.prev_bc = yasm_section_bcs_first(def_sect);
 
     parser_nasm.save_input = save_input;
+    parser_nasm.save_last = 0;
 
     /* initialize scanner structure */
     parser_nasm.s.bot = NULL;
index a615e1c81a108b37bd9ece12597d59ebeacd83e6..c2147018fe34c3d2d30104f323c6a3cc2c61016e 100644 (file)
@@ -59,7 +59,8 @@ typedef struct yasm_parser_nasm {
     yasm_bytecode *temp_bc;
 
     int save_input;
-    YYCTYPE save_line[MAX_SAVED_LINE_LEN];
+    YYCTYPE save_line[2][MAX_SAVED_LINE_LEN];
+    int save_last;
 
     Scanner s;
     enum {
index b36e7d7328e45f7b92598cc5e539268c984a012f..a8b09e53221991e57021319e29b0985019ad8a61 100644 (file)
@@ -91,47 +91,34 @@ fill(yasm_parser_nasm *parser_nasm, YYCTYPE *cursor)
        s->lim += cnt;
        if (first && parser_nasm->save_input) {
            int i;
+           char *saveline;
+           parser_nasm->save_last ^= 1;
+           saveline = parser_nasm->save_line[parser_nasm->save_last];
            /* save next line into cur_line */
            for (i=0; i<79 && &s->tok[i] < s->lim && s->tok[i] != '\n'; i++)
-               parser_nasm->save_line[i] = s->tok[i];
-           parser_nasm->save_line[i] = '\0';
+               saveline[i] = s->tok[i];
+           saveline[i] = '\0';
        }
     }
     return cursor;
 }
 
-static void
-destroy_line(/*@only@*/ void *data)
-{
-    yasm_xfree(data);
-}
-
-static void
-print_line(void *data, FILE *f, int indent_level)
-{
-    fprintf(f, "%*s\"%s\"\n", indent_level, "", (char *)data);
-}
-
-static const yasm_assoc_data_callback line_assoc_data = {
-    destroy_line,
-    print_line
-};
-
 static YYCTYPE *
 save_line(yasm_parser_nasm *parser_nasm, YYCTYPE *cursor)
 {
     Scanner *s = &parser_nasm->s;
     int i = 0;
+    char *saveline;
+
+    parser_nasm->save_last ^= 1;
+    saveline = parser_nasm->save_line[parser_nasm->save_last];
 
-    /* save previous line using assoc_data */
-    yasm_linemap_add_data(parser_nasm->linemap, &line_assoc_data,
-                         yasm__xstrdup(parser_nasm->save_line), 1);
     /* save next line into cur_line */
     if ((YYLIMIT - YYCURSOR) < 80)
        YYFILL(80);
     for (i=0; i<79 && &cursor[i] < s->lim && cursor[i] != '\n'; i++)
-       parser_nasm->save_line[i] = cursor[i];
-    parser_nasm->save_line[i] = '\0';
+       saveline[i] = cursor[i];
+    saveline[i] = '\0';
     return cursor;
 }