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