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 ZONENAME ZONEPATH AUTOBOOT POOL NET 62 %token FS IPD ATTR DEVICE RCTL SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL 63 %token NAME MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET 64 %token OPEN_PAREN CLOSE_PAREN COMMA DATASET 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 ZONENAME 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 ZONENAME 406 { 407 if (($$ = alloc_cmd()) == NULL) 408 YYERROR; 409 cmd = $$; 410 $$->cmd_handler = &info_func; 411 $$->cmd_res_type = RT_ZONENAME; 412 $$->cmd_prop_nv_pairs = 0; 413 } 414 | INFO ZONEPATH 415 { 416 if (($$ = alloc_cmd()) == NULL) 417 YYERROR; 418 cmd = $$; 419 $$->cmd_handler = &info_func; 420 $$->cmd_res_type = RT_ZONEPATH; 421 $$->cmd_prop_nv_pairs = 0; 422 } 423 | INFO AUTOBOOT 424 { 425 if (($$ = alloc_cmd()) == NULL) 426 YYERROR; 427 cmd = $$; 428 $$->cmd_handler = &info_func; 429 $$->cmd_res_type = RT_AUTOBOOT; 430 $$->cmd_prop_nv_pairs = 0; 431 } 432 | INFO POOL 433 { 434 if (($$ = alloc_cmd()) == NULL) 435 YYERROR; 436 cmd = $$; 437 $$->cmd_handler = &info_func; 438 $$->cmd_res_type = RT_POOL; 439 $$->cmd_prop_nv_pairs = 0; 440 } 441 | INFO resource_type 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 = 1; 449 $$->cmd_prop_name[0] = $3; 450 $$->cmd_property_ptr[0] = &property[0]; 451 } 452 | INFO resource_type property_name EQUAL property_value property_name EQUAL property_value 453 { 454 if (($$ = alloc_cmd()) == NULL) 455 YYERROR; 456 cmd = $$; 457 $$->cmd_handler = &info_func; 458 $$->cmd_res_type = $2; 459 $$->cmd_prop_nv_pairs = 2; 460 $$->cmd_prop_name[0] = $3; 461 $$->cmd_property_ptr[0] = &property[0]; 462 $$->cmd_prop_name[1] = $6; 463 $$->cmd_property_ptr[1] = &property[1]; 464 } 465 | INFO resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value 466 { 467 if (($$ = alloc_cmd()) == NULL) 468 YYERROR; 469 cmd = $$; 470 $$->cmd_handler = &info_func; 471 $$->cmd_res_type = $2; 472 $$->cmd_prop_nv_pairs = 3; 473 $$->cmd_prop_name[0] = $3; 474 $$->cmd_property_ptr[0] = &property[0]; 475 $$->cmd_prop_name[1] = $6; 476 $$->cmd_property_ptr[1] = &property[1]; 477 $$->cmd_prop_name[2] = $9; 478 $$->cmd_property_ptr[2] = &property[2]; 479 } 480 481 remove_command: REMOVE 482 { 483 short_usage(CMD_REMOVE); 484 (void) fputs("\n", stderr); 485 usage(FALSE, HELP_RES_PROPS); 486 YYERROR; 487 } 488 | REMOVE resource_type 489 { 490 short_usage(CMD_REMOVE); 491 YYERROR; 492 } 493 | REMOVE property_name property_value 494 { 495 if (($$ = alloc_cmd()) == NULL) 496 YYERROR; 497 cmd = $$; 498 $$->cmd_handler = &remove_func; 499 $$->cmd_prop_nv_pairs = 1; 500 $$->cmd_prop_name[0] = $2; 501 $$->cmd_property_ptr[0] = &property[0]; 502 } 503 | REMOVE resource_type 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 = 1; 511 $$->cmd_prop_name[0] = $3; 512 $$->cmd_property_ptr[0] = &property[0]; 513 } 514 | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value 515 { 516 if (($$ = alloc_cmd()) == NULL) 517 YYERROR; 518 cmd = $$; 519 $$->cmd_handler = &remove_func; 520 $$->cmd_res_type = $2; 521 $$->cmd_prop_nv_pairs = 2; 522 $$->cmd_prop_name[0] = $3; 523 $$->cmd_property_ptr[0] = &property[0]; 524 $$->cmd_prop_name[1] = $6; 525 $$->cmd_property_ptr[1] = &property[1]; 526 } 527 | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value 528 { 529 if (($$ = alloc_cmd()) == NULL) 530 YYERROR; 531 cmd = $$; 532 $$->cmd_handler = &remove_func; 533 $$->cmd_res_type = $2; 534 $$->cmd_prop_nv_pairs = 3; 535 $$->cmd_prop_name[0] = $3; 536 $$->cmd_property_ptr[0] = &property[0]; 537 $$->cmd_prop_name[1] = $6; 538 $$->cmd_property_ptr[1] = &property[1]; 539 $$->cmd_prop_name[2] = $9; 540 $$->cmd_property_ptr[2] = &property[2]; 541 } 542 543 revert_command: REVERT 544 { 545 if (($$ = alloc_cmd()) == NULL) 546 YYERROR; 547 cmd = $$; 548 $$->cmd_handler = &revert_func; 549 $$->cmd_argc = 0; 550 $$->cmd_argv[0] = NULL; 551 } 552 | REVERT TOKEN 553 { 554 if (($$ = alloc_cmd()) == NULL) 555 YYERROR; 556 cmd = $$; 557 $$->cmd_handler = &revert_func; 558 $$->cmd_argc = 1; 559 $$->cmd_argv[0] = $2; 560 $$->cmd_argv[1] = NULL; 561 } 562 563 select_command: SELECT 564 { 565 short_usage(CMD_SELECT); 566 (void) fputs("\n", stderr); 567 usage(FALSE, HELP_RES_PROPS); 568 YYERROR; 569 } 570 | SELECT resource_type 571 { 572 short_usage(CMD_SELECT); 573 YYERROR; 574 } 575 | SELECT resource_type 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 = 1; 583 $$->cmd_prop_name[0] = $3; 584 $$->cmd_property_ptr[0] = &property[0]; 585 } 586 | SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value 587 { 588 if (($$ = alloc_cmd()) == NULL) 589 YYERROR; 590 cmd = $$; 591 $$->cmd_handler = &select_func; 592 $$->cmd_res_type = $2; 593 $$->cmd_prop_nv_pairs = 2; 594 $$->cmd_prop_name[0] = $3; 595 $$->cmd_property_ptr[0] = &property[0]; 596 $$->cmd_prop_name[1] = $6; 597 $$->cmd_property_ptr[1] = &property[1]; 598 } 599 | SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value 600 { 601 if (($$ = alloc_cmd()) == NULL) 602 YYERROR; 603 cmd = $$; 604 $$->cmd_handler = &select_func; 605 $$->cmd_res_type = $2; 606 $$->cmd_prop_nv_pairs = 3; 607 $$->cmd_prop_name[0] = $3; 608 $$->cmd_property_ptr[0] = &property[0]; 609 $$->cmd_prop_name[1] = $6; 610 $$->cmd_property_ptr[1] = &property[1]; 611 $$->cmd_prop_name[2] = $9; 612 $$->cmd_property_ptr[2] = &property[2]; 613 } 614 615 set_command: SET 616 { 617 short_usage(CMD_SET); 618 (void) fputs("\n", stderr); 619 usage(FALSE, HELP_PROPS); 620 YYERROR; 621 } 622 | SET property_name EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET 623 { 624 if (($$ = alloc_cmd()) == NULL) 625 YYERROR; 626 cmd = $$; 627 $$->cmd_handler = &set_func; 628 $$->cmd_prop_nv_pairs = 0; 629 $$->cmd_prop_name[0] = $2; 630 property[0].pv_type = PROP_VAL_LIST; 631 property[0].pv_list = NULL; 632 $$->cmd_property_ptr[0] = &property[0]; 633 } 634 | SET property_name EQUAL property_value 635 { 636 if (($$ = alloc_cmd()) == NULL) 637 YYERROR; 638 cmd = $$; 639 $$->cmd_handler = &set_func; 640 $$->cmd_prop_nv_pairs = 1; 641 $$->cmd_prop_name[0] = $2; 642 $$->cmd_property_ptr[0] = &property[0]; 643 } 644 645 verify_command: VERIFY 646 { 647 if (($$ = alloc_cmd()) == NULL) 648 YYERROR; 649 cmd = $$; 650 $$->cmd_handler = &verify_func; 651 $$->cmd_argc = 0; 652 $$->cmd_argv[0] = NULL; 653 } 654 | VERIFY TOKEN 655 { 656 if (($$ = alloc_cmd()) == NULL) 657 YYERROR; 658 cmd = $$; 659 $$->cmd_handler = &verify_func; 660 $$->cmd_argc = 1; 661 $$->cmd_argv[0] = $2; 662 $$->cmd_argv[1] = NULL; 663 } 664 665 resource_type: NET { $$ = RT_NET; } 666 | FS { $$ = RT_FS; } 667 | IPD { $$ = RT_IPD; } 668 | DEVICE { $$ = RT_DEVICE; } 669 | RCTL { $$ = RT_RCTL; } 670 | ATTR { $$ = RT_ATTR; } 671 | DATASET { $$ = RT_DATASET; } 672 673 property_name: SPECIAL { $$ = PT_SPECIAL; } 674 | RAW { $$ = PT_RAW; } 675 | DIR { $$ = PT_DIR; } 676 | TYPE { $$ = PT_TYPE; } 677 | OPTIONS { $$ = PT_OPTIONS; } 678 | ZONENAME { $$ = PT_ZONENAME; } 679 | ZONEPATH { $$ = PT_ZONEPATH; } 680 | AUTOBOOT { $$ = PT_AUTOBOOT; } 681 | POOL { $$ = PT_POOL; } 682 | ADDRESS { $$ = PT_ADDRESS; } 683 | PHYSICAL { $$ = PT_PHYSICAL; } 684 | NAME { $$ = PT_NAME; } 685 | VALUE { $$ = PT_VALUE; } 686 | MATCH { $$ = PT_MATCH; } 687 | PRIV { $$ = PT_PRIV; } 688 | LIMIT { $$ = PT_LIMIT; } 689 | ACTION { $$ = PT_ACTION; } 690 691 /* 692 * The grammar builds data structures from the bottom up. Thus various 693 * strings are lexed into TOKENs or commands or resource or property values. 694 * Below is where the resource and property values are built up into more 695 * complex data structures. 696 * 697 * There are three kinds of properties: simple (single valued), complex 698 * (one or more name=value pairs) and list (concatenation of one or more 699 * simple or complex properties). 700 * 701 * So the property structure has a type which is one of these, and the 702 * corresponding _simple, _complex or _list is set to the corresponding 703 * lower-level data structure. 704 */ 705 706 property_value: simple_prop_val 707 { 708 property[num_prop_vals].pv_type = PROP_VAL_SIMPLE; 709 property[num_prop_vals].pv_simple = $1; 710 if (list[num_prop_vals] != NULL) { 711 free_outer_list(list[num_prop_vals]); 712 list[num_prop_vals] = NULL; 713 } 714 num_prop_vals++; 715 } 716 | complex_prop_val 717 { 718 property[num_prop_vals].pv_type = PROP_VAL_COMPLEX; 719 property[num_prop_vals].pv_complex = complex; 720 if (list[num_prop_vals] != NULL) { 721 free_outer_list(list[num_prop_vals]); 722 list[num_prop_vals] = NULL; 723 } 724 num_prop_vals++; 725 } 726 | list_prop_val 727 { 728 property[num_prop_vals].pv_type = PROP_VAL_LIST; 729 property[num_prop_vals].pv_list = list[num_prop_vals]; 730 num_prop_vals++; 731 } 732 733 /* 734 * One level lower, lists are made up of simple or complex values, so 735 * simple_prop_val and complex_prop_val fill in a list structure and 736 * insert it into the linked list which is built up. And because 737 * complex properties can have multiple name=value pairs, we keep 738 * track of them in another linked list. 739 * 740 * The complex and list structures for the linked lists are allocated 741 * below, and freed by recursive functions which are ultimately called 742 * by free_cmd(), which is called from the top-most "commands" part of 743 * the grammar. 744 */ 745 746 simple_prop_val: TOKEN 747 { 748 if ((new_list = alloc_list()) == NULL) 749 YYERROR; 750 new_list->lp_simple = $1; 751 new_list->lp_complex = NULL; 752 new_list->lp_next = NULL; 753 if (list[num_prop_vals] == NULL) { 754 list[num_prop_vals] = new_list; 755 } else { 756 for (tmp_list = list[num_prop_vals]; tmp_list != NULL; 757 tmp_list = tmp_list->lp_next) 758 last = tmp_list; 759 last->lp_next = new_list; 760 } 761 } 762 763 complex_prop_val: OPEN_PAREN complex_piece CLOSE_PAREN 764 { 765 if ((new_list = alloc_list()) == NULL) 766 YYERROR; 767 new_list->lp_simple = NULL; 768 new_list->lp_complex = complex; 769 new_list->lp_next = NULL; 770 if (list[num_prop_vals] == NULL) { 771 list[num_prop_vals] = new_list; 772 } else { 773 for (tmp_list = list[num_prop_vals]; tmp_list != NULL; 774 tmp_list = tmp_list->lp_next) 775 last = tmp_list; 776 last->lp_next = new_list; 777 } 778 } 779 780 complex_piece: property_name EQUAL TOKEN 781 { 782 if (($$ = alloc_complex()) == NULL) 783 YYERROR; 784 $$->cp_type = $1; 785 $$->cp_value = $3; 786 $$->cp_next = NULL; 787 complex = $$; 788 } 789 | property_name EQUAL TOKEN COMMA complex_piece 790 { 791 if (($$ = alloc_complex()) == NULL) 792 YYERROR; 793 $$->cp_type = $1; 794 $$->cp_value = $3; 795 $$->cp_next = complex; 796 complex = $$; 797 } 798 799 list_piece: simple_prop_val 800 | complex_prop_val 801 | simple_prop_val COMMA list_piece 802 | complex_prop_val COMMA list_piece 803 804 list_prop_val: OPEN_SQ_BRACKET list_piece CLOSE_SQ_BRACKET 805 %% 806