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