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