"arch",
"dbgfmt",
"objfmt",
+ "listfmt",
"optimizer",
"parser",
"preproc"
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;
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);
MODULE_ARCH = 0,
MODULE_DBGFMT,
MODULE_OBJFMT,
+ MODULE_LISTFMT,
MODULE_OPTIMIZER,
MODULE_PARSER,
MODULE_PREPROC
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) \
#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)
} 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;
/*@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 {
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 */
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);
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,
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;
}
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");
/* 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)
/* 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;
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);
/* 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.
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)
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);
}
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)
#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>
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
* \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,
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.
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 */
/* 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
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;
}
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);
}
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
*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));
}
*/
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
--- /dev/null
+/**
+ * \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
# $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
--- /dev/null
+# $Id$
+
+EXTRA_DIST += modules/listfmts/nasm/Makefile.inc
+
+include modules/listfmts/nasm/Makefile.inc
--- /dev/null
+# $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
--- /dev/null
+/*
+ * 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
+};
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);
}
;
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;
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 {
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;
}