1 
2 # line 2 "poolcfg.y"
3 /*
4  * CDDL HEADER START
5  *
6  * The contents of this file are subject to the terms of the
7  * Common Development and Distribution License, Version 1.0 only
8  * (the "License").  You may not use this file except in compliance
9  * with the License.
10  *
11  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12  * or http://www.opensolaris.org/os/licensing.
13  * See the License for the specific language governing permissions
14  * and limitations under the License.
15  *
16  * When distributing Covered Code, include this CDDL HEADER in each
17  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
18  * If applicable, add the following below this CDDL HEADER, with the
19  * fields enclosed by brackets "[]" replaced with your own identifying
20  * information: Portions Copyright [yyyy] [name of copyright owner]
21  *
22  * CDDL HEADER END
23  *
24  * Copyright 2005 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 /*
31  * Overview of poolcfg(1)
32  *
33  * poolcfg(1) implements a small grammar for manipulating pools configurations.
34  * yacc(1) is used to generate the parser and poolcfg.l contains a simple lexer
35  * (generted by lex(1)) to perform lexical processsing of the input.
36  *
37  * Refer to the poolcfg(1) manpage for more details of the grammar.
38  *
39  * The parser is designed so that all operations implement the same interface.
40  * This allows the parser to simply build up the command (using the cmd
41  * variable) by storing arguments and a pointer to the desired function in the
42  * cmd. The command is executed when the commands production is matched.
43  *
44  * Properties and associations are stored in simple linked lists and processed
45  * in the order submitted by the user.
46  */
47 
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <sys/types.h>
53 #include <locale.h>
54 #include <libintl.h>
55 #include <sys/utsname.h>
56 
57 #include <pool.h>
58 #include "utils.h"
59 #include "poolcfg.h"
60 
61 
62 
63 #define	USAGE1	\
64 "Usage:\n" \
65 "%s -h\n" \
66 "%s -c command [ -d | [ file ] ]\n" \
67 "%s -f command-file [-d | [ file ] ]\n\n"
68 
69 #define	USAGE2	\
70 "command:\n" \
71 "  info [entity name]\n" \
72 "         display configuration (or specified portion) in readable form\n" \
73 "  create entity name [property-list]\n" \
74 "         make an entity of the specified type and name\n" \
75 "  destroy entity name\n" \
76 "         remove the specified entity\n" \
77 "  modify entity name [property-list]\n" \
78 "         change the listed properties on the named entity\n" \
79 "  associate pool name [resource-list]\n" \
80 "         connect one or more resources to a pool, or replace one or more\n" \
81 "         existing connections\n" \
82 "  transfer to resource name [component-list]\n" \
83 "         transfer one or more discreet components to a resource\n" \
84 "  transfer [quantity] from resource src to tgt\n" \
85 "         transfer a resource quantity from src to tgt\n" \
86 "  transfer [quantity] to resource tgt from src\n" \
87 "         transfer a resource quantity to tgt from src\n" \
88 "  discover\n" \
89 "         create a system entity, with one pool entity and resources to\n" \
90 "         match current system configuration\n" \
91 "  rename entity old_name to new_name\n" \
92 "         change the name of the entity on the system to its new name\n\n" \
93 "property-list:\n" \
94 "  ( proptype name = value [ ; proptype name = value ]* )\n" \
95 "         where multiple definitions in the sentence for a given\n" \
96 "         proptype, name pair are ignored; the last one provided is used.\n" \
97 "         For property deletion, use \"~ proptype name\"\n\n" \
98 "resource-list:\n" \
99 "  ( resource name [; resource name ] )\n" \
100 "         where multiple uses of a resource are ignored; the last provided\n" \
101 "         is the one used.\n" \
102 "         There is no deletion syntax for resource lists.\n" \
103 "component-list:\n" \
104 "  ( cpu id [; cpu id ] )\n" \
105 "         where multiple uses of the same component cause the last provided\n" \
106 "         to be the one used.\n" \
107 "         There is no deletion syntax for component lists.\n" \
108 "entity:\n" \
109 "  system | pool | pset | cpu\n" \
110 "         where cpu is only valid for transfer, info and modify commands.\n" \
111 "resource:\n" \
112 "  pset\n\n" \
113 "proptype:\n" \
114 "  boolean | int | uint | string | float\n\n"
115 
116 int dofile = PO_FALSE;			/* poolcfg.l uses this for errors */
117 int conf_edit_error = POE_OK;		/* cached error for error reporting */
118 int conf_edit_errno = 0;		/* cached errno for error reporting */
119 int conf_list_error = POE_OK;		/* cached error for error reporting */
120 int conf_list_errno = 0;		/* cached errno for error reporting */
121 static const char cmdname[] = "poolcfg";
122 static const char cmd_options[] = "c:df:h";
123 static void usage(int);
124 static const char *max_suffix = ".max";
125 static const char *min_suffix = ".min";
126 
127 static const char *conf_file = NULL;	/* Location of target config */
128 static cmd_t *cmd = NULL;		/* Command being processed */
129 static pool_conf_t *conf = NULL;	/* Config to be processed */
130 static int edited = PO_FALSE;		/* Has the configuration been changed */
131 
132 /* yacc externals */
133 extern FILE *yyin;
134 extern int yydebug;
135 extern void yyerror(char *s);
136 
137 /* Utility functions */
138 static void arg_parse(const char *);
139 static void file_parse(const char *);
140 static cmd_t *alloc_cmd(void);
141 static prop_t *alloc_prop(prop_op_t);
142 static assoc_t *alloc_assoc(int, const char *);
143 static void free_cmd(cmd_t *);
144 static void check_conf_name(cmd_t *);
145 static void prop_list_walk(cmd_t *, pool_elem_t *);
146 static void assoc_list_walk(cmd_t *, pool_t *);
147 static void transfer_list_walk(cmd_t *, pool_resource_t *);
148 static void terminate(void);
149 static pool_component_t *get_cpu(const char *);
150 static void process_min_max(pool_resource_t *);
151 
152 /* Info Commands */
153 static void parser_conf_info(cmd_t *);
154 static void parser_pool_info(cmd_t *);
155 static void parser_resource_info(cmd_t *, const char *);
156 static void parser_pset_info(cmd_t *);
157 static void parser_cpu_info(cmd_t *);
158 
159 /* Create Commands */
160 static void parser_conf_create(cmd_t *);
161 static void parser_pool_create(cmd_t *);
162 static void parser_resource_create(cmd_t *, const char *);
163 static void parser_pset_create(cmd_t *);
164 
165 /* Destroy Commands */
166 static void parser_conf_destroy(cmd_t *);
167 static void parser_pool_destroy(cmd_t *);
168 static void parser_resource_destroy(cmd_t *, const char *);
169 static void parser_pset_destroy(cmd_t *);
170 
171 /* Modify Commands */
172 static void parser_conf_modify(cmd_t *);
173 static void parser_pool_modify(cmd_t *);
174 static void parser_resource_modify(cmd_t *, const char *);
175 static void parser_pset_modify(cmd_t *);
176 static void parser_cpu_modify(cmd_t *);
177 
178 /* Associate Commands */
179 static void parser_pool_associate(cmd_t *);
180 
181 /* Assign Commands */
182 static void parser_resource_xtransfer(cmd_t *);
183 static void parser_resource_transfer(cmd_t *);
184 
185 /* Discover Commands */
186 static void parser_conf_discover(cmd_t *);
187 
188 /* Rename Commands */
189 static void parser_rename(cmd_t *, pool_elem_t *, const char *);
190 static void parser_conf_rename(cmd_t *);
191 static void parser_pool_rename(cmd_t *);
192 static void parser_pset_rename(cmd_t *);
193 
194 
195 
196 # line 196 "poolcfg.y"
197 typedef union
198 #ifdef __cplusplus
199 	YYSTYPE
200 #endif
201  {
202 	double dval;
203 	uint64_t uval;
204 	int64_t ival;
205 	char *sval;
206 	uchar_t bval;
207 	cmd_t *cmd;
208 	prop_t *prop;
209 	pv_u val;
210 	assoc_t *assoc;
211 } YYSTYPE;
212 # define PCC_INFO 257
213 # define PCC_CREATE 258
214 # define PCC_DESTROY 259
215 # define PCC_MODIFY 260
216 # define PCC_ASSOC 261
217 # define PCC_DISC 262
218 # define PCC_RENAME 263
219 # define PCC_TRANSFER 264
220 # define PCK_FROM 265
221 # define PCK_TO 266
222 # define PCK_OPENLST 267
223 # define PCK_CLOSELST 268
224 # define PCK_SEPLST 269
225 # define PCK_ASSIGN 270
226 # define PCK_UNDEF 271
227 # define PCK_COMMAND 272
228 # define PCV_FILENAME 273
229 # define PCV_SYMBOL 274
230 # define PCV_VAL_INT 275
231 # define PCV_VAL_UINT 276
232 # define PCV_VAL_FLOAT 277
233 # define PCV_VAL_STRING 278
234 # define PCV_VAL_BOOLEAN 279
235 # define PCT_INT 280
236 # define PCT_UINT 281
237 # define PCT_BOOLEAN 282
238 # define PCT_FLOAT 283
239 # define PCT_STRING 284
240 # define PCE_SYSTEM 285
241 # define PCE_POOL 286
242 # define PCE_PSET 287
243 # define PCE_CPU 288
244 
245 #include <inttypes.h>
246 
247 #ifdef __STDC__
248 #include <stdlib.h>
249 #include <string.h>
250 #define	YYCONST	const
251 #else
252 #include <malloc.h>
253 #include <memory.h>
254 #define	YYCONST
255 #endif
256 
257 #include <values.h>
258 
259 #if defined(__cplusplus) || defined(__STDC__)
260 
261 #if defined(__cplusplus) && defined(__EXTERN_C__)
262 extern "C" {
263 #endif
264 #ifndef yyerror
265 #if defined(__cplusplus)
266 	void yyerror(YYCONST char *);
267 #endif
268 #endif
269 #ifndef yylex
270 	int yylex(void);
271 #endif
272 	int yyparse(void);
273 #if defined(__cplusplus) && defined(__EXTERN_C__)
274 }
275 #endif
276 
277 #endif
278 
279 #define yyclearin yychar = -1
280 #define yyerrok yyerrflag = 0
281 extern int yychar;
282 extern int yyerrflag;
283 YYSTYPE yylval;
284 YYSTYPE yyval;
285 typedef int yytabelem;
286 #ifndef YYMAXDEPTH
287 #define YYMAXDEPTH 150
288 #endif
289 #if YYMAXDEPTH > 0
290 int yy_yys[YYMAXDEPTH], *yys = yy_yys;
291 YYSTYPE yy_yyv[YYMAXDEPTH], *yyv = yy_yyv;
292 #else	/* user does initial allocation */
293 int *yys;
294 YYSTYPE *yyv;
295 #endif
296 static int yymaxdepth = YYMAXDEPTH;
297 # define YYERRCODE 256
298 
299 # line 653 "poolcfg.y"
300 
301 
302 #ifndef	TEXT_DOMAIN
303 #define	TEXT_DOMAIN "SYS_TEST"
304 #endif
305 
306 int
307 main(int argc, char *argv[])
308 {
309 	int opt;
310 	int docmd = PO_FALSE;
311 
312 	(void) getpname(argv[0]);
313 	(void) setlocale(LC_ALL, "");
314 	(void) textdomain(TEXT_DOMAIN);
315 	if (atexit(terminate) != 0) {
316 		die(gettext(ERR_SET_TERM), get_errstr());
317 	}
318 
319 	conf_file = pool_static_location();
320 
321 	yydebug = 0;
322 	while ((opt = getopt(argc, argv, cmd_options)) != (int)EOF) {
323 
324 		switch (opt) {
325 		case 'c': /* Process command line */
326 			if (dofile == PO_TRUE)
327 				usage(1);
328 			arg_parse(optarg);
329 			docmd = PO_TRUE;
330 			break;
331 		case 'd': /* Manipulate dynamic configuration */
332 			conf_file = pool_dynamic_location();
333 			break;
334 		case 'f': /* Process command file */
335 			if (docmd == PO_TRUE)
336 				usage(1);
337 			file_parse(optarg);
338 			dofile = PO_TRUE;
339 			break;
340 		case 'h':
341 			usage(2);
342 			break;
343 		case '?':
344 		default:
345 			usage(1);
346 			break;
347 		}
348 	}
349 	if (docmd == PO_FALSE && dofile == PO_FALSE)
350 		usage(1);
351 
352 	if (optind == argc - 1) {
353 		if (strcmp(conf_file, pool_dynamic_location()) == 0)
354 			usage(1);
355 		conf_file = argv[optind];
356 	} else if (optind <  argc - 1)
357 		usage(1);
358 
359 	if ((conf = pool_conf_alloc()) == NULL) {
360 		die(gettext(ERR_ALLOC_ELEMENT), gettext(CONFIGURATION),
361 		    get_errstr());
362 	}
363 	/*
364 	 * Opening a conf is complex, since we may be opening one of the
365 	 * following:
366 	 *	- An existing configuration that we can modify
367 	 *	- An existing configuration that we can't modify
368 	 *	- A new configuration that we can modify
369 	 *	- A new configuration that we can't modify
370 	 * The parser_conf_discover() function closes the file and reopens
371 	 * in PO_CREAT mode, so we only need be concerned here with the
372 	 * first two cases.
373 	 * Always try to open RDWR, if fail try RDONLY. Don't check
374 	 * if that fails, since we may be trying to discover a configuration
375 	 * in which case it's valid for both open attempts to fail. Later, when
376 	 * processing commands, if we don't have a valid configuration and
377 	 * we are trying to process a command which isn't a create or a discover
378 	 * we will fail the command as there is no valid configuration to
379 	 * work with.
380 	 */
381 	if (pool_conf_open(conf, conf_file, PO_RDWR) != 0) {
382 		conf_edit_error = pool_error();
383 		conf_edit_errno = errno;
384 		if (pool_conf_open(conf, conf_file, PO_RDONLY) != 0) {
385 			conf_list_error = pool_error();
386 			conf_list_errno = errno;
387 		}
388 	}
389 
390 	if (yyparse() == 0) {
391 		if (pool_conf_status(conf) >= POF_VALID) {
392 			if (pool_conf_validate(conf, POV_STRICT) == PO_FAIL) {
393 				die(gettext(ERR_VALIDATION_FAILED),
394 				    get_errstr());
395 			}
396 			/*
397 			 * If the user attempted to change the configuration,
398 			 * then we should try to save the changes.
399 			 */
400 			if (edited == PO_TRUE) {
401 				if (pool_conf_commit(conf, 0) == PO_FAIL) {
402 					die(gettext(ERR_CONFIG_SAVE_FAILED),
403 					    get_errstr());
404 				}
405 			}
406 			pool_conf_close(conf);
407 		}
408 	} else {
409 		die(gettext(ERR_CMDPARSE_FAILED));
410 	}
411 
412 	/*
413 	 * Cleanup is performed in terminate(), using atexit
414 	 */
415 	return (0);
416 }
417 
418 /*
419  * Info Commands
420  * Invoke the appropriate libpool info function and display the returned
421  * information.
422  */
423 static void
424 parser_conf_info(cmd_t *cmd)
425 {
426 	char *info_buf;
427 	const char *tgt = cmd->cmd_tgt1;
428 	pool_value_t *pv = NULL;
429 	pool_elem_t *pe;
430 
431 	if ((pe = pool_conf_to_elem(conf)) == NULL)
432 		die(gettext(ERR_GET_ELEMENT_DETAILS),
433 		    gettext(CONFIGURATION), "unknown", get_errstr());
434 
435 	if (tgt != NULL)
436 		check_conf_name(cmd);
437 	else {
438 		if ((pv = pool_value_alloc()) == NULL)
439 			die(gettext(ERR_GET_ELEMENT_DETAILS),
440 			    gettext(CONFIGURATION), "unknown", get_errstr());
441 		if (pool_get_property(conf, pe, "system.name", pv) ==
442 		    POC_INVAL ||
443 		    pool_value_get_string(pv, &tgt) != PO_SUCCESS)
444 			die(gettext(ERR_GET_ELEMENT_DETAILS),
445 			    gettext(CONFIGURATION), "unknown", get_errstr());
446 	}
447 	if ((info_buf = pool_conf_info(conf, PO_TRUE)) == NULL) {
448 		die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION),
449 		    tgt, get_errstr());
450 	}
451 	if (pv != NULL) {
452 		pool_value_free(pv);
453 	}
454 	(void) printf("%s\n", info_buf);
455 	free(info_buf);
456 }
457 
458 static void
459 parser_pool_info(cmd_t *cmd)
460 {
461 	pool_t *pool;
462 	char *info_buf;
463 
464 	if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL)
465 		die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1,
466 		    get_errstr());
467 
468 	if ((info_buf = pool_info(conf, pool, PO_TRUE)) == NULL)
469 		die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(POOL),
470 		    cmd->cmd_tgt1, get_errstr());
471 	(void) printf("%s\n", info_buf);
472 	free(info_buf);
473 }
474 
475 static void
476 parser_resource_info(cmd_t *cmd, const char *type)
477 {
478 	pool_resource_t *resource;
479 	char *info_buf;
480 
481 	if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL)
482 		die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE),
483 		    cmd->cmd_tgt1, get_errstr());
484 
485 	if ((info_buf = pool_resource_info(conf, resource, PO_TRUE)) == NULL)
486 		die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(RESOURCE),
487 		    cmd->cmd_tgt1, get_errstr());
488 	(void) printf("%s\n", info_buf);
489 	free(info_buf);
490 }
491 
492 static void
493 parser_pset_info(cmd_t *cmd)
494 {
495 	parser_resource_info(cmd, PSET);
496 }
497 
498 static void
499 parser_cpu_info(cmd_t *cmd)
500 {
501 	pool_component_t *comp;
502 	char *info_buf;
503 
504 	if ((comp = get_cpu(cmd->cmd_tgt1)) == NULL)
505 		die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU),
506 		    cmd->cmd_tgt1, get_errstr());
507 	if ((info_buf = pool_component_info(conf, comp, PO_TRUE)) == NULL) {
508 		die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CPU),
509 		    cmd->cmd_tgt1, get_errstr());
510 	}
511 	(void) printf("%s\n", info_buf);
512 	free(info_buf);
513 }
514 
515 /*
516  * Create Commands
517  * Invoke the appropriate libpool create function and perform any requested
518  * property operations.
519  */
520 static void
521 parser_conf_create(cmd_t *cmd)
522 {
523 	const char *tmp_name;
524 	pool_elem_t *pe;
525 
526 	if (conf != NULL && pool_conf_status(conf) >= POF_VALID)
527 		pool_conf_close(conf);
528 	if (pool_conf_open(conf, conf_file, PO_CREAT) != 0) {
529 		die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION),
530 		    cmd->cmd_tgt1, get_errstr());
531 	}
532 	tmp_name = cmd->cmd_tgt1;
533 	cmd->cmd_tgt1 = cmd->cmd_tgt2;
534 	cmd->cmd_tgt2 = tmp_name;
535 	parser_conf_rename(cmd);
536 	if ((pe = pool_conf_to_elem(conf)) == NULL)
537 		die(gettext(ERR_GET_ELEMENT_DETAILS),
538 		    gettext(CONFIGURATION), "unknown", get_errstr());
539 	prop_list_walk(cmd, pe);
540 }
541 
542 static void
543 parser_pool_create(cmd_t *cmd)
544 {
545 	pool_t *pool;
546 
547 	if ((pool = pool_create(conf, cmd->cmd_tgt1)) == NULL)
548 		die(gettext(ERR_CREATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1,
549 		    get_errstr());
550 	prop_list_walk(cmd, pool_to_elem(conf, pool));
551 }
552 
553 static void
554 parser_resource_create(cmd_t *cmd, const char *type)
555 {
556 	pool_resource_t *resource;
557 
558 	if ((resource = pool_resource_create(conf, type, cmd->cmd_tgt1))
559 	    == NULL)
560 		die(gettext(ERR_CREATE_ELEMENT), type, cmd->cmd_tgt1,
561 		    get_errstr());
562 
563 	process_min_max(resource);
564 
565 	prop_list_walk(cmd, pool_resource_to_elem(conf, resource));
566 }
567 
568 static void
569 parser_pset_create(cmd_t *cmd)
570 {
571 	parser_resource_create(cmd, PSET);
572 }
573 
574 /*
575  * Rename Commands
576  * Rename the target by calling pool_put_property for the name property.
577  */
578 static void
579 parser_rename(cmd_t *cmd, pool_elem_t *pe, const char *name)
580 {
581 	pool_value_t *pv;
582 
583 	if ((pv = pool_value_alloc()) == NULL) {
584 		die(gettext(ERR_ALLOC_ELEMENT), gettext(RESOURCE),
585 		    get_errstr());
586 	}
587 	pool_value_set_string(pv, cmd->cmd_tgt2);
588 	if (pool_put_property(conf, pe, name, pv) != 0)
589 		die(gettext(ERR_PUT_PROPERTY), name, get_errstr());
590 	pool_value_free(pv);
591 }
592 
593 static void
594 parser_conf_rename(cmd_t *cmd)
595 {
596 	pool_elem_t *pe;
597 
598 	if ((pe = pool_conf_to_elem(conf)) == NULL)
599 		die(gettext(ERR_GET_ELEMENT_DETAILS),
600 		    gettext(CONFIGURATION), "unknown", get_errstr());
601 
602 	if (cmd->cmd_tgt1 != NULL)
603 		check_conf_name(cmd);
604 
605 	parser_rename(cmd, pe, SYSTEM_NAME);
606 }
607 
608 static void
609 parser_pool_rename(cmd_t *cmd)
610 {
611 	pool_t *pool;
612 
613 	if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL)
614 		die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1,
615 		    get_errstr());
616 
617 	parser_rename(cmd, pool_to_elem(conf, pool), POOL_NAME);
618 }
619 
620 static void
621 parser_pset_rename(cmd_t *cmd)
622 {
623 	pool_resource_t *resource;
624 
625 	if ((resource = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL)
626 		die(gettext(ERR_LOCATE_ELEMENT), gettext(PSET), cmd->cmd_tgt1,
627 		    get_errstr());
628 
629 	parser_rename(cmd, pool_resource_to_elem(conf, resource), PSET_NAME);
630 }
631 
632 /*
633  * Destroy Commands
634  * Invoke the appropriate libpool destroy function to remove the target of the
635  * command from the configuration.
636  */
637 static void
638 parser_conf_destroy(cmd_t *cmd)
639 {
640 	if (cmd->cmd_tgt1 != NULL)
641 		check_conf_name(cmd);
642 
643 	if (pool_conf_remove(conf) != 0)
644 		die(gettext(ERR_DESTROY_ELEMENT), gettext(CONFIGURATION),
645 		    cmd->cmd_tgt1, get_errstr());
646 }
647 
648 static void
649 parser_pool_destroy(cmd_t *cmd)
650 {
651 	pool_t *pool;
652 
653 	if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL)
654 		die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1,
655 		    get_errstr());
656 
657 	if (pool_destroy(conf, pool) != 0)
658 		die(gettext(ERR_DESTROY_ELEMENT), gettext(POOL), cmd->cmd_tgt1,
659 		    get_errstr());
660 }
661 
662 static void
663 parser_resource_destroy(cmd_t *cmd, const char *type)
664 {
665 	pool_resource_t *resource;
666 
667 	if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL)
668 		die(gettext(ERR_LOCATE_ELEMENT), type, cmd->cmd_tgt1,
669 		    get_errstr());
670 
671 	if (pool_resource_destroy(conf, resource) != 0)
672 		die(gettext(ERR_DESTROY_ELEMENT), type, cmd->cmd_tgt1,
673 		    get_errstr());
674 }
675 
676 static void
677 parser_pset_destroy(cmd_t *cmd)
678 {
679 	parser_resource_destroy(cmd, PSET);
680 }
681 
682 /*
683  * Modify Commands
684  * Perform any requested property operations.
685  */
686 static void
687 parser_conf_modify(cmd_t *cmd)
688 {
689 	pool_elem_t *pe;
690 
691 	if ((pe = pool_conf_to_elem(conf)) == NULL)
692 		die(gettext(ERR_GET_ELEMENT_DETAILS),
693 		    gettext(CONFIGURATION), "unknown", get_errstr());
694 
695 	if (cmd->cmd_tgt1 != NULL)
696 		check_conf_name(cmd);
697 
698 	prop_list_walk(cmd, pe);
699 }
700 
701 static void
702 parser_pool_modify(cmd_t *cmd)
703 {
704 	pool_t *pool;
705 
706 	if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL)
707 		die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1,
708 		    get_errstr());
709 	prop_list_walk(cmd, pool_to_elem(conf, pool));
710 }
711 
712 static void
713 parser_resource_modify(cmd_t *cmd, const char *type)
714 {
715 	pool_resource_t *resource;
716 
717 	if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL)
718 		die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE),
719 		    cmd->cmd_tgt1, get_errstr());
720 
721 	process_min_max(resource);
722 
723 	prop_list_walk(cmd, pool_resource_to_elem(conf, resource));
724 }
725 
726 static void
727 parser_pset_modify(cmd_t *cmd)
728 {
729 	parser_resource_modify(cmd, PSET);
730 }
731 
732 static void
733 parser_cpu_modify(cmd_t *cmd)
734 {
735 	pool_component_t *comp;
736 
737 	if ((comp = get_cpu(cmd->cmd_tgt1)) == NULL)
738 		die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU),
739 		    cmd->cmd_tgt1, get_errstr());
740 	prop_list_walk(cmd, pool_component_to_elem(conf, comp));
741 }
742 
743 /*
744  * Discover Commands
745  * Invoke the libpool pool_conf_open function so that discovery will be
746  * performed.
747  */
748 
749 /*ARGSUSED*/
750 static void
751 parser_conf_discover(cmd_t *cmd)
752 {
753 	struct utsname utsname;
754 
755 	if (strcmp(conf_file, pool_dynamic_location()) == 0)
756 		return;
757 
758 	if (uname(&utsname) < 0)
759 		die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION),
760 		    "unknown", get_errstr());
761 
762 	if (conf != NULL && pool_conf_status(conf) >= POF_VALID)
763 		pool_conf_close(conf);
764 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) != 0) {
765 		die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION),
766 		    utsname.nodename, get_errstr());
767 	}
768 	if (pool_conf_export(conf, conf_file, POX_NATIVE) != 0) {
769 		die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION),
770 		    utsname.nodename, get_errstr());
771 	}
772 	(void) pool_conf_close(conf);
773 	if (pool_conf_open(conf, conf_file, PO_RDWR) != 0) {
774 		die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION),
775 		    utsname.nodename, get_errstr());
776 	}
777 }
778 
779 /*
780  * Associate Commands
781  * Walk the list of specified associations so that the target pool will be
782  * associated with the required resources.
783  */
784 
785 static void
786 parser_pool_associate(cmd_t *cmd)
787 {
788 	pool_t *pool;
789 
790 	if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL)
791 		die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1,
792 		    get_errstr());
793 	assoc_list_walk(cmd, pool);
794 }
795 
796 /*
797  * Assign Commands
798  * Walk the list of specified assignations so that the required
799  * components will be assigned to the target resource.
800  */
801 
802 static void
803 parser_resource_xtransfer(cmd_t *cmd)
804 {
805 	pool_resource_t *resource;
806 
807 	if ((resource = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL)
808 		die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE),
809 		    cmd->cmd_tgt1, get_errstr());
810 	transfer_list_walk(cmd, resource);
811 }
812 
813 /*
814  * Transfer Commands
815  * Transfer the specified quantity of resource between the src and the tgt.
816  */
817 
818 static void
819 parser_resource_transfer(cmd_t *cmd)
820 {
821 	pool_resource_t *src;
822 	pool_resource_t *tgt;
823 
824 	if ((src = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL)
825 		die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE),
826 		    cmd->cmd_tgt1, get_errstr());
827 	if ((tgt = pool_get_resource(conf, PSET, cmd->cmd_tgt2)) == NULL)
828 		die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE),
829 		    cmd->cmd_tgt2, get_errstr());
830 	if (pool_resource_transfer(conf, src, tgt, cmd->cmd_qty) != PO_SUCCESS)
831 		die(gettext(ERR_XFER_QUANTITY), cmd->cmd_qty,
832 		    cmd->cmd_tgt1, cmd->cmd_tgt2, get_errstr());
833 }
834 
835 /*
836  * arg_parse() puts the parser into command parsing mode. Create a tmpfile
837  * and instruct the parser to read instructions from this location by setting
838  * yyin to the value returned by tmpfile. Write the command into the file.
839  * Then seek back to to the start of the file so that the parser can read
840  * the instructions.
841  */
842 static void
843 arg_parse(const char *command)
844 {
845 	if ((yyin = tmpfile()) == NULL)
846 		die(gettext(ERR_CMD_FILE_INIT), strerror(errno));
847 	if (fwrite(command, strlen(command), 1, yyin) != 1)
848 		die(gettext(ERR_CMD_FILE_INIT), strerror(errno));
849 	if (fseek(yyin, 0, SEEK_SET) != 0)
850 		die(gettext(ERR_CMD_FILE_INIT), strerror(errno));
851 }
852 
853 /*
854  * file_parse() puts the parser into command file parsing mode. Firstly check
855  * to see if the user wishes to parse from standard input, if so do nothing.
856  * Attempt to open the specified file and instruct the parser to read
857  * instructions from this location by setting yyin to the value returned by
858  * fopen.
859  */
860 static void
861 file_parse(const char *file)
862 {
863 	if (strcmp(file, "-") == 0)
864 		return;
865 
866 	if ((yyin = fopen(file, "r")) == NULL) {
867 		die(gettext(ERR_CMD_FILE_INIT), strerror(errno));
868 	}
869 }
870 
871 /*
872  * free_cmd() releases the resources associated with the supplied cmd parameter.
873  */
874 static void
875 free_cmd(cmd_t *cmd)
876 {
877 	prop_t *prop = cmd->cmd_prop_list;
878 	assoc_t *assoc = cmd->cmd_assoc_list;
879 
880 	free((void *)cmd->cmd_tgt1);
881 	free((void *)cmd->cmd_tgt2);
882 	while (prop != NULL) {
883 		prop_t *tmp = prop;
884 		prop = prop->prop_next;
885 		pool_value_free(tmp->prop_value);
886 		free((void *)tmp->prop_name);
887 		free(tmp);
888 	}
889 	while (assoc != NULL) {
890 		assoc_t *tmp = assoc;
891 		assoc = assoc->assoc_next;
892 		free((void *)tmp->assoc_name);
893 		free(tmp);
894 	}
895 	free(cmd);
896 }
897 
898 /*
899  * alloc_cmd() allocates the required resources for a cmd_t. On failure, a
900  * warning is issued and NULL is returned.
901  */
902 static cmd_t *
903 alloc_cmd(void)
904 {
905 	cmd_t *cmd;
906 
907 	if ((cmd = malloc(sizeof (cmd_t))) == NULL) {
908 		warn(gettext(ERR_CMD_LINE_ALLOC));
909 		return (NULL);
910 	}
911 
912 	(void) memset(cmd, 0, sizeof (cmd_t));
913 
914 	return (cmd);
915 }
916 
917 /*
918  * alloc_prop() allocates the required resources for a prop_t. On failure, a
919  * warning is issued and NULL is returned. The prop_t is initialised with
920  * the prop_op_t parameter.
921  */
922 static prop_t *
923 alloc_prop(prop_op_t op)
924 {
925 	prop_t *prop;
926 
927 	if ((prop = malloc(sizeof (prop_t))) == NULL) {
928 		warn(gettext(ERR_PROP_ALLOC));
929 		return (NULL);
930 	}
931 
932 	(void) memset(prop, 0, sizeof (prop_t));
933 	if ((prop->prop_value = pool_value_alloc()) == NULL) {
934 		warn(gettext(ERR_PROP_ALLOC));
935 		free(prop);
936 		return (NULL);
937 	}
938 	prop->prop_op = op;
939 	return (prop);
940 }
941 
942 /*
943  * alloc_assoc() allocates the required resources for an assoc_t. On failure, a
944  * warning is issued and NULL is returned. The assoc_t is initialised with
945  * the type and name of the association.
946  */
947 static assoc_t *
948 alloc_assoc(int type, const char *name)
949 {
950 	assoc_t *assoc;
951 
952 	if ((assoc = malloc(sizeof (assoc_t))) == NULL) {
953 		warn(gettext(ERR_ASSOC_ALLOC));
954 		return (NULL);
955 	}
956 	(void) memset(assoc, 0, sizeof (assoc_t));
957 	assoc->assoc_type = type;
958 	assoc->assoc_name = name;
959 	return (assoc);
960 }
961 
962 /*
963  * check_conf_name() ensures the the name of the system in the configuration
964  * which is being manipulated matches the name of the system in the command.
965  * If not, the command is terminated with an appropriate error message.
966  */
967 static void
968 check_conf_name(cmd_t *cmd)
969 {
970 	pool_value_t *pv;
971 	const char *name;
972 	pool_elem_t *pe;
973 
974 	if ((pe = pool_conf_to_elem(conf)) == NULL)
975 		die(gettext(ERR_GET_ELEMENT_DETAILS),
976 		    gettext(CONFIGURATION), "unknown", get_errstr());
977 
978 
979 	if ((pv = pool_value_alloc()) == NULL) {
980 		die(gettext(ERR_ALLOC_ELEMENT), gettext(RESOURCE),
981 		    get_errstr());
982 	}
983 
984 	if (pool_get_property(conf, pe, SYSTEM_NAME, pv)
985 	    == POC_INVAL)
986 		die(gettext(ERR_GET_PROPERTY), gettext(SYSTEM_NAME),
987 		    get_errstr());
988 
989 	if (pool_value_get_string(pv, &name) == PO_FAIL)
990 		die(gettext(ERR_GET_PROPERTY), gettext(SYSTEM_NAME),
991 		    get_errstr());
992 
993 	if (strcmp(cmd->cmd_tgt1, name) != 0) {
994 		die(gettext(ERR_WRONG_SYSTEM_NAME), cmd->cmd_tgt1);
995 	}
996 	pool_value_free(pv);
997 }
998 
999 /*
1000  * usage() display brief or verbose help for the poolcfg(1) command.
1001  */
1002 static void
1003 usage(int help)
1004 {
1005 	if (help >= 1)
1006 		(void) fprintf(stderr, gettext(USAGE1), cmdname, cmdname,
1007 		    cmdname);
1008 	if (help >= 2)
1009 		(void) fprintf(stderr, gettext(USAGE2));
1010 	exit(E_USAGE);
1011 }
1012 
1013 /*
1014  * prop_list_walk() walks the property manipulation requests and either puts
1015  * or removes the property as appropriate.
1016  */
1017 static void
1018 prop_list_walk(cmd_t *cmd, pool_elem_t *pe)
1019 {
1020 	prop_t *prop;
1021 
1022 	for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) {
1023 		switch (prop->prop_op) {
1024 		case po_create:
1025 			if (pool_put_property(conf, pe, prop->prop_name,
1026 			    prop->prop_value) != 0)
1027 				die(gettext(ERR_PUT_PROPERTY),
1028 				    prop->prop_name, get_errstr());
1029 			break;
1030 		case po_remove:
1031 			if (pool_rm_property(conf, pe, prop->prop_name) != 0)
1032 				die(gettext(ERR_REMOVE_PROPERTY),
1033 				    prop->prop_name, get_errstr());
1034 			break;
1035 		}
1036 	}
1037 }
1038 
1039 /*
1040  * assoc_list_walk() walks the resource association requests and attempts
1041  * to associate the pool with the specified resource.
1042  */
1043 static void
1044 assoc_list_walk(cmd_t *cmd, pool_t *pool)
1045 {
1046 	assoc_t *assoc;
1047 
1048 	for (assoc = cmd->cmd_assoc_list; assoc != NULL;
1049 	    assoc = assoc->assoc_next) {
1050 		pool_resource_t *resource;
1051 
1052 		switch (assoc->assoc_type) {
1053 		case PCE_PSET:
1054 			if ((resource = pool_get_resource(conf,
1055 			    PSET, assoc->assoc_name)) == NULL)
1056 				die(gettext(ERR_LOCATE_ELEMENT), gettext(PSET),
1057 				    assoc->assoc_name, get_errstr());
1058 			break;
1059 		default:
1060 			die(gettext(ERR_UNKNOWN_RESOURCE),
1061 			    assoc->assoc_type);
1062 			break;
1063 		}
1064 		if (pool_associate(conf, pool, resource) != 0)
1065 			die(gettext(ERR_ASSOC_RESOURCE), assoc->assoc_name,
1066 			    get_errstr());
1067 	}
1068 }
1069 
1070 /*
1071  * transfer_list_walk() walks the component assign requests and attempts
1072  * to assign the component with the specified resource.
1073  */
1074 static void
1075 transfer_list_walk(cmd_t *cmd, pool_resource_t *tgt)
1076 {
1077 	assoc_t *assoc;
1078 
1079 	for (assoc = cmd->cmd_assoc_list; assoc != NULL;
1080 	    assoc = assoc->assoc_next) {
1081 		pool_component_t *comp;
1082 		pool_resource_t *src;
1083 		pool_component_t *xfer[2] = {NULL};
1084 
1085 		if ((comp = get_cpu(assoc->assoc_name)) == NULL)
1086 			die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU),
1087 			    assoc->assoc_name, get_errstr());
1088 		if ((src = pool_get_owning_resource(conf, comp)) == NULL)
1089 			die(gettext(ERR_XFER_COMPONENT), gettext(COMPONENT),
1090 			    assoc->assoc_name, cmd->cmd_tgt1, get_errstr());
1091 		xfer[0] = comp;
1092 		if (pool_resource_xtransfer(conf, src, tgt, xfer) !=
1093 		    PO_SUCCESS)
1094 			die(gettext(ERR_XFER_COMPONENT), gettext(COMPONENT),
1095 			    assoc->assoc_name, cmd->cmd_tgt1, get_errstr());
1096 	}
1097 }
1098 
1099 /*
1100  * terminate() is invoked when poolcfg exits. It cleans up
1101  * configurations and closes the parser input stream.
1102  */
1103 static void
1104 terminate(void)
1105 {
1106 	if (conf != NULL) {
1107 		(void) pool_conf_close(conf);
1108 		pool_conf_free(conf);
1109 	}
1110 	if (yyin != stdin)
1111 		(void) fclose(yyin);
1112 }
1113 
1114 /*
1115  * get_cpu() takes the name of a CPU components and attempts to locate
1116  * the element with that name. If the name is not formatted correctly
1117  * (i.e. contains non-numeric characters) then the function terminates
1118  * execution. If the components cannot be uniquely identified by the
1119  * name, then NULL is returned.
1120  */
1121 static pool_component_t *
1122 get_cpu(const char *name)
1123 {
1124 	pool_component_t **components;
1125 	uint_t nelem;
1126 	int64_t sysid;
1127 	pool_value_t *vals[3] = {NULL};
1128 	pool_component_t *ret;
1129 	const char *c;
1130 
1131 	if ((vals[0] = pool_value_alloc()) == NULL)
1132 		return (NULL);
1133 	if ((vals[1] = pool_value_alloc()) == NULL) {
1134 		pool_value_free(vals[0]);
1135 		return (NULL);
1136 	}
1137 	if (pool_value_set_string(vals[0], "cpu") != PO_SUCCESS ||
1138 	    pool_value_set_name(vals[0], "type") != PO_SUCCESS) {
1139 		pool_value_free(vals[0]);
1140 		pool_value_free(vals[1]);
1141 		return (NULL);
1142 	}
1143 
1144 	for (c = name; *c != NULL; c++) {
1145 		if (!isdigit(*c)){
1146 			pool_value_free(vals[0]);
1147 			pool_value_free(vals[1]);
1148 			die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU),
1149 		    	    cmd->cmd_tgt1, gettext("CPU id should only contain "
1150 			    "digits"));
1151 		}
1152 	}
1153 	sysid = strtoll(name, NULL, 0);
1154 	if (errno == ERANGE || errno == EINVAL) {
1155 		pool_value_free(vals[0]);
1156 		pool_value_free(vals[1]);
1157 		return (NULL);
1158 	}
1159 	pool_value_set_int64(vals[1], sysid);
1160 	if (pool_value_set_name(vals[1], CPU_SYSID) != PO_SUCCESS) {
1161 		pool_value_free(vals[0]);
1162 		pool_value_free(vals[1]);
1163 		return (NULL);
1164 	}
1165 	if ((components = pool_query_components(conf, &nelem, vals)) ==
1166 	    NULL) {
1167 		pool_value_free(vals[0]);
1168 		pool_value_free(vals[1]);
1169 		return (NULL);
1170 	}
1171 	if (nelem != 1) {
1172 		free(components);
1173 		pool_value_free(vals[0]);
1174 		pool_value_free(vals[1]);
1175 		return (NULL);
1176 	}
1177 	pool_value_free(vals[0]);
1178 	pool_value_free(vals[1]);
1179 	ret = components[0];
1180 	free(components);
1181 	return (ret);
1182 }
1183 
1184 /*
1185  * process_min_max() ensures that "min" and "max" properties are
1186  * processed correctly by poolcfg. libpool enforces validity
1187  * constraints on these properties and so it's important that changes
1188  * to them are supplied to the library in the correct order.
1189  */
1190 void
1191 process_min_max(pool_resource_t *resource)
1192 {
1193 	prop_t *minprop = NULL;
1194 	prop_t *maxprop = NULL;
1195 	prop_t *prop;
1196 
1197 	/*
1198 	 * Before walking the list of properties, it has to be checked
1199 	 * to ensure there are no clashes between min and max. If
1200 	 * there are, then process these properties immediately.
1201 	 */
1202 	for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) {
1203 		const char *pos;
1204 
1205 		if ((pos = strstr(prop->prop_name, min_suffix)) != NULL)
1206 			if (pos == prop->prop_name + strlen(prop->prop_name)
1207 			    - 4)
1208 				minprop = prop;
1209 		if ((pos = strstr(prop->prop_name, max_suffix)) != NULL)
1210 			if (pos == prop->prop_name + strlen(prop->prop_name)
1211 			    - 4)
1212 				maxprop = prop;
1213 	}
1214 	if (minprop && maxprop) {
1215 		pool_value_t *pv;
1216 		uint64_t smin, smax, dmax;
1217 		const char *type;
1218 		char *prop_name;
1219 		pool_elem_t *pe = pool_resource_to_elem(conf, resource);
1220 
1221 		if ((pv = pool_value_alloc()) == NULL)
1222 			die(gettext(ERR_NOMEM));
1223 
1224 		(void) pool_get_property(conf, pe, "type", pv);
1225 		(void) pool_value_get_string(pv, &type);
1226 
1227 		if ((prop_name = malloc(strlen(type) + strlen(max_suffix)
1228 		    + 1)) == NULL)
1229 			die(gettext(ERR_NOMEM));
1230 
1231 		(void) sprintf(prop_name, "%s%s", type, max_suffix);
1232 		(void) pool_get_property(conf, pe, prop_name, pv);
1233 		(void) pool_value_get_uint64(pv, &dmax);
1234 
1235 		(void) pool_value_get_uint64(minprop->prop_value, &smin);
1236 
1237 		(void) pool_value_get_uint64(maxprop->prop_value, &smax);
1238 		if (smin < dmax) {
1239 			(void) pool_put_property(conf, pe,
1240 			minprop->prop_name, minprop->prop_value);
1241 		} else {
1242 			(void) pool_put_property(conf, pe,
1243 			maxprop->prop_name, maxprop->prop_value);
1244 		}
1245 		free((void *)prop_name);
1246 		pool_value_free(pv);
1247 	}
1248 }
1249 static YYCONST yytabelem yyexca[] ={
1250 -1, 1,
1251 	0, -1,
1252 	-2, 0,
1253 -1, 2,
1254 	0, 1,
1255 	257, 1,
1256 	258, 1,
1257 	259, 1,
1258 	260, 1,
1259 	261, 1,
1260 	262, 1,
1261 	263, 1,
1262 	264, 1,
1263 	-2, 0,
1264 	};
1265 # define YYNPROD 68
1266 # define YYLAST 172
1267 static YYCONST yytabelem yyact[]={
1268 
1269     33,    34,    35,    40,    33,    34,    35,    32,    52,    33,
1270     34,    35,    41,    71,    61,    89,    88,    53,    54,    55,
1271     56,    57,    53,    54,    55,    56,    57,    73,   101,   102,
1272    103,   105,   104,    45,    97,    99,    63,    43,    91,    84,
1273     83,    81,    80,    46,    13,    15,    16,    17,    18,    14,
1274     21,    22,    77,    76,    74,    75,    24,    29,    26,   106,
1275     86,   107,    96,    62,    98,    69,    59,    48,    51,    31,
1276     25,     2,    70,    23,    60,   100,    42,    68,    28,    58,
1277     27,    47,    49,    50,    20,    36,    37,    39,    19,    11,
1278     12,    44,     6,    10,     9,     8,     7,     4,     5,     3,
1279     64,    65,    66,    38,    30,    67,     1,     0,    72,     0,
1280      0,     0,     0,     0,     0,    78,     0,     0,     0,     0,
1281      0,    79,     0,     0,    82,     0,     0,     0,     0,     0,
1282      0,     0,     0,     0,    85,     0,     0,    87,     0,     0,
1283      0,     0,     0,    92,    90,     0,     0,    93,     0,    94,
1284     95,     0,     0,     0,     0,     0,     0,     0,     0,     0,
1285      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
1286    109,   108 };
1287 static YYCONST yytabelem yypact[]={
1288 
1289   -213,  -213,  -200,-10000000,-10000000,-10000000,-10000000,  -209,-10000000,  -209,
1290   -210,-10000000,-10000000,  -281,-10000000,  -276,  -276,  -285,  -274,-10000000,
1291   -230,  -276,  -233,-10000000,-10000000,-10000000,  -263,-10000000,-10000000,  -273,
1292   -238,-10000000,-10000000,-10000000,-10000000,-10000000,  -238,  -238,  -238,-10000000,
1293 -10000000,  -238,-10000000,  -275,  -238,  -260,  -211,  -216,-10000000,-10000000,
1294 -10000000,  -238,  -258,-10000000,-10000000,-10000000,-10000000,-10000000,  -227,-10000000,
1295   -238,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,  -229,-10000000,
1296   -238,-10000000,  -206,  -238,  -271,  -272,  -263,-10000000,  -232,  -238,
1297   -273,-10000000,-10000000,  -275,-10000000,-10000000,  -238,-10000000,  -240,  -239,
1298 -10000000,  -247,-10000000,-10000000,-10000000,-10000000,  -207,-10000000,  -204,-10000000,
1299 -10000000,-10000000,-10000000,-10000000,-10000000,-10000000,  -239,  -240,-10000000,-10000000 };
1300 static YYCONST yytabelem yypgo[]={
1301 
1302      0,   106,    69,    68,   104,   103,    63,    62,    64,    71,
1303     99,    98,    97,    96,    95,    94,    93,    92,    90,    89,
1304     88,    84,    83,    82,    67,    81,    70,    66,    79,    78,
1305     65,    77,    76,    75,    74,    72 };
1306 static YYCONST yytabelem yyr1[]={
1307 
1308      0,     1,     1,     1,     9,     9,    10,    10,    12,    12,
1309     12,    12,    12,    12,    11,    11,    13,    13,    14,    15,
1310     15,    16,    16,    19,    19,    21,    21,    20,    20,    17,
1311     18,     5,     5,     4,     4,     2,     2,     2,     6,     7,
1312      8,    33,    33,    33,    33,    33,    22,    24,    24,    25,
1313     25,    23,    26,    28,    28,    27,    34,    29,    31,    31,
1314     32,    30,    35,     3,     3,     3,     3,     3 };
1315 static YYCONST yytabelem yyr2[]={
1316 
1317      0,     3,     5,     5,     2,     3,     3,     3,     2,     2,
1318      2,     2,     2,     2,     3,     7,     7,     4,     7,     7,
1319      4,     7,     4,     2,     2,     9,     4,    15,    15,     3,
1320     11,     2,     3,     2,     3,     3,     3,     3,     2,     2,
1321      2,     3,     3,     3,     3,     3,     7,     2,     2,     3,
1322      7,     9,     7,     3,     7,     5,     3,     7,     3,     7,
1323      7,     5,     3,     3,     3,     3,     3,     3 };
1324 static YYCONST yytabelem yychk[]={
1325 
1326 -10000000,    -1,    -9,   -10,   -12,   -11,   -17,   -13,   -14,   -15,
1327    -16,   -19,   -18,   257,   262,   258,   259,   260,   261,   -20,
1328    -21,   263,   264,    -9,   256,   -26,   267,   -26,   -29,   267,
1329     -4,    -2,   288,   285,   286,   287,    -2,    -2,    -5,    -2,
1330    288,   286,   -32,   267,    -2,   266,   276,   -25,   -24,   -23,
1331    -22,    -3,   271,   280,   281,   282,   283,   284,   -28,   -27,
1332    -34,   287,    -6,   274,    -6,    -6,    -6,    -6,   -31,   -30,
1333    -35,   288,    -6,   287,   265,   266,   269,   268,    -6,    -3,
1334    269,   268,    -6,   269,   268,    -6,   266,    -6,   287,   287,
1335    -24,   270,    -6,   -27,   -30,    -6,    -7,   274,    -8,   274,
1336    -33,   275,   276,   277,   279,   278,   266,   265,    -8,    -7 };
1337 static YYCONST yytabelem yydef[]={
1338 
1339      0,    -2,    -2,     4,     5,     6,     7,     8,     9,    10,
1340     11,    12,    13,    14,    29,     0,     0,     0,     0,    23,
1341     24,     0,     0,     2,     3,    17,     0,    20,    22,     0,
1342      0,    33,    34,    35,    36,    37,     0,     0,     0,    31,
1343     32,     0,    26,     0,     0,     0,     0,     0,    49,    47,
1344     48,     0,     0,    63,    64,    65,    66,    67,     0,    53,
1345      0,    56,    15,    38,    16,    18,    19,    21,     0,    58,
1346      0,    62,     0,     0,     0,     0,     0,    52,     0,     0,
1347      0,    57,    55,     0,    60,    61,     0,    25,     0,     0,
1348     50,     0,    46,    54,    59,    30,     0,    39,     0,    40,
1349     51,    41,    42,    43,    44,    45,     0,     0,    27,    28 };
1350 typedef struct
1351 #ifdef __cplusplus
1352 	yytoktype
1353 #endif
1354 {
1355 #ifdef __cplusplus
1356 const
1357 #endif
1358 char *t_name; int t_val; } yytoktype;
1359 #ifndef YYDEBUG
1360 #	define YYDEBUG	0	/* don't allow debugging */
1361 #endif
1362 
1363 #if YYDEBUG
1364 
1365 yytoktype yytoks[] =
1366 {
1367 	"PCC_INFO",	257,
1368 	"PCC_CREATE",	258,
1369 	"PCC_DESTROY",	259,
1370 	"PCC_MODIFY",	260,
1371 	"PCC_ASSOC",	261,
1372 	"PCC_DISC",	262,
1373 	"PCC_RENAME",	263,
1374 	"PCC_TRANSFER",	264,
1375 	"PCK_FROM",	265,
1376 	"PCK_TO",	266,
1377 	"PCK_OPENLST",	267,
1378 	"PCK_CLOSELST",	268,
1379 	"PCK_SEPLST",	269,
1380 	"PCK_ASSIGN",	270,
1381 	"PCK_UNDEF",	271,
1382 	"PCK_COMMAND",	272,
1383 	"PCV_FILENAME",	273,
1384 	"PCV_SYMBOL",	274,
1385 	"PCV_VAL_INT",	275,
1386 	"PCV_VAL_UINT",	276,
1387 	"PCV_VAL_FLOAT",	277,
1388 	"PCV_VAL_STRING",	278,
1389 	"PCV_VAL_BOOLEAN",	279,
1390 	"PCT_INT",	280,
1391 	"PCT_UINT",	281,
1392 	"PCT_BOOLEAN",	282,
1393 	"PCT_FLOAT",	283,
1394 	"PCT_STRING",	284,
1395 	"PCE_SYSTEM",	285,
1396 	"PCE_POOL",	286,
1397 	"PCE_PSET",	287,
1398 	"PCE_CPU",	288,
1399 	"-unknown-",	-1	/* ends search */
1400 };
1401 
1402 #ifdef __cplusplus
1403 const
1404 #endif
1405 char * yyreds[] =
1406 {
1407 	"-no such reduction-",
1408 	"commands : command",
1409 	"commands : commands command",
1410 	"commands : command error",
1411 	"command : list_command",
1412 	"command : edit_command",
1413 	"list_command : info_command",
1414 	"list_command : discover_command",
1415 	"edit_command : create_command",
1416 	"edit_command : destroy_command",
1417 	"edit_command : modify_command",
1418 	"edit_command : associate_command",
1419 	"edit_command : transfer_command",
1420 	"edit_command : rename_command",
1421 	"info_command : PCC_INFO",
1422 	"info_command : PCC_INFO info_entity name",
1423 	"create_command : PCC_CREATE entity name",
1424 	"create_command : create_command property_list",
1425 	"destroy_command : PCC_DESTROY entity name",
1426 	"modify_command : PCC_MODIFY modify_entity name",
1427 	"modify_command : modify_command property_list",
1428 	"associate_command : PCC_ASSOC PCE_POOL name",
1429 	"associate_command : associate_command resource_list",
1430 	"transfer_command : transfer_qty",
1431 	"transfer_command : transfer_components",
1432 	"transfer_components : PCC_TRANSFER PCK_TO PCE_PSET name",
1433 	"transfer_components : transfer_components component_list",
1434 	"transfer_qty : PCC_TRANSFER PCV_VAL_UINT PCK_FROM PCE_PSET src PCK_TO tgt",
1435 	"transfer_qty : PCC_TRANSFER PCV_VAL_UINT PCK_TO PCE_PSET tgt PCK_FROM src",
1436 	"discover_command : PCC_DISC",
1437 	"rename_command : PCC_RENAME entity name PCK_TO name",
1438 	"modify_entity : entity",
1439 	"modify_entity : PCE_CPU",
1440 	"info_entity : entity",
1441 	"info_entity : PCE_CPU",
1442 	"entity : PCE_SYSTEM",
1443 	"entity : PCE_POOL",
1444 	"entity : PCE_PSET",
1445 	"name : PCV_SYMBOL",
1446 	"src : PCV_SYMBOL",
1447 	"tgt : PCV_SYMBOL",
1448 	"value : PCV_VAL_INT",
1449 	"value : PCV_VAL_UINT",
1450 	"value : PCV_VAL_FLOAT",
1451 	"value : PCV_VAL_BOOLEAN",
1452 	"value : PCV_VAL_STRING",
1453 	"prop_remove : PCK_UNDEF proptype name",
1454 	"prop_op : prop_assign",
1455 	"prop_op : prop_remove",
1456 	"prop_ops : prop_op",
1457 	"prop_ops : prop_ops PCK_SEPLST prop_op",
1458 	"prop_assign : proptype name PCK_ASSIGN value",
1459 	"property_list : PCK_OPENLST prop_ops PCK_CLOSELST",
1460 	"resource_assigns : resource_assign",
1461 	"resource_assigns : resource_assigns PCK_SEPLST resource_assign",
1462 	"resource_assign : resource name",
1463 	"resource : PCE_PSET",
1464 	"resource_list : PCK_OPENLST resource_assigns PCK_CLOSELST",
1465 	"component_assigns : component_assign",
1466 	"component_assigns : component_assigns PCK_SEPLST component_assign",
1467 	"component_list : PCK_OPENLST component_assigns PCK_CLOSELST",
1468 	"component_assign : component name",
1469 	"component : PCE_CPU",
1470 	"proptype : PCT_INT",
1471 	"proptype : PCT_UINT",
1472 	"proptype : PCT_BOOLEAN",
1473 	"proptype : PCT_FLOAT",
1474 	"proptype : PCT_STRING",
1475 };
1476 #endif /* YYDEBUG */
1477 # line	1 "/usr/share/lib/ccs/yaccpar"
1478 /*
1479  * CDDL HEADER START
1480  *
1481  * The contents of this file are subject to the terms of the
1482  * Common Development and Distribution License, Version 1.0 only
1483  * (the "License").  You may not use this file except in compliance
1484  * with the License.
1485  *
1486  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1487  * or http://www.opensolaris.org/os/licensing.
1488  * See the License for the specific language governing permissions
1489  * and limitations under the License.
1490  *
1491  * When distributing Covered Code, include this CDDL HEADER in each
1492  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1493  * If applicable, add the following below this CDDL HEADER, with the
1494  * fields enclosed by brackets "[]" replaced with your own identifying
1495  * information: Portions Copyright [yyyy] [name of copyright owner]
1496  *
1497  * CDDL HEADER END
1498  */
1499 /*
1500  * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
1501  * Use is subject to license terms.
1502  */
1503 
1504 /* Copyright (c) 1988 AT&T */
1505 /* All Rights Reserved */
1506 
1507 #pragma ident	"%Z%%M%	%I%	%E% SMI"
1508 
1509 /*
1510 ** Skeleton parser driver for yacc output
1511 */
1512 
1513 /*
1514 ** yacc user known macros and defines
1515 */
1516 #define YYERROR		goto yyerrlab
1517 #define YYACCEPT	return(0)
1518 #define YYABORT		return(1)
1519 #define YYBACKUP( newtoken, newvalue )\
1520 {\
1521 	if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
1522 	{\
1523 		yyerror( "syntax error - cannot backup" );\
1524 		goto yyerrlab;\
1525 	}\
1526 	yychar = newtoken;\
1527 	yystate = *yyps;\
1528 	yylval = newvalue;\
1529 	goto yynewstate;\
1530 }
1531 #define YYRECOVERING()	(!!yyerrflag)
1532 #define YYNEW(type)	malloc(sizeof(type) * yynewmax)
1533 #define YYCOPY(to, from, type) \
1534 	(type *) memcpy(to, (char *) from, yymaxdepth * sizeof (type))
1535 #define YYENLARGE( from, type) \
1536 	(type *) realloc((char *) from, yynewmax * sizeof(type))
1537 #ifndef YYDEBUG
1538 #	define YYDEBUG	1	/* make debugging available */
1539 #endif
1540 
1541 /*
1542 ** user known globals
1543 */
1544 int yydebug;			/* set to 1 to get debugging */
1545 
1546 /*
1547 ** driver internal defines
1548 */
1549 #define YYFLAG		(-10000000)
1550 
1551 /*
1552 ** global variables used by the parser
1553 */
1554 YYSTYPE *yypv;			/* top of value stack */
1555 int *yyps;			/* top of state stack */
1556 
1557 int yystate;			/* current state */
1558 int yytmp;			/* extra var (lasts between blocks) */
1559 
1560 int yynerrs;			/* number of errors */
1561 int yyerrflag;			/* error recovery flag */
1562 int yychar;			/* current input token number */
1563 
1564 
1565 
1566 #ifdef YYNMBCHARS
1567 #define YYLEX()		yycvtok(yylex())
1568 /*
1569 ** yycvtok - return a token if i is a wchar_t value that exceeds 255.
1570 **	If i<255, i itself is the token.  If i>255 but the neither
1571 **	of the 30th or 31st bit is on, i is already a token.
1572 */
1573 #if defined(__STDC__) || defined(__cplusplus)
1574 int yycvtok(int i)
1575 #else
1576 int yycvtok(i) int i;
1577 #endif
1578 {
1579 	int first = 0;
1580 	int last = YYNMBCHARS - 1;
1581 	int mid;
1582 	wchar_t j;
1583 
1584 	if(i&0x60000000){/*Must convert to a token. */
1585 		if( yymbchars[last].character < i ){
1586 			return i;/*Giving up*/
1587 		}
1588 		while ((last>=first)&&(first>=0)) {/*Binary search loop*/
1589 			mid = (first+last)/2;
1590 			j = yymbchars[mid].character;
1591 			if( j==i ){/*Found*/
1592 				return yymbchars[mid].tvalue;
1593 			}else if( j<i ){
1594 				first = mid + 1;
1595 			}else{
1596 				last = mid -1;
1597 			}
1598 		}
1599 		/*No entry in the table.*/
1600 		return i;/* Giving up.*/
1601 	}else{/* i is already a token. */
1602 		return i;
1603 	}
1604 }
1605 #else/*!YYNMBCHARS*/
1606 #define YYLEX()		yylex()
1607 #endif/*!YYNMBCHARS*/
1608 
1609 /*
1610 ** yyparse - return 0 if worked, 1 if syntax error not recovered from
1611 */
1612 #if defined(__STDC__) || defined(__cplusplus)
1613 int yyparse(void)
1614 #else
1615 int yyparse()
1616 #endif
1617 {
1618 	register YYSTYPE *yypvt = 0;	/* top of value stack for $vars */
1619 
1620 #if defined(__cplusplus) || defined(lint)
1621 /*
1622 	hacks to please C++ and lint - goto's inside
1623 	switch should never be executed
1624 */
1625 	static int __yaccpar_lint_hack__ = 0;
1626 	switch (__yaccpar_lint_hack__)
1627 	{
1628 		case 1: goto yyerrlab;
1629 		case 2: goto yynewstate;
1630 	}
1631 #endif
1632 
1633 	/*
1634 	** Initialize externals - yyparse may be called more than once
1635 	*/
1636 	yypv = &yyv[-1];
1637 	yyps = &yys[-1];
1638 	yystate = 0;
1639 	yytmp = 0;
1640 	yynerrs = 0;
1641 	yyerrflag = 0;
1642 	yychar = -1;
1643 
1644 #if YYMAXDEPTH <= 0
1645 	if (yymaxdepth <= 0)
1646 	{
1647 		if ((yymaxdepth = YYEXPAND(0)) <= 0)
1648 		{
1649 			yyerror("yacc initialization error");
1650 			YYABORT;
1651 		}
1652 	}
1653 #endif
1654 
1655 	{
1656 		register YYSTYPE *yy_pv;	/* top of value stack */
1657 		register int *yy_ps;		/* top of state stack */
1658 		register int yy_state;		/* current state */
1659 		register int  yy_n;		/* internal state number info */
1660 	goto yystack;	/* moved from 6 lines above to here to please C++ */
1661 
1662 		/*
1663 		** get globals into registers.
1664 		** branch to here only if YYBACKUP was called.
1665 		*/
1666 	yynewstate:
1667 		yy_pv = yypv;
1668 		yy_ps = yyps;
1669 		yy_state = yystate;
1670 		goto yy_newstate;
1671 
1672 		/*
1673 		** get globals into registers.
1674 		** either we just started, or we just finished a reduction
1675 		*/
1676 	yystack:
1677 		yy_pv = yypv;
1678 		yy_ps = yyps;
1679 		yy_state = yystate;
1680 
1681 		/*
1682 		** top of for (;;) loop while no reductions done
1683 		*/
1684 	yy_stack:
1685 		/*
1686 		** put a state and value onto the stacks
1687 		*/
1688 #if YYDEBUG
1689 		/*
1690 		** if debugging, look up token value in list of value vs.
1691 		** name pairs.  0 and negative (-1) are special values.
1692 		** Note: linear search is used since time is not a real
1693 		** consideration while debugging.
1694 		*/
1695 		if ( yydebug )
1696 		{
1697 			register int yy_i;
1698 
1699 			printf( "State %d, token ", yy_state );
1700 			if ( yychar == 0 )
1701 				printf( "end-of-file\n" );
1702 			else if ( yychar < 0 )
1703 				printf( "-none-\n" );
1704 			else
1705 			{
1706 				for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
1707 					yy_i++ )
1708 				{
1709 					if ( yytoks[yy_i].t_val == yychar )
1710 						break;
1711 				}
1712 				printf( "%s\n", yytoks[yy_i].t_name );
1713 			}
1714 		}
1715 #endif /* YYDEBUG */
1716 		if ( ++yy_ps >= &yys[ yymaxdepth ] )	/* room on stack? */
1717 		{
1718 			/*
1719 			** reallocate and recover.  Note that pointers
1720 			** have to be reset, or bad things will happen
1721 			*/
1722 			long yyps_index = (yy_ps - yys);
1723 			long yypv_index = (yy_pv - yyv);
1724 			long yypvt_index = (yypvt - yyv);
1725 			int yynewmax;
1726 #ifdef YYEXPAND
1727 			yynewmax = YYEXPAND(yymaxdepth);
1728 #else
1729 			yynewmax = 2 * yymaxdepth;	/* double table size */
1730 			if (yymaxdepth == YYMAXDEPTH)	/* first time growth */
1731 			{
1732 				char *newyys = (char *)YYNEW(int);
1733 				char *newyyv = (char *)YYNEW(YYSTYPE);
1734 				if (newyys != 0 && newyyv != 0)
1735 				{
1736 					yys = YYCOPY(newyys, yys, int);
1737 					yyv = YYCOPY(newyyv, yyv, YYSTYPE);
1738 				}
1739 				else
1740 					yynewmax = 0;	/* failed */
1741 			}
1742 			else				/* not first time */
1743 			{
1744 				yys = YYENLARGE(yys, int);
1745 				yyv = YYENLARGE(yyv, YYSTYPE);
1746 				if (yys == 0 || yyv == 0)
1747 					yynewmax = 0;	/* failed */
1748 			}
1749 #endif
1750 			if (yynewmax <= yymaxdepth)	/* tables not expanded */
1751 			{
1752 				yyerror( "yacc stack overflow" );
1753 				YYABORT;
1754 			}
1755 			yymaxdepth = yynewmax;
1756 
1757 			yy_ps = yys + yyps_index;
1758 			yy_pv = yyv + yypv_index;
1759 			yypvt = yyv + yypvt_index;
1760 		}
1761 		*yy_ps = yy_state;
1762 		*++yy_pv = yyval;
1763 
1764 		/*
1765 		** we have a new state - find out what to do
1766 		*/
1767 	yy_newstate:
1768 		if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG )
1769 			goto yydefault;		/* simple state */
1770 #if YYDEBUG
1771 		/*
1772 		** if debugging, need to mark whether new token grabbed
1773 		*/
1774 		yytmp = yychar < 0;
1775 #endif
1776 		if ( ( yychar < 0 ) && ( ( yychar = YYLEX() ) < 0 ) )
1777 			yychar = 0;		/* reached EOF */
1778 #if YYDEBUG
1779 		if ( yydebug && yytmp )
1780 		{
1781 			register int yy_i;
1782 
1783 			printf( "Received token " );
1784 			if ( yychar == 0 )
1785 				printf( "end-of-file\n" );
1786 			else if ( yychar < 0 )
1787 				printf( "-none-\n" );
1788 			else
1789 			{
1790 				for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
1791 					yy_i++ )
1792 				{
1793 					if ( yytoks[yy_i].t_val == yychar )
1794 						break;
1795 				}
1796 				printf( "%s\n", yytoks[yy_i].t_name );
1797 			}
1798 		}
1799 #endif /* YYDEBUG */
1800 		if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) )
1801 			goto yydefault;
1802 		if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar )	/*valid shift*/
1803 		{
1804 			yychar = -1;
1805 			yyval = yylval;
1806 			yy_state = yy_n;
1807 			if ( yyerrflag > 0 )
1808 				yyerrflag--;
1809 			goto yy_stack;
1810 		}
1811 
1812 	yydefault:
1813 		if ( ( yy_n = yydef[ yy_state ] ) == -2 )
1814 		{
1815 #if YYDEBUG
1816 			yytmp = yychar < 0;
1817 #endif
1818 			if ( ( yychar < 0 ) && ( ( yychar = YYLEX() ) < 0 ) )
1819 				yychar = 0;		/* reached EOF */
1820 #if YYDEBUG
1821 			if ( yydebug && yytmp )
1822 			{
1823 				register int yy_i;
1824 
1825 				printf( "Received token " );
1826 				if ( yychar == 0 )
1827 					printf( "end-of-file\n" );
1828 				else if ( yychar < 0 )
1829 					printf( "-none-\n" );
1830 				else
1831 				{
1832 					for ( yy_i = 0;
1833 						yytoks[yy_i].t_val >= 0;
1834 						yy_i++ )
1835 					{
1836 						if ( yytoks[yy_i].t_val
1837 							== yychar )
1838 						{
1839 							break;
1840 						}
1841 					}
1842 					printf( "%s\n", yytoks[yy_i].t_name );
1843 				}
1844 			}
1845 #endif /* YYDEBUG */
1846 			/*
1847 			** look through exception table
1848 			*/
1849 			{
1850 				register YYCONST int *yyxi = yyexca;
1851 
1852 				while ( ( *yyxi != -1 ) ||
1853 					( yyxi[1] != yy_state ) )
1854 				{
1855 					yyxi += 2;
1856 				}
1857 				while ( ( *(yyxi += 2) >= 0 ) &&
1858 					( *yyxi != yychar ) )
1859 					;
1860 				if ( ( yy_n = yyxi[1] ) < 0 )
1861 					YYACCEPT;
1862 			}
1863 		}
1864 
1865 		/*
1866 		** check for syntax error
1867 		*/
1868 		if ( yy_n == 0 )	/* have an error */
1869 		{
1870 			/* no worry about speed here! */
1871 			switch ( yyerrflag )
1872 			{
1873 			case 0:		/* new error */
1874 				yyerror( "syntax error" );
1875 				goto skip_init;
1876 			yyerrlab:
1877 				/*
1878 				** get globals into registers.
1879 				** we have a user generated syntax type error
1880 				*/
1881 				yy_pv = yypv;
1882 				yy_ps = yyps;
1883 				yy_state = yystate;
1884 			skip_init:
1885 				yynerrs++;
1886 				/* FALLTHRU */
1887 			case 1:
1888 			case 2:		/* incompletely recovered error */
1889 					/* try again... */
1890 				yyerrflag = 3;
1891 				/*
1892 				** find state where "error" is a legal
1893 				** shift action
1894 				*/
1895 				while ( yy_ps >= yys )
1896 				{
1897 					yy_n = yypact[ *yy_ps ] + YYERRCODE;
1898 					if ( yy_n >= 0 && yy_n < YYLAST &&
1899 						yychk[yyact[yy_n]] == YYERRCODE)					{
1900 						/*
1901 						** simulate shift of "error"
1902 						*/
1903 						yy_state = yyact[ yy_n ];
1904 						goto yy_stack;
1905 					}
1906 					/*
1907 					** current state has no shift on
1908 					** "error", pop stack
1909 					*/
1910 #if YYDEBUG
1911 #	define _POP_ "Error recovery pops state %d, uncovers state %d\n"
1912 					if ( yydebug )
1913 						printf( _POP_, *yy_ps,
1914 							yy_ps[-1] );
1915 #	undef _POP_
1916 #endif
1917 					yy_ps--;
1918 					yy_pv--;
1919 				}
1920 				/*
1921 				** there is no state on stack with "error" as
1922 				** a valid shift.  give up.
1923 				*/
1924 				YYABORT;
1925 			case 3:		/* no shift yet; eat a token */
1926 #if YYDEBUG
1927 				/*
1928 				** if debugging, look up token in list of
1929 				** pairs.  0 and negative shouldn't occur,
1930 				** but since timing doesn't matter when
1931 				** debugging, it doesn't hurt to leave the
1932 				** tests here.
1933 				*/
1934 				if ( yydebug )
1935 				{
1936 					register int yy_i;
1937 
1938 					printf( "Error recovery discards " );
1939 					if ( yychar == 0 )
1940 						printf( "token end-of-file\n" );
1941 					else if ( yychar < 0 )
1942 						printf( "token -none-\n" );
1943 					else
1944 					{
1945 						for ( yy_i = 0;
1946 							yytoks[yy_i].t_val >= 0;
1947 							yy_i++ )
1948 						{
1949 							if ( yytoks[yy_i].t_val
1950 								== yychar )
1951 							{
1952 								break;
1953 							}
1954 						}
1955 						printf( "token %s\n",
1956 							yytoks[yy_i].t_name );
1957 					}
1958 				}
1959 #endif /* YYDEBUG */
1960 				if ( yychar == 0 )	/* reached EOF. quit */
1961 					YYABORT;
1962 				yychar = -1;
1963 				goto yy_newstate;
1964 			}
1965 		}/* end if ( yy_n == 0 ) */
1966 		/*
1967 		** reduction by production yy_n
1968 		** put stack tops, etc. so things right after switch
1969 		*/
1970 #if YYDEBUG
1971 		/*
1972 		** if debugging, print the string that is the user's
1973 		** specification of the reduction which is just about
1974 		** to be done.
1975 		*/
1976 		if ( yydebug )
1977 			printf( "Reduce by (%d) \"%s\"\n",
1978 				yy_n, yyreds[ yy_n ] );
1979 #endif
1980 		yytmp = yy_n;			/* value to switch over */
1981 		yypvt = yy_pv;			/* $vars top of value stack */
1982 		/*
1983 		** Look in goto table for next state
1984 		** Sorry about using yy_state here as temporary
1985 		** register variable, but why not, if it works...
1986 		** If yyr2[ yy_n ] doesn't have the low order bit
1987 		** set, then there is no action to be done for
1988 		** this reduction.  So, no saving & unsaving of
1989 		** registers done.  The only difference between the
1990 		** code just after the if and the body of the if is
1991 		** the goto yy_stack in the body.  This way the test
1992 		** can be made before the choice of what to do is needed.
1993 		*/
1994 		{
1995 			/* length of production doubled with extra bit */
1996 			register int yy_len = yyr2[ yy_n ];
1997 
1998 			if ( !( yy_len & 01 ) )
1999 			{
2000 				yy_len >>= 1;
2001 				yyval = ( yy_pv -= yy_len )[1];	/* $$ = $1 */
2002 				yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
2003 					*( yy_ps -= yy_len ) + 1;
2004 				if ( yy_state >= YYLAST ||
2005 					yychk[ yy_state =
2006 					yyact[ yy_state ] ] != -yy_n )
2007 				{
2008 					yy_state = yyact[ yypgo[ yy_n ] ];
2009 				}
2010 				goto yy_stack;
2011 			}
2012 			yy_len >>= 1;
2013 			yyval = ( yy_pv -= yy_len )[1];	/* $$ = $1 */
2014 			yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
2015 				*( yy_ps -= yy_len ) + 1;
2016 			if ( yy_state >= YYLAST ||
2017 				yychk[ yy_state = yyact[ yy_state ] ] != -yy_n )
2018 			{
2019 				yy_state = yyact[ yypgo[ yy_n ] ];
2020 			}
2021 		}
2022 					/* save until reenter driver code */
2023 		yystate = yy_state;
2024 		yyps = yy_ps;
2025 		yypv = yy_pv;
2026 	}
2027 	/*
2028 	** code supplied by user is placed in this switch
2029 	*/
2030 	switch( yytmp )
2031 	{
2032 
2033 case 1:
2034 # line 244 "poolcfg.y"
2035 {
2036 		if (yypvt[-0].cmd->cmd != NULL)
2037 			yypvt[-0].cmd->cmd(yypvt[-0].cmd);
2038 		free_cmd(yypvt[-0].cmd);
2039 	} break;
2040 case 2:
2041 # line 250 "poolcfg.y"
2042 {
2043 		if (yypvt[-0].cmd->cmd != NULL)
2044 			yypvt[-0].cmd->cmd(yypvt[-0].cmd);
2045 		free_cmd(yypvt[-0].cmd);
2046 	} break;
2047 case 3:
2048 # line 255 "poolcfg.y"
2049 { YYERROR;} break;
2050 case 5:
2051 # line 259 "poolcfg.y"
2052 {
2053 		if (conf_edit_error != POE_OK) {
2054 			if (yypvt[-0].cmd->cmd != parser_conf_create &&
2055 			    yypvt[-0].cmd->cmd != parser_conf_discover) {
2056 				die(gettext(ERR_CONF_LOAD), conf_file,
2057 				    get_errstr_err(conf_edit_error,
2058 				        conf_edit_errno));
2059 			}
2060 		}
2061 		edited = PO_TRUE;
2062 	} break;
2063 case 6:
2064 # line 272 "poolcfg.y"
2065 {
2066 		if (conf_list_error != POE_OK) {
2067 			if (yypvt[-0].cmd->cmd != parser_conf_create &&
2068 			    yypvt[-0].cmd->cmd != parser_conf_discover) {
2069 				die(gettext(ERR_CONF_LOAD), conf_file,
2070 				    get_errstr_err(conf_list_error,
2071 				        conf_list_errno));
2072 			}
2073 		}
2074 	} break;
2075 case 7:
2076 # line 282 "poolcfg.y"
2077 {conf_list_error = conf_edit_error = POE_OK;} break;
2078 case 14:
2079 # line 292 "poolcfg.y"
2080 {
2081 		if ((yyval.cmd = alloc_cmd()) == NULL)
2082 			YYERROR;
2083 		cmd = yyval.cmd;
2084 		yyval.cmd->cmd = &parser_conf_info;
2085 	} break;
2086 case 15:
2087 # line 299 "poolcfg.y"
2088 {
2089 		if ((yyval.cmd = alloc_cmd()) == NULL)
2090 			YYERROR;
2091 		cmd = yyval.cmd;
2092 		switch (yypvt[-1].ival) {
2093 		case PCE_SYSTEM:
2094 			yyval.cmd->cmd = &parser_conf_info;
2095 			break;
2096 		case PCE_POOL:
2097 			yyval.cmd->cmd = &parser_pool_info;
2098 			break;
2099 		case PCE_PSET:
2100 			yyval.cmd->cmd = &parser_pset_info;
2101 			break;
2102 		case PCE_CPU:
2103 			yyval.cmd->cmd = &parser_cpu_info;
2104 			break;
2105 		default:
2106 			warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival);
2107 			YYERROR;
2108 		}
2109 		yyval.cmd->cmd_tgt1 = yypvt[-0].sval;
2110 	} break;
2111 case 16:
2112 # line 324 "poolcfg.y"
2113 {
2114 		if ((yyval.cmd = alloc_cmd()) == NULL)
2115 			YYERROR;
2116 		cmd = yyval.cmd;
2117 		switch (yypvt[-1].ival) {
2118 		case PCE_SYSTEM:
2119 			yyval.cmd->cmd = &parser_conf_create;
2120 			/*
2121 			 * When creating a new system element, ensure
2122 			 * pre-existing errors are ignored.
2123 			 */
2124 			conf_list_error = conf_edit_error = POE_OK;
2125 			break;
2126 		case PCE_POOL:
2127 			yyval.cmd->cmd = &parser_pool_create;
2128 			break;
2129 		case PCE_PSET:
2130 			yyval.cmd->cmd = &parser_pset_create;
2131 			break;
2132 		default:
2133 			warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival);
2134 			YYERROR;
2135 		}
2136 		yyval.cmd->cmd_tgt1 = yypvt[-0].sval;
2137 	} break;
2138 case 18:
2139 # line 352 "poolcfg.y"
2140 {
2141 		if ((yyval.cmd = alloc_cmd()) == NULL)
2142 			YYERROR;
2143 		cmd = yyval.cmd;
2144 		switch (yypvt[-1].ival) {
2145 		case PCE_SYSTEM:
2146 			yyval.cmd->cmd = &parser_conf_destroy;
2147 			break;
2148 		case PCE_POOL:
2149 			yyval.cmd->cmd = &parser_pool_destroy;
2150 			break;
2151 		case PCE_PSET:
2152 			yyval.cmd->cmd = &parser_pset_destroy;
2153 			break;
2154 		default:
2155 			warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival);
2156 			YYERROR;
2157 		}
2158 		yyval.cmd->cmd_tgt1 = yypvt[-0].sval;
2159 	} break;
2160 case 19:
2161 # line 374 "poolcfg.y"
2162 {
2163 		if ((yyval.cmd = alloc_cmd()) == NULL)
2164 			YYERROR;
2165 		cmd = yyval.cmd;
2166 		switch (yypvt[-1].ival) {
2167 		case PCE_SYSTEM:
2168 			yyval.cmd->cmd = &parser_conf_modify;
2169 			break;
2170 		case PCE_POOL:
2171 			yyval.cmd->cmd = &parser_pool_modify;
2172 			break;
2173 		case PCE_PSET:
2174 			yyval.cmd->cmd = &parser_pset_modify;
2175 			break;
2176 		case PCE_CPU:
2177 			yyval.cmd->cmd = &parser_cpu_modify;
2178 			break;
2179 		default:
2180 			warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival);
2181 			YYERROR;
2182 		}
2183 		yyval.cmd->cmd_tgt1 = yypvt[-0].sval;
2184 	} break;
2185 case 21:
2186 # line 400 "poolcfg.y"
2187 {
2188 		if ((yyval.cmd = alloc_cmd()) == NULL)
2189 			YYERROR;
2190 		cmd = yyval.cmd;
2191 		yyval.cmd->cmd = &parser_pool_associate;
2192 		cmd->cmd_tgt1 = yypvt[-0].sval;
2193 	} break;
2194 case 25:
2195 # line 413 "poolcfg.y"
2196 {
2197 		if ((yyval.cmd = alloc_cmd()) == NULL)
2198 			YYERROR;
2199 		cmd = yyval.cmd;
2200 		yyval.cmd->cmd = &parser_resource_xtransfer;
2201 		cmd->cmd_tgt1 = yypvt[-0].sval;
2202 	} break;
2203 case 27:
2204 # line 423 "poolcfg.y"
2205 {
2206 		if ((yyval.cmd = alloc_cmd()) == NULL)
2207 			YYERROR;
2208 		cmd = yyval.cmd;
2209 		yyval.cmd->cmd = &parser_resource_transfer;
2210 		cmd->cmd_tgt1 = yypvt[-2].sval;
2211 		cmd->cmd_tgt2 = yypvt[-0].sval;
2212 		cmd->cmd_qty = yypvt[-5].uval;
2213 	} break;
2214 case 28:
2215 # line 433 "poolcfg.y"
2216 {
2217 		if ((yyval.cmd = alloc_cmd()) == NULL)
2218 			YYERROR;
2219 		cmd = yyval.cmd;
2220 		yyval.cmd->cmd = &parser_resource_transfer;
2221 		cmd->cmd_tgt1 = yypvt[-0].sval;
2222 		cmd->cmd_tgt2 = yypvt[-2].sval;
2223 		cmd->cmd_qty = yypvt[-5].uval;
2224 	} break;
2225 case 29:
2226 # line 444 "poolcfg.y"
2227 {
2228 		if ((yyval.cmd = alloc_cmd()) == NULL)
2229 			YYERROR;
2230 		cmd = yyval.cmd;
2231 		yyval.cmd->cmd = &parser_conf_discover;
2232 	} break;
2233 case 30:
2234 # line 452 "poolcfg.y"
2235 {
2236 		if ((yyval.cmd = alloc_cmd()) == NULL)
2237 			YYERROR;
2238 		cmd = yyval.cmd;
2239 		switch (yypvt[-3].ival) {
2240 		case PCE_SYSTEM:
2241 			yyval.cmd->cmd = &parser_conf_rename;
2242 			break;
2243 		case PCE_POOL:
2244 			yyval.cmd->cmd = &parser_pool_rename;
2245 			break;
2246 		case PCE_PSET:
2247 			yyval.cmd->cmd = &parser_pset_rename;
2248 			break;
2249 		default:
2250 			warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-3].ival);
2251 			YYERROR;
2252 		}
2253 		yyval.cmd->cmd_tgt1 = yypvt[-2].sval;
2254 		yyval.cmd->cmd_tgt2 = yypvt[-0].sval;
2255 	} break;
2256 case 32:
2257 # line 475 "poolcfg.y"
2258 {yyval.ival = PCE_CPU;} break;
2259 case 34:
2260 # line 478 "poolcfg.y"
2261 {yyval.ival = PCE_CPU;} break;
2262 case 35:
2263 # line 480 "poolcfg.y"
2264 {yyval.ival = PCE_SYSTEM;} break;
2265 case 36:
2266 # line 481 "poolcfg.y"
2267 {yyval.ival = PCE_POOL;} break;
2268 case 37:
2269 # line 482 "poolcfg.y"
2270 {yyval.ival = PCE_PSET;} break;
2271 case 41:
2272 # line 490 "poolcfg.y"
2273 { yyval.val.i = yypvt[-0].ival;} break;
2274 case 42:
2275 # line 491 "poolcfg.y"
2276 { yyval.val.u = yypvt[-0].uval;} break;
2277 case 43:
2278 # line 492 "poolcfg.y"
2279 { yyval.val.d = yypvt[-0].dval;} break;
2280 case 44:
2281 # line 493 "poolcfg.y"
2282 { yyval.val.b = yypvt[-0].bval;} break;
2283 case 45:
2284 # line 494 "poolcfg.y"
2285 { yyval.val.s = yypvt[-0].sval;} break;
2286 case 46:
2287 # line 497 "poolcfg.y"
2288 {
2289 		if ((yyval.prop = alloc_prop(po_remove)) == NULL)
2290 			YYERROR;
2291 		yyval.prop->prop_name = yypvt[-0].sval;
2292 	} break;
2293 case 49:
2294 # line 507 "poolcfg.y"
2295 {
2296 		prop_t *prop = NULL;
2297 		prop_t *prev = NULL;
2298 
2299 		for (prop = cmd->cmd_prop_list; prop != NULL;
2300 		    prop = prop->prop_next)
2301 			prev = prop; /* Find end of list */
2302 		if (prev != NULL)
2303 			prev->prop_next = yypvt[-0].prop;
2304 		else
2305 			cmd->cmd_prop_list = yypvt[-0].prop;
2306 		yyval.prop = cmd->cmd_prop_list;
2307 	} break;
2308 case 50:
2309 # line 521 "poolcfg.y"
2310 {
2311 		prop_t *prop = NULL;
2312 		prop_t *prev = NULL;
2313 
2314 		for (prop = cmd->cmd_prop_list; prop != NULL;
2315 		    prop = prop->prop_next)
2316 			prev = prop; /* Find end of list */
2317 		if (prev != NULL)
2318 			prev->prop_next = yypvt[-0].prop;
2319 		else
2320 			cmd->cmd_prop_list = yypvt[-0].prop;
2321 		yyval.prop = cmd->cmd_prop_list;
2322 
2323 	} break;
2324 case 51:
2325 # line 537 "poolcfg.y"
2326 {
2327 		if ((yyval.prop = alloc_prop(po_create)) == NULL)
2328 			YYERROR;
2329 		yyval.prop->prop_name = yypvt[-2].sval;
2330 		switch (yypvt[-3].ival) {
2331 		case PCT_INT:
2332 			pool_value_set_int64(yyval.prop->prop_value, yypvt[-0].val.i);
2333 			break;
2334 		case PCT_UINT:
2335 			pool_value_set_uint64(yyval.prop->prop_value, yypvt[-0].val.u);
2336 			break;
2337 		case PCT_BOOLEAN:
2338 			pool_value_set_bool(yyval.prop->prop_value, yypvt[-0].val.b);
2339 			break;
2340 		case PCT_FLOAT:
2341 			pool_value_set_double(yyval.prop->prop_value, yypvt[-0].val.d);
2342 			break;
2343 		case PCT_STRING:
2344 			pool_value_set_string(yyval.prop->prop_value, yypvt[-0].val.s);
2345 			break;
2346 		}
2347 	} break;
2348 case 52:
2349 # line 561 "poolcfg.y"
2350 {
2351 		yyval.prop = yypvt[-1].prop;
2352 	} break;
2353 case 53:
2354 # line 566 "poolcfg.y"
2355 {
2356 		assoc_t *assoc = NULL;
2357 		assoc_t *prev = NULL;
2358 
2359 		for (assoc = cmd->cmd_assoc_list; assoc != NULL;
2360 		    assoc = assoc->assoc_next)
2361 			prev = assoc; /* Find end of list */
2362 		if (prev != NULL)
2363 			prev->assoc_next = yypvt[-0].assoc;
2364 		else
2365 			cmd->cmd_assoc_list = yypvt[-0].assoc;
2366 		yyval.assoc = cmd->cmd_assoc_list;
2367 	} break;
2368 case 54:
2369 # line 581 "poolcfg.y"
2370 {
2371 		assoc_t *assoc = NULL;
2372 		assoc_t *prev = NULL;
2373 
2374 		for (assoc = cmd->cmd_assoc_list; assoc != NULL;
2375 		    assoc = assoc->assoc_next)
2376 			prev = assoc; /* Find end of list */
2377 		if (prev != NULL)
2378 			prev->assoc_next = yypvt[-0].assoc;
2379 		yyval.assoc = yypvt[-0].assoc;
2380 	} break;
2381 case 55:
2382 # line 594 "poolcfg.y"
2383 {
2384 		if ((yyval.assoc = alloc_assoc(yypvt[-1].ival, yypvt[-0].sval)) == NULL)
2385 			YYERROR;
2386 	} break;
2387 case 56:
2388 # line 599 "poolcfg.y"
2389 {yyval.ival = PCE_PSET;} break;
2390 case 57:
2391 # line 602 "poolcfg.y"
2392 {
2393 		yyval.assoc = yypvt[-1].assoc;
2394 	} break;
2395 case 58:
2396 # line 607 "poolcfg.y"
2397 {
2398 		assoc_t *assoc = NULL;
2399 		assoc_t *prev = NULL;
2400 
2401 		for (assoc = cmd->cmd_assoc_list; assoc != NULL;
2402 		    assoc = assoc->assoc_next)
2403 			prev = assoc; /* Find end of list */
2404 		if (prev != NULL)
2405 			prev->assoc_next = yypvt[-0].assoc;
2406 		else
2407 			cmd->cmd_assoc_list = yypvt[-0].assoc;
2408 		yyval.assoc = cmd->cmd_assoc_list;
2409 	} break;
2410 case 59:
2411 # line 622 "poolcfg.y"
2412 {
2413 		assoc_t *assoc = NULL;
2414 		assoc_t *prev = NULL;
2415 
2416 		for (assoc = cmd->cmd_assoc_list; assoc != NULL;
2417 		    assoc = assoc->assoc_next)
2418 			prev = assoc; /* Find end of list */
2419 		if (prev != NULL)
2420 			prev->assoc_next = yypvt[-0].assoc;
2421 		yyval.assoc = yypvt[-0].assoc;
2422 	} break;
2423 case 60:
2424 # line 635 "poolcfg.y"
2425 {
2426 		yyval.assoc = yypvt[-1].assoc;
2427 	} break;
2428 case 61:
2429 # line 640 "poolcfg.y"
2430 {
2431 		if ((yyval.assoc = alloc_assoc(yypvt[-1].ival, yypvt[-0].sval)) == NULL)
2432 			YYERROR;
2433 	} break;
2434 case 62:
2435 # line 645 "poolcfg.y"
2436 {yyval.ival = PCE_CPU;} break;
2437 case 63:
2438 # line 647 "poolcfg.y"
2439 {yyval.ival = PCT_INT;} break;
2440 case 64:
2441 # line 648 "poolcfg.y"
2442 {yyval.ival = PCT_UINT;} break;
2443 case 65:
2444 # line 649 "poolcfg.y"
2445 {yyval.ival = PCT_BOOLEAN;} break;
2446 case 66:
2447 # line 650 "poolcfg.y"
2448 {yyval.ival = PCT_FLOAT;} break;
2449 case 67:
2450 # line 651 "poolcfg.y"
2451 {yyval.ival = PCT_STRING;} break;
2452 # line	556 "/usr/share/lib/ccs/yaccpar"
2453 	}
2454 	goto yystack;		/* reset registers in driver code */
2455 }
2456 
2457