]> granicus.if.org Git - yasm/commitdiff
Allow directives to have no parameters in the parser, and check for it at
authorPeter Johnson <peter@tortall.net>
Wed, 7 Feb 2007 08:29:41 +0000 (08:29 -0000)
committerPeter Johnson <peter@tortall.net>
Wed, 7 Feb 2007 08:29:41 +0000 (08:29 -0000)
a lower level.

To reduce code duplication, refactor several of the large if/else structures
into multiple functions with a lookup table.

Add support for registers to be used in directive expressions.

Allow directives to have underscores and numbers (still cannot start with
numbers).

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

15 files changed:
libyasm/arch.h
libyasm/dbgfmt.h
libyasm/objfmt.h
modules/arch/lc3b/lc3barch.c
modules/arch/x86/x86arch.c
modules/dbgfmts/dwarf2/dwarf2-line.c
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/coff/coff-objfmt.c
modules/objfmts/dbg/dbg-objfmt.c
modules/objfmts/elf/elf-objfmt.c
modules/objfmts/macho/macho-objfmt.c
modules/objfmts/rdf/rdf-objfmt.c
modules/objfmts/xdf/xdf-objfmt.c
modules/parsers/nasm/nasm-parse.c
modules/parsers/nasm/nasm-token.re

index 9d1ffba315c4233fa7befc632984aef37a7fc2d5..2355571995c56c59064721e3d569b4f43f39e3d2 100644 (file)
@@ -156,7 +156,7 @@ typedef struct yasm_arch_module {
      * Call yasm_arch_parse_directive() instead of calling this function.
      */
     int (*parse_directive) (yasm_arch *arch, const char *name,
-                           yasm_valparamhead *valparams,
+                           /*@null@*/ yasm_valparamhead *valparams,
                            /*@null@*/ yasm_valparamhead *objext_valparams,
                            yasm_object *object, unsigned long line);
 
@@ -407,7 +407,7 @@ yasm_arch_regtmod yasm_arch_parse_check_regtmod
  *        recognized, even if it wasn't valid.
  */
 int yasm_arch_parse_directive(yasm_arch *arch, const char *name,
-                             yasm_valparamhead *valparams,
+                             /*@null@*/ yasm_valparamhead *valparams,
                              /*@null@*/ yasm_valparamhead *objext_valparams,
                              yasm_object *object, unsigned long line);
 
index 8f767f7c943e6088ff4c11b10a41f89b97c771f5..cae3568d67bf506d8593b66319c4a3dd78b3eb0f 100644 (file)
@@ -72,7 +72,8 @@ typedef struct yasm_dbgfmt_module {
      * Call yasm_dbgfmt_directive() instead of calling this function.
      */
     int (*directive) (yasm_dbgfmt *dbgfmt, const char *name,
-                     yasm_section *sect, yasm_valparamhead *valparams,
+                     yasm_section *sect,
+                     /*@null@*/ yasm_valparamhead *valparams,
                      unsigned long line);
 
     /** Module-level implementation of yasm_dbgfmt_generate().
@@ -115,7 +116,8 @@ void yasm_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt);
  *            recognized even if it wasn't valid.
  */
 int yasm_dbgfmt_directive(yasm_dbgfmt *dbgfmt, const char *name,
-                         yasm_section *sect, yasm_valparamhead *valparams,
+                         yasm_section *sect,
+                         /*@null@*/ yasm_valparamhead *valparams,
                          unsigned long line);
 
 /** Generate debugging information bytecodes.
index 4f63c1ccdea5c2a8326ebede6fc3ec9b0e11e8ff..129803dc42c5a9a5f3fa80bbda3acada5a778c51 100644 (file)
@@ -133,7 +133,7 @@ typedef struct yasm_objfmt_module {
      * Call yasm_objfmt_directive() instead of calling this function.
      */
     int (*directive) (yasm_objfmt *objfmt, const char *name,
-                     yasm_valparamhead *valparams,
+                     /*@null@*/ yasm_valparamhead *valparams,
                      /*@null@*/ yasm_valparamhead *objext_valparams,
                      unsigned long line);
 } yasm_objfmt_module;
@@ -233,7 +233,7 @@ yasm_symrec *yasm_objfmt_common_declare
  *         recognized, even if it wasn't valid.
  */
 int yasm_objfmt_directive(yasm_objfmt *objfmt, const char *name,
-                         yasm_valparamhead *valparams,
+                         /*@null@*/ yasm_valparamhead *valparams,
                          /*@null@*/ yasm_valparamhead *objext_valparams,
                          unsigned long line);
 
index cefbeb19deafafc88bb67fa31e7935f62eba06e6..bbf28956e974c071820a9a714c74a655bb295fb2 100644 (file)
@@ -86,7 +86,7 @@ lc3b_set_var(yasm_arch *arch, const char *var, unsigned long val)
 static int
 lc3b_parse_directive(/*@unused@*/ yasm_arch *arch,
                     /*@unused@*/ const char *name,
-                    /*@unused@*/ yasm_valparamhead *valparams,
+                    /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
                     /*@unused@*/ /*@null@*/
                     yasm_valparamhead *objext_valparams,
                     /*@unused@*/ yasm_object *object,
index 731f102ee200ce783ff9d8f46634762d93e0d34d..c5b6ee04577bc7b787d24fa570c7a46590d1756f 100644 (file)
@@ -120,7 +120,7 @@ x86_set_var(yasm_arch *arch, const char *var, unsigned long val)
 
 static int
 x86_parse_directive(yasm_arch *arch, const char *name,
-                   yasm_valparamhead *valparams,
+                   /*@null@*/ yasm_valparamhead *valparams,
                    /*@unused@*/ /*@null@*/
                    yasm_valparamhead *objext_valparams,
                    /*@unused@*/ yasm_object *object,
@@ -132,7 +132,10 @@ x86_parse_directive(yasm_arch *arch, const char *name,
     long lval;
 
     if (yasm__strcasecmp(name, "bits") == 0) {
-       if ((vp = yasm_vps_first(valparams)) && !vp->val &&
+       if (!valparams)
+           yasm_error_set(YASM_ERROR_VALUE, N_("[%s] requires an argument"),
+                          "BITS");
+       else if ((vp = yasm_vps_first(valparams)) && !vp->val &&
            vp->param != NULL &&
            (intn = yasm_expr_get_intnum(&vp->param, 0)) != NULL &&
            (lval = yasm_intnum_get_int(intn)) &&
index 44d117a8297c598266a6288e6e52b3d11de5c396..a95ec574689bfa7e0756dd3e220aa30ad07d7166 100644 (file)
@@ -825,14 +825,14 @@ yasm_dwarf2__line_directive(yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2,
                            const char *name, yasm_section *sect,
                            yasm_valparamhead *valparams, unsigned long line)
 {
+    yasm_valparam *vp;
     if (yasm__strcasecmp(name, "loc") == 0) {
        /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
        dwarf2_section_data *dsd;
        dwarf2_loc *loc = yasm_xmalloc(sizeof(dwarf2_loc));
 
        /* File number (required) */
-       yasm_valparam *vp = yasm_vps_first(valparams);
-       if (!vp || !vp->param) {
+       if (!valparams || !(vp = yasm_vps_first(valparams)) || !vp->param) {
            yasm_error_set(YASM_ERROR_SYNTAX, N_("file number required"));
            yasm_xfree(loc);
            return 0;
@@ -968,8 +968,13 @@ yasm_dwarf2__line_directive(yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2,
        /*@dependent@*/ /*@null@*/ const yasm_intnum *file_intn;
        size_t filenum;
 
-       yasm_valparam *vp = yasm_vps_first(valparams);
+       if (!valparams) {
+           yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
+                          "FILE");
+           return 0;
+       }
 
+       vp = yasm_vps_first(valparams);
        if (vp->val) {
            /* Just a bare filename */
            yasm_object_set_source_fn(dbgfmt_dwarf2->object, vp->val);
index c010bfa88562e5844cc9f9f98ae63cfacc48074e..b33c8bc2dc90b4e9c0378653e8439942159ec03f 100644 (file)
@@ -529,7 +529,7 @@ bin_objfmt_common_declare(yasm_objfmt *objfmt, const char *name,
 
 static int
 bin_objfmt_directive(yasm_objfmt *objfmt, const char *name,
-                    yasm_valparamhead *valparams,
+                    /*@null@*/ yasm_valparamhead *valparams,
                     /*@unused@*/ /*@null@*/
                     yasm_valparamhead *objext_valparams, unsigned long line)
 {
@@ -540,6 +540,12 @@ bin_objfmt_directive(yasm_objfmt *objfmt, const char *name,
     if (yasm__strcasecmp(name, "org") == 0) {
        /*@null@*/ yasm_expr *start = NULL;
 
+       if (!valparams) {
+           yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
+                          "ORG");
+           return 0;
+       }
+
        /* ORG takes just a simple integer as param */
        vp = yasm_vps_first(valparams);
        if (vp->val)
index ab08bf95ec568f4a0207d145ca0fb9589b33ecf8..cc9ecc681537233a8590dce7b3c6fd40f059449d 100644 (file)
@@ -1689,7 +1689,7 @@ coff_symrec_data_print(void *data, FILE *f, int indent_level)
 static int
 coff_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt,
                      /*@unused@*/ const char *name,
-                     /*@unused@*/ yasm_valparamhead *valparams,
+                     /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
                      /*@unused@*/ /*@null@*/
                      yasm_valparamhead *objext_valparams,
                      /*@unused@*/ unsigned long line)
index 3562cbe1232df67ab587ab23fb5667dd3f24cb72..33fbdb9e01844fb7e9f2363a77c9150373d86303 100644 (file)
@@ -211,7 +211,7 @@ dbg_objfmt_common_declare(yasm_objfmt *objfmt, const char *name,
 
 static int
 dbg_objfmt_directive(yasm_objfmt *objfmt, const char *name,
-                    yasm_valparamhead *valparams,
+                    /*@null@*/ yasm_valparamhead *valparams,
                     /*@null@*/ yasm_valparamhead *objext_valparams,
                     unsigned long line)
 {
index d570a9d6af03ef5277c3c6dc5dc59ddc19853600..9473f022e99c4c0d417dc0cbac2012f41fba4942 100644 (file)
@@ -1101,114 +1101,143 @@ elf_objfmt_common_declare(yasm_objfmt *objfmt, const char *name,
     return sym;
 }
 
-static int
-elf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
-                    yasm_valparamhead *valparams,
-                    /*@unused@*/ /*@null@*/
-                    yasm_valparamhead *objext_valparams,
-                    unsigned long line)
+static void
+dir_type(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
 {
-    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
-    yasm_symrec *sym;
-    yasm_valparam *vp = yasm_vps_first(valparams);
     char *symname = vp->val;
-    elf_symtab_entry *entry;
+    /* Get symbol elf data */
+    yasm_symrec *sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
+    elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
 
-    if (!symname) {
-       yasm_error_set(YASM_ERROR_SYNTAX, N_("Symbol name not specified"));
-       return 0;
+    /* Create entry if necessary */
+    if (!entry) {
+       entry = elf_symtab_entry_create(
+           elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+       yasm_symrec_add_data(sym, &elf_symrec_data, entry);
     }
 
-    if (yasm__strcasecmp(name, "type") == 0) {
-       /* Get symbol elf data */
-       sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
-       entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+    /* Pull new type from val */
+    vp = yasm_vps_next(vp);
+    if (vp->val) {
+       if (yasm__strcasecmp(vp->val, "function") == 0)
+           elf_sym_set_type(entry, STT_FUNC);
+       else if (yasm__strcasecmp(vp->val, "object") == 0)
+           elf_sym_set_type(entry, STT_OBJECT);
+       else
+           yasm_warn_set(YASM_WARN_GENERAL,
+                         N_("unrecognized symbol type `%s'"), vp->val);
+    } else
+       yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
+}
 
-       /* Create entry if necessary */
-       if (!entry) {
-           entry = elf_symtab_entry_create(
-               elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
-           yasm_symrec_add_data(sym, &elf_symrec_data, entry);
-       }
+static void
+dir_size(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
+{
+    char *symname = vp->val;
+    /* Get symbol elf data */
+    yasm_symrec *sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
+    elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
 
-       /* Pull new type from val */
-       vp = yasm_vps_next(vp);
-       if (vp->val) {
-           if (yasm__strcasecmp(vp->val, "function") == 0)
-               elf_sym_set_type(entry, STT_FUNC);
-           else if (yasm__strcasecmp(vp->val, "object") == 0)
-               elf_sym_set_type(entry, STT_OBJECT);
-           else
-               yasm_warn_set(YASM_WARN_GENERAL,
-                             N_("unrecognized symbol type `%s'"), vp->val);
-       } else
-           yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
-    } else if (yasm__strcasecmp(name, "size") == 0) {
-       /* Get symbol elf data */
-       sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
-       entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+    /* Create entry if necessary */
+    if (!entry) {
+       entry = elf_symtab_entry_create(
+           elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+       yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+    }
 
-       /* Create entry if necessary */
-       if (!entry) {
-           entry = elf_symtab_entry_create(
-               elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
-           yasm_symrec_add_data(sym, &elf_symrec_data, entry);
-       }
+    /* Pull new size from either param (expr) or val */
+    vp = yasm_vps_next(vp);
+    if (vp->param) {
+       elf_sym_set_size(entry, vp->param);
+       vp->param = NULL;
+    } else if (vp->val)
+       elf_sym_set_size(entry, yasm_expr_create_ident(yasm_expr_sym(
+           yasm_symtab_use(objfmt_elf->symtab, vp->val, line)), line));
+    else
+       yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
+}
 
-       /* Pull new size from either param (expr) or val */
-       vp = yasm_vps_next(vp);
-       if (vp->param) {
-           elf_sym_set_size(entry, vp->param);
-           vp->param = NULL;
-       } else if (vp->val)
-           elf_sym_set_size(entry, yasm_expr_create_ident(yasm_expr_sym(
-               yasm_symtab_use(objfmt_elf->symtab, vp->val, line)), line));
-       else
-           yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
-    } else if (yasm__strcasecmp(name, "weak") == 0) {
-       sym = yasm_symtab_declare(objfmt_elf->symtab, symname, YASM_SYM_GLOBAL,
-                                 line);
-       elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK,
-                                0, STV_DEFAULT, NULL, NULL);
-    } else if (yasm__strcasecmp(name, "ident") == 0) {
-       yasm_valparamhead sect_vps;
-       yasm_datavalhead dvs;
-       yasm_section *comment;
-       yasm_valparam *vp2;
-
-       /* Put ident data into .comment section */
-       yasm_vps_initialize(&sect_vps);
-       vp2 = yasm_vp_create(yasm__xstrdup(".comment"), NULL);
-       yasm_vps_append(&sect_vps, vp2);
-       comment = elf_objfmt_section_switch(objfmt, &sect_vps, NULL, line);
-       yasm_vps_delete(&sect_vps);
-
-       /* To match GAS output, if the comment section is empty, put an
-        * initial 0 byte in the section.
-        */
-       if (yasm_section_bcs_first(comment)
-           == yasm_section_bcs_last(comment)) {
-           yasm_dvs_initialize(&dvs);
-           yasm_dvs_append(&dvs, yasm_dv_create_expr(
-               yasm_expr_create_ident(
-                   yasm_expr_int(yasm_intnum_create_uint(0)), line)));
-           yasm_section_bcs_append(comment,
-               yasm_bc_create_data(&dvs, 1, 0, objfmt_elf->arch, line));
-       }
+static void
+dir_weak(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
+{
+    char *symname = vp->val;
+    yasm_symrec *sym = yasm_symtab_declare(objfmt_elf->symtab, symname,
+                                          YASM_SYM_GLOBAL, line);
+    elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0,
+                            STV_DEFAULT, NULL, NULL);
+}
 
+static void
+dir_ident(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
+{
+    char *symname = vp->val;
+    yasm_valparamhead sect_vps;
+    yasm_datavalhead dvs;
+    yasm_section *comment;
+    yasm_valparam *vp2;
+
+    /* Put ident data into .comment section */
+    yasm_vps_initialize(&sect_vps);
+    vp2 = yasm_vp_create(yasm__xstrdup(".comment"), NULL);
+    yasm_vps_append(&sect_vps, vp2);
+    comment = elf_objfmt_section_switch((yasm_objfmt *)objfmt_elf, &sect_vps,
+                                       NULL, line);
+    yasm_vps_delete(&sect_vps);
+
+    /* To match GAS output, if the comment section is empty, put an
+     * initial 0 byte in the section.
+     */
+    if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
        yasm_dvs_initialize(&dvs);
-       do {
-           yasm_dvs_append(&dvs, yasm_dv_create_string(vp->val,
-                                                       strlen(vp->val)));
-           vp->val = NULL;
-       } while ((vp = yasm_vps_next(vp)));
-
+       yasm_dvs_append(&dvs, yasm_dv_create_expr(
+           yasm_expr_create_ident(
+               yasm_expr_int(yasm_intnum_create_uint(0)), line)));
        yasm_section_bcs_append(comment,
-           yasm_bc_create_data(&dvs, 1, 1, objfmt_elf->arch, line));
-    } else
-       return 1;       /* unrecognized */
+           yasm_bc_create_data(&dvs, 1, 0, objfmt_elf->arch, line));
+    }
 
-    return 0;
+    yasm_dvs_initialize(&dvs);
+    do {
+       yasm_dvs_append(&dvs, yasm_dv_create_string(vp->val, strlen(vp->val)));
+       vp->val = NULL;
+    } while ((vp = yasm_vps_next(vp)));
+
+    yasm_section_bcs_append(comment,
+       yasm_bc_create_data(&dvs, 1, 1, objfmt_elf->arch, line));
+}
+
+static int
+elf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
+                    /*@null@*/ yasm_valparamhead *valparams,
+                    /*@unused@*/ /*@null@*/
+                    yasm_valparamhead *objext_valparams,
+                    unsigned long line)
+{
+    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
+    static const struct {
+       const char *name;
+       void (*func) (yasm_objfmt_elf *, yasm_valparam *, unsigned long);
+    } dirs[] = {
+       {"TYPE", dir_type},
+       {"SIZE", dir_size},
+       {"WEAK", dir_weak},
+       {"IDENT", dir_ident}
+    };
+    size_t i;
+
+    for (i=0; i<NELEMS(dirs); i++) {
+       if (yasm__strcasecmp(name, dirs[i].name) == 0) {
+           yasm_valparam *vp;
+           if (!valparams || !(vp = yasm_vps_first(valparams)) || !vp->val) {
+               yasm_error_set(YASM_ERROR_SYNTAX,
+                              N_("Symbol name not specified"));
+               return 0;
+           }
+           dirs[i].func(objfmt_elf, vp, line);
+           return 0;
+       }
+    }
+    return 1;  /* unrecognized */
 }
 
 
index e0c6c6375f70a719dc6617c009d3e91cd1446be1..c42191a46ea3a5ce38ee14efb1a2d120b68db5e1 100644 (file)
@@ -1835,7 +1835,7 @@ macho_symrec_data_print(void *data, FILE *f, int indent_level)
 static int
 macho_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt,
                       /*@unused@*/ const char *name,
-                      /*@unused@*/ yasm_valparamhead *valparams,
+                      /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
                       /*@unused@*/ /*@null@*/
                       yasm_valparamhead *objext_valparams,
                       /*@unused@*/ unsigned long line)
index 25a42444c49a525629424f6a3d12d96d88566680..4b09a8f98c8d6fd405ae5e8c6a721df6c57cc08c 100644 (file)
@@ -1104,7 +1104,7 @@ rdf_symrec_data_print(void *data, FILE *f, int indent_level)
 
 static int
 rdf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
-                    yasm_valparamhead *valparams,
+                    /*@null@*/ yasm_valparamhead *valparams,
                     /*@unused@*/ /*@null@*/
                     yasm_valparamhead *objext_valparams, unsigned long line)
 {
@@ -1120,6 +1120,11 @@ rdf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
     else
        return 1;
 
+    if (!valparams) {
+       yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
+                      name);
+       return 0;
+    }
     vp = yasm_vps_first(valparams);
     if (!vp->val) {
        yasm_error_set(YASM_ERROR_SYNTAX, N_("argument to [%s] must be name"),
index 81b6050f01905fcec889fe0620fa558741377e15..33aa77aca1e18b5e0cde619eb0300183c0031fc5 100644 (file)
@@ -877,7 +877,7 @@ xdf_symrec_data_print(void *data, FILE *f, int indent_level)
 static int
 xdf_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt,
                      /*@unused@*/ const char *name,
-                     /*@unused@*/ yasm_valparamhead *valparams,
+                     /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
                      /*@unused@*/ /*@null@*/
                      yasm_valparamhead *objext_valparams,
                      /*@unused@*/ unsigned long line)
index fa1fccdd0a3772363b8caf461041a9996591bfd8..2a96b99683b1ffa1aee7b0e5f161d5d091e2bddf 100644 (file)
@@ -63,7 +63,7 @@ static yasm_expr *parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type);
 
 static void nasm_parser_directive
     (yasm_parser_nasm *parser_nasm, const char *name,
-     yasm_valparamhead *valparams,
+     /*@null@*/ yasm_valparamhead *valparams,
      /*@null@*/ yasm_valparamhead *objext_valparams);
 static int fix_directive_symrec(/*@null@*/ yasm_expr__item *ei,
                                /*@null@*/ void *d);
@@ -262,6 +262,7 @@ parse_line(yasm_parser_nasm *parser_nasm)
        {
            char *dirname;
            yasm_valparamhead dir_vps;
+           int have_vps = 1;
 
            parser_nasm->state = DIRECTIVE;
            get_next_token();
@@ -271,7 +272,9 @@ parse_line(yasm_parser_nasm *parser_nasm)
            dirname = DIRECTIVE_NAME_val;
            get_next_token();
 
-           if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
+           if (curtok == ']' || curtok == ':')
+               have_vps = 0;
+           else if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
                yasm_error_set(YASM_ERROR_SYNTAX,
                               N_("invalid arguments to [%s]"), dirname);
                yasm_xfree(dirname);
@@ -286,10 +289,11 @@ parse_line(yasm_parser_nasm *parser_nasm)
                    yasm_xfree(dirname);
                    return NULL;
                }
-               nasm_parser_directive(parser_nasm, dirname, &dir_vps,
-                                     &ext_vps);
+               nasm_parser_directive(parser_nasm, dirname,
+                                     have_vps ? &dir_vps : NULL, &ext_vps);
            } else
-               nasm_parser_directive(parser_nasm, dirname, &dir_vps, NULL);
+               nasm_parser_directive(parser_nasm, dirname,
+                                     have_vps ? &dir_vps : NULL, NULL);
            yasm_xfree(dirname);
            expect(']');
            get_next_token();
@@ -930,6 +934,9 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
        case INTNUM:
            e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
            break;
+       case REG:
+           e = p_expr_new_ident(yasm_expr_reg(REG_val[0]));
+           break;
        case ID:
            e = p_expr_new_ident(yasm_expr_sym(
                yasm_symtab_define_label(p_symtab, ID_val,
@@ -1050,6 +1057,153 @@ fix_directive_symrec(yasm_expr__item *ei, void *d)
     return 0;
 }
 
+static void
+dir_extern(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+          yasm_valparamhead *objext_valparams)
+{
+    yasm_valparam *vp = yasm_vps_first(valparams);
+    yasm_objfmt_extern_declare(parser_nasm->objfmt, vp->val, objext_valparams,
+                              cur_line);
+}
+
+static void
+dir_global(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+          yasm_valparamhead *objext_valparams)
+{
+    yasm_valparam *vp = yasm_vps_first(valparams);
+    yasm_objfmt_global_declare(parser_nasm->objfmt, vp->val, objext_valparams,
+                              cur_line);
+}
+
+static void
+dir_common(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+          yasm_valparamhead *objext_valparams)
+{
+    yasm_valparam *vp = yasm_vps_first(valparams);
+    yasm_valparam *vp2 = yasm_vps_next(vp);
+    unsigned long line = cur_line;
+
+    if (!vp2 || (!vp2->val && !vp2->param)) {
+       yasm_error_set(YASM_ERROR_SYNTAX,
+                      N_("no size specified in %s declaration"), "COMMON");
+       return;
+    }
+    if (vp2->val) {
+       yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
+           p_expr_new_ident(yasm_expr_sym(
+               yasm_symtab_use(p_symtab, vp2->val, line))),
+           objext_valparams, line);
+    } else if (vp2->param) {
+       yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val, vp2->param,
+                                  objext_valparams, line);
+       vp2->param = NULL;
+    }
+}
+
+static void
+dir_section(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+           yasm_valparamhead *objext_valparams)
+{
+    yasm_valparam *vp = yasm_vps_first(valparams);
+    yasm_section *new_section =
+       yasm_objfmt_section_switch(parser_nasm->objfmt, valparams,
+                                  objext_valparams, cur_line);
+    if (new_section) {
+       parser_nasm->cur_section = new_section;
+       parser_nasm->prev_bc = yasm_section_bcs_last(new_section);
+    } else
+       yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
+                      "SECTION");
+}
+
+static void
+dir_absolute(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+            yasm_valparamhead *objext_valparams)
+{
+    yasm_valparam *vp = yasm_vps_first(valparams);
+    unsigned long line = cur_line;
+    /* it can be just an ID or a complete expression, so handle both. */
+    if (vp->val)
+       parser_nasm->cur_section =
+           yasm_object_create_absolute(parser_nasm->object,
+               p_expr_new_ident(yasm_expr_sym(
+                   yasm_symtab_use(p_symtab, vp->val, line))), line);
+    else if (vp->param) {
+       parser_nasm->cur_section =
+           yasm_object_create_absolute(parser_nasm->object, vp->param, line);
+       vp->param = NULL;
+    }
+    parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
+}
+
+static void
+dir_align(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+         yasm_valparamhead *objext_valparams)
+{
+    /*@only@*/ yasm_expr *boundval;
+    /*@depedent@*/ yasm_intnum *boundintn;
+    yasm_valparam *vp = yasm_vps_first(valparams);
+
+    /* it can be just an ID or a complete expression, so handle both. */
+    vp = yasm_vps_first(valparams);
+    if (vp->val)
+       boundval = p_expr_new_ident(yasm_expr_sym(
+           yasm_symtab_use(p_symtab, vp->val, cur_line)));
+    else if (vp->param) {
+       boundval = vp->param;
+       vp->param = NULL;
+    }
+
+    /* Largest .align in the section specifies section alignment.
+     * Note: this doesn't match NASM behavior, but is a lot more
+     * intelligent!
+     */
+    boundintn = yasm_expr_get_intnum(&boundval, 0);
+    if (boundintn) {
+       unsigned long boundint = yasm_intnum_get_uint(boundintn);
+
+       /* Alignments must be a power of two. */
+       if (is_exp2(boundint)) {
+           if (boundint > yasm_section_get_align(parser_nasm->cur_section))
+               yasm_section_set_align(parser_nasm->cur_section, boundint,
+                                      cur_line);
+       }
+    }
+
+    /* As this directive is called only when nop is used as fill, always
+     * use arch (nop) fill.
+     */
+    parser_nasm->prev_bc =
+       yasm_section_bcs_append(parser_nasm->cur_section,
+           yasm_bc_create_align(boundval, NULL, NULL,
+               /*yasm_section_is_code(parser_nasm->cur_section) ?*/
+                   yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
+               cur_line));
+}
+
+static void
+dir_cpu(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+       yasm_valparamhead *objext_valparams)
+{
+    yasm_valparam *vp;
+    yasm_vps_foreach(vp, valparams) {
+       if (vp->val)
+           yasm_arch_parse_cpu(parser_nasm->arch, vp->val, strlen(vp->val));
+       else if (vp->param) {
+           const yasm_intnum *intcpu;
+           intcpu = yasm_expr_get_intnum(&vp->param, 0);
+           if (!intcpu)
+               yasm_error_set(YASM_ERROR_SYNTAX,
+                              N_("invalid argument to [%s]"), "CPU");
+           else {
+               char strcpu[16];
+               sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
+               yasm_arch_parse_cpu(parser_nasm->arch, strcpu, strlen(strcpu));
+           }
+       }
+    }
+}
+
 static void
 nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
                      yasm_valparamhead *valparams,
@@ -1057,132 +1211,45 @@ nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
 {
     yasm_valparam *vp, *vp2;
     unsigned long line = cur_line;
+    static const struct {
+       const char *name;
+       int required_arg:1;
+       int id_only:1;
+       void (*func) (yasm_parser_nasm *, yasm_valparamhead *,
+                     yasm_valparamhead *);
+    } dirs[] = {
+       {"EXTERN", 1, 1, dir_extern},
+       {"GLOBAL", 1, 1, dir_global},
+       {"COMMON", 1, 1, dir_common},
+       {"SECTION", 1, 0, dir_section},
+       {"SEGMENT", 1, 0, dir_section},
+       {"ABSOLUTE", 1, 0, dir_absolute},
+       {"ALIGN", 1, 0, dir_align},
+       {"CPU", 1, 0, dir_cpu}
+    };
+    size_t i;
 
     /* Handle (mostly) output-format independent directives here */
-    if (yasm__strcasecmp(name, "extern") == 0) {
-       vp = yasm_vps_first(valparams);
-       if (vp->val) {
-           yasm_objfmt_extern_declare(parser_nasm->objfmt, vp->val,
-                                      objext_valparams, line);
-       } else
-           yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
-                          "EXTERN");
-    } else if (yasm__strcasecmp(name, "global") == 0) {
-       vp = yasm_vps_first(valparams);
-       if (vp->val) {
-           yasm_objfmt_global_declare(parser_nasm->objfmt, vp->val,
-                                      objext_valparams, line);
-       } else
-           yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
-                          "GLOBAL");
-    } else if (yasm__strcasecmp(name, "common") == 0) {
-       vp = yasm_vps_first(valparams);
-       if (vp->val) {
-           vp2 = yasm_vps_next(vp);
-           if (!vp2 || (!vp2->val && !vp2->param))
+    for (i=0; i<NELEMS(dirs); i++) {
+       if (yasm__strcasecmp(name, dirs[i].name) == 0) {
+           if (dirs[i].required_arg && !valparams) {
                yasm_error_set(YASM_ERROR_SYNTAX,
-                              N_("no size specified in %s declaration"),
-                              "COMMON");
-           else {
-               if (vp2->val) {
-                   yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
-                       p_expr_new_ident(yasm_expr_sym(
-                           yasm_symtab_use(p_symtab, vp2->val, line))),
-                       objext_valparams, line);
-               } else if (vp2->param) {
-                   yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
-                                              vp2->param, objext_valparams,
-                                              line);
-                   vp2->param = NULL;
-               }
+                              N_("[%s] requires an argument"), dirs[i].name);
+               break;
            }
-       } else
-           yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
-                          "COMMON");
-    } else if (yasm__strcasecmp(name, "section") == 0 ||
-              yasm__strcasecmp(name, "segment") == 0) {
-       yasm_section *new_section =
-           yasm_objfmt_section_switch(parser_nasm->objfmt, valparams,
-                                      objext_valparams, line);
-       if (new_section) {
-           parser_nasm->cur_section = new_section;
-           parser_nasm->prev_bc = yasm_section_bcs_last(new_section);
-       } else
-           yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
-                          "SECTION");
-    } else if (yasm__strcasecmp(name, "absolute") == 0) {
-       /* it can be just an ID or a complete expression, so handle both. */
-       vp = yasm_vps_first(valparams);
-       if (vp->val)
-           parser_nasm->cur_section =
-               yasm_object_create_absolute(parser_nasm->object,
-                   p_expr_new_ident(yasm_expr_sym(
-                       yasm_symtab_use(p_symtab, vp->val, line))), line);
-       else if (vp->param) {
-           parser_nasm->cur_section =
-               yasm_object_create_absolute(parser_nasm->object, vp->param,
-                                           line);
-           vp->param = NULL;
-       }
-       parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
-    } else if (yasm__strcasecmp(name, "align") == 0) {
-       /*@only@*/ yasm_expr *boundval;
-       /*@depedent@*/ yasm_intnum *boundintn;
-
-       /* it can be just an ID or a complete expression, so handle both. */
-       vp = yasm_vps_first(valparams);
-       if (vp->val)
-           boundval = p_expr_new_ident(yasm_expr_sym(
-               yasm_symtab_use(p_symtab, vp->val, line)));
-       else if (vp->param) {
-           boundval = vp->param;
-           vp->param = NULL;
-       }
-
-       /* Largest .align in the section specifies section alignment.
-        * Note: this doesn't match NASM behavior, but is a lot more
-        * intelligent!
-        */
-       boundintn = yasm_expr_get_intnum(&boundval, 0);
-       if (boundintn) {
-           unsigned long boundint = yasm_intnum_get_uint(boundintn);
-
-           /* Alignments must be a power of two. */
-           if (is_exp2(boundint)) {
-               if (boundint > yasm_section_get_align(parser_nasm->cur_section))
-                   yasm_section_set_align(parser_nasm->cur_section, boundint,
-                                          cur_line);
+           if (dirs[i].id_only && (vp = yasm_vps_first(valparams))
+               && !vp->val) {
+               yasm_error_set(YASM_ERROR_SYNTAX,
+                              N_("invalid argument to [%s]"), dirs[i].name);
+               break;
            }
+           dirs[i].func(parser_nasm, valparams, objext_valparams);
+           break;
        }
+    }
 
-       /* As this directive is called only when nop is used as fill, always
-        * use arch (nop) fill.
-        */
-       parser_nasm->prev_bc =
-           yasm_section_bcs_append(parser_nasm->cur_section,
-               yasm_bc_create_align(boundval, NULL, NULL,
-                   /*yasm_section_is_code(parser_nasm->cur_section) ?*/
-                       yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
-                   cur_line));
-    } else if (yasm__strcasecmp(name, "cpu") == 0) {
-       yasm_vps_foreach(vp, valparams) {
-           if (vp->val)
-               yasm_arch_parse_cpu(parser_nasm->arch, vp->val,
-                                   strlen(vp->val));
-           else if (vp->param) {
-               const yasm_intnum *intcpu;
-               intcpu = yasm_expr_get_intnum(&vp->param, 0);
-               if (!intcpu)
-                   yasm_error_set(YASM_ERROR_SYNTAX,
-                                  N_("invalid argument to [%s]"), "CPU");
-               else {
-                   char strcpu[16];
-                   sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
-                   yasm_arch_parse_cpu(parser_nasm->arch, strcpu,
-                                       strlen(strcpu));
-               }
-           }
-       }
+    if (i != NELEMS(dirs)) {
+       ;
     } else if (!yasm_arch_parse_directive(parser_nasm->arch, name, valparams,
                    objext_valparams, parser_nasm->object, line)) {
        ;
@@ -1196,7 +1263,9 @@ nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
                       name);
     }
 
-    yasm_vps_delete(valparams);
+done:
+    if (valparams)
+       yasm_vps_delete(valparams);
     if (objext_valparams)
        yasm_vps_delete(objext_valparams);
 }
index cd45b3b9f5013772ed0301ed21560cd66eee3dc3..92201ee847df6cdfdda87c74c08323c4dbb77d47 100644 (file)
@@ -476,7 +476,7 @@ directive:
            RETURN(s->tok[0]);
        }
 
-       iletter+ {
+       [a-zA-Z_][a-zA-Z_0-9]* {
            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
            if (yasm__strcasecmp(lvalp->str_val, "section") == 0 ||
                yasm__strcasecmp(lvalp->str_val, "segment") == 0)