Merge branch 'next/timer' of git://git.linaro.org/people/arnd/arm-soc
[linux-2.6-block.git] / scripts / dtc / dtc-parser.y
CommitLineData
a4da2e3e
DG
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.
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
a4da2e3e 21%{
ed95d745
DG
22#include <stdio.h>
23
a4da2e3e
DG
24#include "dtc.h"
25#include "srcpos.h"
26
658f29a5
JB
27YYLTYPE yylloc;
28
ed95d745 29extern int yylex(void);
658f29a5
JB
30extern void print_error(char const *fmt, ...);
31extern void yyerror(char const *s);
a4da2e3e
DG
32
33extern struct boot_info *the_boot_info;
ed95d745 34extern int treesource_error;
a4da2e3e 35
ed95d745 36static unsigned long long eval_literal(const char *s, int base, int bits);
a4da2e3e
DG
37%}
38
39%union {
40 char *propnodename;
41 char *literal;
42 char *labelref;
43 unsigned int cbase;
ed95d745 44 uint8_t byte;
a4da2e3e
DG
45 struct data data;
46
ed95d745 47 uint64_t addr;
a4da2e3e
DG
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;
54}
55
56%token DT_V1
57%token DT_MEMRESERVE
58%token <propnodename> DT_PROPNODENAME
59%token <literal> DT_LITERAL
a4da2e3e
DG
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
ed95d745 65%token DT_INCBIN
a4da2e3e
DG
66
67%type <data> propdata
68%type <data> propdataprefix
69%type <re> memreserve
70%type <re> memreserves
a4da2e3e
DG
71%type <addr> addr
72%type <data> celllist
a4da2e3e
DG
73%type <cell> cellval
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
a4da2e3e
DG
82
83%%
84
85sourcefile:
86 DT_V1 ';' memreserves devicetree
87 {
658f29a5
JB
88 the_boot_info = build_boot_info($3, $4,
89 guess_boot_cpuid($4));
a4da2e3e
DG
90 }
91 ;
92
93memreserves:
94 /* empty */
95 {
96 $$ = NULL;
97 }
98 | memreserve memreserves
99 {
100 $$ = chain_reserve_entry($1, $2);
101 }
102 ;
103
104memreserve:
658f29a5 105 DT_MEMRESERVE addr addr ';'
a4da2e3e 106 {
658f29a5 107 $$ = build_reserve_entry($2, $3);
a4da2e3e 108 }
658f29a5 109 | DT_LABEL memreserve
a4da2e3e 110 {
658f29a5
JB
111 add_label(&$2->labels, $1);
112 $$ = $2;
a4da2e3e
DG
113 }
114 ;
115
116addr:
117 DT_LITERAL
118 {
119 $$ = eval_literal($1, 0, 64);
120 }
a4da2e3e
DG
121 ;
122
123devicetree:
124 '/' nodedef
125 {
658f29a5
JB
126 $$ = name_node($2, "");
127 }
128 | devicetree '/' nodedef
129 {
130 $$ = merge_nodes($1, $3);
131 }
132 | devicetree DT_REF nodedef
133 {
134 struct node *target = get_node_by_ref($1, $2);
135
136 if (target)
137 merge_nodes(target, $3);
138 else
139 print_error("label or path, '%s', not found", $2);
140 $$ = $1;
a4da2e3e
DG
141 }
142 ;
143
144nodedef:
145 '{' proplist subnodes '}' ';'
146 {
147 $$ = build_node($2, $3);
148 }
149 ;
150
151proplist:
152 /* empty */
153 {
154 $$ = NULL;
155 }
156 | proplist propdef
157 {
158 $$ = chain_property($2, $1);
159 }
160 ;
161
162propdef:
658f29a5
JB
163 DT_PROPNODENAME '=' propdata ';'
164 {
165 $$ = build_property($1, $3);
166 }
167 | DT_PROPNODENAME ';'
a4da2e3e 168 {
658f29a5 169 $$ = build_property($1, empty_data);
a4da2e3e 170 }
658f29a5 171 | DT_LABEL propdef
a4da2e3e 172 {
658f29a5
JB
173 add_label(&$2->labels, $1);
174 $$ = $2;
a4da2e3e
DG
175 }
176 ;
177
178propdata:
179 propdataprefix DT_STRING
180 {
181 $$ = data_merge($1, $2);
182 }
183 | propdataprefix '<' celllist '>'
184 {
185 $$ = data_merge($1, $3);
186 }
187 | propdataprefix '[' bytestring ']'
188 {
189 $$ = data_merge($1, $3);
190 }
191 | propdataprefix DT_REF
192 {
193 $$ = data_add_marker($1, REF_PATH, $2);
194 }
ed95d745
DG
195 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
196 {
658f29a5
JB
197 FILE *f = srcfile_relative_open($4.val, NULL);
198 struct data d;
ed95d745
DG
199
200 if ($6 != 0)
658f29a5
JB
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));
ed95d745 206
658f29a5 207 d = data_copy_file(f, $8);
ed95d745
DG
208
209 $$ = data_merge($1, d);
658f29a5 210 fclose(f);
ed95d745
DG
211 }
212 | propdataprefix DT_INCBIN '(' DT_STRING ')'
213 {
658f29a5 214 FILE *f = srcfile_relative_open($4.val, NULL);
ed95d745
DG
215 struct data d = empty_data;
216
658f29a5 217 d = data_copy_file(f, -1);
ed95d745
DG
218
219 $$ = data_merge($1, d);
658f29a5 220 fclose(f);
ed95d745 221 }
a4da2e3e
DG
222 | propdata DT_LABEL
223 {
224 $$ = data_add_marker($1, LABEL, $2);
225 }
226 ;
227
228propdataprefix:
229 /* empty */
230 {
231 $$ = empty_data;
232 }
233 | propdata ','
234 {
235 $$ = $1;
236 }
237 | propdataprefix DT_LABEL
238 {
239 $$ = data_add_marker($1, LABEL, $2);
240 }
241 ;
242
243celllist:
244 /* empty */
245 {
246 $$ = empty_data;
247 }
248 | celllist cellval
249 {
250 $$ = data_append_cell($1, $2);
251 }
252 | celllist DT_REF
253 {
254 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
255 $2), -1);
256 }
257 | celllist DT_LABEL
258 {
259 $$ = data_add_marker($1, LABEL, $2);
260 }
261 ;
262
a4da2e3e
DG
263cellval:
264 DT_LITERAL
265 {
266 $$ = eval_literal($1, 0, 32);
267 }
a4da2e3e
DG
268 ;
269
270bytestring:
271 /* empty */
272 {
273 $$ = empty_data;
274 }
275 | bytestring DT_BYTE
276 {
277 $$ = data_append_byte($1, $2);
278 }
279 | bytestring DT_LABEL
280 {
281 $$ = data_add_marker($1, LABEL, $2);
282 }
283 ;
284
285subnodes:
286 /* empty */
287 {
288 $$ = NULL;
289 }
658f29a5 290 | subnode subnodes
a4da2e3e
DG
291 {
292 $$ = chain_node($1, $2);
293 }
294 | subnode propdef
295 {
658f29a5 296 print_error("syntax error: properties must precede subnodes");
a4da2e3e
DG
297 YYERROR;
298 }
299 ;
300
301subnode:
658f29a5 302 DT_PROPNODENAME nodedef
a4da2e3e 303 {
658f29a5 304 $$ = name_node($2, $1);
a4da2e3e 305 }
658f29a5 306 | DT_LABEL subnode
a4da2e3e 307 {
658f29a5
JB
308 add_label(&$2->labels, $1);
309 $$ = $2;
a4da2e3e
DG
310 }
311 ;
312
313%%
314
658f29a5 315void print_error(char const *fmt, ...)
a4da2e3e 316{
ed95d745 317 va_list va;
a4da2e3e 318
658f29a5
JB
319 va_start(va, fmt);
320 srcpos_verror(&yylloc, fmt, va);
321 va_end(va);
ed95d745
DG
322
323 treesource_error = 1;
ed95d745
DG
324}
325
658f29a5
JB
326void yyerror(char const *s) {
327 print_error("%s", s);
a4da2e3e
DG
328}
329
ed95d745 330static unsigned long long eval_literal(const char *s, int base, int bits)
a4da2e3e
DG
331{
332 unsigned long long val;
333 char *e;
334
335 errno = 0;
336 val = strtoull(s, &e, base);
337 if (*e)
658f29a5 338 print_error("bad characters in literal");
a4da2e3e
DG
339 else if ((errno == ERANGE)
340 || ((bits < 64) && (val >= (1ULL << bits))))
658f29a5 341 print_error("literal out of range");
a4da2e3e 342 else if (errno != 0)
658f29a5 343 print_error("bad literal");
a4da2e3e
DG
344 return val;
345}