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