]>
git.saurik.com Git - apple/boot.git/blob - i386/nasm/labels.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* labels.c label handling for the Netwide Assembler
27 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
28 * Julian Hall. All rights reserved. The software is
29 * redistributable under the licence given in the file "Licence"
30 * distributed in the NASM archive.
40 * A local label is one that begins with exactly one period. Things
41 * that begin with _two_ periods are NASM-specific things.
43 #define islocal(l) ((l)[0] == '.' && (l)[1] != '.')
45 #define LABEL_BLOCK 320 /* no. of labels/block */
46 #define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
47 #define LABEL_HASHES 32 /* no. of hash table entries */
49 #define END_LIST -3 /* don't clash with NO_SEG! */
51 #define BOGUS_VALUE -4
53 #define PERMTS_SIZE 4096 /* size of text blocks */
55 /* values for label.defn.is_global */
60 #define NOT_DEFINED_YET 0
62 #define LOCAL_SYMBOL (DEFINED_BIT)
63 #define GLOBAL_PLACEHOLDER (GLOBAL_BIT)
64 #define GLOBAL_SYMBOL (DEFINED_BIT|GLOBAL_BIT)
66 union label
{ /* actual label structures */
69 char *label
, *special
;
78 struct permts
{ /* permanent text storage */
79 struct permts
*next
; /* for the linked list */
80 int size
, usage
; /* size and used space in ... */
81 char data
[PERMTS_SIZE
]; /* ... the data block itself */
84 static union label
*ltab
[LABEL_HASHES
];/* using a hash table */
85 static union label
*lfree
[LABEL_HASHES
];/* pointer into the above */
86 static struct permts
*perm_head
; /* start of perm. text storage */
87 static struct permts
*perm_tail
; /* end of perm. text storage */
89 static void init_block (union label
*blk
);
90 static char *perm_copy (char *string1
, char *string2
);
92 static char *prevlabel
;
94 static int initialised
= FALSE
;
97 * Internal routine: finds the `union label' corresponding to the
98 * given label name. Creates a new one, if it isn't found, and if
101 static union label
*find_label (char *label
, int create
) {
111 prevlen
= strlen(prev
);
113 while (*p
) hash
+= *p
++;
115 while (*p
) hash
+= *p
++;
116 hash
%= LABEL_HASHES
;
118 while (lptr
->admin
.movingon
!= END_LIST
) {
119 if (lptr
->admin
.movingon
== END_BLOCK
) {
120 lptr
= lptr
->admin
.next
;
124 if (!strncmp(lptr
->defn
.label
, prev
, prevlen
) &&
125 !strcmp(lptr
->defn
.label
+prevlen
, label
))
130 if (lfree
[hash
]->admin
.movingon
== END_BLOCK
) {
132 * must allocate a new block
134 lfree
[hash
]->admin
.next
= (union label
*) nasm_malloc (LBLK_SIZE
);
135 lfree
[hash
] = lfree
[hash
]->admin
.next
;
136 init_block(lfree
[hash
]);
139 lfree
[hash
]->admin
.movingon
= BOGUS_VALUE
;
140 lfree
[hash
]->defn
.label
= perm_copy (prev
, label
);
141 lfree
[hash
]->defn
.special
= NULL
;
142 lfree
[hash
]->defn
.is_global
= NOT_DEFINED_YET
;
143 return lfree
[hash
]++;
148 int lookup_label (char *label
, long *segment
, long *offset
) {
154 lptr
= find_label (label
, 0);
155 if (lptr
&& (lptr
->defn
.is_global
& DEFINED_BIT
)) {
156 *segment
= lptr
->defn
.segment
;
157 *offset
= lptr
->defn
.offset
;
163 int is_extern (char *label
) {
169 lptr
= find_label (label
, 0);
170 if (lptr
&& (lptr
->defn
.is_global
& EXTERN_BIT
))
176 void define_label_stub (char *label
, efunc error
) {
179 if (!islocal(label
)) {
180 lptr
= find_label (label
, 1);
182 error (ERR_PANIC
, "can't find label `%s' on pass two", label
);
184 prevlabel
= lptr
->defn
.label
;
188 void define_label (char *label
, long segment
, long offset
, char *special
,
189 int is_norm
, int isextrn
, struct ofmt
*ofmt
, efunc error
) {
192 lptr
= find_label (label
, 1);
193 if (lptr
->defn
.is_global
& DEFINED_BIT
) {
194 error(ERR_NONFATAL
, "symbol `%s' redefined", label
);
197 lptr
->defn
.is_global
|= DEFINED_BIT
;
199 lptr
->defn
.is_global
|= EXTERN_BIT
;
201 if (label
[0] != '.' && is_norm
) /* not local, but not special either */
202 prevlabel
= lptr
->defn
.label
;
203 else if (label
[0] == '.' && label
[1] != '.' && !*prevlabel
)
204 error(ERR_NONFATAL
, "attempt to define a local label before any"
205 " non-local labels");
207 lptr
->defn
.segment
= segment
;
208 lptr
->defn
.offset
= offset
;
210 ofmt
->symdef (lptr
->defn
.label
, segment
, offset
,
211 !!(lptr
->defn
.is_global
& GLOBAL_BIT
),
212 special
? special
: lptr
->defn
.special
);
215 void define_common (char *label
, long segment
, long size
, char *special
,
216 struct ofmt
*ofmt
, efunc error
) {
219 lptr
= find_label (label
, 1);
220 if (lptr
->defn
.is_global
& DEFINED_BIT
) {
221 error(ERR_NONFATAL
, "symbol `%s' redefined", label
);
224 lptr
->defn
.is_global
|= DEFINED_BIT
;
226 if (label
[0] != '.') /* not local, but not special either */
227 prevlabel
= lptr
->defn
.label
;
229 error(ERR_NONFATAL
, "attempt to define a local label as a "
232 lptr
->defn
.segment
= segment
;
233 lptr
->defn
.offset
= 0;
235 ofmt
->symdef (lptr
->defn
.label
, segment
, size
, 2,
236 special
? special
: lptr
->defn
.special
);
239 void declare_as_global (char *label
, char *special
, efunc error
) {
242 if (islocal(label
)) {
243 error(ERR_NONFATAL
, "attempt to declare local symbol `%s' as"
247 lptr
= find_label (label
, 1);
248 switch (lptr
->defn
.is_global
& TYPE_MASK
) {
249 case NOT_DEFINED_YET
:
250 lptr
->defn
.is_global
= GLOBAL_PLACEHOLDER
;
251 lptr
->defn
.special
= special
? perm_copy(special
, "") : NULL
;
253 case GLOBAL_PLACEHOLDER
: /* already done: silently ignore */
257 if (!lptr
->defn
.is_global
& EXTERN_BIT
)
258 error(ERR_NONFATAL
, "symbol `%s': GLOBAL directive must"
259 " appear before symbol definition", label
);
264 int init_labels (void) {
267 for (i
=0; i
<LABEL_HASHES
; i
++) {
268 ltab
[i
] = (union label
*) nasm_malloc (LBLK_SIZE
);
270 return -1; /* can't initialise, panic */
271 init_block (ltab
[i
]);
275 perm_head
= perm_tail
= (struct permts
*) nasm_malloc (sizeof(struct permts
));
279 perm_head
->next
= NULL
;
280 perm_head
->size
= PERMTS_SIZE
;
281 perm_head
->usage
= 0;
290 void cleanup_labels (void) {
295 for (i
=0; i
<LABEL_HASHES
; i
++) {
296 union label
*lptr
, *lhold
;
298 lptr
= lhold
= ltab
[i
];
301 while (lptr
->admin
.movingon
!= END_BLOCK
) lptr
++;
302 lptr
= lptr
->admin
.next
;
309 perm_tail
= perm_head
;
310 perm_head
= perm_head
->next
;
311 nasm_free (perm_tail
);
315 static void init_block (union label
*blk
) {
318 for (j
=0; j
<LABEL_BLOCK
-1; j
++)
319 blk
[j
].admin
.movingon
= END_LIST
;
320 blk
[LABEL_BLOCK
-1].admin
.movingon
= END_BLOCK
;
321 blk
[LABEL_BLOCK
-1].admin
.next
= NULL
;
324 static char *perm_copy (char *string1
, char *string2
) {
326 int len
= strlen(string1
)+strlen(string2
)+1;
328 if (perm_tail
->size
- perm_tail
->usage
< len
) {
329 perm_tail
->next
= (struct permts
*)nasm_malloc(sizeof(struct permts
));
330 perm_tail
= perm_tail
->next
;
331 perm_tail
->next
= NULL
;
332 perm_tail
->size
= PERMTS_SIZE
;
333 perm_tail
->usage
= 0;
335 p
= q
= perm_tail
->data
+ perm_tail
->usage
;
336 while ( (*q
= *string1
++) ) q
++;
337 while ( (*q
++ = *string2
++) );
338 perm_tail
->usage
= q
- perm_tail
->data
;