Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
[sfrench/cifs-2.6.git] / scripts / dtc / dtc-parser.y
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 %{
21 #include <stdio.h>
22
23 #include "dtc.h"
24 #include "srcpos.h"
25
26 extern int yylex(void);
27 extern void yyerror(char const *s);
28 #define ERROR(loc, ...) \
29         do { \
30                 srcpos_error((loc), "Error", __VA_ARGS__); \
31                 treesource_error = true; \
32         } while (0)
33
34 extern struct boot_info *the_boot_info;
35 extern bool treesource_error;
36 %}
37
38 %union {
39         char *propnodename;
40         char *labelref;
41         uint8_t byte;
42         struct data data;
43
44         struct {
45                 struct data     data;
46                 int             bits;
47         } array;
48
49         struct property *prop;
50         struct property *proplist;
51         struct node *node;
52         struct node *nodelist;
53         struct reserve_info *re;
54         uint64_t integer;
55 }
56
57 %token DT_V1
58 %token DT_MEMRESERVE
59 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
60 %token DT_BITS
61 %token DT_DEL_PROP
62 %token DT_DEL_NODE
63 %token <propnodename> DT_PROPNODENAME
64 %token <integer> DT_LITERAL
65 %token <integer> DT_CHAR_LITERAL
66 %token <byte> DT_BYTE
67 %token <data> DT_STRING
68 %token <labelref> DT_LABEL
69 %token <labelref> DT_REF
70 %token DT_INCBIN
71
72 %type <data> propdata
73 %type <data> propdataprefix
74 %type <re> memreserve
75 %type <re> memreserves
76 %type <array> arrayprefix
77 %type <data> bytestring
78 %type <prop> propdef
79 %type <proplist> proplist
80
81 %type <node> devicetree
82 %type <node> nodedef
83 %type <node> subnode
84 %type <nodelist> subnodes
85
86 %type <integer> integer_prim
87 %type <integer> integer_unary
88 %type <integer> integer_mul
89 %type <integer> integer_add
90 %type <integer> integer_shift
91 %type <integer> integer_rela
92 %type <integer> integer_eq
93 %type <integer> integer_bitand
94 %type <integer> integer_bitxor
95 %type <integer> integer_bitor
96 %type <integer> integer_and
97 %type <integer> integer_or
98 %type <integer> integer_trinary
99 %type <integer> integer_expr
100
101 %%
102
103 sourcefile:
104           DT_V1 ';' memreserves devicetree
105                 {
106                         the_boot_info = build_boot_info($3, $4,
107                                                         guess_boot_cpuid($4));
108                 }
109         ;
110
111 memreserves:
112           /* empty */
113                 {
114                         $$ = NULL;
115                 }
116         | memreserve memreserves
117                 {
118                         $$ = chain_reserve_entry($1, $2);
119                 }
120         ;
121
122 memreserve:
123           DT_MEMRESERVE integer_prim integer_prim ';'
124                 {
125                         $$ = build_reserve_entry($2, $3);
126                 }
127         | DT_LABEL memreserve
128                 {
129                         add_label(&$2->labels, $1);
130                         $$ = $2;
131                 }
132         ;
133
134 devicetree:
135           '/' nodedef
136                 {
137                         $$ = name_node($2, "");
138                 }
139         | devicetree '/' nodedef
140                 {
141                         $$ = merge_nodes($1, $3);
142                 }
143
144         | devicetree DT_LABEL DT_REF nodedef
145                 {
146                         struct node *target = get_node_by_ref($1, $3);
147
148                         add_label(&target->labels, $2);
149                         if (target)
150                                 merge_nodes(target, $4);
151                         else
152                                 ERROR(&@3, "Label or path %s not found", $3);
153                         $$ = $1;
154                 }
155         | devicetree DT_REF nodedef
156                 {
157                         struct node *target = get_node_by_ref($1, $2);
158
159                         if (target)
160                                 merge_nodes(target, $3);
161                         else
162                                 ERROR(&@2, "Label or path %s not found", $2);
163                         $$ = $1;
164                 }
165         | devicetree DT_DEL_NODE DT_REF ';'
166                 {
167                         struct node *target = get_node_by_ref($1, $3);
168
169                         if (target)
170                                 delete_node(target);
171                         else
172                                 ERROR(&@3, "Label or path %s not found", $3);
173
174
175                         $$ = $1;
176                 }
177         ;
178
179 nodedef:
180           '{' proplist subnodes '}' ';'
181                 {
182                         $$ = build_node($2, $3);
183                 }
184         ;
185
186 proplist:
187           /* empty */
188                 {
189                         $$ = NULL;
190                 }
191         | proplist propdef
192                 {
193                         $$ = chain_property($2, $1);
194                 }
195         ;
196
197 propdef:
198           DT_PROPNODENAME '=' propdata ';'
199                 {
200                         $$ = build_property($1, $3);
201                 }
202         | DT_PROPNODENAME ';'
203                 {
204                         $$ = build_property($1, empty_data);
205                 }
206         | DT_DEL_PROP DT_PROPNODENAME ';'
207                 {
208                         $$ = build_property_delete($2);
209                 }
210         | DT_LABEL propdef
211                 {
212                         add_label(&$2->labels, $1);
213                         $$ = $2;
214                 }
215         ;
216
217 propdata:
218           propdataprefix DT_STRING
219                 {
220                         $$ = data_merge($1, $2);
221                 }
222         | propdataprefix arrayprefix '>'
223                 {
224                         $$ = data_merge($1, $2.data);
225                 }
226         | propdataprefix '[' bytestring ']'
227                 {
228                         $$ = data_merge($1, $3);
229                 }
230         | propdataprefix DT_REF
231                 {
232                         $$ = data_add_marker($1, REF_PATH, $2);
233                 }
234         | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
235                 {
236                         FILE *f = srcfile_relative_open($4.val, NULL);
237                         struct data d;
238
239                         if ($6 != 0)
240                                 if (fseek(f, $6, SEEK_SET) != 0)
241                                         die("Couldn't seek to offset %llu in \"%s\": %s",
242                                             (unsigned long long)$6, $4.val,
243                                             strerror(errno));
244
245                         d = data_copy_file(f, $8);
246
247                         $$ = data_merge($1, d);
248                         fclose(f);
249                 }
250         | propdataprefix DT_INCBIN '(' DT_STRING ')'
251                 {
252                         FILE *f = srcfile_relative_open($4.val, NULL);
253                         struct data d = empty_data;
254
255                         d = data_copy_file(f, -1);
256
257                         $$ = data_merge($1, d);
258                         fclose(f);
259                 }
260         | propdata DT_LABEL
261                 {
262                         $$ = data_add_marker($1, LABEL, $2);
263                 }
264         ;
265
266 propdataprefix:
267           /* empty */
268                 {
269                         $$ = empty_data;
270                 }
271         | propdata ','
272                 {
273                         $$ = $1;
274                 }
275         | propdataprefix DT_LABEL
276                 {
277                         $$ = data_add_marker($1, LABEL, $2);
278                 }
279         ;
280
281 arrayprefix:
282         DT_BITS DT_LITERAL '<'
283                 {
284                         unsigned long long bits;
285
286                         bits = $2;
287
288                         if ((bits !=  8) && (bits != 16) &&
289                             (bits != 32) && (bits != 64)) {
290                                 ERROR(&@2, "Array elements must be"
291                                       " 8, 16, 32 or 64-bits");
292                                 bits = 32;
293                         }
294
295                         $$.data = empty_data;
296                         $$.bits = bits;
297                 }
298         | '<'
299                 {
300                         $$.data = empty_data;
301                         $$.bits = 32;
302                 }
303         | arrayprefix integer_prim
304                 {
305                         if ($1.bits < 64) {
306                                 uint64_t mask = (1ULL << $1.bits) - 1;
307                                 /*
308                                  * Bits above mask must either be all zero
309                                  * (positive within range of mask) or all one
310                                  * (negative and sign-extended). The second
311                                  * condition is true if when we set all bits
312                                  * within the mask to one (i.e. | in the
313                                  * mask), all bits are one.
314                                  */
315                                 if (($2 > mask) && (($2 | mask) != -1ULL))
316                                         ERROR(&@2, "Value out of range for"
317                                               " %d-bit array element", $1.bits);
318                         }
319
320                         $$.data = data_append_integer($1.data, $2, $1.bits);
321                 }
322         | arrayprefix DT_REF
323                 {
324                         uint64_t val = ~0ULL >> (64 - $1.bits);
325
326                         if ($1.bits == 32)
327                                 $1.data = data_add_marker($1.data,
328                                                           REF_PHANDLE,
329                                                           $2);
330                         else
331                                 ERROR(&@2, "References are only allowed in "
332                                             "arrays with 32-bit elements.");
333
334                         $$.data = data_append_integer($1.data, val, $1.bits);
335                 }
336         | arrayprefix DT_LABEL
337                 {
338                         $$.data = data_add_marker($1.data, LABEL, $2);
339                 }
340         ;
341
342 integer_prim:
343           DT_LITERAL
344         | DT_CHAR_LITERAL
345         | '(' integer_expr ')'
346                 {
347                         $$ = $2;
348                 }
349         ;
350
351 integer_expr:
352         integer_trinary
353         ;
354
355 integer_trinary:
356           integer_or
357         | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
358         ;
359
360 integer_or:
361           integer_and
362         | integer_or DT_OR integer_and { $$ = $1 || $3; }
363         ;
364
365 integer_and:
366           integer_bitor
367         | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
368         ;
369
370 integer_bitor:
371           integer_bitxor
372         | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
373         ;
374
375 integer_bitxor:
376           integer_bitand
377         | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
378         ;
379
380 integer_bitand:
381           integer_eq
382         | integer_bitand '&' integer_eq { $$ = $1 & $3; }
383         ;
384
385 integer_eq:
386           integer_rela
387         | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
388         | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
389         ;
390
391 integer_rela:
392           integer_shift
393         | integer_rela '<' integer_shift { $$ = $1 < $3; }
394         | integer_rela '>' integer_shift { $$ = $1 > $3; }
395         | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
396         | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
397         ;
398
399 integer_shift:
400           integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
401         | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
402         | integer_add
403         ;
404
405 integer_add:
406           integer_add '+' integer_mul { $$ = $1 + $3; }
407         | integer_add '-' integer_mul { $$ = $1 - $3; }
408         | integer_mul
409         ;
410
411 integer_mul:
412           integer_mul '*' integer_unary { $$ = $1 * $3; }
413         | integer_mul '/' integer_unary { $$ = $1 / $3; }
414         | integer_mul '%' integer_unary { $$ = $1 % $3; }
415         | integer_unary
416         ;
417
418 integer_unary:
419           integer_prim
420         | '-' integer_unary { $$ = -$2; }
421         | '~' integer_unary { $$ = ~$2; }
422         | '!' integer_unary { $$ = !$2; }
423         ;
424
425 bytestring:
426           /* empty */
427                 {
428                         $$ = empty_data;
429                 }
430         | bytestring DT_BYTE
431                 {
432                         $$ = data_append_byte($1, $2);
433                 }
434         | bytestring DT_LABEL
435                 {
436                         $$ = data_add_marker($1, LABEL, $2);
437                 }
438         ;
439
440 subnodes:
441           /* empty */
442                 {
443                         $$ = NULL;
444                 }
445         | subnode subnodes
446                 {
447                         $$ = chain_node($1, $2);
448                 }
449         | subnode propdef
450                 {
451                         ERROR(&@2, "Properties must precede subnodes");
452                         YYERROR;
453                 }
454         ;
455
456 subnode:
457           DT_PROPNODENAME nodedef
458                 {
459                         $$ = name_node($2, $1);
460                 }
461         | DT_DEL_NODE DT_PROPNODENAME ';'
462                 {
463                         $$ = name_node(build_node_delete(), $2);
464                 }
465         | DT_LABEL subnode
466                 {
467                         add_label(&$2->labels, $1);
468                         $$ = $2;
469                 }
470         ;
471
472 %%
473
474 void yyerror(char const *s)
475 {
476         ERROR(&yylloc, "%s", s);
477 }