1 %{ 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License, Version 1.0 only 7 * (the "License"). You may not use this file except in compliance 8 * with the License. 9 * 10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 * 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 31 #include "zonecfg.h" 32 33 static cmd_t *cmd = NULL; /* Command being processed */ 34 static complex_property_ptr_t complex = NULL; 35 static list_property_ptr_t new_list = NULL, tmp_list, last, 36 list[MAX_EQ_PROP_PAIRS]; 37 static property_value_t property[MAX_EQ_PROP_PAIRS]; 38 39 extern bool newline_terminated; 40 extern int num_prop_vals; /* # of property values */ 41 42 /* yacc externals */ 43 extern int yydebug; 44 extern void yyerror(char *s); 45 46 %} 47 48 %union { 49 int ival; 50 char *strval; 51 cmd_t *cmd; 52 complex_property_ptr_t complex; 53 list_property_ptr_t list; 54 } 55 56 %start commands 57 58 %token HELP CREATE EXPORT ADD DELETE REMOVE SELECT SET INFO CANCEL END VERIFY 59 %token COMMIT REVERT EXIT SEMICOLON TOKEN ZONEPATH AUTOBOOT POOL NET FS IPD ATTR 60 %token DEVICE RCTL SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME 61 %token MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET 62 %token OPEN_PAREN CLOSE_PAREN COMMA 63 64 %type <strval> TOKEN EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET 65 property_value OPEN_PAREN CLOSE_PAREN COMMA simple_prop_val 66 %type <complex> complex_piece complex_prop_val 67 %type <ival> resource_type NET FS IPD DEVICE RCTL ATTR 68 %type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME 69 MATCH ZONEPATH AUTOBOOT POOL VALUE PRIV LIMIT ACTION 70 %type <cmd> command 71 %type <cmd> add_command ADD 72 %type <cmd> cancel_command CANCEL 73 %type <cmd> commit_command COMMIT 74 %type <cmd> create_command CREATE 75 %type <cmd> delete_command DELETE 76 %type <cmd> end_command END 77 %type <cmd> exit_command EXIT 78 %type <cmd> export_command EXPORT 79 %type <cmd> help_command HELP 80 %type <cmd> info_command INFO 81 %type <cmd> remove_command REMOVE 82 %type <cmd> revert_command REVERT 83 %type <cmd> select_command SELECT 84 %type <cmd> set_command SET 85 %type <cmd> verify_command VERIFY 86 %type <cmd> terminator 87 88 %% 89 90 commands: command terminator 91 { 92 if ($1 != NULL) { 93 if ($1->cmd_handler != NULL) 94 $1->cmd_handler($1); 95 free_cmd($1); 96 bzero(list, sizeof (list_property_t)); 97 num_prop_vals = 0; 98 } 99 return (0); 100 } 101 | command error terminator 102 { 103 if ($1 != NULL) { 104 free_cmd($1); 105 bzero(list, sizeof (list_property_t)); 106 num_prop_vals = 0; 107 } 108 if (YYRECOVERING()) 109 return; 110 yyclearin; 111 yyerrok; 112 } 113 | error terminator 114 { 115 if (YYRECOVERING()) 116 return; 117 yyclearin; 118 yyerrok; 119 } 120 | terminator 121 { 122 return (0); 123 } 124 125 command: add_command 126 | cancel_command 127 | create_command 128 | commit_command 129 | delete_command 130 | end_command 131 | exit_command 132 | export_command 133 | help_command 134 | info_command 135 | remove_command 136 | revert_command 137 | select_command 138 | set_command 139 | verify_command 140 141 terminator: '\n' { newline_terminated = TRUE; } 142 | ';' { newline_terminated = FALSE; } 143 144 add_command: ADD 145 { 146 short_usage(CMD_ADD); 147 (void) fputs("\n", stderr); 148 usage(FALSE, HELP_RES_PROPS); 149 YYERROR; 150 } 151 | ADD TOKEN 152 { 153 if (($$ = alloc_cmd()) == NULL) 154 YYERROR; 155 cmd = $$; 156 $$->cmd_handler = &add_func; 157 $$->cmd_argc = 1; 158 $$->cmd_argv[0] = $2; 159 $$->cmd_argv[1] = NULL; 160 } 161 | ADD resource_type 162 { 163 if (($$ = alloc_cmd()) == NULL) 164 YYERROR; 165 cmd = $$; 166 $$->cmd_handler = &add_func; 167 $$->cmd_argc = 0; 168 $$->cmd_res_type = $2; 169 $$->cmd_prop_nv_pairs = 0; 170 } 171 | ADD property_name property_value 172 { 173 if (($$ = alloc_cmd()) == NULL) 174 YYERROR; 175 cmd = $$; 176 $$->cmd_handler = &add_func; 177 $$->cmd_argc = 0; 178 $$->cmd_prop_nv_pairs = 1; 179 $$->cmd_prop_name[0] = $2; 180 $$->cmd_property_ptr[0] = &property[0]; 181 } 182 183 cancel_command: CANCEL 184 { 185 if (($$ = alloc_cmd()) == NULL) 186 YYERROR; 187 cmd = $$; 188 $$->cmd_handler = &cancel_func; 189 $$->cmd_argc = 0; 190 $$->cmd_argv[0] = NULL; 191 } 192 | CANCEL TOKEN 193 { 194 if (($$ = alloc_cmd()) == NULL) 195 YYERROR; 196 cmd = $$; 197 $$->cmd_handler = &cancel_func; 198 $$->cmd_argc = 1; 199 $$->cmd_argv[0] = $2; 200 $$->cmd_argv[1] = NULL; 201 } 202 203 create_command: CREATE 204 { 205 if (($$ = alloc_cmd()) == NULL) 206 YYERROR; 207 cmd = $$; 208 $$->cmd_handler = &create_func; 209 $$->cmd_argc = 0; 210 $$->cmd_argv[0] = NULL; 211 } 212 | CREATE TOKEN 213 { 214 if (($$ = alloc_cmd()) == NULL) 215 YYERROR; 216 cmd = $$; 217 $$->cmd_handler = &create_func; 218 $$->cmd_argc = 1; 219 $$->cmd_argv[0] = $2; 220 $$->cmd_argv[1] = NULL; 221 } 222 | CREATE TOKEN TOKEN 223 { 224 if (($$ = alloc_cmd()) == NULL) 225 YYERROR; 226 cmd = $$; 227 $$->cmd_handler = &create_func; 228 $$->cmd_argc = 2; 229 $$->cmd_argv[0] = $2; 230 $$->cmd_argv[1] = $3; 231 $$->cmd_argv[2] = NULL; 232 } 233 | CREATE TOKEN TOKEN TOKEN 234 { 235 if (($$ = alloc_cmd()) == NULL) 236 YYERROR; 237 cmd = $$; 238 $$->cmd_handler = &create_func; 239 $$->cmd_argc = 3; 240 $$->cmd_argv[0] = $2; 241 $$->cmd_argv[1] = $3; 242 $$->cmd_argv[2] = $4; 243 $$->cmd_argv[3] = NULL; 244 } 245 246 commit_command: COMMIT 247 { 248 if (($$ = alloc_cmd()) == NULL) 249 YYERROR; 250 cmd = $$; 251 $$->cmd_handler = &commit_func; 252 $$->cmd_argc = 0; 253 $$->cmd_argv[0] = NULL; 254 } 255 | COMMIT TOKEN 256 { 257 if (($$ = alloc_cmd()) == NULL) 258 YYERROR; 259 cmd = $$; 260 $$->cmd_handler = &commit_func; 261 $$->cmd_argc = 1; 262 $$->cmd_argv[0] = $2; 263 $$->cmd_argv[1] = NULL; 264 } 265 266 delete_command: DELETE 267 { 268 if (($$ = alloc_cmd()) == NULL) 269 YYERROR; 270 cmd = $$; 271 $$->cmd_handler = &delete_func; 272 $$->cmd_argc = 0; 273 $$->cmd_argv[0] = NULL; 274 } 275 | DELETE TOKEN 276 { 277 if (($$ = alloc_cmd()) == NULL) 278 YYERROR; 279 cmd = $$; 280 $$->cmd_handler = &delete_func; 281 $$->cmd_argc = 1; 282 $$->cmd_argv[0] = $2; 283 $$->cmd_argv[1] = NULL; 284 } 285 286 end_command: END 287 { 288 if (($$ = alloc_cmd()) == NULL) 289 YYERROR; 290 cmd = $$; 291 $$->cmd_handler = &end_func; 292 $$->cmd_argc = 0; 293 $$->cmd_argv[0] = NULL; 294 } 295 | END TOKEN 296 { 297 if (($$ = alloc_cmd()) == NULL) 298 YYERROR; 299 cmd = $$; 300 $$->cmd_handler = &end_func; 301 $$->cmd_argc = 1; 302 $$->cmd_argv[0] = $2; 303 $$->cmd_argv[1] = NULL; 304 } 305 306 exit_command: EXIT 307 { 308 if (($$ = alloc_cmd()) == NULL) 309 YYERROR; 310 cmd = $$; 311 $$->cmd_handler = &exit_func; 312 $$->cmd_argc = 0; 313 $$->cmd_argv[0] = NULL; 314 } 315 | EXIT TOKEN 316 { 317 if (($$ = alloc_cmd()) == NULL) 318 YYERROR; 319 cmd = $$; 320 $$->cmd_handler = &exit_func; 321 $$->cmd_argc = 1; 322 $$->cmd_argv[0] = $2; 323 $$->cmd_argv[1] = NULL; 324 } 325 326 export_command: EXPORT 327 { 328 if (($$ = alloc_cmd()) == NULL) 329 YYERROR; 330 cmd = $$; 331 $$->cmd_handler = &export_func; 332 $$->cmd_argc = 0; 333 $$->cmd_argv[0] = NULL; 334 } 335 | EXPORT TOKEN 336 { 337 if (($$ = alloc_cmd()) == NULL) 338 YYERROR; 339 cmd = $$; 340 $$->cmd_handler = &export_func; 341 $$->cmd_argc = 1; 342 $$->cmd_argv[0] = $2; 343 $$->cmd_argv[1] = NULL; 344 } 345 | EXPORT TOKEN TOKEN 346 { 347 if (($$ = alloc_cmd()) == NULL) 348 YYERROR; 349 cmd = $$; 350 $$->cmd_handler = &export_func; 351 $$->cmd_argc = 2; 352 $$->cmd_argv[0] = $2; 353 $$->cmd_argv[1] = $3; 354 $$->cmd_argv[2] = NULL; 355 } 356 357 help_command: HELP 358 { 359 if (($$ = alloc_cmd()) == NULL) 360 YYERROR; 361 cmd = $$; 362 $$->cmd_handler = &help_func; 363 $$->cmd_argc = 0; 364 $$->cmd_argv[0] = NULL; 365 } 366 | HELP TOKEN 367 { 368 if (($$ = alloc_cmd()) == NULL) 369 YYERROR; 370 cmd = $$; 371 $$->cmd_handler = &help_func; 372 $$->cmd_argc = 1; 373 $$->cmd_argv[0] = $2; 374 $$->cmd_argv[1] = NULL; 375 } 376 377 info_command: INFO 378 { 379 if (($$ = alloc_cmd()) == NULL) 380 YYERROR; 381 cmd = $$; 382 $$->cmd_handler = &info_func; 383 $$->cmd_res_type = RT_UNKNOWN; 384 $$->cmd_prop_nv_pairs = 0; 385 } 386 | INFO TOKEN 387 { 388 short_usage(CMD_INFO); 389 (void) fputs("\n", stderr); 390 usage(FALSE, HELP_RES_PROPS); 391 free($2); 392 YYERROR; 393 } 394 | INFO resource_type 395 { 396 if (($$ = alloc_cmd()) == NULL) 397 YYERROR; 398 cmd = $$; 399 $$->cmd_handler = &info_func; 400 $$->cmd_res_type = $2; 401 $$->cmd_prop_nv_pairs = 0; 402 } 403 | INFO ZONEPATH 404 { 405 if (($$ = alloc_cmd()) == NULL) 406 YYERROR; 407 cmd = $$; 408 $$->cmd_handler = &info_func; 409 $$->cmd_res_type = RT_ZONEPATH; 410 $$->cmd_prop_nv_pairs = 0; 411 } 412 | INFO AUTOBOOT 413 { 414 if (($$ = alloc_cmd()) == NULL) 415 YYERROR; 416 cmd = $$; 417 $$->cmd_handler = &info_func; 418 $$->cmd_res_type = RT_AUTOBOOT; 419 $$->cmd_prop_nv_pairs = 0; 420 } 421 | INFO POOL 422 { 423 if (($$ = alloc_cmd()) == NULL) 424 YYERROR; 425 cmd = $$; 426 $$->cmd_handler = &info_func; 427 $$->cmd_res_type = RT_POOL; 428 $$->cmd_prop_nv_pairs = 0; 429 } 430 | INFO resource_type property_name EQUAL property_value 431 { 432 if (($$ = alloc_cmd()) == NULL) 433 YYERROR; 434 cmd = $$; 435 $$->cmd_handler = &info_func; 436 $$->cmd_res_type = $2; 437 $$->cmd_prop_nv_pairs = 1; 438 $$->cmd_prop_name[0] = $3; 439 $$->cmd_property_ptr[0] = &property[0]; 440 } 441 | INFO resource_type property_name EQUAL property_value property_name EQUAL property_value 442 { 443 if (($$ = alloc_cmd()) == NULL) 444 YYERROR; 445 cmd = $$; 446 $$->cmd_handler = &info_func; 447 $$->cmd_res_type = $2; 448 $$->cmd_prop_nv_pairs = 2; 449 $$->cmd_prop_name[0] = $3; 450 $$->cmd_property_ptr[0] = &property[0]; 451 $$->cmd_prop_name[1] = $6; 452 $$->cmd_property_ptr[1] = &property[1]; 453 } 454 | INFO resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value 455 { 456 if (($$ = alloc_cmd()) == NULL) 457 YYERROR; 458 cmd = $$; 459 $$->cmd_handler = &info_func; 460 $$->cmd_res_type = $2; 461 $$->cmd_prop_nv_pairs = 3; 462 $$->cmd_prop_name[0] = $3; 463 $$->cmd_property_ptr[0] = &property[0]; 464 $$->cmd_prop_name[1] = $6; 465 $$->cmd_property_ptr[1] = &property[1]; 466 $$->cmd_prop_name[2] = $9; 467 $$->cmd_property_ptr[2] = &property[2]; 468 } 469 470 remove_command: REMOVE 471 { 472 short_usage(CMD_REMOVE); 473 (void) fputs("\n", stderr); 474 usage(FALSE, HELP_RES_PROPS); 475 YYERROR; 476 } 477 | REMOVE resource_type 478 { 479 short_usage(CMD_REMOVE); 480 YYERROR; 481 } 482 | REMOVE property_name property_value 483 { 484 if (($$ = alloc_cmd()) == NULL) 485 YYERROR; 486 cmd = $$; 487 $$->cmd_handler = &remove_func; 488 $$->cmd_prop_nv_pairs = 1; 489 $$->cmd_prop_name[0] = $2; 490 $$->cmd_property_ptr[0] = &property[0]; 491 } 492 | REMOVE resource_type property_name EQUAL property_value 493 { 494 if (($$ = alloc_cmd()) == NULL) 495 YYERROR; 496 cmd = $$; 497 $$->cmd_handler = &remove_func; 498 $$->cmd_res_type = $2; 499 $$->cmd_prop_nv_pairs = 1; 500 $$->cmd_prop_name[0] = $3; 501 $$->cmd_property_ptr[0] = &property[0]; 502 } 503 | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value 504 { 505 if (($$ = alloc_cmd()) == NULL) 506 YYERROR; 507 cmd = $$; 508 $$->cmd_handler = &remove_func; 509 $$->cmd_res_type = $2; 510 $$->cmd_prop_nv_pairs = 2; 511 $$->cmd_prop_name[0] = $3; 512 $$->cmd_property_ptr[0] = &property[0]; 513 $$->cmd_prop_name[1] = $6; 514 $$->cmd_property_ptr[1] = &property[1]; 515 } 516 | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value 517 { 518 if (($$ = alloc_cmd()) == NULL) 519 YYERROR; 520 cmd = $$; 521 $$->cmd_handler = &remove_func; 522 $$->cmd_res_type = $2; 523 $$->cmd_prop_nv_pairs = 3; 524 $$->cmd_prop_name[0] = $3; 525 $$->cmd_property_ptr[0] = &property[0]; 526 $$->cmd_prop_name[1] = $6; 527 $$->cmd_property_ptr[1] = &property[1]; 528 $$->cmd_prop_name[2] = $9; 529 $$->cmd_property_ptr[2] = &property[2]; 530 } 531 532 revert_command: REVERT 533 { 534 if (($$ = alloc_cmd()) == NULL) 535 YYERROR; 536 cmd = $$; 537 $$->cmd_handler = &revert_func; 538 $$->cmd_argc = 0; 539 $$->cmd_argv[0] = NULL; 540 } 541 | REVERT TOKEN 542 { 543 if (($$ = alloc_cmd()) == NULL) 544 YYERROR; 545 cmd = $$; 546 $$->cmd_handler = &revert_func; 547 $$->cmd_argc = 1; 548 $$->cmd_argv[0] = $2; 549 $$->cmd_argv[1] = NULL; 550 } 551 552 select_command: SELECT 553 { 554 short_usage(CMD_SELECT); 555 (void) fputs("\n", stderr); 556 usage(FALSE, HELP_RES_PROPS); 557 YYERROR; 558 } 559 | SELECT resource_type 560 { 561 short_usage(CMD_SELECT); 562 YYERROR; 563 } 564 | SELECT resource_type property_name EQUAL property_value 565 { 566 if (($$ = alloc_cmd()) == NULL) 567 YYERROR; 568 cmd = $$; 569 $$->cmd_handler = &select_func; 570 $$->cmd_res_type = $2; 571 $$->cmd_prop_nv_pairs = 1; 572 $$->cmd_prop_name[0] = $3; 573 $$->cmd_property_ptr[0] = &property[0]; 574 } 575 | SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value 576 { 577 if (($$ = alloc_cmd()) == NULL) 578 YYERROR; 579 cmd = $$; 580 $$->cmd_handler = &select_func; 581 $$->cmd_res_type = $2; 582 $$->cmd_prop_nv_pairs = 2; 583 $$->cmd_prop_name[0] = $3; 584 $$->cmd_property_ptr[0] = &property[0]; 585 $$->cmd_prop_name[1] = $6; 586 $$->cmd_property_ptr[1] = &property[1]; 587 } 588 | SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value 589 { 590 if (($$ = alloc_cmd()) == NULL) 591 YYERROR; 592 cmd = $$; 593 $$->cmd_handler = &select_func; 594 $$->cmd_res_type = $2; 595 $$->cmd_prop_nv_pairs = 3; 596 $$->cmd_prop_name[0] = $3; 597 $$->cmd_property_ptr[0] = &property[0]; 598 $$->cmd_prop_name[1] = $6; 599 $$->cmd_property_ptr[1] = &property[1]; 600 $$->cmd_prop_name[2] = $9; 601 $$->cmd_property_ptr[2] = &property[2]; 602 } 603 604 set_command: SET 605 { 606 short_usage(CMD_SET); 607 (void) fputs("\n", stderr); 608 usage(FALSE, HELP_PROPS); 609 YYERROR; 610 } 611 | SET property_name EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET 612 { 613 if (($$ = alloc_cmd()) == NULL) 614 YYERROR; 615 cmd = $$; 616 $$->cmd_handler = &set_func; 617 $$->cmd_prop_nv_pairs = 0; 618 $$->cmd_prop_name[0] = $2; 619 property[0].pv_type = PROP_VAL_LIST; 620 property[0].pv_list = NULL; 621 $$->cmd_property_ptr[0] = &property[0]; 622 } 623 | SET property_name EQUAL property_value 624 { 625 if (($$ = alloc_cmd()) == NULL) 626 YYERROR; 627 cmd = $$; 628 $$->cmd_handler = &set_func; 629 $$->cmd_prop_nv_pairs = 1; 630 $$->cmd_prop_name[0] = $2; 631 $$->cmd_property_ptr[0] = &property[0]; 632 } 633 634 verify_command: VERIFY 635 { 636 if (($$ = alloc_cmd()) == NULL) 637 YYERROR; 638 cmd = $$; 639 $$->cmd_handler = &verify_func; 640 $$->cmd_argc = 0; 641 $$->cmd_argv[0] = NULL; 642 } 643 | VERIFY TOKEN 644 { 645 if (($$ = alloc_cmd()) == NULL) 646 YYERROR; 647 cmd = $$; 648 $$->cmd_handler = &verify_func; 649 $$->cmd_argc = 1; 650 $$->cmd_argv[0] = $2; 651 $$->cmd_argv[1] = NULL; 652 } 653 654 resource_type: NET { $$ = RT_NET; } 655 | FS { $$ = RT_FS; } 656 | IPD { $$ = RT_IPD; } 657 | DEVICE { $$ = RT_DEVICE; } 658 | RCTL { $$ = RT_RCTL; } 659 | ATTR { $$ = RT_ATTR; } 660 661 property_name: SPECIAL { $$ = PT_SPECIAL; } 662 | RAW { $$ = PT_RAW; } 663 | DIR { $$ = PT_DIR; } 664 | TYPE { $$ = PT_TYPE; } 665 | OPTIONS { $$ = PT_OPTIONS; } 666 | ZONEPATH { $$ = PT_ZONEPATH; } 667 | AUTOBOOT { $$ = PT_AUTOBOOT; } 668 | POOL { $$ = PT_POOL; } 669 | ADDRESS { $$ = PT_ADDRESS; } 670 | PHYSICAL { $$ = PT_PHYSICAL; } 671 | NAME { $$ = PT_NAME; } 672 | VALUE { $$ = PT_VALUE; } 673 | MATCH { $$ = PT_MATCH; } 674 | PRIV { $$ = PT_PRIV; } 675 | LIMIT { $$ = PT_LIMIT; } 676 | ACTION { $$ = PT_ACTION; } 677 678 /* 679 * The grammar builds data structures from the bottom up. Thus various 680 * strings are lexed into TOKENs or commands or resource or property values. 681 * Below is where the resource and property values are built up into more 682 * complex data structures. 683 * 684 * There are three kinds of properties: simple (single valued), complex 685 * (one or more name=value pairs) and list (concatenation of one or more 686 * simple or complex properties). 687 * 688 * So the property structure has a type which is one of these, and the 689 * corresponding _simple, _complex or _list is set to the corresponding 690 * lower-level data structure. 691 */ 692 693 property_value: simple_prop_val 694 { 695 property[num_prop_vals].pv_type = PROP_VAL_SIMPLE; 696 property[num_prop_vals].pv_simple = $1; 697 if (list[num_prop_vals] != NULL) { 698 free_outer_list(list[num_prop_vals]); 699 list[num_prop_vals] = NULL; 700 } 701 num_prop_vals++; 702 } 703 | complex_prop_val 704 { 705 property[num_prop_vals].pv_type = PROP_VAL_COMPLEX; 706 property[num_prop_vals].pv_complex = complex; 707 if (list[num_prop_vals] != NULL) { 708 free_outer_list(list[num_prop_vals]); 709 list[num_prop_vals] = NULL; 710 } 711 num_prop_vals++; 712 } 713 | list_prop_val 714 { 715 property[num_prop_vals].pv_type = PROP_VAL_LIST; 716 property[num_prop_vals].pv_list = list[num_prop_vals]; 717 num_prop_vals++; 718 } 719 720 /* 721 * One level lower, lists are made up of simple or complex values, so 722 * simple_prop_val and complex_prop_val fill in a list structure and 723 * insert it into the linked list which is built up. And because 724 * complex properties can have multiple name=value pairs, we keep 725 * track of them in another linked list. 726 * 727 * The complex and list structures for the linked lists are allocated 728 * below, and freed by recursive functions which are ultimately called 729 * by free_cmd(), which is called from the top-most "commands" part of 730 * the grammar. 731 */ 732 733 simple_prop_val: TOKEN 734 { 735 if ((new_list = alloc_list()) == NULL) 736 YYERROR; 737 new_list->lp_simple = $1; 738 new_list->lp_complex = NULL; 739 new_list->lp_next = NULL; 740 if (list[num_prop_vals] == NULL) { 741 list[num_prop_vals] = new_list; 742 } else { 743 for (tmp_list = list[num_prop_vals]; tmp_list != NULL; 744 tmp_list = tmp_list->lp_next) 745 last = tmp_list; 746 last->lp_next = new_list; 747 } 748 } 749 750 complex_prop_val: OPEN_PAREN complex_piece CLOSE_PAREN 751 { 752 if ((new_list = alloc_list()) == NULL) 753 YYERROR; 754 new_list->lp_simple = NULL; 755 new_list->lp_complex = complex; 756 new_list->lp_next = NULL; 757 if (list[num_prop_vals] == NULL) { 758 list[num_prop_vals] = new_list; 759 } else { 760 for (tmp_list = list[num_prop_vals]; tmp_list != NULL; 761 tmp_list = tmp_list->lp_next) 762 last = tmp_list; 763 last->lp_next = new_list; 764 } 765 } 766 767 complex_piece: property_name EQUAL TOKEN 768 { 769 if (($$ = alloc_complex()) == NULL) 770 YYERROR; 771 $$->cp_type = $1; 772 $$->cp_value = $3; 773 $$->cp_next = NULL; 774 complex = $$; 775 } 776 | property_name EQUAL TOKEN COMMA complex_piece 777 { 778 if (($$ = alloc_complex()) == NULL) 779 YYERROR; 780 $$->cp_type = $1; 781 $$->cp_value = $3; 782 $$->cp_next = complex; 783 complex = $$; 784 } 785 786 list_piece: simple_prop_val 787 | complex_prop_val 788 | simple_prop_val COMMA list_piece 789 | complex_prop_val COMMA list_piece 790 791 list_prop_val: OPEN_SQ_BRACKET list_piece CLOSE_SQ_BRACKET 792 %% 793