Mercurial > repo
diff nasmbuild/nasm-2.13rc9/nasmlib/saa.c @ 10554:587a0a262d22
<moonythedwarf> ` cd nasmbuild; tar -xf nasm.tar.gz
author | HackBot |
---|---|
date | Thu, 30 Mar 2017 20:58:41 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nasmbuild/nasm-2.13rc9/nasmlib/saa.c Thu Mar 30 20:58:41 2017 +0000 @@ -0,0 +1,418 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 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; + } + } +} + +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; + + /* Seek beyond the end of the existing array not supported */ + nasm_assert(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--; + } + + 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); +} + +#ifdef WORDS_LITTEENDIAN + +void saa_write16(struct SAA *s, uint16_t v) +{ + saa_wbytes(s, &v, 2); +} + +void saa_write32(struct SAA *s, uint32_t v) +{ + saa_wbytes(s, &v, 4); +} + +void saa_write64(struct SAA *s, uint64_t v) +{ + saa_wbytes(s, &v, 8); +} + +void saa_writeaddr(struct SAA *s, uint64_t v, size_t len) +{ + saa_wbytes(s, &v, len); +} + +#else /* not WORDS_LITTLEENDIAN */ + +void saa_write16(struct SAA *s, uint16_t v) +{ + uint8_t b[2]; + + b[0] = v; + b[1] = v >> 8; + saa_wbytes(s, b, 2); +} + +void saa_write32(struct SAA *s, uint32_t v) +{ + uint8_t b[4]; + + b[0] = v; + b[1] = v >> 8; + b[2] = v >> 16; + b[3] = v >> 24; + saa_wbytes(s, b, 4); +} + +void saa_write64(struct SAA *s, uint64_t v) +{ + uint8_t b[8]; + + b[0] = v; + b[1] = v >> 8; + b[2] = v >> 16; + b[3] = v >> 24; + b[4] = v >> 32; + b[5] = v >> 40; + b[6] = v >> 48; + b[7] = v >> 56; + + saa_wbytes(s, b, 8); +} + +void saa_writeaddr(struct SAA *s, uint64_t v, size_t len) +{ + uint8_t b[8]; + + b[0] = v; + b[1] = v >> 8; + b[2] = v >> 16; + b[3] = v >> 24; + b[4] = v >> 32; + b[5] = v >> 40; + b[6] = v >> 48; + b[7] = v >> 56; + + saa_wbytes(s, b, len); +} + +#endif /* WORDS_LITTLEENDIAN */ + +/* 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); +}