blob: c47d34c42f73822e73ef5f47c85da10b7ba5e8b3 [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.
18 */
19#define islocal(l) ((l)[0] == '.' && (l)[1] != '.')
20
H. Peter Anvinaf535c12002-04-30 20:59:21 +000021#define LABEL_BLOCK 32 /* no. of labels/block */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000022#define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
H. Peter Anvinaf535c12002-04-30 20:59:21 +000023#define LABEL_HASHES 37 /* no. of hash table entries */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000024
H. Peter Anvinaf535c12002-04-30 20:59:21 +000025#define END_LIST -3 /* don't clash with NO_SEG! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000026#define END_BLOCK -2
27#define BOGUS_VALUE -4
28
H. Peter Anvinaf535c12002-04-30 20:59:21 +000029#define PERMTS_SIZE 4096 /* size of text blocks */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000030
31/* values for label.defn.is_global */
H. Peter Anvin76690a12002-04-30 20:52:49 +000032#define DEFINED_BIT 1
33#define GLOBAL_BIT 2
34#define EXTERN_BIT 4
35
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036#define NOT_DEFINED_YET 0
H. Peter Anvin76690a12002-04-30 20:52:49 +000037#define TYPE_MASK 3
38#define LOCAL_SYMBOL (DEFINED_BIT)
39#define GLOBAL_PLACEHOLDER (GLOBAL_BIT)
40#define GLOBAL_SYMBOL (DEFINED_BIT|GLOBAL_BIT)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000041
H. Peter Anvinaf535c12002-04-30 20:59:21 +000042union label { /* actual label structures */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000043 struct {
H. Peter Anvinaf535c12002-04-30 20:59:21 +000044 long segment, offset;
H. Peter Anvin76690a12002-04-30 20:52:49 +000045 char *label, *special;
H. Peter Anvinaf535c12002-04-30 20:59:21 +000046 int is_global, is_norm;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000047 } defn;
48 struct {
H. Peter Anvinaf535c12002-04-30 20:59:21 +000049 long movingon, dummy;
50 union label *next;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000051 } admin;
52};
53
H. Peter Anvinaf535c12002-04-30 20:59:21 +000054struct permts { /* permanent text storage */
55 struct permts *next; /* for the linked list */
56 int size, usage; /* size and used space in ... */
57 char data[PERMTS_SIZE]; /* ... the data block itself */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000058};
59
H. Peter Anvinaf535c12002-04-30 20:59:21 +000060extern int global_offset_changed; /* defined in nasm.c */
61
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000062static union label *ltab[LABEL_HASHES];/* using a hash table */
63static union label *lfree[LABEL_HASHES];/* pointer into the above */
64static struct permts *perm_head; /* start of perm. text storage */
65static struct permts *perm_tail; /* end of perm. text storage */
66
67static void init_block (union label *blk);
68static char *perm_copy (char *string1, char *string2);
69
70static char *prevlabel;
71
H. Peter Anvin76690a12002-04-30 20:52:49 +000072static int initialised = FALSE;
73
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000074/*
75 * Internal routine: finds the `union label' corresponding to the
76 * given label name. Creates a new one, if it isn't found, and if
77 * `create' is TRUE.
78 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000079static union label *find_label (char *label, int create)
80{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000081 int hash = 0;
82 char *p, *prev;
83 int prevlen;
84 union label *lptr;
85
86 if (islocal(label))
H. Peter Anvinaf535c12002-04-30 20:59:21 +000087 prev = prevlabel;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000088 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +000089 prev = "";
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000090 prevlen = strlen(prev);
91 p = prev;
92 while (*p) hash += *p++;
93 p = label;
94 while (*p) hash += *p++;
95 hash %= LABEL_HASHES;
96 lptr = ltab[hash];
97 while (lptr->admin.movingon != END_LIST) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +000098 if (lptr->admin.movingon == END_BLOCK) {
99 lptr = lptr->admin.next;
100 if (!lptr)
101 break;
102 }
103 if (!strncmp(lptr->defn.label, prev, prevlen) &&
104 !strcmp(lptr->defn.label+prevlen, label))
105 return lptr;
106 lptr++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000107 }
108 if (create) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000109 if (lfree[hash]->admin.movingon == END_BLOCK) {
110 /*
111 * must allocate a new block
112 */
113 lfree[hash]->admin.next = (union label *) nasm_malloc (LBLK_SIZE);
114 lfree[hash] = lfree[hash]->admin.next;
115 init_block(lfree[hash]);
116 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000117
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000118 lfree[hash]->admin.movingon = BOGUS_VALUE;
119 lfree[hash]->defn.label = perm_copy (prev, label);
120 lfree[hash]->defn.special = NULL;
121 lfree[hash]->defn.is_global = NOT_DEFINED_YET;
122 return lfree[hash]++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000123 }
124 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000125 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000126}
127
H. Peter Anvineba20a72002-04-30 20:53:55 +0000128int lookup_label (char *label, long *segment, long *offset)
129{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000130 union label *lptr;
131
H. Peter Anvin76690a12002-04-30 20:52:49 +0000132 if (!initialised)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000133 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000134
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000135 lptr = find_label (label, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000136 if (lptr && (lptr->defn.is_global & DEFINED_BIT)) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000137 *segment = lptr->defn.segment;
138 *offset = lptr->defn.offset;
139 return 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000140 }
141 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000142 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000143}
144
H. Peter Anvineba20a72002-04-30 20:53:55 +0000145int is_extern (char *label)
146{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000147 union label *lptr;
148
149 if (!initialised)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000150 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000151
152 lptr = find_label (label, 0);
153 if (lptr && (lptr->defn.is_global & EXTERN_BIT))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000154 return 1;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000155 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000156 return 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000157}
158
H. Peter Anvineba20a72002-04-30 20:53:55 +0000159void redefine_label (char *label, long segment, long offset, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000160 int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000161{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000162 union label *lptr;
163
H. Peter Anvineba20a72002-04-30 20:53:55 +0000164 /* This routine possibly ought to check for phase errors. Most assemblers
165 * check for phase errors at this point. I don't know whether phase errors
166 * are even possible, nor whether they are checked somewhere else
167 */
168
169 (void) segment; /* Don't warn that this parameter is unused */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000170 (void) special; /* Don't warn that this parameter is unused */
171 (void) is_norm; /* Don't warn that this parameter is unused */
172 (void) isextrn; /* Don't warn that this parameter is unused */
173 (void) ofmt; /* Don't warn that this parameter is unused */
174
175#ifdef DEBUG
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000176#if DEBUG<3
H. Peter Anvineba20a72002-04-30 20:53:55 +0000177 if (!strncmp(label, "debugdump", 9))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000178#endif
179 error(ERR_DEBUG, "redefine_label (%s, %ld, %08lx, %s, %d, %d)",
180 label, segment, offset, special, is_norm, isextrn);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000181#endif
182
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000183 lptr = find_label (label, 1);
184 if (!lptr)
185 error (ERR_PANIC, "can't find label `%s' on pass two", label);
186
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000187 if (!islocal(label)) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000188 if (*label != '.' && lptr->defn.is_norm)
189 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000190 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000191
192 global_offset_changed |= (lptr->defn.offset != offset);
193 lptr->defn.offset = offset;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000194}
195
H. Peter Anvin76690a12002-04-30 20:52:49 +0000196void define_label (char *label, long segment, long offset, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000197 int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000198{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000199 union label *lptr;
200
H. Peter Anvineba20a72002-04-30 20:53:55 +0000201#ifdef DEBUG
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000202#if DEBUG<3
H. Peter Anvineba20a72002-04-30 20:53:55 +0000203 if (!strncmp(label, "debugdump", 9))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000204#endif
205 error(ERR_DEBUG, "define_label (%s, %ld, %08lx, %s, %d, %d)",
206 label, segment, offset, special, is_norm, isextrn);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000207#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000208 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000209 if (lptr->defn.is_global & DEFINED_BIT) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000210 error(ERR_NONFATAL, "symbol `%s' redefined", label);
211 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000212 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000213 lptr->defn.is_global |= DEFINED_BIT;
214 if (isextrn)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000215 lptr->defn.is_global |= EXTERN_BIT;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000216
H. Peter Anvin76690a12002-04-30 20:52:49 +0000217 if (label[0] != '.' && is_norm) /* not local, but not special either */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000218 prevlabel = lptr->defn.label;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000219 else if (label[0] == '.' && label[1] != '.' && !*prevlabel)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000220 error(ERR_NONFATAL, "attempt to define a local label before any"
221 " non-local labels");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000222
223 lptr->defn.segment = segment;
224 lptr->defn.offset = offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000225 lptr->defn.is_norm = (label[0] != '.' && is_norm);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000226
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000227 if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
228 ofmt->symdef (lptr->defn.label, segment, offset,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000229 !!(lptr->defn.is_global & GLOBAL_BIT),
230 special ? special : lptr->defn.special);
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000231 ofmt->current_dfmt->debug_deflabel (label, segment, offset,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000232 !!(lptr->defn.is_global & GLOBAL_BIT),
233 special ? special : lptr->defn.special);
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000234 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000235}
236
H. Peter Anvin76690a12002-04-30 20:52:49 +0000237void define_common (char *label, long segment, long size, char *special,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000238 struct ofmt *ofmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000239{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000240 union label *lptr;
241
242 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000243 if (lptr->defn.is_global & DEFINED_BIT) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000244 error(ERR_NONFATAL, "symbol `%s' redefined", label);
245 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000246 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000247 lptr->defn.is_global |= DEFINED_BIT;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000248
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000249 if (label[0] != '.') /* not local, but not special either */
250 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000251 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000252 error(ERR_NONFATAL, "attempt to define a local label as a "
253 "common variable");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000254
255 lptr->defn.segment = segment;
256 lptr->defn.offset = 0;
257
H. Peter Anvin76690a12002-04-30 20:52:49 +0000258 ofmt->symdef (lptr->defn.label, segment, size, 2,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000259 special ? special : lptr->defn.special);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000260 ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2,
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000261 special ? special : lptr->defn.special);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000262}
263
H. Peter Anvineba20a72002-04-30 20:53:55 +0000264void declare_as_global (char *label, char *special, efunc error)
265{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000266 union label *lptr;
267
268 if (islocal(label)) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000269 error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
270 " global", label);
271 return;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000272 }
273 lptr = find_label (label, 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000274 switch (lptr->defn.is_global & TYPE_MASK) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000275 case NOT_DEFINED_YET:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000276 lptr->defn.is_global = GLOBAL_PLACEHOLDER;
277 lptr->defn.special = special ? perm_copy(special, "") : NULL;
278 break;
279 case GLOBAL_PLACEHOLDER: /* already done: silently ignore */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000280 case GLOBAL_SYMBOL:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000281 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000282 case LOCAL_SYMBOL:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000283 if (!lptr->defn.is_global & EXTERN_BIT)
284 error(ERR_NONFATAL, "symbol `%s': GLOBAL directive must"
285 " appear before symbol definition", label);
286 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000287 }
288}
289
H. Peter Anvineba20a72002-04-30 20:53:55 +0000290int init_labels (void)
291{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000292 int i;
293
294 for (i=0; i<LABEL_HASHES; i++) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000295 ltab[i] = (union label *) nasm_malloc (LBLK_SIZE);
296 if (!ltab[i])
297 return -1; /* can't initialise, panic */
298 init_block (ltab[i]);
299 lfree[i] = ltab[i];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000300 }
301
H. Peter Anvineba20a72002-04-30 20:53:55 +0000302 perm_head =
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000303 perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000304
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000305 if (!perm_head)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000306 return -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000307
308 perm_head->next = NULL;
309 perm_head->size = PERMTS_SIZE;
310 perm_head->usage = 0;
311
312 prevlabel = "";
313
H. Peter Anvin76690a12002-04-30 20:52:49 +0000314 initialised = TRUE;
315
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000316 return 0;
317}
318
H. Peter Anvineba20a72002-04-30 20:53:55 +0000319void cleanup_labels (void)
320{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000321 int i;
322
H. Peter Anvin76690a12002-04-30 20:52:49 +0000323 initialised = FALSE;
324
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000325 for (i=0; i<LABEL_HASHES; i++) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000326 union label *lptr, *lhold;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000327
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000328 lptr = lhold = ltab[i];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000329
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000330 while (lptr) {
331 while (lptr->admin.movingon != END_BLOCK) lptr++;
332 lptr = lptr->admin.next;
333 nasm_free (lhold);
334 lhold = lptr;
335 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000336 }
337
338 while (perm_head) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000339 perm_tail = perm_head;
340 perm_head = perm_head->next;
341 nasm_free (perm_tail);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000342 }
343}
344
H. Peter Anvineba20a72002-04-30 20:53:55 +0000345static void init_block (union label *blk)
346{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000347 int j;
348
349 for (j=0; j<LABEL_BLOCK-1; j++)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000350 blk[j].admin.movingon = END_LIST;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000351 blk[LABEL_BLOCK-1].admin.movingon = END_BLOCK;
352 blk[LABEL_BLOCK-1].admin.next = NULL;
353}
354
H. Peter Anvineba20a72002-04-30 20:53:55 +0000355static char *perm_copy (char *string1, char *string2)
356{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000357 char *p, *q;
358 int len = strlen(string1)+strlen(string2)+1;
359
360 if (perm_tail->size - perm_tail->usage < len) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000361 perm_tail->next = (struct permts *)nasm_malloc(sizeof(struct permts));
362 perm_tail = perm_tail->next;
363 perm_tail->next = NULL;
364 perm_tail->size = PERMTS_SIZE;
365 perm_tail->usage = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000366 }
367 p = q = perm_tail->data + perm_tail->usage;
368 while ( (*q = *string1++) ) q++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000369 while ( (*q++ = *string2++) ) ;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000370 perm_tail->usage = q - perm_tail->data;
371
372 return p;
373}
H. Peter Anvineba20a72002-04-30 20:53:55 +0000374
375/*
376 * Notes regarding bug involving redefinition of external segments.
377 *
378 * Up to and including v0.97, the following code didn't work. From 0.97
379 * developers release 2 onwards, it will generate an error.
380 *
381 * EXTERN extlabel
382 * newlabel EQU extlabel + 1
383 *
384 * The results of allowing this code through are that two import records
385 * are generated, one for 'extlabel' and one for 'newlabel'.
386 *
387 * The reason for this is an inadequacy in the defined interface between
388 * the label manager and the output formats. The problem lies in how the
389 * output format driver tells that a label is an external label for which
390 * a label import record must be produced. Most (all except bin?) produce
391 * the record if the segment number of the label is not one of the internal
392 * segments that the output driver is producing.
393 *
394 * A simple fix to this would be to make the output formats keep track of
395 * which symbols they've produced import records for, and make them not
396 * produce import records for segments that are already defined.
397 *
398 * The best way, which is slightly harder but reduces duplication of code
399 * and should therefore make the entire system smaller and more stable is
400 * to change the interface between assembler, define_label(), and
401 * the output module. The changes that are needed are:
402 *
403 * The semantics of the 'isextern' flag passed to define_label() need
404 * examining. This information may or may not tell us what we need to
405 * know (ie should we be generating an import record at this point for this
406 * label). If these aren't the semantics, the semantics should be changed
407 * to this.
408 *
409 * The output module interface needs changing, so that the `isextern' flag
410 * is passed to the module, so that it can be easily tested for.
411 */