NASM 0.95
[platform/upstream/nasm.git] / nasmlib.c
1 /* nasmlib.c    library routines 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 <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13
14 #include "nasm.h"
15 #include "nasmlib.h"
16
17 static efunc nasm_malloc_error;
18
19 #ifdef LOGALLOC
20 static FILE *logfp;
21 #endif
22
23 void nasm_set_malloc_error (efunc error) {
24     nasm_malloc_error = error;
25 #ifdef LOGALLOC
26     logfp = fopen ("malloc.log", "w");
27     setvbuf (logfp, NULL, _IOLBF, BUFSIZ);
28     fprintf (logfp, "null pointer is %p\n", NULL);
29 #endif
30 }
31
32 #ifdef LOGALLOC
33 void *nasm_malloc_log (char *file, int line, size_t size)
34 #else
35 void *nasm_malloc (size_t size)
36 #endif
37 {
38     void *p = malloc(size);
39     if (!p)
40         nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
41 #ifdef LOGALLOC
42     else
43         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
44                 file, line, (long)size, p);
45 #endif
46     return p;
47 }
48
49 #ifdef LOGALLOC
50 void *nasm_realloc_log (char *file, int line, void *q, size_t size)
51 #else
52 void *nasm_realloc (void *q, size_t size)
53 #endif
54 {
55     void *p = q ? realloc(q, size) : malloc(size);
56     if (!p)
57         nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
58 #ifdef LOGALLOC
59     else if (q)
60         fprintf(logfp, "%s %d realloc(%p,%ld) returns %p\n",
61                 file, line, q, (long)size, p);
62     else
63         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
64                 file, line, (long)size, p);
65 #endif
66     return p;
67 }
68
69 #ifdef LOGALLOC
70 void nasm_free_log (char *file, int line, void *q)
71 #else
72 void nasm_free (void *q)
73 #endif
74 {
75     if (q) {
76         free (q);
77 #ifdef LOGALLOC
78         fprintf(logfp, "%s %d free(%p)\n",
79                 file, line, q);
80 #endif
81     }
82 }
83
84 #ifdef LOGALLOC
85 char *nasm_strdup_log (char *file, int line, char *s)
86 #else
87 char *nasm_strdup (char *s)
88 #endif
89 {
90     char *p;
91     int size = strlen(s)+1;
92
93     p = malloc(size);
94     if (!p)
95         nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
96 #ifdef LOGALLOC
97     else
98         fprintf(logfp, "%s %d strdup(%ld) returns %p\n",
99                 file, line, (long)size, p);
100 #endif
101     strcpy (p, s);
102     return p;
103 }
104
105 int nasm_stricmp (char *s1, char *s2) {
106     while (*s1 && toupper(*s1) == toupper(*s2))
107         s1++, s2++;
108     if (!*s1 && !*s2)
109         return 0;
110     else if (toupper(*s1) < toupper(*s2))
111         return -1;
112     else
113         return 1;
114 }
115
116 int nasm_strnicmp (char *s1, char *s2, int n) {
117     while (n > 0 && *s1 && toupper(*s1) == toupper(*s2))
118         s1++, s2++, n--;
119     if ((!*s1 && !*s2) || n==0)
120         return 0;
121     else if (toupper(*s1) < toupper(*s2))
122         return -1;
123     else
124         return 1;
125 }
126
127 #define lib_isnumchar(c)   ( isalnum(c) || (c) == '$')
128 #define numvalue(c)  ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
129
130 long readnum (char *str, int *error) {
131     char *r = str, *q;
132     long radix;
133     long result;
134
135     *error = FALSE;
136
137     while (isspace(*r)) r++;           /* find start of number */
138     q = r;
139
140     while (lib_isnumchar(*q)) q++;     /* find end of number */
141
142     /*
143      * If it begins 0x, 0X or $, or ends in H, it's in hex. if it
144      * ends in Q, it's octal. if it ends in B, it's binary.
145      * Otherwise, it's ordinary decimal.
146      */
147     if (*r=='0' && (r[1]=='x' || r[1]=='X'))
148         radix = 16, r += 2;
149     else if (*r=='$')
150         radix = 16, r++;
151     else if (q[-1]=='H' || q[-1]=='h')
152         radix = 16 , q--;
153     else if (q[-1]=='Q' || q[-1]=='q')
154         radix = 8 , q--;
155     else if (q[-1]=='B' || q[-1]=='b')
156         radix = 2 , q--;
157     else
158         radix = 10;
159
160     result = 0;
161     while (*r && r < q) {
162         if (*r<'0' || (*r>'9' && *r<'A') || numvalue(*r)>=radix) {
163             *error = TRUE;
164             return 0;
165         }
166         result = radix * result + numvalue(*r);
167         r++;
168     }
169     return result;
170 }
171
172 static long next_seg;
173
174 void seg_init(void) {
175     next_seg = 0;
176 }
177
178 long seg_alloc(void) {
179     return (next_seg += 2) - 2;
180 }
181
182 void fwriteshort (int data, FILE *fp) {
183     fputc ((int) (data & 255), fp);
184     fputc ((int) ((data >> 8) & 255), fp);
185 }
186
187 void fwritelong (long data, FILE *fp) {
188     fputc ((int) (data & 255), fp);
189     fputc ((int) ((data >> 8) & 255), fp);
190     fputc ((int) ((data >> 16) & 255), fp);
191     fputc ((int) ((data >> 24) & 255), fp);
192 }
193
194 void standard_extension (char *inname, char *outname, char *extension,
195                          efunc error) {
196     char *p, *q;
197
198     q = inname;
199     p = outname;
200     while (*q) *p++ = *q++;            /* copy, and find end of string */
201     *p = '\0';                         /* terminate it */
202     while (p > outname && *--p != '.');/* find final period (or whatever) */
203     if (*p != '.') while (*p) p++;     /* go back to end if none found */
204     if (!strcmp(p, extension)) {       /* is the extension already there? */
205         if (*extension)
206             error(ERR_WARNING | ERR_NOFILE,
207                   "file name already ends in `%s': "
208                   "output will be in `nasm.out'",
209                   extension);
210         else
211             error(ERR_WARNING | ERR_NOFILE,
212                   "file name already has no extension: "
213                   "output will be in `nasm.out'");
214         strcpy(outname, "nasm.out");
215     } else
216         strcpy(p, extension);
217 }
218
219 #define RAA_BLKSIZE 4096               /* this many longs allocated at once */
220 #define RAA_LAYERSIZE 1024             /* this many _pointers_ allocated */
221
222 typedef struct RAA RAA;
223 typedef union RAA_UNION RAA_UNION;
224 typedef struct RAA_LEAF RAA_LEAF;
225 typedef struct RAA_BRANCH RAA_BRANCH;
226
227 struct RAA {
228     int layers;
229     long stepsize;
230     union RAA_UNION {
231         struct RAA_LEAF {
232             long data[RAA_BLKSIZE];
233         } l;
234         struct RAA_BRANCH {
235             struct RAA *data[RAA_LAYERSIZE];
236         } b;
237     } u;
238 };
239
240 #define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
241 #define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
242
243 #define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
244
245 static struct RAA *real_raa_init (int layers) {
246     struct RAA *r;
247
248     if (layers == 0) {
249         r = nasm_malloc (LEAFSIZ);
250         memset (r->u.l.data, 0, sizeof(r->u.l.data));
251         r->layers = 0;
252         r->stepsize = 1L;
253     } else {
254         r = nasm_malloc (BRANCHSIZ);
255         memset (r->u.b.data, 0, sizeof(r->u.b.data));
256         r->layers = layers;
257         r->stepsize = 1L;
258         while (layers--)
259             r->stepsize *= RAA_LAYERSIZE;
260     }
261     return r;
262 }
263
264 struct RAA *raa_init (void) {
265     return real_raa_init (0);
266 }
267
268 void raa_free (struct RAA *r) {
269     if (r->layers == 0)
270         nasm_free (r);
271     else {
272         struct RAA **p;
273         for (p = r->u.b.data; p - r->u.b.data < RAA_LAYERSIZE; p++)
274             if (*p)
275                 raa_free (*p);
276     }
277 }
278
279 long raa_read (struct RAA *r, long posn) {
280     if (posn > r->stepsize * LAYERSIZ(r))
281         return 0L;
282     while (r->layers > 0) {
283         ldiv_t l;
284         l = ldiv (posn, r->stepsize);
285         r = r->u.b.data[l.quot];
286         posn = l.rem;
287         if (!r)                        /* better check this */
288             return 0L;
289     }
290     return r->u.l.data[posn];
291 }
292
293 struct RAA *raa_write (struct RAA *r, long posn, long value) {
294     struct RAA *result;
295
296     if (posn < 0)
297         nasm_malloc_error (ERR_PANIC, "negative position in raa_write");
298
299     while (r->stepsize * LAYERSIZ(r) < posn) {
300         /*
301          * Must go up a layer.
302          */
303         struct RAA *s;
304
305         s = nasm_malloc (BRANCHSIZ);
306         memset (s->u.b.data, 0, sizeof(r->u.b.data));
307         s->layers = r->layers + 1;
308         s->stepsize = RAA_LAYERSIZE * r->stepsize;
309         s->u.b.data[0] = r;
310         r = s;
311     }
312
313     result = r;
314
315     while (r->layers > 0) {
316         ldiv_t l;
317         struct RAA **s;
318         l = ldiv (posn, r->stepsize);
319         s = &r->u.b.data[l.quot];
320         if (!*s)
321             *s = real_raa_init (r->layers - 1);
322         r = *s;
323         posn = l.rem;
324     }
325
326     r->u.l.data[posn] = value;
327
328     return result;
329 }
330
331 #define SAA_MAXLEN 8192
332
333 struct SAA {
334     /*
335      * members `end' and `elem_len' are only valid in first link in
336      * list; `rptr' and `rpos' are used for reading
337      */
338     struct SAA *next, *end, *rptr;
339     long elem_len, length, posn, start, rpos;
340     char *data;
341 };
342
343 struct SAA *saa_init (long elem_len) {
344     struct SAA *s;
345
346     if (elem_len > SAA_MAXLEN)
347         nasm_malloc_error (ERR_PANIC | ERR_NOFILE, "SAA with huge elements");
348
349     s = nasm_malloc (sizeof(struct SAA));
350     s->posn = s->start = 0L;
351     s->elem_len = elem_len;
352     s->length = SAA_MAXLEN - (SAA_MAXLEN % elem_len);
353     s->data = nasm_malloc (s->length);
354     s->next = NULL;
355     s->end = s;
356
357     return s;
358 }
359
360 void saa_free (struct SAA *s) {
361     struct SAA *t;
362
363     while (s) {
364         t = s->next;
365         nasm_free (s->data);
366         nasm_free (s);
367         s = t;
368     }
369 }
370
371 void *saa_wstruct (struct SAA *s) {
372     void *p;
373
374     if (s->end->length - s->end->posn < s->elem_len) {
375         s->end->next = nasm_malloc (sizeof(struct SAA));
376         s->end->next->start = s->end->start + s->end->posn;
377         s->end = s->end->next;
378         s->end->length = s->length;
379         s->end->next = NULL;
380         s->end->posn = 0L;
381         s->end->data = nasm_malloc (s->length);
382     }
383
384     p = s->end->data + s->end->posn;
385     s->end->posn += s->elem_len;
386     return p;
387 }
388
389 void saa_wbytes (struct SAA *s, void *data, long len) {
390     char *d = data;
391
392     while (len > 0) {
393         long l = s->end->length - s->end->posn;
394         if (l > len)
395             l = len;
396         if (l > 0) {
397             if (d) {
398                 memcpy (s->end->data + s->end->posn, d, l);
399                 d += l;
400             } else
401                 memset (s->end->data + s->end->posn, 0, l);
402             s->end->posn += l;
403             len -= l;
404         }
405         if (len > 0) {
406             s->end->next = nasm_malloc (sizeof(struct SAA));
407             s->end->next->start = s->end->start + s->end->posn;
408             s->end = s->end->next;
409             s->end->length = s->length;
410             s->end->next = NULL;
411             s->end->posn = 0L;
412             s->end->data = nasm_malloc (s->length);
413         }
414     }
415 }
416
417 void saa_rewind (struct SAA *s) {
418     s->rptr = s;
419     s->rpos = 0L;
420 }
421
422 void *saa_rstruct (struct SAA *s) {
423     void *p;
424
425     if (!s->rptr)
426         return NULL;
427
428     if (s->rptr->posn - s->rpos < s->elem_len) {
429         s->rptr = s->rptr->next;
430         if (!s->rptr)
431             return NULL;               /* end of array */
432         s->rpos = 0L;
433     }
434
435     p = s->rptr->data + s->rpos;
436     s->rpos += s->elem_len;
437     return p;
438 }
439
440 void *saa_rbytes (struct SAA *s, long *len) {
441     void *p;
442
443     if (!s->rptr)
444         return NULL;
445
446     p = s->rptr->data + s->rpos;
447     *len = s->rptr->posn - s->rpos;
448     s->rptr = s->rptr->next;
449     s->rpos = 0L;
450     return p;
451 }
452
453 void saa_rnbytes (struct SAA *s, void *data, long len) {
454     char *d = data;
455
456     while (len > 0) {
457         long l;
458
459         if (!s->rptr)
460             return;
461
462         l = s->rptr->posn - s->rpos;
463         if (l > len)
464             l = len;
465         if (l > 0) {
466             memcpy (d, s->rptr->data + s->rpos, l);
467             d += l;
468             s->rpos += l;
469             len -= l;
470         }
471         if (len > 0) {
472             s->rptr = s->rptr->next;
473             s->rpos = 0L;
474         }
475     }
476 }
477
478 void saa_fread (struct SAA *s, long posn, void *data, long len) {
479     struct SAA *p;
480     long pos;
481     char *cdata = data;
482
483     if (!s->rptr || posn > s->rptr->start + s->rpos)
484         saa_rewind (s);
485     while (posn >= s->rptr->start + s->rptr->posn) {
486         s->rptr = s->rptr->next;
487         if (!s->rptr)
488             return;                    /* what else can we do?! */
489     }
490
491     p = s->rptr;
492     pos = posn - s->rptr->start;
493     while (len) {
494         long l = s->rptr->posn - pos;
495         if (l > len)
496             l = len;
497         memcpy (cdata, s->rptr->data+pos, l);
498         len -= l;
499         cdata += l;
500         p = p->next;
501         if (!p)
502             return;
503         pos = 0L;
504     }
505 }
506
507 void saa_fwrite (struct SAA *s, long posn, void *data, long len) {
508     struct SAA *p;
509     long pos;
510     char *cdata = data;
511
512     if (!s->rptr || posn > s->rptr->start + s->rpos)
513         saa_rewind (s);
514     while (posn >= s->rptr->start + s->rptr->posn) {
515         s->rptr = s->rptr->next;
516         if (!s->rptr)
517             return;                    /* what else can we do?! */
518     }
519
520     p = s->rptr;
521     pos = posn - s->rptr->start;
522     while (len) {
523         long l = s->rptr->posn - pos;
524         if (l > len)
525             l = len;
526         memcpy (s->rptr->data+pos, cdata, l);
527         len -= l;
528         cdata += l;
529         p = p->next;
530         if (!p)
531             return;
532         pos = 0L;
533     }
534 }
535
536 void saa_fpwrite (struct SAA *s, FILE *fp) {
537     char *data;
538     long len;
539
540     saa_rewind (s);
541     while ( (data = saa_rbytes (s, &len)) )
542         fwrite (data, 1, len, fp);
543 }