NASM 2.12rc7
[nasm.git] / nasmlib.c
blobcf39468a896486a930813021ba56a16791f1e52a
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 int32_t seg_alloc(void)
396 static int32_t next_seg = 0;
397 int32_t this_seg = next_seg;
399 next_seg += 2;
401 return this_seg;
404 #ifdef WORDS_LITTLEENDIAN
406 void fwriteint16_t(uint16_t data, FILE * fp)
408 nasm_write(&data, 2, fp);
411 void fwriteint32_t(uint32_t data, FILE * fp)
413 nasm_write(&data, 4, fp);
416 void fwriteint64_t(uint64_t data, FILE * fp)
418 nasm_write(&data, 8, fp);
421 void fwriteaddr(uint64_t data, int size, FILE * fp)
423 nasm_write(&data, size, fp);
426 #else /* not WORDS_LITTLEENDIAN */
428 void fwriteint16_t(uint16_t data, FILE * fp)
430 char buffer[2], *p = buffer;
431 WRITESHORT(p, data);
432 nasm_write(buffer, 2, fp);
435 void fwriteint32_t(uint32_t data, FILE * fp)
437 char buffer[4], *p = buffer;
438 WRITELONG(p, data);
439 nasm_write(buffer, 4, fp);
442 void fwriteint64_t(uint64_t data, FILE * fp)
444 char buffer[8], *p = buffer;
445 WRITEDLONG(p, data);
446 nasm_write(buffer, 8, fp);
449 void fwriteaddr(uint64_t data, int size, FILE * fp)
451 char buffer[8], *p = buffer;
452 WRITEADDR(p, data, size);
453 nasm_write(buffer, size, fp);
456 #endif
458 void fwritezero(size_t bytes, FILE *fp)
460 size_t blksize;
462 while (bytes) {
463 blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE;
465 nasm_write(zero_buffer, blksize, fp);
466 bytes -= blksize;
470 void standard_extension(char *inname, char *outname, char *extension)
472 char *p, *q;
474 if (*outname) /* file name already exists, */
475 return; /* so do nothing */
476 q = inname;
477 p = outname;
478 while (*q)
479 *p++ = *q++; /* copy, and find end of string */
480 *p = '\0'; /* terminate it */
481 while (p > outname && *--p != '.') ; /* find final period (or whatever) */
482 if (*p != '.')
483 while (*p)
484 p++; /* go back to end if none found */
485 if (!strcmp(p, extension)) { /* is the extension already there? */
486 if (*extension)
487 nasm_error(ERR_WARNING | ERR_NOFILE,
488 "file name already ends in `%s': "
489 "output will be in `nasm.out'", extension);
490 else
491 nasm_error(ERR_WARNING | ERR_NOFILE,
492 "file name already has no extension: "
493 "output will be in `nasm.out'");
494 strcpy(outname, "nasm.out");
495 } else
496 strcpy(p, extension);
500 * Common list of prefix names
502 static const char *prefix_names[] = {
503 "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
504 "rep", "repe", "repne", "repnz", "repz", "times", "wait",
505 "xacquire", "xrelease", "bnd"
508 const char *prefix_name(int token)
510 unsigned int prefix = token-PREFIX_ENUM_START;
511 if (prefix >= ARRAY_SIZE(prefix_names))
512 return NULL;
514 return prefix_names[prefix];
518 * Binary search.
520 int bsi(const char *string, const char **array, int size)
522 int i = -1, j = size; /* always, i < index < j */
523 while (j - i >= 2) {
524 int k = (i + j) / 2;
525 int l = strcmp(string, array[k]);
526 if (l < 0) /* it's in the first half */
527 j = k;
528 else if (l > 0) /* it's in the second half */
529 i = k;
530 else /* we've got it :) */
531 return k;
533 return -1; /* we haven't got it :( */
536 int bsii(const char *string, const char **array, int size)
538 int i = -1, j = size; /* always, i < index < j */
539 while (j - i >= 2) {
540 int k = (i + j) / 2;
541 int l = nasm_stricmp(string, array[k]);
542 if (l < 0) /* it's in the first half */
543 j = k;
544 else if (l > 0) /* it's in the second half */
545 i = k;
546 else /* we've got it :) */
547 return k;
549 return -1; /* we haven't got it :( */
552 static char *file_name = NULL;
553 static int32_t line_number = 0;
555 char *src_set_fname(char *newname)
557 char *oldname = file_name;
558 file_name = newname;
559 return oldname;
562 int32_t src_set_linnum(int32_t newline)
564 int32_t oldline = line_number;
565 line_number = newline;
566 return oldline;
569 int32_t src_get_linnum(void)
571 return line_number;
574 int src_get(int32_t *xline, char **xname)
576 if (!file_name || !*xname || strcmp(*xname, file_name)) {
577 nasm_free(*xname);
578 *xname = file_name ? nasm_strdup(file_name) : NULL;
579 *xline = line_number;
580 return -2;
582 if (*xline != line_number) {
583 int32_t tmp = line_number - *xline;
584 *xline = line_number;
585 return tmp;
587 return 0;
590 char *nasm_strcat(const char *one, const char *two)
592 char *rslt;
593 int l1 = strlen(one);
594 rslt = nasm_malloc(l1 + strlen(two) + 1);
595 strcpy(rslt, one);
596 strcpy(rslt + l1, two);
597 return rslt;
600 /* skip leading spaces */
601 char *nasm_skip_spaces(const char *p)
603 if (p)
604 while (*p && nasm_isspace(*p))
605 p++;
606 return (char *)p;
609 /* skip leading non-spaces */
610 char *nasm_skip_word(const char *p)
612 if (p)
613 while (*p && !nasm_isspace(*p))
614 p++;
615 return (char *)p;
618 /* zap leading spaces with zero */
619 char *nasm_zap_spaces_fwd(char *p)
621 if (p)
622 while (*p && nasm_isspace(*p))
623 *p++ = 0x0;
624 return p;
627 /* zap spaces with zero in reverse order */
628 char *nasm_zap_spaces_rev(char *p)
630 if (p)
631 while (*p && nasm_isspace(*p))
632 *p-- = 0x0;
633 return p;
636 /* zap leading and trailing spaces */
637 char *nasm_trim_spaces(char *p)
639 p = nasm_zap_spaces_fwd(p);
640 nasm_zap_spaces_fwd(nasm_skip_word(p));
642 return p;
646 * return the word extracted from a stream
647 * or NULL if nothing left
649 char *nasm_get_word(char *p, char **tail)
651 char *word = nasm_skip_spaces(p);
652 char *next = nasm_skip_word(word);
654 if (word && *word) {
655 if (*next)
656 *next++ = '\0';
657 } else
658 word = next = NULL;
660 /* NOTE: the tail may start with spaces */
661 *tail = next;
663 return word;
667 * Extract "opt=val" values from the stream and
668 * returns "opt"
670 * Exceptions:
671 * 1) If "=val" passed the NULL returned though
672 * you may continue handling the tail via "next"
673 * 2) If "=" passed the NULL is returned and "val"
674 * is set to NULL as well
676 char *nasm_opt_val(char *p, char **val, char **next)
678 char *q, *nxt;
680 *val = *next = NULL;
682 p = nasm_get_word(p, &nxt);
683 if (!p)
684 return NULL;
686 q = strchr(p, '=');
687 if (q) {
688 if (q == p)
689 p = NULL;
690 *q++='\0';
691 if (*q) {
692 *val = q;
693 } else {
694 q = nasm_get_word(q + 1, &nxt);
695 if (q)
696 *val = q;
698 } else {
699 q = nasm_skip_spaces(nxt);
700 if (q && *q == '=') {
701 q = nasm_get_word(q + 1, &nxt);
702 if (q)
703 *val = q;
707 *next = nxt;
708 return p;
712 * initialized data bytes length from opcode
714 int idata_bytes(int opcode)
716 switch (opcode) {
717 case I_DB:
718 return 1;
719 case I_DW:
720 return 2;
721 case I_DD:
722 return 4;
723 case I_DQ:
724 return 8;
725 case I_DT:
726 return 10;
727 case I_DO:
728 return 16;
729 case I_DY:
730 return 32;
731 case I_DZ:
732 return 64;
733 case I_none:
734 return -1;
735 default:
736 return 0;