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
/* 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);
#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;
#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;
*/
/* 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
* 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 */
*/
void list_parsers(void (*printfunc) (const char *name, const char *keyword));
-/* Available parsers */
-extern parser nasm_parser;
-
#endif
* 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. */
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
#include "globals.h"
#include "errwarn.h"
#include "expr.h"
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;
/* 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)
{
{
section *cur;
- STAILQ_FOREACH(cur, headp, link)
+ STAILQ_FOREACH(cur, headp, link) {
+ printf("***SECTION***\n");
section_print(cur);
+ }
}
void
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
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);
}
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;
}
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);
/*@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);
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
#include "ternary.h"
#include "globals.h"
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 {
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 \
#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 */
"dbg",
".text",
32,
- dbg_objfmt_is_valid_section
+ dbg_objfmt_sections_switch,
+ dbg_objfmt_section_data_delete,
+ dbg_objfmt_section_data_print
};
#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 */
"dbg",
".text",
32,
- dbg_objfmt_is_valid_section
+ dbg_objfmt_sections_switch,
+ dbg_objfmt_section_data_delete,
+ dbg_objfmt_section_data_print
};
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 = \
RCSID("$IdPath$");
#ifdef STDC_HEADERS
+# include <assert.h>
# include <math.h>
#endif
#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;
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
%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 '^'
;
/* 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
;
/* 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)); }
}
;
-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);
+ }
}
;
/*@=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
RCSID("$IdPath$");
#ifdef STDC_HEADERS
+# include <assert.h>
# include <math.h>
#endif
#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;
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
%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 '^'
;
/* 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
;
/* 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)); }
}
;
-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);
+ }
}
;
/*@=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
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; */
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; */
%option nounput
%option case-insensitive
-%x DIRECTIVE DIRECTIVE2
+%x DIRECTIVE
+%s DIRECTIVE2
DIGIT [0-9]
BINDIGIT [01]
<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 */
"//" { 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_$#@~.?]+ {
int isatty(int);
static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
{
in = f;
/*@-unrecog@*/
int isatty(int);
static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
{
in = f;
/*@-unrecog@*/
errwarn.h
yasm_LDADD = \
+ libyasm.a \
arch/@ARCH@/libarch.a \
parsers/nasm/libparser.a \
preprocs/raw/libpreproc.a \
section.h \
arch.c \
arch.h \
+ objfmt.c \
objfmt.h \
options.h \
options.c \
#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;
#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;
#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;
#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;
/* 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);
--- /dev/null
+/*
+ * 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);
+}
*/
/* 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
#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 */
"dbg",
".text",
32,
- dbg_objfmt_is_valid_section
+ dbg_objfmt_sections_switch,
+ dbg_objfmt_section_data_delete,
+ dbg_objfmt_section_data_print
};
#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 */
"dbg",
".text",
32,
- dbg_objfmt_is_valid_section
+ dbg_objfmt_sections_switch,
+ dbg_objfmt_section_data_delete,
+ dbg_objfmt_section_data_print
};
#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.
* 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 */
*/
void list_parsers(void (*printfunc) (const char *name, const char *keyword));
-/* Available parsers */
-extern parser nasm_parser;
-
#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 = \
RCSID("$IdPath$");
#ifdef STDC_HEADERS
+# include <assert.h>
# include <math.h>
#endif
#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;
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
%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 '^'
;
/* 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
;
/* 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)); }
}
;
-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);
+ }
}
;
/*@=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
RCSID("$IdPath$");
#ifdef STDC_HEADERS
+# include <assert.h>
# include <math.h>
#endif
#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;
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
%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 '^'
;
/* 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
;
/* 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)); }
}
;
-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);
+ }
}
;
/*@=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
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; */
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; */
%option nounput
%option case-insensitive
-%x DIRECTIVE DIRECTIVE2
+%x DIRECTIVE
+%s DIRECTIVE2
DIGIT [0-9]
BINDIGIT [01]
<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 */
"//" { 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_$#@~.?]+ {
* 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. */
int isatty(int);
static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
{
in = f;
/*@-unrecog@*/
int isatty(int);
static void
-raw_preproc_initialize(/*@unused@*/ objfmt *of, FILE *f)
+raw_preproc_initialize(FILE *f)
{
in = f;
/*@-unrecog@*/
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
#include "globals.h"
#include "errwarn.h"
#include "expr.h"
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;
/* 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)
{
{
section *cur;
- STAILQ_FOREACH(cur, headp, link)
+ STAILQ_FOREACH(cur, headp, link) {
+ printf("***SECTION***\n");
section_print(cur);
+ }
}
void
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
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);
}
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;
}
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);
/*@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);
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
+#ifdef STDC_HEADERS
+# include <assert.h>
+#endif
+
#include "ternary.h"
#include "globals.h"
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 {
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 \