diff options
author | Peter Johnson <peter@tortall.net> | 2001-11-19 03:27:56 +0000 |
---|---|---|
committer | Peter Johnson <peter@tortall.net> | 2001-11-19 03:27:56 +0000 |
commit | 8cbf2c2312926aba897e87e3b3db31d8fbc1c574 (patch) | |
tree | 76488ae3be85834216bf69f45b8443390a4bcda7 | |
parent | b963c38833bca7693fd35fde81d46b23f275ab36 (diff) | |
download | yasm-8cbf2c2312926aba897e87e3b3db31d8fbc1c574.tar.gz |
- Greatly enhance capabilities of directives (they're actually parsed now).
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, 1185 insertions, 290 deletions
diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index 3d72d5dc..bdc31999 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -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/libyasm/linemgr.c b/libyasm/linemgr.c index b5abfe9b..895ff64f 100644 --- a/libyasm/linemgr.c +++ b/libyasm/linemgr.c @@ -27,6 +27,12 @@ #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; diff --git a/libyasm/linemgr.h b/libyasm/linemgr.h index bf37e4a8..9349d12b 100644 --- a/libyasm/linemgr.h +++ b/libyasm/linemgr.h @@ -22,6 +22,12 @@ #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; diff --git a/libyasm/objfmt.h b/libyasm/objfmt.h index ea820306..e484dbd8 100644 --- a/libyasm/objfmt.h +++ b/libyasm/objfmt.h @@ -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 diff --git a/libyasm/parser.h b/libyasm/parser.h index 822c9d4a..7365f1c3 100644 --- a/libyasm/parser.h +++ b/libyasm/parser.h @@ -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 diff --git a/libyasm/preproc.h b/libyasm/preproc.h index f585e7bc..68d4b2d4 100644 --- a/libyasm/preproc.h +++ b/libyasm/preproc.h @@ -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. */ diff --git a/libyasm/section.c b/libyasm/section.c index 4900479b..eb76a74d 100644 --- a/libyasm/section.c +++ b/libyasm/section.c @@ -22,6 +22,10 @@ #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(§->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; } diff --git a/libyasm/section.h b/libyasm/section.h index 05e9c091..8c8da8eb 100644 --- a/libyasm/section.h +++ b/libyasm/section.h @@ -24,11 +24,17 @@ 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); diff --git a/libyasm/symrec.c b/libyasm/symrec.c index b1871689..041d28fe 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -22,6 +22,10 @@ #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 { diff --git a/libyasm/tests/Makefile.am b/libyasm/tests/Makefile.am index 36e4bb1d..b7e4b489 100644 --- a/libyasm/tests/Makefile.am +++ b/libyasm/tests/Makefile.am @@ -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 \ diff --git a/modules/objfmts/dbg/dbg-objfmt.c b/modules/objfmts/dbg/dbg-objfmt.c index 41e2f2f0..21a620fa 100644 --- a/modules/objfmts/dbg/dbg-objfmt.c +++ b/modules/objfmts/dbg/dbg-objfmt.c @@ -22,14 +22,62 @@ #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 }; diff --git a/modules/objfmts/dbg/objfmt.c b/modules/objfmts/dbg/objfmt.c index 41e2f2f0..21a620fa 100644 --- a/modules/objfmts/dbg/objfmt.c +++ b/modules/objfmts/dbg/objfmt.c @@ -22,14 +22,62 @@ #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 }; diff --git a/modules/parsers/nasm/Makefile.am b/modules/parsers/nasm/Makefile.am index 47ddce63..4380b014 100644 --- a/modules/parsers/nasm/Makefile.am +++ b/modules/parsers/nasm/Makefile.am @@ -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 = \ diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index 4de5d9f8..4317140e 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -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 diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index 4de5d9f8..4317140e 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -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 diff --git a/modules/parsers/nasm/nasm-parser.c b/modules/parsers/nasm/nasm-parser.c index 66779fca..0b896f94 100644 --- a/modules/parsers/nasm/nasm-parser.c +++ b/modules/parsers/nasm/nasm-parser.c @@ -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; */ diff --git a/modules/parsers/nasm/parser.c b/modules/parsers/nasm/parser.c index 66779fca..0b896f94 100644 --- a/modules/parsers/nasm/parser.c +++ b/modules/parsers/nasm/parser.c @@ -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; */ diff --git a/modules/parsers/nasm/token.l.in b/modules/parsers/nasm/token.l.in index 1fd8303e..a24da44e 100644 --- a/modules/parsers/nasm/token.l.in +++ b/modules/parsers/nasm/token.l.in @@ -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_$#@~.?]+ { diff --git a/modules/preprocs/raw/preproc.c b/modules/preprocs/raw/preproc.c index ca9fb264..419f7708 100644 --- a/modules/preprocs/raw/preproc.c +++ b/modules/preprocs/raw/preproc.c @@ -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@*/ diff --git a/modules/preprocs/raw/raw-preproc.c b/modules/preprocs/raw/raw-preproc.c index ca9fb264..419f7708 100644 --- a/modules/preprocs/raw/raw-preproc.c +++ b/modules/preprocs/raw/raw-preproc.c @@ -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@*/ diff --git a/src/Makefile.am b/src/Makefile.am index fd68d092..5650b0f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/globals.c b/src/globals.c index b5abfe9b..895ff64f 100644 --- a/src/globals.c +++ b/src/globals.c @@ -27,6 +27,12 @@ #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; diff --git a/src/globals.h b/src/globals.h index bf37e4a8..9349d12b 100644 --- a/src/globals.h +++ b/src/globals.h @@ -22,6 +22,12 @@ #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; diff --git a/src/linemgr.c b/src/linemgr.c index b5abfe9b..895ff64f 100644 --- a/src/linemgr.c +++ b/src/linemgr.c @@ -27,6 +27,12 @@ #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; diff --git a/src/linemgr.h b/src/linemgr.h index bf37e4a8..9349d12b 100644 --- a/src/linemgr.h +++ b/src/linemgr.h @@ -22,6 +22,12 @@ #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; @@ -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 index 00000000..4b7d8ad1 --- /dev/null +++ b/src/objfmt.c @@ -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); +} diff --git a/src/objfmt.h b/src/objfmt.h index ea820306..e484dbd8 100644 --- a/src/objfmt.h +++ b/src/objfmt.h @@ -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 diff --git a/src/objfmts/dbg/dbg-objfmt.c b/src/objfmts/dbg/dbg-objfmt.c index 41e2f2f0..21a620fa 100644 --- a/src/objfmts/dbg/dbg-objfmt.c +++ b/src/objfmts/dbg/dbg-objfmt.c @@ -22,14 +22,62 @@ #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 }; diff --git a/src/objfmts/dbg/objfmt.c b/src/objfmts/dbg/objfmt.c index 41e2f2f0..21a620fa 100644 --- a/src/objfmts/dbg/objfmt.c +++ b/src/objfmts/dbg/objfmt.c @@ -22,14 +22,62 @@ #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 }; diff --git a/src/parser.c b/src/parser.c index cde12bbb..fa0858ea 100644 --- a/src/parser.c +++ b/src/parser.c @@ -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. diff --git a/src/parser.h b/src/parser.h index 822c9d4a..7365f1c3 100644 --- a/src/parser.h +++ b/src/parser.h @@ -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 diff --git a/src/parsers/nasm/Makefile.am b/src/parsers/nasm/Makefile.am index 47ddce63..4380b014 100644 --- a/src/parsers/nasm/Makefile.am +++ b/src/parsers/nasm/Makefile.am @@ -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 = \ diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index 4de5d9f8..4317140e 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -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 diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index 4de5d9f8..4317140e 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -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 diff --git a/src/parsers/nasm/nasm-parser.c b/src/parsers/nasm/nasm-parser.c index 66779fca..0b896f94 100644 --- a/src/parsers/nasm/nasm-parser.c +++ b/src/parsers/nasm/nasm-parser.c @@ -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; */ diff --git a/src/parsers/nasm/parser.c b/src/parsers/nasm/parser.c index 66779fca..0b896f94 100644 --- a/src/parsers/nasm/parser.c +++ b/src/parsers/nasm/parser.c @@ -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; */ diff --git a/src/parsers/nasm/token.l.in b/src/parsers/nasm/token.l.in index 1fd8303e..a24da44e 100644 --- a/src/parsers/nasm/token.l.in +++ b/src/parsers/nasm/token.l.in @@ -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_$#@~.?]+ { diff --git a/src/preproc.h b/src/preproc.h index f585e7bc..68d4b2d4 100644 --- a/src/preproc.h +++ b/src/preproc.h @@ -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. */ diff --git a/src/preprocs/raw/preproc.c b/src/preprocs/raw/preproc.c index ca9fb264..419f7708 100644 --- a/src/preprocs/raw/preproc.c +++ b/src/preprocs/raw/preproc.c @@ -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@*/ diff --git a/src/preprocs/raw/raw-preproc.c b/src/preprocs/raw/raw-preproc.c index ca9fb264..419f7708 100644 --- a/src/preprocs/raw/raw-preproc.c +++ b/src/preprocs/raw/raw-preproc.c @@ -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@*/ diff --git a/src/section.c b/src/section.c index 4900479b..eb76a74d 100644 --- a/src/section.c +++ b/src/section.c @@ -22,6 +22,10 @@ #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(§->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; } diff --git a/src/section.h b/src/section.h index 05e9c091..8c8da8eb 100644 --- a/src/section.h +++ b/src/section.h @@ -24,11 +24,17 @@ 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); diff --git a/src/symrec.c b/src/symrec.c index b1871689..041d28fe 100644 --- a/src/symrec.c +++ b/src/symrec.c @@ -22,6 +22,10 @@ #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 { diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 36e4bb1d..b7e4b489 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -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 \ |