diff options
author | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 20:51:32 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 20:51:32 +0000 |
commit | ea6e34db64c7da7cb885197316c6b5e7d048bdb9 (patch) | |
tree | 78e728348f8fe09e394a51c3617e6261de0f4001 /nasmlib.c | |
download | nasm-ea6e34db64c7da7cb885197316c6b5e7d048bdb9.tar.gz nasm-ea6e34db64c7da7cb885197316c6b5e7d048bdb9.tar.bz2 nasm-ea6e34db64c7da7cb885197316c6b5e7d048bdb9.zip |
NASM 0.91
Diffstat (limited to 'nasmlib.c')
-rw-r--r-- | nasmlib.c | 488 |
1 files changed, 488 insertions, 0 deletions
diff --git a/nasmlib.c b/nasmlib.c new file mode 100644 index 0000000..c8710b0 --- /dev/null +++ b/nasmlib.c @@ -0,0 +1,488 @@ +/* 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" + +static efunc nasm_malloc_error; + +void nasm_set_malloc_error (efunc error) { + nasm_malloc_error = error; +} + +void *nasm_malloc (size_t size) { + void *p = malloc(size); + if (!p) + nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory"); + return p; +} + +void *nasm_realloc (void *q, size_t size) { + void *p = q ? realloc(q, size) : malloc(size); + if (!p) + nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory"); + return p; +} + +void nasm_free (void *q) { + if (q) + free (q); +} + +char *nasm_strdup (char *s) { + char *p; + + p = nasm_malloc(strlen(s)+1); + strcpy (p, s); + return p; +} + +int nasm_stricmp (char *s1, char *s2) { + while (*s1 && toupper(*s1) == toupper(*s2)) + s1++, s2++; + if (!*s1 && !*s2) + return 0; + else if (toupper(*s1) < toupper(*s2)) + return -1; + else + return 1; +} + +int nasm_strnicmp (char *s1, char *s2, int n) { + while (n > 0 && *s1 && toupper(*s1) == toupper(*s2)) + s1++, s2++, n--; + if ((!*s1 && !*s2) || n==0) + return 0; + else if (toupper(*s1) < toupper(*s2)) + return -1; + else + return 1; +} + +#define 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; + long result; + + *error = FALSE; + + while (isspace(*r)) r++; /* find start of number */ + q = r; + + while (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') + radix = 8 , q--; + else if (q[-1]=='B' || q[-1]=='b') + radix = 2 , q--; + else + radix = 10; + + result = 0; + while (*r && r < q) { + if (*r<'0' || (*r>'9' && *r<'A') || numvalue(*r)>=radix) { + *error = TRUE; + return 0; + } + result = radix * result + numvalue(*r); + r++; + } + return result; +} + +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 (data & 255, fp); + fputc ((data >> 8) & 255, fp); +} + +void fwritelong (long data, FILE *fp) { + fputc (data & 255, fp); + fputc ((data >> 8) & 255, fp); + fputc ((data >> 16) & 255, fp); + fputc ((data >> 24) & 255, fp); +} + +void standard_extension (char *inname, char *outname, char *extension, + efunc error) { + char *p, *q; + + 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 RAA_BLKSIZE 4096 /* this many longs allocated at once */ +#define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */ + +typedef struct RAA RAA; +typedef union RAA_UNION RAA_UNION; +typedef struct RAA_LEAF RAA_LEAF; +typedef struct RAA_BRANCH RAA_BRANCH; + +struct RAA { + int layers; + long stepsize; + union RAA_UNION { + struct RAA_LEAF { + long data[RAA_BLKSIZE]; + } l; + struct RAA_BRANCH { + struct RAA *data[RAA_LAYERSIZE]; + } b; + } u; +}; + +#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; + + if (layers == 0) { + r = nasm_malloc (LEAFSIZ); + memset (r->u.l.data, 0, sizeof(r->u.l.data)); + r->layers = 0; + r->stepsize = 1L; + } else { + r = nasm_malloc (BRANCHSIZ); + memset (r->u.b.data, 0, sizeof(r->u.b.data)); + r->layers = layers; + r->stepsize = 1L; + 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 0L; + while (r->layers > 0) { + ldiv_t l; + l = ldiv (posn, r->stepsize); + r = r->u.b.data[l.quot]; + posn = l.rem; + if (!r) /* better check this */ + return 0L; + } + return r->u.l.data[posn]; +} + +struct RAA *raa_write (struct RAA *r, long posn, long value) { + struct RAA *result; + + if (posn < 0) + nasm_malloc_error (ERR_PANIC, "negative position in raa_write"); + + while (r->stepsize * LAYERSIZ(r) < posn) { + /* + * Must go up a layer. + */ + struct RAA *s; + + s = nasm_malloc (BRANCHSIZ); + memset (s->u.b.data, 0, sizeof(r->u.b.data)); + s->layers = r->layers + 1; + s->stepsize = RAA_LAYERSIZE * r->stepsize; + s->u.b.data[0] = r; + r = s; + } + + result = r; + + while (r->layers > 0) { + ldiv_t l; + struct RAA **s; + l = ldiv (posn, r->stepsize); + s = &r->u.b.data[l.quot]; + if (!*s) + *s = real_raa_init (r->layers - 1); + r = *s; + posn = l.rem; + } + + r->u.l.data[posn] = value; + + return result; +} + +#define SAA_MAXLEN 8192 + +struct SAA { + /* + * members `end' and `elem_len' are only valid in first link in + * list; `rptr' and `rpos' are used for reading + */ + struct SAA *next, *end, *rptr; + long elem_len, length, posn, start, rpos; + char *data; +}; + +struct SAA *saa_init (long elem_len) { + struct SAA *s; + + if (elem_len > SAA_MAXLEN) + nasm_malloc_error (ERR_PANIC | ERR_NOFILE, "SAA with huge elements"); + + s = nasm_malloc (sizeof(struct SAA)); + s->posn = s->start = 0L; + s->elem_len = elem_len; + s->length = SAA_MAXLEN - (SAA_MAXLEN % elem_len); + s->data = nasm_malloc (s->length); + s->next = NULL; + s->end = s; + + return s; +} + +void saa_free (struct SAA *s) { + struct SAA *t; + + while (s) { + t = s->next; + nasm_free (s->data); + nasm_free (s); + s = t; + } +} + +void *saa_wstruct (struct SAA *s) { + void *p; + + if (s->end->length - s->end->posn < s->elem_len) { + s->end->next = nasm_malloc (sizeof(struct SAA)); + s->end->next->start = s->end->start + s->end->posn; + s->end = s->end->next; + s->end->length = s->length; + s->end->next = NULL; + s->end->posn = 0L; + s->end->data = nasm_malloc (s->length); + } + + p = s->end->data + s->end->posn; + s->end->posn += s->elem_len; + return p; +} + +void saa_wbytes (struct SAA *s, void *data, long len) { + char *d = data; + + while (len > 0) { + long l = s->end->length - s->end->posn; + if (l > len) + l = len; + if (l > 0) { + if (d) { + memcpy (s->end->data + s->end->posn, d, l); + d += l; + } else + memset (s->end->data + s->end->posn, 0, l); + s->end->posn += l; + len -= l; + } + if (len > 0) { + s->end->next = nasm_malloc (sizeof(struct SAA)); + s->end->next->start = s->end->start + s->end->posn; + s->end = s->end->next; + s->end->length = s->length; + s->end->next = NULL; + s->end->posn = 0L; + s->end->data = nasm_malloc (s->length); + } + } +} + +void saa_rewind (struct SAA *s) { + s->rptr = s; + s->rpos = 0L; +} + +void *saa_rstruct (struct SAA *s) { + void *p; + + if (!s->rptr) + return NULL; + + if (s->rptr->posn - s->rpos < s->elem_len) { + s->rptr = s->rptr->next; + if (!s->rptr) + return NULL; /* end of array */ + s->rpos = 0L; + } + + p = s->rptr->data + s->rpos; + s->rpos += s->elem_len; + return p; +} + +void *saa_rbytes (struct SAA *s, long *len) { + void *p; + + if (!s->rptr) + return NULL; + + p = s->rptr->data + s->rpos; + *len = s->rptr->posn - s->rpos; + s->rptr = s->rptr->next; + s->rpos = 0L; + return p; +} + +void saa_rnbytes (struct SAA *s, void *data, long len) { + char *d = data; + + while (len > 0) { + long l; + + if (!s->rptr) + return; + + l = s->rptr->posn - s->rpos; + if (l > len) + l = len; + if (l > 0) { + memcpy (d, s->rptr->data + s->rpos, l); + d += l; + s->rpos += l; + len -= l; + } + if (len > 0) { + s->rptr = s->rptr->next; + s->rpos = 0L; + } + } +} + +void saa_fread (struct SAA *s, long posn, void *data, long len) { + struct SAA *p; + long pos; + char *cdata = data; + + if (!s->rptr || posn > s->rptr->start + s->rpos) + saa_rewind (s); + while (posn >= s->rptr->start + s->rptr->posn) { + s->rptr = s->rptr->next; + if (!s->rptr) + return; /* what else can we do?! */ + } + + p = s->rptr; + pos = posn - s->rptr->start; + while (len) { + long l = s->rptr->posn - pos; + if (l > len) + l = len; + memcpy (cdata, s->rptr->data+pos, l); + len -= l; + cdata += l; + p = p->next; + if (!p) + return; + pos = 0L; + } +} + +void saa_fwrite (struct SAA *s, long posn, void *data, long len) { + struct SAA *p; + long pos; + char *cdata = data; + + if (!s->rptr || posn > s->rptr->start + s->rpos) + saa_rewind (s); + while (posn >= s->rptr->start + s->rptr->posn) { + s->rptr = s->rptr->next; + if (!s->rptr) + return; /* what else can we do?! */ + } + + p = s->rptr; + pos = posn - s->rptr->start; + while (len) { + long l = s->rptr->posn - pos; + if (l > len) + l = len; + memcpy (s->rptr->data+pos, cdata, l); + len -= l; + cdata += l; + p = p->next; + if (!p) + return; + pos = 0L; + } +} + +void saa_fpwrite (struct SAA *s, FILE *fp) { + char *data; + long len; + + saa_rewind (s); + while ( (data = saa_rbytes (s, &len)) ) + fwrite (data, 1, len, fp); +} |