Move backend-specific code to output/; break out null debug stuff
[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 license given in the file "LICENSE"
6  * distributed in the NASM archive.
7  */
8
9 #include "compiler.h"
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <inttypes.h>
16
17 #include "nasm.h"
18 #include "nasmlib.h"
19 #include "insns.h"
20
21 int globalbits = 0;    /* defined in nasm.h, works better here for ASM+DISASM */
22 efunc nasm_malloc_error;        /* Exported for the benefit of vsnprintf.c */
23
24 #ifdef LOGALLOC
25 static FILE *logfp;
26 #endif
27
28 /* Uninitialized -> all zero by C spec */
29 const uint8_t zero_buffer[ZERO_BUF_SIZE];
30
31 /*
32  * Prepare a table of tolower() results.  This avoids function calls
33  * on some platforms.
34  */
35
36 unsigned char nasm_tolower_tab[256];
37
38 void tolower_init(void)
39 {
40     int i;
41
42     for (i = 0; i < 256; i++)
43         nasm_tolower_tab[i] = tolower(i);
44 }
45
46 void nasm_set_malloc_error(efunc error)
47 {
48     nasm_malloc_error = error;
49 #ifdef LOGALLOC
50     logfp = fopen("malloc.log", "w");
51     setvbuf(logfp, NULL, _IOLBF, BUFSIZ);
52     fprintf(logfp, "null pointer is %p\n", NULL);
53 #endif
54 }
55
56 #ifdef LOGALLOC
57 void *nasm_malloc_log(char *file, int line, size_t size)
58 #else
59 void *nasm_malloc(size_t size)
60 #endif
61 {
62     void *p = malloc(size);
63     if (!p)
64         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
65 #ifdef LOGALLOC
66     else
67         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
68                 file, line, (long)size, p);
69 #endif
70     return p;
71 }
72
73 #ifdef LOGALLOC
74 void *nasm_zalloc_log(char *file, int line, size_t size)
75 #else
76 void *nasm_zalloc(size_t size)
77 #endif
78 {
79     void *p = calloc(size, 1);
80     if (!p)
81         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
82 #ifdef LOGALLOC
83     else
84         fprintf(logfp, "%s %d calloc(%ld, 1) returns %p\n",
85                 file, line, (long)size, p);
86 #endif
87     return p;
88 }
89
90 #ifdef LOGALLOC
91 void *nasm_realloc_log(char *file, int line, void *q, size_t size)
92 #else
93 void *nasm_realloc(void *q, size_t size)
94 #endif
95 {
96     void *p = q ? realloc(q, size) : malloc(size);
97     if (!p)
98         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
99 #ifdef LOGALLOC
100     else if (q)
101         fprintf(logfp, "%s %d realloc(%p,%ld) returns %p\n",
102                 file, line, q, (long)size, p);
103     else
104         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
105                 file, line, (long)size, p);
106 #endif
107     return p;
108 }
109
110 #ifdef LOGALLOC
111 void nasm_free_log(char *file, int line, void *q)
112 #else
113 void nasm_free(void *q)
114 #endif
115 {
116     if (q) {
117 #ifdef LOGALLOC
118         fprintf(logfp, "%s %d free(%p)\n", file, line, q);
119 #endif
120         free(q);
121     }
122 }
123
124 #ifdef LOGALLOC
125 char *nasm_strdup_log(char *file, int line, const char *s)
126 #else
127 char *nasm_strdup(const char *s)
128 #endif
129 {
130     char *p;
131     int size = strlen(s) + 1;
132
133     p = malloc(size);
134     if (!p)
135         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
136 #ifdef LOGALLOC
137     else
138         fprintf(logfp, "%s %d strdup(%ld) returns %p\n",
139                 file, line, (long)size, p);
140 #endif
141     strcpy(p, s);
142     return p;
143 }
144
145 #ifdef LOGALLOC
146 char *nasm_strndup_log(char *file, int line, char *s, size_t len)
147 #else
148 char *nasm_strndup(char *s, size_t len)
149 #endif
150 {
151     char *p;
152     int size = len + 1;
153
154     p = malloc(size);
155     if (!p)
156         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
157 #ifdef LOGALLOC
158     else
159         fprintf(logfp, "%s %d strndup(%ld) returns %p\n",
160                 file, line, (long)size, p);
161 #endif
162     strncpy(p, s, len);
163     p[len] = '\0';
164     return p;
165 }
166
167 #ifndef nasm_stricmp
168 int nasm_stricmp(const char *s1, const char *s2)
169 {
170     unsigned char c1, c2;
171     int d;
172
173     while (1) {
174         c1 = nasm_tolower(*s1++);
175         c2 = nasm_tolower(*s2++);
176         d = c1-c2;
177
178         if (d)
179             return d;
180         if (!c1)
181             break;
182     }
183     return 0;
184 }
185 #endif
186
187 #ifndef nasm_strnicmp
188 int nasm_strnicmp(const char *s1, const char *s2, size_t n)
189 {
190     unsigned char c1, c2;
191     int d;
192
193     while (n--) {
194         c1 = nasm_tolower(*s1++);
195         c2 = nasm_tolower(*s2++);
196         d = c1-c2;
197
198         if (d)
199             return d;
200         if (!c1)
201             break;
202     }
203     return 0;
204 }
205 #endif
206
207 int nasm_memicmp(const char *s1, const char *s2, size_t n)
208 {
209     unsigned char c1, c2;
210     int d;
211
212     while (n--) {
213         c1 = nasm_tolower(*s1++);
214         c2 = nasm_tolower(*s2++);
215         d = c1-c2;
216         if (d)
217             return d;
218     }
219     return 0;
220 }
221
222 #ifndef nasm_strsep
223 char *nasm_strsep(char **stringp, const char *delim)
224 {
225         char *s = *stringp;
226         char *e;
227
228         if (!s)
229                 return NULL;
230
231         e = strpbrk(s, delim);
232         if (e)
233                 *e++ = '\0';
234
235         *stringp = e;
236         return s;
237 }
238 #endif
239
240
241 #define lib_isnumchar(c)   (nasm_isalnum(c) || (c) == '$' || (c) == '_')
242 #define numvalue(c)  ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
243
244 static int radix_letter(char c)
245 {
246     switch (c) {
247     case 'b': case 'B':
248     case 'y': case 'Y':
249         return 2;               /* Binary */
250     case 'o': case 'O':
251     case 'q': case 'Q':
252         return 8;               /* Octal */
253     case 'h': case 'H':
254     case 'x': case 'X':
255         return 16;              /* Hexadecimal */
256     case 'd': case 'D':
257     case 't': case 'T':
258         return 10;              /* Decimal */
259     default:
260         return 0;               /* Not a known radix letter */
261     }
262 }
263
264 int64_t readnum(char *str, bool *error)
265 {
266     char *r = str, *q;
267     int32_t pradix, sradix, radix;
268     int plen, slen, len;
269     uint64_t result, checklimit;
270     int digit, last;
271     bool warn = false;
272     int sign = 1;
273
274     *error = false;
275
276     while (nasm_isspace(*r))
277         r++;                    /* find start of number */
278
279     /*
280      * If the number came from make_tok_num (as a result of an %assign), it
281      * might have a '-' built into it (rather than in a preceeding token).
282      */
283     if (*r == '-') {
284         r++;
285         sign = -1;
286     }
287
288     q = r;
289
290     while (lib_isnumchar(*q))
291         q++;                    /* find end of number */
292
293     len = q-r;
294     if (!len) {
295         /* Not numeric */
296         *error = true;
297         return 0;
298     }
299
300     /*
301      * Handle radix formats:
302      *
303      * 0<radix-letter><string>
304      * $<string>                (hexadecimal)
305      * <string><radix-letter>
306      */
307     pradix = sradix = 0;
308     plen = slen = 0;
309
310     if (len > 2 && *r == '0' && (pradix = radix_letter(r[1])) != 0)
311         plen = 2;
312     else if (len > 1 && *r == '$')
313         pradix = 16, plen = 1;
314
315     if (len > 1 && (sradix = radix_letter(q[-1])) != 0)
316         slen = 1;
317
318     if (pradix > sradix) {
319         radix = pradix;
320         r += plen;
321     } else if (sradix > pradix) {
322         radix = sradix;
323         q -= slen;
324     } else {
325         /* Either decimal, or invalid -- if invalid, we'll trip up
326            further down. */
327         radix = 10;
328     }
329
330     /*
331      * `checklimit' must be 2**64 / radix. We can't do that in
332      * 64-bit arithmetic, which we're (probably) using, so we
333      * cheat: since we know that all radices we use are even, we
334      * can divide 2**63 by radix/2 instead.
335      */
336     checklimit = 0x8000000000000000ULL / (radix >> 1);
337
338     /*
339      * Calculate the highest allowable value for the last digit of a
340      * 64-bit constant... in radix 10, it is 6, otherwise it is 0
341      */
342     last = (radix == 10 ? 6 : 0);
343
344     result = 0;
345     while (*r && r < q) {
346         if (*r != '_') {
347             if (*r < '0' || (*r > '9' && *r < 'A')
348                 || (digit = numvalue(*r)) >= radix) {
349                 *error = true;
350                 return 0;
351             }
352             if (result > checklimit ||
353                 (result == checklimit && digit >= last)) {
354                 warn = true;
355             }
356
357             result = radix * result + digit;
358         }
359         r++;
360     }
361
362     if (warn)
363         nasm_malloc_error(ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
364                           "numeric constant %s does not fit in 64 bits",
365                           str);
366
367     return result * sign;
368 }
369
370 int64_t readstrnum(char *str, int length, bool *warn)
371 {
372     int64_t charconst = 0;
373     int i;
374
375     *warn = false;
376
377     str += length;
378     if (globalbits == 64) {
379         for (i = 0; i < length; i++) {
380             if (charconst & 0xFF00000000000000ULL)
381                 *warn = true;
382             charconst = (charconst << 8) + (uint8_t)*--str;
383         }
384     } else {
385         for (i = 0; i < length; i++) {
386             if (charconst & 0xFF000000UL)
387                 *warn = true;
388             charconst = (charconst << 8) + (uint8_t)*--str;
389         }
390     }
391     return charconst;
392 }
393
394 static int32_t next_seg;
395
396 void seg_init(void)
397 {
398     next_seg = 0;
399 }
400
401 int32_t seg_alloc(void)
402 {
403     return (next_seg += 2) - 2;
404 }
405
406 #ifdef WORDS_LITTLEENDIAN
407
408 void fwriteint16_t(uint16_t data, FILE * fp)
409 {
410     fwrite(&data, 1, 2, fp);
411 }
412
413 void fwriteint32_t(uint32_t data, FILE * fp)
414 {
415     fwrite(&data, 1, 4, fp);
416 }
417
418 void fwriteint64_t(uint64_t data, FILE * fp)
419 {
420     fwrite(&data, 1, 8, fp);
421 }
422
423 void fwriteaddr(uint64_t data, int size, FILE * fp)
424 {
425     fwrite(&data, 1, size, fp);
426 }
427
428 #else /* not WORDS_LITTLEENDIAN */
429
430 void fwriteint16_t(uint16_t data, FILE * fp)
431 {
432     char buffer[2], *p = buffer;
433     WRITESHORT(p, data);
434     fwrite(buffer, 1, 2, fp);
435 }
436
437 void fwriteint32_t(uint32_t data, FILE * fp)
438 {
439     char buffer[4], *p = buffer;
440     WRITELONG(p, data);
441     fwrite(buffer, 1, 4, fp);
442 }
443
444 void fwriteint64_t(uint64_t data, FILE * fp)
445 {
446     char buffer[8], *p = buffer;
447     WRITEDLONG(p, data);
448     fwrite(buffer, 1, 8, fp);
449 }
450
451 void fwriteaddr(uint64_t data, int size, FILE * fp)
452 {
453     char buffer[8], *p = buffer;
454     WRITEADDR(p, data, size);
455     fwrite(buffer, 1, size, fp);
456 }
457
458 #endif
459
460 size_t fwritezero(size_t bytes, FILE *fp)
461 {
462     size_t count = 0;
463     size_t blksize;
464     size_t rv;
465
466     while (bytes) {
467         blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE;
468
469         rv = fwrite(zero_buffer, 1, blksize, fp);
470         if (!rv)
471             break;
472
473         count += rv;
474         bytes -= rv;
475     }
476
477     return count;
478 }
479
480 void standard_extension(char *inname, char *outname, char *extension,
481                         efunc error)
482 {
483     char *p, *q;
484
485     if (*outname)               /* file name already exists, */
486         return;                 /* so do nothing */
487     q = inname;
488     p = outname;
489     while (*q)
490         *p++ = *q++;            /* copy, and find end of string */
491     *p = '\0';                  /* terminate it */
492     while (p > outname && *--p != '.') ;        /* find final period (or whatever) */
493     if (*p != '.')
494         while (*p)
495             p++;                /* go back to end if none found */
496     if (!strcmp(p, extension)) {        /* is the extension already there? */
497         if (*extension)
498             error(ERR_WARNING | ERR_NOFILE,
499                   "file name already ends in `%s': "
500                   "output will be in `nasm.out'", extension);
501         else
502             error(ERR_WARNING | ERR_NOFILE,
503                   "file name already has no extension: "
504                   "output will be in `nasm.out'");
505         strcpy(outname, "nasm.out");
506     } else
507         strcpy(p, extension);
508 }
509
510 /*
511  * Common list of prefix names
512  */
513 static const char *prefix_names[] = {
514     "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
515     "rep", "repe", "repne", "repnz", "repz", "times", "wait"
516 };
517
518 const char *prefix_name(int token)
519 {
520     unsigned int prefix = token-PREFIX_ENUM_START;
521     if (prefix > elements(prefix_names))
522         return NULL;
523
524     return prefix_names[prefix];
525 }
526
527 /*
528  * Binary search.
529  */
530 int bsi(const char *string, const char **array, int size)
531 {
532     int i = -1, j = size;       /* always, i < index < j */
533     while (j - i >= 2) {
534         int k = (i + j) / 2;
535         int l = strcmp(string, array[k]);
536         if (l < 0)              /* it's in the first half */
537             j = k;
538         else if (l > 0)         /* it's in the second half */
539             i = k;
540         else                    /* we've got it :) */
541             return k;
542     }
543     return -1;                  /* we haven't got it :( */
544 }
545
546 int bsii(const char *string, const char **array, int size)
547 {
548     int i = -1, j = size;       /* always, i < index < j */
549     while (j - i >= 2) {
550         int k = (i + j) / 2;
551         int l = nasm_stricmp(string, array[k]);
552         if (l < 0)              /* it's in the first half */
553             j = k;
554         else if (l > 0)         /* it's in the second half */
555             i = k;
556         else                    /* we've got it :) */
557             return k;
558     }
559     return -1;                  /* we haven't got it :( */
560 }
561
562 static char *file_name = NULL;
563 static int32_t line_number = 0;
564
565 char *src_set_fname(char *newname)
566 {
567     char *oldname = file_name;
568     file_name = newname;
569     return oldname;
570 }
571
572 int32_t src_set_linnum(int32_t newline)
573 {
574     int32_t oldline = line_number;
575     line_number = newline;
576     return oldline;
577 }
578
579 int32_t src_get_linnum(void)
580 {
581     return line_number;
582 }
583
584 int src_get(int32_t *xline, char **xname)
585 {
586     if (!file_name || !*xname || strcmp(*xname, file_name)) {
587         nasm_free(*xname);
588         *xname = file_name ? nasm_strdup(file_name) : NULL;
589         *xline = line_number;
590         return -2;
591     }
592     if (*xline != line_number) {
593         int32_t tmp = line_number - *xline;
594         *xline = line_number;
595         return tmp;
596     }
597     return 0;
598 }
599
600 char *nasm_strcat(const char *one, const char *two)
601 {
602     char *rslt;
603     int l1 = strlen(one);
604     rslt = nasm_malloc(l1 + strlen(two) + 1);
605     strcpy(rslt, one);
606     strcpy(rslt + l1, two);
607     return rslt;
608 }