ndisasm: don't use nasm_open_read()
[nasm.git] / nasmlib / nasmlib.c
blobbe48d7bd2755f6d30a15e5b2a44adbeda368d7ad
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_calloc(size_t size, size_t nelem)
113 void *p = calloc(size, nelem);
114 if (!p)
115 nasm_fatal(ERR_NOFILE, "out of memory");
116 return p;
119 void *nasm_zalloc(size_t size)
121 return nasm_calloc(size, 1);
124 void *nasm_realloc(void *q, size_t size)
126 void *p = q ? realloc(q, size) : malloc(size);
127 if (!p)
128 nasm_fatal(ERR_NOFILE, "out of memory");
129 return p;
132 void nasm_free(void *q)
134 if (q)
135 free(q);
138 char *nasm_strdup(const char *s)
140 char *p;
141 int size = strlen(s) + 1;
143 p = malloc(size);
144 if (!p)
145 nasm_fatal(ERR_NOFILE, "out of memory");
146 strcpy(p, s);
147 return p;
150 char *nasm_strndup(const char *s, size_t len)
152 char *p;
153 int size = len + 1;
155 p = malloc(size);
156 if (!p)
157 nasm_fatal(ERR_NOFILE, "out of memory");
158 strncpy(p, s, len);
159 p[len] = '\0';
160 return p;
163 no_return nasm_assert_failed(const char *file, int line, const char *msg)
165 nasm_fatal(0, "assertion %s failed at %s:%d", msg, file, line);
166 exit(1);
169 #ifndef nasm_stricmp
170 int nasm_stricmp(const char *s1, const char *s2)
172 unsigned char c1, c2;
173 int d;
175 while (1) {
176 c1 = nasm_tolower(*s1++);
177 c2 = nasm_tolower(*s2++);
178 d = c1-c2;
180 if (d)
181 return d;
182 if (!c1)
183 break;
185 return 0;
187 #endif
189 #ifndef nasm_strnicmp
190 int nasm_strnicmp(const char *s1, const char *s2, size_t n)
192 unsigned char c1, c2;
193 int d;
195 while (n--) {
196 c1 = nasm_tolower(*s1++);
197 c2 = nasm_tolower(*s2++);
198 d = c1-c2;
200 if (d)
201 return d;
202 if (!c1)
203 break;
205 return 0;
207 #endif
209 int nasm_memicmp(const char *s1, const char *s2, size_t n)
211 unsigned char c1, c2;
212 int d;
214 while (n--) {
215 c1 = nasm_tolower(*s1++);
216 c2 = nasm_tolower(*s2++);
217 d = c1-c2;
218 if (d)
219 return d;
221 return 0;
224 #ifndef nasm_strsep
225 char *nasm_strsep(char **stringp, const char *delim)
227 char *s = *stringp;
228 char *e;
230 if (!s)
231 return NULL;
233 e = strpbrk(s, delim);
234 if (e)
235 *e++ = '\0';
237 *stringp = e;
238 return s;
240 #endif
243 #define lib_isnumchar(c) (nasm_isalnum(c) || (c) == '$' || (c) == '_')
245 static int radix_letter(char c)
247 switch (c) {
248 case 'b': case 'B':
249 case 'y': case 'Y':
250 return 2; /* Binary */
251 case 'o': case 'O':
252 case 'q': case 'Q':
253 return 8; /* Octal */
254 case 'h': case 'H':
255 case 'x': case 'X':
256 return 16; /* Hexadecimal */
257 case 'd': case 'D':
258 case 't': case 'T':
259 return 10; /* Decimal */
260 default:
261 return 0; /* Not a known radix letter */
265 int64_t readnum(char *str, bool *error)
267 char *r = str, *q;
268 int32_t pradix, sradix, radix;
269 int plen, slen, len;
270 uint64_t result, checklimit;
271 int digit, last;
272 bool warn = false;
273 int sign = 1;
275 *error = false;
277 while (nasm_isspace(*r))
278 r++; /* find start of number */
281 * If the number came from make_tok_num (as a result of an %assign), it
282 * might have a '-' built into it (rather than in a preceeding token).
284 if (*r == '-') {
285 r++;
286 sign = -1;
289 q = r;
291 while (lib_isnumchar(*q))
292 q++; /* find end of number */
294 len = q-r;
295 if (!len) {
296 /* Not numeric */
297 *error = true;
298 return 0;
302 * Handle radix formats:
304 * 0<radix-letter><string>
305 * $<string> (hexadecimal)
306 * <string><radix-letter>
308 pradix = sradix = 0;
309 plen = slen = 0;
311 if (len > 2 && *r == '0' && (pradix = radix_letter(r[1])) != 0)
312 plen = 2;
313 else if (len > 1 && *r == '$')
314 pradix = 16, plen = 1;
316 if (len > 1 && (sradix = radix_letter(q[-1])) != 0)
317 slen = 1;
319 if (pradix > sradix) {
320 radix = pradix;
321 r += plen;
322 } else if (sradix > pradix) {
323 radix = sradix;
324 q -= slen;
325 } else {
326 /* Either decimal, or invalid -- if invalid, we'll trip up
327 further down. */
328 radix = 10;
332 * `checklimit' must be 2**64 / radix. We can't do that in
333 * 64-bit arithmetic, which we're (probably) using, so we
334 * cheat: since we know that all radices we use are even, we
335 * can divide 2**63 by radix/2 instead.
337 checklimit = UINT64_C(0x8000000000000000) / (radix >> 1);
340 * Calculate the highest allowable value for the last digit of a
341 * 64-bit constant... in radix 10, it is 6, otherwise it is 0
343 last = (radix == 10 ? 6 : 0);
345 result = 0;
346 while (*r && r < q) {
347 if (*r != '_') {
348 if (*r < '0' || (*r > '9' && *r < 'A')
349 || (digit = numvalue(*r)) >= radix) {
350 *error = true;
351 return 0;
353 if (result > checklimit ||
354 (result == checklimit && digit >= last)) {
355 warn = true;
358 result = radix * result + digit;
360 r++;
363 if (warn)
364 nasm_error(ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
365 "numeric constant %s does not fit in 64 bits",
366 str);
368 return result * sign;
371 int64_t readstrnum(char *str, int length, bool *warn)
373 int64_t charconst = 0;
374 int i;
376 *warn = false;
378 str += length;
379 if (globalbits == 64) {
380 for (i = 0; i < length; i++) {
381 if (charconst & UINT64_C(0xFF00000000000000))
382 *warn = true;
383 charconst = (charconst << 8) + (uint8_t)*--str;
385 } else {
386 for (i = 0; i < length; i++) {
387 if (charconst & 0xFF000000UL)
388 *warn = true;
389 charconst = (charconst << 8) + (uint8_t)*--str;
392 return charconst;
395 int32_t seg_alloc(void)
397 static int32_t next_seg = 0;
398 int32_t this_seg = next_seg;
400 next_seg += 2;
402 return this_seg;
405 void standard_extension(char *inname, char *outname, char *extension)
407 char *p, *q;
409 if (*outname) /* file name already exists, */
410 return; /* so do nothing */
411 q = inname;
412 p = outname;
413 while (*q)
414 *p++ = *q++; /* copy, and find end of string */
415 *p = '\0'; /* terminate it */
416 while (p > outname && *--p != '.') ; /* find final period (or whatever) */
417 if (*p != '.')
418 while (*p)
419 p++; /* go back to end if none found */
420 if (!strcmp(p, extension)) { /* is the extension already there? */
421 if (*extension)
422 nasm_error(ERR_WARNING | ERR_NOFILE,
423 "file name already ends in `%s': "
424 "output will be in `nasm.out'", extension);
425 else
426 nasm_error(ERR_WARNING | ERR_NOFILE,
427 "file name already has no extension: "
428 "output will be in `nasm.out'");
429 strcpy(outname, "nasm.out");
430 } else
431 strcpy(p, extension);
435 * Common list of prefix names
437 static const char *prefix_names[] = {
438 "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
439 "rep", "repe", "repne", "repnz", "repz", "times", "wait",
440 "xacquire", "xrelease", "bnd"
443 const char *prefix_name(int token)
445 unsigned int prefix = token-PREFIX_ENUM_START;
446 if (prefix >= ARRAY_SIZE(prefix_names))
447 return NULL;
449 return prefix_names[prefix];
453 * Binary search.
455 int bsi(const char *string, const char **array, int size)
457 int i = -1, j = size; /* always, i < index < j */
458 while (j - i >= 2) {
459 int k = (i + j) / 2;
460 int l = strcmp(string, array[k]);
461 if (l < 0) /* it's in the first half */
462 j = k;
463 else if (l > 0) /* it's in the second half */
464 i = k;
465 else /* we've got it :) */
466 return k;
468 return -1; /* we haven't got it :( */
471 int bsii(const char *string, const char **array, int size)
473 int i = -1, j = size; /* always, i < index < j */
474 while (j - i >= 2) {
475 int k = (i + j) / 2;
476 int l = nasm_stricmp(string, array[k]);
477 if (l < 0) /* it's in the first half */
478 j = k;
479 else if (l > 0) /* it's in the second half */
480 i = k;
481 else /* we've got it :) */
482 return k;
484 return -1; /* we haven't got it :( */
487 char *nasm_strcat(const char *one, const char *two)
489 char *rslt;
490 int l1 = strlen(one);
491 rslt = nasm_malloc(l1 + strlen(two) + 1);
492 strcpy(rslt, one);
493 strcpy(rslt + l1, two);
494 return rslt;
497 /* skip leading spaces */
498 char *nasm_skip_spaces(const char *p)
500 if (p)
501 while (*p && nasm_isspace(*p))
502 p++;
503 return (char *)p;
506 /* skip leading non-spaces */
507 char *nasm_skip_word(const char *p)
509 if (p)
510 while (*p && !nasm_isspace(*p))
511 p++;
512 return (char *)p;
515 /* zap leading spaces with zero */
516 char *nasm_zap_spaces_fwd(char *p)
518 if (p)
519 while (*p && nasm_isspace(*p))
520 *p++ = 0x0;
521 return p;
524 /* zap spaces with zero in reverse order */
525 char *nasm_zap_spaces_rev(char *p)
527 if (p)
528 while (*p && nasm_isspace(*p))
529 *p-- = 0x0;
530 return p;
533 /* zap leading and trailing spaces */
534 char *nasm_trim_spaces(char *p)
536 p = nasm_zap_spaces_fwd(p);
537 nasm_zap_spaces_fwd(nasm_skip_word(p));
539 return p;
543 * return the word extracted from a stream
544 * or NULL if nothing left
546 char *nasm_get_word(char *p, char **tail)
548 char *word = nasm_skip_spaces(p);
549 char *next = nasm_skip_word(word);
551 if (word && *word) {
552 if (*next)
553 *next++ = '\0';
554 } else
555 word = next = NULL;
557 /* NOTE: the tail may start with spaces */
558 *tail = next;
560 return word;
564 * Extract "opt=val" values from the stream and
565 * returns "opt"
567 * Exceptions:
568 * 1) If "=val" passed the NULL returned though
569 * you may continue handling the tail via "next"
570 * 2) If "=" passed the NULL is returned and "val"
571 * is set to NULL as well
573 char *nasm_opt_val(char *p, char **val, char **next)
575 char *q, *nxt;
577 *val = *next = NULL;
579 p = nasm_get_word(p, &nxt);
580 if (!p)
581 return NULL;
583 q = strchr(p, '=');
584 if (q) {
585 if (q == p)
586 p = NULL;
587 *q++='\0';
588 if (*q) {
589 *val = q;
590 } else {
591 q = nasm_get_word(q + 1, &nxt);
592 if (q)
593 *val = q;
595 } else {
596 q = nasm_skip_spaces(nxt);
597 if (q && *q == '=') {
598 q = nasm_get_word(q + 1, &nxt);
599 if (q)
600 *val = q;
604 *next = nxt;
605 return p;
609 * initialized data bytes length from opcode
611 int idata_bytes(int opcode)
613 switch (opcode) {
614 case I_DB:
615 return 1;
616 case I_DW:
617 return 2;
618 case I_DD:
619 return 4;
620 case I_DQ:
621 return 8;
622 case I_DT:
623 return 10;
624 case I_DO:
625 return 16;
626 case I_DY:
627 return 32;
628 case I_DZ:
629 return 64;
630 case I_none:
631 return -1;
632 default:
633 return 0;