1 | /* ----------------------------------------------------------------------- * |
2 | * |
3 | * Copyright 1996-2017 The NASM Authors - All Rights Reserved |
4 | * See the file AUTHORS included with the NASM distribution for |
5 | * the specific copyright holders. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following |
9 | * conditions are met: |
10 | * |
11 | * * Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * * Redistributions in binary form must reproduce the above |
14 | * copyright notice, this list of conditions and the following |
15 | * disclaimer in the documentation and/or other materials provided |
16 | * with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
19 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | * |
32 | * ----------------------------------------------------------------------- */ |
33 | |
34 | #include "compiler.h" |
35 | #include "nasmlib.h" |
36 | #include "saa.h" |
37 | |
38 | /* Aggregate SAA components smaller than this */ |
39 | #define SAA_BLKSHIFT 16 |
40 | #define SAA_BLKLEN ((size_t)1 << SAA_BLKSHIFT) |
41 | |
42 | struct SAA *saa_init(size_t elem_len) |
43 | { |
44 | struct SAA *s; |
45 | char *data; |
46 | |
47 | s = nasm_zalloc(sizeof(struct SAA)); |
48 | |
49 | if (elem_len >= SAA_BLKLEN) |
50 | s->blk_len = elem_len; |
51 | else |
52 | s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len); |
53 | |
54 | s->elem_len = elem_len; |
55 | s->length = s->blk_len; |
56 | data = nasm_malloc(s->blk_len); |
57 | s->nblkptrs = s->nblks = 1; |
58 | s->blk_ptrs = nasm_malloc(sizeof(char *)); |
59 | s->blk_ptrs[0] = data; |
60 | s->wblk = s->rblk = &s->blk_ptrs[0]; |
61 | |
62 | return s; |
63 | } |
64 | |
65 | void saa_free(struct SAA *s) |
66 | { |
67 | char **p; |
68 | size_t n; |
69 | |
70 | for (p = s->blk_ptrs, n = s->nblks; n; p++, n--) |
71 | nasm_free(*p); |
72 | |
73 | nasm_free(s->blk_ptrs); |
74 | nasm_free(s); |
75 | } |
76 | |
77 | /* Add one allocation block to an SAA */ |
78 | static void saa_extend(struct SAA *s) |
79 | { |
80 | size_t blkn = s->nblks++; |
81 | |
82 | if (blkn >= s->nblkptrs) { |
83 | size_t rindex = s->rblk - s->blk_ptrs; |
84 | size_t windex = s->wblk - s->blk_ptrs; |
85 | |
86 | s->nblkptrs <<= 1; |
87 | s->blk_ptrs = |
88 | nasm_realloc(s->blk_ptrs, s->nblkptrs * sizeof(char *)); |
89 | |
90 | s->rblk = s->blk_ptrs + rindex; |
91 | s->wblk = s->blk_ptrs + windex; |
92 | } |
93 | |
94 | s->blk_ptrs[blkn] = nasm_malloc(s->blk_len); |
95 | s->length += s->blk_len; |
96 | } |
97 | |
98 | void *saa_wstruct(struct SAA *s) |
99 | { |
100 | void *p; |
101 | |
102 | nasm_assert((s->wpos % s->elem_len) == 0); |
103 | |
104 | if (s->wpos + s->elem_len > s->blk_len) { |
105 | nasm_assert(s->wpos == s->blk_len); |
106 | if (s->wptr + s->elem_len > s->length) |
107 | saa_extend(s); |
108 | s->wblk++; |
109 | s->wpos = 0; |
110 | } |
111 | |
112 | p = *s->wblk + s->wpos; |
113 | s->wpos += s->elem_len; |
114 | s->wptr += s->elem_len; |
115 | |
116 | if (s->wptr > s->datalen) |
117 | s->datalen = s->wptr; |
118 | |
119 | return p; |
120 | } |
121 | |
122 | void saa_wbytes(struct SAA *s, const void *data, size_t len) |
123 | { |
124 | const char *d = data; |
125 | |
126 | while (len) { |
127 | size_t l = s->blk_len - s->wpos; |
128 | if (l > len) |
129 | l = len; |
130 | if (l) { |
131 | if (d) { |
132 | memcpy(*s->wblk + s->wpos, d, l); |
133 | d += l; |
134 | } else |
135 | memset(*s->wblk + s->wpos, 0, l); |
136 | s->wpos += l; |
137 | s->wptr += l; |
138 | len -= l; |
139 | |
140 | if (s->datalen < s->wptr) |
141 | s->datalen = s->wptr; |
142 | } |
143 | if (len) { |
144 | if (s->wptr >= s->length) |
145 | saa_extend(s); |
146 | s->wblk++; |
147 | s->wpos = 0; |
148 | } |
149 | } |
150 | } |
151 | |
152 | /* |
153 | * Writes a string, *including* the final null, to the specified SAA, |
154 | * and return the number of bytes written. |
155 | */ |
156 | size_t saa_wcstring(struct SAA *s, const char *str) |
157 | { |
158 | size_t bytes = strlen(str) + 1; |
159 | |
160 | saa_wbytes(s, str, bytes); |
161 | |
162 | return bytes; |
163 | } |
164 | |
165 | void saa_rewind(struct SAA *s) |
166 | { |
167 | s->rblk = s->blk_ptrs; |
168 | s->rpos = s->rptr = 0; |
169 | } |
170 | |
171 | void *saa_rstruct(struct SAA *s) |
172 | { |
173 | void *p; |
174 | |
175 | if (s->rptr + s->elem_len > s->datalen) |
176 | return NULL; |
177 | |
178 | nasm_assert((s->rpos % s->elem_len) == 0); |
179 | |
180 | if (s->rpos + s->elem_len > s->blk_len) { |
181 | s->rblk++; |
182 | s->rpos = 0; |
183 | } |
184 | |
185 | p = *s->rblk + s->rpos; |
186 | s->rpos += s->elem_len; |
187 | s->rptr += s->elem_len; |
188 | |
189 | return p; |
190 | } |
191 | |
192 | const void *saa_rbytes(struct SAA *s, size_t * lenp) |
193 | { |
194 | const void *p; |
195 | size_t len; |
196 | |
197 | if (s->rptr >= s->datalen) { |
198 | *lenp = 0; |
199 | return NULL; |
200 | } |
201 | |
202 | if (s->rpos >= s->blk_len) { |
203 | s->rblk++; |
204 | s->rpos = 0; |
205 | } |
206 | |
207 | len = *lenp; |
208 | if (len > s->datalen - s->rptr) |
209 | len = s->datalen - s->rptr; |
210 | if (len > s->blk_len - s->rpos) |
211 | len = s->blk_len - s->rpos; |
212 | |
213 | *lenp = len; |
214 | p = *s->rblk + s->rpos; |
215 | |
216 | s->rpos += len; |
217 | s->rptr += len; |
218 | |
219 | return p; |
220 | } |
221 | |
222 | void saa_rnbytes(struct SAA *s, void *data, size_t len) |
223 | { |
224 | char *d = data; |
225 | |
226 | nasm_assert(s->rptr + len <= s->datalen); |
227 | |
228 | while (len) { |
229 | size_t l; |
230 | const void *p; |
231 | |
232 | l = len; |
233 | p = saa_rbytes(s, &l); |
234 | |
235 | memcpy(d, p, l); |
236 | d += l; |
237 | len -= l; |
238 | } |
239 | } |
240 | |
241 | /* Same as saa_rnbytes, except position the counter first */ |
242 | void saa_fread(struct SAA *s, size_t posn, void *data, size_t len) |
243 | { |
244 | size_t ix; |
245 | |
246 | nasm_assert(posn + len <= s->datalen); |
247 | |
248 | if (likely(s->blk_len == SAA_BLKLEN)) { |
249 | ix = posn >> SAA_BLKSHIFT; |
250 | s->rpos = posn & (SAA_BLKLEN - 1); |
251 | } else { |
252 | ix = posn / s->blk_len; |
253 | s->rpos = posn % s->blk_len; |
254 | } |
255 | s->rptr = posn; |
256 | s->rblk = &s->blk_ptrs[ix]; |
257 | |
258 | saa_rnbytes(s, data, len); |
259 | } |
260 | |
261 | /* Same as saa_wbytes, except position the counter first */ |
262 | void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len) |
263 | { |
264 | size_t ix; |
265 | |
266 | /* Seek beyond the end of the existing array not supported */ |
267 | nasm_assert(posn <= s->datalen); |
268 | |
269 | if (likely(s->blk_len == SAA_BLKLEN)) { |
270 | ix = posn >> SAA_BLKSHIFT; |
271 | s->wpos = posn & (SAA_BLKLEN - 1); |
272 | } else { |
273 | ix = posn / s->blk_len; |
274 | s->wpos = posn % s->blk_len; |
275 | } |
276 | s->wptr = posn; |
277 | s->wblk = &s->blk_ptrs[ix]; |
278 | |
279 | if (!s->wpos) { |
280 | s->wpos = s->blk_len; |
281 | s->wblk--; |
282 | } |
283 | |
284 | saa_wbytes(s, data, len); |
285 | } |
286 | |
287 | void saa_fpwrite(struct SAA *s, FILE * fp) |
288 | { |
289 | const char *data; |
290 | size_t len; |
291 | |
292 | saa_rewind(s); |
293 | while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL) |
294 | nasm_write(data, len, fp); |
295 | } |
296 | |
297 | void saa_write8(struct SAA *s, uint8_t v) |
298 | { |
299 | saa_wbytes(s, &v, 1); |
300 | } |
301 | |
302 | void saa_write16(struct SAA *s, uint16_t v) |
303 | { |
304 | v = cpu_to_le16(v); |
305 | saa_wbytes(s, &v, 2); |
306 | } |
307 | |
308 | void saa_write32(struct SAA *s, uint32_t v) |
309 | { |
310 | v = cpu_to_le32(v); |
311 | saa_wbytes(s, &v, 4); |
312 | } |
313 | |
314 | void saa_write64(struct SAA *s, uint64_t v) |
315 | { |
316 | v = cpu_to_le64(v); |
317 | saa_wbytes(s, &v, 8); |
318 | } |
319 | |
320 | void saa_writeaddr(struct SAA *s, uint64_t v, size_t len) |
321 | { |
322 | v = cpu_to_le64(v); |
323 | saa_wbytes(s, &v, len); |
324 | } |
325 | |
326 | /* write unsigned LEB128 value to SAA */ |
327 | void saa_wleb128u(struct SAA *psaa, int value) |
328 | { |
329 | char temp[64], *ptemp; |
330 | uint8_t byte; |
331 | int len; |
332 | |
333 | ptemp = temp; |
334 | len = 0; |
335 | do { |
336 | byte = value & 127; |
337 | value >>= 7; |
338 | if (value != 0) /* more bytes to come */ |
339 | byte |= 0x80; |
340 | *ptemp = byte; |
341 | ptemp++; |
342 | len++; |
343 | } while (value != 0); |
344 | saa_wbytes(psaa, temp, len); |
345 | } |
346 | |
347 | /* write signed LEB128 value to SAA */ |
348 | void saa_wleb128s(struct SAA *psaa, int value) |
349 | { |
350 | char temp[64], *ptemp; |
351 | uint8_t byte; |
352 | bool more, negative; |
353 | int size, len; |
354 | |
355 | ptemp = temp; |
356 | more = 1; |
357 | negative = (value < 0); |
358 | size = sizeof(int) * 8; |
359 | len = 0; |
360 | while (more) { |
361 | byte = value & 0x7f; |
362 | value >>= 7; |
363 | if (negative) |
364 | /* sign extend */ |
365 | value |= -(1 << (size - 7)); |
366 | /* sign bit of byte is second high order bit (0x40) */ |
367 | if ((value == 0 && !(byte & 0x40)) || |
368 | ((value == -1) && (byte & 0x40))) |
369 | more = 0; |
370 | else |
371 | byte |= 0x80; |
372 | *ptemp = byte; |
373 | ptemp++; |
374 | len++; |
375 | } |
376 | saa_wbytes(psaa, temp, len); |
377 | } |
378 | |