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