summaryrefslogtreecommitdiff
path: root/labels.c
diff options
context:
space:
mode:
Diffstat (limited to 'labels.c')
-rw-r--r--labels.c237
1 files changed, 123 insertions, 114 deletions
diff --git a/labels.c b/labels.c
index 6259986a..c47d34c4 100644
--- a/labels.c
+++ b/labels.c
@@ -18,15 +18,15 @@
*/
#define islocal(l) ((l)[0] == '.' && (l)[1] != '.')
-#define LABEL_BLOCK 320 /* no. of labels/block */
+#define LABEL_BLOCK 32 /* no. of labels/block */
#define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
-#define LABEL_HASHES 32 /* no. of hash table entries */
+#define LABEL_HASHES 37 /* no. of hash table entries */
-#define END_LIST -3 /* don't clash with NO_SEG! */
+#define END_LIST -3 /* don't clash with NO_SEG! */
#define END_BLOCK -2
#define BOGUS_VALUE -4
-#define PERMTS_SIZE 4096 /* size of text blocks */
+#define PERMTS_SIZE 4096 /* size of text blocks */
/* values for label.defn.is_global */
#define DEFINED_BIT 1
@@ -39,24 +39,26 @@
#define GLOBAL_PLACEHOLDER (GLOBAL_BIT)
#define GLOBAL_SYMBOL (DEFINED_BIT|GLOBAL_BIT)
-union label { /* actual label structures */
+union label { /* actual label structures */
struct {
- long segment, offset;
+ long segment, offset;
char *label, *special;
- int is_global, is_norm;
+ int is_global, is_norm;
} defn;
struct {
- long movingon, dummy;
- union label *next;
+ long movingon, dummy;
+ union label *next;
} admin;
};
-struct permts { /* permanent text storage */
- struct permts *next; /* for the linked list */
- int size, usage; /* size and used space in ... */
- char data[PERMTS_SIZE]; /* ... the data block itself */
+struct permts { /* permanent text storage */
+ struct permts *next; /* for the linked list */
+ int size, usage; /* size and used space in ... */
+ char data[PERMTS_SIZE]; /* ... the data block itself */
};
+extern int global_offset_changed; /* defined in nasm.c */
+
static union label *ltab[LABEL_HASHES];/* using a hash table */
static union label *lfree[LABEL_HASHES];/* pointer into the above */
static struct permts *perm_head; /* start of perm. text storage */
@@ -82,9 +84,9 @@ static union label *find_label (char *label, int create)
union label *lptr;
if (islocal(label))
- prev = prevlabel;
+ prev = prevlabel;
else
- prev = "";
+ prev = "";
prevlen = strlen(prev);
p = prev;
while (*p) hash += *p++;
@@ -93,34 +95,34 @@ static union label *find_label (char *label, int create)
hash %= LABEL_HASHES;
lptr = ltab[hash];
while (lptr->admin.movingon != END_LIST) {
- if (lptr->admin.movingon == END_BLOCK) {
- lptr = lptr->admin.next;
- if (!lptr)
- break;
- }
- if (!strncmp(lptr->defn.label, prev, prevlen) &&
- !strcmp(lptr->defn.label+prevlen, label))
- return lptr;
- lptr++;
+ if (lptr->admin.movingon == END_BLOCK) {
+ lptr = lptr->admin.next;
+ if (!lptr)
+ break;
+ }
+ if (!strncmp(lptr->defn.label, prev, prevlen) &&
+ !strcmp(lptr->defn.label+prevlen, label))
+ return lptr;
+ lptr++;
}
if (create) {
- if (lfree[hash]->admin.movingon == END_BLOCK) {
- /*
- * must allocate a new block
- */
- lfree[hash]->admin.next = (union label *) nasm_malloc (LBLK_SIZE);
- lfree[hash] = lfree[hash]->admin.next;
- init_block(lfree[hash]);
- }
-
- lfree[hash]->admin.movingon = BOGUS_VALUE;
- lfree[hash]->defn.label = perm_copy (prev, label);
- lfree[hash]->defn.special = NULL;
- lfree[hash]->defn.is_global = NOT_DEFINED_YET;
- return lfree[hash]++;
+ if (lfree[hash]->admin.movingon == END_BLOCK) {
+ /*
+ * must allocate a new block
+ */
+ lfree[hash]->admin.next = (union label *) nasm_malloc (LBLK_SIZE);
+ lfree[hash] = lfree[hash]->admin.next;
+ init_block(lfree[hash]);
+ }
+
+ lfree[hash]->admin.movingon = BOGUS_VALUE;
+ lfree[hash]->defn.label = perm_copy (prev, label);
+ lfree[hash]->defn.special = NULL;
+ lfree[hash]->defn.is_global = NOT_DEFINED_YET;
+ return lfree[hash]++;
}
else
- return NULL;
+ return NULL;
}
int lookup_label (char *label, long *segment, long *offset)
@@ -128,16 +130,16 @@ int lookup_label (char *label, long *segment, long *offset)
union label *lptr;
if (!initialised)
- return 0;
+ return 0;
lptr = find_label (label, 0);
if (lptr && (lptr->defn.is_global & DEFINED_BIT)) {
- *segment = lptr->defn.segment;
- *offset = lptr->defn.offset;
- return 1;
+ *segment = lptr->defn.segment;
+ *offset = lptr->defn.offset;
+ return 1;
}
else
- return 0;
+ return 0;
}
int is_extern (char *label)
@@ -145,17 +147,17 @@ int is_extern (char *label)
union label *lptr;
if (!initialised)
- return 0;
+ return 0;
lptr = find_label (label, 0);
if (lptr && (lptr->defn.is_global & EXTERN_BIT))
- return 1;
+ return 1;
else
- return 0;
+ return 0;
}
void redefine_label (char *label, long segment, long offset, char *special,
- int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
+ int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
@@ -165,51 +167,58 @@ void redefine_label (char *label, long segment, long offset, char *special,
*/
(void) segment; /* Don't warn that this parameter is unused */
- (void) offset; /* Don't warn that this parameter is unused */
(void) special; /* Don't warn that this parameter is unused */
(void) is_norm; /* Don't warn that this parameter is unused */
(void) isextrn; /* Don't warn that this parameter is unused */
(void) ofmt; /* Don't warn that this parameter is unused */
#ifdef DEBUG
+#if DEBUG<3
if (!strncmp(label, "debugdump", 9))
- fprintf(stderr, "debug: redefine_label (%s, %ld, %08lx, %s, %d, %d)\n",
- label, segment, offset, special, is_norm, isextrn);
+#endif
+ error(ERR_DEBUG, "redefine_label (%s, %ld, %08lx, %s, %d, %d)",
+ label, segment, offset, special, is_norm, isextrn);
#endif
+ lptr = find_label (label, 1);
+ if (!lptr)
+ error (ERR_PANIC, "can't find label `%s' on pass two", label);
+
if (!islocal(label)) {
- lptr = find_label (label, 1);
- if (!lptr)
- error (ERR_PANIC, "can't find label `%s' on pass two", label);
- if (*label != '.' && lptr->defn.is_norm)
- prevlabel = lptr->defn.label;
+ if (*label != '.' && lptr->defn.is_norm)
+ prevlabel = lptr->defn.label;
}
+
+ global_offset_changed |= (lptr->defn.offset != offset);
+ lptr->defn.offset = offset;
}
void define_label (char *label, long segment, long offset, char *special,
- int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
+ int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
#ifdef DEBUG
+#if DEBUG<3
if (!strncmp(label, "debugdump", 9))
- fprintf(stderr, "debug: define_label (%s, %ld, %08lx, %s, %d, %d)\n",
- label, segment, offset, special, is_norm, isextrn);
+#endif
+ error(ERR_DEBUG, "define_label (%s, %ld, %08lx, %s, %d, %d)",
+ label, segment, offset, special, is_norm, isextrn);
#endif
lptr = find_label (label, 1);
if (lptr->defn.is_global & DEFINED_BIT) {
- error(ERR_NONFATAL, "symbol `%s' redefined", label);
- return;
+ error(ERR_NONFATAL, "symbol `%s' redefined", label);
+ return;
}
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;
+ 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");
+ error(ERR_NONFATAL, "attempt to define a local label before any"
+ " non-local labels");
lptr->defn.segment = segment;
lptr->defn.offset = offset;
@@ -217,39 +226,39 @@ void define_label (char *label, long segment, long offset, char *special,
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);
+ !!(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_global & GLOBAL_BIT),
+ special ? special : lptr->defn.special);
}
}
void define_common (char *label, long segment, long size, char *special,
- struct ofmt *ofmt, efunc error)
+ struct ofmt *ofmt, efunc error)
{
union label *lptr;
lptr = find_label (label, 1);
if (lptr->defn.is_global & DEFINED_BIT) {
- error(ERR_NONFATAL, "symbol `%s' redefined", label);
- return;
+ error(ERR_NONFATAL, "symbol `%s' redefined", label);
+ return;
}
lptr->defn.is_global |= DEFINED_BIT;
- if (label[0] != '.') /* not local, but not special either */
- prevlabel = lptr->defn.label;
+ if (label[0] != '.') /* not local, but not special either */
+ prevlabel = lptr->defn.label;
else
- error(ERR_NONFATAL, "attempt to define a local label as a "
- "common variable");
+ error(ERR_NONFATAL, "attempt to define a local label as a "
+ "common variable");
lptr->defn.segment = segment;
lptr->defn.offset = 0;
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)
@@ -257,24 +266,24 @@ void declare_as_global (char *label, char *special, efunc error)
union label *lptr;
if (islocal(label)) {
- error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
- " global", label);
- return;
+ error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
+ " global", label);
+ return;
}
lptr = find_label (label, 1);
switch (lptr->defn.is_global & TYPE_MASK) {
case NOT_DEFINED_YET:
- lptr->defn.is_global = GLOBAL_PLACEHOLDER;
- lptr->defn.special = special ? perm_copy(special, "") : NULL;
- break;
- case GLOBAL_PLACEHOLDER: /* already done: silently ignore */
+ lptr->defn.is_global = GLOBAL_PLACEHOLDER;
+ lptr->defn.special = special ? perm_copy(special, "") : NULL;
+ break;
+ case GLOBAL_PLACEHOLDER: /* already done: silently ignore */
case GLOBAL_SYMBOL:
- break;
+ break;
case LOCAL_SYMBOL:
- if (!lptr->defn.is_global & EXTERN_BIT)
- error(ERR_NONFATAL, "symbol `%s': GLOBAL directive must"
- " appear before symbol definition", label);
- break;
+ if (!lptr->defn.is_global & EXTERN_BIT)
+ error(ERR_NONFATAL, "symbol `%s': GLOBAL directive must"
+ " appear before symbol definition", label);
+ break;
}
}
@@ -283,18 +292,18 @@ int init_labels (void)
int i;
for (i=0; i<LABEL_HASHES; i++) {
- ltab[i] = (union label *) nasm_malloc (LBLK_SIZE);
- if (!ltab[i])
- return -1; /* can't initialise, panic */
- init_block (ltab[i]);
- lfree[i] = ltab[i];
+ ltab[i] = (union label *) nasm_malloc (LBLK_SIZE);
+ if (!ltab[i])
+ return -1; /* can't initialise, panic */
+ init_block (ltab[i]);
+ lfree[i] = ltab[i];
}
perm_head =
- perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
+ perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
if (!perm_head)
- return -1;
+ return -1;
perm_head->next = NULL;
perm_head->size = PERMTS_SIZE;
@@ -314,22 +323,22 @@ void cleanup_labels (void)
initialised = FALSE;
for (i=0; i<LABEL_HASHES; i++) {
- union label *lptr, *lhold;
+ union label *lptr, *lhold;
- lptr = lhold = ltab[i];
+ lptr = lhold = ltab[i];
- while (lptr) {
- while (lptr->admin.movingon != END_BLOCK) lptr++;
- lptr = lptr->admin.next;
- nasm_free (lhold);
- lhold = lptr;
- }
+ while (lptr) {
+ while (lptr->admin.movingon != END_BLOCK) lptr++;
+ lptr = lptr->admin.next;
+ nasm_free (lhold);
+ lhold = lptr;
+ }
}
while (perm_head) {
- perm_tail = perm_head;
- perm_head = perm_head->next;
- nasm_free (perm_tail);
+ perm_tail = perm_head;
+ perm_head = perm_head->next;
+ nasm_free (perm_tail);
}
}
@@ -338,7 +347,7 @@ static void init_block (union label *blk)
int j;
for (j=0; j<LABEL_BLOCK-1; j++)
- blk[j].admin.movingon = END_LIST;
+ blk[j].admin.movingon = END_LIST;
blk[LABEL_BLOCK-1].admin.movingon = END_BLOCK;
blk[LABEL_BLOCK-1].admin.next = NULL;
}
@@ -349,11 +358,11 @@ static char *perm_copy (char *string1, char *string2)
int len = strlen(string1)+strlen(string2)+1;
if (perm_tail->size - perm_tail->usage < len) {
- perm_tail->next = (struct permts *)nasm_malloc(sizeof(struct permts));
- perm_tail = perm_tail->next;
- perm_tail->next = NULL;
- perm_tail->size = PERMTS_SIZE;
- perm_tail->usage = 0;
+ perm_tail->next = (struct permts *)nasm_malloc(sizeof(struct permts));
+ perm_tail = perm_tail->next;
+ perm_tail->next = NULL;
+ perm_tail->size = PERMTS_SIZE;
+ perm_tail->usage = 0;
}
p = q = perm_tail->data + perm_tail->usage;
while ( (*q = *string1++) ) q++;