blob: c793904a2ffc0c617154ca68c6a9ce7c4d1ebaf7 [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 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000041
42/* values for label.defn.is_global */
H. Peter Anvin76690a12002-04-30 20:52:49 +000043#define DEFINED_BIT 1
44#define GLOBAL_BIT 2
45#define EXTERN_BIT 4
46
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000047#define NOT_DEFINED_YET 0
H. Peter Anvin76690a12002-04-30 20:52:49 +000048#define TYPE_MASK 3
49#define LOCAL_SYMBOL (DEFINED_BIT)
50#define GLOBAL_PLACEHOLDER (GLOBAL_BIT)
51#define GLOBAL_SYMBOL (DEFINED_BIT|GLOBAL_BIT)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000052
H. Peter Anvinaf535c12002-04-30 20:59:21 +000053union label { /* actual label structures */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000054 struct {
H. Peter Anvinaf535c12002-04-30 20:59:21 +000055 long segment, offset;
H. Peter Anvin76690a12002-04-30 20:52:49 +000056 char *label, *special;
H. Peter Anvinaf535c12002-04-30 20:59:21 +000057 int is_global, is_norm;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000058 } defn;
59 struct {
H. Peter Anvinaf535c12002-04-30 20:59:21 +000060 long movingon, dummy;
61 union label *next;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000062 } admin;
63};
64
H. Peter Anvinaf535c12002-04-30 20:59:21 +000065struct permts { /* permanent text storage */
66 struct permts *next; /* for the linked list */
67 int size, usage; /* size and used space in ... */
68 char data[PERMTS_SIZE]; /* ... the data block itself */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000069};
70
H. Peter Anvinaf535c12002-04-30 20:59:21 +000071extern int global_offset_changed; /* defined in nasm.c */
72
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000073static union label *ltab[LABEL_HASHES];/* using a hash table */
74static union label *lfree[LABEL_HASHES];/* pointer into the above */
75static struct permts *perm_head; /* start of perm. text storage */
76static struct permts *perm_tail; /* end of perm. text storage */
77
78static void init_block (union label *blk);
79static char *perm_copy (char *string1, char *string2);
80
81static char *prevlabel;
82
H. Peter Anvin76690a12002-04-30 20:52:49 +000083static int initialised = FALSE;
84
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000085char lprefix[PREFIX_MAX] = {0};
86char lpostfix[PREFIX_MAX] = {0};
87
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000088/*
89 * Internal routine: finds the `union label' corresponding to the
90 * given label name. Creates a new one, if it isn't found, and if
91 * `create' is TRUE.
92 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000093static union label *find_label (char *label, int create)
94{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000095 int hash = 0;
96 char *p, *prev;
97 int prevlen;
98 union label *lptr;
99
100 if (islocal(label))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000101 prev = prevlabel;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000102 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000103 prev = "";
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000104 prevlen = strlen(prev);
105 p = prev;
106 while (*p) hash += *p++;
107 p = label;
108 while (*p) hash += *p++;
109 hash %= LABEL_HASHES;
110 lptr = ltab[hash];
111 while (lptr->admin.movingon != END_LIST) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000112 if (lptr->admin.movingon == END_BLOCK) {
113 lptr = lptr->admin.next;
114 if (!lptr)
115 break;
116 }
117 if (!strncmp(lptr->defn.label, prev, prevlen) &&
118 !strcmp(lptr->defn.label+prevlen, label))
119 return lptr;
120 lptr++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000121 }
122 if (create) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000123 if (lfree[hash]->admin.movingon == END_BLOCK) {
124 /*
125 * must allocate a new block
126 */
127 lfree[hash]->admin.next = (union label *) nasm_malloc (LBLK_SIZE);
128 lfree[hash] = lfree[hash]->admin.next;
129 init_block(lfree[hash]);
130 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000131
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000132 lfree[hash]->admin.movingon = BOGUS_VALUE;
133 lfree[hash]->defn.label = perm_copy (prev, label);
134 lfree[hash]->defn.special = NULL;
135 lfree[hash]->defn.is_global = NOT_DEFINED_YET;
136 return lfree[hash]++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000137 }
138 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000139 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000140}
141
H. Peter Anvineba20a72002-04-30 20:53:55 +0000142int lookup_label (char *label, long *segment, long *offset)
143{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000144 union label *lptr;
145
H. Peter Anvin76690a12002-04-30 20:52:49 +0000146 if (!initialised)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000147 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000148
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000149 lptr = find_label (label, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000150 if (lptr && (lptr->defn.is_global & DEFINED_BIT)) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000151 *segment = lptr->defn.segment;
152 *offset = lptr->defn.offset;
153 return 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000154 }
155 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000156 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000157}
158
H. Peter Anvineba20a72002-04-30 20:53:55 +0000159int is_extern (char *label)
160{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000161 union label *lptr;
162
163 if (!initialised)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000164 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000165
166 lptr = find_label (label, 0);
167 if (lptr && (lptr->defn.is_global & EXTERN_BIT))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000168 return 1;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000169 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000170 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000171}
172
H. Peter Anvineba20a72002-04-30 20:53:55 +0000173void redefine_label (char *label, long segment, long offset, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000174 int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000175{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000176 union label *lptr;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000177 int exi;
178
H. Peter Anvineba20a72002-04-30 20:53:55 +0000179 /* This routine possibly ought to check for phase errors. Most assemblers
180 * check for phase errors at this point. I don't know whether phase errors
181 * are even possible, nor whether they are checked somewhere else
182 */
183
184 (void) segment; /* Don't warn that this parameter is unused */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000185 (void) special; /* Don't warn that this parameter is unused */
186 (void) is_norm; /* Don't warn that this parameter is unused */
187 (void) isextrn; /* Don't warn that this parameter is unused */
188 (void) ofmt; /* Don't warn that this parameter is unused */
189
190#ifdef DEBUG
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000191#if DEBUG<3
H. Peter Anvineba20a72002-04-30 20:53:55 +0000192 if (!strncmp(label, "debugdump", 9))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000193#endif
194 error(ERR_DEBUG, "redefine_label (%s, %ld, %08lx, %s, %d, %d)",
195 label, segment, offset, special, is_norm, isextrn);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000196#endif
197
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000198 lptr = find_label (label, 1);
199 if (!lptr)
200 error (ERR_PANIC, "can't find label `%s' on pass two", label);
201
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000202 if (!islocal(label)) {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000203 if (!islocalchar(*label) && lptr->defn.is_norm)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000204 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000205 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000206
207 global_offset_changed |= (lptr->defn.offset != offset);
208 lptr->defn.offset = offset;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000209
210if (pass0 == 1) {
211 exi = !!(lptr->defn.is_global & GLOBAL_BIT);
212 if (exi)
213 {
214 char *xsymbol;
215 int slen;
216 slen = strlen(lprefix);
217 slen += strlen(lptr->defn.label);
218 slen += strlen(lpostfix);
219 slen++; /* room for that null char */
220 xsymbol = nasm_malloc(slen);
221 sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
222
223 ofmt->symdef (xsymbol, segment, offset, exi,
224 special ? special : lptr->defn.special);
225 ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
226 special ? special : lptr->defn.special);
227/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
228 }
229 else
230 {
231 if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
232 ofmt->symdef (lptr->defn.label, segment, offset, exi,
233 special ? special : lptr->defn.special);
234 ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
235 special ? special : lptr->defn.special);
236 }
237 }
238} /* if (pass0 == 1) */
239
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000240}
241
H. Peter Anvin76690a12002-04-30 20:52:49 +0000242void define_label (char *label, long segment, long offset, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000243 int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000244{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000245 union label *lptr;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000246 int exi;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000247
H. Peter Anvineba20a72002-04-30 20:53:55 +0000248#ifdef DEBUG
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000249#if DEBUG<3
H. Peter Anvineba20a72002-04-30 20:53:55 +0000250 if (!strncmp(label, "debugdump", 9))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000251#endif
252 error(ERR_DEBUG, "define_label (%s, %ld, %08lx, %s, %d, %d)",
253 label, segment, offset, special, is_norm, isextrn);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000254#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000255 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000256 if (lptr->defn.is_global & DEFINED_BIT) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000257 error(ERR_NONFATAL, "symbol `%s' redefined", label);
258 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000259 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000260 lptr->defn.is_global |= DEFINED_BIT;
261 if (isextrn)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000262 lptr->defn.is_global |= EXTERN_BIT;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000263
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000264 if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */
265 prevlabel = lptr->defn.label;
266 else if (islocal(label) && !*prevlabel) {
267 error(ERR_NONFATAL, "attempt to define a local label before any"
268 " non-local labels");
269 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000270
271 lptr->defn.segment = segment;
272 lptr->defn.offset = offset;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000273 lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000274
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000275if (pass0 == 1 || (!is_norm && !isextrn && (segment&1))) {
276 exi = !!(lptr->defn.is_global & GLOBAL_BIT);
277 if (exi)
278 {
279 char *xsymbol;
280 int slen;
281 slen = strlen(lprefix);
282 slen += strlen(lptr->defn.label);
283 slen += strlen(lpostfix);
284 slen++; /* room for that null char */
285 xsymbol = nasm_malloc(slen);
286 sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
287
288 ofmt->symdef (xsymbol, segment, offset, exi,
289 special ? special : lptr->defn.special);
290 ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
291 special ? special : lptr->defn.special);
292/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000293 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000294 else
295 {
296 if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
297 ofmt->symdef (lptr->defn.label, segment, offset, exi,
298 special ? special : lptr->defn.special);
299 ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
300 special ? special : lptr->defn.special);
301 }
302 }
303} /* if (pass0 == 1) */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000304}
305
H. Peter Anvin76690a12002-04-30 20:52:49 +0000306void define_common (char *label, long segment, long size, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000307 struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000308{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000309 union label *lptr;
310
311 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000312 if (lptr->defn.is_global & DEFINED_BIT) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000313 error(ERR_NONFATAL, "symbol `%s' redefined", label);
314 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000315 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000316 lptr->defn.is_global |= DEFINED_BIT;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000317
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000318 if (!islocalchar(label[0])) /* not local, but not special either */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000319 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000320 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000321 error(ERR_NONFATAL, "attempt to define a local label as a "
322 "common variable");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000323
324 lptr->defn.segment = segment;
325 lptr->defn.offset = 0;
326
H. Peter Anvin76690a12002-04-30 20:52:49 +0000327 ofmt->symdef (lptr->defn.label, segment, size, 2,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000328 special ? special : lptr->defn.special);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000329 ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000330 special ? special : lptr->defn.special);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000331}
332
H. Peter Anvineba20a72002-04-30 20:53:55 +0000333void declare_as_global (char *label, char *special, efunc error)
334{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000335 union label *lptr;
336
337 if (islocal(label)) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000338 error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
339 " global", label);
340 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000341 }
342 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000343 switch (lptr->defn.is_global & TYPE_MASK) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000344 case NOT_DEFINED_YET:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000345 lptr->defn.is_global = GLOBAL_PLACEHOLDER;
346 lptr->defn.special = special ? perm_copy(special, "") : NULL;
347 break;
348 case GLOBAL_PLACEHOLDER: /* already done: silently ignore */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000349 case GLOBAL_SYMBOL:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000350 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000351 case LOCAL_SYMBOL:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000352 if (!lptr->defn.is_global & EXTERN_BIT)
353 error(ERR_NONFATAL, "symbol `%s': GLOBAL directive must"
354 " appear before symbol definition", label);
355 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000356 }
357}
358
H. Peter Anvineba20a72002-04-30 20:53:55 +0000359int init_labels (void)
360{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000361 int i;
362
363 for (i=0; i<LABEL_HASHES; i++) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000364 ltab[i] = (union label *) nasm_malloc (LBLK_SIZE);
365 if (!ltab[i])
366 return -1; /* can't initialise, panic */
367 init_block (ltab[i]);
368 lfree[i] = ltab[i];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000369 }
370
H. Peter Anvineba20a72002-04-30 20:53:55 +0000371 perm_head =
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000372 perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000373
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000374 if (!perm_head)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000375 return -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000376
377 perm_head->next = NULL;
378 perm_head->size = PERMTS_SIZE;
379 perm_head->usage = 0;
380
381 prevlabel = "";
382
H. Peter Anvin76690a12002-04-30 20:52:49 +0000383 initialised = TRUE;
384
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000385 return 0;
386}
387
H. Peter Anvineba20a72002-04-30 20:53:55 +0000388void cleanup_labels (void)
389{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000390 int i;
391
H. Peter Anvin76690a12002-04-30 20:52:49 +0000392 initialised = FALSE;
393
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000394 for (i=0; i<LABEL_HASHES; i++) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000395 union label *lptr, *lhold;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000396
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000397 lptr = lhold = ltab[i];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000398
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000399 while (lptr) {
400 while (lptr->admin.movingon != END_BLOCK) lptr++;
401 lptr = lptr->admin.next;
402 nasm_free (lhold);
403 lhold = lptr;
404 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000405 }
406
407 while (perm_head) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000408 perm_tail = perm_head;
409 perm_head = perm_head->next;
410 nasm_free (perm_tail);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000411 }
412}
413
H. Peter Anvineba20a72002-04-30 20:53:55 +0000414static void init_block (union label *blk)
415{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000416 int j;
417
418 for (j=0; j<LABEL_BLOCK-1; j++)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000419 blk[j].admin.movingon = END_LIST;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000420 blk[LABEL_BLOCK-1].admin.movingon = END_BLOCK;
421 blk[LABEL_BLOCK-1].admin.next = NULL;
422}
423
H. Peter Anvineba20a72002-04-30 20:53:55 +0000424static char *perm_copy (char *string1, char *string2)
425{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000426 char *p, *q;
427 int len = strlen(string1)+strlen(string2)+1;
428
429 if (perm_tail->size - perm_tail->usage < len) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000430 perm_tail->next = (struct permts *)nasm_malloc(sizeof(struct permts));
431 perm_tail = perm_tail->next;
432 perm_tail->next = NULL;
433 perm_tail->size = PERMTS_SIZE;
434 perm_tail->usage = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000435 }
436 p = q = perm_tail->data + perm_tail->usage;
437 while ( (*q = *string1++) ) q++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000438 while ( (*q++ = *string2++) ) ;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000439 perm_tail->usage = q - perm_tail->data;
440
441 return p;
442}
H. Peter Anvineba20a72002-04-30 20:53:55 +0000443
444/*
445 * Notes regarding bug involving redefinition of external segments.
446 *
447 * Up to and including v0.97, the following code didn't work. From 0.97
448 * developers release 2 onwards, it will generate an error.
449 *
450 * EXTERN extlabel
451 * newlabel EQU extlabel + 1
452 *
453 * The results of allowing this code through are that two import records
454 * are generated, one for 'extlabel' and one for 'newlabel'.
455 *
456 * The reason for this is an inadequacy in the defined interface between
457 * the label manager and the output formats. The problem lies in how the
458 * output format driver tells that a label is an external label for which
459 * a label import record must be produced. Most (all except bin?) produce
460 * the record if the segment number of the label is not one of the internal
461 * segments that the output driver is producing.
462 *
463 * A simple fix to this would be to make the output formats keep track of
464 * which symbols they've produced import records for, and make them not
465 * produce import records for segments that are already defined.
466 *
467 * The best way, which is slightly harder but reduces duplication of code
468 * and should therefore make the entire system smaller and more stable is
469 * to change the interface between assembler, define_label(), and
470 * the output module. The changes that are needed are:
471 *
472 * The semantics of the 'isextern' flag passed to define_label() need
473 * examining. This information may or may not tell us what we need to
474 * know (ie should we be generating an import record at this point for this
475 * label). If these aren't the semantics, the semantics should be changed
476 * to this.
477 *
478 * The output module interface needs changing, so that the `isextern' flag
479 * is passed to the module, so that it can be easily tested for.
480 */