Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / scripts / dtc / dtc-parser.y
blob5e84a67fc1d2bf110d0d33040d9d3178f5bbddb6
1 /*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
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.
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.
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
22 #include <stdio.h>
24 #include "dtc.h"
25 #include "srcpos.h"
27 YYLTYPE yylloc;
29 extern int yylex(void);
30 extern void print_error(char const *fmt, ...);
31 extern void yyerror(char const *s);
33 extern struct boot_info *the_boot_info;
34 extern int treesource_error;
36 static unsigned long long eval_literal(const char *s, int base, int bits);
39 %union {
40 char *propnodename;
41 char *literal;
42 char *labelref;
43 unsigned int cbase;
44 uint8_t byte;
45 struct data data;
47 uint64_t addr;
48 cell_t cell;
49 struct property *prop;
50 struct property *proplist;
51 struct node *node;
52 struct node *nodelist;
53 struct reserve_info *re;
56 %token DT_V1
57 %token DT_MEMRESERVE
58 %token <propnodename> DT_PROPNODENAME
59 %token <literal> DT_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
67 %type <data> propdata
68 %type <data> propdataprefix
69 %type <re> memreserve
70 %type <re> memreserves
71 %type <addr> addr
72 %type <data> celllist
73 %type <cell> cellval
74 %type <data> bytestring
75 %type <prop> propdef
76 %type <proplist> proplist
78 %type <node> devicetree
79 %type <node> nodedef
80 %type <node> subnode
81 %type <nodelist> subnodes
85 sourcefile:
86 DT_V1 ';' memreserves devicetree
88 the_boot_info = build_boot_info($3, $4,
89 guess_boot_cpuid($4));
93 memreserves:
94 /* empty */
96 $$ = NULL;
98 | memreserve memreserves
100 $$ = chain_reserve_entry($1, $2);
104 memreserve:
105 DT_MEMRESERVE addr addr ';'
107 $$ = build_reserve_entry($2, $3);
109 | DT_LABEL memreserve
111 add_label(&$2->labels, $1);
112 $$ = $2;
116 addr:
117 DT_LITERAL
119 $$ = eval_literal($1, 0, 64);
123 devicetree:
124 '/' nodedef
126 $$ = name_node($2, "");
128 | devicetree '/' nodedef
130 $$ = merge_nodes($1, $3);
132 | devicetree DT_REF nodedef
134 struct node *target = get_node_by_ref($1, $2);
136 if (target)
137 merge_nodes(target, $3);
138 else
139 print_error("label or path, '%s', not found", $2);
140 $$ = $1;
144 nodedef:
145 '{' proplist subnodes '}' ';'
147 $$ = build_node($2, $3);
151 proplist:
152 /* empty */
154 $$ = NULL;
156 | proplist propdef
158 $$ = chain_property($2, $1);
162 propdef:
163 DT_PROPNODENAME '=' propdata ';'
165 $$ = build_property($1, $3);
167 | DT_PROPNODENAME ';'
169 $$ = build_property($1, empty_data);
171 | DT_LABEL propdef
173 add_label(&$2->labels, $1);
174 $$ = $2;
178 propdata:
179 propdataprefix DT_STRING
181 $$ = data_merge($1, $2);
183 | propdataprefix '<' celllist '>'
185 $$ = data_merge($1, $3);
187 | propdataprefix '[' bytestring ']'
189 $$ = data_merge($1, $3);
191 | propdataprefix DT_REF
193 $$ = data_add_marker($1, REF_PATH, $2);
195 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
197 FILE *f = srcfile_relative_open($4.val, NULL);
198 struct data d;
200 if ($6 != 0)
201 if (fseek(f, $6, SEEK_SET) != 0)
202 print_error("Couldn't seek to offset %llu in \"%s\": %s",
203 (unsigned long long)$6,
204 $4.val,
205 strerror(errno));
207 d = data_copy_file(f, $8);
209 $$ = data_merge($1, d);
210 fclose(f);
212 | propdataprefix DT_INCBIN '(' DT_STRING ')'
214 FILE *f = srcfile_relative_open($4.val, NULL);
215 struct data d = empty_data;
217 d = data_copy_file(f, -1);
219 $$ = data_merge($1, d);
220 fclose(f);
222 | propdata DT_LABEL
224 $$ = data_add_marker($1, LABEL, $2);
228 propdataprefix:
229 /* empty */
231 $$ = empty_data;
233 | propdata ','
235 $$ = $1;
237 | propdataprefix DT_LABEL
239 $$ = data_add_marker($1, LABEL, $2);
243 celllist:
244 /* empty */
246 $$ = empty_data;
248 | celllist cellval
250 $$ = data_append_cell($1, $2);
252 | celllist DT_REF
254 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
255 $2), -1);
257 | celllist DT_LABEL
259 $$ = data_add_marker($1, LABEL, $2);
263 cellval:
264 DT_LITERAL
266 $$ = eval_literal($1, 0, 32);
270 bytestring:
271 /* empty */
273 $$ = empty_data;
275 | bytestring DT_BYTE
277 $$ = data_append_byte($1, $2);
279 | bytestring DT_LABEL
281 $$ = data_add_marker($1, LABEL, $2);
285 subnodes:
286 /* empty */
288 $$ = NULL;
290 | subnode subnodes
292 $$ = chain_node($1, $2);
294 | subnode propdef
296 print_error("syntax error: properties must precede subnodes");
297 YYERROR;
301 subnode:
302 DT_PROPNODENAME nodedef
304 $$ = name_node($2, $1);
306 | DT_LABEL subnode
308 add_label(&$2->labels, $1);
309 $$ = $2;
315 void print_error(char const *fmt, ...)
317 va_list va;
319 va_start(va, fmt);
320 srcpos_verror(&yylloc, fmt, va);
321 va_end(va);
323 treesource_error = 1;
326 void yyerror(char const *s) {
327 print_error("%s", s);
330 static unsigned long long eval_literal(const char *s, int base, int bits)
332 unsigned long long val;
333 char *e;
335 errno = 0;
336 val = strtoull(s, &e, base);
337 if (*e)
338 print_error("bad characters in literal");
339 else if ((errno == ERANGE)
340 || ((bits < 64) && (val >= (1ULL << bits))))
341 print_error("literal out of range");
342 else if (errno != 0)
343 print_error("bad literal");
344 return val;