]> granicus.if.org Git - yasm/commitdiff
Add core TASM syntax support.
authorPeter Johnson <peter@tortall.net>
Tue, 7 Oct 2008 05:38:11 +0000 (05:38 -0000)
committerPeter Johnson <peter@tortall.net>
Tue, 7 Oct 2008 05:38:11 +0000 (05:38 -0000)
Contributed by: Samuel Thibault <samuel.thibault@ens-lyon.org>

It is built on top of the NASM parser and preproc, with the following
notable extensions for TASM syntax:
 - case insensitive symbols and filenames,
 - support for segment and size of labels, which permits to avoid giving
   them on each memory dereference,
 - support for data reservation (i.e. e.g. "var dd ?"),
 - support for multiples (i.e. e.g. "var dd 1 dup 10"),
 - little endian string integer constants,
 - additional expression operators: shl, shr, and, or, low, high,
 - additional offset keyword,
 - additional fword and df,
 - support for doubled quotes within quotes,
 - support for array-like and structure-like notations: t[eax] and
   [var].field,
 - support for tasm directives: macro, rept, irp, locals, proc, struc,
   segment, assume.

Notes:

 - Almost all extensions are only effective when tasm_compatible_mode is
   set, so we should have very reduced possible breakage.

 - Because the "and" keyword can be an expression operator and an
   instruction name, the data pseudo-instructions explicitly switch the
   lexer state to INSTRUCTION state to fix the ambiguity.

 - In gen_x86_insn.py, several instructions (namely lds and lea) now take
   relaxed memory sizes.  The reason is that in the case of tasm, the size
   of the actual pointed data is passed up to there, and thus any type of
   data should be accepted.

With all of this, loadlin can be compiled by yasm with quite reduced
modifications.

A new TASM-like frontend is also included.

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

100 files changed:
configure.ac
frontends/CMakeLists.txt
frontends/Makefile.inc
frontends/tasm/Makefile.inc [new file with mode: 0644]
frontends/tasm/tasm-options.c [new file with mode: 0644]
frontends/tasm/tasm-options.h [new file with mode: 0644]
frontends/tasm/tasm.c [new file with mode: 0644]
libyasm/bc-align.c
libyasm/bc-data.c
libyasm/bc-incbin.c
libyasm/bc-org.c
libyasm/bc-reserve.c
libyasm/bytecode.c
libyasm/bytecode.h
libyasm/errwarn.c
libyasm/errwarn.h
libyasm/expr.c
libyasm/expr.h
libyasm/insn.c
libyasm/insn.h
libyasm/intnum.c
libyasm/intnum.h
libyasm/symrec.c
libyasm/symrec.h
modules/arch/lc3b/lc3bbc.c
modules/arch/lc3b/lc3bid.re
modules/arch/x86/gen_x86_insn.py
modules/arch/x86/tests/Makefile.inc
modules/arch/x86/tests/lds-err.errwarn [deleted file]
modules/arch/x86/tests/lds.asm [moved from modules/arch/x86/tests/lds-err.asm with 100% similarity]
modules/arch/x86/tests/lds.hex [new file with mode: 0644]
modules/arch/x86/x86arch.c
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
modules/arch/x86/x86id.c
modules/dbgfmts/codeview/cv-symline.c
modules/dbgfmts/codeview/cv-type.c
modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c
modules/dbgfmts/dwarf2/dwarf2-info.c
modules/dbgfmts/dwarf2/dwarf2-line.c
modules/dbgfmts/stabs/stabs-dbgfmt.c
modules/objfmts/bin/Makefile.inc
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/coff/coff-objfmt.c
modules/objfmts/coff/win64-except.c
modules/objfmts/win64/tests/win64-dataref.hex
modules/parsers/Makefile.inc
modules/parsers/nasm/Makefile.inc
modules/parsers/nasm/nasm-parse.c
modules/parsers/nasm/nasm-parser.c
modules/parsers/nasm/nasm-parser.h
modules/parsers/nasm/nasm-token.re
modules/parsers/tasm/Makefile.inc [new file with mode: 0644]
modules/parsers/tasm/tests/Makefile.inc [new file with mode: 0644]
modules/parsers/tasm/tests/array.asm [new file with mode: 0644]
modules/parsers/tasm/tests/array.hex [new file with mode: 0644]
modules/parsers/tasm/tests/case.asm [new file with mode: 0644]
modules/parsers/tasm/tests/case.hex [new file with mode: 0644]
modules/parsers/tasm/tests/charstr.asm [new file with mode: 0644]
modules/parsers/tasm/tests/charstr.hex [new file with mode: 0644]
modules/parsers/tasm/tests/dup.asm [new file with mode: 0644]
modules/parsers/tasm/tests/dup.hex [new file with mode: 0644]
modules/parsers/tasm/tests/equal.asm [new file with mode: 0644]
modules/parsers/tasm/tests/equal.hex [new file with mode: 0644]
modules/parsers/tasm/tests/exe/Makefile.inc [new file with mode: 0644]
modules/parsers/tasm/tests/exe/exe.asm [new file with mode: 0644]
modules/parsers/tasm/tests/exe/exe.hex [new file with mode: 0644]
modules/parsers/tasm/tests/exe/tasm_exe_test.sh [new file with mode: 0755]
modules/parsers/tasm/tests/expr.asm [new file with mode: 0644]
modules/parsers/tasm/tests/expr.hex [new file with mode: 0644]
modules/parsers/tasm/tests/irp.asm [new file with mode: 0644]
modules/parsers/tasm/tests/irp.hex [new file with mode: 0644]
modules/parsers/tasm/tests/label.asm [new file with mode: 0644]
modules/parsers/tasm/tests/label.hex [new file with mode: 0644]
modules/parsers/tasm/tests/les.asm [new file with mode: 0644]
modules/parsers/tasm/tests/les.hex [new file with mode: 0644]
modules/parsers/tasm/tests/lidt.asm [new file with mode: 0644]
modules/parsers/tasm/tests/lidt.hex [new file with mode: 0644]
modules/parsers/tasm/tests/macro.asm [new file with mode: 0644]
modules/parsers/tasm/tests/macro.hex [new file with mode: 0644]
modules/parsers/tasm/tests/offset.asm [new file with mode: 0644]
modules/parsers/tasm/tests/offset.hex [new file with mode: 0644]
modules/parsers/tasm/tests/quote.asm [new file with mode: 0644]
modules/parsers/tasm/tests/quote.hex [new file with mode: 0644]
modules/parsers/tasm/tests/res.asm [new file with mode: 0644]
modules/parsers/tasm/tests/res.errwarn [new file with mode: 0644]
modules/parsers/tasm/tests/res.hex [new file with mode: 0644]
modules/parsers/tasm/tests/segment.asm [new file with mode: 0644]
modules/parsers/tasm/tests/segment.hex [new file with mode: 0644]
modules/parsers/tasm/tests/size.asm [new file with mode: 0644]
modules/parsers/tasm/tests/size.hex [new file with mode: 0644]
modules/parsers/tasm/tests/struc.asm [new file with mode: 0644]
modules/parsers/tasm/tests/struc.errwarn [new file with mode: 0644]
modules/parsers/tasm/tests/struc.hex [new file with mode: 0644]
modules/parsers/tasm/tests/tasm_test.sh [new file with mode: 0755]
modules/preprocs/nasm/Makefile.inc
modules/preprocs/nasm/nasm-pp.c
modules/preprocs/nasm/nasm-preproc.c
modules/preprocs/nasm/nasm.h

index 9751062259d9e3ecdb3172179f9728a9aa499f78..40d99510ff77ab6ea42bf5f673be11ca33765b45 100644 (file)
@@ -125,7 +125,7 @@ AX_CREATE_STDINT_H([libyasm-stdint.h])
 #
 AC_CHECK_FUNCS([abort toascii vsnprintf])
 AC_CHECK_FUNCS([strsep mergesort getcwd])
-AC_CHECK_FUNCS([popen])
+AC_CHECK_FUNCS([popen ftruncate])
 # Look for the case-insensitive comparison functions
 AC_CHECK_FUNCS([strcasecmp strncasecmp stricmp _stricmp strcmpi])
 
index b8b55d2d08740880103c62b6a164186047ed340e..0d1177343b4a63f60a5039d2d0ddbadc1f1fccf8 100644 (file)
@@ -1 +1,2 @@
 ADD_SUBDIRECTORY(yasm)
+ADD_SUBDIRECTORY(tasm)
index 832a2f0bf72d4e4b28ace245969842cc45b34527..0e1552fad698fc1d4e9955716a2212318a0bc0e8 100644 (file)
@@ -1,5 +1,7 @@
 # $Id$
 
 EXTRA_DIST += frontends/yasm/Makefile.inc
+EXTRA_DIST += frontends/tasm/Makefile.inc
 
 include frontends/yasm/Makefile.inc
+include frontends/tasm/Makefile.inc
diff --git a/frontends/tasm/Makefile.inc b/frontends/tasm/Makefile.inc
new file mode 100644 (file)
index 0000000..69ec826
--- /dev/null
@@ -0,0 +1,9 @@
+# $Id: Makefile.inc 1463 2006-04-05 05:39:23Z peter $
+
+bin_PROGRAMS += tasm
+
+tasm_SOURCES  = frontends/tasm/tasm.c
+tasm_SOURCES += frontends/tasm/tasm-options.c
+tasm_SOURCES += frontends/tasm/tasm-options.h
+
+tasm_LDADD = libyasm.a $(INTLLIBS)
diff --git a/frontends/tasm/tasm-options.c b/frontends/tasm/tasm-options.c
new file mode 100644 (file)
index 0000000..945e5c0
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001  Stanislav Karchebny <berk@madfire.net>
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <util.h>
+#include <ctype.h>
+/*@unused@*/ RCSID("$Id: tasm-options.c 1197 2005-01-24 06:44:25Z peter $");
+
+#include "tasm-options.h"
+
+
+#ifdef __DEBUG__
+#define DEBUG(x) fprintf ## x ;
+#else
+#define DEBUG(x)
+#endif
+
+
+/* Options Parser */
+int
+parse_cmdline(int argc, char **argv, opt_option *options, size_t nopts,
+              void (*print_error) (const char *fmt, ...))
+{
+    int errors = 0, warnings = 0;
+    size_t i;
+    int got_it;
+
+    DEBUG((stderr, "parse_cmdline: entered\n"));
+
+  fail:
+    while (--argc) {
+        argv++;
+
+        if (argv[0][0] == '/' && argv[0][1]) {        /* opt */
+            got_it = 0;
+            for (i = 0; i < nopts; i++) {
+                char lower[3];
+                unsigned len;
+
+                lower[0] = tolower(argv[0][1]);
+                if (!argv[0][2]) {
+                    lower[1] = '\0';
+                } else {
+                    lower[1] = tolower(argv[0][2]);
+                    lower[2] = '\0';
+                }
+
+                len = strlen(options[i].opt);
+                if (!strncmp(lower, options[i].opt, len)) {
+                    char *cmd = &argv[0][1];
+                    char *param;
+
+                    param = &argv[0][1+len];
+                    if (options[i].takes_param) {
+                        if (param[0] == '\0') {
+                            print_error(
+                                _("option `-%c' needs an argument!"),
+                                options[i].opt);
+                            errors++;
+                            goto fail;
+                        } else {
+                            argc--;
+                            argv++;
+                        }
+                    } else
+                        param = NULL;
+
+                    if (!options[i].handler(cmd, param, options[i].extra))
+                        got_it = 1;
+                    break;
+                }
+            }
+            if (!got_it) {
+                print_error(_("warning: unrecognized option `%s'"),
+                            argv[0]);
+                warnings++;
+            }
+        } else {    /* not an option, then it should be a file or something */
+
+            if (not_an_option_handler(argv[0]))
+                errors++;
+        }
+    }
+
+    DEBUG((stderr, "parse_cmdline: finished\n"));
+    return errors;
+}
+
+void
+help_msg(const char *msg, const char *tail, opt_option *options, size_t nopts)
+{
+    char optbuf[100], optopt[100];
+    size_t i;
+
+    printf("%s", gettext(msg));
+
+    for (i = 0; i < nopts; i++) {
+        optbuf[0] = 0;
+        optopt[0] = 0;
+
+        if (options[i].takes_param) {
+            if (options[i].opt)
+                sprintf(optbuf, "/%s <%s>", options[i].opt,
+                        options[i].param_desc ? options[i].
+                        param_desc : _("param"));
+        } else {
+            if (options[i].opt)
+                sprintf(optbuf, "/%s", options[i].opt);
+        }
+
+        printf("    %-22s  %s\n", optbuf, gettext(options[i].description));
+    }
+
+    printf("%s", gettext(tail));
+}
diff --git a/frontends/tasm/tasm-options.h b/frontends/tasm/tasm-options.h
new file mode 100644 (file)
index 0000000..6f2e741
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: tasm-options.h 1137 2004-09-04 01:24:57Z peter $
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001  Stanislav Karchebny <berk@madfire.net>
+ *
+ * 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.
+ */
+#ifndef TASM_OPTIONS_H
+#define TASM_OPTIONS_H
+
+/* an option structure
+ * operate on either -sopt, --lopt, -sopt <val> or --lopt=<val>
+ */
+typedef struct opt_option_s
+{
+    /* option */
+    const char *opt;
+
+    /* !=0 if option requires parameter, 0 if not */
+    int takes_param;
+
+    int (*handler) (char *cmd, /*@null@*/ char *param, int extra);
+    int extra;                 /* extra value for handler */
+
+    /* description to use in help_msg() */
+    /*@observer@*/ const char *description;
+
+    /* optional description for the param taken (NULL if not present) */
+    /*  (short - will be printed after option sopt/lopt) */
+    /*@observer@*/ /*@null@*/ const char *param_desc;
+} opt_option;
+
+/* handle everything that is not an option */
+int not_an_option_handler(char *param);
+
+/* parse command line calling handlers when appropriate
+ * argc, argv - pass directly from main(argc,argv)
+ * options - array of options
+ * nopts - options count
+ */
+int parse_cmdline(int argc, char **argv, opt_option *options, size_t nopts,
+                  void (*print_error) (const char *fmt, ...));
+
+/* display help message msg followed by list of options in options and followed
+ * by tail
+ */
+void help_msg(const char *msg, const char *tail, opt_option *options,
+              size_t nopts);
+
+#endif
diff --git a/frontends/tasm/tasm.c b/frontends/tasm/tasm.c
new file mode 100644 (file)
index 0000000..695681f
--- /dev/null
@@ -0,0 +1,1003 @@
+/*
+ * Program entry point, command line parsing
+ *
+ *  Copyright (C) 2001-2008  Peter Johnson
+ *  Copyright (C) 2007-2008  Samuel Thibault
+ *
+ * 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: tasm.c 1523 2006-05-06 16:11:56Z peter $");
+
+#include <ctype.h>
+#include <unistd.h>
+#include <libyasm/compat-queue.h>
+#include <libyasm/bitvect.h>
+#include <libyasm.h>
+
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#include "tasm-options.h"
+
+#ifdef CMAKE_BUILD
+#include "yasm-plugin.h"
+#endif
+
+#include "license.c"
+
+#define DEFAULT_OBJFMT_MODULE   "bin"
+
+/*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
+/*@null@*/ /*@only@*/ static char *list_filename = NULL, *xref_filename = NULL;
+/*@null@*/ /*@only@*/ static char *machine_name = NULL;
+static int special_options = 0;
+static int segment_ordering = 0;
+static int cross_reference = 0;
+static int floating_point = 0;
+static int listing = 0;
+static int expanded_listing = 0;
+static int case_sensitivity = 0;
+static int valid_length = -1;
+/*@null@*/ /*@dependent@*/ static yasm_arch *cur_arch = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_arch_module *
+    cur_arch_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_parser_module *
+    cur_parser_module = NULL;
+/*@null@*/ /*@dependent@*/ static yasm_preproc *cur_preproc = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_preproc_module *
+    cur_preproc_module = NULL;
+/*@null@*/ static char *objfmt_keyword = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_objfmt_module *
+    cur_objfmt_module = 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 warning_error = 0;   /* warnings being treated as errors */
+static FILE *errfile;
+/*@null@*/ /*@only@*/ static char *error_filename = NULL;
+
+/*@null@*/ /*@dependent@*/ static FILE *open_file(const char *filename,
+                                                  const char *mode);
+static void check_errors(/*@only@*/ yasm_errwarns *errwarns,
+                         /*@only@*/ yasm_object *object,
+                         /*@only@*/ yasm_linemap *linemap);
+static void cleanup(/*@null@*/ /*@only@*/ yasm_object *object);
+
+/* Forward declarations: cmd line parser handlers */
+static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_segment_ordering_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_cross_reference_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_floating_point_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_ignore(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listing_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_case_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_valid_length_handler(char *cmd, /*@null@*/ char *param, int extra);
+
+static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_option(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_exe_handler(char *cmd, /*@null@*/ char *param, int extra);
+
+static /*@only@*/ char *replace_extension(const char *orig, /*@null@*/
+                                          const char *ext, const char *def);
+static void print_error(const char *fmt, ...);
+
+static /*@exits@*/ void handle_yasm_int_error(const char *file,
+                                              unsigned int line,
+                                              const char *message);
+static /*@exits@*/ void handle_yasm_fatal(const char *message, va_list va);
+static const char *handle_yasm_gettext(const char *msgid);
+static void print_yasm_error(const char *filename, unsigned long line,
+                             const char *msg, /*@null@*/ const char *xref_fn,
+                             unsigned long xref_line,
+                             /*@null@*/ const char *xref_msg);
+static void print_yasm_warning(const char *filename, unsigned long line,
+                               const char *msg);
+
+static void apply_preproc_builtins(void);
+static void apply_preproc_standard_macros(const yasm_stdmac *stdmacs);
+static void apply_preproc_saved_options(void);
+static void print_list_keyword_desc(const char *name, const char *keyword);
+
+/* values for special_options */
+#define SPECIAL_SHOW_HELP 0x01
+#define SPECIAL_SHOW_VERSION 0x02
+#define SPECIAL_SHOW_LICENSE 0x04
+
+#define SEGMENT_ORDERING_ALPHABETIC 0x01
+#define SEGMENT_ORDERING_SOURCE 0x02
+
+#define FP_EMULATED 0x01
+#define FP_REAL 0x02
+
+#define CASE_ALL 0x01
+#define CASE_GLOBALS 0x02
+#define CASE_NONE 0x04
+
+#define DEBUG_FULL 0x01
+#define DEBUG_LINES 0x02
+#define DEBUG_NONE 0x04
+
+/* command line options */
+static opt_option options[] =
+{
+    { "version", 0, opt_special_handler, SPECIAL_SHOW_VERSION,
+      N_("show version text"), NULL },
+    { "license", 0, opt_special_handler, SPECIAL_SHOW_LICENSE,
+      N_("show license text"), NULL },
+    { "a", 0, opt_segment_ordering_handler, SEGMENT_ORDERING_ALPHABETIC,
+      N_("Alphabetic segment ordering"), NULL },
+    { "s", 0, opt_segment_ordering_handler, SEGMENT_ORDERING_SOURCE,
+      N_("Source segment ordering"), NULL },
+
+    { "c", 0, opt_cross_reference_handler, 0,
+      N_("Generate cross-reference in listing"), NULL },
+
+    { "d", 1, opt_preproc_option, 2,
+      N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
+
+    { "e", 0, opt_floating_point_handler, FP_EMULATED,
+      N_("Emulated floating-point instructions (not supported)"), NULL },
+    { "r", 0, opt_floating_point_handler, FP_REAL,
+      N_("Real floating-point instructions"), NULL },
+
+    { "h", 0, opt_special_handler, SPECIAL_SHOW_HELP,
+      N_("show help text"), NULL },
+    { "?", 0, opt_special_handler, SPECIAL_SHOW_HELP,
+      N_("show help text"), NULL },
+
+    { "i", 1, opt_preproc_option, 0,
+      N_("add include path"), N_("path") },
+
+    { "j", 1, opt_ignore, 0,
+      N_("Jam in an assemble directive CMD (eg. /jIDEAL) (not supported)"), NULL },
+
+    { "k", 1, opt_ignore, 0,
+      N_("Hash table capacity (ignored)"), N_("# symbols") },
+
+    { "l", 0, opt_listing_handler, 0,
+      N_("Generate listing"), N_("l=normal listing, la=expanded listing") },
+
+    { "ml", 0, opt_case_handler, CASE_ALL,
+      N_("Case sensitivity on all symbols"), NULL },
+    { "mx", 0, opt_case_handler, CASE_GLOBALS,
+      N_("Case sensitivity on global symbols"), NULL },
+    { "mu", 0, opt_case_handler, CASE_NONE,
+      N_("No case sensitivity on symbols"), NULL },
+    { "mv", 0, opt_valid_length_handler, 0,
+      N_("Set maximum valid length for symbols"), N_("length") },
+
+    { "m", 1, opt_ignore, 0,
+      N_("Allow multiple passes to resolve forward reference (ignored)"), N_("number of passes") },
+
+    { "n", 0, opt_ignore, 0,
+      N_("Suppress symbol tables in listing"), NULL },
+
+    { "o", 0, opt_ignore, 0,
+      N_("Object code"), N_("os: standard, o: standard w/overlays, op: Phar Lap, oi: IBM") },
+
+    { "p", 0, opt_ignore, 0,
+      N_("Check for code segment overrides in protected mode"), NULL },
+    { "q", 0, opt_ignore, 0,
+      N_("Suppress OBJ records not needed for linking (ignored)"), NULL },
+    { "t", 0, opt_ignore, 0,
+      N_("Suppress messages if successful assembly"), NULL },
+    { "u", 0, opt_ignore, 0,
+      N_("Set version emulation"), N_("Version") },
+    { "w", 1, opt_warning_handler, 0,
+      N_("Set warning level"), N_("w0=none, w1=w2=warnings on, w-xxx/w+xxx=disable/enable warning xxx") },
+    { "x", 0, opt_ignore, 0,
+      N_("Include false conditionals in listing"), NULL },
+    { "zi", 0, opt_ignore, DEBUG_FULL,
+      N_("Full debug info"), NULL },
+    { "zd", 0, opt_ignore, DEBUG_LINES,
+      N_("Line numbers debug info"), NULL },
+    { "zn", 0, opt_ignore, DEBUG_NONE,
+      N_("No debug info"), NULL },
+    { "z", 0, opt_ignore, 0,
+      N_("Display source line with error message (ignored)"), NULL },
+
+    { "b", 0, opt_exe_handler, 0,
+      N_("Build a (very) basic .exe file"), NULL },
+};
+
+/* version message */
+/*@observer@*/ static const char *version_msg[] = {
+    PACKAGE_NAME " " PACKAGE_INTVER "." PACKAGE_BUILD,
+    "Compiled on " __DATE__ ".",
+    "Copyright (c) 2001-2008 Peter Johnson and other Yasm developers.",
+    "Run yasm --license for licensing overview and summary."
+};
+
+/* help messages */
+/*@observer@*/ static const char *help_head = N_(
+    "usage: tasm [option]* source [,object] [,listing] [,xref] \n"
+    "Options:\n");
+/*@observer@*/ static const char *help_tail = N_(
+    "\n"
+    "source is asm source to be assembled.\n"
+    "\n"
+    "Sample invocation:\n"
+    "   tasm /zi source.asm\n"
+    "\n"
+    "Report bugs to bug-yasm@tortall.net\n");
+
+/* parsed command line storage until appropriate modules have been loaded */
+typedef STAILQ_HEAD(constcharparam_head, constcharparam) constcharparam_head;
+
+typedef struct constcharparam {
+    STAILQ_ENTRY(constcharparam) link;
+    const char *param;
+    int id;
+} constcharparam;
+
+static constcharparam_head preproc_options;
+
+static int
+do_assemble(void)
+{
+    yasm_object *object;
+    const char *base_filename;
+    /*@null@*/ FILE *obj = NULL;
+    yasm_arch_create_error arch_error;
+    yasm_linemap *linemap;
+    yasm_errwarns *errwarns = yasm_errwarns_create();
+    int i, matched;
+
+    /* Initialize line map */
+    linemap = yasm_linemap_create();
+    yasm_linemap_set(linemap, in_filename, 1, 1);
+
+    /* determine the object filename if not specified */
+    if (!obj_filename) {
+        if (in_filename == NULL)
+            /* Default to yasm.out if no obj filename specified */
+            obj_filename = yasm__xstrdup("yasm.out");
+        else {
+            /* replace (or add) extension to base filename */
+            yasm__splitpath(in_filename, &base_filename);
+            if (base_filename[0] == '\0')
+                obj_filename = yasm__xstrdup("yasm.out");
+            else
+                obj_filename = replace_extension(base_filename,
+                                                 "obj",
+                                                 "yasm.out");
+        }
+    }
+
+    cur_arch = yasm_arch_create(cur_arch_module, machine_name,
+                                cur_parser_module->keyword, &arch_error);
+    if (!cur_arch) {
+        switch (arch_error) {
+            case YASM_ARCH_CREATE_BAD_MACHINE:
+                print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+                            _("FATAL"), machine_name, _("machine"),
+                            _("architecture"), cur_arch_module->keyword);
+                break;
+            case YASM_ARCH_CREATE_BAD_PARSER:
+                print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+                            _("FATAL"), cur_parser_module->keyword,
+                            _("parser"), _("architecture"),
+                            cur_arch_module->keyword);
+                break;
+            default:
+                print_error(_("%s: unknown architecture error"), _("FATAL"));
+        }
+
+        return EXIT_FAILURE;
+    }
+
+    /* Create object */
+    object = yasm_object_create(in_filename, obj_filename, cur_arch,
+                                cur_objfmt_module, cur_dbgfmt_module);
+    if (!object) {
+        yasm_error_class eclass;
+        unsigned long xrefline;
+        /*@only@*/ /*@null@*/ char *estr, *xrefstr;
+
+        yasm_error_fetch(&eclass, &estr, &xrefline, &xrefstr);
+        print_error("%s: %s", _("FATAL"), estr);
+        yasm_xfree(estr);
+        yasm_xfree(xrefstr);
+
+        cleanup(object);
+        return EXIT_FAILURE;
+    }
+
+    /* Get a fresh copy of objfmt_module as it may have changed. */
+    cur_objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
+
+    /* Check to see if the requested preprocessor is in the allowed list
+     * for the active parser.
+     */
+    matched = 0;
+    for (i=0; cur_parser_module->preproc_keywords[i]; i++)
+        if (yasm__strcasecmp(cur_parser_module->preproc_keywords[i],
+                             cur_preproc_module->keyword) == 0)
+            matched = 1;
+    if (!matched) {
+        print_error(_("%s: `%s' is not a valid %s for %s `%s'"), _("FATAL"),
+                    cur_preproc_module->keyword, _("preprocessor"),
+                    _("parser"), cur_parser_module->keyword);
+        cleanup(object);
+        return EXIT_FAILURE;
+    }
+
+    cur_preproc = yasm_preproc_create(cur_preproc_module, in_filename,
+                                      object->symtab, linemap, errwarns);
+
+    apply_preproc_builtins();
+    apply_preproc_standard_macros(cur_parser_module->stdmacs);
+    apply_preproc_standard_macros(cur_objfmt_module->stdmacs);
+    apply_preproc_saved_options();
+
+    /* Get initial x86 BITS setting from object format */
+    if (strcmp(cur_arch_module->keyword, "x86") == 0) {
+        yasm_arch_set_var(cur_arch, "mode_bits",
+                          cur_objfmt_module->default_x86_mode_bits);
+    }
+
+    /* Parse! */
+    cur_parser_module->do_parse(object, cur_preproc, list_filename != NULL,
+                                linemap, errwarns);
+
+    check_errors(errwarns, object, linemap);
+
+    /* Finalize parse */
+    yasm_object_finalize(object, errwarns);
+    check_errors(errwarns, object, linemap);
+
+    /* Optimize */
+    yasm_object_optimize(object, errwarns);
+    check_errors(errwarns, object, linemap);
+
+    /* generate any debugging information */
+    yasm_dbgfmt_generate(object, linemap, errwarns);
+    check_errors(errwarns, object, linemap);
+
+    /* open the object file for output (if not already opened by dbg objfmt) */
+    if (!obj && strcmp(cur_objfmt_module->keyword, "dbg") != 0) {
+        obj = open_file(obj_filename, "wb");
+        if (!obj) {
+            cleanup(object);
+            return EXIT_FAILURE;
+        }
+    }
+
+    /* Write the object file */
+    yasm_objfmt_output(object, obj?obj:stderr,
+                       strcmp(cur_dbgfmt_module->keyword, "null"), errwarns);
+
+    /* Close object file */
+    if (obj)
+        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 (yasm_errwarns_num_errors(errwarns, warning_error) > 0)
+        remove(obj_filename);
+    check_errors(errwarns, object, linemap);
+
+    /* 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, linemap, cur_arch);
+        fclose(list);
+    }
+
+    yasm_errwarns_output_all(errwarns, linemap, warning_error,
+                             print_yasm_error, print_yasm_warning);
+
+    yasm_linemap_destroy(linemap);
+    yasm_errwarns_destroy(errwarns);
+    cleanup(object);
+    return EXIT_SUCCESS;
+}
+
+/* main function */
+/*@-globstate -unrecog@*/
+int
+main(int argc, char *argv[])
+{
+    size_t i;
+
+    errfile = stderr;
+
+#if defined(HAVE_SETLOCALE) && defined(HAVE_LC_MESSAGES)
+    setlocale(LC_MESSAGES, "");
+#endif
+#if defined(LOCALEDIR)
+    bindtextdomain(PACKAGE, LOCALEDIR);
+#endif
+    textdomain(PACKAGE);
+
+    /* Initialize errwarn handling */
+    yasm_internal_error_ = handle_yasm_int_error;
+    yasm_fatal = handle_yasm_fatal;
+    yasm_gettext_hook = handle_yasm_gettext;
+    yasm_errwarn_initialize();
+
+    /* Initialize BitVector (needed for intnum/floatnum). */
+    if (BitVector_Boot() != ErrCode_Ok) {
+        print_error(_("%s: could not initialize BitVector"), _("FATAL"));
+        return EXIT_FAILURE;
+    }
+
+    /* Initialize intnum and floatnum */
+    yasm_intnum_initialize();
+    yasm_floatnum_initialize();
+
+#ifdef CMAKE_BUILD
+    /* Load standard modules */
+    if (!load_plugin("yasmstd")) {
+        print_error(_("%s: could not load standard modules"), _("FATAL"));
+        return EXIT_FAILURE;
+    }
+#endif
+
+    /* Initialize parameter storage */
+    STAILQ_INIT(&preproc_options);
+
+    if (parse_cmdline(argc, argv, options, NELEMS(options), print_error))
+        return EXIT_FAILURE;
+
+    switch (special_options) {
+        case SPECIAL_SHOW_HELP:
+            /* Does gettext calls internally */
+            help_msg(help_head, help_tail, options, NELEMS(options));
+            return EXIT_SUCCESS;
+        case SPECIAL_SHOW_VERSION:
+            for (i=0; i<NELEMS(version_msg); i++)
+                printf("%s\n", version_msg[i]);
+            return EXIT_SUCCESS;
+        case SPECIAL_SHOW_LICENSE:
+            for (i=0; i<NELEMS(license_msg); i++)
+                printf("%s\n", license_msg[i]);
+            return EXIT_SUCCESS;
+    }
+
+    /* Open error file if specified. */
+    if (error_filename) {
+        errfile = open_file(error_filename, "wt");
+        if (!errfile)
+            return EXIT_FAILURE;
+    }
+
+    /* If not already specified, default to bin as the object format. */
+    if (!cur_objfmt_module) {
+        if (!objfmt_keyword)
+            objfmt_keyword = yasm__xstrdup(DEFAULT_OBJFMT_MODULE);
+        cur_objfmt_module = yasm_load_objfmt(objfmt_keyword);
+        if (!cur_objfmt_module) {
+            print_error(_("%s: could not load default %s"), _("FATAL"),
+                        _("object format"));
+            return EXIT_FAILURE;
+        }
+    }
+
+    /* TASM's architecture is x86 */
+    cur_arch_module = yasm_load_arch("x86");
+    if (!cur_arch_module) {
+        print_error(_("%s: could not load %s"), _("FATAL"),
+                    _("architecture"));
+        return EXIT_FAILURE;
+    }
+    machine_name =
+        yasm__xstrdup(cur_arch_module->default_machine_keyword);
+
+    /* Check for arch help */
+    if (machine_name && strcmp(machine_name, "help") == 0) {
+        const yasm_arch_machine *m = cur_arch_module->machines;
+        printf(_("Available %s for %s `%s':\n"), _("machines"),
+               _("architecture"), cur_arch_module->keyword);
+        while (m->keyword && m->name) {
+            print_list_keyword_desc(m->name, m->keyword);
+            m++;
+        }
+        return EXIT_SUCCESS;
+    }
+
+    cur_parser_module = yasm_load_parser("tasm");
+    if (!cur_parser_module) {
+        print_error(_("%s: could not load %s"), _("FATAL"),
+                    _("parser"));
+        cleanup(NULL);
+        return EXIT_FAILURE;
+    }
+
+    /* If not already specified, default to the parser's default preproc. */
+    if (!cur_preproc_module) {
+        cur_preproc_module =
+            yasm_load_preproc(cur_parser_module->default_preproc_keyword);
+        if (!cur_preproc_module) {
+            print_error(_("%s: could not load default %s"), _("FATAL"),
+                        _("preprocessor"));
+            cleanup(NULL);
+            return EXIT_FAILURE;
+        }
+    }
+
+    /* Determine input filename and open input file. */
+    if (!in_filename) {
+        print_error(_("No input files specified"));
+        return EXIT_FAILURE;
+    }
+
+    /* If list file enabled, make sure we have a list format loaded. */
+    if (list_filename) {
+        /* use nasm as the list format. */
+        cur_listfmt_module = yasm_load_listfmt("nasm");
+    }
+
+    /* If not already specified, default to null as the debug format. */
+    if (!cur_dbgfmt_module) {
+        cur_dbgfmt_module = yasm_load_dbgfmt("null");
+        if (!cur_dbgfmt_module) {
+            print_error(_("%s: could not load default %s"), _("FATAL"),
+                        _("debug format"));
+            return EXIT_FAILURE;
+        }
+    }
+
+    return do_assemble();
+}
+/*@=globstate =unrecog@*/
+
+/* Open the object file.  Returns 0 on failure. */
+static FILE *
+open_file(const char *filename, const char *mode)
+{
+    FILE *f;
+
+    f = fopen(filename, mode);
+    if (!f)
+        print_error(_("could not open file `%s'"), filename);
+    return f;
+}
+
+static void
+check_errors(yasm_errwarns *errwarns, yasm_object *object,
+             yasm_linemap *linemap)
+{
+    if (yasm_errwarns_num_errors(errwarns, warning_error) > 0) {
+        yasm_errwarns_output_all(errwarns, linemap, warning_error,
+                                 print_yasm_error, print_yasm_warning);
+        yasm_linemap_destroy(linemap);
+        yasm_errwarns_destroy(errwarns);
+        cleanup(object);
+        exit(EXIT_FAILURE);
+    }
+}
+
+/* Define DO_FREE to 1 to enable deallocation of all data structures.
+ * Useful for detecting memory leaks, but slows down execution unnecessarily
+ * (as the OS will free everything we miss here).
+ */
+#define DO_FREE 1
+
+/* Cleans up all allocated structures. */
+static void
+cleanup(yasm_object *object)
+{
+    if (DO_FREE) {
+        if (cur_listfmt)
+            yasm_listfmt_destroy(cur_listfmt);
+        if (cur_preproc)
+            yasm_preproc_destroy(cur_preproc);
+        if (object)
+            yasm_object_destroy(object);
+
+        yasm_floatnum_cleanup();
+        yasm_intnum_cleanup();
+
+        yasm_errwarn_cleanup();
+
+        BitVector_Shutdown();
+    }
+
+    if (DO_FREE) {
+        if (in_filename)
+            yasm_xfree(in_filename);
+        if (obj_filename)
+            yasm_xfree(obj_filename);
+        if (list_filename)
+            yasm_xfree(list_filename);
+        if (xref_filename)
+            yasm_xfree(xref_filename);
+        if (machine_name)
+            yasm_xfree(machine_name);
+        if (objfmt_keyword)
+            yasm_xfree(objfmt_keyword);
+    }
+
+    if (errfile != stderr && errfile != stdout)
+        fclose(errfile);
+#ifdef CMAKE_BUILD
+    unload_plugins();
+#endif
+}
+
+/*
+ *  Command line options handlers
+ */
+static char ** const filenames[] = {
+    &in_filename, &obj_filename, &list_filename, &xref_filename, NULL
+}, ** const * cur_filename = &filenames[0];
+
+static int filename_handler(char *param) {
+    if (!*cur_filename) {
+        print_error(_("error: too many files on command line."));
+        return 1;
+    }
+
+    if (*param)
+            **cur_filename = yasm__xstrdup(param);
+
+    return 0;
+}
+int
+not_an_option_handler(char *param) {
+    char *c, *d = param;
+
+    while ((c = strchr(d, ','))) {
+        *c = '\0';
+        if (filename_handler(d))
+            return 1;
+        d = c + 1;
+        cur_filename++;
+    }
+    filename_handler(d);
+    return 0;
+}
+
+static int
+opt_special_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    if (special_options == 0)
+        special_options = extra;
+    return 0;
+}
+
+static int
+opt_segment_ordering_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    segment_ordering = extra;
+    return 0;
+}
+
+static int
+opt_cross_reference_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    cross_reference = 1;
+    return 0;
+}
+
+static int
+opt_floating_point_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    floating_point = extra;
+    return 0;
+}
+
+static int
+opt_ignore(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    return 0;
+}
+
+static int
+opt_listing_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    if (param[0]) {
+        if (param[0] != 'a')
+            return 1;
+        expanded_listing = 1;
+    }
+    listing = 1;
+    return 0;
+}
+
+static int
+opt_case_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    case_sensitivity = extra;
+    return 0;
+}
+
+static int
+opt_valid_length_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+    valid_length = atoi(param);
+    return 0;
+}
+
+static int
+opt_warning_handler(char *cmd, /*@unused@*/ char *param, int extra)
+{
+    /* is it disabling the warning instead of enabling? */
+    void (*action)(yasm_warn_class wclass) = NULL;
+
+    if (cmd[0] == '0') {
+        /* /w0, disable warnings */
+        yasm_warn_disable_all();
+        return 0;
+    }
+
+    if (cmd[0] == '1' || cmd[0] == '2') {
+        /* /w[12], enable warnings */
+        yasm_warn_enable(YASM_WARN_UNREC_CHAR);
+        yasm_warn_enable(YASM_WARN_ORPHAN_LABEL);
+        yasm_warn_enable(YASM_WARN_UNINIT_CONTENTS);
+        return 0;
+    }
+
+    /* detect no- prefix to disable the warning */
+    if (cmd[0] == '-') {
+        action = yasm_warn_disable;
+    } else if (cmd[0] == '+') {
+        action = yasm_warn_enable;
+    } else return 1;
+
+    /* skip past '+/-' */
+    cmd++;
+
+    if (cmd[0] == '\0')
+        /* just /w- or /w+, so definitely not valid */
+        return 1;
+    else if (strcmp(cmd, "error") == 0)
+        warning_error = (action == yasm_warn_enable);
+    else if (strcmp(cmd, "unrecognized-char") == 0)
+        action(YASM_WARN_UNREC_CHAR);
+    else if (strcmp(cmd, "orphan-labels") == 0)
+        action(YASM_WARN_ORPHAN_LABEL);
+    else if (strcmp(cmd, "uninit-contents") == 0)
+        action(YASM_WARN_UNINIT_CONTENTS);
+    else if (strcmp(cmd, "size-override") == 0)
+        action(YASM_WARN_SIZE_OVERRIDE);
+    else
+        return 1;
+
+    return 0;
+}
+
+static int
+opt_preproc_option(/*@unused@*/ char *cmd, char *param, int extra)
+{
+    constcharparam *cp;
+    cp = yasm_xmalloc(sizeof(constcharparam));
+    cp->param = param;
+    cp->id = extra;
+    STAILQ_INSERT_TAIL(&preproc_options, cp, link);
+    return 0;
+}
+
+static int
+opt_exe_handler(char *cmd, /*@unused@*/ char *param, int extra)
+{
+    objfmt_keyword = yasm__xstrdup("dosexe");
+    return 0;
+}
+
+static void
+apply_preproc_builtins()
+{
+    char *predef;
+
+    if (!objfmt_keyword)
+        objfmt_keyword = yasm__xstrdup(DEFAULT_OBJFMT_MODULE);
+
+    /* Define standard YASM assembly-time macro constants */
+    predef = yasm_xmalloc(strlen("__YASM_OBJFMT__=")
+                          + strlen(objfmt_keyword) + 1);
+    strcpy(predef, "__YASM_OBJFMT__=");
+    strcat(predef, objfmt_keyword);
+    yasm_preproc_define_builtin(cur_preproc, predef);
+    yasm_xfree(predef);
+}
+
+static void
+apply_preproc_standard_macros(const yasm_stdmac *stdmacs)
+{
+    int i, matched;
+
+    if (!stdmacs)
+        return;
+
+    matched = -1;
+    for (i=0; stdmacs[i].parser; i++)
+        if (yasm__strcasecmp(stdmacs[i].parser,
+                             cur_parser_module->keyword) == 0 &&
+            yasm__strcasecmp(stdmacs[i].preproc,
+                             cur_preproc_module->keyword) == 0)
+            matched = i;
+    if (matched >= 0 && stdmacs[matched].macros)
+        yasm_preproc_add_standard(cur_preproc, stdmacs[matched].macros);
+}
+
+static void
+apply_preproc_saved_options()
+{
+    constcharparam *cp, *cpnext;
+
+    void (*funcs[3])(yasm_preproc *, const char *);
+    funcs[0] = cur_preproc_module->add_include_file;
+    funcs[1] = cur_preproc_module->predefine_macro;
+    funcs[2] = cur_preproc_module->undefine_macro;
+
+    STAILQ_FOREACH(cp, &preproc_options, link) {
+        if (0 <= cp->id && cp->id < 3 && funcs[cp->id])
+            funcs[cp->id](cur_preproc, cp->param);
+    }
+
+    cp = STAILQ_FIRST(&preproc_options);
+    while (cp != NULL) {
+        cpnext = STAILQ_NEXT(cp, link);
+        yasm_xfree(cp);
+        cp = cpnext;
+    }
+    STAILQ_INIT(&preproc_options);
+}
+
+/* Replace extension on a filename (or append one if none is present).
+ * If output filename would be identical to input (same extension out as in),
+ * returns (copy of) def.
+ * A NULL ext means the trailing '.' should NOT be included, whereas a "" ext
+ * means the trailing '.' should be included.
+ */
+static char *
+replace_extension(const char *orig, /*@null@*/ const char *ext,
+                  const char *def)
+{
+    char *out, *outext;
+    size_t deflen, outlen;
+
+    /* allocate enough space for full existing name + extension */
+    outlen = strlen(orig) + 2;
+    if (ext)
+        outlen += strlen(ext) + 1;
+    deflen = strlen(def) + 1;
+    if (outlen < deflen)
+        outlen = deflen;
+    out = yasm_xmalloc(outlen);
+
+    strcpy(out, orig);
+    outext = strrchr(out, '.');
+    if (outext) {
+        /* Existing extension: make sure it's not the same as the replacement
+         * (as we don't want to overwrite the source file).
+         */
+        outext++;   /* advance past '.' */
+        if (ext && strcmp(outext, ext) == 0) {
+            outext = NULL;  /* indicate default should be used */
+            print_error(
+                _("file name already ends in `.%s': output will be in `%s'"),
+                ext, def);
+        }
+    } else {
+        /* No extension: make sure the output extension is not empty
+         * (again, we don't want to overwrite the source file).
+         */
+        if (!ext)
+            print_error(
+                _("file name already has no extension: output will be in `%s'"),
+                def);
+        else {
+            outext = strrchr(out, '\0');    /* point to end of the string */
+            *outext++ = '.';                    /* append '.' */
+        }
+    }
+
+    /* replace extension or use default name */
+    if (outext) {
+        if (!ext) {
+            /* Back up and replace '.' with string terminator */
+            outext--;
+            *outext = '\0';
+        } else
+            strcpy(outext, ext);
+    } else
+        strcpy(out, def);
+
+    return out;
+}
+
+void
+print_list_keyword_desc(const char *name, const char *keyword)
+{
+    printf("%4s%-12s%s\n", "", keyword, name);
+}
+
+static void
+print_error(const char *fmt, ...)
+{
+    va_list va;
+    fprintf(errfile, "tasm: ");
+    va_start(va, fmt);
+    vfprintf(errfile, fmt, va);
+    va_end(va);
+    fputc('\n', errfile);
+}
+
+static /*@exits@*/ void
+handle_yasm_int_error(const char *file, unsigned int line, const char *message)
+{
+    fprintf(stderr, _("INTERNAL ERROR at %s, line %u: %s\n"), file, line,
+            gettext(message));
+#ifdef HAVE_ABORT
+    abort();
+#else
+    exit(EXIT_FAILURE);
+#endif
+}
+
+static /*@exits@*/ void
+handle_yasm_fatal(const char *fmt, va_list va)
+{
+    fprintf(errfile, "**%s**: ", _("Fatal"));
+    vfprintf(errfile, gettext(fmt), va);
+    fputc('\n', errfile);
+    exit(EXIT_FAILURE);
+}
+
+static const char *
+handle_yasm_gettext(const char *msgid)
+{
+    return gettext(msgid);
+}
+
+static void
+print_yasm_error(const char *filename, unsigned long line, const char *msg,
+                 const char *xref_fn, unsigned long xref_line,
+                 const char *xref_msg)
+{
+    if (line)
+        fprintf(errfile, "**%s** %s(%lu) %s\n", _("Error"), filename, line, msg);
+    else
+        fprintf(errfile, "**%s** %s %s\n", _("Error"), filename, msg);
+
+    if (/* xref_fn && */ xref_msg) {
+        if (xref_line)
+            fprintf(errfile, "**%s** %s(%lu) %s\n", _("Error"), filename, xref_line, xref_msg);
+        else
+            fprintf(errfile, "**%s** %s %s\n", _("Error"), filename, xref_msg);
+    }
+}
+
+static void
+print_yasm_warning(const char *filename, unsigned long line, const char *msg)
+{
+    if (line)
+        fprintf(errfile, "*%s* %s(%lu) %s\n", _("Warning"), filename, line, msg);
+    else
+        fprintf(errfile, "*%s* %s %s\n", _("Warning"), filename, msg);
+}
index e4e6b64849aa4365eb6c09dbba36d92901bad53f..fd7c8f52d50d085bf62fd1f96814e06c87befc53 100644 (file)
@@ -66,6 +66,7 @@ static const yasm_bytecode_callback bc_align_callback = {
     bc_align_destroy,
     bc_align_print,
     bc_align_finalize,
+    NULL,
     bc_align_calc_len,
     bc_align_expand,
     bc_align_tobytes,
index 8560da3166e71154406a47ba52bdb1c0d9937f66..bdbf7b6b08d8ee7bbdb3a46307a7f0235b0a8184 100644 (file)
@@ -42,7 +42,8 @@
 struct yasm_dataval {
     /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
 
-    enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128 } type;
+    enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128, DV_RESERVE }
+        type;
 
     union {
         yasm_value val;
@@ -51,16 +52,22 @@ struct yasm_dataval {
             unsigned long len;
         } raw;
     } data;
+
+    /* number of times data is repeated, NULL=1. */
+    /*@only@*/ /*@null@*/ yasm_expr *multiple;
 };
 
 typedef struct bytecode_data {
     /* converted data (linked list) */
     yasm_datavalhead datahead;
+
+    int item_size;
 } bytecode_data;
 
 static void bc_data_destroy(void *contents);
 static void bc_data_print(const void *contents, FILE *f, int indent_level);
 static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_data_item_size(yasm_bytecode *bc);
 static int bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                             void *add_span_data);
 static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
@@ -71,6 +78,7 @@ static const yasm_bytecode_callback bc_data_callback = {
     bc_data_destroy,
     bc_data_print,
     bc_data_finalize,
+    bc_data_item_size,
     bc_data_calc_len,
     yasm_bc_expand_common,
     bc_data_tobytes,
@@ -131,9 +139,26 @@ bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
             default:
                 break;
         }
+        if (dv->multiple) {
+            yasm_value val;
+            if (yasm_value_finalize_expr(&val, dv->multiple, prev_bc, 0))
+                yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+                               N_("multiple expression too complex"));
+            else if (val.rel)
+                yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+                               N_("multiple expression not absolute"));
+            dv->multiple = val.abs;
+        }
     }
 }
 
+static int
+bc_data_item_size(yasm_bytecode *bc)
+{
+    bytecode_data *bc_data = (bytecode_data *)bc->contents;
+    return bc_data->item_size;
+}
+
 static int
 bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                  void *add_span_data)
@@ -141,27 +166,37 @@ bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
     bytecode_data *bc_data = (bytecode_data *)bc->contents;
     yasm_dataval *dv;
     yasm_intnum *intn;
+    int len;
+    unsigned long multiple;
 
     /* Count up element sizes, rounding up string length. */
     STAILQ_FOREACH(dv, &bc_data->datahead, link) {
         switch (dv->type) {
             case DV_EMPTY:
+                len = 0;
                 break;
             case DV_VALUE:
-                bc->len += dv->data.val.size/8;
+                len = dv->data.val.size/8;
                 break;
             case DV_RAW:
-                bc->len += dv->data.raw.len;
+                len = dv->data.raw.len;
                 break;
             case DV_ULEB128:
             case DV_SLEB128:
                 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
                 if (!intn)
                     yasm_internal_error(N_("non-constant in data_tobytes"));
-                bc->len +=
-                    yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
+                len = yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
+                break;
+            case DV_RESERVE:
+                len = dv->data.val.size/8;
                 break;
         }
+
+        if (!yasm_dv_get_multiple(dv, &multiple))
+            len *= multiple;
+
+        bc->len += len;
     }
 
     return 0;
@@ -177,29 +212,47 @@ bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
     unsigned char *bufp_orig = *bufp;
     yasm_intnum *intn;
     unsigned int val_len;
+    unsigned long multiple, i;
 
     STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+        if (yasm_dv_get_multiple(dv, &multiple) || multiple == 0)
+            continue;
         switch (dv->type) {
             case DV_EMPTY:
                 break;
             case DV_VALUE:
                 val_len = dv->data.val.size/8;
-                if (output_value(&dv->data.val, *bufp, val_len,
-                                 (unsigned long)(*bufp-bufp_orig), bc, 1, d))
-                    return 1;
-                *bufp += val_len;
+                for (i=0; i<multiple; i++) {
+                    if (output_value(&dv->data.val, *bufp, val_len,
+                                     (unsigned long)(*bufp-bufp_orig), bc, 1,
+                                     d))
+                        return 1;
+                    *bufp += val_len;
+                }
                 break;
             case DV_RAW:
-                memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
-                *bufp += dv->data.raw.len;
+                for (i=0; i<multiple; i++) {
+                    memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
+                    *bufp += dv->data.raw.len;
+                }
                 break;
             case DV_ULEB128:
             case DV_SLEB128:
                 intn = yasm_expr_get_intnum(&dv->data.val.abs, 234);
                 if (!intn)
                     yasm_internal_error(N_("non-constant in data_tobytes"));
-                *bufp +=
-                    yasm_intnum_get_leb128(intn, *bufp, dv->type == DV_SLEB128);
+                for (i=0; i<multiple; i++) {
+                    *bufp +=
+                        yasm_intnum_get_leb128(intn, *bufp,
+                                dv->type == DV_SLEB128);
+                }
+            case DV_RESERVE:
+                val_len = dv->data.val.size/8;
+                for (i=0; i<multiple; i++) {
+                    memset(*bufp, 0, val_len);
+                    *bufp += val_len;
+                }
+                break;
         }
     }
 
@@ -218,11 +271,18 @@ yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
 
 
     yasm_dvs_initialize(&data->datahead);
+    data->item_size = size;
 
     /* Prescan input data for length, etc.  Careful: this needs to be
      * precisely paired with the second loop.
      */
     STAILQ_FOREACH(dv, datahead, link) {
+        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+            /* Flush previous data */
+            dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+            STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+            len = 0;
+        }
         switch (dv->type) {
             case DV_EMPTY:
                 break;
@@ -247,6 +307,7 @@ yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
                     /* Create bytecode for this value */
                     dvo = yasm_xmalloc(sizeof(yasm_dataval));
                     STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+                    dvo->multiple = dv->multiple;
                 }
                 break;
             case DV_RAW:
@@ -255,7 +316,19 @@ yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
                 rlen = (rlen + size - 1) / size;
                 len += rlen*size;
                 break;
+            case DV_RESERVE:
+                len += size;
+                break;
+        }
+
+        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+            /* Flush this data */
+            dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+            STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+            dvo->multiple = dv->multiple;
+            len = 0;
         }
+
         if (append_zero)
             len++;
     }
@@ -271,6 +344,10 @@ yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
     dvo = STAILQ_FIRST(&data->datahead);
     len = 0;
     while (dv && dvo) {
+        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+            dvo = STAILQ_NEXT(dvo, link);
+            len = 0;
+        }
         switch (dv->type) {
             case DV_EMPTY:
                 break;
@@ -323,7 +400,17 @@ yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
                         dvo->data.raw.contents[len++] = 0;
                 }
                 break;
+            case DV_RESERVE:
+                memset(&dvo->data.raw.contents[len], 0, size);
+                len += size;
+                break;
         }
+
+        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+            dvo = STAILQ_NEXT(dvo, link);
+            len = 0;
+        }
+
         if (append_zero)
             dvo->data.raw.contents[len++] = 0;
         dv2 = STAILQ_NEXT(dv, link);
@@ -364,6 +451,7 @@ yasm_dv_create_expr(yasm_expr *e)
 
     retval->type = DV_VALUE;
     yasm_value_initialize(&retval->data.val, e, 0);
+    retval->multiple = NULL;
 
     return retval;
 }
@@ -376,10 +464,54 @@ yasm_dv_create_raw(unsigned char *contents, unsigned long len)
     retval->type = DV_RAW;
     retval->data.raw.contents = contents;
     retval->data.raw.len = len;
+    retval->multiple = NULL;
+
+    return retval;
+}
+
+yasm_dataval *
+yasm_dv_create_reserve(void)
+{
+    yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+    retval->type = DV_RESERVE;
+    retval->multiple = NULL;
 
     return retval;
 }
 
+void
+yasm_dv_set_multiple(yasm_dataval *dv, yasm_expr *e)
+{
+    if (dv->multiple)
+        dv->multiple = yasm_expr_create_tree( dv->multiple, YASM_EXPR_MUL, e,
+                                             e->line);
+    else
+        dv->multiple = e;
+}
+
+int
+yasm_dv_get_multiple(yasm_dataval *dv, unsigned long *multiple)
+{
+    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+    *multiple = 1;
+    if (dv->multiple) {
+        num = yasm_expr_get_intnum(&dv->multiple, 0);
+        if (!num) {
+            yasm_error_set(YASM_ERROR_VALUE,
+                           N_("could not determine multiple"));
+            return 1;
+        }
+        if (yasm_intnum_sign(num) < 0) {
+            yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+            return 1;
+        }
+        *multiple = yasm_intnum_get_uint(num);
+    }
+    return 0;
+}
+
 void
 yasm_dvs_delete(yasm_datavalhead *headp)
 {
@@ -398,6 +530,8 @@ yasm_dvs_delete(yasm_datavalhead *headp)
             default:
                 break;
         }
+        if (cur->multiple)
+            yasm_expr_destroy(cur->multiple);
         yasm_xfree(cur);
         cur = next;
     }
@@ -421,6 +555,11 @@ yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
     unsigned long i;
 
     STAILQ_FOREACH(cur, head, link) {
+        fprintf(f, "%*sMultiple=", indent_level, "");
+        if (!cur->multiple)
+            fprintf(f, "nil (1)");
+        else
+            yasm_expr_print(cur->multiple, f);
         switch (cur->type) {
             case DV_EMPTY:
                 fprintf(f, "%*sEmpty\n", indent_level, "");
@@ -445,6 +584,9 @@ yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
                 fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
                 yasm_value_print(&cur->data.val, f, indent_level+1);
                 break;
+            case DV_RESERVE:
+                fprintf(f, "%*sReserved\n", indent_level, "");
+                break;
         }
     }
 }
index 5563446863c70a510b77a6aa716919c71901fb78..f2bee743272bbbf7366a741700d6c86c53f975fc 100644 (file)
@@ -66,6 +66,7 @@ static const yasm_bytecode_callback bc_incbin_callback = {
     bc_incbin_destroy,
     bc_incbin_print,
     bc_incbin_finalize,
+    NULL,
     bc_incbin_calc_len,
     yasm_bc_expand_common,
     bc_incbin_tobytes,
index ae0497a2523f893cd33e0634ecf1714621c5a3f1..b6f101cc1fe478be39b3bd4698153535be240cb6 100644 (file)
@@ -60,6 +60,7 @@ static const yasm_bytecode_callback bc_org_callback = {
     bc_org_destroy,
     bc_org_print,
     bc_org_finalize,
+    NULL,
     bc_org_calc_len,
     bc_org_expand,
     bc_org_tobytes,
index 32f524f96c6324d76601a506436343f62755ed56..5cfd38a0ae36c64348a5ca1f11bb0a4c122e8306 100644 (file)
@@ -46,6 +46,7 @@ typedef struct bytecode_reserve {
 static void bc_reserve_destroy(void *contents);
 static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
 static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_reserve_elem_size(yasm_bytecode *bc);
 static int bc_reserve_calc_len(yasm_bytecode *bc,
                                yasm_bc_add_span_func add_span,
                                void *add_span_data);
@@ -57,6 +58,7 @@ static const yasm_bytecode_callback bc_reserve_callback = {
     bc_reserve_destroy,
     bc_reserve_print,
     bc_reserve_finalize,
+    bc_reserve_elem_size,
     bc_reserve_calc_len,
     yasm_bc_expand_common,
     bc_reserve_tobytes,
@@ -95,6 +97,13 @@ bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
     reserve->numitems = NULL;
 }
 
+static int
+bc_reserve_elem_size(yasm_bytecode *bc)
+{
+    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+    return reserve->itemsize;
+}
+
 static int
 bc_reserve_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                     void *add_span_data)
index b8386f7993c8355eb22ced1ae208b2df947313e7..df3cc9d5d583e6f9a3afb0aee8362d64abf4c7c0 100644 (file)
@@ -222,6 +222,18 @@ yasm_bc_next_offset(yasm_bytecode *precbc)
     return precbc->offset + precbc->len*precbc->mult_int;
 }
 
+int
+yasm_bc_elem_size(yasm_bytecode *bc)
+{
+    if (!bc->callback) {
+        yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size"));
+        return 0;
+    } else if (!bc->callback->elem_size)
+        return 0;
+    else
+        return bc->callback->elem_size(bc);
+}
+
 int
 yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                  void *add_span_data)
index bff958f8ff2d3fcad90101cd0231dd6f7a5ffe3c..d5a9899544ba0b4b40c6b2fa81b7b2042b4f6964 100644 (file)
@@ -86,6 +86,14 @@ typedef struct yasm_bytecode_callback {
      */
     void (*finalize) (yasm_bytecode *bc, yasm_bytecode *prev_bc);
 
+    /** Return elements size of a data bytecode.
+     * This function should return the size of each elements of a data
+     * bytecode, for proper dereference of symbols attached to it.
+     * \param bc            bytecode
+     * \return 0 if element size is unknown.
+     */
+    int (*elem_size) (yasm_bytecode *bc);
+
     /** Calculates the minimum size of a bytecode.
      * Called from yasm_bc_calc_len().
      * A generic fill-in for this is yasm_bc_calc_len_common(), but as this
@@ -438,6 +446,15 @@ YASM_LIB_DECL
 YASM_LIB_DECL
 unsigned long yasm_bc_next_offset(yasm_bytecode *precbc);
 
+/** Return elemens size of a data bytecode.
+ * Returns the size of each elements of a data bytecode, for proper dereference
+ * of symbols attached to it.
+ * \param bc            bytecode
+ * \return 0 if element size is unknown
+ */
+YASM_LIB_DECL
+int yasm_bc_elem_size(yasm_bytecode *bc);
+
 /** Resolve EQUs in a bytecode and calculate its minimum size.
  * Generates dependent bytecode spans for cases where, if the length spanned
  * increases, it could cause the bytecode size to increase.
@@ -548,11 +565,31 @@ YASM_LIB_DECL
 yasm_dataval *yasm_dv_create_raw(/*@keep@*/ unsigned char *contents,
                                  unsigned long len);
 
+/** Create a new uninitialized data value.
+ * \return Newly allocated data value.
+ */
+yasm_dataval *yasm_dv_create_reserve(void);
+
 #ifndef YASM_DOXYGEN
 #define yasm_dv_create_string(s, l) yasm_dv_create_raw((unsigned char *)(s), \
                                                        (unsigned long)(l))
 #endif
 
+/** Set multiple field of a data value.
+ * A data value can be repeated a number of times when output.  This function
+ * sets that multiple.
+ * \param dv    data value
+ * \param e     multiple (kept, do not free)
+ */
+void yasm_dv_set_multiple(yasm_dataval *dv, /*@keep@*/ yasm_expr *e);
+
+/** Get the data value multiple value as an unsigned long integer.
+ * \param dv            data value
+ * \param multiple      multiple value (output)
+ * \return 1 on error (set with yasm_error_set), 0 on success.
+ */
+int yasm_dv_get_multiple(yasm_dataval *dv, /*@out@*/ unsigned long *multiple);
+
 /** Initialize a list of data values.
  * \param headp list of data values
  */
index 26d7f072300954e2c8f70efad74836a8540c3228..644d7d27c750fbe02e616d913c83f468eb4131c1 100644 (file)
@@ -115,7 +115,8 @@ yasm_errwarn_initialize(void)
     warn_class_enabled = 
         (1UL<<YASM_WARN_GENERAL) | (1UL<<YASM_WARN_UNREC_CHAR) |
         (1UL<<YASM_WARN_PREPROC) | (0UL<<YASM_WARN_ORPHAN_LABEL) |
-        (1UL<<YASM_WARN_UNINIT_CONTENTS);
+        (1UL<<YASM_WARN_UNINIT_CONTENTS) | (0UL<<YASM_WARN_SIZE_OVERRIDE) |
+        (1UL<<YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
 
     yasm_eclass = YASM_ERROR_NONE;
     yasm_estr = NULL;
index d1e9928b4c2811df55a28fb780326c9e3696f0c8..2cc7fb1a28e0273aa747616e7f8d6db0a9ddc68e 100644 (file)
@@ -46,7 +46,8 @@ typedef enum yasm_warn_class {
     YASM_WARN_PREPROC,      /**< Preprocessor warnings */
     YASM_WARN_ORPHAN_LABEL, /**< Label alone on a line without a colon */
     YASM_WARN_UNINIT_CONTENTS, /**< Uninitialized space in code/data section */
-    YASM_WARN_SIZE_OVERRIDE /**< Double size override */
+    YASM_WARN_SIZE_OVERRIDE,/**< Double size override */
+    YASM_WARN_IMPLICIT_SIZE_OVERRIDE /**< Implicit size override */
 } yasm_warn_class;
 
 /** Error classes.  Bitmask-based to support limited subclassing. */
index 20e524732525f0a078312da97ebdfe8fa1faf780..a067229bdcfde76e3e40d71cd780b674b213461f 100644 (file)
@@ -1444,3 +1444,73 @@ yasm_expr_print(const yasm_expr *e, FILE *f)
             fprintf(f, "%s", opstr);
     }
 }
+
+unsigned int
+yasm_expr_size(const yasm_expr *e)
+{
+    int i;
+    int seen = 0;
+    unsigned int size = 0, newsize;
+
+    if (e->op == YASM_EXPR_IDENT) {
+        if (e->terms[0].type == YASM_EXPR_SYM)
+            return yasm_symrec_get_size(e->terms[0].data.sym);
+        return 0;
+    }
+    if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
+        return 0;
+
+    for (i=0; i<e->numterms; i++) {
+        newsize = 0;
+        switch (e->terms[i].type) {
+        case YASM_EXPR_EXPR:
+            newsize = yasm_expr_size(e->terms[i].data.expn);
+            break;
+        case YASM_EXPR_SYM:
+            newsize = yasm_symrec_get_size(e->terms[i].data.sym);
+            break;
+        default:
+            break;
+        }
+        if (newsize) {
+            size = newsize;
+            if (seen)
+                /* either sum of idents (?!) or substract of idents */
+                return 0;
+            seen = 1;
+        }
+    }
+    /* exactly one offset */
+    return size;
+}
+
+const char *
+yasm_expr_segment(const yasm_expr *e)
+{
+    int i;
+    int seen = 0;
+    const char *segment = NULL;
+
+    if (e->op == YASM_EXPR_IDENT) {
+        if (e->terms[0].type == YASM_EXPR_SYM)
+            return yasm_symrec_get_segment(e->terms[0].data.sym);
+        return NULL;
+    }
+    if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
+        return NULL;
+
+    for (i=0; i<e->numterms; i++) {
+        if ((e->op == YASM_EXPR_ADD || !i) &&
+                e->terms[i].type == YASM_EXPR_EXPR) {
+            if ((segment = yasm_expr_segment(e->terms[i].data.expn))) {
+                if (seen) {
+                    /* either sum of idents (?!) or substract of idents */
+                    return NULL;
+                }
+                seen = 1;
+            }
+        }
+    }
+    /* exactly one offset */
+    return segment;
+}
index 96d1796c5f171b7bfe9bce0501f9bc95e2500333..ee43fca625bbf9ff6ded1dce444cec81d55daedd 100644 (file)
@@ -297,6 +297,16 @@ YASM_LIB_DECL
 YASM_LIB_DECL
 void yasm_expr_print(/*@null@*/ const yasm_expr *e, FILE *f);
 
+/** Return the size of an expression, if the user provided it
+ * \param e     expression
+ */
+unsigned int yasm_expr_size(const yasm_expr *e);
+
+/** Return the segment of an expression, if the user provided it
+ * \param e     expression
+ */
+const char *yasm_expr_segment(const yasm_expr *e);
+
 /** Traverse over expression tree in order (const version).
  * Calls func for each leaf (non-operation).
  * \param e     expression
index 46a78dbe1a9c463ee34defcf070581b94ad3de52..c4c268678eeddf3ba864525c0344e200f0dc3ebd 100644 (file)
@@ -96,6 +96,7 @@ yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea)
     retval->size = 0;
     retval->deref = 0;
     retval->strict = 0;
+    retval->size = ea->data_len * 8;
 
     return retval;
 }
index 9fdf0ebbeaa6fe9d2cccf0d863f67e0d20890572..99bcb841fd2bf65e4eba92f43a0b4867e45ac7b8 100644 (file)
@@ -74,6 +74,9 @@ struct yasm_effaddr {
 
     /** 1 if effective address is forced non-PC-relative. */
     unsigned int not_pc_rel:1;
+
+    /** length of pointed data (in bytes), 0 if unknown. */
+    unsigned int data_len;
 };
 
 /** An instruction operand (opaque type). */
index 47173c7e830adc55d3216a7b5c939bf220370797..dab359aba4d82e77d68639e6075f9ce0f8729e54 100644 (file)
@@ -244,11 +244,58 @@ yasm_intnum_create_charconst_nasm(const char *str)
         case 0:
             break;
         default:
-            /* >32 bit conversion */
+            /* >=32 bit conversion */
             while (len) {
                 BitVector_Move_Left(conv_bv, 8);
                 BitVector_Chunk_Store(conv_bv, 8, 0,
-                                      (unsigned long)str[--len]);
+                                      ((unsigned long)str[--len]) & 0xff);
+            }
+            intn->val.bv = BitVector_Clone(conv_bv);
+    }
+
+    return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_charconst_tasm(const char *str)
+{
+    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+    size_t len = strlen(str);
+
+    if(len*8 > BITVECT_NATIVE_SIZE)
+        yasm_error_set(YASM_ERROR_OVERFLOW,
+                       N_("Character constant too large for internal format"));
+
+    /* be conservative in choosing bitvect in case MSB is set */
+    if (len > 3) {
+        BitVector_Empty(conv_bv);
+        intn->type = INTNUM_BV;
+    } else {
+        intn->val.l = 0;
+        intn->type = INTNUM_L;
+    }
+
+    /* tasm uses big endian notation */
+    int i = 0;
+    switch (len) {
+        case 3:
+            intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+            intn->val.l <<= 8;
+            /*@fallthrough@*/
+        case 2:
+            intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+            intn->val.l <<= 8;
+            /*@fallthrough@*/
+        case 1:
+            intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+        case 0:
+            break;
+        default:
+            /* >=32 bit conversion */
+            while (i < len) {
+                BitVector_Chunk_Store(conv_bv, 8, (len-i-1)*8,
+                                      ((unsigned long)str[i]) & 0xff);
+                i++;
             }
             intn->val.bv = BitVector_Clone(conv_bv);
     }
index 8e1529fc1dae58b7b59c457282c2330916e87022..132e8b005425c599d4addc6ff99eb1be9242203c 100644 (file)
@@ -76,13 +76,22 @@ YASM_LIB_DECL
 
 /** Convert character constant to integer value, using NASM rules.  NASM syntax
  * supports automatic conversion from strings such as 'abcd' to a 32-bit
- * integer value.  This function performs those conversions.
+ * integer value (little endian order).  This function performs those conversions.
  * \param str       character constant string
  * \return Newly allocated intnum.
  */
 YASM_LIB_DECL
 /*@only@*/ yasm_intnum *yasm_intnum_create_charconst_nasm(const char *str);
 
+/** Convert character constant to integer value, using TASM rules.  TASM syntax
+ * supports automatic conversion from strings such as 'abcd' to a 32-bit
+ * integer value (big endian order).  This function performs those conversions.
+ * \param str       character constant string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_tasm(const char *str);
+
 /** Create a new intnum from an unsigned integer value.
  * \param i         unsigned integer value
  * \return Newly allocated intnum.
index 4ea0ca7e46a80ea7519087ff5e17f25e7a6fa3af..6ebfc1c6b6268c7325cbbba9bea0e5ad1f273b99 100644 (file)
@@ -28,6 +28,7 @@
 /*@unused@*/ RCSID("$Id$");
 
 #include <limits.h>
+#include <ctype.h>
 
 #include "libyasm-stdint.h"
 #include "coretype.h"
@@ -71,6 +72,8 @@ struct yasm_symrec {
         /* bytecode immediately preceding a label */
         /*@dependent@*/ yasm_bytecode *precbc;
     } value;
+    unsigned int size;          /* 0 if not user-defined */
+    const char *segment;        /* for segmented systems like DOS */
 
     /* associated data; NULL if none */
     /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
@@ -87,6 +90,8 @@ struct yasm_symtab {
     /*@only@*/ HAMT *sym_table;
     /* Symbols not in the table */
     SLIST_HEAD(nontablesymhead_s, non_table_symrec_s) non_table_syms;
+
+    int case_sensitive;
 };
 
 static void
@@ -132,9 +137,16 @@ yasm_symtab_create(void)
     yasm_symtab *symtab = yasm_xmalloc(sizeof(yasm_symtab));
     symtab->sym_table = HAMT_create(0, yasm_internal_error_);
     SLIST_INIT(&symtab->non_table_syms);
+    symtab->case_sensitive = 1;
     return symtab;
 }
 
+void
+yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive)
+{
+    symtab->case_sensitive = sensitive;
+}
+
 static void
 symrec_destroy_one(/*@only@*/ void *d)
 {
@@ -147,15 +159,24 @@ symrec_destroy_one(/*@only@*/ void *d)
 }
 
 static /*@partial@*/ yasm_symrec *
-symrec_new_common(/*@keep@*/ char *name)
+symrec_new_common(/*@keep@*/ char *name, int case_sensitive)
 {
     yasm_symrec *rec = yasm_xmalloc(sizeof(yasm_symrec));
+
+    if (!case_sensitive) {
+        char *c;
+        for (c=name; *c; c++)
+            *c = tolower(*c);
+    }
+
     rec->name = name;
     rec->type = SYM_UNKNOWN;
     rec->def_line = 0;
     rec->decl_line = 0;
     rec->use_line = 0;
     rec->visibility = YASM_SYM_LOCAL;
+    rec->size = 0;
+    rec->segment = NULL;
     rec->assoc_data = NULL;
     return rec;
 }
@@ -163,11 +184,17 @@ symrec_new_common(/*@keep@*/ char *name)
 static /*@partial@*/ /*@dependent@*/ yasm_symrec *
 symtab_get_or_new_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
 {
-    yasm_symrec *rec = symrec_new_common(name);
+    yasm_symrec *rec = symrec_new_common(name, symtab->case_sensitive);
     int replace = 0;
 
     rec->status = YASM_SYM_NOSTATUS;
 
+    if (!symtab->case_sensitive) {
+        char *c;
+        for (c=name; *c; c++)
+            *c = tolower(*c);
+    }
+
     return HAMT_insert(symtab->sym_table, name, rec, &replace,
                        symrec_destroy_one);
 }
@@ -176,7 +203,7 @@ static /*@partial@*/ /*@dependent@*/ yasm_symrec *
 symtab_get_or_new_not_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
 {
     non_table_symrec *sym = yasm_xmalloc(sizeof(non_table_symrec));
-    sym->rec = symrec_new_common(name);
+    sym->rec = symrec_new_common(name, symtab->case_sensitive);
 
     sym->rec->status = YASM_SYM_NOTINTABLE;
 
@@ -251,7 +278,17 @@ yasm_symtab_use(yasm_symtab *symtab, const char *name, unsigned long line)
 yasm_symrec *
 yasm_symtab_get(yasm_symtab *symtab, const char *name)
 {
-    return HAMT_search(symtab->sym_table, name);
+    if (!symtab->case_sensitive) {
+        char *_name = yasm__xstrdup(name);
+        char *c;
+        yasm_symrec *ret;
+        for (c=_name; *c; c++)
+            *c = tolower(*c);
+        ret = HAMT_search(symtab->sym_table, _name);
+        yasm_xfree(_name);
+        return ret;
+    } else
+      return HAMT_search(symtab->sym_table, name);
 }
 
 static /*@dependent@*/ yasm_symrec *
@@ -273,6 +310,8 @@ symtab_define(yasm_symtab *symtab, const char *name, sym_type type,
         rec->def_line = line;   /* set line number of definition */
         rec->type = type;
         rec->status |= YASM_SYM_DEFINED;
+        rec->size = 0;
+        rec->segment = NULL;
     }
     return rec;
 }
@@ -519,6 +558,30 @@ yasm_symrec_get_label(const yasm_symrec *sym,
     return 1;
 }
 
+void
+yasm_symrec_set_size(yasm_symrec *sym, int size)
+{
+    sym->size = size;
+}
+
+int
+yasm_symrec_get_size(const yasm_symrec *sym)
+{
+    return sym->size;
+}
+
+void
+yasm_symrec_set_segment(yasm_symrec *sym, const char *segment)
+{
+    sym->segment = segment;
+}
+
+const char *
+yasm_symrec_get_segment(const yasm_symrec *sym)
+{
+    return sym->segment;
+}
+
 int
 yasm_symrec_is_abs(const yasm_symrec *sym)
 {
index 94dca89da78a7f0886ed03bf8a891abad7703299..0eac87bf0cabe1ceee01dd8fbce6c69b4daa65fc 100644 (file)
@@ -73,6 +73,14 @@ yasm_symtab *yasm_symtab_create(void);
 YASM_LIB_DECL
 void yasm_symtab_destroy(/*@only@*/ yasm_symtab *symtab);
 
+/** Set the symbol table to be case sensitive or not.
+ * Should be called before adding any symbol.
+ * \param symtab    symbol table
+ * \param sensitive whether the symbol table should be case sensitive.
+ */
+YASM_LIB_DECL
+void yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive);
+
 /** Get a reference to the symbol table's "absolute" symbol.  This is
  * essentially an EQU with no name and value 0, and is used for relocating
  * absolute current-position-relative values.
@@ -318,6 +326,30 @@ YASM_LIB_DECL
 int yasm_symrec_get_label(const yasm_symrec *sym,
                           /*@out@*/ yasm_symrec_get_label_bytecodep *precbc);
 
+/** Set the size of a symbol.
+ * \param sym       symbol
+ * \param size      size to be set
+ */
+void yasm_symrec_set_size(yasm_symrec *sym, int size);
+
+/** Get the size of a symbol.
+ * \param sym       symbol
+ * \return size of the symbol, 0 if none specified by the user.
+ */
+int yasm_symrec_get_size(const yasm_symrec *sym);
+
+/** Set the segment of a symbol.
+ * \param sym       symbol
+ * \param segment   segment to be set
+ */
+void yasm_symrec_set_segment(yasm_symrec *sym, const char *segment);
+
+/** Get the segment of a symbol.
+ * \param sym       symbol
+ * \return segment of the symbol, NULL if none specified by the user.
+ */
+const char *yasm_symrec_get_segment(const yasm_symrec *sym);
+
 /** Determine if symbol is the "absolute" symbol created by
  * yasm_symtab_abs_sym().
  * \param sym       symbol
index 35965248bfc1a9ea73908149184715eb2401357e..a5d0192be899985f0ca403c8ca0a0e8451a6cd83 100644 (file)
@@ -53,6 +53,7 @@ static const yasm_bytecode_callback lc3b_bc_callback_insn = {
     lc3b_bc_insn_destroy,
     lc3b_bc_insn_print,
     yasm_bc_finalize_common,
+    NULL,
     lc3b_bc_insn_calc_len,
     lc3b_bc_insn_expand,
     lc3b_bc_insn_tobytes,
index bfbf78b213466883fa7417bcc5e6c5c224362966..de8a2bdfb287d18b860e21c42aa6fe8c64119761 100644 (file)
@@ -128,6 +128,7 @@ static const yasm_bytecode_callback lc3b_id_insn_callback = {
     lc3b_id_insn_destroy,
     lc3b_id_insn_print,
     lc3b_id_insn_finalize,
+    NULL,
     yasm_bc_calc_len_common,
     yasm_bc_expand_common,
     yasm_bc_tobytes_common,
index 4a7c715ca0f41d1ddb740d2b7c659902fc109f58..6397d9c97079dc403c2c04a1c430201955cf5e5b 100755 (executable)
@@ -671,7 +671,7 @@ add_group("twobytemem",
     modifiers=["SpAdd", "Op0Add", "Op1Add"],
     opcode=[0x00, 0x00],
     spare=0,
-    operands=[Operand(type="Mem", dest="EA")])
+    operands=[Operand(type="Mem", relaxed=True, dest="EA")])
 
 #
 # mov
@@ -1666,7 +1666,7 @@ for sfx, sz in zip("wlq", [16, 32, 64]):
         opersize=sz,
         opcode=[0x8D],
         operands=[Operand(type="Reg", size=sz, dest="Spare"),
-                  Operand(type="Mem", size=sz, relaxed=True, dest="EA")])
+                  Operand(type="Mem", relaxed=True, dest="EA")])
 
 add_insn("lea", "lea")
 
@@ -1681,7 +1681,7 @@ for sfx, sz in zip("wl", [16, 32]):
         opersize=sz,
         opcode=[0x00],
         operands=[Operand(type="Reg", size=sz, dest="Spare"),
-                  Operand(type="Mem", dest="EA")])
+                  Operand(type="Mem", relaxed=True, dest="EA")])
 
 add_insn("lds", "ldes", modifiers=[0xC5])
 add_insn("les", "ldes", modifiers=[0xC4])
@@ -1694,7 +1694,7 @@ for sfx, sz in zip("wl", [16, 32]):
         opersize=sz,
         opcode=[0x0F, 0x00],
         operands=[Operand(type="Reg", size=sz, dest="Spare"),
-                  Operand(type="Mem", dest="EA")])
+                  Operand(type="Mem", relaxed=True, dest="EA")])
 
 add_insn("lfs", "lfgss", modifiers=[0xB4])
 add_insn("lgs", "lfgss", modifiers=[0xB5])
index a324aa53ca9d8a3508680d3d8a3ea1b8a0372865..4f83c1edf3b01fd92d980dac4c34d41de7a518da 100644 (file)
@@ -84,8 +84,8 @@ EXTRA_DIST += modules/arch/x86/tests/jmp64-6.asm
 EXTRA_DIST += modules/arch/x86/tests/jmp64-6.hex
 EXTRA_DIST += modules/arch/x86/tests/jmpfar.asm
 EXTRA_DIST += modules/arch/x86/tests/jmpfar.hex
-EXTRA_DIST += modules/arch/x86/tests/lds-err.asm
-EXTRA_DIST += modules/arch/x86/tests/lds-err.errwarn
+EXTRA_DIST += modules/arch/x86/tests/lds.asm
+EXTRA_DIST += modules/arch/x86/tests/lds.hex
 EXTRA_DIST += modules/arch/x86/tests/loopadsz.asm
 EXTRA_DIST += modules/arch/x86/tests/loopadsz.hex
 EXTRA_DIST += modules/arch/x86/tests/lsahf.asm
diff --git a/modules/arch/x86/tests/lds-err.errwarn b/modules/arch/x86/tests/lds-err.errwarn
deleted file mode 100644 (file)
index e29dc72..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
--:2: error: invalid size for operand 2
--:3: error: invalid size for operand 2
--:5: error: invalid size for operand 2
--:6: error: invalid size for operand 2
diff --git a/modules/arch/x86/tests/lds.hex b/modules/arch/x86/tests/lds.hex
new file mode 100644 (file)
index 0000000..c390954
--- /dev/null
@@ -0,0 +1,27 @@
+c5 
+06 
+01 
+00 
+c5 
+06 
+01 
+00 
+c5 
+06 
+01 
+00 
+66 
+c5 
+06 
+01 
+00 
+66 
+c5 
+06 
+01 
+00 
+66 
+c5 
+06 
+01 
+00 
index 9ad3cda0bc991d0642b85c407a93f62a938da5b3..1b272f4bfecdd4f24953411b5839c2713d813113 100644 (file)
@@ -71,6 +71,8 @@ x86_create(const char *machine, const char *parser,
 
     if (yasm__strcasecmp(parser, "nasm") == 0)
         arch_x86->parser = X86_PARSER_NASM;
+    else if (yasm__strcasecmp(parser, "tasm") == 0)
+        arch_x86->parser = X86_PARSER_TASM;
     else if (yasm__strcasecmp(parser, "gas") == 0
              || yasm__strcasecmp(parser, "gnu") == 0)
         arch_x86->parser = X86_PARSER_GAS;
index 2491b3bcf4e9986a738701cb9cab244922473fc8..adcc87eae9388e171b1165b19febc753fe7d7240 100644 (file)
@@ -82,7 +82,8 @@ typedef struct yasm_arch_x86 {
     unsigned int amd64_machine;
     enum {
         X86_PARSER_NASM = 0,
-        X86_PARSER_GAS = 1
+        X86_PARSER_TASM = 1,
+        X86_PARSER_GAS = 2
     } parser;
     unsigned int mode_bits;
     unsigned int force_strict;
index 5f542432fb787f555941f5531a8de25091d0d214..adf08c9ab58cc54dde9b62484e36a7c2320b0ed9 100644 (file)
@@ -76,6 +76,7 @@ static const yasm_bytecode_callback x86_bc_callback_insn = {
     x86_bc_insn_destroy,
     x86_bc_insn_print,
     yasm_bc_finalize_common,
+    NULL,
     x86_bc_insn_calc_len,
     x86_bc_insn_expand,
     x86_bc_insn_tobytes,
@@ -86,6 +87,7 @@ static const yasm_bytecode_callback x86_bc_callback_jmp = {
     x86_bc_jmp_destroy,
     x86_bc_jmp_print,
     yasm_bc_finalize_common,
+    NULL,
     x86_bc_jmp_calc_len,
     x86_bc_jmp_expand,
     x86_bc_jmp_tobytes,
@@ -96,6 +98,7 @@ static const yasm_bytecode_callback x86_bc_callback_jmpfar = {
     x86_bc_jmpfar_destroy,
     x86_bc_jmpfar_print,
     yasm_bc_finalize_common,
+    NULL,
     x86_bc_jmpfar_calc_len,
     yasm_bc_expand_common,
     x86_bc_jmpfar_tobytes,
@@ -192,6 +195,7 @@ ea_create(void)
     x86_ea->ea.segreg = 0;
     x86_ea->ea.pc_rel = 0;
     x86_ea->ea.not_pc_rel = 0;
+    x86_ea->ea.data_len = 0;
     x86_ea->modrm = 0;
     x86_ea->valid_modrm = 0;
     x86_ea->need_modrm = 0;
@@ -254,6 +258,8 @@ yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e)
      */
     x86_ea->need_sib = 0xff;
 
+    x86_ea->ea.data_len = 0;
+
     return (yasm_effaddr *)x86_ea;
 }
 
index f7ace08a97aead3a3c027f677a930e7a9f350821..b141a1210e56385b986d961513f8349a29629857 100644 (file)
@@ -422,7 +422,7 @@ x86_checkea_calc_displen(x86_effaddr *x86_ea, unsigned int wordsize, int noreg,
              * EA.  With no registers, we must have a 16/32 value.
              */
             if (noreg) {
-                yasm_warn_set(YASM_WARN_GENERAL,
+                yasm_warn_set(YASM_WARN_IMPLICIT_SIZE_OVERRIDE,
                               N_("invalid displacement size; fixed"));
                 x86_ea->ea.disp.size = wordsize;
             } else
index 2e51a4339f451fd01057007420559d65328b451a..29926adae7bc2c980923ff64f9a28cbba96e7eca 100644 (file)
@@ -350,6 +350,7 @@ static const yasm_bytecode_callback x86_id_insn_callback = {
     x86_id_insn_destroy,
     x86_id_insn_print,
     x86_id_insn_finalize,
+    NULL,
     yasm_bc_calc_len_common,
     yasm_bc_expand_common,
     yasm_bc_tobytes_common,
@@ -1733,6 +1734,9 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
         case X86_PARSER_NASM:
             pdata = insnprefix_nasm_find(lcaseid, id_len);
             break;
+        case X86_PARSER_TASM:
+            pdata = insnprefix_nasm_find(lcaseid, id_len);
+            break;
         case X86_PARSER_GAS:
             pdata = insnprefix_gas_find(lcaseid, id_len);
             break;
index ab14b143da55d85d7c5abbc8c1bac6d5a401a4a8..0a8062267bbd2284c78b4d723f745f220d38d2f2 100644 (file)
@@ -201,6 +201,7 @@ static const yasm_bytecode_callback cv8_symhead_bc_callback = {
     cv8_symhead_bc_destroy,
     cv8_symhead_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     cv8_symhead_bc_calc_len,
     yasm_bc_expand_common,
     cv8_symhead_bc_tobytes,
@@ -211,6 +212,7 @@ static const yasm_bytecode_callback cv8_fileinfo_bc_callback = {
     cv8_fileinfo_bc_destroy,
     cv8_fileinfo_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     cv8_fileinfo_bc_calc_len,
     yasm_bc_expand_common,
     cv8_fileinfo_bc_tobytes,
@@ -221,6 +223,7 @@ static const yasm_bytecode_callback cv8_lineinfo_bc_callback = {
     cv8_lineinfo_bc_destroy,
     cv8_lineinfo_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     cv8_lineinfo_bc_calc_len,
     yasm_bc_expand_common,
     cv8_lineinfo_bc_tobytes,
@@ -231,6 +234,7 @@ static const yasm_bytecode_callback cv_sym_bc_callback = {
     cv_sym_bc_destroy,
     cv_sym_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     cv_sym_bc_calc_len,
     yasm_bc_expand_common,
     cv_sym_bc_tobytes,
index 0f2fd5d49f4b57e8c430f94bcf8992356590ad95..862bea43cd0133edf09ee85f144643cb4f36bcf6 100644 (file)
@@ -492,6 +492,7 @@ static const yasm_bytecode_callback cv_type_bc_callback = {
     cv_type_bc_destroy,
     cv_type_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     cv_type_bc_calc_len,
     yasm_bc_expand_common,
     cv_type_bc_tobytes,
index 6e89a13d39ff58d7af2c6f246c728210a2722eb6..d015f5c3b5273eab42f873186c7b97990a71eb61 100644 (file)
@@ -55,6 +55,7 @@ static const yasm_bytecode_callback dwarf2_head_bc_callback = {
     dwarf2_head_bc_destroy,
     dwarf2_head_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     dwarf2_head_bc_calc_len,
     yasm_bc_expand_common,
     dwarf2_head_bc_tobytes,
index 556ca926d9f1aa8e31b060d856d044a12b23c432..dd48098b6ead3a54a7f33778c9f1aa0e2838e398 100644 (file)
@@ -207,6 +207,7 @@ static const yasm_bytecode_callback dwarf2_abbrev_bc_callback = {
     dwarf2_abbrev_bc_destroy,
     dwarf2_abbrev_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     dwarf2_abbrev_bc_calc_len,
     yasm_bc_expand_common,
     dwarf2_abbrev_bc_tobytes,
index d3fa76f2a7801d48eed5c989da6317b3403e04d2..3f7b96ed3bc583322c4fed0711f6b1179af64e7d 100644 (file)
@@ -149,6 +149,7 @@ static const yasm_bytecode_callback dwarf2_spp_bc_callback = {
     dwarf2_spp_bc_destroy,
     dwarf2_spp_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     dwarf2_spp_bc_calc_len,
     yasm_bc_expand_common,
     dwarf2_spp_bc_tobytes,
@@ -159,6 +160,7 @@ static const yasm_bytecode_callback dwarf2_line_op_bc_callback = {
     dwarf2_line_op_bc_destroy,
     dwarf2_line_op_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     dwarf2_line_op_bc_calc_len,
     yasm_bc_expand_common,
     dwarf2_line_op_bc_tobytes,
index 88d573ab700a277af08508a7ca1d53826677ffaf..247639ead2273252563ca243c4a97577e8b2fecf 100644 (file)
@@ -139,6 +139,7 @@ static const yasm_bytecode_callback stabs_bc_str_callback = {
     stabs_bc_str_destroy,
     stabs_bc_str_print,
     yasm_bc_finalize_common,
+    NULL,
     stabs_bc_str_calc_len,
     yasm_bc_expand_common,
     stabs_bc_str_tobytes,
@@ -149,6 +150,7 @@ static const yasm_bytecode_callback stabs_bc_stab_callback = {
     stabs_bc_stab_destroy,
     stabs_bc_stab_print,
     yasm_bc_finalize_common,
+    NULL,
     stabs_bc_stab_calc_len,
     yasm_bc_expand_common,
     stabs_bc_stab_tobytes,
index 4d38b53913137caac3a8d76f7906dacd53b32b07..a7539fe874052a74bd21a793ae679ffaab97cb27 100644 (file)
@@ -2,7 +2,7 @@
 
 libyasm_a_SOURCES += modules/objfmts/bin/bin-objfmt.c
 
-YASM_MODULES += objfmt_bin
+YASM_MODULES += objfmt_bin objfmt_dosexe
 
 EXTRA_DIST += modules/objfmts/bin/tests/Makefile.inc
 
index fc283d71520f36839662d3d82e0b294856b56a56..e05a5acba0e18312321f87a03a81e0fa8565aa75 100644 (file)
@@ -27,6 +27,9 @@
 #include <util.h>
 /*@unused@*/ RCSID("$Id$");
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <libyasm.h>
 
 
@@ -1071,7 +1074,8 @@ bin_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
             yasm_errwarn_propagate(info->errwarns, 0);
             return 0;
         }
-        if (fseek(info->f, yasm_intnum_get_int(info->tmp_intn), SEEK_SET) < 0)
+        if (fseek(info->f, yasm_intnum_get_int(info->tmp_intn) + info->start,
+                  SEEK_SET) < 0)
             yasm__fatal(N_("could not seek on output file"));
         yasm_section_bcs_traverse(sect, info->errwarns,
                                   info, bin_objfmt_output_bytecode);
@@ -1106,6 +1110,8 @@ bin_objfmt_output(yasm_object *object, FILE *f, /*@unused@*/ int all_syms,
     yasm_intnum *start, *last, *vdelta;
     bin_groups unsorted_groups, bss_groups;
 
+    info.start = ftell(f);
+
     /* Set ORG to 0 unless otherwise specified */
     if (objfmt_bin->org) {
         info.origin = yasm_expr_get_intnum(&objfmt_bin->org, 0);
@@ -1782,6 +1788,7 @@ static const char *bin_nasm_stdmac[] = {
 
 static const yasm_stdmac bin_objfmt_stdmacs[] = {
     { "nasm", "nasm", bin_nasm_stdmac },
+    { "tasm", "tasm", bin_nasm_stdmac },
     { NULL, NULL, NULL }
 };
 
@@ -1802,3 +1809,154 @@ yasm_objfmt_module yasm_bin_LTX_objfmt = {
     bin_objfmt_section_switch,
     bin_objfmt_get_special_sym
 };
+
+#define EXE_HEADER_SIZE 0x200
+
+/* DOS .EXE binaries are just raw binaries with a header */
+yasm_objfmt_module yasm_dosexe_LTX_objfmt;
+
+static yasm_objfmt *
+dosexe_objfmt_create(yasm_object *object)
+{
+    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *) bin_objfmt_create(object);
+    objfmt_bin->objfmt.module = &yasm_dosexe_LTX_objfmt;
+    return (yasm_objfmt *)objfmt_bin;
+}
+
+static unsigned long
+get_sym(yasm_object *object, const char *name) {
+    yasm_symrec *symrec = yasm_symtab_get(object->symtab, name);
+    yasm_bytecode *prevbc;
+    if (!symrec)
+        return 0;
+    if (!yasm_symrec_get_label(symrec, &prevbc))
+        return 0;
+    return prevbc->offset + prevbc->len;
+}
+
+static void
+dosexe_objfmt_output(yasm_object *object, FILE *f, /*@unused@*/ int all_syms,
+                  yasm_errwarns *errwarns)
+{
+    unsigned long tot_size, size, bss_size;
+    unsigned long start, bss;
+    unsigned char c;
+
+    fseek(f, EXE_HEADER_SIZE, SEEK_SET);
+
+    bin_objfmt_output(object, f, all_syms, errwarns);
+
+    tot_size = ftell(f);
+
+    /* if there is a __bss_start symbol, data after it is 0, no need to write
+     * it.  */
+    bss = get_sym(object, "__bss_start");
+    if (bss)
+        size = bss;
+    else
+        size = tot_size;
+    bss_size = tot_size - size;
+#ifdef HAVE_FTRUNCATE
+    if (size != tot_size)
+        ftruncate(fileno(f), EXE_HEADER_SIZE + size);
+#endif
+    fseek(f, 0, SEEK_SET);
+
+    /* magic */
+    fwrite("MZ", 1, 2, f);
+
+    /* file size */
+    c = size & 0xff;
+    fwrite(&c, 1, 1, f);
+    c = !!(size & 0x100);
+    fwrite(&c, 1, 1, f);
+    c = ((size + 511) >> 9) & 0xff;
+    fwrite(&c, 1, 1, f);
+    c = ((size + 511) >> 17) & 0xff;
+    fwrite(&c, 1, 1, f);
+
+    /* relocation # */
+    c = 0;
+    fwrite(&c, 1, 1, f);
+    fwrite(&c, 1, 1, f);
+
+    /* header size */
+    c = EXE_HEADER_SIZE / 16;
+    fwrite(&c, 1, 1, f);
+    c = 0;
+    fwrite(&c, 1, 1, f);
+
+    /* minimum paragraph # */
+    bss_size = (bss_size + 15) >> 4;
+    c = bss_size & 0xff;
+    fwrite(&c, 1, 1, f);
+    c = (bss_size >> 8) & 0xff;
+    fwrite(&c, 1, 1, f);
+
+    /* maximum paragraph # */
+    c = 0xFF;
+    fwrite(&c, 1, 1, f);
+    fwrite(&c, 1, 1, f);
+
+    /* relative value of stack segment */
+    c = 0;
+    fwrite(&c, 1, 1, f);
+    fwrite(&c, 1, 1, f);
+
+    /* SP at start */
+    c = 0;
+    fwrite(&c, 1, 1, f);
+    fwrite(&c, 1, 1, f);
+
+    /* header checksum */
+    c = 0;
+    fwrite(&c, 1, 1, f);
+    fwrite(&c, 1, 1, f);
+
+    /* IP at start */
+    start = get_sym(object, "start");
+    if (!start) {
+        yasm_error_set(YASM_ERROR_GENERAL,
+                N_("%s: could not find symbol `start'"));
+        return;
+    }
+    c = start & 0xff;
+    fwrite(&c, 1, 1, f);
+    c = (start >> 8) & 0xff;
+    fwrite(&c, 1, 1, f);
+
+    /* CS start */
+    c = 0;
+    fwrite(&c, 1, 1, f);
+    fwrite(&c, 1, 1, f);
+
+    /* reloc start */
+    c = 0x22;
+    fwrite(&c, 1, 1, f);
+    c = 0;
+    fwrite(&c, 1, 1, f);
+
+    /* Overlay number */
+    c = 0;
+    fwrite(&c, 1, 1, f);
+    fwrite(&c, 1, 1, f);
+}
+
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_dosexe_LTX_objfmt = {
+    "DOS .EXE format binary",
+    "dosexe",
+    "exe",
+    16,
+    bin_objfmt_dbgfmt_keywords,
+    "null",
+    bin_objfmt_directives,
+    bin_objfmt_stdmacs,
+    dosexe_objfmt_create,
+    dosexe_objfmt_output,
+    bin_objfmt_destroy,
+    bin_objfmt_add_default_section,
+    bin_objfmt_section_switch,
+    bin_objfmt_get_special_sym
+};
index 46f6d1ebf7ef2e221ba4d96ec956d97e794fc6fa..448682e22ed9c2a3309ceeacd0b5be9dd463a0b0 100644 (file)
@@ -234,6 +234,7 @@ static const yasm_bytecode_callback win32_sxdata_bc_callback = {
     win32_sxdata_bc_destroy,
     win32_sxdata_bc_print,
     yasm_bc_finalize_common,
+    NULL,
     win32_sxdata_bc_calc_len,
     yasm_bc_expand_common,
     win32_sxdata_bc_tobytes,
index 11ea4bde8ab69a44af483e4507210912ba8febe5..5596eac3724397d27860da3f8bf10897a71221f7 100644 (file)
@@ -72,6 +72,7 @@ static const yasm_bytecode_callback win64_uwinfo_bc_callback = {
     win64_uwinfo_bc_destroy,
     win64_uwinfo_bc_print,
     win64_uwinfo_bc_finalize,
+    NULL,
     win64_uwinfo_bc_calc_len,
     win64_uwinfo_bc_expand,
     win64_uwinfo_bc_tobytes,
@@ -82,6 +83,7 @@ static const yasm_bytecode_callback win64_uwcode_bc_callback = {
     win64_uwcode_bc_destroy,
     win64_uwcode_bc_print,
     win64_uwcode_bc_finalize,
+    NULL,
     win64_uwcode_bc_calc_len,
     win64_uwcode_bc_expand,
     win64_uwcode_bc_tobytes,
index 3af07864f79fe0b9b9908e81c343f5c5e6ea889d..fa604a6fce465438dd7b220a3114ce124ce78fe6 100644 (file)
@@ -1364,7 +1364,7 @@ f8
 00 
 00 
 00 
-17 
+16 
 00 
 00 
 00 
@@ -1374,7 +1374,7 @@ f8
 00 
 00 
 00 
-17 
+16 
 00 
 00 
 00 
@@ -1999,36 +1999,36 @@ a0
 03 
 00 
 78 
-70 
-74 
-72 
 00 
 00 
 00 
 00 
-40 
 00 
 00 
 00 
-02 
 00 
 00 
 00 
-03 
 00 
-78 
+03 
 00 
 00 
 00 
+03 
 00 
+78 
+70 
+74 
+72 
 00 
 00 
 00 
 00 
+40 
 00 
 00 
 00 
-03 
+02 
 00 
 00 
 00 
index 89bfd35b6a36b7d0152c3880f2a947fc2373fd86..a2ab23f33cf76c57a251e7bfaf541c45b61b0c88 100644 (file)
@@ -5,6 +5,7 @@ EXTRA_DIST += modules/parsers/nasm/Makefile.inc
 
 include modules/parsers/gas/Makefile.inc
 include modules/parsers/nasm/Makefile.inc
+include modules/parsers/tasm/Makefile.inc
 
 dist_man_MANS += yasm_parsers.7
 
index ac174ca06f7e4f588a8753265ded2df77c5d7022..7149959d6b5e5c758cb18110faae5d7e8ecc62ab 100644 (file)
@@ -5,7 +5,7 @@ libyasm_a_SOURCES += modules/parsers/nasm/nasm-parser.h
 libyasm_a_SOURCES += modules/parsers/nasm/nasm-parse.c
 nodist_libyasm_a_SOURCES += nasm-token.c
 
-YASM_MODULES += parser_nasm
+YASM_MODULES += parser_nasm parser_tasm
 
 nasm-token.c: $(srcdir)/modules/parsers/nasm/nasm-token.re re2c$(EXEEXT)
        $(top_builddir)/re2c$(EXEEXT) -b -o $@ $(srcdir)/modules/parsers/nasm/nasm-token.re
index cba949f85da946e1b851d7785ac95cb7ba51e1f4..7afd00861b9729ce25dcbc5a1d159426839c9d32 100644 (file)
@@ -32,6 +32,7 @@ RCSID("$Id$");
 #include <math.h>
 
 #include "modules/parsers/nasm/nasm-parser.h"
+#include "modules/preprocs/nasm/nasm.h"
 
 typedef enum {
     NORM_EXPR,
@@ -62,7 +63,23 @@ static void nasm_parser_directive
      /*@null@*/ yasm_valparamhead *valparams,
      /*@null@*/ yasm_valparamhead *objext_valparams);
 static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
-                         int local);
+                         unsigned int size, int local);
+
+static void yasm_ea_set_implicit_size_segment(yasm_parser_nasm *parser_nasm,
+                                              yasm_effaddr *ea, yasm_expr *e)
+{
+    if (tasm_compatible_mode) {
+        const char *segment = yasm_expr_segment(e);
+        ea->data_len = yasm_expr_size(e);
+        if (segment) {
+            const char *segreg = tasm_get_segment_register(segment);
+            if (segreg)
+                yasm_arch_parse_check_regtmod(p_object->arch, segreg,
+                                              strlen(segreg), &ea->segreg);
+        }
+    }
+}
+
 
 #define is_eol_tok(tok) ((tok) == 0)
 #define is_eol()        is_eol_tok(curtok)
@@ -242,11 +259,12 @@ nasm_parser_parse(yasm_parser_nasm *parser_nasm)
                 yasm_bc_destroy(bc);
             }
             temp_bc = NULL;
-        } else {
+        } else if (bc) {
             temp_bc = yasm_section_bcs_append(cursect, bc);
             if (temp_bc)
                 parser_nasm->prev_bc = temp_bc;
-        }
+        } else
+            temp_bc = NULL;
         yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
 
         if (parser_nasm->save_input)
@@ -355,23 +373,33 @@ parse_line(yasm_parser_nasm *parser_nasm)
         case LOCAL_ID:
         {
             char *name = ID_val;
-            int local = (curtok != ID);
+            int local = tasm_compatible_mode
+                ? (curtok == ID || curtok == LOCAL_ID ||
+                        (curtok == SPECIAL_ID && name[0] == '@'))
+                : (curtok != ID);
+            unsigned int size = 0;
 
             get_next_token();
             if (is_eol()) {
                 /* label alone on the line */
                 yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
                     N_("label alone on a line without a colon might be in error"));
-                define_label(parser_nasm, name, local);
+                define_label(parser_nasm, name, 0, local);
                 return NULL;
             }
             if (curtok == ':')
                 get_next_token();
 
-            if (curtok == EQU) {
+            if (curtok == EQU || (tasm_compatible_mode && curtok == '=')) {
                 /* label EQU expr */
                 yasm_expr *e;
                 get_next_token();
+
+                if (tasm_compatible_mode && curtok == SIZE_OVERRIDE) {
+                    size = SIZE_OVERRIDE_val;
+                    get_next_token();
+                }
+
                 e = parse_expr(parser_nasm, NORM_EXPR);
                 if (!e) {
                     yasm_error_set(YASM_ERROR_SYNTAX,
@@ -384,17 +412,30 @@ parse_line(yasm_parser_nasm *parser_nasm)
                 return NULL;
             }
 
-            define_label(parser_nasm, name, local);
-            if (is_eol())
+            if (tasm_compatible_mode && curtok == LABEL)
+                get_next_token();
+
+            if (tasm_compatible_mode && curtok == SIZE_OVERRIDE) {
+                size = SIZE_OVERRIDE_val;
+                get_next_token();
+            }
+
+            if (is_eol()) {
+                define_label(parser_nasm, name, size, local);
                 return NULL;
+            }
             if (curtok == TIMES) {
+                define_label(parser_nasm, name, size, local);
                 get_next_token();
                 return parse_times(parser_nasm);
             }
             bc = parse_exp(parser_nasm);
-            if (!bc)
+            if (!tasm_compatible_mode && !bc)
                 yasm_error_set(YASM_ERROR_SYNTAX,
                                N_("instruction expected after label"));
+            if (tasm_compatible_mode && bc && !size)
+                size = yasm_bc_elem_size(bc);
+            define_label(parser_nasm, name, size, local);
             return bc;
         }
         default:
@@ -510,7 +551,7 @@ parse_exp(yasm_parser_nasm *parser_nasm)
             unsigned int size = DECLARE_DATA_val/8;
             yasm_datavalhead dvs;
             yasm_dataval *dv;
-            yasm_expr *e;
+            yasm_expr *e, *e2;
 
             get_next_token();
 
@@ -529,14 +570,68 @@ parse_exp(yasm_parser_nasm *parser_nasm)
                         goto dv_done;
                     }
                 }
-                if ((e = parse_bexpr(parser_nasm, DV_EXPR)))
-                    dv = yasm_dv_create_expr(e);
-                else {
+                if (curtok == '?') {
+                    yasm_dvs_delete(&dvs);
+                    get_next_token();
+                    if (! is_eol_tok(curtok)) {
+                        yasm_error_set(YASM_ERROR_SYNTAX,
+                                N_("can not handle more than one '?'"));
+                        return NULL;
+                    }
+                    return yasm_bc_create_reserve(
+                            p_expr_new_ident(yasm_expr_int(
+                                yasm_intnum_create_uint(1))),
+                            size, cur_line);
+                }
+                if (!(e = parse_bexpr(parser_nasm, DV_EXPR))) {
                     yasm_error_set(YASM_ERROR_SYNTAX,
                                    N_("expression or string expected"));
                     yasm_dvs_delete(&dvs);
                     return NULL;
                 }
+                if (curtok == DUP) {
+                    get_next_token();
+                    if (curtok != '(') {
+                        yasm_error_set(YASM_ERROR_SYNTAX,
+                                       N_("expected ( after DUP"));
+                        goto error;
+                    }
+                    get_next_token();
+                    if (curtok == '?') {
+                        get_next_token();
+                        if (curtok != ')') {
+                            yasm_error_set(YASM_ERROR_SYNTAX,
+                                N_("expected ) after DUPlicated expression"));
+                            goto error;
+                        }
+                        get_next_token();
+                        if (! is_eol_tok(curtok)) {
+                            yasm_error_set(YASM_ERROR_SYNTAX,
+                                    N_("can not handle more than one '?'"));
+                            goto error;
+                        }
+                        yasm_dvs_delete(&dvs);
+                        return yasm_bc_create_reserve(e, size, cur_line);
+                    } else if ((e2 = parse_bexpr(parser_nasm, DV_EXPR))) {
+                        if (curtok != ')') {
+                            yasm_expr_destroy(e2);
+                            yasm_error_set(YASM_ERROR_SYNTAX,
+                                N_("expected ) after DUPlicated expression"));
+                            goto error;
+                        }
+                        get_next_token();
+                        dv = yasm_dv_create_expr(e2);
+                        yasm_dv_set_multiple(dv, e);
+                    } else {
+                        yasm_error_set(YASM_ERROR_SYNTAX,
+                                       N_("expression or string expected"));
+error:
+                        yasm_expr_destroy(e);
+                        yasm_dvs_delete(&dvs);
+                        return NULL;
+                    }
+                } else
+                    dv = yasm_dv_create_expr(e);
 dv_done:
                 yasm_dvs_append(&dvs, dv);
                 if (is_eol())
@@ -699,12 +794,104 @@ parse_operand(yasm_parser_nasm *parser_nasm)
                                N_("memory address expected"));
                 return NULL;
             }
+
+            if (tasm_compatible_mode && !is_eol() && curtok != ',') {
+                yasm_expr *e, *f;
+                yasm_effaddr *ea;
+
+                switch (op->type) {
+                    case YASM_INSN__OPERAND_IMM:
+                        e = op->data.val;
+                        break;
+                    case YASM_INSN__OPERAND_MEMORY:
+                        if (op->data.ea->disp.rel) {
+                            yasm_error_set(YASM_ERROR_SYNTAX,
+                                    N_("relative adressing not supported\n"));
+                            return NULL;
+                        }
+                        e = yasm_expr_copy(op->data.ea->disp.abs);
+                        yasm_arch_ea_destroy(p_object->arch, op->data.ea);
+                        break;
+                    case YASM_INSN__OPERAND_REG:
+                    case YASM_INSN__OPERAND_SEGREG:
+                        yasm_error_set(YASM_ERROR_SYNTAX,
+                                N_("register adressing not supported\n"));
+                        return NULL;
+                }
+                yasm_xfree(op);
+                f = parse_bexpr(parser_nasm, NORM_EXPR);
+                if (!f) {
+                    yasm_expr_destroy(e);
+                    yasm_error_set(YASM_ERROR_SYNTAX,
+                                   N_("expected expression after ]"));
+                    return NULL;
+                }
+                e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+                ea = yasm_arch_ea_create(p_object->arch, e);
+                yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+                op = yasm_operand_create_mem(ea);
+            }
             return op;
         }
+        case OFFSET:
+        {
+            yasm_insn_operand *op2;
+            get_next_token();
+            op = parse_operand(parser_nasm);
+            if (!op) {
+                yasm_error_set(YASM_ERROR_SYNTAX,
+                               N_("memory address expected"));
+                return NULL;
+            }
+            if (op->type == YASM_INSN__OPERAND_IMM)
+                return op;
+            if (op->type != YASM_INSN__OPERAND_MEMORY) {
+                yasm_error_set(YASM_ERROR_SYNTAX,
+                               N_("OFFSET applied to non-memory operand"));
+                return NULL;
+            }
+            if (op->data.ea->disp.rel) {
+                yasm_error_set(YASM_ERROR_SYNTAX,
+                               N_("OFFSET applied to non-absolute memory operand"));
+                return NULL;
+            }
+            if (op->data.ea->disp.abs)
+                op2 = yasm_operand_create_imm(op->data.ea->disp.abs);
+            else
+                op2 = yasm_operand_create_imm(p_expr_new_ident(
+                        yasm_expr_int(yasm_intnum_create_uint(0))));
+            yasm_xfree(op);
+            return op2;
+        }
         case SEGREG:
-            op = yasm_operand_create_segreg(SEGREG_val);
+        {
+            uintptr_t segreg = SEGREG_val;
             get_next_token();
+            if (tasm_compatible_mode && curtok == ':') {
+                get_next_token();
+                op = parse_operand(parser_nasm);
+                if (!op)
+                    return NULL;
+                if (op->type == YASM_INSN__OPERAND_IMM) {
+                    yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch,
+                                                           op->data.val);
+                    yasm_ea_set_implicit_size_segment(parser_nasm, ea, op->data.val);
+                    yasm_insn_operand *op2 = yasm_operand_create_mem(ea);
+                    op2->size = op->size;
+                    yasm_xfree(op);
+                    op = op2;
+                }
+                if (op->type != YASM_INSN__OPERAND_MEMORY) {
+                    yasm_error_set(YASM_ERROR_SYNTAX,
+                                   N_("segment applied to non-memory operand"));
+                    return NULL;
+                }
+                yasm_ea_set_segreg(op->data.ea, segreg);
+                return op;
+            }
+            op = yasm_operand_create_segreg(segreg);
             return op;
+        }
         case REG:
             op = yasm_operand_create_reg(REG_val);
             get_next_token();
@@ -756,13 +943,51 @@ parse_operand(yasm_parser_nasm *parser_nasm)
                 op->targetmod = tmod;
             return op;
         }
+        case ID:
+        case LOCAL_ID:
+        case NONLOCAL_ID:
+            if (tasm_compatible_mode) {
+                get_peek_token(parser_nasm);
+                if (parser_nasm->peek_token == '[') {
+                    yasm_symrec *sym = yasm_symtab_use(p_symtab, ID_val,
+                                                       cur_line);
+                    yasm_expr *e = p_expr_new_ident(yasm_expr_sym(sym)), *f;
+                    yasm_effaddr *ea;
+                    yasm_xfree(ID_val);
+                    get_next_token();
+                    get_next_token();
+                    f = parse_bexpr(parser_nasm, NORM_EXPR);
+                    if (!f) {
+                        yasm_error_set(YASM_ERROR_SYNTAX,
+                                       N_("expected expression after ["));
+                        return NULL;
+                    }
+                    e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+                    if (!expect(']')) {
+                        yasm_error_set(YASM_ERROR_SYNTAX, N_("missing closing bracket"));
+                        return NULL;
+                    }
+                    get_next_token();
+                    ea = yasm_arch_ea_create(p_object->arch, e);
+                    yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+                    op = yasm_operand_create_mem(ea);
+                    return op;
+                }
+            }
+            /* Fallthrough */
         default:
         {
             yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
             if (!e)
                 return NULL;
             if (curtok != ':')
-                return yasm_operand_create_imm(e);
+                if (tasm_compatible_mode && yasm_expr_size(e)) {
+                    yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
+                    yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+                    op = yasm_operand_create_mem(ea);
+                    return op;
+                } else
+                    return yasm_operand_create_imm(e);
             else {
                 yasm_expr *off;
                 get_next_token();
@@ -836,10 +1061,12 @@ parse_memaddr(yasm_parser_nasm *parser_nasm)
             yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
             if (!e)
                 return NULL;
-            if (curtok != ':')
-                return yasm_operand_create_mem(
-                    yasm_arch_ea_create(p_object->arch, e));
-            else {
+            if (curtok != ':') {
+                yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
+                yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+                return yasm_operand_create_mem(ea);
+            } else {
+                yasm_effaddr *ea;
                 yasm_expr *off;
                 get_next_token();
                 off = parse_bexpr(parser_nasm, NORM_EXPR);
@@ -847,8 +1074,9 @@ parse_memaddr(yasm_parser_nasm *parser_nasm)
                     yasm_expr_destroy(e);
                     return NULL;
                 }
-                op = yasm_operand_create_mem(
-                    yasm_arch_ea_create(p_object->arch, off));
+                ea = yasm_arch_ea_create(p_object->arch, off);
+                yasm_ea_set_implicit_size_segment(parser_nasm, ea, off);
+                op = yasm_operand_create_mem(ea);
                 op->seg = e;
                 return op;
             }
@@ -1094,6 +1322,30 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
                 return NULL;
             }
             return p_expr_new_branch(YASM_EXPR_NOT, e);
+        case LOW:
+            get_next_token();
+            e = parse_expr6(parser_nasm, type);
+            if (!e) {
+                yasm_error_set(YASM_ERROR_SYNTAX,
+                               N_("expected expression after %s"), "LOW");
+                return NULL;
+            }
+            return p_expr_new_tree(e, YASM_EXPR_AND,
+                p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
+        case HIGH:
+            get_next_token();
+            e = parse_expr6(parser_nasm, type);
+            if (!e) {
+                yasm_error_set(YASM_ERROR_SYNTAX,
+                               N_("expected expression after %s"), "HIGH");
+                return NULL;
+            }
+            return p_expr_new_tree(
+                p_expr_new_tree(e, YASM_EXPR_SHR,
+                    p_expr_new_ident(yasm_expr_int(
+                        yasm_intnum_create_uint(8)))),
+                YASM_EXPR_AND,
+                p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
         case SEG:
             get_next_token();
             e = parse_expr6(parser_nasm, type);
@@ -1132,10 +1384,16 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
             e = p_expr_new_ident(yasm_expr_reg(REG_val));
             break;
         case STRING:
-            e = p_expr_new_ident(yasm_expr_int(
-                yasm_intnum_create_charconst_nasm(STRING_val.contents)));
+        {
+            yasm_intnum *intn;
+            if (tasm_compatible_mode)
+                intn = yasm_intnum_create_charconst_tasm(STRING_val.contents);
+            else
+                intn = yasm_intnum_create_charconst_nasm(STRING_val.contents);
+            e = p_expr_new_ident(yasm_expr_int(intn));
             yasm_xfree(STRING_val.contents);
             break;
+        }
         case SPECIAL_ID:
             sym = yasm_objfmt_get_special_sym(p_object, ID_val+2, "nasm");
             if (sym) {
@@ -1179,9 +1437,12 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
 }
 
 static void
-define_label(yasm_parser_nasm *parser_nasm, char *name, int local)
+define_label(yasm_parser_nasm *parser_nasm, char *name, unsigned int size,
+             int local)
 {
-    if (!local) {
+    yasm_symrec *symrec;
+
+    if ((!tasm_compatible_mode || tasm_locals) && !local) {
         if (parser_nasm->locallabel_base)
             yasm_xfree(parser_nasm->locallabel_base);
         parser_nasm->locallabel_base_len = strlen(name);
@@ -1191,11 +1452,16 @@ define_label(yasm_parser_nasm *parser_nasm, char *name, int local)
     }
 
     if (parser_nasm->abspos)
-        yasm_symtab_define_equ(p_symtab, name,
-                               yasm_expr_copy(parser_nasm->abspos), cur_line);
+        symrec = yasm_symtab_define_equ(p_symtab, name,
+                                        yasm_expr_copy(parser_nasm->abspos),
+                                        cur_line);
     else
-        yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc, 1,
-                                 cur_line);
+        symrec = yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc,
+                                          1, cur_line);
+
+    yasm_symrec_set_size(symrec, size);
+    yasm_symrec_set_segment(symrec, tasm_segment);
+
     yasm_xfree(name);
 }
 
index ac10de377c100becc58ab3f2bd923f2677708338..12070061fb89f306fed2fdd3101ff89afc9fd9c4 100644 (file)
@@ -31,6 +31,8 @@
 
 #include "nasm-parser.h"
 
+#include "modules/preprocs/nasm/nasm.h"
+
 
 static void
 nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
@@ -100,3 +102,36 @@ yasm_parser_module yasm_nasm_LTX_parser = {
     nasm_parser_stdmacs,
     nasm_parser_do_parse
 };
+
+static void
+tasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+                     int save_input, yasm_linemap *linemap,
+                     yasm_errwarns *errwarns)
+{
+    tasm_compatible_mode = 1;
+    yasm_symtab_set_case_sensitive(object->symtab, 0);
+    yasm_warn_disable(YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
+    nasm_parser_do_parse(object, pp, save_input, linemap, errwarns);
+}
+
+/* Define valid preprocessors to use with this parser */
+static const char *tasm_parser_preproc_keywords[] = {
+    "raw",
+    "tasm",
+    NULL
+};
+
+static const yasm_stdmac tasm_parser_stdmacs[] = {
+    { "tasm", "tasm", nasm_standard_mac },
+    { NULL, NULL, NULL }
+};
+
+/* Define parser structure -- see parser.h for details */
+yasm_parser_module yasm_tasm_LTX_parser = {
+    "TASM-compatible parser",
+    "tasm",
+    tasm_parser_preproc_keywords,
+    "tasm",
+    tasm_parser_stdmacs,
+    tasm_parser_do_parse
+};
index c6148a7b65a86323cf939e11fa9a334d63f06417..63127589b2aa0b8502368138e51a847aa79fa17a 100644 (file)
@@ -38,11 +38,14 @@ enum tokentype {
     FILENAME,
     STRING,
     SIZE_OVERRIDE,
+    OFFSET,
     DECLARE_DATA,
     RESERVE_SPACE,
+    LABEL,
     INCBIN,
     EQU,
     TIMES,
+    DUP,
     SEG,
     WRT,
     ABS,
@@ -56,6 +59,8 @@ enum tokentype {
     TARGETMOD,
     LEFT_OP,
     RIGHT_OP,
+    LOW,
+    HIGH,
     SIGNDIV,
     SIGNMOD,
     START_SECTION_ID,
index cc589b18c77e2e6e410af09f0f75c4d3e1e29c9c..72e15080e533b6b96ae02a86deb2e7d45caf726c 100644 (file)
@@ -32,6 +32,7 @@ RCSID("$Id$");
 #include <libyasm.h>
 
 #include "modules/parsers/nasm/nasm-parser.h"
+#include "modules/preprocs/nasm/nasm.h"
 
 
 #define YYCURSOR        cursor
@@ -76,13 +77,22 @@ handle_dot_label(YYSTYPE *lvalp, char *tok, size_t toklen, size_t zeropos,
 {
     /* check for special non-local labels like ..start */
     if (tok[zeropos+1] == '.') {
-        lvalp->str_val = yasm__xstrndup(tok+zeropos, toklen-zeropos);
+        lvalp->str_val = yasm__xstrndup(tok+zeropos+(tasm_compatible_mode?2:0),
+            toklen-zeropos-(tasm_compatible_mode?2:0));
         /* check for special non-local ..@label */
         if (lvalp->str_val[zeropos+2] == '@')
             return NONLOCAL_ID;
         return SPECIAL_ID;
     }
-
+    if (tasm_compatible_mode && (!tasm_locals || 
+                (tok[zeropos] == '.' &&
+                 tok[zeropos+1] != '@' && tok[zeropos+2] != '@'))) {
+        /* no locals on Tasm without the 'locals' directive */
+        /* .foo is never local either, but .@@foo may be (local structure
+         * members) */
+        lvalp->str_val = yasm__xstrndup(tok + zeropos, toklen - zeropos);
+        return SPECIAL_ID;
+    }
     if (!parser_nasm->locallabel_base) {
         lvalp->str_val = yasm__xstrndup(tok+zeropos, toklen-zeropos);
         yasm_warn_set(YASM_WARN_GENERAL,
@@ -242,65 +252,95 @@ scan:
         }
 
         /* pseudo-instructions */
-        'db'            { lvalp->int_info = 8; RETURN(DECLARE_DATA); }
+        'db'            {
+            lvalp->int_info = 8;
+            parser_nasm->state = INSTRUCTION;
+            RETURN(DECLARE_DATA);
+        }
         'dhw'           {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
+            parser_nasm->state = INSTRUCTION;
             RETURN(DECLARE_DATA);
         }
         'dw'            {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch);
+            parser_nasm->state = INSTRUCTION;
             RETURN(DECLARE_DATA);
         }
         'dd'            {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
+            parser_nasm->state = INSTRUCTION;
             RETURN(DECLARE_DATA);
         }
         'dq'            {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
+            parser_nasm->state = INSTRUCTION;
+            RETURN(DECLARE_DATA);
+        }
+        'dt'            {
+            lvalp->int_info = 80;
+            parser_nasm->state = INSTRUCTION;
             RETURN(DECLARE_DATA);
         }
-        'dt'            { lvalp->int_info = 80; RETURN(DECLARE_DATA); }
         'ddq'           {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+            parser_nasm->state = INSTRUCTION;
             RETURN(DECLARE_DATA);
         }
         'do'           {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+            parser_nasm->state = INSTRUCTION;
             RETURN(DECLARE_DATA);
         }
         'dy'           {
             lvalp->int_info = 256;
+            parser_nasm->state = INSTRUCTION;
             RETURN(DECLARE_DATA);
         }
 
-        'resb'          { lvalp->int_info = 8; RETURN(RESERVE_SPACE); }
+        'resb'          {
+            lvalp->int_info = 8;
+            parser_nasm->state = INSTRUCTION;
+            RETURN(RESERVE_SPACE);
+        }
         'reshw'         {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
+            parser_nasm->state = INSTRUCTION;
             RETURN(RESERVE_SPACE);
         }
         'resw'          {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch);
+            parser_nasm->state = INSTRUCTION;
             RETURN(RESERVE_SPACE);
         }
         'resd'          {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
+            parser_nasm->state = INSTRUCTION;
             RETURN(RESERVE_SPACE);
         }
         'resq'          {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
+            parser_nasm->state = INSTRUCTION;
+            RETURN(RESERVE_SPACE);
+        }
+        'rest'          {
+            lvalp->int_info = 80;
+            parser_nasm->state = INSTRUCTION;
             RETURN(RESERVE_SPACE);
         }
-        'rest'          { lvalp->int_info = 80; RETURN(RESERVE_SPACE); }
         'resdq'         {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+            parser_nasm->state = INSTRUCTION;
             RETURN(RESERVE_SPACE);
         }
         'reso'         {
             lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+            parser_nasm->state = INSTRUCTION;
             RETURN(RESERVE_SPACE);
         }
         'resy'         {
             lvalp->int_info = 256;
+            parser_nasm->state = INSTRUCTION;
             RETURN(RESERVE_SPACE);
         }
 
@@ -325,17 +365,18 @@ scan:
         "//"                    { RETURN(SIGNDIV); }
         "%%"                    { RETURN(SIGNMOD); }
         "$$"                    { RETURN(START_SECTION_ID); }
-        [-+|^*&/%~$():=,\[    { RETURN(s->tok[0]); }
+        [-+|^*&/%~$():=,\[?]    { RETURN(s->tok[0]); }
         "]"                     { RETURN(s->tok[0]); }
 
         /* local label (.label) */
-        "." [a-zA-Z0-9_$#@~.?]+ {
+        ("." | "@@") [a-zA-Z0-9_$#@~.?]+ {
             RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 0, parser_nasm));
         }
 
         /* forced identifier */
         "$" [a-zA-Z0-9_$#@~.?]+ {
-            if (TOK[1] == '.') {
+            if (TOK[1] == '.' ||
+                    (tasm_compatible_mode && TOK[1] == '@' && TOK[2] == '@')) {
                 /* handle like .label */
                 RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 1, parser_nasm));
             }
@@ -376,11 +417,61 @@ scan:
                     s->tok[TOKLEN] = savech;
                     RETURN(TARGETMOD);
                 default:
+                    break;
+            }
+            if (tasm_compatible_mode) {
+                if (!strcasecmp(TOK, "shl")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN(LEFT_OP);
+                }
+                if (!strcasecmp(TOK, "shr")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN(RIGHT_OP);
+                }
+                if (!strcasecmp(TOK, "and")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN('&');
+                }
+                if (!strcasecmp(TOK, "or")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN('|');
+                }
+                if (!strcasecmp(TOK, "low")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN(LOW);
+                }
+                if (!strcasecmp(TOK, "high")) {
                     s->tok[TOKLEN] = savech;
+                    RETURN(HIGH);
+                }
+                if (!strcasecmp(TOK, "offset")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN(OFFSET);
+                }
+                if (!strcasecmp(TOK, "fword")) {
+                    s->tok[TOKLEN] = savech;
+                    lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
+                    RETURN(SIZE_OVERRIDE);
+                }
+                if (!strcasecmp(TOK, "df")) {
+                    s->tok[TOKLEN] = savech;
+                    lvalp->int_info = yasm_arch_wordsize(p_object->arch)*3;
+                    parser_nasm->state = INSTRUCTION;
+                    RETURN(DECLARE_DATA);
+                }
+                if (!strcasecmp(TOK, "label")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN(LABEL);
+                }
+                if (!strcasecmp(TOK, "dup")) {
+                    s->tok[TOKLEN] = savech;
+                    RETURN(DUP);
+                }
             }
             /* Propagate errors in case we got a warning from the arch */
             yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
             /* Just an identifier, return as such. */
+            s->tok[TOKLEN] = savech;
             lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
             RETURN(ID);
         }
@@ -638,6 +729,26 @@ stringconst_scan:
     /*!re2c
         [\000]  { goto stringconst_error; }
 
+        "''" | '""'     {
+            if (endch != s->tok[0]) {
+                strbuf[count++] = s->tok[0];
+                if (count >= strbuf_size) {
+                    strbuf = yasm_xrealloc(strbuf,
+                                           strbuf_size + STRBUF_ALLOC_SIZE);
+                    strbuf_size += STRBUF_ALLOC_SIZE;
+                }
+            } else if (!tasm_compatible_mode) {
+                YYCURSOR--;
+                goto stringconst_end;
+            }
+            strbuf[count++] = s->tok[0];
+            if (count >= strbuf_size) {
+                strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
+                strbuf_size += STRBUF_ALLOC_SIZE;
+            }
+            goto stringconst_scan;
+        }
+
         any     {
             if (s->tok[0] == endch)
                 goto stringconst_end;
diff --git a/modules/parsers/tasm/Makefile.inc b/modules/parsers/tasm/Makefile.inc
new file mode 100644 (file)
index 0000000..e758958
--- /dev/null
@@ -0,0 +1,5 @@
+# $Id: Makefile.inc 2082 2008-05-09 06:46:02Z peter $
+
+EXTRA_DIST += modules/parsers/tasm/tests/Makefile.inc
+
+include modules/parsers/tasm/tests/Makefile.inc
diff --git a/modules/parsers/tasm/tests/Makefile.inc b/modules/parsers/tasm/tests/Makefile.inc
new file mode 100644 (file)
index 0000000..64decec
--- /dev/null
@@ -0,0 +1,46 @@
+# $Id: Makefile.inc 2063 2008-04-12 08:30:22Z peter $
+
+TESTS += modules/parsers/tasm/tests/tasm_test.sh
+
+EXTRA_DIST += modules/parsers/tasm/tests/tasm_test.sh
+EXTRA_DIST += modules/parsers/tasm/tests/array.asm
+EXTRA_DIST += modules/parsers/tasm/tests/array.hex
+EXTRA_DIST += modules/parsers/tasm/tests/case.asm
+EXTRA_DIST += modules/parsers/tasm/tests/case.hex
+EXTRA_DIST += modules/parsers/tasm/tests/charstr.asm
+EXTRA_DIST += modules/parsers/tasm/tests/charstr.hex
+EXTRA_DIST += modules/parsers/tasm/tests/dup.asm
+EXTRA_DIST += modules/parsers/tasm/tests/dup.hex
+EXTRA_DIST += modules/parsers/tasm/tests/equal.asm
+EXTRA_DIST += modules/parsers/tasm/tests/equal.hex
+EXTRA_DIST += modules/parsers/tasm/tests/expr.asm
+EXTRA_DIST += modules/parsers/tasm/tests/expr.hex
+EXTRA_DIST += modules/parsers/tasm/tests/irp.asm
+EXTRA_DIST += modules/parsers/tasm/tests/irp.hex
+EXTRA_DIST += modules/parsers/tasm/tests/label.asm
+EXTRA_DIST += modules/parsers/tasm/tests/label.hex
+EXTRA_DIST += modules/parsers/tasm/tests/les.asm
+EXTRA_DIST += modules/parsers/tasm/tests/les.hex
+EXTRA_DIST += modules/parsers/tasm/tests/lidt.asm
+EXTRA_DIST += modules/parsers/tasm/tests/lidt.hex
+EXTRA_DIST += modules/parsers/tasm/tests/macro.asm
+EXTRA_DIST += modules/parsers/tasm/tests/macro.hex
+EXTRA_DIST += modules/parsers/tasm/tests/offset.asm
+EXTRA_DIST += modules/parsers/tasm/tests/offset.hex
+EXTRA_DIST += modules/parsers/tasm/tests/quote.asm
+EXTRA_DIST += modules/parsers/tasm/tests/quote.hex
+EXTRA_DIST += modules/parsers/tasm/tests/res.asm
+EXTRA_DIST += modules/parsers/tasm/tests/res.errwarn
+EXTRA_DIST += modules/parsers/tasm/tests/res.hex
+EXTRA_DIST += modules/parsers/tasm/tests/segment.asm
+EXTRA_DIST += modules/parsers/tasm/tests/segment.hex
+EXTRA_DIST += modules/parsers/tasm/tests/size.asm
+EXTRA_DIST += modules/parsers/tasm/tests/size.hex
+EXTRA_DIST += modules/parsers/tasm/tests/struc.asm
+EXTRA_DIST += modules/parsers/tasm/tests/struc.errwarn
+EXTRA_DIST += modules/parsers/tasm/tests/struc.hex
+EXTRA_DIST += modules/parsers/tasm/tests/
+
+EXTRA_DIST += modules/parsers/tasm/tests/exe/Makefile.inc
+
+include modules/parsers/tasm/tests/exe/Makefile.inc
diff --git a/modules/parsers/tasm/tests/array.asm b/modules/parsers/tasm/tests/array.asm
new file mode 100644 (file)
index 0000000..4484267
--- /dev/null
@@ -0,0 +1,2 @@
+t db 0,1,2
+mov al,t[1]
diff --git a/modules/parsers/tasm/tests/array.hex b/modules/parsers/tasm/tests/array.hex
new file mode 100644 (file)
index 0000000..9775893
--- /dev/null
@@ -0,0 +1,6 @@
+00 
+01 
+02 
+a0 
+01 
+00 
diff --git a/modules/parsers/tasm/tests/case.asm b/modules/parsers/tasm/tests/case.asm
new file mode 100644 (file)
index 0000000..1549d4b
--- /dev/null
@@ -0,0 +1,3 @@
+a db 0
+B dw A
+c dw b
diff --git a/modules/parsers/tasm/tests/case.hex b/modules/parsers/tasm/tests/case.hex
new file mode 100644 (file)
index 0000000..e2092e0
--- /dev/null
@@ -0,0 +1,5 @@
+00 
+00 
+00 
+01 
+00 
diff --git a/modules/parsers/tasm/tests/charstr.asm b/modules/parsers/tasm/tests/charstr.asm
new file mode 100644 (file)
index 0000000..a753716
--- /dev/null
@@ -0,0 +1 @@
+mov eax,"1234"
diff --git a/modules/parsers/tasm/tests/charstr.hex b/modules/parsers/tasm/tests/charstr.hex
new file mode 100644 (file)
index 0000000..42deac4
--- /dev/null
@@ -0,0 +1,6 @@
+66 
+b8 
+34 
+33 
+32 
+31 
diff --git a/modules/parsers/tasm/tests/dup.asm b/modules/parsers/tasm/tests/dup.asm
new file mode 100644 (file)
index 0000000..c19ea76
--- /dev/null
@@ -0,0 +1 @@
+a db 10 dup(1)
diff --git a/modules/parsers/tasm/tests/dup.hex b/modules/parsers/tasm/tests/dup.hex
new file mode 100644 (file)
index 0000000..5a51766
--- /dev/null
@@ -0,0 +1,10 @@
+01 
+01 
+01 
+01 
+01 
+01 
+01 
+01 
+01 
+01 
diff --git a/modules/parsers/tasm/tests/equal.asm b/modules/parsers/tasm/tests/equal.asm
new file mode 100644 (file)
index 0000000..4b8919d
--- /dev/null
@@ -0,0 +1 @@
+a = byte 1
diff --git a/modules/parsers/tasm/tests/equal.hex b/modules/parsers/tasm/tests/equal.hex
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/parsers/tasm/tests/exe/Makefile.inc b/modules/parsers/tasm/tests/exe/Makefile.inc
new file mode 100644 (file)
index 0000000..faed7f5
--- /dev/null
@@ -0,0 +1,8 @@
+# $Id: Makefile.inc 2063 2008-04-12 08:30:22Z peter $
+
+TESTS += modules/parsers/tasm/tests/exe/tasm_exe_test.sh
+
+EXTRA_DIST += modules/parsers/tasm/tests/exe/tasm_exe_test.sh
+EXTRA_DIST += modules/parsers/tasm/tests/exe/exe.asm
+EXTRA_DIST += modules/parsers/tasm/tests/exe/exe.hex
+
diff --git a/modules/parsers/tasm/tests/exe/exe.asm b/modules/parsers/tasm/tests/exe/exe.asm
new file mode 100644 (file)
index 0000000..f040a1c
--- /dev/null
@@ -0,0 +1,4 @@
+a db 1
+start proc
+int 22
+start endp
diff --git a/modules/parsers/tasm/tests/exe/exe.hex b/modules/parsers/tasm/tests/exe/exe.hex
new file mode 100644 (file)
index 0000000..4547fbc
--- /dev/null
@@ -0,0 +1,515 @@
+4d 
+5a 
+03 
+00 
+02 
+00 
+00 
+00 
+20 
+00 
+00 
+00 
+ff 
+ff 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+22 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+cd 
+16 
diff --git a/modules/parsers/tasm/tests/exe/tasm_exe_test.sh b/modules/parsers/tasm/tests/exe/tasm_exe_test.sh
new file mode 100755 (executable)
index 0000000..47645e3
--- /dev/null
@@ -0,0 +1,4 @@
+#! /bin/sh
+# $Id: tasm_test.sh 1137 2004-09-04 01:24:57Z peter $
+${srcdir}/out_test.sh tasm_test modules/parsers/tasm/tests/exe "tasm-compat parser" "-f dosexe -p tasm" ""
+exit $?
diff --git a/modules/parsers/tasm/tests/expr.asm b/modules/parsers/tasm/tests/expr.asm
new file mode 100644 (file)
index 0000000..5319885
--- /dev/null
@@ -0,0 +1 @@
+a db low ((1 shl 2) and (16 shr 2) or (high 0x5034))
diff --git a/modules/parsers/tasm/tests/expr.hex b/modules/parsers/tasm/tests/expr.hex
new file mode 100644 (file)
index 0000000..d3c4f66
--- /dev/null
@@ -0,0 +1 @@
+54 
diff --git a/modules/parsers/tasm/tests/irp.asm b/modules/parsers/tasm/tests/irp.asm
new file mode 100644 (file)
index 0000000..d24cd29
--- /dev/null
@@ -0,0 +1,3 @@
+irp i,<1,2,3>
+ mov ax,i
+endm
diff --git a/modules/parsers/tasm/tests/irp.hex b/modules/parsers/tasm/tests/irp.hex
new file mode 100644 (file)
index 0000000..7bf091d
--- /dev/null
@@ -0,0 +1,9 @@
+b8 
+01 
+00 
+b8 
+02 
+00 
+b8 
+03 
+00 
diff --git a/modules/parsers/tasm/tests/label.asm b/modules/parsers/tasm/tests/label.asm
new file mode 100644 (file)
index 0000000..ff72ba3
--- /dev/null
@@ -0,0 +1,2 @@
+a label byte
+mov ax,offset a
diff --git a/modules/parsers/tasm/tests/label.hex b/modules/parsers/tasm/tests/label.hex
new file mode 100644 (file)
index 0000000..b74f90b
--- /dev/null
@@ -0,0 +1,3 @@
+b8 
+00 
+00 
diff --git a/modules/parsers/tasm/tests/les.asm b/modules/parsers/tasm/tests/les.asm
new file mode 100644 (file)
index 0000000..bbcfd90
--- /dev/null
@@ -0,0 +1,2 @@
+a db 1
+les ax,a
diff --git a/modules/parsers/tasm/tests/les.hex b/modules/parsers/tasm/tests/les.hex
new file mode 100644 (file)
index 0000000..032eee7
--- /dev/null
@@ -0,0 +1,5 @@
+01 
+c4 
+06 
+00 
+00 
diff --git a/modules/parsers/tasm/tests/lidt.asm b/modules/parsers/tasm/tests/lidt.asm
new file mode 100644 (file)
index 0000000..11cf0c6
--- /dev/null
@@ -0,0 +1,3 @@
+idtr dw 0
+     dd 0
+lidt fword ptr idtr
diff --git a/modules/parsers/tasm/tests/lidt.hex b/modules/parsers/tasm/tests/lidt.hex
new file mode 100644 (file)
index 0000000..97fb3b7
--- /dev/null
@@ -0,0 +1,11 @@
+00 
+00 
+00 
+00 
+00 
+00 
+0f 
+01 
+1e 
+00 
+00 
diff --git a/modules/parsers/tasm/tests/macro.asm b/modules/parsers/tasm/tests/macro.asm
new file mode 100644 (file)
index 0000000..7590239
--- /dev/null
@@ -0,0 +1,6 @@
+a macro reg,i
+  mov reg,i
+  endm
+
+a ax,0
+a bx,1
diff --git a/modules/parsers/tasm/tests/macro.hex b/modules/parsers/tasm/tests/macro.hex
new file mode 100644 (file)
index 0000000..92b4e4a
--- /dev/null
@@ -0,0 +1,6 @@
+b8 
+00 
+00 
+bb 
+01 
+00 
diff --git a/modules/parsers/tasm/tests/offset.asm b/modules/parsers/tasm/tests/offset.asm
new file mode 100644 (file)
index 0000000..417fd2c
--- /dev/null
@@ -0,0 +1,3 @@
+a db 1
+mov ax,offset a
+mov ax,offset[a]
diff --git a/modules/parsers/tasm/tests/offset.hex b/modules/parsers/tasm/tests/offset.hex
new file mode 100644 (file)
index 0000000..3def1cf
--- /dev/null
@@ -0,0 +1,7 @@
+01 
+b8 
+00 
+00 
+b8 
+00 
+00 
diff --git a/modules/parsers/tasm/tests/quote.asm b/modules/parsers/tasm/tests/quote.asm
new file mode 100644 (file)
index 0000000..a269ba3
--- /dev/null
@@ -0,0 +1,2 @@
+a db 'don''t'
+b db """"
diff --git a/modules/parsers/tasm/tests/quote.hex b/modules/parsers/tasm/tests/quote.hex
new file mode 100644 (file)
index 0000000..eb41f7b
--- /dev/null
@@ -0,0 +1,6 @@
+64 
+6f 
+6e 
+27 
+74 
+22 
diff --git a/modules/parsers/tasm/tests/res.asm b/modules/parsers/tasm/tests/res.asm
new file mode 100644 (file)
index 0000000..8cf0829
--- /dev/null
@@ -0,0 +1,2 @@
+a db ?
+b db 2 dup (?)
diff --git a/modules/parsers/tasm/tests/res.errwarn b/modules/parsers/tasm/tests/res.errwarn
new file mode 100644 (file)
index 0000000..490e1ad
--- /dev/null
@@ -0,0 +1,2 @@
+-:1: warning: uninitialized space declared in code/data section: zeroing
+-:2: warning: uninitialized space declared in code/data section: zeroing
diff --git a/modules/parsers/tasm/tests/res.hex b/modules/parsers/tasm/tests/res.hex
new file mode 100644 (file)
index 0000000..47f99ba
--- /dev/null
@@ -0,0 +1,3 @@
+00 
+00 
+00 
diff --git a/modules/parsers/tasm/tests/segment.asm b/modules/parsers/tasm/tests/segment.asm
new file mode 100644 (file)
index 0000000..f0563eb
--- /dev/null
@@ -0,0 +1,8 @@
+data segment
+  a db 0
+data ends
+
+assume es:data
+code segment
+  mov byte ptr [a],1
+code ends
diff --git a/modules/parsers/tasm/tests/segment.hex b/modules/parsers/tasm/tests/segment.hex
new file mode 100644 (file)
index 0000000..667a69b
--- /dev/null
@@ -0,0 +1,7 @@
+00 
+26 
+c6 
+06 
+00 
+00 
+01 
diff --git a/modules/parsers/tasm/tests/size.asm b/modules/parsers/tasm/tests/size.asm
new file mode 100644 (file)
index 0000000..405cc40
--- /dev/null
@@ -0,0 +1,2 @@
+a db 0
+mov a,1
diff --git a/modules/parsers/tasm/tests/size.hex b/modules/parsers/tasm/tests/size.hex
new file mode 100644 (file)
index 0000000..401266a
--- /dev/null
@@ -0,0 +1,6 @@
+00 
+c6 
+06 
+00 
+00 
+01 
diff --git a/modules/parsers/tasm/tests/struc.asm b/modules/parsers/tasm/tests/struc.asm
new file mode 100644 (file)
index 0000000..5a88b61
--- /dev/null
@@ -0,0 +1,8 @@
+s struc
+  a db ?
+  b db ?
+s ends
+
+v s <1,?>
+
+mov al,[v].b
diff --git a/modules/parsers/tasm/tests/struc.errwarn b/modules/parsers/tasm/tests/struc.errwarn
new file mode 100644 (file)
index 0000000..4e18889
--- /dev/null
@@ -0,0 +1 @@
+-:6: warning: uninitialized space declared in code/data section: zeroing
diff --git a/modules/parsers/tasm/tests/struc.hex b/modules/parsers/tasm/tests/struc.hex
new file mode 100644 (file)
index 0000000..d2ad956
--- /dev/null
@@ -0,0 +1,5 @@
+01 
+00 
+a0 
+01 
+00 
diff --git a/modules/parsers/tasm/tests/tasm_test.sh b/modules/parsers/tasm/tests/tasm_test.sh
new file mode 100755 (executable)
index 0000000..531e03e
--- /dev/null
@@ -0,0 +1,4 @@
+#! /bin/sh
+# $Id: tasm_test.sh 1137 2004-09-04 01:24:57Z peter $
+${srcdir}/out_test.sh tasm_test modules/parsers/tasm/tests "tasm-compat parser" "-f bin -p tasm" ""
+exit $?
index f9aa9d5ed3d3c75e53ff2765a8aca714d8f5b0d5..922b887cc19775015064d406648382fd343183d1 100644 (file)
@@ -9,7 +9,7 @@ libyasm_a_SOURCES += modules/preprocs/nasm/nasmlib.c
 libyasm_a_SOURCES += modules/preprocs/nasm/nasm-eval.h
 libyasm_a_SOURCES += modules/preprocs/nasm/nasm-eval.c
 
-YASM_MODULES += preproc_nasm
+YASM_MODULES += preproc_nasm preproc_tasm
 
 $(top_srcdir)/modules/preprocs/nasm/nasm-preproc.c: nasm-version.c
 
index 2d5e7d2187946fe07e984acb06e119ddbd9689b1..3f6e2961a202a29075bcdd7869138eeadcf3158e 100644 (file)
@@ -324,7 +324,9 @@ static int is_condition(int arg)
 enum
 {
     TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
-    TM_IFNDEF, TM_INCLUDE, TM_LOCAL
+    TM_IFNDEF, TM_INCLUDE, TM_LOCAL,
+    TM_REPT, TM_IRP, TM_MACRO,
+    TM_STRUC, TM_SEGMENT
 };
 
 static const char *tasm_directives[] = {
@@ -393,10 +395,53 @@ static const char *tasm_compat_macros[] =
 {
     "%idefine IDEAL",
     "%idefine JUMPS",
-    "%idefine P386",
-    "%idefine P486",
-    "%idefine P586",
     "%idefine END",
+    "%idefine P8086    CPU 8086",
+    "%idefine P186     CPU 186",
+    "%idefine P286     CPU 286",
+    "%idefine P286N    CPU 286",
+    "%idefine P286P    CPU 286 Priv",
+    "%idefine P386     CPU 386",
+    "%idefine P386N    CPU 386",
+    "%idefine P386P    CPU 386 Priv",
+    "%idefine P486     CPU 486",
+    "%idefine P586     CPU 586",
+    "%idefine .8086    CPU 8086",
+    "%idefine .186     CPU 186",
+    "%idefine .286     CPU 286",
+    "%idefine .286C    CPU 286",
+    "%idefine .286P    CPU 286",
+    "%idefine .386     CPU 386",
+    "%idefine .386C    CPU 386",
+    "%idefine .386P    CPU 386",
+    "%idefine .486     CPU 486",
+    "%idefine .486C    CPU 486",
+    "%idefine .486P    CPU 486",
+    "%idefine .586     CPU 586",
+    "%idefine .586C    CPU 586",
+    "%idefine .586P    CPU 586",
+    "",
+    "%imacro TITLE 1",
+    "%endm",
+    "%imacro NAME 1",
+    "%endm",
+    "",
+    "%imacro EXTRN 1-*.nolist",
+    "%rep %0",
+    "[extern %1]",
+    "%rotate 1",
+    "%endrep",
+    "%endmacro",
+    "",
+    "%imacro PUBLIC 1-*.nolist",
+    "%rep %0",
+    "[global %1]",
+    "%rotate 1",
+    "%endrep",
+    "%endmacro",
+    "",
+    "; this is not needed",
+    "%idefine PTR",
     NULL
 };
 
@@ -428,6 +473,7 @@ static void delete_Blocks(void);
 static Token *new_Token(Token * next, int type, const char *text,
                         size_t txtlen);
 static Token *delete_Token(Token * t);
+static Token *tokenise(char *line);
 
 /*
  * Macros for safe checking of token pointers, avoid *(NULL)
@@ -442,69 +488,555 @@ static Token *delete_Token(Token * t);
  * place to do it for the moment, and it is a hack (ideally it would
  * be nice to be able to use the NASM pre-processor to do it).
  */
+
+typedef struct TMEndItem {
+    int type;
+    void *data;
+    struct TMEndItem *next;
+} TMEndItem;
+
+static TMEndItem *EndmStack = NULL, *EndsStack = NULL;
+
+char **TMParameters;
+
+struct TStrucField {
+    char *name;
+    char *type;
+    struct TStrucField *next;
+};
+struct TStruc {
+    char *name;
+    struct TStrucField *fields, *lastField;
+    struct TStruc *next;
+};
+static struct TStruc *TStrucs = NULL;
+static int inTstruc = 0;
+
+struct TSegmentAssume {
+    char *segreg;
+    char *segment;
+};
+struct TSegmentAssume *TAssumes;
+
+const char *tasm_get_segment_register(const char *segment)
+{
+    struct TSegmentAssume *assume;
+    if (!TAssumes)
+        return NULL;
+    for (assume = TAssumes; assume->segreg; assume++) {
+        if (!strcmp(assume->segment, segment))
+            break;
+    }
+    return assume->segreg;
+}
+
 static char *
 check_tasm_directive(char *line)
 {
     int i, j, k, m;
-    size_t len;
-    char *p = line, *oldline, oldchar;
+    size_t len, len2;
+    char *p, *oldline, oldchar, *q, oldchar2;
+    TMEndItem *end;
+
+    if ((p = strchr(line, ';')))
+        *p = '\0';
+
+    p = line;
 
     /* Skip whitespace */
     while (isspace(*p) && *p != 0)
         p++;
 
+    /* Ignore nasm directives */
+    if (*p == '%')
+        return line;
+
     /* Binary search for the directive name */
-    i = -1;
-    j = elements(tasm_directives);
     len = 0;
     while (!isspace(p[len]) && p[len] != 0)
         len++;
-    if (len)
+    if (!len)
+        return line;
+
+    oldchar = p[len];
+    p[len] = 0;
+    i = -1;
+    j = elements(tasm_directives);
+    while (j - i > 1)
     {
-        oldchar = p[len];
-        p[len] = 0;
-        while (j - i > 1)
+        k = (j + i) / 2;
+        m = nasm_stricmp(p, tasm_directives[k]);
+        if (m == 0)
         {
-            k = (j + i) / 2;
-            m = nasm_stricmp(p, tasm_directives[k]);
-            if (m == 0)
+            /* We have found a directive, so jam a % in front of it
+             * so that NASM will then recognise it as one if it's own.
+             */
+            p[len] = oldchar;
+            len = strlen(p);
+            oldline = line;
+            if (k == TM_IFDIFI)
             {
-                /* We have found a directive, so jam a % in front of it
-                 * so that NASM will then recognise it as one if it's own.
+                /* NASM does not recognise IFDIFI, so we convert it to
+                 * %ifdef BOGUS. This is not used in NASM comaptible
+                 * code, but does need to parse for the TASM macro
+                 * package.
                  */
-                p[len] = oldchar;
+                line = nasm_malloc(13);
+                strcpy(line, "%ifdef BOGUS");
+            }
+            else if (k == TM_INCLUDE)
+            {
+                /* add double quotes around file name */
+                p += 7 + 1;
+                while (isspace(*p) && *p)
+                    p++;
                 len = strlen(p);
-                oldline = line;
+                line = nasm_malloc(1 + 7 + 1 + 1 + len + 1 + 1);
+                sprintf(line, "%%include \"%s\"", p);
+            }
+            else
+            {
                 line = nasm_malloc(len + 2);
                 line[0] = '%';
-                if (k == TM_IFDIFI)
-                {
-                    /* NASM does not recognise IFDIFI, so we convert it to
-                     * %ifdef BOGUS. This is not used in NASM comaptible
-                     * code, but does need to parse for the TASM macro
-                     * package.
-                     */
-                    strcpy(line + 1, "ifdef BOGUS");
+                memcpy(line + 1, p, len + 1);
+            }
+            nasm_free(oldline);
+            return line;
+        }
+        else if (m < 0)
+        {
+            j = k;
+        }
+        else
+            i = k;
+    }
+
+    /* Not a simple directive */
+
+    if (!nasm_stricmp(p, "endm")) {
+        /* handle end of endm directive */
+        char **parameter;
+        end = EndmStack;
+        /* undef parameters */
+        if (!end) {
+            error(ERR_FATAL, "ENDM: not in an endm context");
+            return line;
+        }
+        EndmStack = EndmStack->next;
+        nasm_free(line);
+        switch (end->type) {
+        case TM_MACRO:
+            len = 0;
+            for (parameter = end->data; *parameter; parameter++)
+                len += 6 + 1 + strlen(*parameter) + 1;
+            len += 5 + 1;
+            line = nasm_malloc(len);
+            p = line;
+            for (parameter = end->data; *parameter; parameter++) {
+                p += sprintf(p, "%%undef %s\n", *parameter);
+                nasm_free(*parameter);
+            }
+            nasm_free(end->data);
+            nasm_free(end);
+            sprintf(p, "%%endm");
+            return line;
+        case TM_REPT:
+            nasm_free(end);
+            return nasm_strdup("%endrep");
+        case TM_IRP: {
+            char **data;
+            const char *irp_format = 
+                "%%undef %s\n"
+                "%%rotate 1\n"
+                "%%endrep\n"
+                "%%endm\n"
+                "irp %s\n"
+                "%%undef irp";
+            data = end->data;
+            line = nasm_malloc(strlen(irp_format) - 4 + strlen(data[0])
+                   + strlen(data[1]));
+            sprintf(line, irp_format, data[0], data[1]);
+            nasm_free(data[0]);
+            nasm_free(data[1]);
+            nasm_free(data);
+            return line;
+            }
+        default:
+            error(ERR_FATAL, "ENDM: bogus endm context type %d\n",end->type);
+            return NULL;
+        }
+    } else if (!nasm_stricmp(p, "end")) {
+        nasm_free(line);
+        return strdup("");
+    } else if (!nasm_stricmp(p, "rept")) {
+        /* handle repeat directive */
+        end = nasm_malloc(sizeof(*end));
+        end->type = TM_REPT;
+        end->next = EndmStack;
+        EndmStack = end;
+        memcpy(p, "%rep", 4);
+        p[len] = oldchar;
+        return line;
+    } else if (!nasm_stricmp(p, "locals")) {
+        tasm_locals = 1;
+        nasm_free(line);
+        return strdup("");
+    }
+
+    if (!oldchar)
+        return line;
+
+    /* handle two-words directives */
+    q = p + len + 1;
+    /* Skip whitespaces */
+    while (isspace(*q) && *q)
+        q++;
+
+    len2 = 0;
+    while (!isspace(q[len2]) && q[len2]!=',' && q[len2] != 0)
+        len2++;
+    oldchar2 = q[len2];
+    q[len2] = '\0';
+
+    if (!nasm_stricmp(p, "irp")) {
+        /* handle indefinite repeat directive */
+        const char *irp_format = 
+            "%%imacro irp 0-*\n"
+            "%%rep %%0\n"
+            "%%define %s %%1\n";
+        char **data;
+
+        data = malloc(2*sizeof(char*));
+        oldline = line;
+        line = nasm_malloc(strlen(irp_format) - 2 + len2 + 1);
+        sprintf(line,irp_format,q);
+        data[0] = nasm_strdup(q);
+
+        if (!oldchar2)
+            error(ERR_FATAL, "%s: expected <values>", q + len2);
+        p = strchr(q + len2 + 1, '<');
+        if (!p)
+            error(ERR_FATAL, "%s: expected <values>", q + len2);
+        p++;
+        q = strchr(p, '>');
+        data[1] = nasm_strndup(p, q - p);
+
+        end = nasm_malloc(sizeof(*end));
+        end->type = TM_IRP;
+        end->next = EndmStack;
+        end->data = data;
+        EndmStack = end;
+
+        nasm_free(oldline);
+        return line;
+    } else if (!nasm_stricmp(q, "macro")) {
+        char *name = p;
+        /* handle MACRO */
+        /* count parameters */
+        j = 1;
+        i = 0;
+        TMParameters = nasm_malloc(j*sizeof(*TMParameters));
+        len = 0;
+        p = q + len2 + 1;
+        /* Skip whitespaces */
+        while (isspace(*p) && *p)
+            p++;
+        while (*p) {
+            /* Get parameter name */
+            for (q = p; !isspace(*q) && *q != ',' && *q; q++);
+            len2 = q-p;
+            if (len2 == 0)
+                error(ERR_FATAL, "'%s': expected parameter name", p);
+            TMParameters[i] = nasm_malloc(len2 + 1);
+            memcpy(TMParameters[i], p, len2);
+            TMParameters[i][len2] = '\0';
+            len += len2;
+            i++;
+            if (i + 1 > j) {
+                j *= 2;
+                TMParameters = nasm_realloc(TMParameters,
+                                               j*sizeof(*TMParameters));
+            }
+            if (i == 1000)
+                error(ERR_FATAL, "too many parameters for macro %s", name);
+            p = q;
+            while (isspace(*p) && *p)
+                p++;
+            if (!*p)
+                break;
+            if (*p != ',')
+                error(ERR_FATAL, "expected comma");
+            p++;
+            while (isspace(*p) && *p)
+                p++;
+        }
+        TMParameters[i] = NULL;
+        TMParameters = nasm_realloc(TMParameters,
+                                        (i+1)*sizeof(*TMParameters));
+        len += 1 + 6 + 1 + strlen(name) + 1 + 3; /* macro definition */
+        len += i * (1 + 9 + 1 + 1 + 1 + 3 + 2); /* macro parameter definition */
+        oldline = line;
+        p = line = nasm_malloc(len + 1);
+        p += sprintf(p, "%%imacro %s 0-*", name);
+        nasm_free(oldline);
+        for (j = 0; TMParameters[j]; j++) {
+            p += sprintf(p, "\n%%idefine %s %%{%-u}", TMParameters[j], j + 1);
+        }
+        end = nasm_malloc(sizeof(*end));
+        end->type = TM_MACRO;
+        end->next = EndmStack;
+        end->data = TMParameters;
+        EndmStack = end;
+        return line;
+    } else if (!nasm_stricmp(q, "proc")) {
+        /* handle PROC */
+        oldline = line;
+        line = nasm_malloc(2 + len + 1);
+        sprintf(line, "..%s",p);
+        nasm_free(oldline);
+        return line;
+    } else if (!nasm_stricmp(q, "struc")) {
+        /* handle struc */
+        struct TStruc *struc;
+        if (inTstruc) {
+            error(ERR_FATAL, "STRUC: already in a struc context");
+            return line;
+        }
+        oldline = line;
+        line = nasm_malloc(5 + 1 + len + 1);
+        sprintf(line, "struc %s", p);
+        struc = malloc(sizeof(*struc));
+        struc->name = strdup(p);
+        struc->fields = NULL;
+        struc->lastField = NULL;
+        struc->next = TStrucs;
+        TStrucs = struc;
+        inTstruc = 1;
+        nasm_free(oldline);
+        end = nasm_malloc(sizeof(*end));
+        end->type = TM_STRUC;
+        end->next = EndsStack;
+        EndsStack = end;
+        return line;
+    } else if (!nasm_stricmp(q, "segment")) {
+        /* handle SEGMENT */
+        oldline = line;
+        line = strdup(oldchar2?q+len2+1:"");
+        if (tasm_segment) {
+            error(ERR_FATAL, "SEGMENT: already in a segment context");
+            return line;
+        }
+        tasm_segment = strdup(p);
+        nasm_free(oldline);
+        end = nasm_malloc(sizeof(*end));
+        end->type = TM_SEGMENT;
+        end->next = EndsStack;
+        EndsStack = end;
+        return line;
+    } else if (!nasm_stricmp(p, "ends") || !nasm_stricmp(q, "ends")) {
+        /* handle end of ends directive */
+        end = EndsStack;
+        /* undef parameters */
+        if (!end) {
+            error(ERR_FATAL, "ENDS: not in an ends context");
+            return line;
+        }
+        EndsStack = EndsStack->next;
+        nasm_free(line);
+        switch (end->type) {
+        case TM_STRUC:
+            inTstruc = 0;
+            return strdup("endstruc");
+        case TM_SEGMENT:
+            /* XXX: yes, we leak memory here, but that permits labels
+             * to avoid strduping... */
+            tasm_segment = NULL;
+            return strdup("");
+        default:
+            error(ERR_FATAL, "ENDS: bogus ends context type %d",end->type);
+            return NULL;
+        }
+    } else if (!nasm_stricmp(p, "endp") || !nasm_stricmp(q, "endp")) {
+        nasm_free(line);
+        return strdup("");
+    } else if (!nasm_stricmp(p, "assume")) {
+        struct TSegmentAssume *assume;
+        /* handle ASSUME */
+        if (!TAssumes) {
+            TAssumes = nasm_malloc(sizeof(*TAssumes));
+            TAssumes[0].segreg = NULL;
+        }
+        i = 0;
+        q[len2] = oldchar2;
+        /* Skip whitespaces */
+        while (isspace(*q) && *q)
+            q++;
+        while (*q) {
+            p = q;
+            for (; *q && *q != ':' && !isspace(*q); q++);
+            if (!*q)
+                break;
+            /* segment register name */
+            for (assume = TAssumes; assume->segreg; assume++)
+                if (strlen(assume->segreg) == q-p &&
+                    !strncasecmp(assume->segreg, p, q-p))
+                    break;
+            if (!assume->segreg) {
+                i = assume - TAssumes + 1;
+                TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes));
+                assume = TAssumes + i - 1;
+                assume->segreg = nasm_strndup(p, q-p);
+                assume[1].segreg = NULL;
+            }
+            for (; *q && *q != ':' && isspace(*q); q++);
+            if (*q != ':')
+                error(ERR_FATAL, "expected `:' instead of `%c'", *q);
+            for (q++; *q && isspace(*q); q++);
+
+            /* segment name */
+            p = q;
+            for (; *q && *q != ',' && !isspace(*q); q++);
+            assume->segment = nasm_strndup(p, q-p);
+            for (; *q && isspace(*q); q++);
+            if (*q && *q != ',')
+                error(ERR_FATAL, "expected `,' instead of `%c'", *q);
+        
+            for (q++; *q && isspace(*q); q++);
+        }
+        TAssumes[i].segreg = NULL;
+        TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes));
+        nasm_free(line);
+        return strdup("");
+    } else if (inTstruc) {
+        struct TStrucField *field;
+        /* TODO: handle unnamed data */
+        field = nasm_malloc(sizeof(*field));
+        field->name = strdup(p);
+        /* TODO: type struc ! */
+        field->type = strdup(q);
+        field->next = NULL;
+        if (!TStrucs->fields)
+                TStrucs->fields = field;
+        else if (TStrucs->lastField)
+                TStrucs->lastField->next = field;
+        TStrucs->lastField = field;
+        if (!oldchar2) {
+            error(ERR_FATAL, "Expected struc field initializer after %s %s", p, q);
+            return line;
+        }
+        oldline = line;
+        line = nasm_malloc(1 + len + 1 + len2 + 1 + strlen(q+len2+1) + 1);
+        sprintf(line, ".%s %s %s", p, q, q+len2+1);
+        nasm_free(oldline);
+        return line;
+    }
+    {
+        struct TStruc *struc;
+        for (struc = TStrucs; struc; struc = struc->next) {
+            if (!strcasecmp(q, struc->name)) {
+                char *r = q + len2 + 1, *s, *t, tasm_param[6];
+                struct TStrucField *field = struc->fields;
+                int size, n, m;
+                if (!oldchar2) {
+                    error(ERR_FATAL, "Expected struc field initializer after %s %s", p, q);
+                    return line;
                 }
-                else
-                {
-                    memcpy(line + 1, p, len + 1);
+                r = strchr(r, '<');
+                if (!r) {
+                    error(ERR_FATAL, "Expected < for struc field initializer in %s %s %s", p, q, r);
+                    return line;
+                }
+                t = strchr(r + 1, '>');
+                if (!t) {
+                    error(ERR_FATAL, "Expected > for struc field initializer in %s %s %s", p, q, r);
+                    return line;
+                }
+                *t = 0;
+                oldline = line;
+                size = len + len2 + 128;
+                line = nasm_malloc(size);
+                if (defining)
+                    for (n=0;TMParameters[n];n++)
+                        if (!strcmp(TMParameters[n],p)) {
+                            sprintf(tasm_param,"%%{%d}",n+1);
+                            p = tasm_param;
+                            break;
+                        }
+                n = sprintf(line, "%s: istruc %s\n", p, q);
+                /* use initialisers */
+                while ((s = strchr(r + 1, ','))) {
+                    if (!field) {
+                        error(ERR_FATAL, "Too many initializers in structure %s %s", p, q);
+                        return oldline;
+                    }
+                    *s = 0;
+                    while (1) {
+                            m = snprintf(line + n, size - n, "%s.%s: at .%s, %s %s\n", p, field->name, field->name, field->type, r + 1);
+                        if (m + 1 <= size - n)
+                                break;
+                        size *= 2;
+                        line = nasm_realloc(line, size);
+                    }
+                    n += m;
+                    r = s;
+                    field = field->next;
                 }
+                /* complete with last initializer and '?' */
+                while(field) {
+                    while (1) {
+                            m = snprintf(line + n, size - n, "%s.%s: at .%s, %s %s\n", p, field->name, field->name, field->type, r ? r + 1: "?");
+                        if (m + 1 <= size - n)
+                                break;
+                        size *= 2;
+                        line = nasm_realloc(line, size);
+                    }
+                    n += m;
+                    r = NULL;
+                    field = field->next;
+                }
+                line = nasm_realloc(line, n + 5);
+                sprintf(line + n, "iend");
                 nasm_free(oldline);
                 return line;
             }
-            else if (m < 0)
-            {
-                j = k;
-            }
-            else
-                i = k;
         }
-        p[len] = oldchar;
     }
+
+    q[len2] = oldchar2;
+    p[len] = oldchar;
+    
     return line;
 }
 
+Token * tasm_join_tokens(Token *tline)
+{
+    Token *t, *prev, *next;
+    for (prev = NULL, t = tline; t; prev = t, t = next) {
+        next = t->next;
+        if (t->type == TOK_OTHER && !strcmp(t->text,"&")) {
+            if (!prev)
+                error(ERR_FATAL, "no token before &");
+            else if (!next)
+                error(ERR_FATAL, "no token after &");
+            else if (prev->type != next->type)
+                error(ERR_FATAL, "can't handle different types of token around &");
+            else if (!prev->text || !next->text)
+                error(ERR_FATAL, "can't handle empty token around &");
+            else {
+                int lenp = strlen(prev->text);
+                int lenn = strlen(next->text);
+                prev->text = nasm_realloc(prev->text, lenp + lenn + 1);
+                strncpy(prev->text + lenp, next->text, lenn + 1);
+                (void) delete_Token(t);
+                prev->next = delete_Token(next);
+                t = prev;
+                next = t->next;
+            }
+        }
+    }
+    return tline;
+}
+
 /*
  * The pre-preprocessing stage... This function translates line
  * number indications as they emerge from GNU cpp (`# lineno "file"
@@ -517,6 +1049,8 @@ prepreproc(char *line)
     int lineno;
     size_t fnlen;
     char *fname, *oldline;
+    char *c, *d, *ret;
+    Line *l, **lp;
 
     if (line[0] == '#' && line[1] == ' ')
     {
@@ -532,8 +1066,30 @@ prepreproc(char *line)
         nasm_free(oldline);
     }
     if (tasm_compatible_mode)
-        return check_tasm_directive(line);
-    return line;
+        line = check_tasm_directive(line);
+
+    if (!(c = strchr(line, '\n')))
+        return line;
+
+    /* Turn multiline macros into several lines */
+    *c = '\0';
+    ret = nasm_strdup(line);
+
+    lp = &istk->expansion;
+    do {
+        d = strchr(c+1, '\n');
+        if (d)
+            *d = '\0';
+        l = malloc(sizeof(*l));
+        l -> first = tokenise(c+1);
+        l -> finishes = NULL;
+        l -> next = *lp;
+        *lp = l;
+        c = d;
+        lp = &l -> next;
+    } while (c);
+    nasm_free(line);
+    return ret;
 }
 
 /*
@@ -1231,7 +1787,7 @@ static FILE *
 inc_fopen(char *file, char **newname)
 {
     FILE *fp;
-    char *combine = NULL;
+    char *combine = NULL, *c;
     char *pb, *p1, *p2, *file2 = NULL;
 
     /* Try to expand all %ENVVAR% in filename.  Warn, and leave %string%
@@ -1281,6 +1837,27 @@ inc_fopen(char *file, char **newname)
 
     fp = yasm_fopen_include(file2 ? file2 : file, nasm_src_get_fname(), "r",
                             &combine);
+    if (!fp && tasm_compatible_mode)
+    {
+        char *thefile = file2 ? file2 : file;
+        /* try a few case combinations */
+        do {
+            for (c = thefile; *c; c++)
+                *c = toupper(*c);
+            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+            if (fp) break;
+            *thefile = tolower(*thefile);
+            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+            if (fp) break;
+            for (c = thefile; *c; c++)
+                *c = tolower(*c);
+            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+            if (fp) break;
+            *thefile = toupper(*thefile);
+            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+            if (fp) break;
+        } while (0);
+    }
     if (!fp)
         error(ERR_FATAL, "unable to open include file `%s'",
               file2 ? file2 : file);
@@ -4420,6 +4997,9 @@ pp_getline(void)
                 /*
                  * De-tokenise the line again, and emit it.
                  */
+                if (tasm_compatible_mode)
+                    tline = tasm_join_tokens(tline);
+
                 line = detoken(tline, TRUE);
                 free_tlist(tline);
                 break;
index bb4c7a744ba57000462c8190bfed24580eaa33d1..fa2b91e7930344bc9ecf4cf61211109c3239379a 100644 (file)
@@ -47,6 +47,8 @@ yasm_symtab *nasm_symtab;
 static yasm_linemap *cur_lm;
 static yasm_errwarns *cur_errwarns;
 int tasm_compatible_mode = 0;
+int tasm_locals;
+const char *tasm_segment;
 
 #include "nasm-version.c"
 
@@ -314,3 +316,25 @@ yasm_preproc_module yasm_nasm_LTX_preproc = {
     nasm_preproc_define_builtin,
     nasm_preproc_add_standard
 };
+
+static yasm_preproc *
+tasm_preproc_create(const char *in_filename, yasm_symtab *symtab,
+                    yasm_linemap *lm, yasm_errwarns *errwarns)
+{
+    tasm_compatible_mode = 1;
+    return nasm_preproc_create(in_filename, symtab, lm, errwarns);
+}
+
+yasm_preproc_module yasm_tasm_LTX_preproc = {
+    "Real TASM Preprocessor",
+    "tasm",
+    tasm_preproc_create,
+    nasm_preproc_destroy,
+    nasm_preproc_get_line,
+    nasm_preproc_get_included_file,
+    nasm_preproc_add_include_file,
+    nasm_preproc_predefine_macro,
+    nasm_preproc_undefine_macro,
+    nasm_preproc_define_builtin,
+    nasm_preproc_add_standard
+};
index 792877b0b496c0599924c111615355901e8a72d6..b3382ffe92beec3a24a0da368de835b79dfedf31 100644 (file)
@@ -276,5 +276,8 @@ enum {
 #define elements(x)     ( sizeof(x) / sizeof(*(x)) )
 
 extern int tasm_compatible_mode;
+extern int tasm_locals;
+extern const char *tasm_segment;
+const char *tasm_get_segment_register(const char *segment);
 
 #endif