summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Johnson <peter@tortall.net>2001-11-19 03:27:56 +0000
committerPeter Johnson <peter@tortall.net>2001-11-19 03:27:56 +0000
commit8cbf2c2312926aba897e87e3b3db31d8fbc1c574 (patch)
tree76488ae3be85834216bf69f45b8443390a4bcda7
parentb963c38833bca7693fd35fde81d46b23f275ab36 (diff)
downloadyasm-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
-rw-r--r--frontends/yasm/yasm.c18
-rw-r--r--libyasm/linemgr.c6
-rw-r--r--libyasm/linemgr.h6
-rw-r--r--libyasm/objfmt.h24
-rw-r--r--libyasm/parser.h5
-rw-r--r--libyasm/preproc.h2
-rw-r--r--libyasm/section.c128
-rw-r--r--libyasm/section.h17
-rw-r--r--libyasm/symrec.c12
-rw-r--r--libyasm/tests/Makefile.am1
-rw-r--r--modules/objfmts/dbg/dbg-objfmt.c60
-rw-r--r--modules/objfmts/dbg/objfmt.c60
-rw-r--r--modules/parsers/nasm/Makefile.am2
-rw-r--r--modules/parsers/nasm/bison.y.in156
-rw-r--r--modules/parsers/nasm/nasm-bison.y156
-rw-r--r--modules/parsers/nasm/nasm-parser.c9
-rw-r--r--modules/parsers/nasm/parser.c9
-rw-r--r--modules/parsers/nasm/token.l.in20
-rw-r--r--modules/preprocs/raw/preproc.c2
-rw-r--r--modules/preprocs/raw/raw-preproc.c2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/globals.c6
-rw-r--r--src/globals.h6
-rw-r--r--src/linemgr.c6
-rw-r--r--src/linemgr.h6
-rw-r--r--src/main.c18
-rw-r--r--src/objfmt.c68
-rw-r--r--src/objfmt.h24
-rw-r--r--src/objfmts/dbg/dbg-objfmt.c60
-rw-r--r--src/objfmts/dbg/objfmt.c60
-rw-r--r--src/parser.c3
-rw-r--r--src/parser.h5
-rw-r--r--src/parsers/nasm/Makefile.am2
-rw-r--r--src/parsers/nasm/bison.y.in156
-rw-r--r--src/parsers/nasm/nasm-bison.y156
-rw-r--r--src/parsers/nasm/nasm-parser.c9
-rw-r--r--src/parsers/nasm/parser.c9
-rw-r--r--src/parsers/nasm/token.l.in20
-rw-r--r--src/preproc.h2
-rw-r--r--src/preprocs/raw/preproc.c2
-rw-r--r--src/preprocs/raw/raw-preproc.c2
-rw-r--r--src/section.c128
-rw-r--r--src/section.h17
-rw-r--r--src/symrec.c12
-rw-r--r--src/tests/Makefile.am1
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(&sect->bc);
xfree(sect);
}
@@ -169,15 +227,21 @@ section_delete(section *sect)
void
section_print(const section *sect)
{
- printf("***SECTION %s***\n", sect->name);
printf(" type=");
switch (sect->type) {
case SECTION_GENERAL:
- printf("general\n");
+ printf("general\n name=%s\n objfmt data:\n",
+ sect->data.general.name);
+ assert(cur_objfmt != NULL);
+ if (sect->data.general.of_data)
+ cur_objfmt->section_data_print(sect->data.general.of_data);
+ else
+ printf(" (none)\n");
break;
case SECTION_ABSOLUTE:
- printf("absolute\n");
- printf("start=%lu\n", sect->data.start);
+ printf("absolute\n start=");
+ expr_print(sect->data.start);
+ printf("\n");
break;
}
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;
diff --git a/src/main.c b/src/main.c
index 3d72d5dc..bdc31999 100644
--- a/src/main.c
+++ b/src/main.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/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(&sect->bc);
xfree(sect);
}
@@ -169,15 +227,21 @@ section_delete(section *sect)
void
section_print(const section *sect)
{
- printf("***SECTION %s***\n", sect->name);
printf(" type=");
switch (sect->type) {
case SECTION_GENERAL:
- printf("general\n");
+ printf("general\n name=%s\n objfmt data:\n",
+ sect->data.general.name);
+ assert(cur_objfmt != NULL);
+ if (sect->data.general.of_data)
+ cur_objfmt->section_data_print(sect->data.general.of_data);
+ else
+ printf(" (none)\n");
break;
case SECTION_ABSOLUTE:
- printf("absolute\n");
- printf("start=%lu\n", sect->data.start);
+ printf("absolute\n start=");
+ expr_print(sect->data.start);
+ printf("\n");
break;
}
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 \