output: outmac -- Fix few nits during merge
[nasm.git] / nasmlib.c
blob656350d5835f10003e43c20ecfa4f5894f76c605
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2016 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
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.
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.
32 * ----------------------------------------------------------------------- */
35 * nasmlib.c library routines for the Netwide Assembler
38 #include "compiler.h"
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <errno.h>
45 #include <inttypes.h>
47 #include "nasm.h"
48 #include "nasmlib.h"
49 #include "insns.h"
51 int globalbits = 0; /* defined in nasm.h, works better here for ASM+DISASM */
52 static vefunc nasm_verror; /* Global error handling function */
54 /* Uninitialized -> all zero by C spec */
55 const uint8_t zero_buffer[ZERO_BUF_SIZE];
58 * Prepare a table of tolower() results. This avoids function calls
59 * on some platforms.
62 unsigned char nasm_tolower_tab[256];
64 void tolower_init(void)
66 int i;
68 for (i = 0; i < 256; i++)
69 nasm_tolower_tab[i] = tolower(i);
72 void nasm_set_verror(vefunc ve)
74 nasm_verror = ve;
77 void nasm_error(int severity, const char *fmt, ...)
79 va_list ap;
81 va_start(ap, fmt);
82 nasm_verror(severity, fmt, ap);
83 va_end(ap);
86 no_return nasm_panic(int flags, const char *fmt, ...)
88 va_list ap;
90 va_start(ap, fmt);
91 nasm_verror(flags | ERR_PANIC, fmt, ap);
92 abort(); /* We should never get here */
95 no_return nasm_panic_from_macro(const char *file, int line)
97 nasm_panic(ERR_NOFILE, "Internal error at %s:%d\n", file, line);
100 void *nasm_malloc(size_t size)
102 void *p = malloc(size);
103 if (!p)
104 nasm_error(ERR_FATAL | ERR_NOFILE, "out of memory");
105 return p;
108 void *nasm_zalloc(size_t size)
110 void *p = calloc(size, 1);
111 if (!p)
112 nasm_error(ERR_FATAL | ERR_NOFILE, "out of memory");
113 return p;
116 void *nasm_realloc(void *q, size_t size)
118 void *p = q ? realloc(q, size) : malloc(size);
119 if (!p)
120 nasm_error(ERR_FATAL | ERR_NOFILE, "out of memory");
121 return p;
124 void nasm_free(void *q)
126 if (q)
127 free(q);
130 char *nasm_strdup(const char *s)
132 char *p;
133 int size = strlen(s) + 1;
135 p = malloc(size);
136 if (!p)
137 nasm_error(ERR_FATAL | ERR_NOFILE, "out of memory");
138 strcpy(p, s);
139 return p;
142 char *nasm_strndup(const char *s, size_t len)
144 char *p;
145 int size = len + 1;
147 p = malloc(size);
148 if (!p)
149 nasm_error(ERR_FATAL | ERR_NOFILE, "out of memory");
150 strncpy(p, s, len);
151 p[len] = '\0';
152 return p;
155 no_return nasm_assert_failed(const char *file, int line, const char *msg)
157 nasm_error(ERR_FATAL, "assertion %s failed at %s:%d", msg, file, line);
158 exit(1);
161 void nasm_write(const void *ptr, size_t size, FILE *f)
163 size_t n = fwrite(ptr, 1, size, f);
164 if (n != size)
165 nasm_error(ERR_FATAL, "unable to write output: %s", strerror(errno));
168 #ifndef nasm_stricmp
169 int nasm_stricmp(const char *s1, const char *s2)
171 unsigned char c1, c2;
172 int d;
174 while (1) {
175 c1 = nasm_tolower(*s1++);
176 c2 = nasm_tolower(*s2++);
177 d = c1-c2;
179 if (d)
180 return d;
181 if (!c1)
182 break;
184 return 0;
186 #endif
188 #ifndef nasm_strnicmp
189 int nasm_strnicmp(const char *s1, const char *s2, size_t n)
191 unsigned char c1, c2;
192 int d;
194 while (n--) {
195 c1 = nasm_tolower(*s1++);
196 c2 = nasm_tolower(*s2++);
197 d = c1-c2;
199 if (d)
200 return d;
201 if (!c1)
202 break;
204 return 0;
206 #endif
208 int nasm_memicmp(const char *s1, const char *s2, size_t n)
210 unsigned char c1, c2;
211 int d;
213 while (n--) {
214 c1 = nasm_tolower(*s1++);
215 c2 = nasm_tolower(*s2++);
216 d = c1-c2;
217 if (d)
218 return d;
220 return 0;
223 #ifndef nasm_strsep
224 char *nasm_strsep(char **stringp, const char *delim)
226 char *s = *stringp;
227 char *e;
229 if (!s)
230 return NULL;
232 e = strpbrk(s, delim);
233 if (e)
234 *e++ = '\0';
236 *stringp = e;
237 return s;
239 #endif
242 #define lib_isnumchar(c) (nasm_isalnum(c) || (c) == '$' || (c) == '_')
244 static int radix_letter(char c)
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 */
264 int64_t readnum(char *str, bool *error)
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;
274 *error = false;
276 while (nasm_isspace(*r))
277 r++; /* find start of number */
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).
283 if (*r == '-') {
284 r++;
285 sign = -1;
288 q = r;
290 while (lib_isnumchar(*q))
291 q++; /* find end of number */
293 len = q-r;
294 if (!len) {
295 /* Not numeric */
296 *error = true;
297 return 0;
301 * Handle radix formats:
303 * 0<radix-letter><string>
304 * $<string> (hexadecimal)
305 * <string><radix-letter>
307 pradix = sradix = 0;
308 plen = slen = 0;
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;
315 if (len > 1 && (sradix = radix_letter(q[-1])) != 0)
316 slen = 1;
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;
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.
336 checklimit = UINT64_C(0x8000000000000000) / (radix >> 1);
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
342 last = (radix == 10 ? 6 : 0);
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;
352 if (result > checklimit ||
353 (result == checklimit && digit >= last)) {
354 warn = true;
357 result = radix * result + digit;
359 r++;
362 if (warn)
363 nasm_error(ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
364 "numeric constant %s does not fit in 64 bits",
365 str);
367 return result * sign;
370 int64_t readstrnum(char *str, int length, bool *warn)
372 int64_t charconst = 0;
373 int i;
375 *warn = false;
377 str += length;
378 if (globalbits == 64) {
379 for (i = 0; i < length; i++) {
380 if (charconst & UINT64_C(0xFF00000000000000))
381 *warn = true;
382 charconst = (charconst << 8) + (uint8_t)*--str;
384 } else {
385 for (i = 0; i < length; i++) {
386 if (charconst & 0xFF000000UL)
387 *warn = true;
388 charconst = (charconst << 8) + (uint8_t)*--str;
391 return charconst;
394 static int32_t next_seg;
396 void seg_init(void)
398 next_seg = 0;
401 int32_t seg_alloc(void)
403 return (next_seg += 2) - 2;
406 #ifdef WORDS_LITTLEENDIAN
408 void fwriteint16_t(uint16_t data, FILE * fp)
410 nasm_write(&data, 2, fp);
413 void fwriteint32_t(uint32_t data, FILE * fp)
415 nasm_write(&data, 4, fp);
418 void fwriteint64_t(uint64_t data, FILE * fp)
420 nasm_write(&data, 8, fp);
423 void fwriteaddr(uint64_t data, int size, FILE * fp)
425 nasm_write(&data, size, fp);
428 #else /* not WORDS_LITTLEENDIAN */
430 void fwriteint16_t(uint16_t data, FILE * fp)
432 char buffer[2], *p = buffer;
433 WRITESHORT(p, data);
434 nasm_write(buffer, 2, fp);
437 void fwriteint32_t(uint32_t data, FILE * fp)
439 char buffer[4], *p = buffer;
440 WRITELONG(p, data);
441 nasm_write(buffer, 4, fp);
444 void fwriteint64_t(uint64_t data, FILE * fp)
446 char buffer[8], *p = buffer;
447 WRITEDLONG(p, data);
448 nasm_write(buffer, 8, fp);
451 void fwriteaddr(uint64_t data, int size, FILE * fp)
453 char buffer[8], *p = buffer;
454 WRITEADDR(p, data, size);
455 nasm_write(buffer, size, fp);
458 #endif
460 void fwritezero(size_t bytes, FILE *fp)
462 size_t blksize;
464 while (bytes) {
465 blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE;
467 nasm_write(zero_buffer, blksize, fp);
468 bytes -= blksize;
472 void standard_extension(char *inname, char *outname, char *extension)
474 char *p, *q;
476 if (*outname) /* file name already exists, */
477 return; /* so do nothing */
478 q = inname;
479 p = outname;
480 while (*q)
481 *p++ = *q++; /* copy, and find end of string */
482 *p = '\0'; /* terminate it */
483 while (p > outname && *--p != '.') ; /* find final period (or whatever) */
484 if (*p != '.')
485 while (*p)
486 p++; /* go back to end if none found */
487 if (!strcmp(p, extension)) { /* is the extension already there? */
488 if (*extension)
489 nasm_error(ERR_WARNING | ERR_NOFILE,
490 "file name already ends in `%s': "
491 "output will be in `nasm.out'", extension);
492 else
493 nasm_error(ERR_WARNING | ERR_NOFILE,
494 "file name already has no extension: "
495 "output will be in `nasm.out'");
496 strcpy(outname, "nasm.out");
497 } else
498 strcpy(p, extension);
502 * Common list of prefix names
504 static const char *prefix_names[] = {
505 "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
506 "rep", "repe", "repne", "repnz", "repz", "times", "wait",
507 "xacquire", "xrelease", "bnd"
510 const char *prefix_name(int token)
512 unsigned int prefix = token-PREFIX_ENUM_START;
513 if (prefix >= ARRAY_SIZE(prefix_names))
514 return NULL;
516 return prefix_names[prefix];
520 * Binary search.
522 int bsi(const char *string, const char **array, int size)
524 int i = -1, j = size; /* always, i < index < j */
525 while (j - i >= 2) {
526 int k = (i + j) / 2;
527 int l = strcmp(string, array[k]);
528 if (l < 0) /* it's in the first half */
529 j = k;
530 else if (l > 0) /* it's in the second half */
531 i = k;
532 else /* we've got it :) */
533 return k;
535 return -1; /* we haven't got it :( */
538 int bsii(const char *string, const char **array, int size)
540 int i = -1, j = size; /* always, i < index < j */
541 while (j - i >= 2) {
542 int k = (i + j) / 2;
543 int l = nasm_stricmp(string, array[k]);
544 if (l < 0) /* it's in the first half */
545 j = k;
546 else if (l > 0) /* it's in the second half */
547 i = k;
548 else /* we've got it :) */
549 return k;
551 return -1; /* we haven't got it :( */
554 static char *file_name = NULL;
555 static int32_t line_number = 0;
557 char *src_set_fname(char *newname)
559 char *oldname = file_name;
560 file_name = newname;
561 return oldname;
564 int32_t src_set_linnum(int32_t newline)
566 int32_t oldline = line_number;
567 line_number = newline;
568 return oldline;
571 int32_t src_get_linnum(void)
573 return line_number;
576 int src_get(int32_t *xline, char **xname)
578 if (!file_name || !*xname || strcmp(*xname, file_name)) {
579 nasm_free(*xname);
580 *xname = file_name ? nasm_strdup(file_name) : NULL;
581 *xline = line_number;
582 return -2;
584 if (*xline != line_number) {
585 int32_t tmp = line_number - *xline;
586 *xline = line_number;
587 return tmp;
589 return 0;
592 char *nasm_strcat(const char *one, const char *two)
594 char *rslt;
595 int l1 = strlen(one);
596 rslt = nasm_malloc(l1 + strlen(two) + 1);
597 strcpy(rslt, one);
598 strcpy(rslt + l1, two);
599 return rslt;
602 /* skip leading spaces */
603 char *nasm_skip_spaces(const char *p)
605 if (p)
606 while (*p && nasm_isspace(*p))
607 p++;
608 return (char *)p;
611 /* skip leading non-spaces */
612 char *nasm_skip_word(const char *p)
614 if (p)
615 while (*p && !nasm_isspace(*p))
616 p++;
617 return (char *)p;
620 /* zap leading spaces with zero */
621 char *nasm_zap_spaces_fwd(char *p)
623 if (p)
624 while (*p && nasm_isspace(*p))
625 *p++ = 0x0;
626 return p;
629 /* zap spaces with zero in reverse order */
630 char *nasm_zap_spaces_rev(char *p)
632 if (p)
633 while (*p && nasm_isspace(*p))
634 *p-- = 0x0;
635 return p;
638 /* zap leading and trailing spaces */
639 char *nasm_trim_spaces(char *p)
641 p = nasm_zap_spaces_fwd(p);
642 nasm_zap_spaces_fwd(nasm_skip_word(p));
644 return p;
648 * return the word extracted from a stream
649 * or NULL if nothing left
651 char *nasm_get_word(char *p, char **tail)
653 char *word = nasm_skip_spaces(p);
654 char *next = nasm_skip_word(word);
656 if (word && *word) {
657 if (*next)
658 *next++ = '\0';
659 } else
660 word = next = NULL;
662 /* NOTE: the tail may start with spaces */
663 *tail = next;
665 return word;
669 * Extract "opt=val" values from the stream and
670 * returns "opt"
672 * Exceptions:
673 * 1) If "=val" passed the NULL returned though
674 * you may continue handling the tail via "next"
675 * 2) If "=" passed the NULL is returned and "val"
676 * is set to NULL as well
678 char *nasm_opt_val(char *p, char **val, char **next)
680 char *q, *nxt;
682 *val = *next = NULL;
684 p = nasm_get_word(p, &nxt);
685 if (!p)
686 return NULL;
688 q = strchr(p, '=');
689 if (q) {
690 if (q == p)
691 p = NULL;
692 *q++='\0';
693 if (*q) {
694 *val = q;
695 } else {
696 q = nasm_get_word(q + 1, &nxt);
697 if (q)
698 *val = q;
700 } else {
701 q = nasm_skip_spaces(nxt);
702 if (q && *q == '=') {
703 q = nasm_get_word(q + 1, &nxt);
704 if (q)
705 *val = q;
709 *next = nxt;
710 return p;
714 * initialized data bytes length from opcode
716 int idata_bytes(int opcode)
718 switch (opcode) {
719 case I_DB:
720 return 1;
721 case I_DW:
722 return 2;
723 case I_DD:
724 return 4;
725 case I_DQ:
726 return 8;
727 case I_DT:
728 return 10;
729 case I_DO:
730 return 16;
731 case I_DY:
732 return 32;
733 case I_DZ:
734 return 64;
735 case I_none:
736 return -1;
737 default:
738 return 0;