Polish up most directive support. This necessitated adding objfmt-specific

data pointers to symrec for extern/common/etc.  Also fixed parsing of direxpr;
it didn't allow exprs with ID's before.

svn path=/trunk/yasm/; revision=356
0.3
Peter Johnson 23 years ago
parent ac655d6bc6
commit b930d117d3
  1. 8
      libyasm/coretype.h
  2. 20
      libyasm/objfmt.h
  3. 38
      libyasm/symrec.c
  4. 11
      libyasm/symrec.h
  5. 76
      modules/objfmts/dbg/dbg-objfmt.c
  6. 76
      modules/objfmts/dbg/objfmt.c
  7. 85
      modules/parsers/nasm/bison.y.in
  8. 85
      modules/parsers/nasm/nasm-bison.y
  9. 8
      src/coretype.h
  10. 20
      src/objfmt.h
  11. 76
      src/objfmts/dbg/dbg-objfmt.c
  12. 76
      src/objfmts/dbg/objfmt.c
  13. 85
      src/parsers/nasm/bison.y.in
  14. 85
      src/parsers/nasm/nasm-bison.y
  15. 38
      src/symrec.c
  16. 11
      src/symrec.h

@ -68,4 +68,12 @@ typedef enum {
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

@ -55,6 +55,26 @@ struct objfmt {
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 */

@ -37,6 +37,7 @@
#include "bytecode.h"
#include "section.h"
#include "objfmt.h"
/* DEFINED is set with EXTERN and COMMON below */
@ -68,6 +69,12 @@ struct symrec {
/*@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. */
@ -96,6 +103,8 @@ symrec_get_or_new(const char *name, int in_table)
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;
@ -156,10 +165,12 @@ symrec_define_label(const char *name, section *sect, bytecode *precbc,
}
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)) ||
@ -167,6 +178,8 @@ symrec_declare(const char *name, SymVisibility vis)
((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;
@ -174,6 +187,20 @@ symrec_declare(const char *name, SymVisibility 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;
}
@ -269,6 +296,15 @@ symrec_delete_one(/*@only@*/ void *d)
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);
}

@ -22,14 +22,6 @@
#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);
@ -39,7 +31,8 @@ typedef enum {
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.

@ -82,6 +82,75 @@ dbg_objfmt_section_data_print(/*@unused@*/ void *data)
{
}
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",
@ -90,5 +159,10 @@ objfmt dbg_objfmt = {
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
};

@ -82,6 +82,75 @@ dbg_objfmt_section_data_print(/*@unused@*/ void *data)
{
}
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",
@ -90,5 +159,10 @@ objfmt dbg_objfmt = {
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
};

@ -235,8 +235,15 @@ directive_valparams: directive_valparam {
}
;
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); }
;
@ -480,6 +487,10 @@ target: expr {
/* 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); }
@ -605,12 +616,52 @@ static void
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);
@ -620,6 +671,7 @@ nasm_parser_directive(const char *name, valparamhead *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 =
@ -638,31 +690,8 @@ nasm_parser_directive(const char *name, valparamhead *valparams,
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);

@ -235,8 +235,15 @@ directive_valparams: directive_valparam {
}
;
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); }
;
@ -480,6 +487,10 @@ target: expr {
/* 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); }
@ -605,12 +616,52 @@ static void
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);
@ -620,6 +671,7 @@ nasm_parser_directive(const char *name, valparamhead *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 =
@ -638,31 +690,8 @@ nasm_parser_directive(const char *name, valparamhead *valparams,
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);

@ -68,4 +68,12 @@ typedef enum {
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

@ -55,6 +55,26 @@ struct objfmt {
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 */

@ -82,6 +82,75 @@ dbg_objfmt_section_data_print(/*@unused@*/ void *data)
{
}
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",
@ -90,5 +159,10 @@ objfmt dbg_objfmt = {
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
};

@ -82,6 +82,75 @@ dbg_objfmt_section_data_print(/*@unused@*/ void *data)
{
}
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",
@ -90,5 +159,10 @@ objfmt dbg_objfmt = {
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
};

@ -235,8 +235,15 @@ directive_valparams: directive_valparam {
}
;
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); }
;
@ -480,6 +487,10 @@ target: expr {
/* 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); }
@ -605,12 +616,52 @@ static void
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);
@ -620,6 +671,7 @@ nasm_parser_directive(const char *name, valparamhead *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 =
@ -638,31 +690,8 @@ nasm_parser_directive(const char *name, valparamhead *valparams,
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);

@ -235,8 +235,15 @@ directive_valparams: directive_valparam {
}
;
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); }
;
@ -480,6 +487,10 @@ target: expr {
/* 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); }
@ -605,12 +616,52 @@ static void
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);
@ -620,6 +671,7 @@ nasm_parser_directive(const char *name, valparamhead *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 =
@ -638,31 +690,8 @@ nasm_parser_directive(const char *name, valparamhead *valparams,
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);

@ -37,6 +37,7 @@
#include "bytecode.h"
#include "section.h"
#include "objfmt.h"
/* DEFINED is set with EXTERN and COMMON below */
@ -68,6 +69,12 @@ struct symrec {
/*@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. */
@ -96,6 +103,8 @@ symrec_get_or_new(const char *name, int in_table)
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;
@ -156,10 +165,12 @@ symrec_define_label(const char *name, section *sect, bytecode *precbc,
}
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)) ||
@ -167,6 +178,8 @@ symrec_declare(const char *name, SymVisibility vis)
((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;
@ -174,6 +187,20 @@ symrec_declare(const char *name, SymVisibility 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;
}
@ -269,6 +296,15 @@ symrec_delete_one(/*@only@*/ void *d)
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);
}

@ -22,14 +22,6 @@
#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);
@ -39,7 +31,8 @@ typedef enum {
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.

Loading…
Cancel
Save