Merge branch 'nasm-2.03.x'
[platform/upstream/nasm.git] / saa.c
1 #include "compiler.h"
2 #include "nasmlib.h"
3 #include "saa.h"
4
5 /* Aggregate SAA components smaller than this */
6 #define SAA_BLKSHIFT    16
7 #define SAA_BLKLEN      ((size_t)1 << SAA_BLKSHIFT)
8
9 struct SAA *saa_init(size_t elem_len)
10 {
11     struct SAA *s;
12     char *data;
13
14     s = nasm_zalloc(sizeof(struct SAA));
15
16     if (elem_len >= SAA_BLKLEN)
17         s->blk_len = elem_len;
18     else
19         s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len);
20
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];
28
29     return s;
30 }
31
32 void saa_free(struct SAA *s)
33 {
34     char **p;
35     size_t n;
36
37     for (p = s->blk_ptrs, n = s->nblks; n; p++, n--)
38         nasm_free(*p);
39
40     nasm_free(s->blk_ptrs);
41     nasm_free(s);
42 }
43
44 /* Add one allocation block to an SAA */
45 static void saa_extend(struct SAA *s)
46 {
47     size_t blkn = s->nblks++;
48
49     if (blkn >= s->nblkptrs) {
50         size_t rindex = s->rblk - s->blk_ptrs;
51         size_t windex = s->wblk - s->blk_ptrs;
52
53         s->nblkptrs <<= 1;
54         s->blk_ptrs = nasm_realloc(s->blk_ptrs, s->nblkptrs*sizeof(char *));
55
56         s->rblk = s->blk_ptrs + rindex;
57         s->wblk = s->blk_ptrs + windex;
58     }
59
60     s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
61     s->length += s->blk_len;
62 }
63
64 void *saa_wstruct(struct SAA *s)
65 {
66     void *p;
67
68     if (s->wpos % s->elem_len)
69             nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
70                               "misaligned wpos in saa_wstruct");
71
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");
76
77         if (s->wptr + s->elem_len > s->length)
78             saa_extend(s);
79         s->wblk++;
80         s->wpos = 0;
81     }
82
83     p = *s->wblk + s->wpos;
84     s->wpos += s->elem_len;
85     s->wptr += s->elem_len;
86
87     if (s->wptr > s->datalen)
88         s->datalen = s->wptr;
89
90     return p;
91 }
92
93 void saa_wbytes(struct SAA *s, const void *data, size_t len)
94 {
95     const char *d = data;
96
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;
110
111             if (s->datalen < s->wptr)
112                 s->datalen = s->wptr;
113         }
114         if (len) {
115             if (s->wptr >= s->length)
116                 saa_extend(s);
117             s->wblk++;
118             s->wpos = 0;
119         }
120     }
121 }
122
123 void saa_rewind(struct SAA *s)
124 {
125     s->rblk = s->blk_ptrs;
126     s->rpos = s->rptr = 0;
127 }
128
129 void *saa_rstruct(struct SAA *s)
130 {
131     void *p;
132
133     if (s->rptr + s->elem_len > s->datalen)
134         return NULL;
135
136     if (s->rpos % s->elem_len)
137             nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
138                               "misaligned rpos in saa_rstruct");
139
140     if (s->rpos + s->elem_len > s->blk_len) {
141         s->rblk++;
142         s->rpos = 0;
143     }
144
145     p = *s->rblk + s->rpos;
146     s->rpos += s->elem_len;
147     s->rptr += s->elem_len;
148
149     return p;
150 }
151
152 const void *saa_rbytes(struct SAA *s, size_t *lenp)
153 {
154     const void *p;
155     size_t len;
156
157     if (s->rptr >= s->datalen) {
158         *lenp = 0;
159         return NULL;
160     }
161
162     if (s->rpos >= s->blk_len) {
163         s->rblk++;
164         s->rpos = 0;
165     }
166
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;
172
173     *lenp = len;
174     p = *s->rblk + s->rpos;
175
176     s->rpos += len;
177     s->rptr += len;
178
179     return p;
180 }
181
182 void saa_rnbytes(struct SAA *s, void *data, size_t len)
183 {
184     char *d = data;
185
186     if (s->rptr + len > s->datalen) {
187         nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_rnbytes");
188         return;
189     }
190
191     while (len) {
192         size_t l;
193         const void *p;
194
195         l = len;
196         p = saa_rbytes(s, &l);
197
198         memcpy(d, p, l);
199         d   += l;
200         len -= l;
201     }
202 }
203
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)
206 {
207     size_t ix;
208
209     if (posn+len > s->datalen) {
210         nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fread");
211         return;
212     }
213
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;
220     }
221     s->rptr = posn;
222     s->rblk = &s->blk_ptrs[ix];
223
224     saa_rnbytes(s, data, len);
225 }
226
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)
229 {
230     size_t ix;
231
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;
236     }
237     
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;
244     }
245     s->wptr = posn;
246     s->wblk = &s->blk_ptrs[ix];
247
248     if (!s->wpos) {
249         s->wpos = s->blk_len;
250         s->wblk--;
251     }
252
253     saa_wbytes(s, data, len);
254 }
255
256 void saa_fpwrite(struct SAA *s, FILE * fp)
257 {
258     const char *data;
259     size_t len;
260
261     saa_rewind(s);
262     while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL)
263         fwrite(data, 1, len, fp);
264 }
265
266 void saa_write8(struct SAA *s, uint8_t v)
267 {
268     saa_wbytes(s, &v, 1);
269 }
270
271 #ifdef WORDS_LITTEENDIAN
272
273 void saa_write16(struct SAA *s, uint16_t v)
274 {
275     saa_wbytes(s, &v, 2);
276 }
277
278 void saa_write32(struct SAA *s, uint32_t v)
279 {
280     saa_wbytes(s, &v, 4);
281 }
282
283 void saa_write64(struct SAA *s, uint64_t v)
284 {
285     saa_wbytes(s, &v, 8);
286 }
287
288 #else /* not WORDS_LITTLEENDIAN */
289
290 void saa_write16(struct SAA *s, uint16_t v)
291 {
292     uint8_t b[2];
293
294     b[0] = v;
295     b[1] = v >> 8;
296     saa_wbytes(s, b, 2);
297 }
298
299 void saa_write32(struct SAA *s, uint32_t v)
300 {
301     uint8_t b[4];
302
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);
308 }
309
310 void saa_write64(struct SAA *s, uint64_t v)
311 {
312     uint8_t b[8];
313
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);
323 }
324
325 #endif  /* WORDS_LITTLEENDIAN */
326
327 /* write unsigned LEB128 value to SAA */
328 void saa_wleb128u(struct SAA *psaa, int value)
329 {
330   char temp[64], *ptemp;
331   uint8_t byte;
332   int len;
333
334   ptemp = temp;
335   len = 0;
336   do
337   {
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);
347 }
348
349 /* write signed LEB128 value to SAA */
350 void saa_wleb128s(struct SAA *psaa, int value)
351 {
352   char temp[64], *ptemp;
353   uint8_t byte;
354   bool more, negative;
355   int size, len;
356
357   ptemp = temp;
358   more = 1;
359   negative = (value < 0);
360   size = sizeof(int) * 8;
361   len = 0;
362   while(more)
363   {
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++;
378   }
379   saa_wbytes(psaa, temp, len);
380 }