]> granicus.if.org Git - yasm/commitdiff
- Greatly enhance capabilities of directives (they're actually parsed now).
authorPeter Johnson <peter@tortall.net>
Mon, 19 Nov 2001 03:27:56 +0000 (03:27 -0000)
committerPeter Johnson <peter@tortall.net>
Mon, 19 Nov 2001 03:27:56 +0000 (03:27 -0000)
  objfmt interface changed a lot due to this.
- New variables cur_objfmt and cur_parser that define what objfmt/parser are
  active.  They're set in main() by searching through the list of objfmts and
  parsers.  This necessitated libyasm.a to be listed twice in LDADD.

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

45 files changed:
frontends/yasm/yasm.c
libyasm/linemgr.c
libyasm/linemgr.h
libyasm/objfmt.h
libyasm/parser.h
libyasm/preproc.h
libyasm/section.c
libyasm/section.h
libyasm/symrec.c
libyasm/tests/Makefile.am
modules/objfmts/dbg/dbg-objfmt.c
modules/objfmts/dbg/objfmt.c
modules/parsers/nasm/Makefile.am
modules/parsers/nasm/bison.y.in
modules/parsers/nasm/nasm-bison.y
modules/parsers/nasm/nasm-parser.c
modules/parsers/nasm/parser.c
modules/parsers/nasm/token.l.in
modules/preprocs/raw/preproc.c
modules/preprocs/raw/raw-preproc.c
src/Makefile.am
src/globals.c
src/globals.h
src/linemgr.c
src/linemgr.h
src/main.c
src/objfmt.c [new file with mode: 0644]
src/objfmt.h
src/objfmts/dbg/dbg-objfmt.c
src/objfmts/dbg/objfmt.c
src/parser.c
src/parser.h
src/parsers/nasm/Makefile.am
src/parsers/nasm/bison.y.in
src/parsers/nasm/nasm-bison.y
src/parsers/nasm/nasm-parser.c
src/parsers/nasm/parser.c
src/parsers/nasm/token.l.in
src/preproc.h
src/preprocs/raw/preproc.c
src/preprocs/raw/raw-preproc.c
src/section.c
src/section.h
src/symrec.c
src/tests/Makefile.am

index 3d72d5dc48e1b8c48b1f7d91cdb771e2040c2628..bdc319994508e252c5800054c725580781da5486 100644 (file)
@@ -117,10 +117,24 @@ main(int argc, char *argv[])
     /* Set x86 as the architecture */
     cur_arch = &x86_arch;
 
+    /* Set dbg as the object format */
+    cur_objfmt = find_objfmt("dbg");
+    if (!cur_objfmt) {
+       ErrorNow(_("unrecognized output format `%s'"), "dbg");
+       return EXIT_FAILURE;
+    }
+
+    /* Set NASM as the parser */
+    cur_parser = find_parser("nasm");
+    if (!cur_parser) {
+       ErrorNow(_("unrecognized parser `%s'"), "nasm");
+       return EXIT_FAILURE;
+    }
+
     /* Get initial BITS setting from object format */
-    x86_mode_bits = dbg_objfmt.default_mode_bits;
+    x86_mode_bits = cur_objfmt->default_mode_bits;
 
-    sections = nasm_parser.do_parse(&nasm_parser, &dbg_objfmt, in);
+    sections = cur_parser->do_parse(cur_parser, in);
 
     if (OutputAllErrorWarning() > 0) {
        sections_delete(sections);
index b5abfe9b5d31c2f348dc65be9fa077f56762d8ad..895ff64fcbd6d92121311f7b1aa3e1a08a5a294f 100644 (file)
 #include "globals.h"
 
 
+/* Current (selected) parser */
+/*@null@*/ parser *cur_parser = NULL;
+
+/* Current (selected) object format) */
+/*@null@*/ objfmt *cur_objfmt = NULL;
+
 /*@null@*/ /*@dependent@*/ const char *in_filename = (const char *)NULL;
 unsigned int line_number = 1;
 unsigned int asm_options = 0;
index bf37e4a8bd2a19198e2dccfee4bba0eaa3b88cba..9349d12b70e69c4f7bc28f6169f75768b8c932e1 100644 (file)
 #ifndef YASM_GLOBALS_H
 #define YASM_GLOBALS_H
 
+/* Current (selected) parser */
+extern /*@null@*/ parser *cur_parser;
+
+/* Current (selected) object format */
+extern /*@null@*/ objfmt *cur_objfmt;
+
 /*@null@*/ /*@dependent@*/ extern const char *in_filename;
 extern unsigned int line_number;
 extern unsigned int asm_options;
index ea82030697176befac52787bd6fa9e3c3434b23e..e484dbd87bb764a3f3c1f1a3ba937d2e936938e4 100644 (file)
@@ -46,13 +46,27 @@ struct objfmt {
      */
 /*    debugfmt *default_df;*/
 
-    /* Is the specified section name valid?
-     * Return is a boolean value.
+    /* Switch object file sections.  The first val of the valparams should
+     * be the section name.
      */
-    int (*is_valid_section) (const char *name);
+    /*@dependent@*/ /*@null@*/ section *
+       (*sections_switch)(sectionhead *headp, valparamhead *valparams,
+                          /*@null@*/ valparamhead *objext_valparams);
+
+    void (*section_data_delete)(/*@only@*/ void *data);
+    void (*section_data_print)(void *data);
 };
 
-/* Available object formats */
-extern objfmt dbg_objfmt;
+/* Generic functions for all object formats - implemented in src/objfmt.c */
+
+/* Finds an object format based on its keyword.  Returns NULL if no match was
+ * found.
+ */
+/*@null@*/ objfmt *find_objfmt(const char *keyword);
+
+/* Lists all available object formats.  Calls printfunc with the name and
+ * keyword of each available format.
+ */
+void list_objfmts(void (*printfunc) (const char *name, const char *keyword));
 
 #endif
index 822c9d4a880511b81f8f46331183e75181e2ce51..7365f1c37f27ee0d99c499d4a0bf705a6c673f96 100644 (file)
@@ -52,7 +52,7 @@ struct parser {
      * This function returns the starting section of a linked list of sections
      * (whatever was in the file).
      */
-    sectionhead *(*do_parse) (parser *p, objfmt *of, FILE *f);
+    sectionhead *(*do_parse) (parser *p, FILE *f);
 };
 
 /* Generic functions for all parsers - implemented in src/parser.c */
@@ -77,7 +77,4 @@ void parser_listpp(parser *p,
  */
 void list_parsers(void (*printfunc) (const char *name, const char *keyword));
 
-/* Available parsers */
-extern parser nasm_parser;
-
 #endif
index f585e7bc60c1162056e9ce04baf74f1e62222b9c..68d4b2d4295371160d2535d8b0253cad75c4f7b2 100644 (file)
@@ -39,7 +39,7 @@ struct preproc {
      * not the filename (which is in a global variable and is not
      * preprocessor-specific).
      */
-    void (*initialize) (objfmt *of, FILE *f);
+    void (*initialize) (FILE *f);
 
     /* Gets more preprocessed source code (up to max_size bytes) into buf.
      * Note that more than a single line may be returned in buf. */
index 4900479b49ce98de7e76700bee586c47519b6bc0..eb76a74d4fb210ba78c32d7bc5ad23df0522a55c 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
 #include "globals.h"
 #include "errwarn.h"
 #include "expr.h"
@@ -36,19 +40,27 @@ struct section {
 
     enum { SECTION_GENERAL, SECTION_ABSOLUTE } type;
 
-    char *name;                        /* strdup()'ed name (given by user) */
-
     union {
        /* SECTION_GENERAL data */
+       struct general {
+           /*@owned@*/ char *name;     /* strdup()'ed name (given by user) */
+
+           /* object-format-specific data */ 
+           /*@null@*/ /*@owned@*/ void *of_data;
+       } general;
+
        /* SECTION_ABSOLUTE data */
-       unsigned long start;
+       /*@owned@*/ expr *start;
     } data;
 
+
+    int res_only;              /* allow only resb family of bytecodes? */
+
     bytecodehead bc;           /* the bytecodes for the section's contents */
 };
 
 section *
-sections_initialize(sectionhead *headp, objfmt *of)
+sections_initialize(sectionhead *headp)
 {
     section *s;
 
@@ -61,56 +73,80 @@ sections_initialize(sectionhead *headp, objfmt *of)
 
     /* Initialize default section */
     s->type = SECTION_GENERAL;
-    s->name = xstrdup(of->default_section_name);
+    assert(cur_objfmt != NULL);
+    s->data.general.name = xstrdup(cur_objfmt->default_section_name);
+    s->data.general.of_data = NULL;
     bytecodes_initialize(&s->bc);
 
-    s->data.start = 0;
+    s->res_only = 0;
 
     return s;
 }
 
 /*@-onlytrans@*/
 section *
-sections_switch(sectionhead *headp, objfmt *of, const char *name)
+sections_switch_general(sectionhead *headp, const char *name, void *of_data,
+                       int res_only)
 {
-    section *s, *sp;
+    section *s;
 
     /* Search through current sections to see if we already have one with
      * that name.
      */
-    s = (section *)NULL;
-    STAILQ_FOREACH(sp, headp, link) {
-       if (strcmp(sp->name, name) == 0)
-           s = sp;
+    STAILQ_FOREACH(s, headp, link) {
+       if (s->type == SECTION_GENERAL &&
+           strcmp(s->data.general.name, name) == 0) {
+           if (of_data) {
+               Warning(_("segment attributes specified on redeclaration of segment: ignoring"));
+               assert(cur_objfmt != NULL);
+               cur_objfmt->section_data_delete(of_data);
+           }
+           return s;
+       }
     }
 
-    if (s)
-       return s;
-
     /* No: we have to allocate and create a new one. */
 
-    /* But first check with objfmt to see if the name is valid.
-     * If it isn't, error and just return the default (first) section.
-     */
-    if (!of->is_valid_section(name)) {
-       Error(_("Invalid section name: %s"), name);
-       return STAILQ_FIRST(headp);
-    }
-
     /* Okay, the name is valid; now allocate and initialize */
     s = xcalloc(1, sizeof(section));
     STAILQ_INSERT_TAIL(headp, s, link);
 
     s->type = SECTION_GENERAL;
-    s->name = xstrdup(name);
+    s->data.general.name = xstrdup(name);
+    s->data.general.of_data = of_data;
+    bytecodes_initialize(&s->bc);
+
+    s->res_only = res_only;
+
+    return s;
+}
+/*@=onlytrans@*/
+
+/*@-onlytrans@*/
+section *
+sections_switch_absolute(sectionhead *headp, expr *start)
+{
+    section *s;
+
+    s = xcalloc(1, sizeof(section));
+    STAILQ_INSERT_TAIL(headp, s, link);
+
+    s->type = SECTION_ABSOLUTE;
+    s->data.start = start;
     bytecodes_initialize(&s->bc);
 
-    s->data.start = 0;
+    s->res_only = 1;
 
     return s;
 }
 /*@=onlytrans@*/
 
+int
+section_is_absolute(section *sect)
+{
+    return (sect->type == SECTION_ABSOLUTE);
+}
+
 void
 sections_delete(sectionhead *headp)
 {
@@ -130,8 +166,10 @@ sections_print(const sectionhead *headp)
 {
     section *cur;
     
-    STAILQ_FOREACH(cur, headp, link)
+    STAILQ_FOREACH(cur, headp, link) {
+       printf("***SECTION***\n");
        section_print(cur);
+    }
 }
 
 void
@@ -152,7 +190,17 @@ section_get_bytecodes(section *sect)
 const char *
 section_get_name(const section *sect)
 {
-    return sect->name;
+    if (sect->type == SECTION_GENERAL)
+       return sect->data.general.name;
+    return NULL;
+}
+
+const expr *
+section_get_start(const section *sect)
+{
+    if (sect->type == SECTION_ABSOLUTE)
+       return sect->data.start;
+    return NULL;
 }
 
 void
@@ -161,7 +209,17 @@ section_delete(section *sect)
     if (!sect)
        return;
 
-    xfree(sect->name);
+    switch (sect->type) {
+       case SECTION_GENERAL:
+           xfree(sect->data.general.name);
+           assert(cur_objfmt != NULL);
+           if (sect->data.general.of_data)
+               cur_objfmt->section_data_delete(sect->data.general.of_data);
+           break;
+       case SECTION_ABSOLUTE:
+           expr_delete(sect->data.start);
+           break;
+    }
     bcs_delete(&sect->bc);
     xfree(sect);
 }
@@ -169,15 +227,21 @@ section_delete(section *sect)
 void
 section_print(const section *sect)
 {
-    printf("***SECTION %s***\n", sect->name);
     printf(" type=");
     switch (sect->type) {
        case SECTION_GENERAL:
-           printf("general\n");
+           printf("general\n name=%s\n objfmt data:\n",
+                  sect->data.general.name);
+           assert(cur_objfmt != NULL);
+           if (sect->data.general.of_data)
+               cur_objfmt->section_data_print(sect->data.general.of_data);
+           else
+               printf("  (none)\n");
            break;
        case SECTION_ABSOLUTE:
-           printf("absolute\n");
-           printf("start=%lu\n", sect->data.start);
+           printf("absolute\n start=");
+           expr_print(sect->data.start);
+           printf("\n");
            break;
     }
 
index 05e9c091164a590c934efb2101e7c2bfb68a681c..8c8da8eb4cb65d4086061f16d9f80e15bf4fcb3f 100644 (file)
 
 struct objfmt;
 
-/*@dependent@*/ section *sections_initialize(sectionhead *headp,
-                                            struct objfmt *of);
+/*@dependent@*/ section *sections_initialize(sectionhead *headp);
 
-/*@dependent@*/ section *sections_switch(sectionhead *headp, struct objfmt *of,
-                                        const char *name);
+/*@dependent@*/ section *sections_switch_general(sectionhead *headp,
+                                                const char *name,
+                                                /*@null@*/ /*@only@*/
+                                                void *of_data, int res_only);
+
+/*@dependent@*/ section *sections_switch_absolute(sectionhead *headp,
+                                                 /*@keep@*/ expr *start);
+
+int section_is_absolute(section *sect);
 
 void sections_delete(sectionhead *headp);
 
@@ -38,7 +44,8 @@ void sections_parser_finalize(sectionhead *headp);
 
 /*@dependent@*/ bytecodehead *section_get_bytecodes(section *sect);
 
-/*@observer@*/ const char *section_get_name(const section *sect);
+/*@observer@*/ /*@null@*/ const char *section_get_name(const section *sect);
+/*@observer@*/ /*@null@*/ const expr *section_get_start(const section *sect);
 
 void section_delete(/*@only@*/ section *sect);
 
index b1871689034af0fa1f0427d6ef632c45244973f9..041d28fe92cec9ba4b79f62f40fbcc4516296c95 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
 #include "ternary.h"
 
 #include "globals.h"
@@ -291,9 +295,11 @@ symrec_print(const symrec *sym)
            printf("\n");
            break;
        case SYM_LABEL:
-           printf("_Label_\n");
-           printf("Section=`%s'\n", sym->value.label.sect?
-                  section_get_name(sym->value.label.sect):"(nil)");
+           printf("_Label_\nSection:");
+           if (sym->value.label.sect)
+               section_print(sym->value.label.sect);
+           else
+               printf(" (none)\n");
            if (!sym->value.label.bc)
                printf("[First bytecode]\n");
            else {
index 36e4bb1d0d521b63ddc446418453f7a4cb0f566a..b7e4b4894228e2367588cf0a3b0aad2447da4e64 100644 (file)
@@ -21,6 +21,7 @@ noinst_PROGRAMS =
 endif
 
 LDADD = \
+       $(top_builddir)/src/libyasm.a                           \
        $(top_builddir)/check/libcheck.a                        \
        $(top_builddir)/src/parsers/nasm/libparser.a            \
        $(top_builddir)/src/preprocs/raw/libpreproc.a           \
index 41e2f2f0700ce06c5c2fd174d7185ecd74ebcf16..21a620fa230e163685025c67eb0852ea9bcef3ed 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#include "expr.h"
+#include "symrec.h"
+
+#include "section.h"
 #include "objfmt.h"
 
 
-static int
-dbg_objfmt_is_valid_section(const char *name)
+static /*@dependent@*/ /*@null@*/ section *
+dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
+                          /*@unused@*/ /*@null@*/
+                          valparamhead *objext_valparams)
+{
+    valparam *vp;
+    section *retval;
+
+#if 0
+    fprintf(stderr, "-dbg_objfmt_sections_switch():\n");
+    printf(" Val/Params:\n");
+    vps_foreach(vp, valparams) {
+       printf("  (%s,", vp->val?vp->val:"(nil)");
+       if (vp->param)
+           expr_print(vp->param);
+       else
+           printf("(nil)");
+       printf(")\n");
+    }
+    printf(" Obj Ext Val/Params:\n");
+    if (!objext_valparams)
+       printf("  (none)\n");
+    else
+       vps_foreach(vp, objext_valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+#endif
+    if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) {
+       retval = sections_switch_general(headp, vp->val, NULL, 0);
+       symrec_define_label(vp->val, retval, (bytecode *)NULL, 1);
+       return retval;
+    } else
+       return NULL;
+}
+
+static void
+dbg_objfmt_section_data_delete(/*@only@*/ void *data)
+{
+    xfree(data);
+}
+
+static void
+dbg_objfmt_section_data_print(/*@unused@*/ void *data)
 {
-    fprintf(stderr, "-dbg_objfmt_is_valid_section(\"%s\")\n", name);
-    return 1;
 }
 
 /* Define objfmt structure -- see objfmt.h for details */
@@ -38,5 +86,7 @@ objfmt dbg_objfmt = {
     "dbg",
     ".text",
     32,
-    dbg_objfmt_is_valid_section
+    dbg_objfmt_sections_switch,
+    dbg_objfmt_section_data_delete,
+    dbg_objfmt_section_data_print
 };
index 41e2f2f0700ce06c5c2fd174d7185ecd74ebcf16..21a620fa230e163685025c67eb0852ea9bcef3ed 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#include "expr.h"
+#include "symrec.h"
+
+#include "section.h"
 #include "objfmt.h"
 
 
-static int
-dbg_objfmt_is_valid_section(const char *name)
+static /*@dependent@*/ /*@null@*/ section *
+dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
+                          /*@unused@*/ /*@null@*/
+                          valparamhead *objext_valparams)
+{
+    valparam *vp;
+    section *retval;
+
+#if 0
+    fprintf(stderr, "-dbg_objfmt_sections_switch():\n");
+    printf(" Val/Params:\n");
+    vps_foreach(vp, valparams) {
+       printf("  (%s,", vp->val?vp->val:"(nil)");
+       if (vp->param)
+           expr_print(vp->param);
+       else
+           printf("(nil)");
+       printf(")\n");
+    }
+    printf(" Obj Ext Val/Params:\n");
+    if (!objext_valparams)
+       printf("  (none)\n");
+    else
+       vps_foreach(vp, objext_valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+#endif
+    if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) {
+       retval = sections_switch_general(headp, vp->val, NULL, 0);
+       symrec_define_label(vp->val, retval, (bytecode *)NULL, 1);
+       return retval;
+    } else
+       return NULL;
+}
+
+static void
+dbg_objfmt_section_data_delete(/*@only@*/ void *data)
+{
+    xfree(data);
+}
+
+static void
+dbg_objfmt_section_data_print(/*@unused@*/ void *data)
 {
-    fprintf(stderr, "-dbg_objfmt_is_valid_section(\"%s\")\n", name);
-    return 1;
 }
 
 /* Define objfmt structure -- see objfmt.h for details */
@@ -38,5 +86,7 @@ objfmt dbg_objfmt = {
     "dbg",
     ".text",
     32,
-    dbg_objfmt_is_valid_section
+    dbg_objfmt_sections_switch,
+    dbg_objfmt_section_data_delete,
+    dbg_objfmt_section_data_print
 };
index 47ddce63cca3f7354c6c3d50641bdb48804e5816..4380b0141f8eeeda00f919379af40a7376aef68f 100644 (file)
@@ -24,7 +24,7 @@ endif
 
 noinst_SCRIPTS = gen_instr.pl
 
-AM_YFLAGS = -d --name-prefix=nasm_parser_
+AM_YFLAGS = -v -d --name-prefix=nasm_parser_
 AM_LFLAGS = -Pnasm_parser_ -olex.yy.c
 
 INCLUDES = \
index 4de5d9f8ae491bb762c8f5969597a7821557e335..4317140e2a3ce6a5deaef014d93adabffda77cf7 100644 (file)
@@ -24,6 +24,7 @@
 RCSID("$IdPath$");
 
 #ifdef STDC_HEADERS
+# include <assert.h>
 # include <math.h>
 #endif
 
@@ -42,12 +43,12 @@ RCSID("$IdPath$");
 
 #include "arch.h"
 
-#define YYDEBUG 1
-
 void init_table(void);
 extern int nasm_parser_lex(void);
 void nasm_parser_error(const char *);
-static void nasm_parser_directive(const char *name, const char *val);
+static void nasm_parser_directive(const char *name,
+                                 valparamhead *valparams,
+                                 /*@null@*/ valparamhead *objext_valparams);
 
 extern objfmt *nasm_parser_objfmt;
 extern sectionhead nasm_parser_sections;
@@ -77,11 +78,13 @@ static bytecode *nasm_parser_temp_bc;
     datavalhead datahead;
     dataval *data;
     bytecode *bc;
+    valparamhead dir_valparams;
+    valparam *dir_valparam;
 }
 
 %token <intn> INTNUM
 %token <flt> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
+%token <str_val> DIRECTIVE_NAME STRING
 %token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_info> DECLARE_DATA
 %token <int_info> RESERVE_SPACE
@@ -113,12 +116,14 @@ static bytecode *nasm_parser_temp_bc;
 %type <ea> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr expr_no_string memexpr
+%type <exp> expr expr_no_string memexpr direxpr
 %type <sym> explabel
 %type <str_val> label_id
 %type <tgt_val> target
 %type <data> dataval
 %type <datahead> datavals
+%type <dir_valparams> directive_valparams
+%type <dir_valparam> directive_valparam
 
 %left '|'
 %left '^'
@@ -201,22 +206,40 @@ label_id: ID          {
 ;
 
 /* directives */
-directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']'        {
-       nasm_parser_directive($2, $3);
+directive: '[' DIRECTIVE_NAME directive_val ']'        {
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME DIRECTIVE_VAL error   {
-       Error(_("missing `%c'"), ']');
+    | '[' DIRECTIVE_NAME error ']'             {
+       Error(_("invalid arguments to [%s]"), $2);
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME error                 {
-       Error(_("missing argument to `%s'"), $2);
-       xfree($2);
+;
+
+    /* $<str_val>0 is the DIRECTIVE_NAME */
+    /* After : is (optional) object-format specific extension */
+directive_val: directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, NULL);
+    }
+    | directive_valparams ':' directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, &$3);
+    }
+;
+
+directive_valparams: directive_valparam                {
+       vps_initialize(&$$);
+       vps_append(&$$, $1);
+    }
+    | directive_valparams directive_valparam   {
+       vps_append(&$1, $2);
+       $$ = $1;
     }
 ;
 
+directive_valparam: ID         { vp_new($$, $1, NULL); }
+    | direxpr                  { vp_new($$, NULL, $1); }
+    | ID '=' direxpr           { vp_new($$, $1, $3); }
+;
+
 /* register groupings */
 fpureg: ST0
     | FPUREG_NOTST0
@@ -454,6 +477,26 @@ target: expr               {
 ;
 
 /* expression trees */
+
+/* expr w/o FLTNUM and unary + and -, for use in directives */
+direxpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | direxpr '|' direxpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | direxpr '^' direxpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    | direxpr '&' direxpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    | direxpr LEFT_OP direxpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | direxpr RIGHT_OP direxpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | direxpr '+' direxpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | direxpr '-' direxpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | direxpr '*' direxpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | direxpr '/' direxpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | direxpr SIGNDIV direxpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | direxpr '%' direxpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | direxpr SIGNMOD direxpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    /*| '!' expr               { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' direxpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' direxpr ')'          { $$ = $2; }
+;
+
 expr_no_string: INTNUM         { $$ = expr_new_ident(ExprInt($1)); }
     | FLTNUM                   { $$ = expr_new_ident(ExprFloat($1)); }
     | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
@@ -491,15 +534,31 @@ expr: expr_no_string
     }
 ;
 
-explabel: ID           { $$ = symrec_use($1); xfree($1); }
-    | SPECIAL_ID       { $$ = symrec_use($1); xfree($1); }
-    | LOCAL_ID         { $$ = symrec_use($1); xfree($1); }
+explabel: ID           {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | SPECIAL_ID       {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | LOCAL_ID         {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
     | '$'              {
        $$ = symrec_define_label("$", nasm_parser_cur_section,
                                 nasm_parser_prev_bc, 0);
     }
     | START_SECTION_ID {
-       $$ = symrec_use(section_get_name(nasm_parser_cur_section));
+       if (section_is_absolute(nasm_parser_cur_section)) {
+           Error(_("`$$' is not valid within an ABSOLUTE section"));
+           YYERROR;
+       } else {
+           const char *ss_name = section_get_name(nasm_parser_cur_section);
+           assert(ss_name != NULL);
+           $$ = symrec_use(ss_name);
+       }
     }
 ;
 
@@ -543,25 +602,66 @@ instr: instrbase
 /*@=usedef =nullassign =memtrans =usereleased =compdef =mustfree@*/
 
 static void
-nasm_parser_directive(const char *name, const char *val)
+nasm_parser_directive(const char *name, valparamhead *valparams,
+                     valparamhead *objext_valparams)
 {
+    valparam *vp;
+    const intnum *intn;
     long lval;
-    char *end;
 
+    assert(cur_objfmt != NULL);
     if (strcasecmp(name, "section") == 0) {
-       nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
-                                                 nasm_parser_objfmt, val);
+       section *new_section =
+           cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
+                                       objext_valparams);
+       if (new_section) {
+           nasm_parser_cur_section = new_section;
+           nasm_parser_prev_bc = (bytecode *)NULL;
+       } else
+           Error(_("invalid argument to [%s]"), "SECTION");
+    } else if (strcasecmp(name, "absolute") == 0) {
+       vp = vps_first(valparams);
+       nasm_parser_cur_section =
+           sections_switch_absolute(&nasm_parser_sections, vp->val ?
+               expr_new_ident(ExprSym(symrec_use(vp->val))) : vp->param);
        nasm_parser_prev_bc = (bytecode *)NULL;
-       symrec_define_label(val, nasm_parser_cur_section, (bytecode *)NULL, 1);
     } else if (strcasecmp(name, "bits") == 0) {
-       lval = strtol(val, &end, 10);
-       if (*val == '\0' || *end != '\0' || (lval != 16 && lval != 32))
-           Error(_("`%s' is not a valid argument to [BITS]"), val);
-       else
+       if ((vp = vps_first(valparams)) && !vp->val && vp->param != NULL &&
+           (intn = expr_get_intnum(&vp->param)) != NULL &&
+           (lval = intnum_get_int(intn)) && (lval == 16 || lval == 32))
            x86_mode_bits = (unsigned char)lval;
+       else
+           Error(_("invalid argument to [%s]"), "BITS");
     } else {
-       printf("Directive: Name=`%s' Value=`%s'\n", name, val);
+       Error(_("unrecognized directive [%s]"), name);
+#if 0
+       printf("Directive: Name=`%s'\n Val/Params:\n", name);
+       vps_foreach(vp, valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+       printf(" Obj Ext Val/Params:\n");
+       if (!objext_valparams)
+           printf("  (none)\n");
+       else
+           vps_foreach(vp, objext_valparams) {
+               printf("  (%s,", vp->val?vp->val:"(nil)");
+               if (vp->param)
+                   expr_print(vp->param);
+               else
+                   printf("(nil)");
+               printf(")\n");
+           }
+#endif
     }
+
+    vps_delete(valparams);
+    if (objext_valparams)
+       vps_delete(objext_valparams);
 }
 
 void
index 4de5d9f8ae491bb762c8f5969597a7821557e335..4317140e2a3ce6a5deaef014d93adabffda77cf7 100644 (file)
@@ -24,6 +24,7 @@
 RCSID("$IdPath$");
 
 #ifdef STDC_HEADERS
+# include <assert.h>
 # include <math.h>
 #endif
 
@@ -42,12 +43,12 @@ RCSID("$IdPath$");
 
 #include "arch.h"
 
-#define YYDEBUG 1
-
 void init_table(void);
 extern int nasm_parser_lex(void);
 void nasm_parser_error(const char *);
-static void nasm_parser_directive(const char *name, const char *val);
+static void nasm_parser_directive(const char *name,
+                                 valparamhead *valparams,
+                                 /*@null@*/ valparamhead *objext_valparams);
 
 extern objfmt *nasm_parser_objfmt;
 extern sectionhead nasm_parser_sections;
@@ -77,11 +78,13 @@ static bytecode *nasm_parser_temp_bc;
     datavalhead datahead;
     dataval *data;
     bytecode *bc;
+    valparamhead dir_valparams;
+    valparam *dir_valparam;
 }
 
 %token <intn> INTNUM
 %token <flt> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
+%token <str_val> DIRECTIVE_NAME STRING
 %token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_info> DECLARE_DATA
 %token <int_info> RESERVE_SPACE
@@ -113,12 +116,14 @@ static bytecode *nasm_parser_temp_bc;
 %type <ea> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr expr_no_string memexpr
+%type <exp> expr expr_no_string memexpr direxpr
 %type <sym> explabel
 %type <str_val> label_id
 %type <tgt_val> target
 %type <data> dataval
 %type <datahead> datavals
+%type <dir_valparams> directive_valparams
+%type <dir_valparam> directive_valparam
 
 %left '|'
 %left '^'
@@ -201,22 +206,40 @@ label_id: ID          {
 ;
 
 /* directives */
-directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']'        {
-       nasm_parser_directive($2, $3);
+directive: '[' DIRECTIVE_NAME directive_val ']'        {
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME DIRECTIVE_VAL error   {
-       Error(_("missing `%c'"), ']');
+    | '[' DIRECTIVE_NAME error ']'             {
+       Error(_("invalid arguments to [%s]"), $2);
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME error                 {
-       Error(_("missing argument to `%s'"), $2);
-       xfree($2);
+;
+
+    /* $<str_val>0 is the DIRECTIVE_NAME */
+    /* After : is (optional) object-format specific extension */
+directive_val: directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, NULL);
+    }
+    | directive_valparams ':' directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, &$3);
+    }
+;
+
+directive_valparams: directive_valparam                {
+       vps_initialize(&$$);
+       vps_append(&$$, $1);
+    }
+    | directive_valparams directive_valparam   {
+       vps_append(&$1, $2);
+       $$ = $1;
     }
 ;
 
+directive_valparam: ID         { vp_new($$, $1, NULL); }
+    | direxpr                  { vp_new($$, NULL, $1); }
+    | ID '=' direxpr           { vp_new($$, $1, $3); }
+;
+
 /* register groupings */
 fpureg: ST0
     | FPUREG_NOTST0
@@ -454,6 +477,26 @@ target: expr               {
 ;
 
 /* expression trees */
+
+/* expr w/o FLTNUM and unary + and -, for use in directives */
+direxpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | direxpr '|' direxpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | direxpr '^' direxpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    | direxpr '&' direxpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    | direxpr LEFT_OP direxpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | direxpr RIGHT_OP direxpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | direxpr '+' direxpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | direxpr '-' direxpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | direxpr '*' direxpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | direxpr '/' direxpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | direxpr SIGNDIV direxpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | direxpr '%' direxpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | direxpr SIGNMOD direxpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    /*| '!' expr               { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' direxpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' direxpr ')'          { $$ = $2; }
+;
+
 expr_no_string: INTNUM         { $$ = expr_new_ident(ExprInt($1)); }
     | FLTNUM                   { $$ = expr_new_ident(ExprFloat($1)); }
     | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
@@ -491,15 +534,31 @@ expr: expr_no_string
     }
 ;
 
-explabel: ID           { $$ = symrec_use($1); xfree($1); }
-    | SPECIAL_ID       { $$ = symrec_use($1); xfree($1); }
-    | LOCAL_ID         { $$ = symrec_use($1); xfree($1); }
+explabel: ID           {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | SPECIAL_ID       {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | LOCAL_ID         {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
     | '$'              {
        $$ = symrec_define_label("$", nasm_parser_cur_section,
                                 nasm_parser_prev_bc, 0);
     }
     | START_SECTION_ID {
-       $$ = symrec_use(section_get_name(nasm_parser_cur_section));
+       if (section_is_absolute(nasm_parser_cur_section)) {
+           Error(_("`$$' is not valid within an ABSOLUTE section"));
+           YYERROR;
+       } else {
+           const char *ss_name = section_get_name(nasm_parser_cur_section);
+           assert(ss_name != NULL);
+           $$ = symrec_use(ss_name);
+       }
     }
 ;
 
@@ -543,25 +602,66 @@ instr: instrbase
 /*@=usedef =nullassign =memtrans =usereleased =compdef =mustfree@*/
 
 static void
-nasm_parser_directive(const char *name, const char *val)
+nasm_parser_directive(const char *name, valparamhead *valparams,
+                     valparamhead *objext_valparams)
 {
+    valparam *vp;
+    const intnum *intn;
     long lval;
-    char *end;
 
+    assert(cur_objfmt != NULL);
     if (strcasecmp(name, "section") == 0) {
-       nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
-                                                 nasm_parser_objfmt, val);
+       section *new_section =
+           cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
+                                       objext_valparams);
+       if (new_section) {
+           nasm_parser_cur_section = new_section;
+           nasm_parser_prev_bc = (bytecode *)NULL;
+       } else
+           Error(_("invalid argument to [%s]"), "SECTION");
+    } else if (strcasecmp(name, "absolute") == 0) {
+       vp = vps_first(valparams);
+       nasm_parser_cur_section =
+           sections_switch_absolute(&nasm_parser_sections, vp->val ?
+               expr_new_ident(ExprSym(symrec_use(vp->val))) : vp->param);
        nasm_parser_prev_bc = (bytecode *)NULL;
-       symrec_define_label(val, nasm_parser_cur_section, (bytecode *)NULL, 1);
     } else if (strcasecmp(name, "bits") == 0) {
-       lval = strtol(val, &end, 10);
-       if (*val == '\0' || *end != '\0' || (lval != 16 && lval != 32))
-           Error(_("`%s' is not a valid argument to [BITS]"), val);
-       else
+       if ((vp = vps_first(valparams)) && !vp->val && vp->param != NULL &&
+           (intn = expr_get_intnum(&vp->param)) != NULL &&
+           (lval = intnum_get_int(intn)) && (lval == 16 || lval == 32))
            x86_mode_bits = (unsigned char)lval;
+       else
+           Error(_("invalid argument to [%s]"), "BITS");
     } else {
-       printf("Directive: Name=`%s' Value=`%s'\n", name, val);
+       Error(_("unrecognized directive [%s]"), name);
+#if 0
+       printf("Directive: Name=`%s'\n Val/Params:\n", name);
+       vps_foreach(vp, valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+       printf(" Obj Ext Val/Params:\n");
+       if (!objext_valparams)
+           printf("  (none)\n");
+       else
+           vps_foreach(vp, objext_valparams) {
+               printf("  (%s,", vp->val?vp->val:"(nil)");
+               if (vp->param)
+                   expr_print(vp->param);
+               else
+                   printf("(nil)");
+               printf(")\n");
+           }
+#endif
     }
+
+    vps_delete(valparams);
+    if (objext_valparams)
+       vps_delete(objext_valparams);
 }
 
 void
index 66779fcaed0b1a9070944a96fc96c9971680fdbc..0b896f94a74324db2830a39e87e757549cea8a38 100644 (file)
@@ -37,24 +37,21 @@ extern int nasm_parser_parse(void);
 
 size_t (*nasm_parser_yyinput) (char *buf, size_t max_size);
 
-objfmt *nasm_parser_objfmt;
 sectionhead nasm_parser_sections;
 /*@dependent@*/ section *nasm_parser_cur_section;
 
 extern /*@only@*/ char *nasm_parser_locallabel_base;
 
 static /*@dependent@*/ sectionhead *
-nasm_parser_do_parse(parser *p, objfmt *of, FILE *f)
+nasm_parser_do_parse(parser *p, FILE *f)
     /*@globals killed nasm_parser_locallabel_base @*/
 {
-    p->current_pp->initialize(of, f);
+    p->current_pp->initialize(f);
     nasm_parser_in = f;
     nasm_parser_yyinput = p->current_pp->input;
 
-    nasm_parser_objfmt = of;
-
     /* Initialize section list */
-    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections, of);
+    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections);
 
     /* yacc debugging, needs YYDEBUG set in bison.y.in to work */
     /* nasm_parser_debug = 1; */
index 66779fcaed0b1a9070944a96fc96c9971680fdbc..0b896f94a74324db2830a39e87e757549cea8a38 100644 (file)
@@ -37,24 +37,21 @@ extern int nasm_parser_parse(void);
 
 size_t (*nasm_parser_yyinput) (char *buf, size_t max_size);
 
-objfmt *nasm_parser_objfmt;
 sectionhead nasm_parser_sections;
 /*@dependent@*/ section *nasm_parser_cur_section;
 
 extern /*@only@*/ char *nasm_parser_locallabel_base;
 
 static /*@dependent@*/ sectionhead *
-nasm_parser_do_parse(parser *p, objfmt *of, FILE *f)
+nasm_parser_do_parse(parser *p, FILE *f)
     /*@globals killed nasm_parser_locallabel_base @*/
 {
-    p->current_pp->initialize(of, f);
+    p->current_pp->initialize(f);
     nasm_parser_in = f;
     nasm_parser_yyinput = p->current_pp->input;
 
-    nasm_parser_objfmt = of;
-
     /* Initialize section list */
-    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections, of);
+    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections);
 
     /* yacc debugging, needs YYDEBUG set in bison.y.in to work */
     /* nasm_parser_debug = 1; */
index 1fd8303efa7ff9def1663e05e8d3731aceb80d30..a24da44ebb21f80c1541400b3325adf358baf90b 100644 (file)
@@ -68,7 +68,8 @@ int line_number;
 %option nounput
 %option case-insensitive
 
-%x DIRECTIVE DIRECTIVE2
+%x DIRECTIVE
+%s DIRECTIVE2
 
 DIGIT    [0-9]
 BINDIGIT [01]
@@ -158,26 +159,21 @@ WS       [ \t\r]
 <DIRECTIVE2>"]"            { BEGIN INITIAL; return ']'; }
 <DIRECTIVE>\n      { BEGIN INITIAL; return '\n'; }
 <DIRECTIVE2>\n     { BEGIN INITIAL; return '\n'; }
-<DIRECTIVE>{WS}+    ;
-<DIRECTIVE2>{WS}+   ;
 
 <DIRECTIVE>[a-z]+   {
     BEGIN DIRECTIVE2;
     yylval.str_val = xstrdup(yytext);
     return DIRECTIVE_NAME;
-}
-    /* everything printable except for ' ', '[' and ']'. */
-<DIRECTIVE2>[!-@a-z\\^-`{|}~]+ {
-    yylval.str_val = xstrdup(yytext);
-    return DIRECTIVE_VAL;
 }
 <DIRECTIVE>. {
     Warning(_("ignoring unrecognized character `%s'"),
            conv_unprint(yytext[0]));
 }
-<DIRECTIVE2>. {
-    Warning(_("ignoring unrecognized character `%s'"),
-           conv_unprint(yytext[0]));
+
+    /* override local labels in directive state */
+<DIRECTIVE2>\.[a-z0-9_$#@~.?]* {
+    yylval.str_val = xstrdup(yytext);
+    return ID;
 }
 
     /* size specifiers */
@@ -288,7 +284,7 @@ gs  { yylval.int_info = 5; return REG_GS; }
 "//"                   { return SIGNDIV; }
 "%%"                   { return SIGNMOD; }
 "$$"                   { return START_SECTION_ID; }
-[-+|^&*/%~$():[\],]    { return yytext[0]; }
+[-+|^&*/%~$():[\]=,]   { return yytext[0]; }
 
     /* special non-local ..@label and labels like ..start */
 \.\.[a-z0-9_$#@~.?]+ {
index ca9fb2647cea4055c3bb755fb339301be814cec9..419f7708d960e88e977e69267f2c01d3ca3486b8 100644 (file)
@@ -33,7 +33,7 @@ static FILE *in;
 int isatty(int);
 
 static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
 {
     in = f;
     /*@-unrecog@*/
index ca9fb2647cea4055c3bb755fb339301be814cec9..419f7708d960e88e977e69267f2c01d3ca3486b8 100644 (file)
@@ -33,7 +33,7 @@ static FILE *in;
 int isatty(int);
 
 static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
 {
     in = f;
     /*@-unrecog@*/
index fd68d0924219aa826e05a5df02f21ef58967ce73..5650b0f3816246d2659fe0c0d5bdd5a55e876aa9 100644 (file)
@@ -12,6 +12,7 @@ yasm_SOURCES = \
        errwarn.h
 
 yasm_LDADD = \
+       libyasm.a                       \
        arch/@ARCH@/libarch.a           \
        parsers/nasm/libparser.a        \
        preprocs/raw/libpreproc.a       \
@@ -41,6 +42,7 @@ libyasm_a_SOURCES = \
        section.h               \
        arch.c                  \
        arch.h                  \
+       objfmt.c                \
        objfmt.h                \
        options.h               \
        options.c               \
index b5abfe9b5d31c2f348dc65be9fa077f56762d8ad..895ff64fcbd6d92121311f7b1aa3e1a08a5a294f 100644 (file)
 #include "globals.h"
 
 
+/* Current (selected) parser */
+/*@null@*/ parser *cur_parser = NULL;
+
+/* Current (selected) object format) */
+/*@null@*/ objfmt *cur_objfmt = NULL;
+
 /*@null@*/ /*@dependent@*/ const char *in_filename = (const char *)NULL;
 unsigned int line_number = 1;
 unsigned int asm_options = 0;
index bf37e4a8bd2a19198e2dccfee4bba0eaa3b88cba..9349d12b70e69c4f7bc28f6169f75768b8c932e1 100644 (file)
 #ifndef YASM_GLOBALS_H
 #define YASM_GLOBALS_H
 
+/* Current (selected) parser */
+extern /*@null@*/ parser *cur_parser;
+
+/* Current (selected) object format */
+extern /*@null@*/ objfmt *cur_objfmt;
+
 /*@null@*/ /*@dependent@*/ extern const char *in_filename;
 extern unsigned int line_number;
 extern unsigned int asm_options;
index b5abfe9b5d31c2f348dc65be9fa077f56762d8ad..895ff64fcbd6d92121311f7b1aa3e1a08a5a294f 100644 (file)
 #include "globals.h"
 
 
+/* Current (selected) parser */
+/*@null@*/ parser *cur_parser = NULL;
+
+/* Current (selected) object format) */
+/*@null@*/ objfmt *cur_objfmt = NULL;
+
 /*@null@*/ /*@dependent@*/ const char *in_filename = (const char *)NULL;
 unsigned int line_number = 1;
 unsigned int asm_options = 0;
index bf37e4a8bd2a19198e2dccfee4bba0eaa3b88cba..9349d12b70e69c4f7bc28f6169f75768b8c932e1 100644 (file)
 #ifndef YASM_GLOBALS_H
 #define YASM_GLOBALS_H
 
+/* Current (selected) parser */
+extern /*@null@*/ parser *cur_parser;
+
+/* Current (selected) object format */
+extern /*@null@*/ objfmt *cur_objfmt;
+
 /*@null@*/ /*@dependent@*/ extern const char *in_filename;
 extern unsigned int line_number;
 extern unsigned int asm_options;
index 3d72d5dc48e1b8c48b1f7d91cdb771e2040c2628..bdc319994508e252c5800054c725580781da5486 100644 (file)
@@ -117,10 +117,24 @@ main(int argc, char *argv[])
     /* Set x86 as the architecture */
     cur_arch = &x86_arch;
 
+    /* Set dbg as the object format */
+    cur_objfmt = find_objfmt("dbg");
+    if (!cur_objfmt) {
+       ErrorNow(_("unrecognized output format `%s'"), "dbg");
+       return EXIT_FAILURE;
+    }
+
+    /* Set NASM as the parser */
+    cur_parser = find_parser("nasm");
+    if (!cur_parser) {
+       ErrorNow(_("unrecognized parser `%s'"), "nasm");
+       return EXIT_FAILURE;
+    }
+
     /* Get initial BITS setting from object format */
-    x86_mode_bits = dbg_objfmt.default_mode_bits;
+    x86_mode_bits = cur_objfmt->default_mode_bits;
 
-    sections = nasm_parser.do_parse(&nasm_parser, &dbg_objfmt, in);
+    sections = cur_parser->do_parse(cur_parser, in);
 
     if (OutputAllErrorWarning() > 0) {
        sections_delete(sections);
diff --git a/src/objfmt.c b/src/objfmt.c
new file mode 100644 (file)
index 0000000..4b7d8ad
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Generic functions for all object formats
+ *
+ *  Copyright (C) 2001  Peter Johnson
+ *
+ *  This file is part of YASM.
+ *
+ *  YASM is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  YASM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "util.h"
+/*@unused@*/ RCSID("$IdPath$");
+
+#include "globals.h"
+
+#include "objfmt.h"
+
+
+/* Available object formats */
+extern objfmt dbg_objfmt;
+
+/* NULL-terminated list of all available object formats.
+ * Someday change this if we dynamically load object formats at runtime.
+ * Could improve this a little by generating automatically at build-time.
+ */
+/*@-nullassign@*/
+objfmt *objfmts[] = {
+    &dbg_objfmt,
+    NULL
+};
+/*@=nullassign@*/
+
+objfmt *
+find_objfmt(const char *keyword)
+{
+    int i;
+
+    /* We're just doing a linear search, as there aren't many object formats */
+    for (i = 0; objfmts[i]; i++) {
+       if (strcasecmp(objfmts[i]->keyword, keyword) == 0)
+           /*@-unqualifiedtrans@*/
+           return objfmts[i];
+           /*@=unqualifiedtrans@*/
+    }
+
+    /* no match found */
+    return NULL;
+}
+
+void
+list_objfmts(void (*printfunc) (const char *name, const char *keyword))
+{
+    int i;
+
+    for (i = 0; objfmts[i]; i++)
+       printfunc(objfmts[i]->name, objfmts[i]->keyword);
+}
index ea82030697176befac52787bd6fa9e3c3434b23e..e484dbd87bb764a3f3c1f1a3ba937d2e936938e4 100644 (file)
@@ -46,13 +46,27 @@ struct objfmt {
      */
 /*    debugfmt *default_df;*/
 
-    /* Is the specified section name valid?
-     * Return is a boolean value.
+    /* Switch object file sections.  The first val of the valparams should
+     * be the section name.
      */
-    int (*is_valid_section) (const char *name);
+    /*@dependent@*/ /*@null@*/ section *
+       (*sections_switch)(sectionhead *headp, valparamhead *valparams,
+                          /*@null@*/ valparamhead *objext_valparams);
+
+    void (*section_data_delete)(/*@only@*/ void *data);
+    void (*section_data_print)(void *data);
 };
 
-/* Available object formats */
-extern objfmt dbg_objfmt;
+/* Generic functions for all object formats - implemented in src/objfmt.c */
+
+/* Finds an object format based on its keyword.  Returns NULL if no match was
+ * found.
+ */
+/*@null@*/ objfmt *find_objfmt(const char *keyword);
+
+/* Lists all available object formats.  Calls printfunc with the name and
+ * keyword of each available format.
+ */
+void list_objfmts(void (*printfunc) (const char *name, const char *keyword));
 
 #endif
index 41e2f2f0700ce06c5c2fd174d7185ecd74ebcf16..21a620fa230e163685025c67eb0852ea9bcef3ed 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#include "expr.h"
+#include "symrec.h"
+
+#include "section.h"
 #include "objfmt.h"
 
 
-static int
-dbg_objfmt_is_valid_section(const char *name)
+static /*@dependent@*/ /*@null@*/ section *
+dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
+                          /*@unused@*/ /*@null@*/
+                          valparamhead *objext_valparams)
+{
+    valparam *vp;
+    section *retval;
+
+#if 0
+    fprintf(stderr, "-dbg_objfmt_sections_switch():\n");
+    printf(" Val/Params:\n");
+    vps_foreach(vp, valparams) {
+       printf("  (%s,", vp->val?vp->val:"(nil)");
+       if (vp->param)
+           expr_print(vp->param);
+       else
+           printf("(nil)");
+       printf(")\n");
+    }
+    printf(" Obj Ext Val/Params:\n");
+    if (!objext_valparams)
+       printf("  (none)\n");
+    else
+       vps_foreach(vp, objext_valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+#endif
+    if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) {
+       retval = sections_switch_general(headp, vp->val, NULL, 0);
+       symrec_define_label(vp->val, retval, (bytecode *)NULL, 1);
+       return retval;
+    } else
+       return NULL;
+}
+
+static void
+dbg_objfmt_section_data_delete(/*@only@*/ void *data)
+{
+    xfree(data);
+}
+
+static void
+dbg_objfmt_section_data_print(/*@unused@*/ void *data)
 {
-    fprintf(stderr, "-dbg_objfmt_is_valid_section(\"%s\")\n", name);
-    return 1;
 }
 
 /* Define objfmt structure -- see objfmt.h for details */
@@ -38,5 +86,7 @@ objfmt dbg_objfmt = {
     "dbg",
     ".text",
     32,
-    dbg_objfmt_is_valid_section
+    dbg_objfmt_sections_switch,
+    dbg_objfmt_section_data_delete,
+    dbg_objfmt_section_data_print
 };
index 41e2f2f0700ce06c5c2fd174d7185ecd74ebcf16..21a620fa230e163685025c67eb0852ea9bcef3ed 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#include "expr.h"
+#include "symrec.h"
+
+#include "section.h"
 #include "objfmt.h"
 
 
-static int
-dbg_objfmt_is_valid_section(const char *name)
+static /*@dependent@*/ /*@null@*/ section *
+dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams,
+                          /*@unused@*/ /*@null@*/
+                          valparamhead *objext_valparams)
+{
+    valparam *vp;
+    section *retval;
+
+#if 0
+    fprintf(stderr, "-dbg_objfmt_sections_switch():\n");
+    printf(" Val/Params:\n");
+    vps_foreach(vp, valparams) {
+       printf("  (%s,", vp->val?vp->val:"(nil)");
+       if (vp->param)
+           expr_print(vp->param);
+       else
+           printf("(nil)");
+       printf(")\n");
+    }
+    printf(" Obj Ext Val/Params:\n");
+    if (!objext_valparams)
+       printf("  (none)\n");
+    else
+       vps_foreach(vp, objext_valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+#endif
+    if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) {
+       retval = sections_switch_general(headp, vp->val, NULL, 0);
+       symrec_define_label(vp->val, retval, (bytecode *)NULL, 1);
+       return retval;
+    } else
+       return NULL;
+}
+
+static void
+dbg_objfmt_section_data_delete(/*@only@*/ void *data)
+{
+    xfree(data);
+}
+
+static void
+dbg_objfmt_section_data_print(/*@unused@*/ void *data)
 {
-    fprintf(stderr, "-dbg_objfmt_is_valid_section(\"%s\")\n", name);
-    return 1;
 }
 
 /* Define objfmt structure -- see objfmt.h for details */
@@ -38,5 +86,7 @@ objfmt dbg_objfmt = {
     "dbg",
     ".text",
     32,
-    dbg_objfmt_is_valid_section
+    dbg_objfmt_sections_switch,
+    dbg_objfmt_section_data_delete,
+    dbg_objfmt_section_data_print
 };
index cde12bbbf119da8543e9ee7951b1c5e4b976b816..fa0858eab7fda5630521cdf56e9d4c7b1ef31b57 100644 (file)
@@ -28,6 +28,9 @@
 #include "parser.h"
 
 
+/* Available parsers */
+extern parser nasm_parser;
+
 /* NULL-terminated list of all available parsers.
  * Someday change this if we dynamically load parsers at runtime.
  * Could improve this a little by generating automatically at build-time.
index 822c9d4a880511b81f8f46331183e75181e2ce51..7365f1c37f27ee0d99c499d4a0bf705a6c673f96 100644 (file)
@@ -52,7 +52,7 @@ struct parser {
      * This function returns the starting section of a linked list of sections
      * (whatever was in the file).
      */
-    sectionhead *(*do_parse) (parser *p, objfmt *of, FILE *f);
+    sectionhead *(*do_parse) (parser *p, FILE *f);
 };
 
 /* Generic functions for all parsers - implemented in src/parser.c */
@@ -77,7 +77,4 @@ void parser_listpp(parser *p,
  */
 void list_parsers(void (*printfunc) (const char *name, const char *keyword));
 
-/* Available parsers */
-extern parser nasm_parser;
-
 #endif
index 47ddce63cca3f7354c6c3d50641bdb48804e5816..4380b0141f8eeeda00f919379af40a7376aef68f 100644 (file)
@@ -24,7 +24,7 @@ endif
 
 noinst_SCRIPTS = gen_instr.pl
 
-AM_YFLAGS = -d --name-prefix=nasm_parser_
+AM_YFLAGS = -v -d --name-prefix=nasm_parser_
 AM_LFLAGS = -Pnasm_parser_ -olex.yy.c
 
 INCLUDES = \
index 4de5d9f8ae491bb762c8f5969597a7821557e335..4317140e2a3ce6a5deaef014d93adabffda77cf7 100644 (file)
@@ -24,6 +24,7 @@
 RCSID("$IdPath$");
 
 #ifdef STDC_HEADERS
+# include <assert.h>
 # include <math.h>
 #endif
 
@@ -42,12 +43,12 @@ RCSID("$IdPath$");
 
 #include "arch.h"
 
-#define YYDEBUG 1
-
 void init_table(void);
 extern int nasm_parser_lex(void);
 void nasm_parser_error(const char *);
-static void nasm_parser_directive(const char *name, const char *val);
+static void nasm_parser_directive(const char *name,
+                                 valparamhead *valparams,
+                                 /*@null@*/ valparamhead *objext_valparams);
 
 extern objfmt *nasm_parser_objfmt;
 extern sectionhead nasm_parser_sections;
@@ -77,11 +78,13 @@ static bytecode *nasm_parser_temp_bc;
     datavalhead datahead;
     dataval *data;
     bytecode *bc;
+    valparamhead dir_valparams;
+    valparam *dir_valparam;
 }
 
 %token <intn> INTNUM
 %token <flt> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
+%token <str_val> DIRECTIVE_NAME STRING
 %token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_info> DECLARE_DATA
 %token <int_info> RESERVE_SPACE
@@ -113,12 +116,14 @@ static bytecode *nasm_parser_temp_bc;
 %type <ea> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr expr_no_string memexpr
+%type <exp> expr expr_no_string memexpr direxpr
 %type <sym> explabel
 %type <str_val> label_id
 %type <tgt_val> target
 %type <data> dataval
 %type <datahead> datavals
+%type <dir_valparams> directive_valparams
+%type <dir_valparam> directive_valparam
 
 %left '|'
 %left '^'
@@ -201,22 +206,40 @@ label_id: ID          {
 ;
 
 /* directives */
-directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']'        {
-       nasm_parser_directive($2, $3);
+directive: '[' DIRECTIVE_NAME directive_val ']'        {
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME DIRECTIVE_VAL error   {
-       Error(_("missing `%c'"), ']');
+    | '[' DIRECTIVE_NAME error ']'             {
+       Error(_("invalid arguments to [%s]"), $2);
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME error                 {
-       Error(_("missing argument to `%s'"), $2);
-       xfree($2);
+;
+
+    /* $<str_val>0 is the DIRECTIVE_NAME */
+    /* After : is (optional) object-format specific extension */
+directive_val: directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, NULL);
+    }
+    | directive_valparams ':' directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, &$3);
+    }
+;
+
+directive_valparams: directive_valparam                {
+       vps_initialize(&$$);
+       vps_append(&$$, $1);
+    }
+    | directive_valparams directive_valparam   {
+       vps_append(&$1, $2);
+       $$ = $1;
     }
 ;
 
+directive_valparam: ID         { vp_new($$, $1, NULL); }
+    | direxpr                  { vp_new($$, NULL, $1); }
+    | ID '=' direxpr           { vp_new($$, $1, $3); }
+;
+
 /* register groupings */
 fpureg: ST0
     | FPUREG_NOTST0
@@ -454,6 +477,26 @@ target: expr               {
 ;
 
 /* expression trees */
+
+/* expr w/o FLTNUM and unary + and -, for use in directives */
+direxpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | direxpr '|' direxpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | direxpr '^' direxpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    | direxpr '&' direxpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    | direxpr LEFT_OP direxpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | direxpr RIGHT_OP direxpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | direxpr '+' direxpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | direxpr '-' direxpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | direxpr '*' direxpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | direxpr '/' direxpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | direxpr SIGNDIV direxpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | direxpr '%' direxpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | direxpr SIGNMOD direxpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    /*| '!' expr               { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' direxpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' direxpr ')'          { $$ = $2; }
+;
+
 expr_no_string: INTNUM         { $$ = expr_new_ident(ExprInt($1)); }
     | FLTNUM                   { $$ = expr_new_ident(ExprFloat($1)); }
     | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
@@ -491,15 +534,31 @@ expr: expr_no_string
     }
 ;
 
-explabel: ID           { $$ = symrec_use($1); xfree($1); }
-    | SPECIAL_ID       { $$ = symrec_use($1); xfree($1); }
-    | LOCAL_ID         { $$ = symrec_use($1); xfree($1); }
+explabel: ID           {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | SPECIAL_ID       {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | LOCAL_ID         {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
     | '$'              {
        $$ = symrec_define_label("$", nasm_parser_cur_section,
                                 nasm_parser_prev_bc, 0);
     }
     | START_SECTION_ID {
-       $$ = symrec_use(section_get_name(nasm_parser_cur_section));
+       if (section_is_absolute(nasm_parser_cur_section)) {
+           Error(_("`$$' is not valid within an ABSOLUTE section"));
+           YYERROR;
+       } else {
+           const char *ss_name = section_get_name(nasm_parser_cur_section);
+           assert(ss_name != NULL);
+           $$ = symrec_use(ss_name);
+       }
     }
 ;
 
@@ -543,25 +602,66 @@ instr: instrbase
 /*@=usedef =nullassign =memtrans =usereleased =compdef =mustfree@*/
 
 static void
-nasm_parser_directive(const char *name, const char *val)
+nasm_parser_directive(const char *name, valparamhead *valparams,
+                     valparamhead *objext_valparams)
 {
+    valparam *vp;
+    const intnum *intn;
     long lval;
-    char *end;
 
+    assert(cur_objfmt != NULL);
     if (strcasecmp(name, "section") == 0) {
-       nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
-                                                 nasm_parser_objfmt, val);
+       section *new_section =
+           cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
+                                       objext_valparams);
+       if (new_section) {
+           nasm_parser_cur_section = new_section;
+           nasm_parser_prev_bc = (bytecode *)NULL;
+       } else
+           Error(_("invalid argument to [%s]"), "SECTION");
+    } else if (strcasecmp(name, "absolute") == 0) {
+       vp = vps_first(valparams);
+       nasm_parser_cur_section =
+           sections_switch_absolute(&nasm_parser_sections, vp->val ?
+               expr_new_ident(ExprSym(symrec_use(vp->val))) : vp->param);
        nasm_parser_prev_bc = (bytecode *)NULL;
-       symrec_define_label(val, nasm_parser_cur_section, (bytecode *)NULL, 1);
     } else if (strcasecmp(name, "bits") == 0) {
-       lval = strtol(val, &end, 10);
-       if (*val == '\0' || *end != '\0' || (lval != 16 && lval != 32))
-           Error(_("`%s' is not a valid argument to [BITS]"), val);
-       else
+       if ((vp = vps_first(valparams)) && !vp->val && vp->param != NULL &&
+           (intn = expr_get_intnum(&vp->param)) != NULL &&
+           (lval = intnum_get_int(intn)) && (lval == 16 || lval == 32))
            x86_mode_bits = (unsigned char)lval;
+       else
+           Error(_("invalid argument to [%s]"), "BITS");
     } else {
-       printf("Directive: Name=`%s' Value=`%s'\n", name, val);
+       Error(_("unrecognized directive [%s]"), name);
+#if 0
+       printf("Directive: Name=`%s'\n Val/Params:\n", name);
+       vps_foreach(vp, valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+       printf(" Obj Ext Val/Params:\n");
+       if (!objext_valparams)
+           printf("  (none)\n");
+       else
+           vps_foreach(vp, objext_valparams) {
+               printf("  (%s,", vp->val?vp->val:"(nil)");
+               if (vp->param)
+                   expr_print(vp->param);
+               else
+                   printf("(nil)");
+               printf(")\n");
+           }
+#endif
     }
+
+    vps_delete(valparams);
+    if (objext_valparams)
+       vps_delete(objext_valparams);
 }
 
 void
index 4de5d9f8ae491bb762c8f5969597a7821557e335..4317140e2a3ce6a5deaef014d93adabffda77cf7 100644 (file)
@@ -24,6 +24,7 @@
 RCSID("$IdPath$");
 
 #ifdef STDC_HEADERS
+# include <assert.h>
 # include <math.h>
 #endif
 
@@ -42,12 +43,12 @@ RCSID("$IdPath$");
 
 #include "arch.h"
 
-#define YYDEBUG 1
-
 void init_table(void);
 extern int nasm_parser_lex(void);
 void nasm_parser_error(const char *);
-static void nasm_parser_directive(const char *name, const char *val);
+static void nasm_parser_directive(const char *name,
+                                 valparamhead *valparams,
+                                 /*@null@*/ valparamhead *objext_valparams);
 
 extern objfmt *nasm_parser_objfmt;
 extern sectionhead nasm_parser_sections;
@@ -77,11 +78,13 @@ static bytecode *nasm_parser_temp_bc;
     datavalhead datahead;
     dataval *data;
     bytecode *bc;
+    valparamhead dir_valparams;
+    valparam *dir_valparam;
 }
 
 %token <intn> INTNUM
 %token <flt> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
+%token <str_val> DIRECTIVE_NAME STRING
 %token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_info> DECLARE_DATA
 %token <int_info> RESERVE_SPACE
@@ -113,12 +116,14 @@ static bytecode *nasm_parser_temp_bc;
 %type <ea> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr expr_no_string memexpr
+%type <exp> expr expr_no_string memexpr direxpr
 %type <sym> explabel
 %type <str_val> label_id
 %type <tgt_val> target
 %type <data> dataval
 %type <datahead> datavals
+%type <dir_valparams> directive_valparams
+%type <dir_valparam> directive_valparam
 
 %left '|'
 %left '^'
@@ -201,22 +206,40 @@ label_id: ID          {
 ;
 
 /* directives */
-directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']'        {
-       nasm_parser_directive($2, $3);
+directive: '[' DIRECTIVE_NAME directive_val ']'        {
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME DIRECTIVE_VAL error   {
-       Error(_("missing `%c'"), ']');
+    | '[' DIRECTIVE_NAME error ']'             {
+       Error(_("invalid arguments to [%s]"), $2);
        xfree($2);
-       xfree($3);
     }
-    | '[' DIRECTIVE_NAME error                 {
-       Error(_("missing argument to `%s'"), $2);
-       xfree($2);
+;
+
+    /* $<str_val>0 is the DIRECTIVE_NAME */
+    /* After : is (optional) object-format specific extension */
+directive_val: directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, NULL);
+    }
+    | directive_valparams ':' directive_valparams {
+       nasm_parser_directive($<str_val>0, &$1, &$3);
+    }
+;
+
+directive_valparams: directive_valparam                {
+       vps_initialize(&$$);
+       vps_append(&$$, $1);
+    }
+    | directive_valparams directive_valparam   {
+       vps_append(&$1, $2);
+       $$ = $1;
     }
 ;
 
+directive_valparam: ID         { vp_new($$, $1, NULL); }
+    | direxpr                  { vp_new($$, NULL, $1); }
+    | ID '=' direxpr           { vp_new($$, $1, $3); }
+;
+
 /* register groupings */
 fpureg: ST0
     | FPUREG_NOTST0
@@ -454,6 +477,26 @@ target: expr               {
 ;
 
 /* expression trees */
+
+/* expr w/o FLTNUM and unary + and -, for use in directives */
+direxpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | direxpr '|' direxpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | direxpr '^' direxpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    | direxpr '&' direxpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    | direxpr LEFT_OP direxpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | direxpr RIGHT_OP direxpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | direxpr '+' direxpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | direxpr '-' direxpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | direxpr '*' direxpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | direxpr '/' direxpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | direxpr SIGNDIV direxpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | direxpr '%' direxpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | direxpr SIGNMOD direxpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    /*| '!' expr               { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' direxpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' direxpr ')'          { $$ = $2; }
+;
+
 expr_no_string: INTNUM         { $$ = expr_new_ident(ExprInt($1)); }
     | FLTNUM                   { $$ = expr_new_ident(ExprFloat($1)); }
     | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
@@ -491,15 +534,31 @@ expr: expr_no_string
     }
 ;
 
-explabel: ID           { $$ = symrec_use($1); xfree($1); }
-    | SPECIAL_ID       { $$ = symrec_use($1); xfree($1); }
-    | LOCAL_ID         { $$ = symrec_use($1); xfree($1); }
+explabel: ID           {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | SPECIAL_ID       {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
+    | LOCAL_ID         {
+       $$ = symrec_use($1);
+       xfree($1);
+    }
     | '$'              {
        $$ = symrec_define_label("$", nasm_parser_cur_section,
                                 nasm_parser_prev_bc, 0);
     }
     | START_SECTION_ID {
-       $$ = symrec_use(section_get_name(nasm_parser_cur_section));
+       if (section_is_absolute(nasm_parser_cur_section)) {
+           Error(_("`$$' is not valid within an ABSOLUTE section"));
+           YYERROR;
+       } else {
+           const char *ss_name = section_get_name(nasm_parser_cur_section);
+           assert(ss_name != NULL);
+           $$ = symrec_use(ss_name);
+       }
     }
 ;
 
@@ -543,25 +602,66 @@ instr: instrbase
 /*@=usedef =nullassign =memtrans =usereleased =compdef =mustfree@*/
 
 static void
-nasm_parser_directive(const char *name, const char *val)
+nasm_parser_directive(const char *name, valparamhead *valparams,
+                     valparamhead *objext_valparams)
 {
+    valparam *vp;
+    const intnum *intn;
     long lval;
-    char *end;
 
+    assert(cur_objfmt != NULL);
     if (strcasecmp(name, "section") == 0) {
-       nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
-                                                 nasm_parser_objfmt, val);
+       section *new_section =
+           cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
+                                       objext_valparams);
+       if (new_section) {
+           nasm_parser_cur_section = new_section;
+           nasm_parser_prev_bc = (bytecode *)NULL;
+       } else
+           Error(_("invalid argument to [%s]"), "SECTION");
+    } else if (strcasecmp(name, "absolute") == 0) {
+       vp = vps_first(valparams);
+       nasm_parser_cur_section =
+           sections_switch_absolute(&nasm_parser_sections, vp->val ?
+               expr_new_ident(ExprSym(symrec_use(vp->val))) : vp->param);
        nasm_parser_prev_bc = (bytecode *)NULL;
-       symrec_define_label(val, nasm_parser_cur_section, (bytecode *)NULL, 1);
     } else if (strcasecmp(name, "bits") == 0) {
-       lval = strtol(val, &end, 10);
-       if (*val == '\0' || *end != '\0' || (lval != 16 && lval != 32))
-           Error(_("`%s' is not a valid argument to [BITS]"), val);
-       else
+       if ((vp = vps_first(valparams)) && !vp->val && vp->param != NULL &&
+           (intn = expr_get_intnum(&vp->param)) != NULL &&
+           (lval = intnum_get_int(intn)) && (lval == 16 || lval == 32))
            x86_mode_bits = (unsigned char)lval;
+       else
+           Error(_("invalid argument to [%s]"), "BITS");
     } else {
-       printf("Directive: Name=`%s' Value=`%s'\n", name, val);
+       Error(_("unrecognized directive [%s]"), name);
+#if 0
+       printf("Directive: Name=`%s'\n Val/Params:\n", name);
+       vps_foreach(vp, valparams) {
+           printf("  (%s,", vp->val?vp->val:"(nil)");
+           if (vp->param)
+               expr_print(vp->param);
+           else
+               printf("(nil)");
+           printf(")\n");
+       }
+       printf(" Obj Ext Val/Params:\n");
+       if (!objext_valparams)
+           printf("  (none)\n");
+       else
+           vps_foreach(vp, objext_valparams) {
+               printf("  (%s,", vp->val?vp->val:"(nil)");
+               if (vp->param)
+                   expr_print(vp->param);
+               else
+                   printf("(nil)");
+               printf(")\n");
+           }
+#endif
     }
+
+    vps_delete(valparams);
+    if (objext_valparams)
+       vps_delete(objext_valparams);
 }
 
 void
index 66779fcaed0b1a9070944a96fc96c9971680fdbc..0b896f94a74324db2830a39e87e757549cea8a38 100644 (file)
@@ -37,24 +37,21 @@ extern int nasm_parser_parse(void);
 
 size_t (*nasm_parser_yyinput) (char *buf, size_t max_size);
 
-objfmt *nasm_parser_objfmt;
 sectionhead nasm_parser_sections;
 /*@dependent@*/ section *nasm_parser_cur_section;
 
 extern /*@only@*/ char *nasm_parser_locallabel_base;
 
 static /*@dependent@*/ sectionhead *
-nasm_parser_do_parse(parser *p, objfmt *of, FILE *f)
+nasm_parser_do_parse(parser *p, FILE *f)
     /*@globals killed nasm_parser_locallabel_base @*/
 {
-    p->current_pp->initialize(of, f);
+    p->current_pp->initialize(f);
     nasm_parser_in = f;
     nasm_parser_yyinput = p->current_pp->input;
 
-    nasm_parser_objfmt = of;
-
     /* Initialize section list */
-    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections, of);
+    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections);
 
     /* yacc debugging, needs YYDEBUG set in bison.y.in to work */
     /* nasm_parser_debug = 1; */
index 66779fcaed0b1a9070944a96fc96c9971680fdbc..0b896f94a74324db2830a39e87e757549cea8a38 100644 (file)
@@ -37,24 +37,21 @@ extern int nasm_parser_parse(void);
 
 size_t (*nasm_parser_yyinput) (char *buf, size_t max_size);
 
-objfmt *nasm_parser_objfmt;
 sectionhead nasm_parser_sections;
 /*@dependent@*/ section *nasm_parser_cur_section;
 
 extern /*@only@*/ char *nasm_parser_locallabel_base;
 
 static /*@dependent@*/ sectionhead *
-nasm_parser_do_parse(parser *p, objfmt *of, FILE *f)
+nasm_parser_do_parse(parser *p, FILE *f)
     /*@globals killed nasm_parser_locallabel_base @*/
 {
-    p->current_pp->initialize(of, f);
+    p->current_pp->initialize(f);
     nasm_parser_in = f;
     nasm_parser_yyinput = p->current_pp->input;
 
-    nasm_parser_objfmt = of;
-
     /* Initialize section list */
-    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections, of);
+    nasm_parser_cur_section = sections_initialize(&nasm_parser_sections);
 
     /* yacc debugging, needs YYDEBUG set in bison.y.in to work */
     /* nasm_parser_debug = 1; */
index 1fd8303efa7ff9def1663e05e8d3731aceb80d30..a24da44ebb21f80c1541400b3325adf358baf90b 100644 (file)
@@ -68,7 +68,8 @@ int line_number;
 %option nounput
 %option case-insensitive
 
-%x DIRECTIVE DIRECTIVE2
+%x DIRECTIVE
+%s DIRECTIVE2
 
 DIGIT    [0-9]
 BINDIGIT [01]
@@ -158,26 +159,21 @@ WS       [ \t\r]
 <DIRECTIVE2>"]"            { BEGIN INITIAL; return ']'; }
 <DIRECTIVE>\n      { BEGIN INITIAL; return '\n'; }
 <DIRECTIVE2>\n     { BEGIN INITIAL; return '\n'; }
-<DIRECTIVE>{WS}+    ;
-<DIRECTIVE2>{WS}+   ;
 
 <DIRECTIVE>[a-z]+   {
     BEGIN DIRECTIVE2;
     yylval.str_val = xstrdup(yytext);
     return DIRECTIVE_NAME;
-}
-    /* everything printable except for ' ', '[' and ']'. */
-<DIRECTIVE2>[!-@a-z\\^-`{|}~]+ {
-    yylval.str_val = xstrdup(yytext);
-    return DIRECTIVE_VAL;
 }
 <DIRECTIVE>. {
     Warning(_("ignoring unrecognized character `%s'"),
            conv_unprint(yytext[0]));
 }
-<DIRECTIVE2>. {
-    Warning(_("ignoring unrecognized character `%s'"),
-           conv_unprint(yytext[0]));
+
+    /* override local labels in directive state */
+<DIRECTIVE2>\.[a-z0-9_$#@~.?]* {
+    yylval.str_val = xstrdup(yytext);
+    return ID;
 }
 
     /* size specifiers */
@@ -288,7 +284,7 @@ gs  { yylval.int_info = 5; return REG_GS; }
 "//"                   { return SIGNDIV; }
 "%%"                   { return SIGNMOD; }
 "$$"                   { return START_SECTION_ID; }
-[-+|^&*/%~$():[\],]    { return yytext[0]; }
+[-+|^&*/%~$():[\]=,]   { return yytext[0]; }
 
     /* special non-local ..@label and labels like ..start */
 \.\.[a-z0-9_$#@~.?]+ {
index f585e7bc60c1162056e9ce04baf74f1e62222b9c..68d4b2d4295371160d2535d8b0253cad75c4f7b2 100644 (file)
@@ -39,7 +39,7 @@ struct preproc {
      * not the filename (which is in a global variable and is not
      * preprocessor-specific).
      */
-    void (*initialize) (objfmt *of, FILE *f);
+    void (*initialize) (FILE *f);
 
     /* Gets more preprocessed source code (up to max_size bytes) into buf.
      * Note that more than a single line may be returned in buf. */
index ca9fb2647cea4055c3bb755fb339301be814cec9..419f7708d960e88e977e69267f2c01d3ca3486b8 100644 (file)
@@ -33,7 +33,7 @@ static FILE *in;
 int isatty(int);
 
 static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
 {
     in = f;
     /*@-unrecog@*/
index ca9fb2647cea4055c3bb755fb339301be814cec9..419f7708d960e88e977e69267f2c01d3ca3486b8 100644 (file)
@@ -33,7 +33,7 @@ static FILE *in;
 int isatty(int);
 
 static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
 {
     in = f;
     /*@-unrecog@*/
index 4900479b49ce98de7e76700bee586c47519b6bc0..eb76a74d4fb210ba78c32d7bc5ad23df0522a55c 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
 #include "globals.h"
 #include "errwarn.h"
 #include "expr.h"
@@ -36,19 +40,27 @@ struct section {
 
     enum { SECTION_GENERAL, SECTION_ABSOLUTE } type;
 
-    char *name;                        /* strdup()'ed name (given by user) */
-
     union {
        /* SECTION_GENERAL data */
+       struct general {
+           /*@owned@*/ char *name;     /* strdup()'ed name (given by user) */
+
+           /* object-format-specific data */ 
+           /*@null@*/ /*@owned@*/ void *of_data;
+       } general;
+
        /* SECTION_ABSOLUTE data */
-       unsigned long start;
+       /*@owned@*/ expr *start;
     } data;
 
+
+    int res_only;              /* allow only resb family of bytecodes? */
+
     bytecodehead bc;           /* the bytecodes for the section's contents */
 };
 
 section *
-sections_initialize(sectionhead *headp, objfmt *of)
+sections_initialize(sectionhead *headp)
 {
     section *s;
 
@@ -61,56 +73,80 @@ sections_initialize(sectionhead *headp, objfmt *of)
 
     /* Initialize default section */
     s->type = SECTION_GENERAL;
-    s->name = xstrdup(of->default_section_name);
+    assert(cur_objfmt != NULL);
+    s->data.general.name = xstrdup(cur_objfmt->default_section_name);
+    s->data.general.of_data = NULL;
     bytecodes_initialize(&s->bc);
 
-    s->data.start = 0;
+    s->res_only = 0;
 
     return s;
 }
 
 /*@-onlytrans@*/
 section *
-sections_switch(sectionhead *headp, objfmt *of, const char *name)
+sections_switch_general(sectionhead *headp, const char *name, void *of_data,
+                       int res_only)
 {
-    section *s, *sp;
+    section *s;
 
     /* Search through current sections to see if we already have one with
      * that name.
      */
-    s = (section *)NULL;
-    STAILQ_FOREACH(sp, headp, link) {
-       if (strcmp(sp->name, name) == 0)
-           s = sp;
+    STAILQ_FOREACH(s, headp, link) {
+       if (s->type == SECTION_GENERAL &&
+           strcmp(s->data.general.name, name) == 0) {
+           if (of_data) {
+               Warning(_("segment attributes specified on redeclaration of segment: ignoring"));
+               assert(cur_objfmt != NULL);
+               cur_objfmt->section_data_delete(of_data);
+           }
+           return s;
+       }
     }
 
-    if (s)
-       return s;
-
     /* No: we have to allocate and create a new one. */
 
-    /* But first check with objfmt to see if the name is valid.
-     * If it isn't, error and just return the default (first) section.
-     */
-    if (!of->is_valid_section(name)) {
-       Error(_("Invalid section name: %s"), name);
-       return STAILQ_FIRST(headp);
-    }
-
     /* Okay, the name is valid; now allocate and initialize */
     s = xcalloc(1, sizeof(section));
     STAILQ_INSERT_TAIL(headp, s, link);
 
     s->type = SECTION_GENERAL;
-    s->name = xstrdup(name);
+    s->data.general.name = xstrdup(name);
+    s->data.general.of_data = of_data;
+    bytecodes_initialize(&s->bc);
+
+    s->res_only = res_only;
+
+    return s;
+}
+/*@=onlytrans@*/
+
+/*@-onlytrans@*/
+section *
+sections_switch_absolute(sectionhead *headp, expr *start)
+{
+    section *s;
+
+    s = xcalloc(1, sizeof(section));
+    STAILQ_INSERT_TAIL(headp, s, link);
+
+    s->type = SECTION_ABSOLUTE;
+    s->data.start = start;
     bytecodes_initialize(&s->bc);
 
-    s->data.start = 0;
+    s->res_only = 1;
 
     return s;
 }
 /*@=onlytrans@*/
 
+int
+section_is_absolute(section *sect)
+{
+    return (sect->type == SECTION_ABSOLUTE);
+}
+
 void
 sections_delete(sectionhead *headp)
 {
@@ -130,8 +166,10 @@ sections_print(const sectionhead *headp)
 {
     section *cur;
     
-    STAILQ_FOREACH(cur, headp, link)
+    STAILQ_FOREACH(cur, headp, link) {
+       printf("***SECTION***\n");
        section_print(cur);
+    }
 }
 
 void
@@ -152,7 +190,17 @@ section_get_bytecodes(section *sect)
 const char *
 section_get_name(const section *sect)
 {
-    return sect->name;
+    if (sect->type == SECTION_GENERAL)
+       return sect->data.general.name;
+    return NULL;
+}
+
+const expr *
+section_get_start(const section *sect)
+{
+    if (sect->type == SECTION_ABSOLUTE)
+       return sect->data.start;
+    return NULL;
 }
 
 void
@@ -161,7 +209,17 @@ section_delete(section *sect)
     if (!sect)
        return;
 
-    xfree(sect->name);
+    switch (sect->type) {
+       case SECTION_GENERAL:
+           xfree(sect->data.general.name);
+           assert(cur_objfmt != NULL);
+           if (sect->data.general.of_data)
+               cur_objfmt->section_data_delete(sect->data.general.of_data);
+           break;
+       case SECTION_ABSOLUTE:
+           expr_delete(sect->data.start);
+           break;
+    }
     bcs_delete(&sect->bc);
     xfree(sect);
 }
@@ -169,15 +227,21 @@ section_delete(section *sect)
 void
 section_print(const section *sect)
 {
-    printf("***SECTION %s***\n", sect->name);
     printf(" type=");
     switch (sect->type) {
        case SECTION_GENERAL:
-           printf("general\n");
+           printf("general\n name=%s\n objfmt data:\n",
+                  sect->data.general.name);
+           assert(cur_objfmt != NULL);
+           if (sect->data.general.of_data)
+               cur_objfmt->section_data_print(sect->data.general.of_data);
+           else
+               printf("  (none)\n");
            break;
        case SECTION_ABSOLUTE:
-           printf("absolute\n");
-           printf("start=%lu\n", sect->data.start);
+           printf("absolute\n start=");
+           expr_print(sect->data.start);
+           printf("\n");
            break;
     }
 
index 05e9c091164a590c934efb2101e7c2bfb68a681c..8c8da8eb4cb65d4086061f16d9f80e15bf4fcb3f 100644 (file)
 
 struct objfmt;
 
-/*@dependent@*/ section *sections_initialize(sectionhead *headp,
-                                            struct objfmt *of);
+/*@dependent@*/ section *sections_initialize(sectionhead *headp);
 
-/*@dependent@*/ section *sections_switch(sectionhead *headp, struct objfmt *of,
-                                        const char *name);
+/*@dependent@*/ section *sections_switch_general(sectionhead *headp,
+                                                const char *name,
+                                                /*@null@*/ /*@only@*/
+                                                void *of_data, int res_only);
+
+/*@dependent@*/ section *sections_switch_absolute(sectionhead *headp,
+                                                 /*@keep@*/ expr *start);
+
+int section_is_absolute(section *sect);
 
 void sections_delete(sectionhead *headp);
 
@@ -38,7 +44,8 @@ void sections_parser_finalize(sectionhead *headp);
 
 /*@dependent@*/ bytecodehead *section_get_bytecodes(section *sect);
 
-/*@observer@*/ const char *section_get_name(const section *sect);
+/*@observer@*/ /*@null@*/ const char *section_get_name(const section *sect);
+/*@observer@*/ /*@null@*/ const expr *section_get_start(const section *sect);
 
 void section_delete(/*@only@*/ section *sect);
 
index b1871689034af0fa1f0427d6ef632c45244973f9..041d28fe92cec9ba4b79f62f40fbcc4516296c95 100644 (file)
 #include "util.h"
 /*@unused@*/ RCSID("$IdPath$");
 
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
 #include "ternary.h"
 
 #include "globals.h"
@@ -291,9 +295,11 @@ symrec_print(const symrec *sym)
            printf("\n");
            break;
        case SYM_LABEL:
-           printf("_Label_\n");
-           printf("Section=`%s'\n", sym->value.label.sect?
-                  section_get_name(sym->value.label.sect):"(nil)");
+           printf("_Label_\nSection:");
+           if (sym->value.label.sect)
+               section_print(sym->value.label.sect);
+           else
+               printf(" (none)\n");
            if (!sym->value.label.bc)
                printf("[First bytecode]\n");
            else {
index 36e4bb1d0d521b63ddc446418453f7a4cb0f566a..b7e4b4894228e2367588cf0a3b0aad2447da4e64 100644 (file)
@@ -21,6 +21,7 @@ noinst_PROGRAMS =
 endif
 
 LDADD = \
+       $(top_builddir)/src/libyasm.a                           \
        $(top_builddir)/check/libcheck.a                        \
        $(top_builddir)/src/parsers/nasm/libparser.a            \
        $(top_builddir)/src/preprocs/raw/libpreproc.a           \