📄 nasmlib.c
字号:
/* nasmlib.c library routines for the Netwide Assembler
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is
* redistributable under the licence given in the file "Licence"
* distributed in the NASM archive.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "nasm.h"
#include "nasmlib.h"
#include "insns.h" /* For MAX_KEYWORD */
static efunc nasm_malloc_error;
#ifdef LOGALLOC
static FILE *logfp;
#endif
void nasm_set_malloc_error(efunc error)
{
nasm_malloc_error = error;
#ifdef LOGALLOC
logfp = fopen("malloc.log", "w");
setvbuf(logfp, NULL, _IOLBF, BUFSIZ);
fprintf(logfp, "null pointer is %p\n", NULL);
#endif
}
#ifdef LOGALLOC
void *nasm_malloc_log(char *file, int line, size_t size)
#else
void *nasm_malloc(size_t size)
#endif
{
void *p = malloc(size);
if (!p)
nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
#ifdef LOGALLOC
else
fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
file, line, (long)size, p);
#endif
return p;
}
#ifdef LOGALLOC
void *nasm_realloc_log(char *file, int line, void *q, size_t size)
#else
void *nasm_realloc(void *q, size_t size)
#endif
{
void *p = q ? realloc(q, size) : malloc(size);
if (!p)
nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
#ifdef LOGALLOC
else if (q)
fprintf(logfp, "%s %d realloc(%p,%ld) returns %p\n",
file, line, q, (long)size, p);
else
fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
file, line, (long)size, p);
#endif
return p;
}
#ifdef LOGALLOC
void nasm_free_log(char *file, int line, void *q)
#else
void nasm_free(void *q)
#endif
{
if (q) {
free(q);
#ifdef LOGALLOC
fprintf(logfp, "%s %d free(%p)\n", file, line, q);
#endif
}
}
#ifdef LOGALLOC
char *nasm_strdup_log(char *file, int line, const char *s)
#else
char *nasm_strdup(const char *s)
#endif
{
char *p;
int size = strlen(s) + 1;
p = malloc(size);
if (!p)
nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
#ifdef LOGALLOC
else
fprintf(logfp, "%s %d strdup(%ld) returns %p\n",
file, line, (long)size, p);
#endif
strcpy(p, s);
return p;
}
#ifdef LOGALLOC
char *nasm_strndup_log(char *file, int line, char *s, size_t len)
#else
char *nasm_strndup(char *s, size_t len)
#endif
{
char *p;
int size = len + 1;
p = malloc(size);
if (!p)
nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
#ifdef LOGALLOC
else
fprintf(logfp, "%s %d strndup(%ld) returns %p\n",
file, line, (long)size, p);
#endif
strncpy(p, s, len);
p[len] = '\0';
return p;
}
#if !defined(stricmp) && !defined(strcasecmp)
int nasm_stricmp(const char *s1, const char *s2)
{
while (*s1 && tolower(*s1) == tolower(*s2))
s1++, s2++;
if (!*s1 && !*s2)
return 0;
else if (tolower(*s1) < tolower(*s2))
return -1;
else
return 1;
}
#endif
#if !defined(strnicmp) && !defined(strncasecmp)
int nasm_strnicmp(const char *s1, const char *s2, int n)
{
while (n > 0 && *s1 && tolower(*s1) == tolower(*s2))
s1++, s2++, n--;
if ((!*s1 && !*s2) || n == 0)
return 0;
else if (tolower(*s1) < tolower(*s2))
return -1;
else
return 1;
}
#endif
#define lib_isnumchar(c) ( isalnum(c) || (c) == '$')
#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
long readnum(char *str, int *error)
{
char *r = str, *q;
long radix;
unsigned long result, checklimit;
int digit, last;
int warn = FALSE;
int sign = 1;
*error = FALSE;
while (isspace(*r))
r++; /* find start of number */
/*
* If the number came from make_tok_num (as a result of an %assign), it
* might have a '-' built into it (rather than in a preceeding token).
*/
if (*r == '-') {
r++;
sign = -1;
}
q = r;
while (lib_isnumchar(*q))
q++; /* find end of number */
/*
* If it begins 0x, 0X or $, or ends in H, it's in hex. if it
* ends in Q, it's octal. if it ends in B, it's binary.
* Otherwise, it's ordinary decimal.
*/
if (*r == '0' && (r[1] == 'x' || r[1] == 'X'))
radix = 16, r += 2;
else if (*r == '$')
radix = 16, r++;
else if (q[-1] == 'H' || q[-1] == 'h')
radix = 16, q--;
else if (q[-1] == 'Q' || q[-1] == 'q' || q[-1] == 'O' || q[-1] == 'o')
radix = 8, q--;
else if (q[-1] == 'B' || q[-1] == 'b')
radix = 2, q--;
else
radix = 10;
/*
* If this number has been found for us by something other than
* the ordinary scanners, then it might be malformed by having
* nothing between the prefix and the suffix. Check this case
* now.
*/
if (r >= q) {
*error = TRUE;
return 0;
}
/*
* `checklimit' must be 2**32 / radix. We can't do that in
* 32-bit arithmetic, which we're (probably) using, so we
* cheat: since we know that all radices we use are even, we
* can divide 2**31 by radix/2 instead.
*/
checklimit = 0x80000000UL / (radix >> 1);
/*
* Calculate the highest allowable value for the last digit
* of a 32 bit constant... in radix 10, it is 6, otherwise it is 0
*/
last = (radix == 10 ? 6 : 0);
result = 0;
while (*r && r < q) {
if (*r < '0' || (*r > '9' && *r < 'A')
|| (digit = numvalue(*r)) >= radix) {
*error = TRUE;
return 0;
}
if (result > checklimit || (result == checklimit && digit >= last)) {
warn = TRUE;
}
result = radix * result + digit;
r++;
}
if (warn)
nasm_malloc_error(ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
"numeric constant %s does not fit in 32 bits",
str);
return result * sign;
}
long readstrnum(char *str, int length, int *warn)
{
long charconst = 0;
int i;
*warn = FALSE;
str += length;
for (i = 0; i < length; i++) {
if (charconst & 0xff000000UL) {
*warn = TRUE;
}
charconst = (charconst << 8) + (unsigned char)*--str;
}
return charconst;
}
static long next_seg;
void seg_init(void)
{
next_seg = 0;
}
long seg_alloc(void)
{
return (next_seg += 2) - 2;
}
void fwriteshort(int data, FILE * fp)
{
fputc((int)(data & 255), fp);
fputc((int)((data >> 8) & 255), fp);
}
void fwritelong(long data, FILE * fp)
{
fputc((int)(data & 255), fp);
fputc((int)((data >> 8) & 255), fp);
fputc((int)((data >> 16) & 255), fp);
fputc((int)((data >> 24) & 255), fp);
}
void standard_extension(char *inname, char *outname, char *extension,
efunc error)
{
char *p, *q;
if (*outname) /* file name already exists, */
return; /* so do nothing */
q = inname;
p = outname;
while (*q)
*p++ = *q++; /* copy, and find end of string */
*p = '\0'; /* terminate it */
while (p > outname && *--p != '.') ; /* find final period (or whatever) */
if (*p != '.')
while (*p)
p++; /* go back to end if none found */
if (!strcmp(p, extension)) { /* is the extension already there? */
if (*extension)
error(ERR_WARNING | ERR_NOFILE,
"file name already ends in `%s': "
"output will be in `nasm.out'", extension);
else
error(ERR_WARNING | ERR_NOFILE,
"file name already has no extension: "
"output will be in `nasm.out'");
strcpy(outname, "nasm.out");
} else
strcpy(p, extension);
}
#define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
#define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
#define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
static struct RAA *real_raa_init(int layers)
{
struct RAA *r;
int i;
if (layers == 0) {
r = nasm_malloc(LEAFSIZ);
r->layers = 0;
memset(r->u.l.data, 0, sizeof(r->u.l.data));
r->stepsize = 1L;
} else {
r = nasm_malloc(BRANCHSIZ);
r->layers = layers;
for (i = 0; i < RAA_LAYERSIZE; i++)
r->u.b.data[i] = NULL;
r->stepsize = RAA_BLKSIZE;
while (--layers)
r->stepsize *= RAA_LAYERSIZE;
}
return r;
}
struct RAA *raa_init(void)
{
return real_raa_init(0);
}
void raa_free(struct RAA *r)
{
if (r->layers == 0)
nasm_free(r);
else {
struct RAA **p;
for (p = r->u.b.data; p - r->u.b.data < RAA_LAYERSIZE; p++)
if (*p)
raa_free(*p);
}
}
long raa_read(struct RAA *r, long posn)
{
if (posn >= r->stepsize * LAYERSIZ(r))
return 0; /* Return 0 for undefined entries */
while (r->layers > 0) {
ldiv_t l;
l = ldiv(posn, r->stepsize);
r = r->u.b.data[l.quot];
posn = l.rem;
if (!r)
return 0; /* Return 0 for undefined entries */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -