Deleted Added
full compact
dtc-parser.y (204489) dtc-parser.y (238742)
1/*
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.

--- 4 unchanged lines hidden (view full) ---

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
1/*
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.

--- 4 unchanged lines hidden (view full) ---

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
22%{
23#include <stdio.h>
24
25#include "dtc.h"
26#include "srcpos.h"
27
28YYLTYPE yylloc;
29
30extern int yylex(void);
21%{
22#include <stdio.h>
23
24#include "dtc.h"
25#include "srcpos.h"
26
27YYLTYPE yylloc;
28
29extern int yylex(void);
30extern void print_error(char const *fmt, ...);
31extern void yyerror(char const *s);
32
33extern struct boot_info *the_boot_info;
34extern int treesource_error;
35
36static unsigned long long eval_literal(const char *s, int base, int bits);
31extern void yyerror(char const *s);
32
33extern struct boot_info *the_boot_info;
34extern int treesource_error;
35
36static unsigned long long eval_literal(const char *s, int base, int bits);
37static unsigned char eval_char_literal(const char *s);
37%}
38
39%union {
40 char *propnodename;
41 char *literal;
42 char *labelref;
43 unsigned int cbase;
44 uint8_t byte;
45 struct data data;
46
38%}
39
40%union {
41 char *propnodename;
42 char *literal;
43 char *labelref;
44 unsigned int cbase;
45 uint8_t byte;
46 struct data data;
47
47 uint64_t addr;
48 cell_t cell;
48 struct {
49 struct data data;
50 int bits;
51 } array;
52
49 struct property *prop;
50 struct property *proplist;
51 struct node *node;
52 struct node *nodelist;
53 struct reserve_info *re;
53 struct property *prop;
54 struct property *proplist;
55 struct node *node;
56 struct node *nodelist;
57 struct reserve_info *re;
58 uint64_t integer;
54}
55
56%token DT_V1
57%token DT_MEMRESERVE
59}
60
61%token DT_V1
62%token DT_MEMRESERVE
63%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
64%token DT_BITS
58%token <propnodename> DT_PROPNODENAME
59%token <literal> DT_LITERAL
65%token <propnodename> DT_PROPNODENAME
66%token <literal> DT_LITERAL
67%token <literal> DT_CHAR_LITERAL
60%token <cbase> DT_BASE
61%token <byte> DT_BYTE
62%token <data> DT_STRING
63%token <labelref> DT_LABEL
64%token <labelref> DT_REF
65%token DT_INCBIN
66
67%type <data> propdata
68%type <data> propdataprefix
69%type <re> memreserve
70%type <re> memreserves
68%token <cbase> DT_BASE
69%token <byte> DT_BYTE
70%token <data> DT_STRING
71%token <labelref> DT_LABEL
72%token <labelref> DT_REF
73%token DT_INCBIN
74
75%type <data> propdata
76%type <data> propdataprefix
77%type <re> memreserve
78%type <re> memreserves
71%type <addr> addr
72%type <data> celllist
73%type <cell> cellval
79%type <array> arrayprefix
74%type <data> bytestring
75%type <prop> propdef
76%type <proplist> proplist
77
78%type <node> devicetree
79%type <node> nodedef
80%type <node> subnode
81%type <nodelist> subnodes
80%type <data> bytestring
81%type <prop> propdef
82%type <proplist> proplist
83
84%type <node> devicetree
85%type <node> nodedef
86%type <node> subnode
87%type <nodelist> subnodes
82%type <labelref> label
83
88
89%type <integer> integer_prim
90%type <integer> integer_unary
91%type <integer> integer_mul
92%type <integer> integer_add
93%type <integer> integer_shift
94%type <integer> integer_rela
95%type <integer> integer_eq
96%type <integer> integer_bitand
97%type <integer> integer_bitxor
98%type <integer> integer_bitor
99%type <integer> integer_and
100%type <integer> integer_or
101%type <integer> integer_trinary
102%type <integer> integer_expr
103
84%%
85
86sourcefile:
87 DT_V1 ';' memreserves devicetree
88 {
104%%
105
106sourcefile:
107 DT_V1 ';' memreserves devicetree
108 {
89 the_boot_info = build_boot_info($3, $4, 0);
109 the_boot_info = build_boot_info($3, $4,
110 guess_boot_cpuid($4));
90 }
91 ;
92
93memreserves:
94 /* empty */
95 {
96 $$ = NULL;
97 }
98 | memreserve memreserves
99 {
100 $$ = chain_reserve_entry($1, $2);
101 }
102 ;
103
104memreserve:
111 }
112 ;
113
114memreserves:
115 /* empty */
116 {
117 $$ = NULL;
118 }
119 | memreserve memreserves
120 {
121 $$ = chain_reserve_entry($1, $2);
122 }
123 ;
124
125memreserve:
105 label DT_MEMRESERVE addr addr ';'
126 DT_MEMRESERVE integer_prim integer_prim ';'
106 {
127 {
107 $$ = build_reserve_entry($3, $4, $1);
128 $$ = build_reserve_entry($2, $3);
108 }
129 }
109 ;
110
111addr:
112 DT_LITERAL
130 | DT_LABEL memreserve
113 {
131 {
114 $$ = eval_literal($1, 0, 64);
132 add_label(&$2->labels, $1);
133 $$ = $2;
115 }
134 }
116 ;
135 ;
117
118devicetree:
119 '/' nodedef
120 {
136
137devicetree:
138 '/' nodedef
139 {
121 $$ = name_node($2, "", NULL);
140 $$ = name_node($2, "");
122 }
141 }
142 | devicetree '/' nodedef
143 {
144 $$ = merge_nodes($1, $3);
145 }
146 | devicetree DT_REF nodedef
147 {
148 struct node *target = get_node_by_ref($1, $2);
149
150 if (target)
151 merge_nodes(target, $3);
152 else
153 print_error("label or path, '%s', not found", $2);
154 $$ = $1;
155 }
123 ;
124
125nodedef:
126 '{' proplist subnodes '}' ';'
127 {
128 $$ = build_node($2, $3);
129 }
130 ;

--- 5 unchanged lines hidden (view full) ---

136 }
137 | proplist propdef
138 {
139 $$ = chain_property($2, $1);
140 }
141 ;
142
143propdef:
156 ;
157
158nodedef:
159 '{' proplist subnodes '}' ';'
160 {
161 $$ = build_node($2, $3);
162 }
163 ;

--- 5 unchanged lines hidden (view full) ---

169 }
170 | proplist propdef
171 {
172 $$ = chain_property($2, $1);
173 }
174 ;
175
176propdef:
144 label DT_PROPNODENAME '=' propdata ';'
177 DT_PROPNODENAME '=' propdata ';'
145 {
178 {
146 $$ = build_property($2, $4, $1);
179 $$ = build_property($1, $3);
147 }
180 }
148 | label DT_PROPNODENAME ';'
181 | DT_PROPNODENAME ';'
149 {
182 {
150 $$ = build_property($2, empty_data, $1);
183 $$ = build_property($1, empty_data);
151 }
184 }
185 | DT_LABEL propdef
186 {
187 add_label(&$2->labels, $1);
188 $$ = $2;
189 }
152 ;
153
154propdata:
155 propdataprefix DT_STRING
156 {
157 $$ = data_merge($1, $2);
158 }
190 ;
191
192propdata:
193 propdataprefix DT_STRING
194 {
195 $$ = data_merge($1, $2);
196 }
159 | propdataprefix '<' celllist '>'
197 | propdataprefix arrayprefix '>'
160 {
198 {
161 $$ = data_merge($1, $3);
199 $$ = data_merge($1, $2.data);
162 }
163 | propdataprefix '[' bytestring ']'
164 {
165 $$ = data_merge($1, $3);
166 }
167 | propdataprefix DT_REF
168 {
169 $$ = data_add_marker($1, REF_PATH, $2);
170 }
200 }
201 | propdataprefix '[' bytestring ']'
202 {
203 $$ = data_merge($1, $3);
204 }
205 | propdataprefix DT_REF
206 {
207 $$ = data_add_marker($1, REF_PATH, $2);
208 }
171 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
209 | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
172 {
210 {
173 struct search_path path = { srcpos_file->dir, NULL, NULL };
174 struct dtc_file *file = dtc_open_file($4.val, &path);
175 struct data d = empty_data;
211 FILE *f = srcfile_relative_open($4.val, NULL);
212 struct data d;
176
177 if ($6 != 0)
213
214 if ($6 != 0)
178 if (fseek(file->file, $6, SEEK_SET) != 0)
179 srcpos_error(&yylloc,
180 "Couldn't seek to offset %llu in \"%s\": %s",
215 if (fseek(f, $6, SEEK_SET) != 0)
216 print_error("Couldn't seek to offset %llu in \"%s\": %s",
181 (unsigned long long)$6,
182 $4.val,
183 strerror(errno));
184
217 (unsigned long long)$6,
218 $4.val,
219 strerror(errno));
220
185 d = data_copy_file(file->file, $8);
221 d = data_copy_file(f, $8);
186
187 $$ = data_merge($1, d);
222
223 $$ = data_merge($1, d);
188 dtc_close_file(file);
224 fclose(f);
189 }
190 | propdataprefix DT_INCBIN '(' DT_STRING ')'
191 {
225 }
226 | propdataprefix DT_INCBIN '(' DT_STRING ')'
227 {
192 struct search_path path = { srcpos_file->dir, NULL, NULL };
193 struct dtc_file *file = dtc_open_file($4.val, &path);
228 FILE *f = srcfile_relative_open($4.val, NULL);
194 struct data d = empty_data;
195
229 struct data d = empty_data;
230
196 d = data_copy_file(file->file, -1);
231 d = data_copy_file(f, -1);
197
198 $$ = data_merge($1, d);
232
233 $$ = data_merge($1, d);
199 dtc_close_file(file);
234 fclose(f);
200 }
201 | propdata DT_LABEL
202 {
203 $$ = data_add_marker($1, LABEL, $2);
204 }
205 ;
206
207propdataprefix:

--- 6 unchanged lines hidden (view full) ---

214 $$ = $1;
215 }
216 | propdataprefix DT_LABEL
217 {
218 $$ = data_add_marker($1, LABEL, $2);
219 }
220 ;
221
235 }
236 | propdata DT_LABEL
237 {
238 $$ = data_add_marker($1, LABEL, $2);
239 }
240 ;
241
242propdataprefix:

--- 6 unchanged lines hidden (view full) ---

249 $$ = $1;
250 }
251 | propdataprefix DT_LABEL
252 {
253 $$ = data_add_marker($1, LABEL, $2);
254 }
255 ;
256
222celllist:
223 /* empty */
257arrayprefix:
258 DT_BITS DT_LITERAL '<'
224 {
259 {
225 $$ = empty_data;
260 $$.data = empty_data;
261 $$.bits = eval_literal($2, 0, 7);
262
263 if (($$.bits != 8) &&
264 ($$.bits != 16) &&
265 ($$.bits != 32) &&
266 ($$.bits != 64))
267 {
268 print_error("Only 8, 16, 32 and 64-bit elements"
269 " are currently supported");
270 $$.bits = 32;
271 }
226 }
272 }
227 | celllist cellval
273 | '<'
228 {
274 {
229 $$ = data_append_cell($1, $2);
275 $$.data = empty_data;
276 $$.bits = 32;
230 }
277 }
231 | celllist DT_REF
278 | arrayprefix integer_prim
232 {
279 {
233 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
234 $2), -1);
280 if ($1.bits < 64) {
281 uint64_t mask = (1ULL << $1.bits) - 1;
282 /*
283 * Bits above mask must either be all zero
284 * (positive within range of mask) or all one
285 * (negative and sign-extended). The second
286 * condition is true if when we set all bits
287 * within the mask to one (i.e. | in the
288 * mask), all bits are one.
289 */
290 if (($2 > mask) && (($2 | mask) != -1ULL))
291 print_error(
292 "integer value out of range "
293 "%016lx (%d bits)", $1.bits);
294 }
295
296 $$.data = data_append_integer($1.data, $2, $1.bits);
235 }
297 }
236 | celllist DT_LABEL
298 | arrayprefix DT_REF
237 {
299 {
238 $$ = data_add_marker($1, LABEL, $2);
300 uint64_t val = ~0ULL >> (64 - $1.bits);
301
302 if ($1.bits == 32)
303 $1.data = data_add_marker($1.data,
304 REF_PHANDLE,
305 $2);
306 else
307 print_error("References are only allowed in "
308 "arrays with 32-bit elements.");
309
310 $$.data = data_append_integer($1.data, val, $1.bits);
239 }
311 }
312 | arrayprefix DT_LABEL
313 {
314 $$.data = data_add_marker($1.data, LABEL, $2);
315 }
240 ;
241
316 ;
317
242cellval:
318integer_prim:
243 DT_LITERAL
244 {
319 DT_LITERAL
320 {
245 $$ = eval_literal($1, 0, 32);
321 $$ = eval_literal($1, 0, 64);
246 }
322 }
323 | DT_CHAR_LITERAL
324 {
325 $$ = eval_char_literal($1);
326 }
327 | '(' integer_expr ')'
328 {
329 $$ = $2;
330 }
247 ;
248
331 ;
332
333integer_expr:
334 integer_trinary
335 ;
336
337integer_trinary:
338 integer_or
339 | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
340 ;
341
342integer_or:
343 integer_and
344 | integer_or DT_OR integer_and { $$ = $1 || $3; }
345 ;
346
347integer_and:
348 integer_bitor
349 | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
350 ;
351
352integer_bitor:
353 integer_bitxor
354 | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
355 ;
356
357integer_bitxor:
358 integer_bitand
359 | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
360 ;
361
362integer_bitand:
363 integer_eq
364 | integer_bitand '&' integer_eq { $$ = $1 & $3; }
365 ;
366
367integer_eq:
368 integer_rela
369 | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
370 | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
371 ;
372
373integer_rela:
374 integer_shift
375 | integer_rela '<' integer_shift { $$ = $1 < $3; }
376 | integer_rela '>' integer_shift { $$ = $1 > $3; }
377 | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
378 | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
379 ;
380
381integer_shift:
382 integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
383 | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
384 | integer_add
385 ;
386
387integer_add:
388 integer_add '+' integer_mul { $$ = $1 + $3; }
389 | integer_add '-' integer_mul { $$ = $1 - $3; }
390 | integer_mul
391 ;
392
393integer_mul:
394 integer_mul '*' integer_unary { $$ = $1 * $3; }
395 | integer_mul '/' integer_unary { $$ = $1 / $3; }
396 | integer_mul '%' integer_unary { $$ = $1 % $3; }
397 | integer_unary
398 ;
399
400integer_unary:
401 integer_prim
402 | '-' integer_unary { $$ = -$2; }
403 | '~' integer_unary { $$ = ~$2; }
404 | '!' integer_unary { $$ = !$2; }
405 ;
406
249bytestring:
250 /* empty */
251 {
252 $$ = empty_data;
253 }
254 | bytestring DT_BYTE
255 {
256 $$ = data_append_byte($1, $2);

--- 4 unchanged lines hidden (view full) ---

261 }
262 ;
263
264subnodes:
265 /* empty */
266 {
267 $$ = NULL;
268 }
407bytestring:
408 /* empty */
409 {
410 $$ = empty_data;
411 }
412 | bytestring DT_BYTE
413 {
414 $$ = data_append_byte($1, $2);

--- 4 unchanged lines hidden (view full) ---

419 }
420 ;
421
422subnodes:
423 /* empty */
424 {
425 $$ = NULL;
426 }
269 | subnode subnodes
427 | subnode subnodes
270 {
271 $$ = chain_node($1, $2);
272 }
273 | subnode propdef
274 {
428 {
429 $$ = chain_node($1, $2);
430 }
431 | subnode propdef
432 {
275 yyerror("syntax error: properties must precede subnodes");
433 print_error("syntax error: properties must precede subnodes");
276 YYERROR;
277 }
278 ;
279
280subnode:
434 YYERROR;
435 }
436 ;
437
438subnode:
281 label DT_PROPNODENAME nodedef
439 DT_PROPNODENAME nodedef
282 {
440 {
283 $$ = name_node($3, $2, $1);
441 $$ = name_node($2, $1);
284 }
442 }
285 ;
286
287label:
288 /* empty */
443 | DT_LABEL subnode
289 {
444 {
290 $$ = NULL;
445 add_label(&$2->labels, $1);
446 $$ = $2;
291 }
447 }
292 | DT_LABEL
293 {
294 $$ = $1;
295 }
296 ;
297
298%%
299
448 ;
449
450%%
451
300void yyerror(char const *s)
452void print_error(char const *fmt, ...)
301{
453{
302 srcpos_error(&yylloc, "%s", s);
454 va_list va;
455
456 va_start(va, fmt);
457 srcpos_verror(&yylloc, fmt, va);
458 va_end(va);
459
303 treesource_error = 1;
304}
305
460 treesource_error = 1;
461}
462
463void yyerror(char const *s) {
464 print_error("%s", s);
465}
466
306static unsigned long long eval_literal(const char *s, int base, int bits)
307{
308 unsigned long long val;
309 char *e;
310
311 errno = 0;
312 val = strtoull(s, &e, base);
467static unsigned long long eval_literal(const char *s, int base, int bits)
468{
469 unsigned long long val;
470 char *e;
471
472 errno = 0;
473 val = strtoull(s, &e, base);
313 if (*e)
314 yyerror("bad characters in literal");
315 else if ((errno == ERANGE)
474 if (*e) {
475 size_t uls = strspn(e, "UL");
476 if (e[uls])
477 print_error("bad characters in literal");
478 }
479 if ((errno == ERANGE)
316 || ((bits < 64) && (val >= (1ULL << bits))))
480 || ((bits < 64) && (val >= (1ULL << bits))))
317 yyerror("literal out of range");
481 print_error("literal out of range");
318 else if (errno != 0)
482 else if (errno != 0)
319 yyerror("bad literal");
483 print_error("bad literal");
320 return val;
321}
484 return val;
485}
486
487static unsigned char eval_char_literal(const char *s)
488{
489 int i = 1;
490 char c = s[0];
491
492 if (c == '\0')
493 {
494 print_error("empty character literal");
495 return 0;
496 }
497
498 /*
499 * If the first character in the character literal is a \ then process
500 * the remaining characters as an escape encoding. If the first
501 * character is neither an escape or a terminator it should be the only
502 * character in the literal and will be returned.
503 */
504 if (c == '\\')
505 c = get_escape_char(s, &i);
506
507 if (s[i] != '\0')
508 print_error("malformed character literal");
509
510 return c;
511}