Support EVEX encodings of maps 0-15
[nasm.git] / nasmlib / nasmlib.c
blobb264080a1cd70f781fe9cfd8bee3ade43fde1f95
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>
46 #include "nasm.h"
47 #include "nasmlib.h"
48 #include "insns.h"
50 int globalbits = 0; /* defined in nasm.h, works better here for ASM+DISASM */
51 vefunc nasm_verror; /* Global error handling function */
53 /* Uninitialized -> all zero by C spec */
54 const uint8_t zero_buffer[ZERO_BUF_SIZE];
57 * Prepare a table of tolower() results. This avoids function calls
58 * on some platforms.
61 unsigned char nasm_tolower_tab[256];
63 void tolower_init(void)
65 int i;
67 for (i = 0; i < 256; i++)
68 nasm_tolower_tab[i] = tolower(i);
71 void nasm_error(int severity, const char *fmt, ...)
73 va_list ap;
75 va_start(ap, fmt);
76 nasm_verror(severity, fmt, ap);
77 va_end(ap);
80 no_return nasm_fatal(int flags, const char *fmt, ...)
82 va_list ap;
84 va_start(ap, fmt);
85 nasm_verror(flags | ERR_FATAL, fmt, ap);
86 abort(); /* We should never get here */
89 no_return nasm_panic(int flags, const char *fmt, ...)
91 va_list ap;
93 va_start(ap, fmt);
94 nasm_verror(flags | ERR_PANIC, fmt, ap);
95 abort(); /* We should never get here */
98 no_return nasm_panic_from_macro(const char *file, int line)
100 nasm_panic(ERR_NOFILE, "Internal error at %s:%d\n", file, line);
103 void *nasm_malloc(size_t size)
105 void *p = malloc(size);
106 if (!p)
107 nasm_fatal(ERR_NOFILE, "out of memory");
108 return p;
111 void *nasm_zalloc(size_t size)
113 void *p = calloc(size, 1);
114 if (!p)
115 nasm_fatal(ERR_NOFILE, "out of memory");
116 return p;
119 void *nasm_realloc(void *q, size_t size)
121 void *p = q ? realloc(q, size) : malloc(size);
122 if (!p)
123 nasm_fatal(ERR_NOFILE, "out of memory");
124 return p;
127 void nasm_free(void *q)
129 if (q)
130 free(q);
133 char *nasm_strdup(const char *s)
135 char *p;
136 int size = strlen(s) + 1;
138 p = malloc(size);
139 if (!p)
140 nasm_fatal(ERR_NOFILE, "out of memory");
141 strcpy(p, s);
142 return p;
145 char *nasm_strndup(const char *s, size_t len)
147 char *p;
148 int size = len + 1;
150 p = malloc(size);
151 if (!p)
152 nasm_fatal(ERR_NOFILE, "out of memory");
153 strncpy(p, s, len);
154 p[len] = '\0';
155 return p;
158 no_return nasm_assert_failed(const char *file, int line, const char *msg)
160 nasm_fatal(0, "assertion %s failed at %s:%d", msg, file, line);
161 exit(1);
164 #ifndef nasm_stricmp
165 int nasm_stricmp(const char *s1, const char *s2)
167 unsigned char c1, c2;
168 int d;
170 while (1) {
171 c1 = nasm_tolower(*s1++);
172 c2 = nasm_tolower(*s2++);
173 d = c1-c2;
175 if (d)
176 return d;
177 if (!c1)
178 break;
180 return 0;
182 #endif
184 #ifndef nasm_strnicmp
185 int nasm_strnicmp(const char *s1, const char *s2, size_t n)
187 unsigned char c1, c2;
188 int d;
190 while (n--) {
191 c1 = nasm_tolower(*s1++);
192 c2 = nasm_tolower(*s2++);
193 d = c1-c2;
195 if (d)
196 return d;
197 if (!c1)
198 break;
200 return 0;
202 #endif
204 int nasm_memicmp(const char *s1, const char *s2, size_t n)
206 unsigned char c1, c2;
207 int d;
209 while (n--) {
210 c1 = nasm_tolower(*s1++);
211 c2 = nasm_tolower(*s2++);
212 d = c1-c2;
213 if (d)
214 return d;
216 return 0;
219 #ifndef nasm_strsep
220 char *nasm_strsep(char **stringp, const char *delim)
222 char *s = *stringp;
223 char *e;
225 if (!s)
226 return NULL;
228 e = strpbrk(s, delim);
229 if (e)
230 *e++ = '\0';
232 *stringp = e;
233 return s;
235 #endif
238 #define lib_isnumchar(c) (nasm_isalnum(c) || (c) == '$' || (c) == '_')
240 static int radix_letter(char c)
242 switch (c) {
243 case 'b': case 'B':
244 case 'y': case 'Y':
245 return 2; /* Binary */
246 case 'o': case 'O':
247 case 'q': case 'Q':
248 return 8; /* Octal */
249 case 'h': case 'H':
250 case 'x': case 'X':
251 return 16; /* Hexadecimal */
252 case 'd': case 'D':
253 case 't': case 'T':
254 return 10; /* Decimal */
255 default:
256 return 0; /* Not a known radix letter */
260 int64_t readnum(char *str, bool *error)
262 char *r = str, *q;
263 int32_t pradix, sradix, radix;
264 int plen, slen, len;
265 uint64_t result, checklimit;
266 int digit, last;
267 bool warn = false;
268 int sign = 1;
270 *error = false;
272 while (nasm_isspace(*r))
273 r++; /* find start of number */
276 * If the number came from make_tok_num (as a result of an %assign), it
277 * might have a '-' built into it (rather than in a preceeding token).
279 if (*r == '-') {
280 r++;
281 sign = -1;
284 q = r;
286 while (lib_isnumchar(*q))
287 q++; /* find end of number */
289 len = q-r;
290 if (!len) {
291 /* Not numeric */
292 *error = true;
293 return 0;
297 * Handle radix formats:
299 * 0<radix-letter><string>
300 * $<string> (hexadecimal)
301 * <string><radix-letter>
303 pradix = sradix = 0;
304 plen = slen = 0;
306 if (len > 2 && *r == '0' && (pradix = radix_letter(r[1])) != 0)
307 plen = 2;
308 else if (len > 1 && *r == '$')
309 pradix = 16, plen = 1;
311 if (len > 1 && (sradix = radix_letter(q[-1])) != 0)
312 slen = 1;
314 if (pradix > sradix) {
315 radix = pradix;
316 r += plen;
317 } else if (sradix > pradix) {
318 radix = sradix;
319 q -= slen;
320 } else {
321 /* Either decimal, or invalid -- if invalid, we'll trip up
322 further down. */
323 radix = 10;
327 * `checklimit' must be 2**64 / radix. We can't do that in
328 * 64-bit arithmetic, which we're (probably) using, so we
329 * cheat: since we know that all radices we use are even, we
330 * can divide 2**63 by radix/2 instead.
332 checklimit = UINT64_C(0x8000000000000000) / (radix >> 1);
335 * Calculate the highest allowable value for the last digit of a
336 * 64-bit constant... in radix 10, it is 6, otherwise it is 0
338 last = (radix == 10 ? 6 : 0);
340 result = 0;
341 while (*r && r < q) {
342 if (*r != '_') {
343 if (*r < '0' || (*r > '9' && *r < 'A')
344 || (digit = numvalue(*r)) >= radix) {
345 *error = true;
346 return 0;
348 if (result > checklimit ||
349 (result == checklimit && digit >= last)) {
350 warn = true;
353 result = radix * result + digit;
355 r++;
358 if (warn)
359 nasm_error(ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
360 "numeric constant %s does not fit in 64 bits",
361 str);
363 return result * sign;
366 int64_t readstrnum(char *str, int length, bool *warn)
368 int64_t charconst = 0;
369 int i;
371 *warn = false;
373 str += length;
374 if (globalbits == 64) {
375 for (i = 0; i < length; i++) {
376 if (charconst & UINT64_C(0xFF00000000000000))
377 *warn = true;
378 charconst = (charconst << 8) + (uint8_t)*--str;
380 } else {
381 for (i = 0; i < length; i++) {
382 if (charconst & 0xFF000000UL)
383 *warn = true;
384 charconst = (charconst << 8) + (uint8_t)*--str;
387 return charconst;
390 int32_t seg_alloc(void)
392 static int32_t next_seg = 0;
393 int32_t this_seg = next_seg;
395 next_seg += 2;
397 return this_seg;
400 void standard_extension(char *inname, char *outname, char *extension)
402 char *p, *q;
404 if (*outname) /* file name already exists, */
405 return; /* so do nothing */
406 q = inname;
407 p = outname;
408 while (*q)
409 *p++ = *q++; /* copy, and find end of string */
410 *p = '\0'; /* terminate it */
411 while (p > outname && *--p != '.') ; /* find final period (or whatever) */
412 if (*p != '.')
413 while (*p)
414 p++; /* go back to end if none found */
415 if (!strcmp(p, extension)) { /* is the extension already there? */
416 if (*extension)
417 nasm_error(ERR_WARNING | ERR_NOFILE,
418 "file name already ends in `%s': "
419 "output will be in `nasm.out'", extension);
420 else
421 nasm_error(ERR_WARNING | ERR_NOFILE,
422 "file name already has no extension: "
423 "output will be in `nasm.out'");
424 strcpy(outname, "nasm.out");
425 } else
426 strcpy(p, extension);
430 * Common list of prefix names
432 static const char *prefix_names[] = {
433 "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
434 "rep", "repe", "repne", "repnz", "repz", "times", "wait",
435 "xacquire", "xrelease", "bnd"
438 const char *prefix_name(int token)
440 unsigned int prefix = token-PREFIX_ENUM_START;
441 if (prefix >= ARRAY_SIZE(prefix_names))
442 return NULL;
444 return prefix_names[prefix];
448 * Binary search.
450 int bsi(const char *string, const char **array, int size)
452 int i = -1, j = size; /* always, i < index < j */
453 while (j - i >= 2) {
454 int k = (i + j) / 2;
455 int l = strcmp(string, array[k]);
456 if (l < 0) /* it's in the first half */
457 j = k;
458 else if (l > 0) /* it's in the second half */
459 i = k;
460 else /* we've got it :) */
461 return k;
463 return -1; /* we haven't got it :( */
466 int bsii(const char *string, const char **array, int size)
468 int i = -1, j = size; /* always, i < index < j */
469 while (j - i >= 2) {
470 int k = (i + j) / 2;
471 int l = nasm_stricmp(string, array[k]);
472 if (l < 0) /* it's in the first half */
473 j = k;
474 else if (l > 0) /* it's in the second half */
475 i = k;
476 else /* we've got it :) */
477 return k;
479 return -1; /* we haven't got it :( */
482 static char *file_name = NULL;
483 static int32_t line_number = 0;
485 char *src_set_fname(char *newname)
487 char *oldname = file_name;
488 file_name = newname;
489 return oldname;
492 int32_t src_set_linnum(int32_t newline)
494 int32_t oldline = line_number;
495 line_number = newline;
496 return oldline;
499 int32_t src_get_linnum(void)
501 return line_number;
504 int src_get(int32_t *xline, char **xname)
506 if (!file_name || !*xname || strcmp(*xname, file_name)) {
507 nasm_free(*xname);
508 *xname = file_name ? nasm_strdup(file_name) : NULL;
509 *xline = line_number;
510 return -2;
512 if (*xline != line_number) {
513 int32_t tmp = line_number - *xline;
514 *xline = line_number;
515 return tmp;
517 return 0;
520 char *nasm_strcat(const char *one, const char *two)
522 char *rslt;
523 int l1 = strlen(one);
524 rslt = nasm_malloc(l1 + strlen(two) + 1);
525 strcpy(rslt, one);
526 strcpy(rslt + l1, two);
527 return rslt;
530 /* skip leading spaces */
531 char *nasm_skip_spaces(const char *p)
533 if (p)
534 while (*p && nasm_isspace(*p))
535 p++;
536 return (char *)p;
539 /* skip leading non-spaces */
540 char *nasm_skip_word(const char *p)
542 if (p)
543 while (*p && !nasm_isspace(*p))
544 p++;
545 return (char *)p;
548 /* zap leading spaces with zero */
549 char *nasm_zap_spaces_fwd(char *p)
551 if (p)
552 while (*p && nasm_isspace(*p))
553 *p++ = 0x0;
554 return p;
557 /* zap spaces with zero in reverse order */
558 char *nasm_zap_spaces_rev(char *p)
560 if (p)
561 while (*p && nasm_isspace(*p))
562 *p-- = 0x0;
563 return p;
566 /* zap leading and trailing spaces */
567 char *nasm_trim_spaces(char *p)
569 p = nasm_zap_spaces_fwd(p);
570 nasm_zap_spaces_fwd(nasm_skip_word(p));
572 return p;
576 * return the word extracted from a stream
577 * or NULL if nothing left
579 char *nasm_get_word(char *p, char **tail)
581 char *word = nasm_skip_spaces(p);
582 char *next = nasm_skip_word(word);
584 if (word && *word) {
585 if (*next)
586 *next++ = '\0';
587 } else
588 word = next = NULL;
590 /* NOTE: the tail may start with spaces */
591 *tail = next;
593 return word;
597 * Extract "opt=val" values from the stream and
598 * returns "opt"
600 * Exceptions:
601 * 1) If "=val" passed the NULL returned though
602 * you may continue handling the tail via "next"
603 * 2) If "=" passed the NULL is returned and "val"
604 * is set to NULL as well
606 char *nasm_opt_val(char *p, char **val, char **next)
608 char *q, *nxt;
610 *val = *next = NULL;
612 p = nasm_get_word(p, &nxt);
613 if (!p)
614 return NULL;
616 q = strchr(p, '=');
617 if (q) {
618 if (q == p)
619 p = NULL;
620 *q++='\0';
621 if (*q) {
622 *val = q;
623 } else {
624 q = nasm_get_word(q + 1, &nxt);
625 if (q)
626 *val = q;
628 } else {
629 q = nasm_skip_spaces(nxt);
630 if (q && *q == '=') {
631 q = nasm_get_word(q + 1, &nxt);
632 if (q)
633 *val = q;
637 *next = nxt;
638 return p;
642 * initialized data bytes length from opcode
644 int idata_bytes(int opcode)
646 switch (opcode) {
647 case I_DB:
648 return 1;
649 case I_DW:
650 return 2;
651 case I_DD:
652 return 4;
653 case I_DQ:
654 return 8;
655 case I_DT:
656 return 10;
657 case I_DO:
658 return 16;
659 case I_DY:
660 return 32;
661 case I_DZ:
662 return 64;
663 case I_none:
664 return -1;
665 default:
666 return 0;