]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/dtc/dtc-parser.y
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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
22 %{
23 #include <stdio.h>
24
25 #include "dtc.h"
26 #include "srcpos.h"
27
28 YYLTYPE yylloc;
29
30 extern int yylex(void);
31 extern void yyerror(char const *s);
32
33 extern struct boot_info *the_boot_info;
34 extern int treesource_error;
35
36 static unsigned long long eval_literal(const char *s, int base, int bits);
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
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;
54 }
55
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
66
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
77
78 %type <node> devicetree
79 %type <node> nodedef
80 %type <node> subnode
81 %type <nodelist> subnodes
82 %type <labelref> label
83
84 %%
85
86 sourcefile:
87           DT_V1 ';' memreserves devicetree
88                 {
89                         the_boot_info = build_boot_info($3, $4, 0);
90                 }
91         ;
92
93 memreserves:
94           /* empty */
95                 {
96                         $$ = NULL;
97                 }
98         | memreserve memreserves
99                 {
100                         $$ = chain_reserve_entry($1, $2);
101                 }
102         ;
103
104 memreserve:
105           label DT_MEMRESERVE addr addr ';'
106                 {
107                         $$ = build_reserve_entry($3, $4, $1);
108                 }
109         ;
110
111 addr:
112           DT_LITERAL
113                 {
114                         $$ = eval_literal($1, 0, 64);
115                 }
116           ;
117
118 devicetree:
119           '/' nodedef
120                 {
121                         $$ = name_node($2, "", NULL);
122                 }
123         ;
124
125 nodedef:
126           '{' proplist subnodes '}' ';'
127                 {
128                         $$ = build_node($2, $3);
129                 }
130         ;
131
132 proplist:
133           /* empty */
134                 {
135                         $$ = NULL;
136                 }
137         | proplist propdef
138                 {
139                         $$ = chain_property($2, $1);
140                 }
141         ;
142
143 propdef:
144           label DT_PROPNODENAME '=' propdata ';'
145                 {
146                         $$ = build_property($2, $4, $1);
147                 }
148         | label DT_PROPNODENAME ';'
149                 {
150                         $$ = build_property($2, empty_data, $1);
151                 }
152         ;
153
154 propdata:
155           propdataprefix DT_STRING
156                 {
157                         $$ = data_merge($1, $2);
158                 }
159         | propdataprefix '<' celllist '>'
160                 {
161                         $$ = data_merge($1, $3);
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                 }
171         | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
172                 {
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;
176
177                         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",
181                                                      (unsigned long long)$6,
182                                                      $4.val,
183                                                      strerror(errno));
184
185                         d = data_copy_file(file->file, $8);
186
187                         $$ = data_merge($1, d);
188                         dtc_close_file(file);
189                 }
190         | propdataprefix DT_INCBIN '(' DT_STRING ')'
191                 {
192                         struct search_path path = { srcpos_file->dir, NULL, NULL };
193                         struct dtc_file *file = dtc_open_file($4.val, &path);
194                         struct data d = empty_data;
195
196                         d = data_copy_file(file->file, -1);
197
198                         $$ = data_merge($1, d);
199                         dtc_close_file(file);
200                 }
201         | propdata DT_LABEL
202                 {
203                         $$ = data_add_marker($1, LABEL, $2);
204                 }
205         ;
206
207 propdataprefix:
208           /* empty */
209                 {
210                         $$ = empty_data;
211                 }
212         | propdata ','
213                 {
214                         $$ = $1;
215                 }
216         | propdataprefix DT_LABEL
217                 {
218                         $$ = data_add_marker($1, LABEL, $2);
219                 }
220         ;
221
222 celllist:
223           /* empty */
224                 {
225                         $$ = empty_data;
226                 }
227         | celllist cellval
228                 {
229                         $$ = data_append_cell($1, $2);
230                 }
231         | celllist DT_REF
232                 {
233                         $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
234                                                               $2), -1);
235                 }
236         | celllist DT_LABEL
237                 {
238                         $$ = data_add_marker($1, LABEL, $2);
239                 }
240         ;
241
242 cellval:
243           DT_LITERAL
244                 {
245                         $$ = eval_literal($1, 0, 32);
246                 }
247         ;
248
249 bytestring:
250           /* empty */
251                 {
252                         $$ = empty_data;
253                 }
254         | bytestring DT_BYTE
255                 {
256                         $$ = data_append_byte($1, $2);
257                 }
258         | bytestring DT_LABEL
259                 {
260                         $$ = data_add_marker($1, LABEL, $2);
261                 }
262         ;
263
264 subnodes:
265           /* empty */
266                 {
267                         $$ = NULL;
268                 }
269         |  subnode subnodes
270                 {
271                         $$ = chain_node($1, $2);
272                 }
273         | subnode propdef
274                 {
275                         yyerror("syntax error: properties must precede subnodes");
276                         YYERROR;
277                 }
278         ;
279
280 subnode:
281           label DT_PROPNODENAME nodedef
282                 {
283                         $$ = name_node($3, $2, $1);
284                 }
285         ;
286
287 label:
288           /* empty */
289                 {
290                         $$ = NULL;
291                 }
292         | DT_LABEL
293                 {
294                         $$ = $1;
295                 }
296         ;
297
298 %%
299
300 void yyerror(char const *s)
301 {
302         srcpos_error(&yylloc, "%s", s);
303         treesource_error = 1;
304 }
305
306 static 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);
313         if (*e)
314                 yyerror("bad characters in literal");
315         else if ((errno == ERANGE)
316                  || ((bits < 64) && (val >= (1ULL << bits))))
317                 yyerror("literal out of range");
318         else if (errno != 0)
319                 yyerror("bad literal");
320         return val;
321 }