blob: 260224951c898931e124bdb878c30ee1335a4dfd [file] [log] [blame]
David Gibsonfc14dad2005-06-08 17:18:34 +10001/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
David Gibson63dc9c72007-09-18 11:44:04 +10004 *
David Gibsonfc14dad2005-06-08 17:18:34 +10005 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
David Gibson63dc9c72007-09-18 11:44:04 +100014 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
David Gibsonfc14dad2005-06-08 17:18:34 +100019 */
20
21#include "dtc.h"
Jon Loeligeraf0278a2007-02-15 10:59:27 -060022#include "dtc-parser.tab.h"
David Gibsonfc14dad2005-06-08 17:18:34 +100023
David Gibson81f2e892005-06-16 17:04:00 +100024void fixup_free(struct fixup *f)
25{
26 free(f->ref);
27 free(f);
28}
29
David Gibsonfc14dad2005-06-08 17:18:34 +100030void data_free(struct data d)
31{
Milton Miller6a99b132007-07-07 01:18:51 -050032 struct fixup *f, *nf;
David Gibson81f2e892005-06-16 17:04:00 +100033
34 f = d.refs;
35 while (f) {
Milton Miller6a99b132007-07-07 01:18:51 -050036 nf = f->next;
37 fixup_free(f);
38 f = nf;
39 }
David Gibson81f2e892005-06-16 17:04:00 +100040
Milton Miller6a99b132007-07-07 01:18:51 -050041 f = d.labels;
42 while (f) {
David Gibson81f2e892005-06-16 17:04:00 +100043 nf = f->next;
44 fixup_free(f);
45 f = nf;
46 }
47
David Gibsonfc14dad2005-06-08 17:18:34 +100048 assert(!d.val || d.asize);
49
50 if (d.val)
51 free(d.val);
52}
53
54struct data data_grow_for(struct data d, int xlen)
55{
56 struct data nd;
57 int newsize;
58
59 /* we must start with an allocated datum */
60 assert(!d.val || d.asize);
61
62 if (xlen == 0)
63 return d;
64
Milton Miller46779e82007-07-07 01:18:49 -050065 nd = d;
66
David Gibsonfc14dad2005-06-08 17:18:34 +100067 newsize = xlen;
68
69 while ((d.len + xlen) > newsize)
70 newsize *= 2;
71
72 nd.asize = newsize;
73 nd.val = xrealloc(d.val, newsize);
David Gibsonfc14dad2005-06-08 17:18:34 +100074
75 assert(nd.asize >= (d.len + xlen));
76
77 return nd;
78}
79
80struct data data_copy_mem(char *mem, int len)
81{
82 struct data d;
83
84 d = data_grow_for(empty_data, len);
85
86 d.len = len;
87 memcpy(d.val, mem, len);
88
89 return d;
90}
91
David Gibson230f2532005-08-29 12:48:02 +100092static char get_oct_char(char *s, int *i)
David Gibsonfc14dad2005-06-08 17:18:34 +100093{
94 char x[4];
95 char *endx;
96 long val;
97
98 x[3] = '\0';
99 x[0] = s[(*i)];
100 if (x[0]) {
101 x[1] = s[(*i)+1];
102 if (x[1])
103 x[2] = s[(*i)+2];
104 }
105
106 val = strtol(x, &endx, 8);
107 if ((endx - x) == 0)
108 fprintf(stderr, "Empty \\nnn escape\n");
David Gibson63dc9c72007-09-18 11:44:04 +1000109
David Gibsonfc14dad2005-06-08 17:18:34 +1000110 (*i) += endx - x;
111 return val;
112}
113
David Gibson230f2532005-08-29 12:48:02 +1000114static char get_hex_char(char *s, int *i)
David Gibsonfc14dad2005-06-08 17:18:34 +1000115{
116 char x[3];
117 char *endx;
118 long val;
119
120 x[2] = '\0';
121 x[0] = s[(*i)];
122 if (x[0])
123 x[1] = s[(*i)+1];
124
125 val = strtol(x, &endx, 16);
126 if ((endx - x) == 0)
127 fprintf(stderr, "Empty \\x escape\n");
David Gibson63dc9c72007-09-18 11:44:04 +1000128
David Gibsonfc14dad2005-06-08 17:18:34 +1000129 (*i) += endx - x;
130 return val;
131}
132
133struct data data_copy_escape_string(char *s, int len)
134{
135 int i = 0;
136 struct data d;
137 char *q;
138
139 d = data_grow_for(empty_data, strlen(s)+1);
140
141 q = d.val;
142 while (i < len) {
143 char c = s[i++];
144
145 if (c != '\\') {
146 q[d.len++] = c;
147 continue;
148 }
149
150 c = s[i++];
151 assert(c);
152 switch (c) {
153 case 't':
154 q[d.len++] = '\t';
155 break;
156 case 'n':
157 q[d.len++] = '\n';
158 break;
159 case 'r':
160 q[d.len++] = '\r';
161 break;
David Gibsonb4ac0492005-10-17 10:27:45 +1000162 case '0':
163 case '1':
164 case '2':
165 case '3':
166 case '4':
167 case '5':
168 case '6':
169 case '7':
David Gibsonfc14dad2005-06-08 17:18:34 +1000170 i--; /* need to re-read the first digit as
171 * part of the octal value */
172 q[d.len++] = get_oct_char(s, &i);
173 break;
174 case 'x':
175 q[d.len++] = get_hex_char(s, &i);
176 break;
177 default:
178 q[d.len++] = c;
179 }
180 }
181
182 q[d.len++] = '\0';
183 return d;
184}
185
186struct data data_copy_file(FILE *f, size_t len)
187{
188 struct data d;
189
190 d = data_grow_for(empty_data, len);
191
192 d.len = len;
193 fread(d.val, len, 1, f);
194
195 return d;
196}
197
198struct data data_append_data(struct data d, void *p, int len)
199{
200 d = data_grow_for(d, len);
201 memcpy(d.val + d.len, p, len);
202 d.len += len;
203 return d;
204}
205
Milton Miller6a99b132007-07-07 01:18:51 -0500206void fixup_merge(struct fixup **fd, struct fixup **fd2, int d1_len)
David Gibson32da4752007-02-07 16:37:50 +1100207{
David Gibson32da4752007-02-07 16:37:50 +1100208 struct fixup **ff;
209 struct fixup *f, *f2;
210
David Gibson32da4752007-02-07 16:37:50 +1100211 /* Extract d2's fixups */
Milton Miller6a99b132007-07-07 01:18:51 -0500212 f2 = *fd2;
213 *fd2 = NULL;
David Gibson32da4752007-02-07 16:37:50 +1100214
215 /* Tack them onto d's list of fixups */
Milton Miller6a99b132007-07-07 01:18:51 -0500216 ff = fd;
David Gibson32da4752007-02-07 16:37:50 +1100217 while (*ff)
218 ff = &((*ff)->next);
219 *ff = f2;
220
221 /* And correct them for their new position */
222 for (f = f2; f; f = f->next)
Milton Miller6a99b132007-07-07 01:18:51 -0500223 f->offset += d1_len;
224
225
226}
227
228struct data data_merge(struct data d1, struct data d2)
229{
230 struct data d;
231
232 d = data_append_data(d1, d2.val, d2.len);
233
234 fixup_merge(&d.refs, &d2.refs, d1.len);
235 fixup_merge(&d.labels, &d2.labels, d1.len);
David Gibson32da4752007-02-07 16:37:50 +1100236
237 data_free(d2);
238
239 return d;
240}
241
David Gibsonfc14dad2005-06-08 17:18:34 +1000242struct data data_append_cell(struct data d, cell_t word)
243{
244 cell_t beword = cpu_to_be32(word);
245
246 return data_append_data(d, &beword, sizeof(beword));
247}
248
David Gibsonf040d952005-10-24 18:18:38 +1000249struct data data_append_re(struct data d, struct reserve_entry *re)
250{
251 struct reserve_entry bere;
252
253 bere.address = cpu_to_be64(re->address);
254 bere.size = cpu_to_be64(re->size);
255
256 return data_append_data(d, &bere, sizeof(bere));
257}
258
David Gibsonf0517db2005-07-15 17:14:24 +1000259struct data data_append_addr(struct data d, u64 addr)
260{
261 u64 beaddr = cpu_to_be64(addr);
262
263 return data_append_data(d, &beaddr, sizeof(beaddr));
264}
265
David Gibsonfc14dad2005-06-08 17:18:34 +1000266struct data data_append_byte(struct data d, uint8_t byte)
267{
268 return data_append_data(d, &byte, 1);
269}
270
271struct data data_append_zeroes(struct data d, int len)
272{
273 d = data_grow_for(d, len);
274
275 memset(d.val + d.len, 0, len);
276 d.len += len;
277 return d;
278}
279
280struct data data_append_align(struct data d, int align)
281{
282 int newlen = ALIGN(d.len, align);
283 return data_append_zeroes(d, newlen - d.len);
284}
285
David Gibson81f2e892005-06-16 17:04:00 +1000286struct data data_add_fixup(struct data d, char *ref)
287{
288 struct fixup *f;
289 struct data nd;
290
291 f = xmalloc(sizeof(*f));
292 f->offset = d.len;
293 f->ref = ref;
294 f->next = d.refs;
295
296 nd = d;
297 nd.refs = f;
298
299 return nd;
300}
301
Milton Miller6a99b132007-07-07 01:18:51 -0500302struct data data_add_label(struct data d, char *label)
303{
Milton Miller43a68c62007-07-07 01:18:52 -0500304 struct fixup *f, **p;
Milton Miller6a99b132007-07-07 01:18:51 -0500305 struct data nd;
306
307 f = xmalloc(sizeof(*f));
308 f->offset = d.len;
309 f->ref = label;
Milton Miller6a99b132007-07-07 01:18:51 -0500310
311 nd = d;
Milton Miller43a68c62007-07-07 01:18:52 -0500312 p = &nd.labels;
313
314 /* adding to end keeps them sorted */
315 while (*p)
316 p = &((*p)->next);
317
318 f->next = *p;
319 *p = f;
Milton Miller6a99b132007-07-07 01:18:51 -0500320
321 return nd;
322}
323
David Gibsonfc14dad2005-06-08 17:18:34 +1000324int data_is_one_string(struct data d)
325{
326 int i;
327 int len = d.len;
328
329 if (len == 0)
330 return 0;
331
332 for (i = 0; i < len-1; i++)
333 if (d.val[i] == '\0')
334 return 0;
335
336 if (d.val[len-1] != '\0')
337 return 0;
338
339 return 1;
340}