[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#396291: Bug#356055: loadlin: loadlin.exe cannot be built from source



Hello,

Peter commited upstream my yasm patch to support tasm syntax for
loadlin, here is a backport to the debian package (just a few minor
changes).  The patch is quite big, but as noted in the changelog, it
just adds extensions that are enabled only when tasm compatible mode is
requested.

Samuel
Index: libyasm/bytecode.c
===================================================================
--- libyasm/bytecode.c	(révision 2128)
+++ libyasm/bytecode.c	(copie de travail)
@@ -223,6 +223,18 @@
 }
 
 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: libyasm/symrec.c
===================================================================
--- libyasm/symrec.c	(révision 2128)
+++ libyasm/symrec.c	(copie de travail)
@@ -28,6 +28,7 @@
 /*@unused@*/ RCSID("$Id$");
 
 #include <limits.h>
+#include <ctype.h>
 
 #include "libyasm-stdint.h"
 #include "coretype.h"
@@ -71,6 +72,8 @@
         /* 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 @@
     /*@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 *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 @@
 }
 
 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 @@
 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 @@
 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_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 @@
         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,7 +558,31 @@
     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)
 {
     return (sym->def_line == 0 && sym->type == SYM_EQU &&
Index: libyasm/bytecode.h
===================================================================
--- libyasm/bytecode.h	(révision 2128)
+++ libyasm/bytecode.h	(copie de travail)
@@ -86,6 +86,14 @@
      */
     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,14 @@
 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
+ */
+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_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: libyasm/symrec.h
===================================================================
--- libyasm/symrec.h	(révision 2128)
+++ libyasm/symrec.h	(copie de travail)
@@ -73,6 +73,13 @@
 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.
+ */
+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 @@
 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: libyasm/insn.c
===================================================================
--- libyasm/insn.c	(révision 2128)
+++ libyasm/insn.c	(copie de travail)
@@ -96,6 +96,7 @@
     retval->size = 0;
     retval->deref = 0;
     retval->strict = 0;
+    retval->size = ea->data_len * 8;
 
     return retval;
 }
Index: libyasm/insn.h
===================================================================
--- libyasm/insn.h	(révision 2128)
+++ libyasm/insn.h	(copie de travail)
@@ -74,6 +74,9 @@
 
     /** 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: libyasm/bc-align.c
===================================================================
--- libyasm/bc-align.c	(révision 2128)
+++ libyasm/bc-align.c	(copie de travail)
@@ -66,6 +66,7 @@
     bc_align_destroy,
     bc_align_print,
     bc_align_finalize,
+    NULL,
     bc_align_calc_len,
     bc_align_expand,
     bc_align_tobytes,
Index: libyasm/bc-reserve.c
===================================================================
--- libyasm/bc-reserve.c	(révision 2128)
+++ libyasm/bc-reserve.c	(copie de travail)
@@ -46,6 +46,7 @@
 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 @@
     bc_reserve_destroy,
     bc_reserve_print,
     bc_reserve_finalize,
+    bc_reserve_elem_size,
     bc_reserve_calc_len,
     yasm_bc_expand_common,
     bc_reserve_tobytes,
@@ -96,6 +98,13 @@
 }
 
 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: libyasm/bc-org.c
===================================================================
--- libyasm/bc-org.c	(révision 2128)
+++ libyasm/bc-org.c	(copie de travail)
@@ -60,6 +60,7 @@
     bc_org_destroy,
     bc_org_print,
     bc_org_finalize,
+    NULL,
     bc_org_calc_len,
     bc_org_expand,
     bc_org_tobytes,
Index: libyasm/intnum.c
===================================================================
--- libyasm/intnum.c	(révision 2128)
+++ libyasm/intnum.c	(copie de travail)
@@ -244,17 +244,65 @@
         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);
+    size_t i;
+
+    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 */
+    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);
+    }
+
+    return intn;
+}
 /*@=usedef =compdef =uniondef@*/
 
 yasm_intnum *
Index: libyasm/expr.c
===================================================================
--- libyasm/expr.c	(révision 2128)
+++ libyasm/expr.c	(copie de travail)
@@ -1444,3 +1444,73 @@
             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: libyasm/intnum.h
===================================================================
--- libyasm/intnum.h	(révision 2128)
+++ libyasm/intnum.h	(copie de travail)
@@ -76,12 +76,20 @@
 
 /** 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.
  */
 /*@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.
+ */
+/*@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: libyasm/errwarn.c
===================================================================
--- libyasm/errwarn.c	(révision 2128)
+++ libyasm/errwarn.c	(copie de travail)
@@ -115,7 +115,8 @@
     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: libyasm/expr.h
===================================================================
--- libyasm/expr.h	(révision 2128)
+++ libyasm/expr.h	(copie de travail)
@@ -297,6 +297,16 @@
 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: libyasm/bc-incbin.c
===================================================================
--- libyasm/bc-incbin.c	(révision 2128)
+++ libyasm/bc-incbin.c	(copie de travail)
@@ -66,6 +66,7 @@
     bc_incbin_destroy,
     bc_incbin_print,
     bc_incbin_finalize,
+    NULL,
     bc_incbin_calc_len,
     yasm_bc_expand_common,
     bc_incbin_tobytes,
Index: libyasm/errwarn.h
===================================================================
--- libyasm/errwarn.h	(révision 2128)
+++ libyasm/errwarn.h	(copie de travail)
@@ -46,7 +46,8 @@
     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: libyasm/bc-data.c
===================================================================
--- libyasm/bc-data.c	(révision 2128)
+++ libyasm/bc-data.c	(copie de travail)
@@ -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 @@
             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 @@
     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,37 +139,64 @@
             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)
 {
     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 @@
     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_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 @@
                     /* 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 @@
                 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 @@
     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 @@
                         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 @@
 
     retval->type = DV_VALUE;
     yasm_value_initialize(&retval->data.val, e, 0);
+    retval->multiple = NULL;
 
     return retval;
 }
@@ -376,11 +464,55 @@
     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)
 {
     yasm_dataval *cur, *next;
@@ -398,6 +530,8 @@
             default:
                 break;
         }
+        if (cur->multiple)
+            yasm_expr_destroy(cur->multiple);
         yasm_xfree(cur);
         cur = next;
     }
@@ -421,6 +555,11 @@
     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 @@
                 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: configure.ac
===================================================================
--- configure.ac	(révision 2129)
+++ configure.ac	(révision 2137)
@@ -125,7 +125,7 @@
 #
 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: COPYING
===================================================================
--- COPYING	(révision 2129)
+++ COPYING	(révision 2137)
@@ -10,6 +10,7 @@
   Stephen Polkowski (x86 instruction patches)
   Henryk Richter (Mach-O object format)
   Ben Skeggs (patches, bug reports)
+  Samuel Thibault (TASM parser and frontend)
 
 -----------------------------------
 Yasm licensing overview and summary
Index: modules/parsers/tasm/tests/lidt.hex
===================================================================
--- modules/parsers/tasm/tests/lidt.hex	(révision 0)
+++ modules/parsers/tasm/tests/lidt.hex	(révision 0)
@@ -0,0 +1,11 @@
+00 
+00 
+00 
+00 
+00 
+00 
+0f 
+01 
+1e 
+00 
+00 
Index: modules/parsers/tasm/tests/macro.asm
===================================================================
--- modules/parsers/tasm/tests/macro.asm	(révision 0)
+++ modules/parsers/tasm/tests/macro.asm	(révision 0)
@@ -0,0 +1,6 @@
+a macro reg,i
+  mov reg,i
+  endm
+
+a ax,0
+a bx,1
Index: modules/parsers/tasm/tests/segment.asm
===================================================================
--- modules/parsers/tasm/tests/segment.asm	(révision 0)
+++ modules/parsers/tasm/tests/segment.asm	(révision 0)
@@ -0,0 +1,8 @@
+data segment
+  a db 0
+data ends
+
+assume es:data
+code segment
+  mov byte ptr [a],1
+code ends
Index: modules/parsers/tasm/tests/exe/exe.asm
===================================================================
--- modules/parsers/tasm/tests/exe/exe.asm	(révision 0)
+++ modules/parsers/tasm/tests/exe/exe.asm	(révision 0)
@@ -0,0 +1,4 @@
+a db 1
+start proc
+int 22
+start endp
Index: modules/parsers/tasm/tests/exe/exe.hex
===================================================================
--- modules/parsers/tasm/tests/exe/exe.hex	(révision 0)
+++ modules/parsers/tasm/tests/exe/exe.hex	(révision 0)
@@ -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 
Index: modules/parsers/tasm/tests/exe/Makefile.inc
===================================================================
--- modules/parsers/tasm/tests/exe/Makefile.inc	(révision 0)
+++ modules/parsers/tasm/tests/exe/Makefile.inc	(révision 0)
@@ -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
+
Index: modules/parsers/tasm/tests/exe/tasm_exe_test.sh
===================================================================
--- modules/parsers/tasm/tests/exe/tasm_exe_test.sh	(révision 0)
+++ modules/parsers/tasm/tests/exe/tasm_exe_test.sh	(révision 0)
@@ -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 $?

Modification de propriétés sur modules/parsers/tasm/tests/exe/tasm_exe_test.sh
___________________________________________________________________
Ajouté : svn:mergeinfo

Index: modules/parsers/tasm/tests/macro.hex
===================================================================
--- modules/parsers/tasm/tests/macro.hex	(révision 0)
+++ modules/parsers/tasm/tests/macro.hex	(révision 0)
@@ -0,0 +1,6 @@
+b8 
+00 
+00 
+bb 
+01 
+00 
Index: modules/parsers/tasm/tests/Makefile.inc
===================================================================
--- modules/parsers/tasm/tests/Makefile.inc	(révision 0)
+++ modules/parsers/tasm/tests/Makefile.inc	(révision 0)
@@ -0,0 +1,44 @@
+# $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.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.hex
+EXTRA_DIST += modules/parsers/tasm/tests/
+
+EXTRA_DIST += modules/parsers/nasm/test/exe/Makefile.inc
+
+include modules/parsers/nasm/test/exe/Makefile.inc
Index: modules/parsers/tasm/tests/segment.hex
===================================================================
--- modules/parsers/tasm/tests/segment.hex	(révision 0)
+++ modules/parsers/tasm/tests/segment.hex	(révision 0)
@@ -0,0 +1,7 @@
+00 
+26 
+c6 
+06 
+00 
+00 
+01 
Index: modules/parsers/tasm/tests/charstr.asm
===================================================================
--- modules/parsers/tasm/tests/charstr.asm	(révision 0)
+++ modules/parsers/tasm/tests/charstr.asm	(révision 0)
@@ -0,0 +1 @@
+mov eax,"1234"
Index: modules/parsers/tasm/tests/charstr.hex
===================================================================
--- modules/parsers/tasm/tests/charstr.hex	(révision 0)
+++ modules/parsers/tasm/tests/charstr.hex	(révision 0)
@@ -0,0 +1,6 @@
+66 
+b8 
+34 
+33 
+32 
+31 
Index: modules/parsers/tasm/tests/array.asm
===================================================================
--- modules/parsers/tasm/tests/array.asm	(révision 0)
+++ modules/parsers/tasm/tests/array.asm	(révision 0)
@@ -0,0 +1,2 @@
+t db 0,1,2
+mov al,t[1]
Index: modules/parsers/tasm/tests/label.asm
===================================================================
--- modules/parsers/tasm/tests/label.asm	(révision 0)
+++ modules/parsers/tasm/tests/label.asm	(révision 0)
@@ -0,0 +1,2 @@
+a label byte
+mov ax,offset a
Index: modules/parsers/tasm/tests/array.hex
===================================================================
--- modules/parsers/tasm/tests/array.hex	(révision 0)
+++ modules/parsers/tasm/tests/array.hex	(révision 0)
@@ -0,0 +1,6 @@
+00 
+01 
+02 
+a0 
+01 
+00 
Index: modules/parsers/tasm/tests/label.hex
===================================================================
--- modules/parsers/tasm/tests/label.hex	(révision 0)
+++ modules/parsers/tasm/tests/label.hex	(révision 0)
@@ -0,0 +1,3 @@
+b8 
+00 
+00 
Index: modules/parsers/tasm/tests/offset.asm
===================================================================
--- modules/parsers/tasm/tests/offset.asm	(révision 0)
+++ modules/parsers/tasm/tests/offset.asm	(révision 0)
@@ -0,0 +1,3 @@
+a db 1
+mov ax,offset a
+mov ax,offset[a]
Index: modules/parsers/tasm/tests/offset.hex
===================================================================
--- modules/parsers/tasm/tests/offset.hex	(révision 0)
+++ modules/parsers/tasm/tests/offset.hex	(révision 0)
@@ -0,0 +1,7 @@
+01 
+b8 
+00 
+00 
+b8 
+00 
+00 
Index: modules/parsers/tasm/tests/irp.asm
===================================================================
--- modules/parsers/tasm/tests/irp.asm	(révision 0)
+++ modules/parsers/tasm/tests/irp.asm	(révision 0)
@@ -0,0 +1,3 @@
+irp i,<1,2,3>
+ mov ax,i
+endm
Index: modules/parsers/tasm/tests/quote.asm
===================================================================
--- modules/parsers/tasm/tests/quote.asm	(révision 0)
+++ modules/parsers/tasm/tests/quote.asm	(révision 0)
@@ -0,0 +1,2 @@
+a db 'don''t'
+b db """"
Index: modules/parsers/tasm/tests/tasm_test.sh
===================================================================
--- modules/parsers/tasm/tests/tasm_test.sh	(révision 0)
+++ modules/parsers/tasm/tests/tasm_test.sh	(révision 0)
@@ -0,0 +1,5 @@
+#! /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" ""
+${srcdir}/out_test.sh tasm_test modules/parsers/tasm/tests/exe "tasm-compat parser" "-f dosexe -p tasm" ""
+exit $?

Modification de propriétés sur modules/parsers/tasm/tests/tasm_test.sh
___________________________________________________________________
Ajouté : svn:executable
   + *

Index: modules/parsers/tasm/tests/irp.hex
===================================================================
--- modules/parsers/tasm/tests/irp.hex	(révision 0)
+++ modules/parsers/tasm/tests/irp.hex	(révision 0)
@@ -0,0 +1,9 @@
+b8 
+01 
+00 
+b8 
+02 
+00 
+b8 
+03 
+00 
Index: modules/parsers/tasm/tests/struc.asm
===================================================================
--- modules/parsers/tasm/tests/struc.asm	(révision 0)
+++ modules/parsers/tasm/tests/struc.asm	(révision 0)
@@ -0,0 +1,8 @@
+s struc
+  a db ?
+  b db ?
+s ends
+
+v s <1,?>
+
+mov al,[v].b
Index: modules/parsers/tasm/tests/struc.errwarn
===================================================================
--- modules/parsers/tasm/tests/struc.errwarn	(révision 0)
+++ modules/parsers/tasm/tests/struc.errwarn	(révision 0)
@@ -0,0 +1 @@
+-:6: warning: uninitialized space declared in code/data section: zeroing
Index: modules/parsers/tasm/tests/quote.hex
===================================================================
--- modules/parsers/tasm/tests/quote.hex	(révision 0)
+++ modules/parsers/tasm/tests/quote.hex	(révision 0)
@@ -0,0 +1,6 @@
+64 
+6f 
+6e 
+27 
+74 
+22 
Index: modules/parsers/tasm/tests/struc.hex
===================================================================
--- modules/parsers/tasm/tests/struc.hex	(révision 0)
+++ modules/parsers/tasm/tests/struc.hex	(révision 0)
@@ -0,0 +1,5 @@
+01 
+00 
+a0 
+01 
+00 
Index: modules/parsers/tasm/tests/equal.asm
===================================================================
--- modules/parsers/tasm/tests/equal.asm	(révision 0)
+++ modules/parsers/tasm/tests/equal.asm	(révision 0)
@@ -0,0 +1 @@
+a = byte 1
Index: modules/parsers/tasm/tests/size.asm
===================================================================
--- modules/parsers/tasm/tests/size.asm	(révision 0)
+++ modules/parsers/tasm/tests/size.asm	(révision 0)
@@ -0,0 +1,2 @@
+a db 0
+mov a,1
Index: modules/parsers/tasm/tests/equal.hex
===================================================================
Index: modules/parsers/tasm/tests/case.asm
===================================================================
--- modules/parsers/tasm/tests/case.asm	(révision 0)
+++ modules/parsers/tasm/tests/case.asm	(révision 0)
@@ -0,0 +1,3 @@
+a db 0
+B dw A
+c dw b
Index: modules/parsers/tasm/tests/size.hex
===================================================================
--- modules/parsers/tasm/tests/size.hex	(révision 0)
+++ modules/parsers/tasm/tests/size.hex	(révision 0)
@@ -0,0 +1,6 @@
+00 
+c6 
+06 
+00 
+00 
+01 
Index: modules/parsers/tasm/tests/expr.asm
===================================================================
--- modules/parsers/tasm/tests/expr.asm	(révision 0)
+++ modules/parsers/tasm/tests/expr.asm	(révision 0)
@@ -0,0 +1 @@
+a db low ((1 shl 2) and (16 shr 2) or (high 0x5034))
Index: modules/parsers/tasm/tests/case.hex
===================================================================
--- modules/parsers/tasm/tests/case.hex	(révision 0)
+++ modules/parsers/tasm/tests/case.hex	(révision 0)
@@ -0,0 +1,5 @@
+00 
+00 
+00 
+01 
+00 
Index: modules/parsers/tasm/tests/expr.hex
===================================================================
--- modules/parsers/tasm/tests/expr.hex	(révision 0)
+++ modules/parsers/tasm/tests/expr.hex	(révision 0)
@@ -0,0 +1 @@
+54 
Index: modules/parsers/tasm/tests/les.asm
===================================================================
--- modules/parsers/tasm/tests/les.asm	(révision 0)
+++ modules/parsers/tasm/tests/les.asm	(révision 0)
@@ -0,0 +1,2 @@
+a db 1
+les ax,a
Index: modules/parsers/tasm/tests/les.hex
===================================================================
--- modules/parsers/tasm/tests/les.hex	(révision 0)
+++ modules/parsers/tasm/tests/les.hex	(révision 0)
@@ -0,0 +1,5 @@
+01 
+c4 
+06 
+00 
+00 
Index: modules/parsers/tasm/tests/dup.asm
===================================================================
--- modules/parsers/tasm/tests/dup.asm	(révision 0)
+++ modules/parsers/tasm/tests/dup.asm	(révision 0)
@@ -0,0 +1 @@
+a db 10 dup(1)
Index: modules/parsers/tasm/tests/res.errwarn
===================================================================
--- modules/parsers/tasm/tests/res.errwarn	(révision 0)
+++ modules/parsers/tasm/tests/res.errwarn	(révision 0)
@@ -0,0 +1,2 @@
+-:1: warning: uninitialized space declared in code/data section: zeroing
+-:2: warning: uninitialized space declared in code/data section: zeroing
Index: modules/parsers/tasm/tests/res.asm
===================================================================
--- modules/parsers/tasm/tests/res.asm	(révision 0)
+++ modules/parsers/tasm/tests/res.asm	(révision 0)
@@ -0,0 +1,2 @@
+a db ?
+b db 2 dup (?)
Index: modules/parsers/tasm/tests/lidt.asm
===================================================================
--- modules/parsers/tasm/tests/lidt.asm	(révision 0)
+++ modules/parsers/tasm/tests/lidt.asm	(révision 0)
@@ -0,0 +1,3 @@
+idtr dw 0
+     dd 0
+lidt fword ptr idtr
Index: modules/parsers/tasm/tests/dup.hex
===================================================================
--- modules/parsers/tasm/tests/dup.hex	(révision 0)
+++ modules/parsers/tasm/tests/dup.hex	(révision 0)
@@ -0,0 +1,10 @@
+01 
+01 
+01 
+01 
+01 
+01 
+01 
+01 
+01 
+01 
Index: modules/parsers/tasm/tests/res.hex
===================================================================
--- modules/parsers/tasm/tests/res.hex	(révision 0)
+++ modules/parsers/tasm/tests/res.hex	(révision 0)
@@ -0,0 +1,3 @@
+00 
+00 
+00 
Index: modules/parsers/tasm/Makefile.inc
===================================================================
--- modules/parsers/tasm/Makefile.inc	(révision 0)
+++ modules/parsers/tasm/Makefile.inc	(révision 0)
@@ -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
Index: modules/parsers/Makefile.inc
===================================================================
--- modules/parsers/Makefile.inc	(révision 2128)
+++ modules/parsers/Makefile.inc	(copie de travail)
@@ -5,6 +5,7 @@
 
 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: modules/parsers/nasm/nasm-token.re
===================================================================
--- modules/parsers/nasm/nasm-token.re	(révision 2128)
+++ modules/parsers/nasm/nasm-token.re	(copie de travail)
@@ -32,6 +32,7 @@
 #include <libyasm.h>
 
 #include "modules/parsers/nasm/nasm-parser.h"
+#include "modules/preprocs/nasm/nasm.h"
 
 
 #define YYCURSOR        cursor
@@ -76,13 +77,22 @@
 {
     /* 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+(parser_nasm->tasm?2:0),
+            toklen-zeropos-(parser_nasm->tasm?2:0));
         /* check for special non-local ..@label */
         if (lvalp->str_val[zeropos+2] == '@')
             return NONLOCAL_ID;
         return SPECIAL_ID;
     }
-
+    if (parser_nasm->tasm && (!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 @@
         }
 
         /* 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; RETURN(DECLARE_DATA); }
+        'dt'            {
+            lvalp->int_info = 80;
+            parser_nasm->state = INSTRUCTION;
+            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; RETURN(RESERVE_SPACE); }
+        'rest'          {
+            lvalp->int_info = 80;
+            parser_nasm->state = INSTRUCTION;
+            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 @@
         "//"                    { 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] == '.' ||
+                    (parser_nasm->tasm && TOK[1] == '@' && TOK[2] == '@')) {
                 /* handle like .label */
                 RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 1, parser_nasm));
             }
@@ -376,11 +417,61 @@
                     s->tok[TOKLEN] = savech;
                     RETURN(TARGETMOD);
                 default:
+                    break;
+            }
+            if (parser_nasm->tasm) {
+                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 @@
     /*!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 (!parser_nasm->tasm) {
+                YYCURSOR--;
+                goto scan;
+            }
+            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;
Index: modules/parsers/nasm/Makefile.inc
===================================================================
--- modules/parsers/nasm/Makefile.inc	(révision 2128)
+++ modules/parsers/nasm/Makefile.inc	(copie de travail)
@@ -5,7 +5,7 @@
 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: modules/parsers/nasm/nasm-parse.c
===================================================================
--- modules/parsers/nasm/nasm-parse.c	(révision 2128)
+++ modules/parsers/nasm/nasm-parse.c	(copie de travail)
@@ -32,6 +32,7 @@
 #include <math.h>
 
 #include "modules/parsers/nasm/nasm-parser.h"
+#include "modules/preprocs/nasm/nasm.h"
 
 typedef enum {
     NORM_EXPR,
@@ -62,8 +63,24 @@
      /*@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 (parser_nasm->tasm) {
+        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 @@
                 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 @@
         case LOCAL_ID:
         {
             char *name = ID_val;
-            int local = (curtok != ID);
+            int local = parser_nasm->tasm
+                ? (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 || (parser_nasm->tasm && curtok == '=')) {
                 /* label EQU expr */
                 yasm_expr *e;
                 get_next_token();
+
+                if (parser_nasm->tasm && 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 @@
                 return NULL;
             }
 
-            define_label(parser_nasm, name, local);
-            if (is_eol())
+            if (parser_nasm->tasm && curtok == LABEL)
+                get_next_token();
+
+            if (parser_nasm->tasm && 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 (!parser_nasm->tasm && !bc)
                 yasm_error_set(YASM_ERROR_SYNTAX,
                                N_("instruction expected after label"));
+            if (parser_nasm->tasm && bc && !size)
+                size = yasm_bc_elem_size(bc);
+            define_label(parser_nasm, name, size, local);
             return bc;
         }
         default:
@@ -510,7 +551,7 @@
             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 @@
                         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,106 @@
                                N_("memory address expected"));
                 return NULL;
             }
+
+            if (parser_nasm->tasm && !is_eol() && curtok != ',') {
+                yasm_expr *e = NULL, *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 (parser_nasm->tasm && 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_insn_operand *op2;
+                    yasm_ea_set_implicit_size_segment(parser_nasm, ea,
+                                                      op->data.val);
+                    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 +945,51 @@
                 op->targetmod = tmod;
             return op;
         }
+        case ID:
+        case LOCAL_ID:
+        case NONLOCAL_ID:
+            if (parser_nasm->tasm) {
+                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 (parser_nasm->tasm && 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 @@
             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 @@
                     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 @@
                 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 @@
             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 (parser_nasm->tasm)
+                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 @@
 }
 
 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 ((!parser_nasm->tasm || 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 @@
     }
 
     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: modules/parsers/nasm/nasm-parser.c
===================================================================
--- modules/parsers/nasm/nasm-parser.c	(révision 2129)
+++ modules/parsers/nasm/nasm-parser.c	(révision 2137)
@@ -33,12 +33,13 @@
 
 
 static void
-nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
-                     int save_input, yasm_linemap *linemap,
-                     yasm_errwarns *errwarns)
+nasm_do_parse(yasm_object *object, yasm_preproc *pp, int save_input,
+              yasm_linemap *linemap, yasm_errwarns *errwarns, int tasm)
 {
     yasm_parser_nasm parser_nasm;
 
+    parser_nasm.tasm = tasm;
+
     parser_nasm.object = object;
     parser_nasm.linemap = linemap;
 
@@ -77,6 +78,14 @@
     yasm_symtab_parser_finalize(object->symtab, 0, errwarns);
 }
 
+static void
+nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+                     int save_input, yasm_linemap *linemap,
+                     yasm_errwarns *errwarns)
+{
+    nasm_do_parse(object, pp, save_input, linemap, errwarns, 0);
+}
+
 /* Define valid preprocessors to use with this parser */
 static const char *nasm_parser_preproc_keywords[] = {
     "raw",
@@ -100,3 +109,29 @@
     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)
+{
+    yasm_symtab_set_case_sensitive(object->symtab, 0);
+    yasm_warn_disable(YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
+    nasm_do_parse(object, pp, save_input, linemap, errwarns, 1);
+}
+
+/* Define valid preprocessors to use with this parser */
+static const char *tasm_parser_preproc_keywords[] = {
+    "raw",
+    "tasm",
+    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_do_parse
+};
Index: modules/parsers/nasm/nasm-parser.h
===================================================================
--- modules/parsers/nasm/nasm-parser.h	(révision 2128)
+++ modules/parsers/nasm/nasm-parser.h	(copie de travail)
@@ -38,11 +38,14 @@
     FILENAME,
     STRING,
     SIZE_OVERRIDE,
+    OFFSET,
     DECLARE_DATA,
     RESERVE_SPACE,
+    LABEL,
     INCBIN,
     EQU,
     TIMES,
+    DUP,
     SEG,
     WRT,
     ABS,
@@ -56,6 +59,8 @@
     TARGETMOD,
     LEFT_OP,
     RIGHT_OP,
+    LOW,
+    HIGH,
     SIGNDIV,
     SIGNMOD,
     START_SECTION_ID,
@@ -82,6 +87,8 @@
 #define YYSTYPE yystype
 
 typedef struct yasm_parser_nasm {
+    int tasm;
+
     int debug;
 
     /*@only@*/ yasm_object *object;
Index: modules/objfmts/win64/tests/win64-dataref.hex
===================================================================
--- modules/objfmts/win64/tests/win64-dataref.hex	(révision 2128)
+++ modules/objfmts/win64/tests/win64-dataref.hex	(copie de travail)
@@ -1364,7 +1364,7 @@
 00 
 00 
 00 
-17 
+16 
 00 
 00 
 00 
@@ -1374,7 +1374,7 @@
 00 
 00 
 00 
-17 
+16 
 00 
 00 
 00 
@@ -1999,39 +1999,39 @@
 03 
 00 
 78 
-70 
-74 
-72 
 00 
 00 
 00 
 00 
-40 
 00 
 00 
 00 
-02 
 00 
 00 
 00 
+00 
 03 
 00 
-78 
 00 
 00 
+03 
 00 
+78 
+70 
+74 
+72 
 00 
 00 
 00 
 00 
+40 
 00 
 00 
 00 
+02 
 00 
-03 
 00 
 00 
-00 
 03 
 00 
 78 
Index: modules/objfmts/bin/Makefile.inc
===================================================================
--- modules/objfmts/bin/Makefile.inc	(révision 2128)
+++ modules/objfmts/bin/Makefile.inc	(copie de travail)
@@ -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: modules/objfmts/bin/bin-objfmt.c
===================================================================
--- modules/objfmts/bin/bin-objfmt.c	(révision 2128)
+++ modules/objfmts/bin/bin-objfmt.c	(copie de travail)
@@ -27,6 +27,9 @@
 #include <util.h>
 /*@unused@*/ RCSID("$Id$");
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <libyasm.h>
 
 
@@ -1071,7 +1072,8 @@
             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 +1107,8 @@
     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);
@@ -1802,3 +1806,153 @@
     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,
+    dosexe_objfmt_create,
+    dosexe_objfmt_output,
+    bin_objfmt_destroy,
+    bin_objfmt_add_default_section,
+    bin_objfmt_section_switch,
+    bin_objfmt_get_special_sym
+};
Index: modules/objfmts/coff/coff-objfmt.c
===================================================================
--- modules/objfmts/coff/coff-objfmt.c	(révision 2128)
+++ modules/objfmts/coff/coff-objfmt.c	(copie de travail)
@@ -234,6 +234,7 @@
     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: modules/objfmts/coff/win64-except.c
===================================================================
--- modules/objfmts/coff/win64-except.c	(révision 2128)
+++ modules/objfmts/coff/win64-except.c	(copie de travail)
@@ -72,6 +72,7 @@
     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 @@
     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: modules/dbgfmts/codeview/cv-symline.c
===================================================================
--- modules/dbgfmts/codeview/cv-symline.c	(révision 2128)
+++ modules/dbgfmts/codeview/cv-symline.c	(copie de travail)
@@ -201,6 +201,7 @@
     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 @@
     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 @@
     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 @@
     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: modules/dbgfmts/codeview/cv-type.c
===================================================================
--- modules/dbgfmts/codeview/cv-type.c	(révision 2128)
+++ modules/dbgfmts/codeview/cv-type.c	(copie de travail)
@@ -492,6 +492,7 @@
     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: modules/dbgfmts/dwarf2/dwarf2-info.c
===================================================================
--- modules/dbgfmts/dwarf2/dwarf2-info.c	(révision 2128)
+++ modules/dbgfmts/dwarf2/dwarf2-info.c	(copie de travail)
@@ -207,6 +207,7 @@
     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: modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c
===================================================================
--- modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c	(révision 2128)
+++ modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c	(copie de travail)
@@ -55,6 +55,7 @@
     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: modules/dbgfmts/dwarf2/dwarf2-line.c
===================================================================
--- modules/dbgfmts/dwarf2/dwarf2-line.c	(révision 2128)
+++ modules/dbgfmts/dwarf2/dwarf2-line.c	(copie de travail)
@@ -149,6 +149,7 @@
     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 @@
     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: modules/dbgfmts/stabs/stabs-dbgfmt.c
===================================================================
--- modules/dbgfmts/stabs/stabs-dbgfmt.c	(révision 2128)
+++ modules/dbgfmts/stabs/stabs-dbgfmt.c	(copie de travail)
@@ -139,6 +139,7 @@
     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 @@
     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: modules/arch/lc3b/lc3bid.re
===================================================================
--- modules/arch/lc3b/lc3bid.re	(révision 2128)
+++ modules/arch/lc3b/lc3bid.re	(copie de travail)
@@ -128,6 +128,7 @@
     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: modules/arch/lc3b/lc3bbc.c
===================================================================
--- modules/arch/lc3b/lc3bbc.c	(révision 2128)
+++ modules/arch/lc3b/lc3bbc.c	(copie de travail)
@@ -53,6 +53,7 @@
     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: modules/arch/x86/tests/lds-err.errwarn
===================================================================
--- modules/arch/x86/tests/lds-err.errwarn	(révision 2129)
+++ modules/arch/x86/tests/lds-err.errwarn	(révision 2137)
@@ -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
Index: modules/arch/x86/tests/lds-err.asm
===================================================================
--- modules/arch/x86/tests/lds-err.asm	(révision 2129)
+++ modules/arch/x86/tests/lds-err.asm	(révision 2137)
@@ -1,6 +0,0 @@
-lds ax,[1]
-lds ax,word [1]
-lds ax,dword [1]
-lds eax,[1]
-lds eax,word [1]
-lds eax,dword [1]
Index: modules/arch/x86/tests/Makefile.inc
===================================================================
--- modules/arch/x86/tests/Makefile.inc	(révision 2129)
+++ modules/arch/x86/tests/Makefile.inc	(révision 2137)
@@ -84,8 +84,8 @@
 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
Index: modules/arch/x86/tests/lds.asm
===================================================================
--- modules/arch/x86/tests/lds.asm	(révision 0)
+++ modules/arch/x86/tests/lds.asm	(révision 2137)
@@ -0,0 +1,6 @@
+lds ax,[1]
+lds ax,word [1]
+lds ax,dword [1]
+lds eax,[1]
+lds eax,word [1]
+lds eax,dword [1]
Index: modules/arch/x86/tests/lds.hex
===================================================================
--- modules/arch/x86/tests/lds.hex	(révision 0)
+++ modules/arch/x86/tests/lds.hex	(révision 2137)
@@ -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: modules/arch/x86/x86id.c
===================================================================
--- modules/arch/x86/x86id.c	(révision 2128)
+++ modules/arch/x86/x86id.c	(copie de travail)
@@ -350,6 +350,7 @@
     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 @@
         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: modules/arch/x86/x86arch.c
===================================================================
--- modules/arch/x86/x86arch.c	(révision 2128)
+++ modules/arch/x86/x86arch.c	(copie de travail)
@@ -71,6 +71,8 @@
 
     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: modules/arch/x86/x86expr.c
===================================================================
--- modules/arch/x86/x86expr.c	(révision 2128)
+++ modules/arch/x86/x86expr.c	(copie de travail)
@@ -422,7 +422,7 @@
              * 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: modules/arch/x86/x86arch.h
===================================================================
--- modules/arch/x86/x86arch.h	(révision 2128)
+++ modules/arch/x86/x86arch.h	(copie de travail)
@@ -82,7 +82,8 @@
     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: modules/arch/x86/x86bc.c
===================================================================
--- modules/arch/x86/x86bc.c	(révision 2128)
+++ modules/arch/x86/x86bc.c	(copie de travail)
@@ -76,6 +76,7 @@
     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 @@
     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 @@
     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 @@
     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 @@
      */
     x86_ea->need_sib = 0xff;
 
+    x86_ea->ea.data_len = 0;
+
     return (yasm_effaddr *)x86_ea;
 }
 
Index: modules/arch/x86/gen_x86_insn.py
===================================================================
--- modules/arch/x86/gen_x86_insn.py	(révision 2128)
+++ modules/arch/x86/gen_x86_insn.py	(copie de travail)
@@ -671,7 +671,7 @@
     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 @@
         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 @@
         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 @@
         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: modules/preprocs/nasm/nasm.h
===================================================================
--- modules/preprocs/nasm/nasm.h	(révision 2128)
+++ modules/preprocs/nasm/nasm.h	(copie de travail)
@@ -276,5 +276,8 @@
 #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
Index: modules/preprocs/nasm/Makefile.inc
===================================================================
--- modules/preprocs/nasm/Makefile.inc	(révision 2128)
+++ modules/preprocs/nasm/Makefile.inc	(copie de travail)
@@ -9,7 +9,7 @@
 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
 

Modification de propriétés sur modules/preprocs/nasm/nasmlib.c
___________________________________________________________________
Ajouté : svn:mergeinfo

Index: modules/preprocs/nasm/nasm-preproc.c
===================================================================
--- modules/preprocs/nasm/nasm-preproc.c	(révision 2128)
+++ modules/preprocs/nasm/nasm-preproc.c	(copie de travail)
@@ -47,6 +47,8 @@
 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,24 @@
     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,
+};

Modification de propriétés sur modules/preprocs/nasm/nasmlib.h
___________________________________________________________________
Ajouté : svn:mergeinfo

Index: modules/preprocs/nasm/nasm-pp.c
===================================================================
--- modules/preprocs/nasm/nasm-pp.c	(révision 2128)
+++ modules/preprocs/nasm/nasm-pp.c	(copie de travail)
@@ -324,7 +324,9 @@
 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[] = {
@@ -428,6 +473,7 @@
 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 @@
  * 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) == (size_t)(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;
+                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;
 }
 
+static 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 @@
     int lineno;
     size_t fnlen;
     char *fname, *oldline;
+    char *c, *d, *ret;
+    Line *l, **lp;
 
     if (line[0] == '#' && line[1] == ' ')
     {
@@ -532,8 +1066,30 @@
         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 @@
 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 @@
 
     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 @@
                 /*
                  * 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: frontends/tasm/tasm-options.h
===================================================================
--- frontends/tasm/tasm-options.h	(révision 0)
+++ frontends/tasm/tasm-options.h	(révision 0)
@@ -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
Index: frontends/tasm/Makefile.inc
===================================================================
--- frontends/tasm/Makefile.inc	(révision 0)
+++ frontends/tasm/Makefile.inc	(révision 0)
@@ -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)
Index: frontends/tasm/tasm.c
===================================================================
--- frontends/tasm/tasm.c	(révision 0)
+++ frontends/tasm/tasm.c	(révision 0)
@@ -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 && 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: frontends/tasm/tasm-options.c
===================================================================
--- frontends/tasm/tasm-options.c	(révision 0)
+++ frontends/tasm/tasm-options.c	(révision 2137)
@@ -0,0 +1,129 @@
+/*
+ * 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 *cmd = &argv[0][1];
+                size_t len = strlen(options[i].opt);
+                if (yasm__strncasecmp(cmd, options[i].opt, len) == 0) {
+                    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));
+}
Index: frontends/Makefile.inc
===================================================================
--- frontends/Makefile.inc	(révision 2128)
+++ frontends/Makefile.inc	(copie de travail)
@@ -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
--- modules/preprocs/nasm/standard.mac	2008-04-16 05:29:59.000000000 +0200
+++ modules/preprocs/nasm/standard.mac	2008-10-06 19:21:36.000000000 +0200
@@ -5,10 +5,53 @@
 
     %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
 
 ; This is a magic token which indicates the end of the TASM macros
 *END*TASM*MACROS*

Reply to: