doc: document %pop with argument
[nasm/perl-rewrite.git] / saa.c
blobb5068331325918277fca7268c73f7898bd04bd49
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 =
55 nasm_realloc(s->blk_ptrs, s->nblkptrs * sizeof(char *));
57 s->rblk = s->blk_ptrs + rindex;
58 s->wblk = s->blk_ptrs + windex;
61 s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
62 s->length += s->blk_len;
65 void *saa_wstruct(struct SAA *s)
67 void *p;
69 if (s->wpos % s->elem_len)
70 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
71 "misaligned wpos in saa_wstruct");
73 if (s->wpos + s->elem_len > s->blk_len) {
74 if (s->wpos != s->blk_len)
75 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
76 "unfilled block in saa_wstruct");
78 if (s->wptr + s->elem_len > s->length)
79 saa_extend(s);
80 s->wblk++;
81 s->wpos = 0;
84 p = *s->wblk + s->wpos;
85 s->wpos += s->elem_len;
86 s->wptr += s->elem_len;
88 if (s->wptr > s->datalen)
89 s->datalen = s->wptr;
91 return p;
94 void saa_wbytes(struct SAA *s, const void *data, size_t len)
96 const char *d = data;
98 while (len) {
99 size_t l = s->blk_len - s->wpos;
100 if (l > len)
101 l = len;
102 if (l) {
103 if (d) {
104 memcpy(*s->wblk + s->wpos, d, l);
105 d += l;
106 } else
107 memset(*s->wblk + s->wpos, 0, l);
108 s->wpos += l;
109 s->wptr += l;
110 len -= l;
112 if (s->datalen < s->wptr)
113 s->datalen = s->wptr;
115 if (len) {
116 if (s->wptr >= s->length)
117 saa_extend(s);
118 s->wblk++;
119 s->wpos = 0;
124 void saa_rewind(struct SAA *s)
126 s->rblk = s->blk_ptrs;
127 s->rpos = s->rptr = 0;
130 void *saa_rstruct(struct SAA *s)
132 void *p;
134 if (s->rptr + s->elem_len > s->datalen)
135 return NULL;
137 if (s->rpos % s->elem_len)
138 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
139 "misaligned rpos in saa_rstruct");
141 if (s->rpos + s->elem_len > s->blk_len) {
142 s->rblk++;
143 s->rpos = 0;
146 p = *s->rblk + s->rpos;
147 s->rpos += s->elem_len;
148 s->rptr += s->elem_len;
150 return p;
153 const void *saa_rbytes(struct SAA *s, size_t * lenp)
155 const void *p;
156 size_t len;
158 if (s->rptr >= s->datalen) {
159 *lenp = 0;
160 return NULL;
163 if (s->rpos >= s->blk_len) {
164 s->rblk++;
165 s->rpos = 0;
168 len = *lenp;
169 if (len > s->datalen - s->rptr)
170 len = s->datalen - s->rptr;
171 if (len > s->blk_len - s->rpos)
172 len = s->blk_len - s->rpos;
174 *lenp = len;
175 p = *s->rblk + s->rpos;
177 s->rpos += len;
178 s->rptr += len;
180 return p;
183 void saa_rnbytes(struct SAA *s, void *data, size_t len)
185 char *d = data;
187 if (s->rptr + len > s->datalen) {
188 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
189 "overrun in saa_rnbytes");
190 return;
193 while (len) {
194 size_t l;
195 const void *p;
197 l = len;
198 p = saa_rbytes(s, &l);
200 memcpy(d, p, l);
201 d += l;
202 len -= l;
206 /* Same as saa_rnbytes, except position the counter first */
207 void saa_fread(struct SAA *s, size_t posn, void *data, size_t len)
209 size_t ix;
211 if (posn + len > s->datalen) {
212 nasm_malloc_error(ERR_PANIC | ERR_NOFILE, "overrun in saa_fread");
213 return;
216 if (likely(s->blk_len == SAA_BLKLEN)) {
217 ix = posn >> SAA_BLKSHIFT;
218 s->rpos = posn & (SAA_BLKLEN - 1);
219 } else {
220 ix = posn / s->blk_len;
221 s->rpos = posn % s->blk_len;
223 s->rptr = posn;
224 s->rblk = &s->blk_ptrs[ix];
226 saa_rnbytes(s, data, len);
229 /* Same as saa_wbytes, except position the counter first */
230 void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len)
232 size_t ix;
234 if (posn > s->datalen) {
235 /* Seek beyond the end of the existing array not supported */
236 nasm_malloc_error(ERR_PANIC | ERR_NOFILE, "overrun in saa_fwrite");
237 return;
240 if (likely(s->blk_len == SAA_BLKLEN)) {
241 ix = posn >> SAA_BLKSHIFT;
242 s->wpos = posn & (SAA_BLKLEN - 1);
243 } else {
244 ix = posn / s->blk_len;
245 s->wpos = posn % s->blk_len;
247 s->wptr = posn;
248 s->wblk = &s->blk_ptrs[ix];
250 if (!s->wpos) {
251 s->wpos = s->blk_len;
252 s->wblk--;
255 saa_wbytes(s, data, len);
258 void saa_fpwrite(struct SAA *s, FILE * fp)
260 const char *data;
261 size_t len;
263 saa_rewind(s);
264 while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL)
265 fwrite(data, 1, len, fp);
268 void saa_write8(struct SAA *s, uint8_t v)
270 saa_wbytes(s, &v, 1);
273 #ifdef WORDS_LITTEENDIAN
275 void saa_write16(struct SAA *s, uint16_t v)
277 saa_wbytes(s, &v, 2);
280 void saa_write32(struct SAA *s, uint32_t v)
282 saa_wbytes(s, &v, 4);
285 void saa_write64(struct SAA *s, uint64_t v)
287 saa_wbytes(s, &v, 8);
290 void saa_writeaddr(struct SAA *s, uint64_t v, size_t len)
292 saa_wbytes(s, &v, len);
295 #else /* not WORDS_LITTLEENDIAN */
297 void saa_write16(struct SAA *s, uint16_t v)
299 uint8_t b[2];
301 b[0] = v;
302 b[1] = v >> 8;
303 saa_wbytes(s, b, 2);
306 void saa_write32(struct SAA *s, uint32_t v)
308 uint8_t b[4];
310 b[0] = v;
311 b[1] = v >> 8;
312 b[2] = v >> 16;
313 b[3] = v >> 24;
314 saa_wbytes(s, b, 4);
317 void saa_write64(struct SAA *s, uint64_t v)
319 uint8_t b[8];
321 b[0] = v;
322 b[1] = v >> 8;
323 b[2] = v >> 16;
324 b[3] = v >> 24;
325 b[4] = v >> 32;
326 b[5] = v >> 40;
327 b[6] = v >> 48;
328 b[7] = v >> 56;
329 saa_wbytes(s, b, 8);
332 void saa_writeaddr(struct SAA *s, uint64_t v, size_t len)
334 uint8_t b[8];
336 b[0] = v;
337 b[1] = v >> 8;
338 b[2] = v >> 16;
339 b[3] = v >> 24;
340 b[4] = v >> 32;
341 b[5] = v >> 40;
342 b[6] = v >> 48;
343 b[7] = v >> 56;
345 saa_wbytes(s, &v, len);
348 #endif /* WORDS_LITTLEENDIAN */
350 /* write unsigned LEB128 value to SAA */
351 void saa_wleb128u(struct SAA *psaa, int value)
353 char temp[64], *ptemp;
354 uint8_t byte;
355 int len;
357 ptemp = temp;
358 len = 0;
359 do {
360 byte = value & 127;
361 value >>= 7;
362 if (value != 0) /* more bytes to come */
363 byte |= 0x80;
364 *ptemp = byte;
365 ptemp++;
366 len++;
367 } while (value != 0);
368 saa_wbytes(psaa, temp, len);
371 /* write signed LEB128 value to SAA */
372 void saa_wleb128s(struct SAA *psaa, int value)
374 char temp[64], *ptemp;
375 uint8_t byte;
376 bool more, negative;
377 int size, len;
379 ptemp = temp;
380 more = 1;
381 negative = (value < 0);
382 size = sizeof(int) * 8;
383 len = 0;
384 while (more) {
385 byte = value & 0x7f;
386 value >>= 7;
387 if (negative)
388 /* sign extend */
389 value |= -(1 << (size - 7));
390 /* sign bit of byte is second high order bit (0x40) */
391 if ((value == 0 && !(byte & 0x40)) ||
392 ((value == -1) && (byte & 0x40)))
393 more = 0;
394 else
395 byte |= 0x80;
396 *ptemp = byte;
397 ptemp++;
398 len++;
400 saa_wbytes(psaa, temp, len);