blob: 833ad843ceb7e5a827f5713b7bf00d53e63211b0 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* labels.c label handling for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 */
8
9#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include "nasm.h"
13#include "nasmlib.h"
14
15/*
16 * A local label is one that begins with exactly one period. Things
17 * that begin with _two_ periods are NASM-specific things.
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000018 *
19 * If TASM compatibility is enabled, a local label can also begin with
20 * @@, so @@local is a TASM compatible local label. Note that we only
21 * check for the first @ symbol, although TASM requires both.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000022 */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000023#define islocal(l) \
24 (tasm_compatible_mode ? \
25 (((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \
26 ((l)[0] == '.' && (l)[1] != '.'))
27#define islocalchar(c) \
28 (tasm_compatible_mode ? \
29 ((c) == '.' || (c) == '@') : \
30 ((c) == '.'))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000031
H. Peter Anvinaf535c12002-04-30 20:59:21 +000032#define LABEL_BLOCK 32 /* no. of labels/block */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000033#define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
H. Peter Anvinaf535c12002-04-30 20:59:21 +000034#define LABEL_HASHES 37 /* no. of hash table entries */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000035
H. Peter Anvinaf535c12002-04-30 20:59:21 +000036#define END_LIST -3 /* don't clash with NO_SEG! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000037#define END_BLOCK -2
38#define BOGUS_VALUE -4
39
H. Peter Anvinaf535c12002-04-30 20:59:21 +000040#define PERMTS_SIZE 4096 /* size of text blocks */
Ed Berosetc06f6df2003-09-08 00:30:40 +000041#if (PERMTS_SIZE > IDLEN_MAX)
42#error "IPERMTS_SIZE must be less than or equal to IDLEN_MAX"
43#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000044
45/* values for label.defn.is_global */
H. Peter Anvin76690a12002-04-30 20:52:49 +000046#define DEFINED_BIT 1
47#define GLOBAL_BIT 2
48#define EXTERN_BIT 4
49
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000050#define NOT_DEFINED_YET 0
H. Peter Anvin76690a12002-04-30 20:52:49 +000051#define TYPE_MASK 3
52#define LOCAL_SYMBOL (DEFINED_BIT)
53#define GLOBAL_PLACEHOLDER (GLOBAL_BIT)
54#define GLOBAL_SYMBOL (DEFINED_BIT|GLOBAL_BIT)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000055
H. Peter Anvinaf535c12002-04-30 20:59:21 +000056union label { /* actual label structures */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000057 struct {
H. Peter Anvinaf535c12002-04-30 20:59:21 +000058 long segment, offset;
H. Peter Anvin76690a12002-04-30 20:52:49 +000059 char *label, *special;
H. Peter Anvinaf535c12002-04-30 20:59:21 +000060 int is_global, is_norm;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000061 } defn;
62 struct {
H. Peter Anvinaf535c12002-04-30 20:59:21 +000063 long movingon, dummy;
64 union label *next;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000065 } admin;
66};
67
H. Peter Anvinaf535c12002-04-30 20:59:21 +000068struct permts { /* permanent text storage */
69 struct permts *next; /* for the linked list */
70 int size, usage; /* size and used space in ... */
71 char data[PERMTS_SIZE]; /* ... the data block itself */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072};
73
H. Peter Anvinaf535c12002-04-30 20:59:21 +000074extern int global_offset_changed; /* defined in nasm.c */
75
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000076static union label *ltab[LABEL_HASHES];/* using a hash table */
77static union label *lfree[LABEL_HASHES];/* pointer into the above */
78static struct permts *perm_head; /* start of perm. text storage */
79static struct permts *perm_tail; /* end of perm. text storage */
80
81static void init_block (union label *blk);
82static char *perm_copy (char *string1, char *string2);
83
84static char *prevlabel;
85
H. Peter Anvin76690a12002-04-30 20:52:49 +000086static int initialised = FALSE;
87
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000088char lprefix[PREFIX_MAX] = {0};
89char lpostfix[PREFIX_MAX] = {0};
90
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000091/*
92 * Internal routine: finds the `union label' corresponding to the
93 * given label name. Creates a new one, if it isn't found, and if
94 * `create' is TRUE.
95 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000096static union label *find_label (char *label, int create)
97{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000098 int hash = 0;
99 char *p, *prev;
100 int prevlen;
101 union label *lptr;
102
103 if (islocal(label))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000104 prev = prevlabel;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000105 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000106 prev = "";
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000107 prevlen = strlen(prev);
108 p = prev;
109 while (*p) hash += *p++;
110 p = label;
111 while (*p) hash += *p++;
112 hash %= LABEL_HASHES;
113 lptr = ltab[hash];
114 while (lptr->admin.movingon != END_LIST) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000115 if (lptr->admin.movingon == END_BLOCK) {
116 lptr = lptr->admin.next;
117 if (!lptr)
118 break;
119 }
120 if (!strncmp(lptr->defn.label, prev, prevlen) &&
121 !strcmp(lptr->defn.label+prevlen, label))
122 return lptr;
123 lptr++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000124 }
125 if (create) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000126 if (lfree[hash]->admin.movingon == END_BLOCK) {
127 /*
128 * must allocate a new block
129 */
130 lfree[hash]->admin.next = (union label *) nasm_malloc (LBLK_SIZE);
131 lfree[hash] = lfree[hash]->admin.next;
132 init_block(lfree[hash]);
133 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000134
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000135 lfree[hash]->admin.movingon = BOGUS_VALUE;
136 lfree[hash]->defn.label = perm_copy (prev, label);
137 lfree[hash]->defn.special = NULL;
138 lfree[hash]->defn.is_global = NOT_DEFINED_YET;
139 return lfree[hash]++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000140 }
141 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000142 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000143}
144
H. Peter Anvineba20a72002-04-30 20:53:55 +0000145int lookup_label (char *label, long *segment, long *offset)
146{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000147 union label *lptr;
148
H. Peter Anvin76690a12002-04-30 20:52:49 +0000149 if (!initialised)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000150 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000151
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000152 lptr = find_label (label, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000153 if (lptr && (lptr->defn.is_global & DEFINED_BIT)) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000154 *segment = lptr->defn.segment;
155 *offset = lptr->defn.offset;
156 return 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000157 }
158 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000159 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000160}
161
H. Peter Anvineba20a72002-04-30 20:53:55 +0000162int is_extern (char *label)
163{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000164 union label *lptr;
165
166 if (!initialised)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000167 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000168
169 lptr = find_label (label, 0);
170 if (lptr && (lptr->defn.is_global & EXTERN_BIT))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000171 return 1;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000172 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000173 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000174}
175
H. Peter Anvineba20a72002-04-30 20:53:55 +0000176void redefine_label (char *label, long segment, long offset, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000177 int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000178{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000179 union label *lptr;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000180 int exi;
181
H. Peter Anvineba20a72002-04-30 20:53:55 +0000182 /* This routine possibly ought to check for phase errors. Most assemblers
183 * check for phase errors at this point. I don't know whether phase errors
184 * are even possible, nor whether they are checked somewhere else
185 */
186
187 (void) segment; /* Don't warn that this parameter is unused */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000188 (void) special; /* Don't warn that this parameter is unused */
189 (void) is_norm; /* Don't warn that this parameter is unused */
190 (void) isextrn; /* Don't warn that this parameter is unused */
191 (void) ofmt; /* Don't warn that this parameter is unused */
192
193#ifdef DEBUG
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000194#if DEBUG<3
H. Peter Anvineba20a72002-04-30 20:53:55 +0000195 if (!strncmp(label, "debugdump", 9))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000196#endif
197 error(ERR_DEBUG, "redefine_label (%s, %ld, %08lx, %s, %d, %d)",
198 label, segment, offset, special, is_norm, isextrn);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000199#endif
200
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000201 lptr = find_label (label, 1);
202 if (!lptr)
203 error (ERR_PANIC, "can't find label `%s' on pass two", label);
204
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000205 if (!islocal(label)) {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000206 if (!islocalchar(*label) && lptr->defn.is_norm)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000207 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000208 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000209
210 global_offset_changed |= (lptr->defn.offset != offset);
211 lptr->defn.offset = offset;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000212
213if (pass0 == 1) {
214 exi = !!(lptr->defn.is_global & GLOBAL_BIT);
215 if (exi)
216 {
217 char *xsymbol;
218 int slen;
219 slen = strlen(lprefix);
220 slen += strlen(lptr->defn.label);
221 slen += strlen(lpostfix);
222 slen++; /* room for that null char */
223 xsymbol = nasm_malloc(slen);
Ed Berosetfcc50ae2004-12-15 18:03:20 +0000224 snprintf(xsymbol,slen,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000225
226 ofmt->symdef (xsymbol, segment, offset, exi,
227 special ? special : lptr->defn.special);
228 ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
229 special ? special : lptr->defn.special);
230/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
231 }
232 else
233 {
234 if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
235 ofmt->symdef (lptr->defn.label, segment, offset, exi,
236 special ? special : lptr->defn.special);
237 ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
238 special ? special : lptr->defn.special);
239 }
240 }
241} /* if (pass0 == 1) */
242
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000243}
244
H. Peter Anvin76690a12002-04-30 20:52:49 +0000245void define_label (char *label, long segment, long offset, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000246 int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000247{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000248 union label *lptr;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000249 int exi;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000250
H. Peter Anvineba20a72002-04-30 20:53:55 +0000251#ifdef DEBUG
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000252#if DEBUG<3
H. Peter Anvineba20a72002-04-30 20:53:55 +0000253 if (!strncmp(label, "debugdump", 9))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000254#endif
255 error(ERR_DEBUG, "define_label (%s, %ld, %08lx, %s, %d, %d)",
256 label, segment, offset, special, is_norm, isextrn);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000257#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000258 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000259 if (lptr->defn.is_global & DEFINED_BIT) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000260 error(ERR_NONFATAL, "symbol `%s' redefined", label);
261 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000262 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000263 lptr->defn.is_global |= DEFINED_BIT;
264 if (isextrn)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000265 lptr->defn.is_global |= EXTERN_BIT;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000266
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000267 if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */
268 prevlabel = lptr->defn.label;
269 else if (islocal(label) && !*prevlabel) {
270 error(ERR_NONFATAL, "attempt to define a local label before any"
271 " non-local labels");
272 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000273
274 lptr->defn.segment = segment;
275 lptr->defn.offset = offset;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000276 lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000277
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000278if (pass0 == 1 || (!is_norm && !isextrn && (segment&1))) {
279 exi = !!(lptr->defn.is_global & GLOBAL_BIT);
280 if (exi)
281 {
282 char *xsymbol;
283 int slen;
284 slen = strlen(lprefix);
285 slen += strlen(lptr->defn.label);
286 slen += strlen(lpostfix);
287 slen++; /* room for that null char */
288 xsymbol = nasm_malloc(slen);
Ed Berosetfcc50ae2004-12-15 18:03:20 +0000289 snprintf(xsymbol,slen,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000290
291 ofmt->symdef (xsymbol, segment, offset, exi,
292 special ? special : lptr->defn.special);
293 ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
294 special ? special : lptr->defn.special);
295/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000296 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000297 else
298 {
299 if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
300 ofmt->symdef (lptr->defn.label, segment, offset, exi,
301 special ? special : lptr->defn.special);
302 ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
303 special ? special : lptr->defn.special);
304 }
305 }
306} /* if (pass0 == 1) */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000307}
308
H. Peter Anvin76690a12002-04-30 20:52:49 +0000309void define_common (char *label, long segment, long size, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000310 struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000311{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000312 union label *lptr;
313
314 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000315 if (lptr->defn.is_global & DEFINED_BIT) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000316 error(ERR_NONFATAL, "symbol `%s' redefined", label);
317 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000318 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000319 lptr->defn.is_global |= DEFINED_BIT;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000320
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000321 if (!islocalchar(label[0])) /* not local, but not special either */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000322 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000323 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000324 error(ERR_NONFATAL, "attempt to define a local label as a "
325 "common variable");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000326
327 lptr->defn.segment = segment;
328 lptr->defn.offset = 0;
329
H. Peter Anvin76690a12002-04-30 20:52:49 +0000330 ofmt->symdef (lptr->defn.label, segment, size, 2,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000331 special ? special : lptr->defn.special);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000332 ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000333 special ? special : lptr->defn.special);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000334}
335
H. Peter Anvineba20a72002-04-30 20:53:55 +0000336void declare_as_global (char *label, char *special, efunc error)
337{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000338 union label *lptr;
339
340 if (islocal(label)) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000341 error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
342 " global", label);
343 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000344 }
345 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000346 switch (lptr->defn.is_global & TYPE_MASK) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000347 case NOT_DEFINED_YET:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000348 lptr->defn.is_global = GLOBAL_PLACEHOLDER;
349 lptr->defn.special = special ? perm_copy(special, "") : NULL;
350 break;
351 case GLOBAL_PLACEHOLDER: /* already done: silently ignore */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000352 case GLOBAL_SYMBOL:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000353 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000354 case LOCAL_SYMBOL:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000355 if (!lptr->defn.is_global & EXTERN_BIT)
356 error(ERR_NONFATAL, "symbol `%s': GLOBAL directive must"
357 " appear before symbol definition", label);
358 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000359 }
360}
361
H. Peter Anvineba20a72002-04-30 20:53:55 +0000362int init_labels (void)
363{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000364 int i;
365
366 for (i=0; i<LABEL_HASHES; i++) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000367 ltab[i] = (union label *) nasm_malloc (LBLK_SIZE);
368 if (!ltab[i])
369 return -1; /* can't initialise, panic */
370 init_block (ltab[i]);
371 lfree[i] = ltab[i];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000372 }
373
H. Peter Anvineba20a72002-04-30 20:53:55 +0000374 perm_head =
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000375 perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000376
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000377 if (!perm_head)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000378 return -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000379
380 perm_head->next = NULL;
381 perm_head->size = PERMTS_SIZE;
382 perm_head->usage = 0;
383
384 prevlabel = "";
385
H. Peter Anvin76690a12002-04-30 20:52:49 +0000386 initialised = TRUE;
387
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000388 return 0;
389}
390
H. Peter Anvineba20a72002-04-30 20:53:55 +0000391void cleanup_labels (void)
392{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000393 int i;
394
H. Peter Anvin76690a12002-04-30 20:52:49 +0000395 initialised = FALSE;
396
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000397 for (i=0; i<LABEL_HASHES; i++) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000398 union label *lptr, *lhold;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000399
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000400 lptr = lhold = ltab[i];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000401
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000402 while (lptr) {
403 while (lptr->admin.movingon != END_BLOCK) lptr++;
404 lptr = lptr->admin.next;
405 nasm_free (lhold);
406 lhold = lptr;
407 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000408 }
409
410 while (perm_head) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000411 perm_tail = perm_head;
412 perm_head = perm_head->next;
413 nasm_free (perm_tail);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000414 }
415}
416
H. Peter Anvineba20a72002-04-30 20:53:55 +0000417static void init_block (union label *blk)
418{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000419 int j;
420
421 for (j=0; j<LABEL_BLOCK-1; j++)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000422 blk[j].admin.movingon = END_LIST;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000423 blk[LABEL_BLOCK-1].admin.movingon = END_BLOCK;
424 blk[LABEL_BLOCK-1].admin.next = NULL;
425}
426
H. Peter Anvineba20a72002-04-30 20:53:55 +0000427static char *perm_copy (char *string1, char *string2)
428{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000429 char *p, *q;
430 int len = strlen(string1)+strlen(string2)+1;
431
432 if (perm_tail->size - perm_tail->usage < len) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000433 perm_tail->next = (struct permts *)nasm_malloc(sizeof(struct permts));
434 perm_tail = perm_tail->next;
435 perm_tail->next = NULL;
436 perm_tail->size = PERMTS_SIZE;
437 perm_tail->usage = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000438 }
439 p = q = perm_tail->data + perm_tail->usage;
440 while ( (*q = *string1++) ) q++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000441 while ( (*q++ = *string2++) ) ;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000442 perm_tail->usage = q - perm_tail->data;
443
444 return p;
445}
H. Peter Anvineba20a72002-04-30 20:53:55 +0000446
447/*
448 * Notes regarding bug involving redefinition of external segments.
449 *
450 * Up to and including v0.97, the following code didn't work. From 0.97
451 * developers release 2 onwards, it will generate an error.
452 *
453 * EXTERN extlabel
454 * newlabel EQU extlabel + 1
455 *
456 * The results of allowing this code through are that two import records
457 * are generated, one for 'extlabel' and one for 'newlabel'.
458 *
459 * The reason for this is an inadequacy in the defined interface between
460 * the label manager and the output formats. The problem lies in how the
461 * output format driver tells that a label is an external label for which
462 * a label import record must be produced. Most (all except bin?) produce
463 * the record if the segment number of the label is not one of the internal
464 * segments that the output driver is producing.
465 *
466 * A simple fix to this would be to make the output formats keep track of
467 * which symbols they've produced import records for, and make them not
468 * produce import records for segments that are already defined.
469 *
470 * The best way, which is slightly harder but reduces duplication of code
471 * and should therefore make the entire system smaller and more stable is
472 * to change the interface between assembler, define_label(), and
473 * the output module. The changes that are needed are:
474 *
475 * The semantics of the 'isextern' flag passed to define_label() need
476 * examining. This information may or may not tell us what we need to
477 * know (ie should we be generating an import record at this point for this
478 * label). If these aren't the semantics, the semantics should be changed
479 * to this.
480 *
481 * The output module interface needs changing, so that the `isextern' flag
482 * is passed to the module, so that it can be easily tested for.
483 */