doc: Add NASMENV to the index (BR 1917084)
[nasm/autotest.git] / saa.c
blob1704b7db77dcd7747b2cc2e22eb5695b3f1b782a
1 #include "compiler.h"
2 #include "nasmlib.h"
3 #include "saa.h"
5 /* Aggregate SAA components smaller than this */
6 #define SAA_BLKSHIFT 16
7 #define SAA_BLKLEN ((size_t)1 << SAA_BLKSHIFT)
9 struct SAA *saa_init(size_t elem_len)
11 struct SAA *s;
12 char *data;
14 s = nasm_zalloc(sizeof(struct SAA));
16 if (elem_len >= SAA_BLKLEN)
17 s->blk_len = elem_len;
18 else
19 s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len);
21 s->elem_len = elem_len;
22 s->length = s->blk_len;
23 data = nasm_malloc(s->blk_len);
24 s->nblkptrs = s->nblks = 1;
25 s->blk_ptrs = nasm_malloc(sizeof(char *));
26 s->blk_ptrs[0] = data;
27 s->wblk = s->rblk = &s->blk_ptrs[0];
29 return s;
32 void saa_free(struct SAA *s)
34 char **p;
35 size_t n;
37 for (p = s->blk_ptrs, n = s->nblks; n; p++, n--)
38 nasm_free(*p);
40 nasm_free(s->blk_ptrs);
41 nasm_free(s);
44 /* Add one allocation block to an SAA */
45 static void saa_extend(struct SAA *s)
47 size_t blkn = s->nblks++;
49 if (blkn >= s->nblkptrs) {
50 size_t rindex = s->rblk - s->blk_ptrs;
51 size_t windex = s->wblk - s->blk_ptrs;
53 s->nblkptrs <<= 1;
54 s->blk_ptrs = nasm_realloc(s->blk_ptrs, s->nblkptrs*sizeof(char *));
56 s->rblk = s->blk_ptrs + rindex;
57 s->wblk = s->blk_ptrs + windex;
60 s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
61 s->length += s->blk_len;
64 void *saa_wstruct(struct SAA *s)
66 void *p;
68 if (s->wpos % s->elem_len)
69 nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
70 "misaligned wpos in saa_wstruct");
72 if (s->wpos + s->elem_len > s->blk_len) {
73 if (s->wpos != s->blk_len)
74 nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
75 "unfilled block in saa_wstruct");
77 if (s->wptr + s->elem_len > s->length)
78 saa_extend(s);
79 s->wblk++;
80 s->wpos = 0;
83 p = *s->wblk + s->wpos;
84 s->wpos += s->elem_len;
85 s->wptr += s->elem_len;
87 if (s->wptr > s->datalen)
88 s->datalen = s->wptr;
90 return p;
93 void saa_wbytes(struct SAA *s, const void *data, size_t len)
95 const char *d = data;
97 while (len) {
98 size_t l = s->blk_len - s->wpos;
99 if (l > len)
100 l = len;
101 if (l) {
102 if (d) {
103 memcpy(*s->wblk + s->wpos, d, l);
104 d += l;
105 } else
106 memset(*s->wblk + s->wpos, 0, l);
107 s->wpos += l;
108 s->wptr += l;
109 len -= l;
111 if (s->datalen < s->wptr)
112 s->datalen = s->wptr;
114 if (len) {
115 if (s->wptr >= s->length)
116 saa_extend(s);
117 s->wblk++;
118 s->wpos = 0;
123 void saa_rewind(struct SAA *s)
125 s->rblk = s->blk_ptrs;
126 s->rpos = s->rptr = 0;
129 void *saa_rstruct(struct SAA *s)
131 void *p;
133 if (s->rptr + s->elem_len > s->datalen)
134 return NULL;
136 if (s->rpos % s->elem_len)
137 nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
138 "misaligned rpos in saa_rstruct");
140 if (s->rpos + s->elem_len > s->blk_len) {
141 s->rblk++;
142 s->rpos = 0;
145 p = *s->rblk + s->rpos;
146 s->rpos += s->elem_len;
147 s->rptr += s->elem_len;
149 return p;
152 const void *saa_rbytes(struct SAA *s, size_t *lenp)
154 const void *p;
155 size_t len;
157 if (s->rptr >= s->datalen) {
158 *lenp = 0;
159 return NULL;
162 if (s->rpos >= s->blk_len) {
163 s->rblk++;
164 s->rpos = 0;
167 len = *lenp;
168 if (len > s->datalen - s->rptr)
169 len = s->datalen - s->rptr;
170 if (len > s->blk_len - s->rpos)
171 len = s->blk_len - s->rpos;
173 *lenp = len;
174 p = *s->rblk + s->rpos;
176 s->rpos += len;
177 s->rptr += len;
179 return p;
182 void saa_rnbytes(struct SAA *s, void *data, size_t len)
184 char *d = data;
186 if (s->rptr + len > s->datalen) {
187 nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_rnbytes");
188 return;
191 while (len) {
192 size_t l;
193 const void *p;
195 l = len;
196 p = saa_rbytes(s, &l);
198 memcpy(d, p, l);
199 d += l;
200 len -= l;
204 /* Same as saa_rnbytes, except position the counter first */
205 void saa_fread(struct SAA *s, size_t posn, void *data, size_t len)
207 size_t ix;
209 if (posn+len > s->datalen) {
210 nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fread");
211 return;
214 if (likely(s->blk_len == SAA_BLKLEN)) {
215 ix = posn >> SAA_BLKSHIFT;
216 s->rpos = posn & (SAA_BLKLEN-1);
217 } else {
218 ix = posn / s->blk_len;
219 s->rpos = posn % s->blk_len;
221 s->rptr = posn;
222 s->rblk = &s->blk_ptrs[ix];
224 saa_rnbytes(s, data, len);
227 /* Same as saa_wbytes, except position the counter first */
228 void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len)
230 size_t ix;
232 if (posn > s->datalen) {
233 /* Seek beyond the end of the existing array not supported */
234 nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fwrite");
235 return;
238 if (likely(s->blk_len == SAA_BLKLEN)) {
239 ix = posn >> SAA_BLKSHIFT;
240 s->wpos = posn & (SAA_BLKLEN-1);
241 } else {
242 ix = posn / s->blk_len;
243 s->wpos = posn % s->blk_len;
245 s->wptr = posn;
246 s->wblk = &s->blk_ptrs[ix];
248 if (!s->wpos) {
249 s->wpos = s->blk_len;
250 s->wblk--;
253 saa_wbytes(s, data, len);
256 void saa_fpwrite(struct SAA *s, FILE * fp)
258 const char *data;
259 size_t len;
261 saa_rewind(s);
262 while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL)
263 fwrite(data, 1, len, fp);
266 void saa_write8(struct SAA *s, uint8_t v)
268 saa_wbytes(s, &v, 1);
271 #ifdef WORDS_LITTEENDIAN
273 void saa_write16(struct SAA *s, uint16_t v)
275 saa_wbytes(s, &v, 2);
278 void saa_write32(struct SAA *s, uint32_t v)
280 saa_wbytes(s, &v, 4);
283 void saa_write64(struct SAA *s, uint64_t v)
285 saa_wbytes(s, &v, 8);
288 #else /* not WORDS_LITTLEENDIAN */
290 void saa_write16(struct SAA *s, uint16_t v)
292 uint8_t b[2];
294 b[0] = v;
295 b[1] = v >> 8;
296 saa_wbytes(s, b, 2);
299 void saa_write32(struct SAA *s, uint32_t v)
301 uint8_t b[4];
303 b[0] = v;
304 b[1] = v >> 8;
305 b[2] = v >> 16;
306 b[3] = v >> 24;
307 saa_wbytes(s, b, 4);
310 void saa_write64(struct SAA *s, uint64_t v)
312 uint8_t b[8];
314 b[0] = v;
315 b[1] = v >> 8;
316 b[2] = v >> 16;
317 b[3] = v >> 24;
318 b[4] = v >> 32;
319 b[5] = v >> 40;
320 b[6] = v >> 48;
321 b[7] = v >> 56;
322 saa_wbytes(s, b, 8);
325 #endif /* WORDS_LITTLEENDIAN */
327 /* write unsigned LEB128 value to SAA */
328 void saa_wleb128u(struct SAA *psaa, int value)
330 char temp[64], *ptemp;
331 uint8_t byte;
332 int len;
334 ptemp = temp;
335 len = 0;
338 byte = value & 127;
339 value >>= 7;
340 if (value != 0) /* more bytes to come */
341 byte |= 0x80;
342 *ptemp = byte;
343 ptemp++;
344 len++;
345 } while (value != 0);
346 saa_wbytes(psaa, temp, len);
349 /* write signed LEB128 value to SAA */
350 void saa_wleb128s(struct SAA *psaa, int value)
352 char temp[64], *ptemp;
353 uint8_t byte;
354 bool more, negative;
355 int size, len;
357 ptemp = temp;
358 more = 1;
359 negative = (value < 0);
360 size = sizeof(int) * 8;
361 len = 0;
362 while(more)
364 byte = value & 0x7f;
365 value >>= 7;
366 if (negative)
367 /* sign extend */
368 value |= - (1 <<(size - 7));
369 /* sign bit of byte is second high order bit (0x40) */
370 if ((value == 0 && ! (byte & 0x40)) ||
371 ((value == -1) && (byte & 0x40)))
372 more = 0;
373 else
374 byte |= 0x80;
375 *ptemp = byte;
376 ptemp++;
377 len++;
379 saa_wbytes(psaa, temp, len);