diff options
-rw-r--r-- | labels.c | 40 | ||||
-rw-r--r-- | nasm.c | 111 |
2 files changed, 81 insertions, 70 deletions
@@ -47,9 +47,10 @@ #endif /* values for label.defn.is_global */ -#define DEFINED_BIT 1 -#define GLOBAL_BIT 2 -#define EXTERN_BIT 4 +#define DEFINED_BIT 1 +#define GLOBAL_BIT 2 +#define EXTERN_BIT 4 +#define COMMON_BIT 8 #define NOT_DEFINED_YET 0 #define TYPE_MASK 3 @@ -209,7 +210,9 @@ void redefine_label(char *label, int32_t segment, int64_t offset, char *special, prevlabel = lptr->defn.label; } - if (lptr->defn.offset != offset) global_offset_changed++; + if (lptr->defn.offset != offset) + global_offset_changed++; + lptr->defn.offset = offset; lptr->defn.segment = segment; @@ -270,9 +273,10 @@ void define_label(char *label, int32_t segment, int64_t offset, char *special, if (isextrn) lptr->defn.is_global |= EXTERN_BIT; - if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */ + if (!islocalchar(label[0]) && is_norm) { + /* not local, but not special either */ prevlabel = lptr->defn.label; - else if (islocal(label) && !*prevlabel) { + } else if (islocal(label) && !*prevlabel) { error(ERR_NONFATAL, "attempt to define a local label before any" " non-local labels"); } @@ -321,26 +325,32 @@ void define_common(char *label, int32_t segment, int32_t size, char *special, union label *lptr; lptr = find_label(label, 1); - if (lptr->defn.is_global & DEFINED_BIT) { - error(ERR_NONFATAL, "symbol `%s' redefined", label); - return; + if ((lptr->defn.is_global & DEFINED_BIT) && + (passn == 1 || !(lptr->defn.is_global & COMMON_BIT))) { + error(ERR_NONFATAL, "symbol `%s' redefined", label); + return; } - lptr->defn.is_global |= DEFINED_BIT; + lptr->defn.is_global |= DEFINED_BIT|COMMON_BIT; - if (!islocalchar(label[0])) /* not local, but not special either */ + if (!islocalchar(label[0])) { prevlabel = lptr->defn.label; - else + } else { error(ERR_NONFATAL, "attempt to define a local label as a " "common variable"); + return; + } lptr->defn.segment = segment; lptr->defn.offset = 0; + if (pass0 == 0) + return; + ofmt->symdef(lptr->defn.label, segment, size, 2, - special ? special : lptr->defn.special); + special ? special : lptr->defn.special); ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2, - special ? special : lptr->defn. - special); + special ? special : lptr->defn. + special); } void declare_as_global(char *label, char *special, efunc error) @@ -1189,8 +1189,10 @@ static void assemble_file(char *fname, StrList **depend_ptr) enum directives d; globallineno++; - /* here we parse our directives; this is not handled by the 'real' - * parser. */ + /* + * Here we parse our directives; this is not handled by the + * 'real' parser. This really should be a separate function. + */ directive = line; d = getkw(&directive, &value); if (d) { @@ -1289,61 +1291,59 @@ static void assemble_file(char *fname, StrList **depend_ptr) } /* pass == 1 */ break; case D_COMMON: /* [COMMON symbol size:special] */ + { + int64_t size; + if (*value == '$') value++; /* skip initial $ if present */ - if (pass0 == 1) { - p = value; - validid = true; - if (!isidstart(*p)) - validid = false; - while (*p && !nasm_isspace(*p)) { - if (!isidchar(*p)) - validid = false; - p++; - } - if (!validid) { - report_error(ERR_NONFATAL, - "identifier expected after COMMON"); - break; - } - if (*p) { - int64_t size; - - while (*p && nasm_isspace(*p)) - *p++ = '\0'; - q = p; - while (*q && *q != ':') - q++; - if (*q == ':') { - *q++ = '\0'; - special = q; - } else - special = NULL; - size = readnum(p, &rn_error); - if (rn_error) - report_error(ERR_NONFATAL, - "invalid size specified" - " in COMMON declaration"); - else - define_common(value, seg_alloc(), size, - special, ofmt, report_error); - } else - report_error(ERR_NONFATAL, - "no size specified in" - " COMMON declaration"); - } else if (pass0 == 2) { /* pass == 2 */ - q = value; - while (*q && *q != ':') { - if (nasm_isspace(*q)) - *q = '\0'; - q++; - } - if (*q == ':') { - *q++ = '\0'; - ofmt->symdef(value, 0L, 0L, 3, q); - } + p = value; + validid = true; + if (!isidstart(*p)) + validid = false; + while (*p && !nasm_isspace(*p)) { + if (!isidchar(*p)) + validid = false; + p++; + } + if (!validid) { + report_error(ERR_NONFATAL, + "identifier expected after COMMON"); + break; + } + if (*p) { + while (*p && nasm_isspace(*p)) + *p++ = '\0'; + q = p; + while (*q && *q != ':') + q++; + if (*q == ':') { + *q++ = '\0'; + special = q; + } else { + special = NULL; + } + size = readnum(p, &rn_error); + if (rn_error) { + report_error(ERR_NONFATAL, + "invalid size specified" + " in COMMON declaration"); + break; + } + } else { + report_error(ERR_NONFATAL, + "no size specified in" + " COMMON declaration"); + break; + } + + if (pass0 < 2) { + define_common(value, seg_alloc(), size, + special, ofmt, report_error); + } else if (pass0 == 2) { + ofmt->symdef(value, 0L, 0L, 3, special); } break; + } case D_ABSOLUTE: /* [ABSOLUTE address] */ stdscan_reset(); stdscan_bufptr = value; @@ -1690,9 +1690,10 @@ static void assemble_file(char *fname, StrList **depend_ptr) nasm_free(line); location.offset = offs = GET_CURR_OFFS; } /* end while (line = preproc->getline... */ - if (pass1 == 2 && global_offset_changed) + + if (pass0 && global_offset_changed) report_error(ERR_NONFATAL, - "phase error detected at end of assembly."); + "phase error detected at end of assembly."); if (pass1 == 1) preproc->cleanup(1); |