Merge branches 'release', 'asus', 'sony-laptop' and 'thinkpad' into release
[pandora-kernel.git] / arch / powerpc / boot / dtc-src / 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 %locations
22
23 %{
24 #include "dtc.h"
25 #include "srcpos.h"
26
27 int yylex(void);
28 unsigned long long eval_literal(const char *s, int base, int bits);
29
30 extern struct boot_info *the_boot_info;
31
32 %}
33
34 %union {
35         char *propnodename;
36         char *literal;
37         char *labelref;
38         unsigned int cbase;
39         u8 byte;
40         struct data data;
41
42         u64 addr;
43         cell_t cell;
44         struct property *prop;
45         struct property *proplist;
46         struct node *node;
47         struct node *nodelist;
48         struct reserve_info *re;
49 }
50
51 %token DT_V1
52 %token DT_MEMRESERVE
53 %token <propnodename> DT_PROPNODENAME
54 %token <literal> DT_LITERAL
55 %token <literal> DT_LEGACYLITERAL
56 %token <cbase> DT_BASE
57 %token <byte> DT_BYTE
58 %token <data> DT_STRING
59 %token <labelref> DT_LABEL
60 %token <labelref> DT_REF
61
62 %type <data> propdata
63 %type <data> propdataprefix
64 %type <re> memreserve
65 %type <re> memreserves
66 %type <re> v0_memreserve
67 %type <re> v0_memreserves
68 %type <addr> addr
69 %type <data> celllist
70 %type <cbase> cellbase
71 %type <cell> cellval
72 %type <data> bytestring
73 %type <prop> propdef
74 %type <proplist> proplist
75
76 %type <node> devicetree
77 %type <node> nodedef
78 %type <node> subnode
79 %type <nodelist> subnodes
80 %type <labelref> label
81
82 %%
83
84 sourcefile:
85           DT_V1 ';' memreserves devicetree
86                 {
87                         the_boot_info = build_boot_info($3, $4);
88                 }
89         | v0_memreserves devicetree
90                 {
91                         the_boot_info = build_boot_info($1, $2);
92                 }
93         ;
94
95 memreserves:
96           /* empty */
97                 {
98                         $$ = NULL;
99                 }
100         | memreserve memreserves
101                 {
102                         $$ = chain_reserve_entry($1, $2);
103                 }
104         ;
105
106 memreserve:
107           label DT_MEMRESERVE addr addr ';'
108                 {
109                         $$ = build_reserve_entry($3, $4, $1);
110                 }
111         ;
112
113 v0_memreserves:
114           /* empty */
115                 {
116                         $$ = NULL;
117                 }
118         | v0_memreserve v0_memreserves
119                 {
120                         $$ = chain_reserve_entry($1, $2);
121                 };
122         ;
123
124 v0_memreserve:
125           memreserve
126                 {
127                         $$ = $1;
128                 }
129         | label DT_MEMRESERVE addr '-' addr ';'
130                 {
131                         $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
132                 }
133         ;
134
135 addr:
136           DT_LITERAL
137                 {
138                         $$ = eval_literal($1, 0, 64);
139                 }
140         | DT_LEGACYLITERAL
141                 {
142                         $$ = eval_literal($1, 16, 64);
143                 }
144           ;
145
146 devicetree:
147           '/' nodedef
148                 {
149                         $$ = name_node($2, "", NULL);
150                 }
151         ;
152
153 nodedef:
154           '{' proplist subnodes '}' ';'
155                 {
156                         $$ = build_node($2, $3);
157                 }
158         ;
159
160 proplist:
161           /* empty */
162                 {
163                         $$ = NULL;
164                 }
165         | proplist propdef
166                 {
167                         $$ = chain_property($2, $1);
168                 }
169         ;
170
171 propdef:
172           label DT_PROPNODENAME '=' propdata ';'
173                 {
174                         $$ = build_property($2, $4, $1);
175                 }
176         | label DT_PROPNODENAME ';'
177                 {
178                         $$ = build_property($2, empty_data, $1);
179                 }
180         ;
181
182 propdata:
183           propdataprefix DT_STRING
184                 {
185                         $$ = data_merge($1, $2);
186                 }
187         | propdataprefix '<' celllist '>'
188                 {
189                         $$ = data_merge($1, $3);
190                 }
191         | propdataprefix '[' bytestring ']'
192                 {
193                         $$ = data_merge($1, $3);
194                 }
195         | propdataprefix DT_REF
196                 {
197                         $$ = data_add_marker($1, REF_PATH, $2);
198                 }
199         | propdata DT_LABEL
200                 {
201                         $$ = data_add_marker($1, LABEL, $2);
202                 }
203         ;
204
205 propdataprefix:
206           /* empty */
207                 {
208                         $$ = empty_data;
209                 }
210         | propdata ','
211                 {
212                         $$ = $1;
213                 }
214         | propdataprefix DT_LABEL
215                 {
216                         $$ = data_add_marker($1, LABEL, $2);
217                 }
218         ;
219
220 celllist:
221           /* empty */
222                 {
223                         $$ = empty_data;
224                 }
225         | celllist cellval
226                 {
227                         $$ = data_append_cell($1, $2);
228                 }
229         | celllist DT_REF
230                 {
231                         $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
232                                                               $2), -1);
233                 }
234         | celllist DT_LABEL
235                 {
236                         $$ = data_add_marker($1, LABEL, $2);
237                 }
238         ;
239
240 cellbase:
241           /* empty */
242                 {
243                         $$ = 16;
244                 }
245         | DT_BASE
246         ;
247
248 cellval:
249           DT_LITERAL
250                 {
251                         $$ = eval_literal($1, 0, 32);
252                 }
253         | cellbase DT_LEGACYLITERAL
254                 {
255                         $$ = eval_literal($2, $1, 32);
256                 }
257         ;
258
259 bytestring:
260           /* empty */
261                 {
262                         $$ = empty_data;
263                 }
264         | bytestring DT_BYTE
265                 {
266                         $$ = data_append_byte($1, $2);
267                 }
268         | bytestring DT_LABEL
269                 {
270                         $$ = data_add_marker($1, LABEL, $2);
271                 }
272         ;
273
274 subnodes:
275           /* empty */
276                 {
277                         $$ = NULL;
278                 }
279         |  subnode subnodes
280                 {
281                         $$ = chain_node($1, $2);
282                 }
283         | subnode propdef
284                 {
285                         yyerror("syntax error: properties must precede subnodes\n");
286                         YYERROR;
287                 }
288         ;
289
290 subnode:
291           label DT_PROPNODENAME nodedef
292                 {
293                         $$ = name_node($3, $2, $1);
294                 }
295         ;
296
297 label:
298           /* empty */
299                 {
300                         $$ = NULL;
301                 }
302         | DT_LABEL
303                 {
304                         $$ = $1;
305                 }
306         ;
307
308 %%
309
310 void yyerror (char const *s)
311 {
312         const char *fname = srcpos_filename_for_num(yylloc.filenum);
313
314         if (strcmp(fname, "-") == 0)
315                 fname = "stdin";
316
317         fprintf(stderr, "%s:%d %s\n",
318                 fname, yylloc.first_line, s);
319 }
320
321 unsigned long long eval_literal(const char *s, int base, int bits)
322 {
323         unsigned long long val;
324         char *e;
325
326         errno = 0;
327         val = strtoull(s, &e, base);
328         if (*e)
329                 yyerror("bad characters in literal");
330         else if ((errno == ERANGE)
331                  || ((bits < 64) && (val >= (1ULL << bits))))
332                 yyerror("literal out of range");
333         else if (errno != 0)
334                 yyerror("bad literal");
335         return val;
336 }