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