]> granicus.if.org Git - yasm/commitdiff
Polish up most directive support. This necessitated adding objfmt-specific
authorPeter Johnson <peter@tortall.net>
Wed, 21 Nov 2001 03:17:43 +0000 (03:17 -0000)
committerPeter Johnson <peter@tortall.net>
Wed, 21 Nov 2001 03:17:43 +0000 (03:17 -0000)
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

16 files changed:
libyasm/coretype.h
libyasm/objfmt.h
libyasm/symrec.c
libyasm/symrec.h
modules/objfmts/dbg/dbg-objfmt.c
modules/objfmts/dbg/objfmt.c
modules/parsers/nasm/bison.y.in
modules/parsers/nasm/nasm-bison.y
src/coretype.h
src/objfmt.h
src/objfmts/dbg/dbg-objfmt.c
src/objfmts/dbg/objfmt.c
src/parsers/nasm/bison.y.in
src/parsers/nasm/nasm-bison.y
src/symrec.c
src/symrec.h

index 3ce0bff3cef05dd48e794c0661cb64c521f35de8..0389d7eec3f703f70e37f78ffdbdfd8d627aed5e 100644 (file)
@@ -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
index e484dbd87bb764a3f3c1f1a3ba937d2e936938e4..7b36c157eddde1547f054291df3b4081a76491f6 100644 (file)
@@ -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 */
index c426f5f436645211aaf8675f64758bcb70368c8b..70a611d5446384001bcd89ea5842bd23b788b87c 100644 (file)
@@ -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);
 }
 
index 8946275bb4c5a5ee7beeddad8126a8e5997c4cba..2d2c149732820eae86a8a34f9a6f01573c6d8723 100644 (file)
 #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.
index 825204ec34b231d4f07c1fc0cc25a29b9e604a1f..ab6a3349ec71b643c55b5d8b91dd4a0bfa4d57c6 100644 (file)
@@ -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
 };
index 825204ec34b231d4f07c1fc0cc25a29b9e604a1f..ab6a3349ec71b643c55b5d8b91dd4a0bfa4d57c6 100644 (file)
@@ -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
 };
index a4aa433e972446b9a33e1d7475543c3ddbc441fb..7ea848160a21de6b2589cac20751d5c991806986 100644 (file)
@@ -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);
index a4aa433e972446b9a33e1d7475543c3ddbc441fb..7ea848160a21de6b2589cac20751d5c991806986 100644 (file)
@@ -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);
index 3ce0bff3cef05dd48e794c0661cb64c521f35de8..0389d7eec3f703f70e37f78ffdbdfd8d627aed5e 100644 (file)
@@ -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
index e484dbd87bb764a3f3c1f1a3ba937d2e936938e4..7b36c157eddde1547f054291df3b4081a76491f6 100644 (file)
@@ -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 */
index 825204ec34b231d4f07c1fc0cc25a29b9e604a1f..ab6a3349ec71b643c55b5d8b91dd4a0bfa4d57c6 100644 (file)
@@ -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
 };
index 825204ec34b231d4f07c1fc0cc25a29b9e604a1f..ab6a3349ec71b643c55b5d8b91dd4a0bfa4d57c6 100644 (file)
@@ -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
 };
index a4aa433e972446b9a33e1d7475543c3ddbc441fb..7ea848160a21de6b2589cac20751d5c991806986 100644 (file)
@@ -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);
index a4aa433e972446b9a33e1d7475543c3ddbc441fb..7ea848160a21de6b2589cac20751d5c991806986 100644 (file)
@@ -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);
index c426f5f436645211aaf8675f64758bcb70368c8b..70a611d5446384001bcd89ea5842bd23b788b87c 100644 (file)
@@ -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);
 }
 
index 8946275bb4c5a5ee7beeddad8126a8e5997c4cba..2d2c149732820eae86a8a34f9a6f01573c6d8723 100644 (file)
 #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.