From: Peter Johnson Date: Wed, 7 Feb 2007 08:29:41 +0000 (-0000) Subject: Allow directives to have no parameters in the parser, and check for it at X-Git-Tag: v0.6.0~30 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e7b1cea7ffc86243f060253bb8d9277b12f72bc7;p=yasm Allow directives to have no parameters in the parser, and check for it at 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 --- diff --git a/libyasm/arch.h b/libyasm/arch.h index 9d1ffba3..23555719 100644 --- a/libyasm/arch.h +++ b/libyasm/arch.h @@ -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); diff --git a/libyasm/dbgfmt.h b/libyasm/dbgfmt.h index 8f767f7c..cae3568d 100644 --- a/libyasm/dbgfmt.h +++ b/libyasm/dbgfmt.h @@ -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. diff --git a/libyasm/objfmt.h b/libyasm/objfmt.h index 4f63c1cc..129803dc 100644 --- a/libyasm/objfmt.h +++ b/libyasm/objfmt.h @@ -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); diff --git a/modules/arch/lc3b/lc3barch.c b/modules/arch/lc3b/lc3barch.c index cefbeb19..bbf28956 100644 --- a/modules/arch/lc3b/lc3barch.c +++ b/modules/arch/lc3b/lc3barch.c @@ -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, diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c index 731f102e..c5b6ee04 100644 --- a/modules/arch/x86/x86arch.c +++ b/modules/arch/x86/x86arch.c @@ -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)) && diff --git a/modules/dbgfmts/dwarf2/dwarf2-line.c b/modules/dbgfmts/dwarf2/dwarf2-line.c index 44d117a8..a95ec574 100644 --- a/modules/dbgfmts/dwarf2/dwarf2-line.c +++ b/modules/dbgfmts/dwarf2/dwarf2-line.c @@ -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); diff --git a/modules/objfmts/bin/bin-objfmt.c b/modules/objfmts/bin/bin-objfmt.c index c010bfa8..b33c8bc2 100644 --- a/modules/objfmts/bin/bin-objfmt.c +++ b/modules/objfmts/bin/bin-objfmt.c @@ -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) diff --git a/modules/objfmts/coff/coff-objfmt.c b/modules/objfmts/coff/coff-objfmt.c index ab08bf95..cc9ecc68 100644 --- a/modules/objfmts/coff/coff-objfmt.c +++ b/modules/objfmts/coff/coff-objfmt.c @@ -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) diff --git a/modules/objfmts/dbg/dbg-objfmt.c b/modules/objfmts/dbg/dbg-objfmt.c index 3562cbe1..33fbdb9e 100644 --- a/modules/objfmts/dbg/dbg-objfmt.c +++ b/modules/objfmts/dbg/dbg-objfmt.c @@ -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) { diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index d570a9d6..9473f022 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -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(§_vps); - vp2 = yasm_vp_create(yasm__xstrdup(".comment"), NULL); - yasm_vps_append(§_vps, vp2); - comment = elf_objfmt_section_switch(objfmt, §_vps, NULL, line); - yasm_vps_delete(§_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(§_vps); + vp2 = yasm_vp_create(yasm__xstrdup(".comment"), NULL); + yasm_vps_append(§_vps, vp2); + comment = elf_objfmt_section_switch((yasm_objfmt *)objfmt_elf, §_vps, + NULL, line); + yasm_vps_delete(§_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; ival) { + 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 */ } diff --git a/modules/objfmts/macho/macho-objfmt.c b/modules/objfmts/macho/macho-objfmt.c index e0c6c637..c42191a4 100644 --- a/modules/objfmts/macho/macho-objfmt.c +++ b/modules/objfmts/macho/macho-objfmt.c @@ -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) diff --git a/modules/objfmts/rdf/rdf-objfmt.c b/modules/objfmts/rdf/rdf-objfmt.c index 25a42444..4b09a8f9 100644 --- a/modules/objfmts/rdf/rdf-objfmt.c +++ b/modules/objfmts/rdf/rdf-objfmt.c @@ -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"), diff --git a/modules/objfmts/xdf/xdf-objfmt.c b/modules/objfmts/xdf/xdf-objfmt.c index 81b6050f..33aa77ac 100644 --- a/modules/objfmts/xdf/xdf-objfmt.c +++ b/modules/objfmts/xdf/xdf-objfmt.c @@ -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) diff --git a/modules/parsers/nasm/nasm-parse.c b/modules/parsers/nasm/nasm-parse.c index fa1fccdd..2a96b996 100644 --- a/modules/parsers/nasm/nasm-parse.c +++ b/modules/parsers/nasm/nasm-parse.c @@ -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; ival) { - 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); } diff --git a/modules/parsers/nasm/nasm-token.re b/modules/parsers/nasm/nasm-token.re index cd45b3b9..92201ee8 100644 --- a/modules/parsers/nasm/nasm-token.re +++ b/modules/parsers/nasm/nasm-token.re @@ -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)