diff options
Diffstat (limited to 'vere/ext/nasm/nasmlib/saa.c')
-rw-r--r-- | vere/ext/nasm/nasmlib/saa.c | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/vere/ext/nasm/nasmlib/saa.c b/vere/ext/nasm/nasmlib/saa.c new file mode 100644 index 0000000..dcc2c01 --- /dev/null +++ b/vere/ext/nasm/nasmlib/saa.c @@ -0,0 +1,383 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2017 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#include "compiler.h" +#include "nasmlib.h" +#include "saa.h" + +/* Aggregate SAA components smaller than this */ +#define SAA_BLKSHIFT 16 +#define SAA_BLKLEN ((size_t)1 << SAA_BLKSHIFT) + +struct SAA *saa_init(size_t elem_len) +{ + struct SAA *s; + char *data; + + s = nasm_zalloc(sizeof(struct SAA)); + + if (elem_len >= SAA_BLKLEN) + s->blk_len = elem_len; + else + s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len); + + s->elem_len = elem_len; + s->length = s->blk_len; + data = nasm_malloc(s->blk_len); + s->nblkptrs = s->nblks = 1; + s->blk_ptrs = nasm_malloc(sizeof(char *)); + s->blk_ptrs[0] = data; + s->wblk = s->rblk = &s->blk_ptrs[0]; + + return s; +} + +void saa_free(struct SAA *s) +{ + char **p; + size_t n; + + for (p = s->blk_ptrs, n = s->nblks; n; p++, n--) + nasm_free(*p); + + nasm_free(s->blk_ptrs); + nasm_free(s); +} + +/* Add one allocation block to an SAA */ +static void saa_extend(struct SAA *s) +{ + size_t blkn = s->nblks++; + + if (blkn >= s->nblkptrs) { + size_t rindex = s->rblk - s->blk_ptrs; + size_t windex = s->wblk - s->blk_ptrs; + + s->nblkptrs <<= 1; + s->blk_ptrs = + nasm_realloc(s->blk_ptrs, s->nblkptrs * sizeof(char *)); + + s->rblk = s->blk_ptrs + rindex; + s->wblk = s->blk_ptrs + windex; + } + + s->blk_ptrs[blkn] = nasm_malloc(s->blk_len); + s->length += s->blk_len; +} + +void *saa_wstruct(struct SAA *s) +{ + void *p; + + nasm_assert((s->wpos % s->elem_len) == 0); + + if (s->wpos + s->elem_len > s->blk_len) { + nasm_assert(s->wpos == s->blk_len); + if (s->wptr + s->elem_len > s->length) + saa_extend(s); + s->wblk++; + s->wpos = 0; + } + + p = *s->wblk + s->wpos; + s->wpos += s->elem_len; + s->wptr += s->elem_len; + + if (s->wptr > s->datalen) + s->datalen = s->wptr; + + return p; +} + +void saa_wbytes(struct SAA *s, const void *data, size_t len) +{ + const char *d = data; + + while (len) { + size_t l = s->blk_len - s->wpos; + if (l > len) + l = len; + if (l) { + if (d) { + memcpy(*s->wblk + s->wpos, d, l); + d += l; + } else + memset(*s->wblk + s->wpos, 0, l); + s->wpos += l; + s->wptr += l; + len -= l; + + if (s->datalen < s->wptr) + s->datalen = s->wptr; + } + if (len) { + if (s->wptr >= s->length) + saa_extend(s); + s->wblk++; + s->wpos = 0; + } + } +} + +/* + * Writes a string, *including* the final null, to the specified SAA, + * and return the number of bytes written. + */ +size_t saa_wcstring(struct SAA *s, const char *str) +{ + size_t bytes = strlen(str) + 1; + + saa_wbytes(s, str, bytes); + + return bytes; +} + +void saa_rewind(struct SAA *s) +{ + s->rblk = s->blk_ptrs; + s->rpos = s->rptr = 0; +} + +void *saa_rstruct(struct SAA *s) +{ + void *p; + + if (s->rptr + s->elem_len > s->datalen) + return NULL; + + nasm_assert((s->rpos % s->elem_len) == 0); + + if (s->rpos + s->elem_len > s->blk_len) { + s->rblk++; + s->rpos = 0; + } + + p = *s->rblk + s->rpos; + s->rpos += s->elem_len; + s->rptr += s->elem_len; + + return p; +} + +const void *saa_rbytes(struct SAA *s, size_t * lenp) +{ + const void *p; + size_t len; + + if (s->rptr >= s->datalen) { + *lenp = 0; + return NULL; + } + + if (s->rpos >= s->blk_len) { + s->rblk++; + s->rpos = 0; + } + + len = *lenp; + if (len > s->datalen - s->rptr) + len = s->datalen - s->rptr; + if (len > s->blk_len - s->rpos) + len = s->blk_len - s->rpos; + + *lenp = len; + p = *s->rblk + s->rpos; + + s->rpos += len; + s->rptr += len; + + return p; +} + +void saa_rnbytes(struct SAA *s, void *data, size_t len) +{ + char *d = data; + + nasm_assert(s->rptr + len <= s->datalen); + + while (len) { + size_t l; + const void *p; + + l = len; + p = saa_rbytes(s, &l); + + memcpy(d, p, l); + d += l; + len -= l; + } +} + +/* Same as saa_rnbytes, except position the counter first */ +void saa_fread(struct SAA *s, size_t posn, void *data, size_t len) +{ + size_t ix; + + nasm_assert(posn + len <= s->datalen); + + if (likely(s->blk_len == SAA_BLKLEN)) { + ix = posn >> SAA_BLKSHIFT; + s->rpos = posn & (SAA_BLKLEN - 1); + } else { + ix = posn / s->blk_len; + s->rpos = posn % s->blk_len; + } + s->rptr = posn; + s->rblk = &s->blk_ptrs[ix]; + + saa_rnbytes(s, data, len); +} + +/* Same as saa_wbytes, except position the counter first */ +void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len) +{ + size_t ix; + size_t padding = 0; + + if (posn > s->datalen) { + padding = posn - s->datalen; + posn = s->datalen; + } + + if (likely(s->blk_len == SAA_BLKLEN)) { + ix = posn >> SAA_BLKSHIFT; + s->wpos = posn & (SAA_BLKLEN - 1); + } else { + ix = posn / s->blk_len; + s->wpos = posn % s->blk_len; + } + s->wptr = posn; + s->wblk = &s->blk_ptrs[ix]; + + if (!s->wpos) { + s->wpos = s->blk_len; + s->wblk--; + } + + if (padding) + saa_wbytes(s, NULL, padding); + + saa_wbytes(s, data, len); +} + +void saa_fpwrite(struct SAA *s, FILE * fp) +{ + const char *data; + size_t len; + + saa_rewind(s); + while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL) + nasm_write(data, len, fp); +} + +void saa_write8(struct SAA *s, uint8_t v) +{ + saa_wbytes(s, &v, 1); +} + +void saa_write16(struct SAA *s, uint16_t v) +{ + v = cpu_to_le16(v); + saa_wbytes(s, &v, 2); +} + +void saa_write32(struct SAA *s, uint32_t v) +{ + v = cpu_to_le32(v); + saa_wbytes(s, &v, 4); +} + +void saa_write64(struct SAA *s, uint64_t v) +{ + v = cpu_to_le64(v); + saa_wbytes(s, &v, 8); +} + +void saa_writeaddr(struct SAA *s, uint64_t v, size_t len) +{ + v = cpu_to_le64(v); + saa_wbytes(s, &v, len); +} + +/* write unsigned LEB128 value to SAA */ +void saa_wleb128u(struct SAA *psaa, int value) +{ + char temp[64], *ptemp; + uint8_t byte; + int len; + + ptemp = temp; + len = 0; + do { + byte = value & 127; + value >>= 7; + if (value != 0) /* more bytes to come */ + byte |= 0x80; + *ptemp = byte; + ptemp++; + len++; + } while (value != 0); + saa_wbytes(psaa, temp, len); +} + +/* write signed LEB128 value to SAA */ +void saa_wleb128s(struct SAA *psaa, int value) +{ + char temp[64], *ptemp; + uint8_t byte; + bool more, negative; + int size, len; + + ptemp = temp; + more = 1; + negative = (value < 0); + size = sizeof(int) * 8; + len = 0; + while (more) { + byte = value & 0x7f; + value >>= 7; + if (negative) + /* sign extend */ + value |= -(1 << (size - 7)); + /* sign bit of byte is second high order bit (0x40) */ + if ((value == 0 && !(byte & 0x40)) || + ((value == -1) && (byte & 0x40))) + more = 0; + else + byte |= 0x80; + *ptemp = byte; + ptemp++; + len++; + } + saa_wbytes(psaa, temp, len); +} |