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 (the "License").
   7  * You may not use this file except in compliance with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  25  * Copyright 2013, Joyent Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * This file defines zonecfg(1M)'s grammar.
  30  *
  31  * Reduction rules that consume TOKENs must invoke claim_token() immediately
  32  * before freeing the TOKENs or adding them to data structures (e.g., cmd) that
  33  * will be cleaned up when the parser finishes or encounters errors.
  34  */
  35 
  36 #include <stdio.h>
  37 #include <strings.h>
  38 
  39 #include "zonecfg.h"
  40 
  41 static cmd_t *cmd = NULL;               /* Command being processed */
  42 static complex_property_ptr_t complex = NULL;
  43 static list_property_ptr_t new_list = NULL, tmp_list, last,
  44     list[MAX_EQ_PROP_PAIRS];
  45 static property_value_t property[MAX_EQ_PROP_PAIRS];
  46 
  47 extern boolean_t newline_terminated;
  48 extern int num_prop_vals;               /* # of property values */
  49 
  50 /* yacc externals */
  51 extern int yydebug;
  52 extern void yyerror(char *s);
  53 
  54 /*
  55  * This function is used by the simple_prop_val reduction rules to set up
  56  * a list_property_ptr_t and adjust the above global variables appropriately.
  57  * Note that this function duplicates the specified string and makes
  58  * the new list's lp_simple field point to the duplicate.  This function does
  59  * not free the original string.
  60  *
  61  * This function returns a pointer to the duplicated string or NULL if an error
  62  * occurred.  The simple_prop_val reduction rules that invoke this function
  63  * should set $$ to the returned pointer.
  64  */
  65 static char *
  66 simple_prop_val_func(const char *str)
  67 {
  68         char *retstr;
  69 
  70         if ((new_list = alloc_list()) == NULL)
  71                 return (NULL);
  72         if ((retstr = strdup(str)) == NULL) {
  73                 free_list(new_list);
  74                 return (NULL);
  75         }
  76         new_list->lp_simple = retstr;
  77         new_list->lp_complex = NULL;
  78         new_list->lp_next = NULL;
  79         if (list[num_prop_vals] == NULL) {
  80                 list[num_prop_vals] = new_list;
  81         } else {
  82                 for (tmp_list = list[num_prop_vals]; tmp_list != NULL;
  83                     tmp_list = tmp_list->lp_next)
  84                         last = tmp_list;
  85                 last->lp_next = new_list;
  86         }
  87         return (retstr);
  88 }
  89 
  90 /*
  91  * This function is used by the complex_piece reduction rules to set up a
  92  * complex_property_prt_t and adjust the above global variables appropriately.
  93  * Note that this function duplicates the specified string and makes the new
  94  * complex_property_ptr_t's cp_value field point to the duplicate.  It also sets
  95  * the complex_property_ptr_t's cp_type field to cp_type and its cp_next field
  96  * to cp_next.  This function does not free the original string.
  97  *
  98  * This function returns a pointer to the complex_property_t created for the
  99  * complex_piece or NULL if an error occurred.  The complex_piece reduction
 100  * rules that invoke this function should set $$ to the returned pointer.
 101  */
 102 static complex_property_ptr_t
 103 complex_piece_func(int cp_type, const char *str, complex_property_ptr_t cp_next)
 104 {
 105         complex_property_ptr_t retval;
 106 
 107         if ((retval = alloc_complex()) == NULL)
 108                 return (NULL);
 109         if ((retval->cp_value = strdup(str)) == NULL) {
 110                 free_complex(retval);
 111                 return (NULL);
 112         }
 113         retval->cp_type = cp_type;
 114         retval->cp_next = cp_next;
 115         complex = retval;
 116         return (retval);
 117 }
 118 
 119 
 120 %}
 121 
 122 %union {
 123         int ival;
 124         char *strval;
 125         cmd_t *cmd;
 126         complex_property_ptr_t complex;
 127         list_property_ptr_t list;
 128 }
 129 
 130 %start commands
 131 
 132 %token HELP CREATE EXPORT ADD DELETE REMOVE SELECT SET INFO CANCEL END VERIFY
 133 %token COMMIT REVERT EXIT SEMICOLON TOKEN ZONENAME ZONEPATH AUTOBOOT POOL NET
 134 %token FS ATTR DEVICE RCTL SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL
 135 %token IPTYPE HOSTID FS_ALLOWED ALLOWED_ADDRESS
 136 %token NAME MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
 137 %token OPEN_PAREN CLOSE_PAREN COMMA DATASET LIMITPRIV BOOTARGS BRAND PSET PCAP
 138 %token MCAP NCPUS IMPORTANCE SHARES MAXLWPS MAXSHMMEM MAXSHMIDS MAXMSGIDS
 139 %token MAXSEMIDS LOCKED SWAP SCHED CLEAR DEFROUTER ADMIN USER AUTHS MAXPROCS
 140 %token ZFSPRI MAC VLANID GNIC NPROP UUID
 141 
 142 %type <strval> TOKEN EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
 143     property_value OPEN_PAREN CLOSE_PAREN COMMA simple_prop_val
 144 %type <complex> complex_piece complex_prop_val
 145 %type <ival> resource_type NET FS DEVICE RCTL ATTR DATASET PSET PCAP MCAP
 146     ADMIN
 147 %type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME
 148     MATCH ZONENAME ZONEPATH AUTOBOOT POOL LIMITPRIV BOOTARGS VALUE PRIV LIMIT
 149     ACTION BRAND SCHED IPTYPE DEFROUTER HOSTID USER AUTHS FS_ALLOWED
 150     ALLOWED_ADDRESS MAC VLANID GNIC NPROP UUID
 151 %type <cmd> command
 152 %type <cmd> add_command ADD
 153 %type <cmd> cancel_command CANCEL
 154 %type <cmd> commit_command COMMIT
 155 %type <cmd> create_command CREATE
 156 %type <cmd> delete_command DELETE
 157 %type <cmd> end_command END
 158 %type <cmd> exit_command EXIT
 159 %type <cmd> export_command EXPORT
 160 %type <cmd> help_command HELP
 161 %type <cmd> info_command INFO
 162 %type <cmd> remove_command REMOVE
 163 %type <cmd> revert_command REVERT
 164 %type <cmd> select_command SELECT
 165 %type <cmd> set_command SET
 166 %type <cmd> clear_command CLEAR
 167 %type <cmd> verify_command VERIFY
 168 %type <cmd> terminator
 169 
 170 %%
 171 
 172 /*
 173  * NOTE: Each commands reduction rule must invoke assert_no_unclaimed_tokens()
 174  * before it completes if it isn't processing an error.  This ensures that
 175  * reduction rules properly consume TOKENs.
 176  */
 177 commands: command terminator
 178         {
 179                 if ($1 != NULL) {
 180                         if ($1->cmd_handler != NULL)
 181                                 $1->cmd_handler($1);
 182                         free_cmd($1);
 183                         bzero(list, sizeof (list_property_t));
 184                         num_prop_vals = 0;
 185                 }
 186                 assert_no_unclaimed_tokens();
 187                 return (0);
 188         }
 189         | command error terminator
 190         {
 191                 if ($1 != NULL) {
 192                         free_cmd($1);
 193                         bzero(list, sizeof (list_property_t));
 194                         num_prop_vals = 0;
 195                 }
 196                 if (YYRECOVERING())
 197                         YYABORT;
 198                 yyclearin;
 199                 yyerrok;
 200         }
 201         | error terminator
 202         {
 203                 if (YYRECOVERING())
 204                         YYABORT;
 205                 yyclearin;
 206                 yyerrok;
 207         }
 208         | terminator
 209         {
 210                 assert_no_unclaimed_tokens();
 211                 return (0);
 212         }
 213 
 214 command: add_command
 215         | cancel_command
 216         | clear_command
 217         | create_command
 218         | commit_command
 219         | delete_command
 220         | end_command
 221         | exit_command
 222         | export_command
 223         | help_command
 224         | info_command
 225         | remove_command
 226         | revert_command
 227         | select_command
 228         | set_command
 229         | verify_command
 230 
 231 terminator:     '\n'    { newline_terminated = B_TRUE; }
 232         |       ';'     { newline_terminated = B_FALSE; }
 233 
 234 add_command: ADD
 235         {
 236                 short_usage(CMD_ADD);
 237                 (void) fputs("\n", stderr);
 238                 usage(B_FALSE, HELP_RES_PROPS);
 239                 YYERROR;
 240         }
 241         | ADD TOKEN
 242         {
 243                 if (($$ = alloc_cmd()) == NULL)
 244                         YYERROR;
 245                 cmd = $$;
 246                 $$->cmd_handler = &add_func;
 247                 $$->cmd_argc = 1;
 248                 $$->cmd_argv[0] = claim_token($2);
 249                 $$->cmd_argv[1] = NULL;
 250         }
 251         | ADD resource_type
 252         {
 253                 if (($$ = alloc_cmd()) == NULL)
 254                         YYERROR;
 255                 cmd = $$;
 256                 $$->cmd_handler = &add_func;
 257                 $$->cmd_argc = 0;
 258                 $$->cmd_res_type = $2;
 259                 $$->cmd_prop_nv_pairs = 0;
 260         }
 261         | ADD property_name property_value
 262         {
 263                 if (($$ = alloc_cmd()) == NULL)
 264                         YYERROR;
 265                 cmd = $$;
 266                 $$->cmd_handler = &add_func;
 267                 $$->cmd_argc = 0;
 268                 $$->cmd_prop_nv_pairs = 1;
 269                 $$->cmd_prop_name[0] = $2;
 270                 $$->cmd_property_ptr[0] = &property[0];
 271         }
 272 
 273 cancel_command: CANCEL
 274         {
 275                 if (($$ = alloc_cmd()) == NULL)
 276                         YYERROR;
 277                 cmd = $$;
 278                 $$->cmd_handler = &cancel_func;
 279                 $$->cmd_argc = 0;
 280                 $$->cmd_argv[0] = NULL;
 281         }
 282         | CANCEL TOKEN
 283         {
 284                 if (($$ = alloc_cmd()) == NULL)
 285                         YYERROR;
 286                 cmd = $$;
 287                 $$->cmd_handler = &cancel_func;
 288                 $$->cmd_argc = 1;
 289                 $$->cmd_argv[0] = claim_token($2);
 290                 $$->cmd_argv[1] = NULL;
 291         }
 292 
 293 create_command: CREATE
 294         {
 295                 if (($$ = alloc_cmd()) == NULL)
 296                         YYERROR;
 297                 cmd = $$;
 298                 $$->cmd_handler = &create_func;
 299                 $$->cmd_argc = 0;
 300                 $$->cmd_argv[0] = NULL;
 301         }
 302         | CREATE TOKEN
 303         {
 304                 if (($$ = alloc_cmd()) == NULL)
 305                         YYERROR;
 306                 cmd = $$;
 307                 $$->cmd_handler = &create_func;
 308                 $$->cmd_argc = 1;
 309                 $$->cmd_argv[0] = claim_token($2);
 310                 $$->cmd_argv[1] = NULL;
 311         }
 312         | CREATE TOKEN TOKEN
 313         {
 314                 if (($$ = alloc_cmd()) == NULL)
 315                         YYERROR;
 316                 cmd = $$;
 317                 $$->cmd_handler = &create_func;
 318                 $$->cmd_argc = 2;
 319                 $$->cmd_argv[0] = claim_token($2);
 320                 $$->cmd_argv[1] = claim_token($3);
 321                 $$->cmd_argv[2] = NULL;
 322         }
 323         | CREATE TOKEN TOKEN TOKEN
 324         {
 325                 if (($$ = alloc_cmd()) == NULL)
 326                         YYERROR;
 327                 cmd = $$;
 328                 $$->cmd_handler = &create_func;
 329                 $$->cmd_argc = 3;
 330                 $$->cmd_argv[0] = claim_token($2);
 331                 $$->cmd_argv[1] = claim_token($3);
 332                 $$->cmd_argv[2] = claim_token($4);
 333                 $$->cmd_argv[3] = NULL;
 334         }
 335 
 336 commit_command: COMMIT
 337         {
 338                 if (($$ = alloc_cmd()) == NULL)
 339                         YYERROR;
 340                 cmd = $$;
 341                 $$->cmd_handler = &commit_func;
 342                 $$->cmd_argc = 0;
 343                 $$->cmd_argv[0] = NULL;
 344         }
 345         | COMMIT TOKEN
 346         {
 347                 if (($$ = alloc_cmd()) == NULL)
 348                         YYERROR;
 349                 cmd = $$;
 350                 $$->cmd_handler = &commit_func;
 351                 $$->cmd_argc = 1;
 352                 $$->cmd_argv[0] = claim_token($2);
 353                 $$->cmd_argv[1] = NULL;
 354         }
 355 
 356 delete_command: DELETE
 357         {
 358                 if (($$ = alloc_cmd()) == NULL)
 359                         YYERROR;
 360                 cmd = $$;
 361                 $$->cmd_handler = &delete_func;
 362                 $$->cmd_argc = 0;
 363                 $$->cmd_argv[0] = NULL;
 364         }
 365         |       DELETE TOKEN
 366         {
 367                 if (($$ = alloc_cmd()) == NULL)
 368                         YYERROR;
 369                 cmd = $$;
 370                 $$->cmd_handler = &delete_func;
 371                 $$->cmd_argc = 1;
 372                 $$->cmd_argv[0] = claim_token($2);
 373                 $$->cmd_argv[1] = NULL;
 374         }
 375 
 376 end_command: END
 377         {
 378                 if (($$ = alloc_cmd()) == NULL)
 379                         YYERROR;
 380                 cmd = $$;
 381                 $$->cmd_handler = &end_func;
 382                 $$->cmd_argc = 0;
 383                 $$->cmd_argv[0] = NULL;
 384         }
 385         | END TOKEN
 386         {
 387                 if (($$ = alloc_cmd()) == NULL)
 388                         YYERROR;
 389                 cmd = $$;
 390                 $$->cmd_handler = &end_func;
 391                 $$->cmd_argc = 1;
 392                 $$->cmd_argv[0] = claim_token($2);
 393                 $$->cmd_argv[1] = NULL;
 394         }
 395 
 396 exit_command: EXIT
 397         {
 398                 if (($$ = alloc_cmd()) == NULL)
 399                         YYERROR;
 400                 cmd = $$;
 401                 $$->cmd_handler = &exit_func;
 402                 $$->cmd_argc = 0;
 403                 $$->cmd_argv[0] = NULL;
 404         }
 405         | EXIT TOKEN
 406         {
 407                 if (($$ = alloc_cmd()) == NULL)
 408                         YYERROR;
 409                 cmd = $$;
 410                 $$->cmd_handler = &exit_func;
 411                 $$->cmd_argc = 1;
 412                 $$->cmd_argv[0] = claim_token($2);
 413                 $$->cmd_argv[1] = NULL;
 414         }
 415 
 416 export_command: EXPORT
 417         {
 418                 if (($$ = alloc_cmd()) == NULL)
 419                         YYERROR;
 420                 cmd = $$;
 421                 $$->cmd_handler = &export_func;
 422                 $$->cmd_argc = 0;
 423                 $$->cmd_argv[0] = NULL;
 424         }
 425         | EXPORT TOKEN
 426         {
 427                 if (($$ = alloc_cmd()) == NULL)
 428                         YYERROR;
 429                 cmd = $$;
 430                 $$->cmd_handler = &export_func;
 431                 $$->cmd_argc = 1;
 432                 $$->cmd_argv[0] = claim_token($2);
 433                 $$->cmd_argv[1] = NULL;
 434         }
 435         | EXPORT TOKEN TOKEN
 436         {
 437                 if (($$ = alloc_cmd()) == NULL)
 438                         YYERROR;
 439                 cmd = $$;
 440                 $$->cmd_handler = &export_func;
 441                 $$->cmd_argc = 2;
 442                 $$->cmd_argv[0] = claim_token($2);
 443                 $$->cmd_argv[1] = claim_token($3);
 444                 $$->cmd_argv[2] = NULL;
 445         }
 446 
 447 help_command:   HELP
 448         {
 449                 if (($$ = alloc_cmd()) == NULL)
 450                         YYERROR;
 451                 cmd = $$;
 452                 $$->cmd_handler = &help_func;
 453                 $$->cmd_argc = 0;
 454                 $$->cmd_argv[0] = NULL;
 455         }
 456         |       HELP TOKEN
 457         {
 458                 if (($$ = alloc_cmd()) == NULL)
 459                         YYERROR;
 460                 cmd = $$;
 461                 $$->cmd_handler = &help_func;
 462                 $$->cmd_argc = 1;
 463                 $$->cmd_argv[0] = claim_token($2);
 464                 $$->cmd_argv[1] = NULL;
 465         }
 466 
 467 info_command:   INFO
 468         {
 469                 if (($$ = alloc_cmd()) == NULL)
 470                         YYERROR;
 471                 cmd = $$;
 472                 $$->cmd_handler = &info_func;
 473                 $$->cmd_res_type = RT_UNKNOWN;
 474                 $$->cmd_prop_nv_pairs = 0;
 475         }
 476         |       INFO TOKEN
 477         {
 478                 short_usage(CMD_INFO);
 479                 (void) fputs("\n", stderr);
 480                 usage(B_FALSE, HELP_RES_PROPS);
 481                 free(claim_token($2));
 482                 YYERROR;
 483         }
 484         |       INFO resource_type
 485         {
 486                 if (($$ = alloc_cmd()) == NULL)
 487                         YYERROR;
 488                 cmd = $$;
 489                 $$->cmd_handler = &info_func;
 490                 $$->cmd_res_type = $2;
 491                 $$->cmd_prop_nv_pairs = 0;
 492         }
 493         |       INFO ZONENAME
 494         {
 495                 if (($$ = alloc_cmd()) == NULL)
 496                         YYERROR;
 497                 cmd = $$;
 498                 $$->cmd_handler = &info_func;
 499                 $$->cmd_res_type = RT_ZONENAME;
 500                 $$->cmd_prop_nv_pairs = 0;
 501         }
 502         |       INFO ZONEPATH
 503         {
 504                 if (($$ = alloc_cmd()) == NULL)
 505                         YYERROR;
 506                 cmd = $$;
 507                 $$->cmd_handler = &info_func;
 508                 $$->cmd_res_type = RT_ZONEPATH;
 509                 $$->cmd_prop_nv_pairs = 0;
 510         }
 511         |       INFO BRAND
 512         {
 513                 if (($$ = alloc_cmd()) == NULL)
 514                         YYERROR;
 515                 cmd = $$;
 516                 $$->cmd_handler = &info_func;
 517                 $$->cmd_res_type = RT_BRAND;
 518                 $$->cmd_prop_nv_pairs = 0;
 519         }
 520         |       INFO AUTOBOOT
 521         {
 522                 if (($$ = alloc_cmd()) == NULL)
 523                         YYERROR;
 524                 cmd = $$;
 525                 $$->cmd_handler = &info_func;
 526                 $$->cmd_res_type = RT_AUTOBOOT;
 527                 $$->cmd_prop_nv_pairs = 0;
 528         }
 529         |       INFO IPTYPE
 530         {
 531                 if (($$ = alloc_cmd()) == NULL)
 532                         YYERROR;
 533                 cmd = $$;
 534                 $$->cmd_handler = &info_func;
 535                 $$->cmd_res_type = RT_IPTYPE;
 536                 $$->cmd_prop_nv_pairs = 0;
 537         }
 538         |       INFO POOL
 539         {
 540                 if (($$ = alloc_cmd()) == NULL)
 541                         YYERROR;
 542                 cmd = $$;
 543                 $$->cmd_handler = &info_func;
 544                 $$->cmd_res_type = RT_POOL;
 545                 $$->cmd_prop_nv_pairs = 0;
 546         }
 547         |       INFO LIMITPRIV
 548         {
 549                 if (($$ = alloc_cmd()) == NULL)
 550                         YYERROR;
 551                 cmd = $$;
 552                 $$->cmd_handler = &info_func;
 553                 $$->cmd_res_type = RT_LIMITPRIV;
 554                 $$->cmd_prop_nv_pairs = 0;
 555         }
 556         |       INFO BOOTARGS
 557         {
 558                 if (($$ = alloc_cmd()) == NULL)
 559                         YYERROR;
 560                 cmd = $$;
 561                 $$->cmd_handler = &info_func;
 562                 $$->cmd_res_type = RT_BOOTARGS;
 563                 $$->cmd_prop_nv_pairs = 0;
 564         }
 565         |       INFO SCHED
 566         {
 567                 if (($$ = alloc_cmd()) == NULL)
 568                         YYERROR;
 569                 cmd = $$;
 570                 $$->cmd_handler = &info_func;
 571                 $$->cmd_res_type = RT_SCHED;
 572                 $$->cmd_prop_nv_pairs = 0;
 573         }
 574         |       INFO SHARES
 575         {
 576                 if (($$ = alloc_cmd()) == NULL)
 577                         YYERROR;
 578                 cmd = $$;
 579                 $$->cmd_handler = &info_func;
 580                 $$->cmd_res_type = RT_SHARES;
 581                 $$->cmd_prop_nv_pairs = 0;
 582         }
 583         |       INFO MAXLWPS
 584         {
 585                 if (($$ = alloc_cmd()) == NULL)
 586                         YYERROR;
 587                 cmd = $$;
 588                 $$->cmd_handler = &info_func;
 589                 $$->cmd_res_type = RT_MAXLWPS;
 590                 $$->cmd_prop_nv_pairs = 0;
 591         }
 592         |       INFO MAXPROCS
 593         {
 594                 if (($$ = alloc_cmd()) == NULL)
 595                         YYERROR;
 596                 cmd = $$;
 597                 $$->cmd_handler = &info_func;
 598                 $$->cmd_res_type = RT_MAXPROCS;
 599                 $$->cmd_prop_nv_pairs = 0;
 600         }
 601         |       INFO MAXSHMMEM
 602         {
 603                 if (($$ = alloc_cmd()) == NULL)
 604                         YYERROR;
 605                 cmd = $$;
 606                 $$->cmd_handler = &info_func;
 607                 $$->cmd_res_type = RT_MAXSHMMEM;
 608                 $$->cmd_prop_nv_pairs = 0;
 609         }
 610         |       INFO MAXSHMIDS
 611         {
 612                 if (($$ = alloc_cmd()) == NULL)
 613                         YYERROR;
 614                 cmd = $$;
 615                 $$->cmd_handler = &info_func;
 616                 $$->cmd_res_type = RT_MAXSHMIDS;
 617                 $$->cmd_prop_nv_pairs = 0;
 618         }
 619         |       INFO MAXMSGIDS
 620         {
 621                 if (($$ = alloc_cmd()) == NULL)
 622                         YYERROR;
 623                 cmd = $$;
 624                 $$->cmd_handler = &info_func;
 625                 $$->cmd_res_type = RT_MAXMSGIDS;
 626                 $$->cmd_prop_nv_pairs = 0;
 627         }
 628         |       INFO MAXSEMIDS
 629         {
 630                 if (($$ = alloc_cmd()) == NULL)
 631                         YYERROR;
 632                 cmd = $$;
 633                 $$->cmd_handler = &info_func;
 634                 $$->cmd_res_type = RT_MAXSEMIDS;
 635                 $$->cmd_prop_nv_pairs = 0;
 636         }
 637         |       INFO HOSTID
 638         {
 639                 if (($$ = alloc_cmd()) == NULL)
 640                         YYERROR;
 641                 cmd = $$;
 642                 $$->cmd_handler = &info_func;
 643                 $$->cmd_res_type = RT_HOSTID;
 644                 $$->cmd_prop_nv_pairs = 0;
 645         }
 646         |       INFO FS_ALLOWED
 647         {
 648                 if (($$ = alloc_cmd()) == NULL)
 649                         YYERROR;
 650                 cmd = $$;
 651                 $$->cmd_handler = &info_func;
 652                 $$->cmd_res_type = RT_FS_ALLOWED;
 653                 $$->cmd_prop_nv_pairs = 0;
 654         }
 655         |       INFO UUID
 656         {
 657                 if (($$ = alloc_cmd()) == NULL)
 658                         YYERROR;
 659                 cmd = $$;
 660                 $$->cmd_handler = &info_func;
 661                 $$->cmd_res_type = RT_UUID;
 662                 $$->cmd_prop_nv_pairs = 0;
 663         }
 664         |       INFO ZFSPRI
 665         {
 666                 if (($$ = alloc_cmd()) == NULL)
 667                         YYERROR;
 668                 cmd = $$;
 669                 $$->cmd_handler = &info_func;
 670                 $$->cmd_res_type = RT_ZFSPRI;
 671                 $$->cmd_prop_nv_pairs = 0;
 672         }
 673         |       INFO resource_type property_name EQUAL property_value
 674         {
 675                 if (($$ = alloc_cmd()) == NULL)
 676                         YYERROR;
 677                 cmd = $$;
 678                 $$->cmd_handler = &info_func;
 679                 $$->cmd_res_type = $2;
 680                 $$->cmd_prop_nv_pairs = 1;
 681                 $$->cmd_prop_name[0] = $3;
 682                 $$->cmd_property_ptr[0] = &property[0];
 683         }
 684         |       INFO resource_type property_name EQUAL property_value property_name EQUAL property_value
 685         {
 686                 if (($$ = alloc_cmd()) == NULL)
 687                         YYERROR;
 688                 cmd = $$;
 689                 $$->cmd_handler = &info_func;
 690                 $$->cmd_res_type = $2;
 691                 $$->cmd_prop_nv_pairs = 2;
 692                 $$->cmd_prop_name[0] = $3;
 693                 $$->cmd_property_ptr[0] = &property[0];
 694                 $$->cmd_prop_name[1] = $6;
 695                 $$->cmd_property_ptr[1] = &property[1];
 696         }
 697         |       INFO resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value
 698         {
 699                 if (($$ = alloc_cmd()) == NULL)
 700                         YYERROR;
 701                 cmd = $$;
 702                 $$->cmd_handler = &info_func;
 703                 $$->cmd_res_type = $2;
 704                 $$->cmd_prop_nv_pairs = 3;
 705                 $$->cmd_prop_name[0] = $3;
 706                 $$->cmd_property_ptr[0] = &property[0];
 707                 $$->cmd_prop_name[1] = $6;
 708                 $$->cmd_property_ptr[1] = &property[1];
 709                 $$->cmd_prop_name[2] = $9;
 710                 $$->cmd_property_ptr[2] = &property[2];
 711         }
 712 
 713 remove_command: REMOVE
 714         {
 715                 short_usage(CMD_REMOVE);
 716                 (void) fputs("\n", stderr);
 717                 usage(B_FALSE, HELP_RES_PROPS);
 718                 YYERROR;
 719         }
 720         | REMOVE TOKEN
 721         {
 722                 short_usage(CMD_REMOVE);
 723                 (void) fputs("\n", stderr);
 724                 usage(B_FALSE, HELP_RES_PROPS);
 725                 free(claim_token($2));
 726                 YYERROR;
 727         }
 728         | REMOVE resource_type
 729         {
 730                 if (($$ = alloc_cmd()) == NULL)
 731                         YYERROR;
 732                 cmd = $$;
 733                 $$->cmd_handler = &remove_func;
 734                 $$->cmd_res_type = $2;
 735         }
 736         | REMOVE TOKEN resource_type
 737         {
 738                 if (($$ = alloc_cmd()) == NULL)
 739                         YYERROR;
 740                 cmd = $$;
 741                 $$->cmd_handler = &remove_func;
 742                 $$->cmd_res_type = $3;
 743                 $$->cmd_argc = 1;
 744                 $$->cmd_argv[0] = claim_token($2);
 745                 $$->cmd_argv[1] = NULL;
 746         }
 747         | REMOVE property_name property_value
 748         {
 749                 if (($$ = alloc_cmd()) == NULL)
 750                         YYERROR;
 751                 cmd = $$;
 752                 $$->cmd_handler = &remove_func;
 753                 $$->cmd_prop_nv_pairs = 1;
 754                 $$->cmd_prop_name[0] = $2;
 755                 $$->cmd_property_ptr[0] = &property[0];
 756         }
 757         | REMOVE TOKEN property_name property_value
 758         {
 759                 if (($$ = alloc_cmd()) == NULL)
 760                         YYERROR;
 761                 cmd = $$;
 762                 $$->cmd_handler = &remove_func;
 763                 $$->cmd_argc = 1;
 764                 $$->cmd_argv[0] = claim_token($2);
 765                 $$->cmd_argv[1] = NULL;
 766                 $$->cmd_prop_nv_pairs = 1;
 767                 $$->cmd_prop_name[0] = $3;
 768                 $$->cmd_property_ptr[0] = &property[0];
 769         }
 770         | REMOVE resource_type property_name EQUAL property_value
 771         {
 772                 if (($$ = alloc_cmd()) == NULL)
 773                         YYERROR;
 774                 cmd = $$;
 775                 $$->cmd_handler = &remove_func;
 776                 $$->cmd_res_type = $2;
 777                 $$->cmd_prop_nv_pairs = 1;
 778                 $$->cmd_prop_name[0] = $3;
 779                 $$->cmd_property_ptr[0] = &property[0];
 780         }
 781         | REMOVE TOKEN resource_type property_name EQUAL property_value
 782         {
 783                 if (($$ = alloc_cmd()) == NULL)
 784                         YYERROR;
 785                 cmd = $$;
 786                 $$->cmd_handler = &remove_func;
 787                 $$->cmd_res_type = $3;
 788                 $$->cmd_argc = 1;
 789                 $$->cmd_argv[0] = claim_token($2);
 790                 $$->cmd_argv[1] = NULL;
 791                 $$->cmd_prop_nv_pairs = 1;
 792                 $$->cmd_prop_name[0] = $4;
 793                 $$->cmd_property_ptr[0] = &property[0];
 794         }
 795         | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value
 796         {
 797                 if (($$ = alloc_cmd()) == NULL)
 798                         YYERROR;
 799                 cmd = $$;
 800                 $$->cmd_handler = &remove_func;
 801                 $$->cmd_res_type = $2;
 802                 $$->cmd_prop_nv_pairs = 2;
 803                 $$->cmd_prop_name[0] = $3;
 804                 $$->cmd_property_ptr[0] = &property[0];
 805                 $$->cmd_prop_name[1] = $6;
 806                 $$->cmd_property_ptr[1] = &property[1];
 807         }
 808         | REMOVE TOKEN resource_type property_name EQUAL property_value property_name EQUAL property_value
 809         {
 810                 if (($$ = alloc_cmd()) == NULL)
 811                         YYERROR;
 812                 cmd = $$;
 813                 $$->cmd_handler = &remove_func;
 814                 $$->cmd_res_type = $3;
 815                 $$->cmd_argc = 1;
 816                 $$->cmd_argv[0] = claim_token($2);
 817                 $$->cmd_argv[1] = NULL;
 818                 $$->cmd_prop_nv_pairs = 2;
 819                 $$->cmd_prop_name[0] = $4;
 820                 $$->cmd_property_ptr[0] = &property[0];
 821                 $$->cmd_prop_name[1] = $7;
 822                 $$->cmd_property_ptr[1] = &property[1];
 823         }
 824         | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value
 825         {
 826                 if (($$ = alloc_cmd()) == NULL)
 827                         YYERROR;
 828                 cmd = $$;
 829                 $$->cmd_handler = &remove_func;
 830                 $$->cmd_res_type = $2;
 831                 $$->cmd_prop_nv_pairs = 3;
 832                 $$->cmd_prop_name[0] = $3;
 833                 $$->cmd_property_ptr[0] = &property[0];
 834                 $$->cmd_prop_name[1] = $6;
 835                 $$->cmd_property_ptr[1] = &property[1];
 836                 $$->cmd_prop_name[2] = $9;
 837                 $$->cmd_property_ptr[2] = &property[2];
 838         }
 839         | REMOVE TOKEN resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value
 840         {
 841                 if (($$ = alloc_cmd()) == NULL)
 842                         YYERROR;
 843                 cmd = $$;
 844                 $$->cmd_handler = &remove_func;
 845                 $$->cmd_res_type = $3;
 846                 $$->cmd_argc = 1;
 847                 $$->cmd_argv[0] = claim_token($2);
 848                 $$->cmd_argv[1] = NULL;
 849                 $$->cmd_prop_nv_pairs = 3;
 850                 $$->cmd_prop_name[0] = $4;
 851                 $$->cmd_property_ptr[0] = &property[0];
 852                 $$->cmd_prop_name[1] = $7;
 853                 $$->cmd_property_ptr[1] = &property[1];
 854                 $$->cmd_prop_name[2] = $10;
 855                 $$->cmd_property_ptr[2] = &property[2];
 856         }
 857 
 858 revert_command: REVERT
 859         {
 860                 if (($$ = alloc_cmd()) == NULL)
 861                         YYERROR;
 862                 cmd = $$;
 863                 $$->cmd_handler = &revert_func;
 864                 $$->cmd_argc = 0;
 865                 $$->cmd_argv[0] = NULL;
 866         }
 867         | REVERT TOKEN
 868         {
 869                 if (($$ = alloc_cmd()) == NULL)
 870                         YYERROR;
 871                 cmd = $$;
 872                 $$->cmd_handler = &revert_func;
 873                 $$->cmd_argc = 1;
 874                 $$->cmd_argv[0] = claim_token($2);
 875                 $$->cmd_argv[1] = NULL;
 876         }
 877 
 878 select_command: SELECT
 879         {
 880                 short_usage(CMD_SELECT);
 881                 (void) fputs("\n", stderr);
 882                 usage(B_FALSE, HELP_RES_PROPS);
 883                 YYERROR;
 884         }
 885         | SELECT PSET
 886         {
 887                 if (($$ = alloc_cmd()) == NULL)
 888                         YYERROR;
 889                 cmd = $$;
 890                 $$->cmd_handler = &select_func;
 891                 $$->cmd_res_type = RT_DCPU;
 892         }
 893         | SELECT PCAP
 894         {
 895                 if (($$ = alloc_cmd()) == NULL)
 896                         YYERROR;
 897                 cmd = $$;
 898                 $$->cmd_handler = &select_func;
 899                 $$->cmd_res_type = RT_PCAP;
 900         }
 901         | SELECT MCAP
 902         {
 903                 if (($$ = alloc_cmd()) == NULL)
 904                         YYERROR;
 905                 cmd = $$;
 906                 $$->cmd_handler = &select_func;
 907                 $$->cmd_res_type = RT_MCAP;
 908         }
 909         | SELECT resource_type
 910         {
 911                 short_usage(CMD_SELECT);
 912                 YYERROR;
 913         }
 914         | SELECT resource_type property_name EQUAL property_value
 915         {
 916                 if (($$ = alloc_cmd()) == NULL)
 917                         YYERROR;
 918                 cmd = $$;
 919                 $$->cmd_handler = &select_func;
 920                 $$->cmd_res_type = $2;
 921                 $$->cmd_prop_nv_pairs = 1;
 922                 $$->cmd_prop_name[0] = $3;
 923                 $$->cmd_property_ptr[0] = &property[0];
 924         }
 925         | SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value
 926         {
 927                 if (($$ = alloc_cmd()) == NULL)
 928                         YYERROR;
 929                 cmd = $$;
 930                 $$->cmd_handler = &select_func;
 931                 $$->cmd_res_type = $2;
 932                 $$->cmd_prop_nv_pairs = 2;
 933                 $$->cmd_prop_name[0] = $3;
 934                 $$->cmd_property_ptr[0] = &property[0];
 935                 $$->cmd_prop_name[1] = $6;
 936                 $$->cmd_property_ptr[1] = &property[1];
 937         }
 938         | SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value
 939         {
 940                 if (($$ = alloc_cmd()) == NULL)
 941                         YYERROR;
 942                 cmd = $$;
 943                 $$->cmd_handler = &select_func;
 944                 $$->cmd_res_type = $2;
 945                 $$->cmd_prop_nv_pairs = 3;
 946                 $$->cmd_prop_name[0] = $3;
 947                 $$->cmd_property_ptr[0] = &property[0];
 948                 $$->cmd_prop_name[1] = $6;
 949                 $$->cmd_property_ptr[1] = &property[1];
 950                 $$->cmd_prop_name[2] = $9;
 951                 $$->cmd_property_ptr[2] = &property[2];
 952         }
 953 
 954 set_command: SET
 955         {
 956                 short_usage(CMD_SET);
 957                 (void) fputs("\n", stderr);
 958                 usage(B_FALSE, HELP_PROPS);
 959                 YYERROR;
 960         }
 961         | SET property_name EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
 962         {
 963                 if (($$ = alloc_cmd()) == NULL)
 964                         YYERROR;
 965                 cmd = $$;
 966                 $$->cmd_handler = &set_func;
 967                 $$->cmd_prop_nv_pairs = 0;
 968                 $$->cmd_prop_name[0] = $2;
 969                 property[0].pv_type = PROP_VAL_LIST;
 970                 property[0].pv_list = NULL;
 971                 $$->cmd_property_ptr[0] = &property[0];
 972         }
 973         | SET property_name EQUAL property_value
 974         {
 975                 if (($$ = alloc_cmd()) == NULL)
 976                         YYERROR;
 977                 cmd = $$;
 978                 $$->cmd_handler = &set_func;
 979                 $$->cmd_prop_nv_pairs = 1;
 980                 $$->cmd_prop_name[0] = $2;
 981                 $$->cmd_property_ptr[0] = &property[0];
 982         }
 983         | SET TOKEN ZONEPATH EQUAL property_value
 984         {
 985                 if (($$ = alloc_cmd()) == NULL)
 986                         YYERROR;
 987                 cmd = $$;
 988                 $$->cmd_argc = 1;
 989                 $$->cmd_argv[0] = claim_token($2);
 990                 $$->cmd_argv[1] = NULL;
 991                 $$->cmd_handler = &set_func;
 992                 $$->cmd_prop_nv_pairs = 1;
 993                 $$->cmd_prop_name[0] = PT_ZONEPATH;
 994                 $$->cmd_property_ptr[0] = &property[0];
 995         }
 996 
 997 clear_command: CLEAR
 998         {
 999                 short_usage(CMD_CLEAR);
1000                 (void) fputs("\n", stderr);
1001                 usage(B_FALSE, HELP_PROPS);
1002                 YYERROR;
1003         }
1004         | CLEAR property_name
1005         {
1006                 if (($$ = alloc_cmd()) == NULL)
1007                         YYERROR;
1008                 cmd = $$;
1009                 $$->cmd_handler = &clear_func;
1010                 $$->cmd_res_type = $2;
1011         }
1012 
1013 verify_command: VERIFY
1014         {
1015                 if (($$ = alloc_cmd()) == NULL)
1016                         YYERROR;
1017                 cmd = $$;
1018                 $$->cmd_handler = &verify_func;
1019                 $$->cmd_argc = 0;
1020                 $$->cmd_argv[0] = NULL;
1021         }
1022         | VERIFY TOKEN
1023         {
1024                 if (($$ = alloc_cmd()) == NULL)
1025                         YYERROR;
1026                 cmd = $$;
1027                 $$->cmd_handler = &verify_func;
1028                 $$->cmd_argc = 1;
1029                 $$->cmd_argv[0] = claim_token($2);
1030                 $$->cmd_argv[1] = NULL;
1031         }
1032 
1033 resource_type: NET      { $$ = RT_NET; }
1034         | FS            { $$ = RT_FS; }
1035         | DEVICE        { $$ = RT_DEVICE; }
1036         | RCTL          { $$ = RT_RCTL; }
1037         | ATTR          { $$ = RT_ATTR; }
1038         | DATASET       { $$ = RT_DATASET; }
1039         | PSET          { $$ = RT_DCPU; }
1040         | PCAP          { $$ = RT_PCAP; }
1041         | MCAP          { $$ = RT_MCAP; }
1042         | ADMIN         { $$ = RT_ADMIN; }
1043 
1044 property_name: SPECIAL  { $$ = PT_SPECIAL; }
1045         | RAW           { $$ = PT_RAW; }
1046         | DIR           { $$ = PT_DIR; }
1047         | TYPE          { $$ = PT_TYPE; }
1048         | OPTIONS       { $$ = PT_OPTIONS; }
1049         | ZONENAME      { $$ = PT_ZONENAME; }
1050         | ZONEPATH      { $$ = PT_ZONEPATH; }
1051         | AUTOBOOT      { $$ = PT_AUTOBOOT; }
1052         | IPTYPE        { $$ = PT_IPTYPE; }
1053         | POOL          { $$ = PT_POOL; }
1054         | LIMITPRIV     { $$ = PT_LIMITPRIV; }
1055         | BOOTARGS      { $$ = PT_BOOTARGS; }
1056         | ADDRESS       { $$ = PT_ADDRESS; }
1057         | ALLOWED_ADDRESS       { $$ = PT_ALLOWED_ADDRESS; }
1058         | PHYSICAL      { $$ = PT_PHYSICAL; }
1059         | DEFROUTER     { $$ = PT_DEFROUTER; }
1060         | MAC           { $$ = PT_MAC; }
1061         | VLANID        { $$ = PT_VLANID; }
1062         | GNIC          { $$ = PT_GNIC; }
1063         | NPROP         { $$ = PT_NPROP; }
1064         | NAME          { $$ = PT_NAME; }
1065         | VALUE         { $$ = PT_VALUE; }
1066         | MATCH         { $$ = PT_MATCH; }
1067         | PRIV          { $$ = PT_PRIV; }
1068         | LIMIT         { $$ = PT_LIMIT; }
1069         | ACTION        { $$ = PT_ACTION; }
1070         | BRAND         { $$ = PT_BRAND; }
1071         | NCPUS         { $$ = PT_NCPUS; }
1072         | LOCKED        { $$ = PT_LOCKED; }
1073         | SWAP          { $$ = PT_SWAP; }
1074         | IMPORTANCE    { $$ = PT_IMPORTANCE; }
1075         | SHARES        { $$ = PT_SHARES; }
1076         | MAXLWPS       { $$ = PT_MAXLWPS; }
1077         | MAXPROCS      { $$ = PT_MAXPROCS; }
1078         | MAXSHMMEM     { $$ = PT_MAXSHMMEM; }
1079         | MAXSHMIDS     { $$ = PT_MAXSHMIDS; }
1080         | MAXMSGIDS     { $$ = PT_MAXMSGIDS; }
1081         | MAXSEMIDS     { $$ = PT_MAXSEMIDS; }
1082         | SCHED         { $$ = PT_SCHED; }
1083         | HOSTID        { $$ = PT_HOSTID; }
1084         | USER          { $$ = PT_USER; }
1085         | AUTHS         { $$ = PT_AUTHS; }
1086         | FS_ALLOWED    { $$ = PT_FS_ALLOWED; }
1087         | UUID          { $$ = PT_UUID; }
1088         | ZFSPRI        { $$ = PT_ZFSPRI; }
1089 
1090 /*
1091  * The grammar builds data structures from the bottom up.  Thus various
1092  * strings are lexed into TOKENs or commands or resource or property values.
1093  * Below is where the resource and property values are built up into more
1094  * complex data structures.
1095  *
1096  * There are three kinds of properties: simple (single valued), complex
1097  * (one or more name=value pairs) and list (concatenation of one or more
1098  * simple or complex properties).
1099  *
1100  * So the property structure has a type which is one of these, and the
1101  * corresponding _simple, _complex or _list is set to the corresponding
1102  * lower-level data structure.
1103  */
1104 
1105 property_value: simple_prop_val
1106         {
1107                 property[num_prop_vals].pv_type = PROP_VAL_SIMPLE;
1108                 property[num_prop_vals].pv_simple = $1;
1109                 if (list[num_prop_vals] != NULL) {
1110                         free_outer_list(list[num_prop_vals]);
1111                         list[num_prop_vals] = NULL;
1112                 }
1113                 num_prop_vals++;
1114         }
1115         | complex_prop_val
1116         {
1117                 property[num_prop_vals].pv_type = PROP_VAL_COMPLEX;
1118                 property[num_prop_vals].pv_complex = complex;
1119                 if (list[num_prop_vals] != NULL) {
1120                         free_outer_list(list[num_prop_vals]);
1121                         list[num_prop_vals] = NULL;
1122                 }
1123                 num_prop_vals++;
1124         }
1125         | list_prop_val
1126         {
1127                 property[num_prop_vals].pv_type = PROP_VAL_LIST;
1128                 property[num_prop_vals].pv_list = list[num_prop_vals];
1129                 num_prop_vals++;
1130         }
1131 
1132 /*
1133  * One level lower, lists are made up of simple or complex values, so
1134  * simple_prop_val and complex_prop_val fill in a list structure and
1135  * insert it into the linked list which is built up.  And because
1136  * complex properties can have multiple name=value pairs, we keep
1137  * track of them in another linked list.
1138  *
1139  * The complex and list structures for the linked lists are allocated
1140  * below, and freed by recursive functions which are ultimately called
1141  * by free_cmd(), which is called from the top-most "commands" part of
1142  * the grammar.
1143  *
1144  * NOTE: simple_prop_val and complex_piece need reduction rules for
1145  * property_name and resource_type so that the parser will accept property names
1146  * and resource type names as property values.
1147  */
1148 
1149 simple_prop_val: TOKEN
1150         {
1151                 $$ = simple_prop_val_func($1);
1152                 free(claim_token($1));
1153                 if ($$ == NULL)
1154                         YYERROR;
1155         }
1156         | resource_type
1157         {
1158                 if (($$ = simple_prop_val_func(res_types[$1])) == NULL)
1159                         YYERROR;
1160         }
1161         | property_name
1162         {
1163                 if (($$ = simple_prop_val_func(prop_types[$1])) == NULL)
1164                         YYERROR;
1165         }
1166 
1167 complex_prop_val: OPEN_PAREN complex_piece CLOSE_PAREN
1168         {
1169                 if ((new_list = alloc_list()) == NULL)
1170                         YYERROR;
1171                 new_list->lp_simple = NULL;
1172                 new_list->lp_complex = complex;
1173                 new_list->lp_next = NULL;
1174                 if (list[num_prop_vals] == NULL) {
1175                         list[num_prop_vals] = new_list;
1176                 } else {
1177                         for (tmp_list = list[num_prop_vals]; tmp_list != NULL;
1178                             tmp_list = tmp_list->lp_next)
1179                                 last = tmp_list;
1180                         last->lp_next = new_list;
1181                 }
1182         }
1183 
1184 complex_piece: property_name EQUAL TOKEN
1185         {
1186                 $$ = complex_piece_func($1, $3, NULL);
1187                 free(claim_token($3));
1188                 if ($$ == NULL)
1189                         YYERROR;
1190         }
1191         | property_name EQUAL resource_type
1192         {
1193                 if (($$ = complex_piece_func($1, res_types[$3], NULL)) == NULL)
1194                         YYERROR;
1195         }
1196         | property_name EQUAL property_name
1197         {
1198                 if (($$ = complex_piece_func($1, prop_types[$3], NULL)) == NULL)
1199                         YYERROR;
1200         }
1201         | property_name EQUAL TOKEN COMMA complex_piece 
1202         {
1203                 $$ = complex_piece_func($1, $3, complex);
1204                 free(claim_token($3));
1205                 if ($$ == NULL)
1206                         YYERROR;
1207         }
1208         | property_name EQUAL resource_type COMMA complex_piece 
1209         {
1210                 if (($$ = complex_piece_func($1, res_types[$3], complex)) ==
1211                     NULL)
1212                         YYERROR;
1213         }
1214         | property_name EQUAL property_name COMMA complex_piece 
1215         {
1216                 if (($$ = complex_piece_func($1, prop_types[$3], complex)) ==
1217                     NULL)
1218                         YYERROR;
1219         }
1220 
1221 list_piece: simple_prop_val
1222         | complex_prop_val
1223         | simple_prop_val COMMA list_piece
1224         | complex_prop_val COMMA list_piece
1225 
1226 list_prop_val: OPEN_SQ_BRACKET list_piece CLOSE_SQ_BRACKET
1227 %%