EXPR_IDENT /* no operation, just a value */
} ExprOp;
+/* EXTERN and COMMON are mutually exclusive */
+typedef enum {
+ SYM_LOCAL = 0, /* default, local only */
+ SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */
+ SYM_COMMON = 1 << 1, /* if it's declared COMMON */
+ SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */
+} SymVisibility;
+
#endif
void (*section_data_delete)(/*@only@*/ void *data);
void (*section_data_print)(void *data);
+
+ /*@null@*/ void *(*extern_data_new)(const char *name, /*@null@*/
+ valparamhead *objext_valparams);
+ /*@null@*/ void *(*global_data_new)(const char *name, /*@null@*/
+ valparamhead *objext_valparams);
+ /*@null@*/ void *(*common_data_new)(const char *name,
+ /*@only@*/ expr *size, /*@null@*/
+ valparamhead *objext_valparams);
+
+ /* It's only valid to pass this *one* SymVisibility (eg, vis is an enum not
+ * a bitmask).
+ */
+ void (*declare_data_delete)(SymVisibility vis, /*@only@*/ void *data);
+
+ /* Object format-specific directive support. Returns 1 if directive was
+ * not recognized. Returns 0 if directive was recognized, even if it
+ * wasn't valid.
+ */
+ int (*directive)(const char *name, valparamhead *valparams,
+ /*@null@*/ valparamhead *objext_valparams);
};
/* Generic functions for all object formats - implemented in src/objfmt.c */
#include "bytecode.h"
#include "section.h"
+#include "objfmt.h"
/* DEFINED is set with EXTERN and COMMON below */
/*@dependent@*/ /*@null@*/ bytecode *bc;
} label;
} value;
+
+ /* objfmt-specific data (related to visibility, so common/extern share
+ * a pointer, and global has its own pointer).
+ */
+ /*@null@*/ /*@owned@*/ void *of_data_vis_ce;
+ /*@null@*/ /*@owned@*/ void *of_data_vis_g;
};
/* The symbol table: a ternary tree. */
rec->filename = in_filename;
rec->line = line_number;
rec->visibility = SYM_LOCAL;
+ rec->of_data_vis_ce = NULL;
+ rec->of_data_vis_g = NULL;
/*@-freshtrans -mustfree@*/
return rec;
}
symrec *
-symrec_declare(const char *name, SymVisibility vis)
+symrec_declare(const char *name, SymVisibility vis, void *of_data)
{
symrec *rec = symrec_get_or_new(name, 1);
+ assert(cur_objfmt != NULL);
+
/* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */
/* Also, EXTERN and COMMON are mutually exclusive. */
if (((rec->status & SYM_DEFINED) && !(rec->visibility & SYM_EXTERN)) ||
((rec->visibility & SYM_EXTERN) && (vis == SYM_COMMON))) {
Error(_("duplicate definition of `%s'; first defined on line %d"),
name, rec->line);
+ if (of_data)
+ cur_objfmt->declare_data_delete(vis, of_data);
} else {
rec->line = line_number; /* set line number of declaration */
rec->visibility |= vis;
/* If declared as COMMON or EXTERN, set as DEFINED. */
if ((vis == SYM_COMMON) || (vis == SYM_EXTERN))
rec->status |= SYM_DEFINED;
+
+ if (of_data) {
+ switch (vis) {
+ case SYM_GLOBAL:
+ rec->of_data_vis_g = of_data;
+ break;
+ case SYM_COMMON:
+ case SYM_EXTERN:
+ rec->of_data_vis_ce = of_data;
+ break;
+ default:
+ InternalError(_("Unexpected vis value"));
+ }
+ }
}
return rec;
}
xfree(sym->name);
if (sym->type == SYM_EQU)
expr_delete(sym->value.expn);
+ assert(cur_objfmt != NULL);
+ if (sym->of_data_vis_g && (sym->visibility & SYM_GLOBAL))
+ cur_objfmt->declare_data_delete(SYM_GLOBAL, sym->of_data_vis_g);
+ if (sym->of_data_vis_ce && (sym->visibility & SYM_COMMON)) {
+ cur_objfmt->declare_data_delete(SYM_COMMON, sym->of_data_vis_ce);
+ sym->of_data_vis_ce = NULL;
+ }
+ if (sym->of_data_vis_ce && (sym->visibility & SYM_EXTERN))
+ cur_objfmt->declare_data_delete(SYM_EXTERN, sym->of_data_vis_ce);
xfree(sym);
}
#ifndef YASM_SYMREC_H
#define YASM_SYMREC_H
-/* EXTERN and COMMON are mutually exclusive */
-typedef enum {
- SYM_LOCAL = 0, /* default, local only */
- SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */
- SYM_COMMON = 1 << 1, /* if it's declared COMMON */
- SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */
-} SymVisibility;
-
/*@dependent@*/ symrec *symrec_use(const char *name);
/*@dependent@*/ symrec *symrec_define_equ(const char *name,
/*@keep@*/ expr *e);
section *sect,
/*@dependent@*/ /*@null@*/
bytecode *precbc, int in_table);
-/*@dependent@*/ symrec *symrec_declare(const char *name, SymVisibility vis);
+/*@dependent@*/ symrec *symrec_declare(const char *name, SymVisibility vis,
+ /*@only@*/ /*@null@*/ void *of_data);
/* Get the numeric 32-bit value of a symbol if possible.
* Return value is IF POSSIBLE, not the value.
{
}
+static /*@null@*/ void *
+dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("extern_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("global_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size,
+ /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("common_data_new(\"%s\",", name);
+ expr_print(size);
+ printf(")\n");
+ return size;
+}
+
+static void
+dbg_objfmt_declare_data_delete(/*@unused@*/ SymVisibility vis,
+ /*@unused@*/ /*@only@*/ void *data)
+{
+ printf("declare_data_delete()\n");
+ if (vis == SYM_COMMON)
+ expr_delete(data);
+ else
+ xfree(data);
+}
+
+static int
+dbg_objfmt_directive(const char *name, valparamhead *valparams,
+ /*@null@*/ valparamhead *objext_valparams)
+{
+ valparam *vp;
+
+ printf("directive(\"%s\", valparams:\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(" objext_valparams:\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");
+ }
+
+ return 0; /* dbg format "recognizes" all directives */
+}
+
/* Define objfmt structure -- see objfmt.h for details */
objfmt dbg_objfmt = {
"Trace of all info passed to object format module",
32,
dbg_objfmt_sections_switch,
dbg_objfmt_section_data_delete,
- dbg_objfmt_section_data_print
+ dbg_objfmt_section_data_print,
+ dbg_objfmt_extern_data_new,
+ dbg_objfmt_global_data_new,
+ dbg_objfmt_common_data_new,
+ dbg_objfmt_declare_data_delete,
+ dbg_objfmt_directive
};
{
}
+static /*@null@*/ void *
+dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("extern_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("global_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size,
+ /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("common_data_new(\"%s\",", name);
+ expr_print(size);
+ printf(")\n");
+ return size;
+}
+
+static void
+dbg_objfmt_declare_data_delete(/*@unused@*/ SymVisibility vis,
+ /*@unused@*/ /*@only@*/ void *data)
+{
+ printf("declare_data_delete()\n");
+ if (vis == SYM_COMMON)
+ expr_delete(data);
+ else
+ xfree(data);
+}
+
+static int
+dbg_objfmt_directive(const char *name, valparamhead *valparams,
+ /*@null@*/ valparamhead *objext_valparams)
+{
+ valparam *vp;
+
+ printf("directive(\"%s\", valparams:\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(" objext_valparams:\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");
+ }
+
+ return 0; /* dbg format "recognizes" all directives */
+}
+
/* Define objfmt structure -- see objfmt.h for details */
objfmt dbg_objfmt = {
"Trace of all info passed to object format module",
32,
dbg_objfmt_sections_switch,
dbg_objfmt_section_data_delete,
- dbg_objfmt_section_data_print
+ dbg_objfmt_section_data_print,
+ dbg_objfmt_extern_data_new,
+ dbg_objfmt_global_data_new,
+ dbg_objfmt_common_data_new,
+ dbg_objfmt_declare_data_delete,
+ dbg_objfmt_directive
};
}
;
-directive_valparam: ID { vp_new($$, $1, NULL); }
- | direxpr { vp_new($$, NULL, $1); }
+directive_valparam: direxpr {
+ /* If direxpr is just an ID, put it in val and delete the expr */
+ const /*@null@*/ symrec *vp_symrec;
+ if ((vp_symrec = expr_get_symrec(&$1, 0))) {
+ vp_new($$, xstrdup(symrec_get_name(vp_symrec)), NULL);
+ expr_delete($1);
+ } else
+ vp_new($$, NULL, $1);
+ }
| ID '=' direxpr { vp_new($$, $1, $3); }
;
/* expr w/o FLTNUM and unary + and -, for use in directives */
direxpr: INTNUM { $$ = expr_new_ident(ExprInt($1)); }
+ | ID {
+ $$ = expr_new_ident(ExprSym(symrec_define_label($1, NULL, NULL, 0)));
+ xfree($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); }
nasm_parser_directive(const char *name, valparamhead *valparams,
valparamhead *objext_valparams)
{
- valparam *vp;
+ valparam *vp, *vp2;
const intnum *intn;
long lval;
assert(cur_objfmt != NULL);
- if (strcasecmp(name, "section") == 0) {
+
+ /* Handle (mostly) output-format independent directives here */
+ if (strcasecmp(name, "extern") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_EXTERN,
+ cur_objfmt->extern_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "EXTERN");
+ } else if (strcasecmp(name, "global") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_GLOBAL,
+ cur_objfmt->global_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "GLOBAL");
+ } else if (strcasecmp(name, "common") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val) {
+ vp2 = vps_next(vp);
+ if (!vp2 || (!vp2->val && !vp2->param))
+ Error(_("no size specified in %s declaration"), "COMMON");
+ else {
+ if (vp2->val)
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val,
+ expr_new_ident(ExprSym(symrec_use(vp2->val))),
+ objext_valparams));
+ else if (vp2->param) {
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val, vp2->param,
+ objext_valparams));
+ vp2->param = NULL;
+ }
+ }
+ } else
+ Error(_("invalid argument to [%s]"), "COMMON");
+ } else if (strcasecmp(name, "section") == 0 ||
+ strcasecmp(name, "segment") == 0) {
section *new_section =
cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
objext_valparams);
} else
Error(_("invalid argument to [%s]"), "SECTION");
} else if (strcasecmp(name, "absolute") == 0) {
+ /* it can be just an ID or a complete expression, so handle both. */
vp = vps_first(valparams);
if (vp->val)
nasm_parser_cur_section =
x86_mode_bits = (unsigned char)lval;
else
Error(_("invalid argument to [%s]"), "BITS");
- } else {
+ } else if (cur_objfmt->directive(name, valparams, objext_valparams)) {
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);
}
;
-directive_valparam: ID { vp_new($$, $1, NULL); }
- | direxpr { vp_new($$, NULL, $1); }
+directive_valparam: direxpr {
+ /* If direxpr is just an ID, put it in val and delete the expr */
+ const /*@null@*/ symrec *vp_symrec;
+ if ((vp_symrec = expr_get_symrec(&$1, 0))) {
+ vp_new($$, xstrdup(symrec_get_name(vp_symrec)), NULL);
+ expr_delete($1);
+ } else
+ vp_new($$, NULL, $1);
+ }
| ID '=' direxpr { vp_new($$, $1, $3); }
;
/* expr w/o FLTNUM and unary + and -, for use in directives */
direxpr: INTNUM { $$ = expr_new_ident(ExprInt($1)); }
+ | ID {
+ $$ = expr_new_ident(ExprSym(symrec_define_label($1, NULL, NULL, 0)));
+ xfree($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); }
nasm_parser_directive(const char *name, valparamhead *valparams,
valparamhead *objext_valparams)
{
- valparam *vp;
+ valparam *vp, *vp2;
const intnum *intn;
long lval;
assert(cur_objfmt != NULL);
- if (strcasecmp(name, "section") == 0) {
+
+ /* Handle (mostly) output-format independent directives here */
+ if (strcasecmp(name, "extern") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_EXTERN,
+ cur_objfmt->extern_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "EXTERN");
+ } else if (strcasecmp(name, "global") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_GLOBAL,
+ cur_objfmt->global_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "GLOBAL");
+ } else if (strcasecmp(name, "common") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val) {
+ vp2 = vps_next(vp);
+ if (!vp2 || (!vp2->val && !vp2->param))
+ Error(_("no size specified in %s declaration"), "COMMON");
+ else {
+ if (vp2->val)
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val,
+ expr_new_ident(ExprSym(symrec_use(vp2->val))),
+ objext_valparams));
+ else if (vp2->param) {
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val, vp2->param,
+ objext_valparams));
+ vp2->param = NULL;
+ }
+ }
+ } else
+ Error(_("invalid argument to [%s]"), "COMMON");
+ } else if (strcasecmp(name, "section") == 0 ||
+ strcasecmp(name, "segment") == 0) {
section *new_section =
cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
objext_valparams);
} else
Error(_("invalid argument to [%s]"), "SECTION");
} else if (strcasecmp(name, "absolute") == 0) {
+ /* it can be just an ID or a complete expression, so handle both. */
vp = vps_first(valparams);
if (vp->val)
nasm_parser_cur_section =
x86_mode_bits = (unsigned char)lval;
else
Error(_("invalid argument to [%s]"), "BITS");
- } else {
+ } else if (cur_objfmt->directive(name, valparams, objext_valparams)) {
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);
EXPR_IDENT /* no operation, just a value */
} ExprOp;
+/* EXTERN and COMMON are mutually exclusive */
+typedef enum {
+ SYM_LOCAL = 0, /* default, local only */
+ SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */
+ SYM_COMMON = 1 << 1, /* if it's declared COMMON */
+ SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */
+} SymVisibility;
+
#endif
void (*section_data_delete)(/*@only@*/ void *data);
void (*section_data_print)(void *data);
+
+ /*@null@*/ void *(*extern_data_new)(const char *name, /*@null@*/
+ valparamhead *objext_valparams);
+ /*@null@*/ void *(*global_data_new)(const char *name, /*@null@*/
+ valparamhead *objext_valparams);
+ /*@null@*/ void *(*common_data_new)(const char *name,
+ /*@only@*/ expr *size, /*@null@*/
+ valparamhead *objext_valparams);
+
+ /* It's only valid to pass this *one* SymVisibility (eg, vis is an enum not
+ * a bitmask).
+ */
+ void (*declare_data_delete)(SymVisibility vis, /*@only@*/ void *data);
+
+ /* Object format-specific directive support. Returns 1 if directive was
+ * not recognized. Returns 0 if directive was recognized, even if it
+ * wasn't valid.
+ */
+ int (*directive)(const char *name, valparamhead *valparams,
+ /*@null@*/ valparamhead *objext_valparams);
};
/* Generic functions for all object formats - implemented in src/objfmt.c */
{
}
+static /*@null@*/ void *
+dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("extern_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("global_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size,
+ /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("common_data_new(\"%s\",", name);
+ expr_print(size);
+ printf(")\n");
+ return size;
+}
+
+static void
+dbg_objfmt_declare_data_delete(/*@unused@*/ SymVisibility vis,
+ /*@unused@*/ /*@only@*/ void *data)
+{
+ printf("declare_data_delete()\n");
+ if (vis == SYM_COMMON)
+ expr_delete(data);
+ else
+ xfree(data);
+}
+
+static int
+dbg_objfmt_directive(const char *name, valparamhead *valparams,
+ /*@null@*/ valparamhead *objext_valparams)
+{
+ valparam *vp;
+
+ printf("directive(\"%s\", valparams:\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(" objext_valparams:\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");
+ }
+
+ return 0; /* dbg format "recognizes" all directives */
+}
+
/* Define objfmt structure -- see objfmt.h for details */
objfmt dbg_objfmt = {
"Trace of all info passed to object format module",
32,
dbg_objfmt_sections_switch,
dbg_objfmt_section_data_delete,
- dbg_objfmt_section_data_print
+ dbg_objfmt_section_data_print,
+ dbg_objfmt_extern_data_new,
+ dbg_objfmt_global_data_new,
+ dbg_objfmt_common_data_new,
+ dbg_objfmt_declare_data_delete,
+ dbg_objfmt_directive
};
{
}
+static /*@null@*/ void *
+dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("extern_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("global_data_new(\"%s\")\n", name);
+ return NULL;
+}
+
+static /*@null@*/ void *
+dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size,
+ /*@unused@*/ /*@null@*/
+ valparamhead *objext_valparams)
+{
+ printf("common_data_new(\"%s\",", name);
+ expr_print(size);
+ printf(")\n");
+ return size;
+}
+
+static void
+dbg_objfmt_declare_data_delete(/*@unused@*/ SymVisibility vis,
+ /*@unused@*/ /*@only@*/ void *data)
+{
+ printf("declare_data_delete()\n");
+ if (vis == SYM_COMMON)
+ expr_delete(data);
+ else
+ xfree(data);
+}
+
+static int
+dbg_objfmt_directive(const char *name, valparamhead *valparams,
+ /*@null@*/ valparamhead *objext_valparams)
+{
+ valparam *vp;
+
+ printf("directive(\"%s\", valparams:\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(" objext_valparams:\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");
+ }
+
+ return 0; /* dbg format "recognizes" all directives */
+}
+
/* Define objfmt structure -- see objfmt.h for details */
objfmt dbg_objfmt = {
"Trace of all info passed to object format module",
32,
dbg_objfmt_sections_switch,
dbg_objfmt_section_data_delete,
- dbg_objfmt_section_data_print
+ dbg_objfmt_section_data_print,
+ dbg_objfmt_extern_data_new,
+ dbg_objfmt_global_data_new,
+ dbg_objfmt_common_data_new,
+ dbg_objfmt_declare_data_delete,
+ dbg_objfmt_directive
};
}
;
-directive_valparam: ID { vp_new($$, $1, NULL); }
- | direxpr { vp_new($$, NULL, $1); }
+directive_valparam: direxpr {
+ /* If direxpr is just an ID, put it in val and delete the expr */
+ const /*@null@*/ symrec *vp_symrec;
+ if ((vp_symrec = expr_get_symrec(&$1, 0))) {
+ vp_new($$, xstrdup(symrec_get_name(vp_symrec)), NULL);
+ expr_delete($1);
+ } else
+ vp_new($$, NULL, $1);
+ }
| ID '=' direxpr { vp_new($$, $1, $3); }
;
/* expr w/o FLTNUM and unary + and -, for use in directives */
direxpr: INTNUM { $$ = expr_new_ident(ExprInt($1)); }
+ | ID {
+ $$ = expr_new_ident(ExprSym(symrec_define_label($1, NULL, NULL, 0)));
+ xfree($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); }
nasm_parser_directive(const char *name, valparamhead *valparams,
valparamhead *objext_valparams)
{
- valparam *vp;
+ valparam *vp, *vp2;
const intnum *intn;
long lval;
assert(cur_objfmt != NULL);
- if (strcasecmp(name, "section") == 0) {
+
+ /* Handle (mostly) output-format independent directives here */
+ if (strcasecmp(name, "extern") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_EXTERN,
+ cur_objfmt->extern_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "EXTERN");
+ } else if (strcasecmp(name, "global") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_GLOBAL,
+ cur_objfmt->global_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "GLOBAL");
+ } else if (strcasecmp(name, "common") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val) {
+ vp2 = vps_next(vp);
+ if (!vp2 || (!vp2->val && !vp2->param))
+ Error(_("no size specified in %s declaration"), "COMMON");
+ else {
+ if (vp2->val)
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val,
+ expr_new_ident(ExprSym(symrec_use(vp2->val))),
+ objext_valparams));
+ else if (vp2->param) {
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val, vp2->param,
+ objext_valparams));
+ vp2->param = NULL;
+ }
+ }
+ } else
+ Error(_("invalid argument to [%s]"), "COMMON");
+ } else if (strcasecmp(name, "section") == 0 ||
+ strcasecmp(name, "segment") == 0) {
section *new_section =
cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
objext_valparams);
} else
Error(_("invalid argument to [%s]"), "SECTION");
} else if (strcasecmp(name, "absolute") == 0) {
+ /* it can be just an ID or a complete expression, so handle both. */
vp = vps_first(valparams);
if (vp->val)
nasm_parser_cur_section =
x86_mode_bits = (unsigned char)lval;
else
Error(_("invalid argument to [%s]"), "BITS");
- } else {
+ } else if (cur_objfmt->directive(name, valparams, objext_valparams)) {
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);
}
;
-directive_valparam: ID { vp_new($$, $1, NULL); }
- | direxpr { vp_new($$, NULL, $1); }
+directive_valparam: direxpr {
+ /* If direxpr is just an ID, put it in val and delete the expr */
+ const /*@null@*/ symrec *vp_symrec;
+ if ((vp_symrec = expr_get_symrec(&$1, 0))) {
+ vp_new($$, xstrdup(symrec_get_name(vp_symrec)), NULL);
+ expr_delete($1);
+ } else
+ vp_new($$, NULL, $1);
+ }
| ID '=' direxpr { vp_new($$, $1, $3); }
;
/* expr w/o FLTNUM and unary + and -, for use in directives */
direxpr: INTNUM { $$ = expr_new_ident(ExprInt($1)); }
+ | ID {
+ $$ = expr_new_ident(ExprSym(symrec_define_label($1, NULL, NULL, 0)));
+ xfree($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); }
nasm_parser_directive(const char *name, valparamhead *valparams,
valparamhead *objext_valparams)
{
- valparam *vp;
+ valparam *vp, *vp2;
const intnum *intn;
long lval;
assert(cur_objfmt != NULL);
- if (strcasecmp(name, "section") == 0) {
+
+ /* Handle (mostly) output-format independent directives here */
+ if (strcasecmp(name, "extern") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_EXTERN,
+ cur_objfmt->extern_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "EXTERN");
+ } else if (strcasecmp(name, "global") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val)
+ symrec_declare(vp->val, SYM_GLOBAL,
+ cur_objfmt->global_data_new(vp->val,
+ objext_valparams));
+ else
+ Error(_("invalid argument to [%s]"), "GLOBAL");
+ } else if (strcasecmp(name, "common") == 0) {
+ vp = vps_first(valparams);
+ if (vp->val) {
+ vp2 = vps_next(vp);
+ if (!vp2 || (!vp2->val && !vp2->param))
+ Error(_("no size specified in %s declaration"), "COMMON");
+ else {
+ if (vp2->val)
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val,
+ expr_new_ident(ExprSym(symrec_use(vp2->val))),
+ objext_valparams));
+ else if (vp2->param) {
+ symrec_declare(vp->val, SYM_COMMON,
+ cur_objfmt->common_data_new(vp->val, vp2->param,
+ objext_valparams));
+ vp2->param = NULL;
+ }
+ }
+ } else
+ Error(_("invalid argument to [%s]"), "COMMON");
+ } else if (strcasecmp(name, "section") == 0 ||
+ strcasecmp(name, "segment") == 0) {
section *new_section =
cur_objfmt->sections_switch(&nasm_parser_sections, valparams,
objext_valparams);
} else
Error(_("invalid argument to [%s]"), "SECTION");
} else if (strcasecmp(name, "absolute") == 0) {
+ /* it can be just an ID or a complete expression, so handle both. */
vp = vps_first(valparams);
if (vp->val)
nasm_parser_cur_section =
x86_mode_bits = (unsigned char)lval;
else
Error(_("invalid argument to [%s]"), "BITS");
- } else {
+ } else if (cur_objfmt->directive(name, valparams, objext_valparams)) {
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);
#include "bytecode.h"
#include "section.h"
+#include "objfmt.h"
/* DEFINED is set with EXTERN and COMMON below */
/*@dependent@*/ /*@null@*/ bytecode *bc;
} label;
} value;
+
+ /* objfmt-specific data (related to visibility, so common/extern share
+ * a pointer, and global has its own pointer).
+ */
+ /*@null@*/ /*@owned@*/ void *of_data_vis_ce;
+ /*@null@*/ /*@owned@*/ void *of_data_vis_g;
};
/* The symbol table: a ternary tree. */
rec->filename = in_filename;
rec->line = line_number;
rec->visibility = SYM_LOCAL;
+ rec->of_data_vis_ce = NULL;
+ rec->of_data_vis_g = NULL;
/*@-freshtrans -mustfree@*/
return rec;
}
symrec *
-symrec_declare(const char *name, SymVisibility vis)
+symrec_declare(const char *name, SymVisibility vis, void *of_data)
{
symrec *rec = symrec_get_or_new(name, 1);
+ assert(cur_objfmt != NULL);
+
/* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */
/* Also, EXTERN and COMMON are mutually exclusive. */
if (((rec->status & SYM_DEFINED) && !(rec->visibility & SYM_EXTERN)) ||
((rec->visibility & SYM_EXTERN) && (vis == SYM_COMMON))) {
Error(_("duplicate definition of `%s'; first defined on line %d"),
name, rec->line);
+ if (of_data)
+ cur_objfmt->declare_data_delete(vis, of_data);
} else {
rec->line = line_number; /* set line number of declaration */
rec->visibility |= vis;
/* If declared as COMMON or EXTERN, set as DEFINED. */
if ((vis == SYM_COMMON) || (vis == SYM_EXTERN))
rec->status |= SYM_DEFINED;
+
+ if (of_data) {
+ switch (vis) {
+ case SYM_GLOBAL:
+ rec->of_data_vis_g = of_data;
+ break;
+ case SYM_COMMON:
+ case SYM_EXTERN:
+ rec->of_data_vis_ce = of_data;
+ break;
+ default:
+ InternalError(_("Unexpected vis value"));
+ }
+ }
}
return rec;
}
xfree(sym->name);
if (sym->type == SYM_EQU)
expr_delete(sym->value.expn);
+ assert(cur_objfmt != NULL);
+ if (sym->of_data_vis_g && (sym->visibility & SYM_GLOBAL))
+ cur_objfmt->declare_data_delete(SYM_GLOBAL, sym->of_data_vis_g);
+ if (sym->of_data_vis_ce && (sym->visibility & SYM_COMMON)) {
+ cur_objfmt->declare_data_delete(SYM_COMMON, sym->of_data_vis_ce);
+ sym->of_data_vis_ce = NULL;
+ }
+ if (sym->of_data_vis_ce && (sym->visibility & SYM_EXTERN))
+ cur_objfmt->declare_data_delete(SYM_EXTERN, sym->of_data_vis_ce);
xfree(sym);
}
#ifndef YASM_SYMREC_H
#define YASM_SYMREC_H
-/* EXTERN and COMMON are mutually exclusive */
-typedef enum {
- SYM_LOCAL = 0, /* default, local only */
- SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */
- SYM_COMMON = 1 << 1, /* if it's declared COMMON */
- SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */
-} SymVisibility;
-
/*@dependent@*/ symrec *symrec_use(const char *name);
/*@dependent@*/ symrec *symrec_define_equ(const char *name,
/*@keep@*/ expr *e);
section *sect,
/*@dependent@*/ /*@null@*/
bytecode *precbc, int in_table);
-/*@dependent@*/ symrec *symrec_declare(const char *name, SymVisibility vis);
+/*@dependent@*/ symrec *symrec_declare(const char *name, SymVisibility vis,
+ /*@only@*/ /*@null@*/ void *of_data);
/* Get the numeric 32-bit value of a symbol if possible.
* Return value is IF POSSIBLE, not the value.