summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--labels.c40
-rw-r--r--nasm.c111
2 files changed, 81 insertions, 70 deletions
diff --git a/labels.c b/labels.c
index 9a7fc615..49792d28 100644
--- a/labels.c
+++ b/labels.c
@@ -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)
diff --git a/nasm.c b/nasm.c
index 55352153..9d3776af 100644
--- a/nasm.c
+++ b/nasm.c
@@ -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);