summaryrefslogtreecommitdiff
path: root/labels.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-04-30 21:00:33 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-04-30 21:00:33 +0000
commit1cd0e2d5bf50b2cc482cad7beb8f7dee6a81d57b (patch)
tree53de3660be58d806d9de78394b44e95b9e80a55c /labels.c
parentaf535c16cf3f9f628384ec834e3aa325709cb37b (diff)
downloadnasm-1cd0e2d5bf50b2cc482cad7beb8f7dee6a81d57b.tar.gz
nasm-1cd0e2d5bf50b2cc482cad7beb8f7dee6a81d57b.tar.bz2
nasm-1cd0e2d5bf50b2cc482cad7beb8f7dee6a81d57b.zip
NASM 0.98.08
Diffstat (limited to 'labels.c')
-rw-r--r--labels.c110
1 files changed, 92 insertions, 18 deletions
diff --git a/labels.c b/labels.c
index c47d34c..f137847 100644
--- a/labels.c
+++ b/labels.c
@@ -15,8 +15,24 @@
/*
* A local label is one that begins with exactly one period. Things
* that begin with _two_ periods are NASM-specific things.
+ *
+ * If TASM compatibility is enabled, a local label can also begin with
+ * @@, so @@local is a TASM compatible local label. Note that we only
+ * check for the first @ symbol, although TASM requires both.
*/
+#ifdef TASM_COMPAT
+#define islocal(l) \
+ (tasm_compatible_mode ? \
+ (((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \
+ ((l)[0] == '.' && (l)[1] != '.'))
+#define islocalchar(c) \
+ (tasm_compatible_mode ? \
+ ((c) == '.' || (c) == '@') : \
+ ((c) == '.'))
+#else
#define islocal(l) ((l)[0] == '.' && (l)[1] != '.')
+#define islocalchar(c) ((c) == '.')
+#endif
#define LABEL_BLOCK 32 /* no. of labels/block */
#define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
@@ -71,6 +87,9 @@ static char *prevlabel;
static int initialised = FALSE;
+char lprefix[PREFIX_MAX] = {0};
+char lpostfix[PREFIX_MAX] = {0};
+
/*
* Internal routine: finds the `union label' corresponding to the
* given label name. Creates a new one, if it isn't found, and if
@@ -160,7 +179,8 @@ void redefine_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
-
+ int exi;
+
/* This routine possibly ought to check for phase errors. Most assemblers
* check for phase errors at this point. I don't know whether phase errors
* are even possible, nor whether they are checked somewhere else
@@ -185,18 +205,50 @@ void redefine_label (char *label, long segment, long offset, char *special,
error (ERR_PANIC, "can't find label `%s' on pass two", label);
if (!islocal(label)) {
- if (*label != '.' && lptr->defn.is_norm)
+ if (!islocalchar(*label) && lptr->defn.is_norm)
prevlabel = lptr->defn.label;
}
global_offset_changed |= (lptr->defn.offset != offset);
lptr->defn.offset = offset;
+
+if (pass0 == 1) {
+ exi = !!(lptr->defn.is_global & GLOBAL_BIT);
+ if (exi)
+ {
+ char *xsymbol;
+ int slen;
+ slen = strlen(lprefix);
+ slen += strlen(lptr->defn.label);
+ slen += strlen(lpostfix);
+ slen++; /* room for that null char */
+ xsymbol = nasm_malloc(slen);
+ sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
+
+ ofmt->symdef (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
+ }
+ else
+ {
+ if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
+ ofmt->symdef (lptr->defn.label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ }
+ }
+} /* if (pass0 == 1) */
+
}
void define_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
+ int exi;
#ifdef DEBUG
#if DEBUG<3
@@ -212,26 +264,48 @@ void define_label (char *label, long segment, long offset, char *special,
}
lptr->defn.is_global |= DEFINED_BIT;
if (isextrn)
- lptr->defn.is_global |= EXTERN_BIT;
+ lptr->defn.is_global |= EXTERN_BIT;
- if (label[0] != '.' && is_norm) /* not local, but not special either */
- prevlabel = lptr->defn.label;
- else if (label[0] == '.' && label[1] != '.' && !*prevlabel)
- error(ERR_NONFATAL, "attempt to define a local label before any"
- " non-local labels");
+ if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */
+ prevlabel = lptr->defn.label;
+ else if (islocal(label) && !*prevlabel) {
+ error(ERR_NONFATAL, "attempt to define a local label before any"
+ " non-local labels");
+ }
lptr->defn.segment = segment;
lptr->defn.offset = offset;
- lptr->defn.is_norm = (label[0] != '.' && is_norm);
-
- if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
- ofmt->symdef (lptr->defn.label, segment, offset,
- !!(lptr->defn.is_global & GLOBAL_BIT),
- special ? special : lptr->defn.special);
- ofmt->current_dfmt->debug_deflabel (label, segment, offset,
- !!(lptr->defn.is_global & GLOBAL_BIT),
- special ? special : lptr->defn.special);
+ lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm);
+
+if (pass0 == 1 || (!is_norm && !isextrn && (segment&1))) {
+ exi = !!(lptr->defn.is_global & GLOBAL_BIT);
+ if (exi)
+ {
+ char *xsymbol;
+ int slen;
+ slen = strlen(lprefix);
+ slen += strlen(lptr->defn.label);
+ slen += strlen(lpostfix);
+ slen++; /* room for that null char */
+ xsymbol = nasm_malloc(slen);
+ sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
+
+ ofmt->symdef (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
+ }
+ else
+ {
+ if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
+ ofmt->symdef (lptr->defn.label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ }
}
+} /* if (pass0 == 1) */
}
void define_common (char *label, long segment, long size, char *special,
@@ -246,7 +320,7 @@ void define_common (char *label, long segment, long size, char *special,
}
lptr->defn.is_global |= DEFINED_BIT;
- if (label[0] != '.') /* not local, but not special either */
+ if (!islocalchar(label[0])) /* not local, but not special either */
prevlabel = lptr->defn.label;
else
error(ERR_NONFATAL, "attempt to define a local label as a "