]>
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 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* labels.c label handling for the Netwide Assembler
26 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
27 * Julian Hall. All rights reserved. The software is
28 * redistributable under the licence given in the file "Licence"
29 * distributed in the NASM archive.
39 * A local label is one that begins with exactly one period. Things
40 * that begin with _two_ periods are NASM-specific things.
42 #define islocal(l) ((l)[0] == '.' && (l)[1] != '.')
44 #define LABEL_BLOCK 320 /* no. of labels/block */
45 #define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
46 #define LABEL_HASHES 32 /* no. of hash table entries */
48 #define END_LIST -3 /* don't clash with NO_SEG! */
50 #define BOGUS_VALUE -4
52 #define PERMTS_SIZE 4096 /* size of text blocks */
54 /* values for label.defn.is_global */
59 #define NOT_DEFINED_YET 0
61 #define LOCAL_SYMBOL (DEFINED_BIT)
62 #define GLOBAL_PLACEHOLDER (GLOBAL_BIT)
63 #define GLOBAL_SYMBOL (DEFINED_BIT|GLOBAL_BIT)
65 union label
{ /* actual label structures */
68 char *label
, *special
;
77 struct permts
{ /* permanent text storage */
78 struct permts
*next
; /* for the linked list */
79 int size
, usage
; /* size and used space in ... */
80 char data
[PERMTS_SIZE
]; /* ... the data block itself */
83 static union label
*ltab
[LABEL_HASHES
];/* using a hash table */
84 static union label
*lfree
[LABEL_HASHES
];/* pointer into the above */
85 static struct permts
*perm_head
; /* start of perm. text storage */
86 static struct permts
*perm_tail
; /* end of perm. text storage */
88 static void init_block (union label
*blk
);
89 static char *perm_copy (char *string1
, char *string2
);
91 static char *prevlabel
;
93 static int initialised
= FALSE
;
96 * Internal routine: finds the `union label' corresponding to the
97 * given label name. Creates a new one, if it isn't found, and if
100 static union label
*find_label (char *label
, int create
) {
110 prevlen
= strlen(prev
);
112 while (*p
) hash
+= *p
++;
114 while (*p
) hash
+= *p
++;
115 hash
%= LABEL_HASHES
;
117 while (lptr
->admin
.movingon
!= END_LIST
) {
118 if (lptr
->admin
.movingon
== END_BLOCK
) {
119 lptr
= lptr
->admin
.next
;
123 if (!strncmp(lptr
->defn
.label
, prev
, prevlen
) &&
124 !strcmp(lptr
->defn
.label
+prevlen
, label
))
129 if (lfree
[hash
]->admin
.movingon
== END_BLOCK
) {
131 * must allocate a new block
133 lfree
[hash
]->admin
.next
= (union label
*) nasm_malloc (LBLK_SIZE
);
134 lfree
[hash
] = lfree
[hash
]->admin
.next
;
135 init_block(lfree
[hash
]);
138 lfree
[hash
]->admin
.movingon
= BOGUS_VALUE
;
139 lfree
[hash
]->defn
.label
= perm_copy (prev
, label
);
140 lfree
[hash
]->defn
.special
= NULL
;
141 lfree
[hash
]->defn
.is_global
= NOT_DEFINED_YET
;
142 return lfree
[hash
]++;
147 int lookup_label (char *label
, long *segment
, long *offset
) {
153 lptr
= find_label (label
, 0);
154 if (lptr
&& (lptr
->defn
.is_global
& DEFINED_BIT
)) {
155 *segment
= lptr
->defn
.segment
;
156 *offset
= lptr
->defn
.offset
;
162 int is_extern (char *label
) {
168 lptr
= find_label (label
, 0);
169 if (lptr
&& (lptr
->defn
.is_global
& EXTERN_BIT
))
175 void define_label_stub (char *label
, efunc error
) {
178 if (!islocal(label
)) {
179 lptr
= find_label (label
, 1);
181 error (ERR_PANIC
, "can't find label `%s' on pass two", label
);
183 prevlabel
= lptr
->defn
.label
;
187 void define_label (char *label
, long segment
, long offset
, char *special
,
188 int is_norm
, int isextrn
, struct ofmt
*ofmt
, efunc error
) {
191 lptr
= find_label (label
, 1);
192 if (lptr
->defn
.is_global
& DEFINED_BIT
) {
193 error(ERR_NONFATAL
, "symbol `%s' redefined", label
);
196 lptr
->defn
.is_global
|= DEFINED_BIT
;
198 lptr
->defn
.is_global
|= EXTERN_BIT
;
200 if (label
[0] != '.' && is_norm
) /* not local, but not special either */
201 prevlabel
= lptr
->defn
.label
;
202 else if (label
[0] == '.' && label
[1] != '.' && !*prevlabel
)
203 error(ERR_NONFATAL
, "attempt to define a local label before any"
204 " non-local labels");
206 lptr
->defn
.segment
= segment
;
207 lptr
->defn
.offset
= offset
;
209 ofmt
->symdef (lptr
->defn
.label
, segment
, offset
,
210 !!(lptr
->defn
.is_global
& GLOBAL_BIT
),
211 special
? special
: lptr
->defn
.special
);
214 void define_common (char *label
, long segment
, long size
, char *special
,
215 struct ofmt
*ofmt
, efunc error
) {
218 lptr
= find_label (label
, 1);
219 if (lptr
->defn
.is_global
& DEFINED_BIT
) {
220 error(ERR_NONFATAL
, "symbol `%s' redefined", label
);
223 lptr
->defn
.is_global
|= DEFINED_BIT
;
225 if (label
[0] != '.') /* not local, but not special either */
226 prevlabel
= lptr
->defn
.label
;
228 error(ERR_NONFATAL
, "attempt to define a local label as a "
231 lptr
->defn
.segment
= segment
;
232 lptr
->defn
.offset
= 0;
234 ofmt
->symdef (lptr
->defn
.label
, segment
, size
, 2,
235 special
? special
: lptr
->defn
.special
);
238 void declare_as_global (char *label
, char *special
, efunc error
) {
241 if (islocal(label
)) {
242 error(ERR_NONFATAL
, "attempt to declare local symbol `%s' as"
246 lptr
= find_label (label
, 1);
247 switch (lptr
->defn
.is_global
& TYPE_MASK
) {
248 case NOT_DEFINED_YET
:
249 lptr
->defn
.is_global
= GLOBAL_PLACEHOLDER
;
250 lptr
->defn
.special
= special
? perm_copy(special
, "") : NULL
;
252 case GLOBAL_PLACEHOLDER
: /* already done: silently ignore */
256 if (!lptr
->defn
.is_global
& EXTERN_BIT
)
257 error(ERR_NONFATAL
, "symbol `%s': GLOBAL directive must"
258 " appear before symbol definition", label
);
263 int init_labels (void) {
266 for (i
=0; i
<LABEL_HASHES
; i
++) {
267 ltab
[i
] = (union label
*) nasm_malloc (LBLK_SIZE
);
269 return -1; /* can't initialise, panic */
270 init_block (ltab
[i
]);
274 perm_head
= perm_tail
= (struct permts
*) nasm_malloc (sizeof(struct permts
));
278 perm_head
->next
= NULL
;
279 perm_head
->size
= PERMTS_SIZE
;
280 perm_head
->usage
= 0;
289 void cleanup_labels (void) {
294 for (i
=0; i
<LABEL_HASHES
; i
++) {
295 union label
*lptr
, *lhold
;
297 lptr
= lhold
= ltab
[i
];
300 while (lptr
->admin
.movingon
!= END_BLOCK
) lptr
++;
301 lptr
= lptr
->admin
.next
;
308 perm_tail
= perm_head
;
309 perm_head
= perm_head
->next
;
310 nasm_free (perm_tail
);
314 static void init_block (union label
*blk
) {
317 for (j
=0; j
<LABEL_BLOCK
-1; j
++)
318 blk
[j
].admin
.movingon
= END_LIST
;
319 blk
[LABEL_BLOCK
-1].admin
.movingon
= END_BLOCK
;
320 blk
[LABEL_BLOCK
-1].admin
.next
= NULL
;
323 static char *perm_copy (char *string1
, char *string2
) {
325 int len
= strlen(string1
)+strlen(string2
)+1;
327 if (perm_tail
->size
- perm_tail
->usage
< len
) {
328 perm_tail
->next
= (struct permts
*)nasm_malloc(sizeof(struct permts
));
329 perm_tail
= perm_tail
->next
;
330 perm_tail
->next
= NULL
;
331 perm_tail
->size
= PERMTS_SIZE
;
332 perm_tail
->usage
= 0;
334 p
= q
= perm_tail
->data
+ perm_tail
->usage
;
335 while ( (*q
= *string1
++) ) q
++;
336 while ( (*q
++ = *string2
++) );
337 perm_tail
->usage
= q
- perm_tail
->data
;