blob: 5d7db175a16deacb76290c756ad455f6cc813568 [file] [log] [blame]
David Gibsonfc14dad2005-06-08 17:18:34 +10001/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * 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.
14 *
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
19 */
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{
David Gibson81f2e892005-06-16 17:04:00 +100032 struct fixup *f;
33
34 f = d.refs;
35 while (f) {
36 struct fixup *nf;
37
38 nf = f->next;
39 fixup_free(f);
40 f = nf;
41 }
42
David Gibsonfc14dad2005-06-08 17:18:34 +100043 assert(!d.val || d.asize);
44
45 if (d.val)
46 free(d.val);
47}
48
49struct data data_grow_for(struct data d, int xlen)
50{
51 struct data nd;
52 int newsize;
53
54 /* we must start with an allocated datum */
55 assert(!d.val || d.asize);
56
57 if (xlen == 0)
58 return d;
59
60 newsize = xlen;
61
62 while ((d.len + xlen) > newsize)
63 newsize *= 2;
64
65 nd.asize = newsize;
66 nd.val = xrealloc(d.val, newsize);
67 nd.len = d.len;
David Gibson81f2e892005-06-16 17:04:00 +100068 nd.refs = d.refs;
David Gibsonfc14dad2005-06-08 17:18:34 +100069
70 assert(nd.asize >= (d.len + xlen));
71
72 return nd;
73}
74
75struct data data_copy_mem(char *mem, int len)
76{
77 struct data d;
78
79 d = data_grow_for(empty_data, len);
80
81 d.len = len;
82 memcpy(d.val, mem, len);
83
84 return d;
85}
86
David Gibson230f2532005-08-29 12:48:02 +100087static char get_oct_char(char *s, int *i)
David Gibsonfc14dad2005-06-08 17:18:34 +100088{
89 char x[4];
90 char *endx;
91 long val;
92
93 x[3] = '\0';
94 x[0] = s[(*i)];
95 if (x[0]) {
96 x[1] = s[(*i)+1];
97 if (x[1])
98 x[2] = s[(*i)+2];
99 }
100
101 val = strtol(x, &endx, 8);
102 if ((endx - x) == 0)
103 fprintf(stderr, "Empty \\nnn escape\n");
104
105 (*i) += endx - x;
106 return val;
107}
108
David Gibson230f2532005-08-29 12:48:02 +1000109static char get_hex_char(char *s, int *i)
David Gibsonfc14dad2005-06-08 17:18:34 +1000110{
111 char x[3];
112 char *endx;
113 long val;
114
115 x[2] = '\0';
116 x[0] = s[(*i)];
117 if (x[0])
118 x[1] = s[(*i)+1];
119
120 val = strtol(x, &endx, 16);
121 if ((endx - x) == 0)
122 fprintf(stderr, "Empty \\x escape\n");
123
124 (*i) += endx - x;
125 return val;
126}
127
128struct data data_copy_escape_string(char *s, int len)
129{
130 int i = 0;
131 struct data d;
132 char *q;
133
134 d = data_grow_for(empty_data, strlen(s)+1);
135
136 q = d.val;
137 while (i < len) {
138 char c = s[i++];
139
140 if (c != '\\') {
141 q[d.len++] = c;
142 continue;
143 }
144
145 c = s[i++];
146 assert(c);
147 switch (c) {
148 case 't':
149 q[d.len++] = '\t';
150 break;
151 case 'n':
152 q[d.len++] = '\n';
153 break;
154 case 'r':
155 q[d.len++] = '\r';
156 break;
David Gibsonb4ac0492005-10-17 10:27:45 +1000157 case '0':
158 case '1':
159 case '2':
160 case '3':
161 case '4':
162 case '5':
163 case '6':
164 case '7':
David Gibsonfc14dad2005-06-08 17:18:34 +1000165 i--; /* need to re-read the first digit as
166 * part of the octal value */
167 q[d.len++] = get_oct_char(s, &i);
168 break;
169 case 'x':
170 q[d.len++] = get_hex_char(s, &i);
171 break;
172 default:
173 q[d.len++] = c;
174 }
175 }
176
177 q[d.len++] = '\0';
178 return d;
179}
180
181struct data data_copy_file(FILE *f, size_t len)
182{
183 struct data d;
184
185 d = data_grow_for(empty_data, len);
186
187 d.len = len;
188 fread(d.val, len, 1, f);
189
190 return d;
191}
192
193struct data data_append_data(struct data d, void *p, int len)
194{
195 d = data_grow_for(d, len);
196 memcpy(d.val + d.len, p, len);
197 d.len += len;
198 return d;
199}
200
David Gibson32da4752007-02-07 16:37:50 +1100201struct data data_merge(struct data d1, struct data d2)
202{
203 struct data d;
204 struct fixup **ff;
205 struct fixup *f, *f2;
206
207 d = data_append_data(d1, d2.val, d2.len);
208
209 /* Extract d2's fixups */
210 f2 = d2.refs;
211 d2.refs = NULL;
212
213 /* Tack them onto d's list of fixups */
214 ff = &d.refs;
215 while (*ff)
216 ff = &((*ff)->next);
217 *ff = f2;
218
219 /* And correct them for their new position */
220 for (f = f2; f; f = f->next)
221 f->offset += d1.len;
222
223 data_free(d2);
224
225 return d;
226}
227
David Gibsonfc14dad2005-06-08 17:18:34 +1000228struct data data_append_cell(struct data d, cell_t word)
229{
230 cell_t beword = cpu_to_be32(word);
231
232 return data_append_data(d, &beword, sizeof(beword));
233}
234
David Gibsonf040d952005-10-24 18:18:38 +1000235struct data data_append_re(struct data d, struct reserve_entry *re)
236{
237 struct reserve_entry bere;
238
239 bere.address = cpu_to_be64(re->address);
240 bere.size = cpu_to_be64(re->size);
241
242 return data_append_data(d, &bere, sizeof(bere));
243}
244
David Gibsonf0517db2005-07-15 17:14:24 +1000245struct data data_append_addr(struct data d, u64 addr)
246{
247 u64 beaddr = cpu_to_be64(addr);
248
249 return data_append_data(d, &beaddr, sizeof(beaddr));
250}
251
David Gibsonfc14dad2005-06-08 17:18:34 +1000252struct data data_append_byte(struct data d, uint8_t byte)
253{
254 return data_append_data(d, &byte, 1);
255}
256
257struct data data_append_zeroes(struct data d, int len)
258{
259 d = data_grow_for(d, len);
260
261 memset(d.val + d.len, 0, len);
262 d.len += len;
263 return d;
264}
265
266struct data data_append_align(struct data d, int align)
267{
268 int newlen = ALIGN(d.len, align);
269 return data_append_zeroes(d, newlen - d.len);
270}
271
David Gibson81f2e892005-06-16 17:04:00 +1000272struct data data_add_fixup(struct data d, char *ref)
273{
274 struct fixup *f;
275 struct data nd;
276
277 f = xmalloc(sizeof(*f));
278 f->offset = d.len;
279 f->ref = ref;
280 f->next = d.refs;
281
282 nd = d;
283 nd.refs = f;
284
285 return nd;
286}
287
David Gibsonfc14dad2005-06-08 17:18:34 +1000288int data_is_one_string(struct data d)
289{
290 int i;
291 int len = d.len;
292
293 if (len == 0)
294 return 0;
295
296 for (i = 0; i < len-1; i++)
297 if (d.val[i] == '\0')
298 return 0;
299
300 if (d.val[len-1] != '\0')
301 return 0;
302
303 return 1;
304}