NASM 0.91
[nasm.git] / nasmlib.c
blobc8710b0c0b28709eb4ffd10b012397bb6f91da09
1 /* nasmlib.c library routines for the Netwide Assembler
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 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
14 #include "nasm.h"
15 #include "nasmlib.h"
17 static efunc nasm_malloc_error;
19 void nasm_set_malloc_error (efunc error) {
20 nasm_malloc_error = error;
23 void *nasm_malloc (size_t size) {
24 void *p = malloc(size);
25 if (!p)
26 nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
27 return p;
30 void *nasm_realloc (void *q, size_t size) {
31 void *p = q ? realloc(q, size) : malloc(size);
32 if (!p)
33 nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
34 return p;
37 void nasm_free (void *q) {
38 if (q)
39 free (q);
42 char *nasm_strdup (char *s) {
43 char *p;
45 p = nasm_malloc(strlen(s)+1);
46 strcpy (p, s);
47 return p;
50 int nasm_stricmp (char *s1, char *s2) {
51 while (*s1 && toupper(*s1) == toupper(*s2))
52 s1++, s2++;
53 if (!*s1 && !*s2)
54 return 0;
55 else if (toupper(*s1) < toupper(*s2))
56 return -1;
57 else
58 return 1;
61 int nasm_strnicmp (char *s1, char *s2, int n) {
62 while (n > 0 && *s1 && toupper(*s1) == toupper(*s2))
63 s1++, s2++, n--;
64 if ((!*s1 && !*s2) || n==0)
65 return 0;
66 else if (toupper(*s1) < toupper(*s2))
67 return -1;
68 else
69 return 1;
72 #define isnumchar(c) ( isalnum(c) || (c) == '$')
73 #define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
75 long readnum (char *str, int *error) {
76 char *r = str, *q;
77 long radix;
78 long result;
80 *error = FALSE;
82 while (isspace(*r)) r++; /* find start of number */
83 q = r;
85 while (isnumchar(*q)) q++; /* find end of number */
88 * If it begins 0x, 0X or $, or ends in H, it's in hex. if it
89 * ends in Q, it's octal. if it ends in B, it's binary.
90 * Otherwise, it's ordinary decimal.
92 if (*r=='0' && (r[1]=='x' || r[1]=='X'))
93 radix = 16, r += 2;
94 else if (*r=='$')
95 radix = 16, r++;
96 else if (q[-1]=='H' || q[-1]=='h')
97 radix = 16 , q--;
98 else if (q[-1]=='Q' || q[-1]=='q')
99 radix = 8 , q--;
100 else if (q[-1]=='B' || q[-1]=='b')
101 radix = 2 , q--;
102 else
103 radix = 10;
105 result = 0;
106 while (*r && r < q) {
107 if (*r<'0' || (*r>'9' && *r<'A') || numvalue(*r)>=radix) {
108 *error = TRUE;
109 return 0;
111 result = radix * result + numvalue(*r);
112 r++;
114 return result;
117 static long next_seg;
119 void seg_init(void) {
120 next_seg = 0;
123 long seg_alloc(void) {
124 return (next_seg += 2) - 2;
127 void fwriteshort (int data, FILE *fp) {
128 fputc (data & 255, fp);
129 fputc ((data >> 8) & 255, fp);
132 void fwritelong (long data, FILE *fp) {
133 fputc (data & 255, fp);
134 fputc ((data >> 8) & 255, fp);
135 fputc ((data >> 16) & 255, fp);
136 fputc ((data >> 24) & 255, fp);
139 void standard_extension (char *inname, char *outname, char *extension,
140 efunc error) {
141 char *p, *q;
143 q = inname;
144 p = outname;
145 while (*q) *p++ = *q++; /* copy, and find end of string */
146 *p = '\0'; /* terminate it */
147 while (p > outname && *--p != '.');/* find final period (or whatever) */
148 if (*p != '.') while (*p) p++; /* go back to end if none found */
149 if (!strcmp(p, extension)) { /* is the extension already there? */
150 if (*extension)
151 error(ERR_WARNING | ERR_NOFILE,
152 "file name already ends in `%s': "
153 "output will be in `nasm.out'",
154 extension);
155 else
156 error(ERR_WARNING | ERR_NOFILE,
157 "file name already has no extension: "
158 "output will be in `nasm.out'");
159 strcpy(outname, "nasm.out");
160 } else
161 strcpy(p, extension);
164 #define RAA_BLKSIZE 4096 /* this many longs allocated at once */
165 #define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */
167 typedef struct RAA RAA;
168 typedef union RAA_UNION RAA_UNION;
169 typedef struct RAA_LEAF RAA_LEAF;
170 typedef struct RAA_BRANCH RAA_BRANCH;
172 struct RAA {
173 int layers;
174 long stepsize;
175 union RAA_UNION {
176 struct RAA_LEAF {
177 long data[RAA_BLKSIZE];
178 } l;
179 struct RAA_BRANCH {
180 struct RAA *data[RAA_LAYERSIZE];
181 } b;
182 } u;
185 #define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
186 #define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
188 #define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
190 static struct RAA *real_raa_init (int layers) {
191 struct RAA *r;
193 if (layers == 0) {
194 r = nasm_malloc (LEAFSIZ);
195 memset (r->u.l.data, 0, sizeof(r->u.l.data));
196 r->layers = 0;
197 r->stepsize = 1L;
198 } else {
199 r = nasm_malloc (BRANCHSIZ);
200 memset (r->u.b.data, 0, sizeof(r->u.b.data));
201 r->layers = layers;
202 r->stepsize = 1L;
203 while (layers--)
204 r->stepsize *= RAA_LAYERSIZE;
206 return r;
209 struct RAA *raa_init (void) {
210 return real_raa_init (0);
213 void raa_free (struct RAA *r) {
214 if (r->layers == 0)
215 nasm_free (r);
216 else {
217 struct RAA **p;
218 for (p = r->u.b.data; p - r->u.b.data < RAA_LAYERSIZE; p++)
219 if (*p)
220 raa_free (*p);
224 long raa_read (struct RAA *r, long posn) {
225 if (posn > r->stepsize * LAYERSIZ(r))
226 return 0L;
227 while (r->layers > 0) {
228 ldiv_t l;
229 l = ldiv (posn, r->stepsize);
230 r = r->u.b.data[l.quot];
231 posn = l.rem;
232 if (!r) /* better check this */
233 return 0L;
235 return r->u.l.data[posn];
238 struct RAA *raa_write (struct RAA *r, long posn, long value) {
239 struct RAA *result;
241 if (posn < 0)
242 nasm_malloc_error (ERR_PANIC, "negative position in raa_write");
244 while (r->stepsize * LAYERSIZ(r) < posn) {
246 * Must go up a layer.
248 struct RAA *s;
250 s = nasm_malloc (BRANCHSIZ);
251 memset (s->u.b.data, 0, sizeof(r->u.b.data));
252 s->layers = r->layers + 1;
253 s->stepsize = RAA_LAYERSIZE * r->stepsize;
254 s->u.b.data[0] = r;
255 r = s;
258 result = r;
260 while (r->layers > 0) {
261 ldiv_t l;
262 struct RAA **s;
263 l = ldiv (posn, r->stepsize);
264 s = &r->u.b.data[l.quot];
265 if (!*s)
266 *s = real_raa_init (r->layers - 1);
267 r = *s;
268 posn = l.rem;
271 r->u.l.data[posn] = value;
273 return result;
276 #define SAA_MAXLEN 8192
278 struct SAA {
280 * members `end' and `elem_len' are only valid in first link in
281 * list; `rptr' and `rpos' are used for reading
283 struct SAA *next, *end, *rptr;
284 long elem_len, length, posn, start, rpos;
285 char *data;
288 struct SAA *saa_init (long elem_len) {
289 struct SAA *s;
291 if (elem_len > SAA_MAXLEN)
292 nasm_malloc_error (ERR_PANIC | ERR_NOFILE, "SAA with huge elements");
294 s = nasm_malloc (sizeof(struct SAA));
295 s->posn = s->start = 0L;
296 s->elem_len = elem_len;
297 s->length = SAA_MAXLEN - (SAA_MAXLEN % elem_len);
298 s->data = nasm_malloc (s->length);
299 s->next = NULL;
300 s->end = s;
302 return s;
305 void saa_free (struct SAA *s) {
306 struct SAA *t;
308 while (s) {
309 t = s->next;
310 nasm_free (s->data);
311 nasm_free (s);
312 s = t;
316 void *saa_wstruct (struct SAA *s) {
317 void *p;
319 if (s->end->length - s->end->posn < s->elem_len) {
320 s->end->next = nasm_malloc (sizeof(struct SAA));
321 s->end->next->start = s->end->start + s->end->posn;
322 s->end = s->end->next;
323 s->end->length = s->length;
324 s->end->next = NULL;
325 s->end->posn = 0L;
326 s->end->data = nasm_malloc (s->length);
329 p = s->end->data + s->end->posn;
330 s->end->posn += s->elem_len;
331 return p;
334 void saa_wbytes (struct SAA *s, void *data, long len) {
335 char *d = data;
337 while (len > 0) {
338 long l = s->end->length - s->end->posn;
339 if (l > len)
340 l = len;
341 if (l > 0) {
342 if (d) {
343 memcpy (s->end->data + s->end->posn, d, l);
344 d += l;
345 } else
346 memset (s->end->data + s->end->posn, 0, l);
347 s->end->posn += l;
348 len -= l;
350 if (len > 0) {
351 s->end->next = nasm_malloc (sizeof(struct SAA));
352 s->end->next->start = s->end->start + s->end->posn;
353 s->end = s->end->next;
354 s->end->length = s->length;
355 s->end->next = NULL;
356 s->end->posn = 0L;
357 s->end->data = nasm_malloc (s->length);
362 void saa_rewind (struct SAA *s) {
363 s->rptr = s;
364 s->rpos = 0L;
367 void *saa_rstruct (struct SAA *s) {
368 void *p;
370 if (!s->rptr)
371 return NULL;
373 if (s->rptr->posn - s->rpos < s->elem_len) {
374 s->rptr = s->rptr->next;
375 if (!s->rptr)
376 return NULL; /* end of array */
377 s->rpos = 0L;
380 p = s->rptr->data + s->rpos;
381 s->rpos += s->elem_len;
382 return p;
385 void *saa_rbytes (struct SAA *s, long *len) {
386 void *p;
388 if (!s->rptr)
389 return NULL;
391 p = s->rptr->data + s->rpos;
392 *len = s->rptr->posn - s->rpos;
393 s->rptr = s->rptr->next;
394 s->rpos = 0L;
395 return p;
398 void saa_rnbytes (struct SAA *s, void *data, long len) {
399 char *d = data;
401 while (len > 0) {
402 long l;
404 if (!s->rptr)
405 return;
407 l = s->rptr->posn - s->rpos;
408 if (l > len)
409 l = len;
410 if (l > 0) {
411 memcpy (d, s->rptr->data + s->rpos, l);
412 d += l;
413 s->rpos += l;
414 len -= l;
416 if (len > 0) {
417 s->rptr = s->rptr->next;
418 s->rpos = 0L;
423 void saa_fread (struct SAA *s, long posn, void *data, long len) {
424 struct SAA *p;
425 long pos;
426 char *cdata = data;
428 if (!s->rptr || posn > s->rptr->start + s->rpos)
429 saa_rewind (s);
430 while (posn >= s->rptr->start + s->rptr->posn) {
431 s->rptr = s->rptr->next;
432 if (!s->rptr)
433 return; /* what else can we do?! */
436 p = s->rptr;
437 pos = posn - s->rptr->start;
438 while (len) {
439 long l = s->rptr->posn - pos;
440 if (l > len)
441 l = len;
442 memcpy (cdata, s->rptr->data+pos, l);
443 len -= l;
444 cdata += l;
445 p = p->next;
446 if (!p)
447 return;
448 pos = 0L;
452 void saa_fwrite (struct SAA *s, long posn, void *data, long len) {
453 struct SAA *p;
454 long pos;
455 char *cdata = data;
457 if (!s->rptr || posn > s->rptr->start + s->rpos)
458 saa_rewind (s);
459 while (posn >= s->rptr->start + s->rptr->posn) {
460 s->rptr = s->rptr->next;
461 if (!s->rptr)
462 return; /* what else can we do?! */
465 p = s->rptr;
466 pos = posn - s->rptr->start;
467 while (len) {
468 long l = s->rptr->posn - pos;
469 if (l > len)
470 l = len;
471 memcpy (s->rptr->data+pos, cdata, l);
472 len -= l;
473 cdata += l;
474 p = p->next;
475 if (!p)
476 return;
477 pos = 0L;
481 void saa_fpwrite (struct SAA *s, FILE *fp) {
482 char *data;
483 long len;
485 saa_rewind (s);
486 while ( (data = saa_rbytes (s, &len)) )
487 fwrite (data, 1, len, fp);