diff options
Diffstat (limited to 'scripts/dtc/dtc-parser.y')
-rw-r--r-- | scripts/dtc/dtc-parser.y | 160 |
1 files changed, 63 insertions, 97 deletions
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index b2ab562420ea..5e84a67fc1d2 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y | |||
@@ -18,15 +18,17 @@ | |||
18 | * USA | 18 | * USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | %locations | ||
22 | |||
23 | %{ | 21 | %{ |
24 | #include <stdio.h> | 22 | #include <stdio.h> |
25 | 23 | ||
26 | #include "dtc.h" | 24 | #include "dtc.h" |
27 | #include "srcpos.h" | 25 | #include "srcpos.h" |
28 | 26 | ||
27 | YYLTYPE yylloc; | ||
28 | |||
29 | extern int yylex(void); | 29 | extern int yylex(void); |
30 | extern void print_error(char const *fmt, ...); | ||
31 | extern void yyerror(char const *s); | ||
30 | 32 | ||
31 | extern struct boot_info *the_boot_info; | 33 | extern struct boot_info *the_boot_info; |
32 | extern int treesource_error; | 34 | extern int treesource_error; |
@@ -55,7 +57,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
55 | %token DT_MEMRESERVE | 57 | %token DT_MEMRESERVE |
56 | %token <propnodename> DT_PROPNODENAME | 58 | %token <propnodename> DT_PROPNODENAME |
57 | %token <literal> DT_LITERAL | 59 | %token <literal> DT_LITERAL |
58 | %token <literal> DT_LEGACYLITERAL | ||
59 | %token <cbase> DT_BASE | 60 | %token <cbase> DT_BASE |
60 | %token <byte> DT_BYTE | 61 | %token <byte> DT_BYTE |
61 | %token <data> DT_STRING | 62 | %token <data> DT_STRING |
@@ -67,11 +68,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
67 | %type <data> propdataprefix | 68 | %type <data> propdataprefix |
68 | %type <re> memreserve | 69 | %type <re> memreserve |
69 | %type <re> memreserves | 70 | %type <re> memreserves |
70 | %type <re> v0_memreserve | ||
71 | %type <re> v0_memreserves | ||
72 | %type <addr> addr | 71 | %type <addr> addr |
73 | %type <data> celllist | 72 | %type <data> celllist |
74 | %type <cbase> cellbase | ||
75 | %type <cell> cellval | 73 | %type <cell> cellval |
76 | %type <data> bytestring | 74 | %type <data> bytestring |
77 | %type <prop> propdef | 75 | %type <prop> propdef |
@@ -81,18 +79,14 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
81 | %type <node> nodedef | 79 | %type <node> nodedef |
82 | %type <node> subnode | 80 | %type <node> subnode |
83 | %type <nodelist> subnodes | 81 | %type <nodelist> subnodes |
84 | %type <labelref> label | ||
85 | 82 | ||
86 | %% | 83 | %% |
87 | 84 | ||
88 | sourcefile: | 85 | sourcefile: |
89 | DT_V1 ';' memreserves devicetree | 86 | DT_V1 ';' memreserves devicetree |
90 | { | 87 | { |
91 | the_boot_info = build_boot_info($3, $4, 0); | 88 | the_boot_info = build_boot_info($3, $4, |
92 | } | 89 | guess_boot_cpuid($4)); |
93 | | v0_memreserves devicetree | ||
94 | { | ||
95 | the_boot_info = build_boot_info($1, $2, 0); | ||
96 | } | 90 | } |
97 | ; | 91 | ; |
98 | 92 | ||
@@ -108,31 +102,14 @@ memreserves: | |||
108 | ; | 102 | ; |
109 | 103 | ||
110 | memreserve: | 104 | memreserve: |
111 | label DT_MEMRESERVE addr addr ';' | 105 | DT_MEMRESERVE addr addr ';' |
112 | { | 106 | { |
113 | $$ = build_reserve_entry($3, $4, $1); | 107 | $$ = build_reserve_entry($2, $3); |
114 | } | 108 | } |
115 | ; | 109 | | DT_LABEL memreserve |
116 | |||
117 | v0_memreserves: | ||
118 | /* empty */ | ||
119 | { | 110 | { |
120 | $$ = NULL; | 111 | add_label(&$2->labels, $1); |
121 | } | 112 | $$ = $2; |
122 | | v0_memreserve v0_memreserves | ||
123 | { | ||
124 | $$ = chain_reserve_entry($1, $2); | ||
125 | }; | ||
126 | ; | ||
127 | |||
128 | v0_memreserve: | ||
129 | memreserve | ||
130 | { | ||
131 | $$ = $1; | ||
132 | } | ||
133 | | label DT_MEMRESERVE addr '-' addr ';' | ||
134 | { | ||
135 | $$ = build_reserve_entry($3, $5 - $3 + 1, $1); | ||
136 | } | 113 | } |
137 | ; | 114 | ; |
138 | 115 | ||
@@ -141,16 +118,26 @@ addr: | |||
141 | { | 118 | { |
142 | $$ = eval_literal($1, 0, 64); | 119 | $$ = eval_literal($1, 0, 64); |
143 | } | 120 | } |
144 | | DT_LEGACYLITERAL | ||
145 | { | ||
146 | $$ = eval_literal($1, 16, 64); | ||
147 | } | ||
148 | ; | 121 | ; |
149 | 122 | ||
150 | devicetree: | 123 | devicetree: |
151 | '/' nodedef | 124 | '/' nodedef |
152 | { | 125 | { |
153 | $$ = name_node($2, "", NULL); | 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; | ||
154 | } | 141 | } |
155 | ; | 142 | ; |
156 | 143 | ||
@@ -173,13 +160,18 @@ proplist: | |||
173 | ; | 160 | ; |
174 | 161 | ||
175 | propdef: | 162 | propdef: |
176 | label DT_PROPNODENAME '=' propdata ';' | 163 | DT_PROPNODENAME '=' propdata ';' |
164 | { | ||
165 | $$ = build_property($1, $3); | ||
166 | } | ||
167 | | DT_PROPNODENAME ';' | ||
177 | { | 168 | { |
178 | $$ = build_property($2, $4, $1); | 169 | $$ = build_property($1, empty_data); |
179 | } | 170 | } |
180 | | label DT_PROPNODENAME ';' | 171 | | DT_LABEL propdef |
181 | { | 172 | { |
182 | $$ = build_property($2, empty_data, $1); | 173 | add_label(&$2->labels, $1); |
174 | $$ = $2; | ||
183 | } | 175 | } |
184 | ; | 176 | ; |
185 | 177 | ||
@@ -202,31 +194,30 @@ propdata: | |||
202 | } | 194 | } |
203 | | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' | 195 | | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' |
204 | { | 196 | { |
205 | struct search_path path = { srcpos_file->dir, NULL, NULL }; | 197 | FILE *f = srcfile_relative_open($4.val, NULL); |
206 | struct dtc_file *file = dtc_open_file($4.val, &path); | 198 | struct data d; |
207 | struct data d = empty_data; | ||
208 | 199 | ||
209 | if ($6 != 0) | 200 | if ($6 != 0) |
210 | if (fseek(file->file, $6, SEEK_SET) != 0) | 201 | if (fseek(f, $6, SEEK_SET) != 0) |
211 | yyerrorf("Couldn't seek to offset %llu in \"%s\": %s", | 202 | print_error("Couldn't seek to offset %llu in \"%s\": %s", |
212 | (unsigned long long)$6, | 203 | (unsigned long long)$6, |
213 | $4.val, strerror(errno)); | 204 | $4.val, |
205 | strerror(errno)); | ||
214 | 206 | ||
215 | d = data_copy_file(file->file, $8); | 207 | d = data_copy_file(f, $8); |
216 | 208 | ||
217 | $$ = data_merge($1, d); | 209 | $$ = data_merge($1, d); |
218 | dtc_close_file(file); | 210 | fclose(f); |
219 | } | 211 | } |
220 | | propdataprefix DT_INCBIN '(' DT_STRING ')' | 212 | | propdataprefix DT_INCBIN '(' DT_STRING ')' |
221 | { | 213 | { |
222 | struct search_path path = { srcpos_file->dir, NULL, NULL }; | 214 | FILE *f = srcfile_relative_open($4.val, NULL); |
223 | struct dtc_file *file = dtc_open_file($4.val, &path); | ||
224 | struct data d = empty_data; | 215 | struct data d = empty_data; |
225 | 216 | ||
226 | d = data_copy_file(file->file, -1); | 217 | d = data_copy_file(f, -1); |
227 | 218 | ||
228 | $$ = data_merge($1, d); | 219 | $$ = data_merge($1, d); |
229 | dtc_close_file(file); | 220 | fclose(f); |
230 | } | 221 | } |
231 | | propdata DT_LABEL | 222 | | propdata DT_LABEL |
232 | { | 223 | { |
@@ -269,23 +260,11 @@ celllist: | |||
269 | } | 260 | } |
270 | ; | 261 | ; |
271 | 262 | ||
272 | cellbase: | ||
273 | /* empty */ | ||
274 | { | ||
275 | $$ = 16; | ||
276 | } | ||
277 | | DT_BASE | ||
278 | ; | ||
279 | |||
280 | cellval: | 263 | cellval: |
281 | DT_LITERAL | 264 | DT_LITERAL |
282 | { | 265 | { |
283 | $$ = eval_literal($1, 0, 32); | 266 | $$ = eval_literal($1, 0, 32); |
284 | } | 267 | } |
285 | | cellbase DT_LEGACYLITERAL | ||
286 | { | ||
287 | $$ = eval_literal($2, $1, 32); | ||
288 | } | ||
289 | ; | 268 | ; |
290 | 269 | ||
291 | bytestring: | 270 | bytestring: |
@@ -308,57 +287,44 @@ subnodes: | |||
308 | { | 287 | { |
309 | $$ = NULL; | 288 | $$ = NULL; |
310 | } | 289 | } |
311 | | subnode subnodes | 290 | | subnode subnodes |
312 | { | 291 | { |
313 | $$ = chain_node($1, $2); | 292 | $$ = chain_node($1, $2); |
314 | } | 293 | } |
315 | | subnode propdef | 294 | | subnode propdef |
316 | { | 295 | { |
317 | yyerror("syntax error: properties must precede subnodes"); | 296 | print_error("syntax error: properties must precede subnodes"); |
318 | YYERROR; | 297 | YYERROR; |
319 | } | 298 | } |
320 | ; | 299 | ; |
321 | 300 | ||
322 | subnode: | 301 | subnode: |
323 | label DT_PROPNODENAME nodedef | 302 | DT_PROPNODENAME nodedef |
324 | { | 303 | { |
325 | $$ = name_node($3, $2, $1); | 304 | $$ = name_node($2, $1); |
326 | } | 305 | } |
327 | ; | 306 | | DT_LABEL subnode |
328 | |||
329 | label: | ||
330 | /* empty */ | ||
331 | { | 307 | { |
332 | $$ = NULL; | 308 | add_label(&$2->labels, $1); |
333 | } | 309 | $$ = $2; |
334 | | DT_LABEL | ||
335 | { | ||
336 | $$ = $1; | ||
337 | } | 310 | } |
338 | ; | 311 | ; |
339 | 312 | ||
340 | %% | 313 | %% |
341 | 314 | ||
342 | void yyerrorf(char const *s, ...) | 315 | void print_error(char const *fmt, ...) |
343 | { | 316 | { |
344 | const char *fname = srcpos_file ? srcpos_file->name : "<no-file>"; | ||
345 | va_list va; | 317 | va_list va; |
346 | va_start(va, s); | ||
347 | |||
348 | if (strcmp(fname, "-") == 0) | ||
349 | fname = "stdin"; | ||
350 | 318 | ||
351 | fprintf(stderr, "%s:%d ", fname, yylloc.first_line); | 319 | va_start(va, fmt); |
352 | vfprintf(stderr, s, va); | 320 | srcpos_verror(&yylloc, fmt, va); |
353 | fprintf(stderr, "\n"); | 321 | va_end(va); |
354 | 322 | ||
355 | treesource_error = 1; | 323 | treesource_error = 1; |
356 | va_end(va); | ||
357 | } | 324 | } |
358 | 325 | ||
359 | void yyerror (char const *s) | 326 | void yyerror(char const *s) { |
360 | { | 327 | print_error("%s", s); |
361 | yyerrorf("%s", s); | ||
362 | } | 328 | } |
363 | 329 | ||
364 | static unsigned long long eval_literal(const char *s, int base, int bits) | 330 | static unsigned long long eval_literal(const char *s, int base, int bits) |
@@ -369,11 +335,11 @@ static unsigned long long eval_literal(const char *s, int base, int bits) | |||
369 | errno = 0; | 335 | errno = 0; |
370 | val = strtoull(s, &e, base); | 336 | val = strtoull(s, &e, base); |
371 | if (*e) | 337 | if (*e) |
372 | yyerror("bad characters in literal"); | 338 | print_error("bad characters in literal"); |
373 | else if ((errno == ERANGE) | 339 | else if ((errno == ERANGE) |
374 | || ((bits < 64) && (val >= (1ULL << bits)))) | 340 | || ((bits < 64) && (val >= (1ULL << bits)))) |
375 | yyerror("literal out of range"); | 341 | print_error("literal out of range"); |
376 | else if (errno != 0) | 342 | else if (errno != 0) |
377 | yyerror("bad literal"); | 343 | print_error("bad literal"); |
378 | return val; | 344 | return val; |
379 | } | 345 | } |