# line 2 "poolcfg.y" /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * Overview of poolcfg(1) * * poolcfg(1) implements a small grammar for manipulating pools configurations. * yacc(1) is used to generate the parser and poolcfg.l contains a simple lexer * (generted by lex(1)) to perform lexical processsing of the input. * * Refer to the poolcfg(1) manpage for more details of the grammar. * * The parser is designed so that all operations implement the same interface. * This allows the parser to simply build up the command (using the cmd * variable) by storing arguments and a pointer to the desired function in the * cmd. The command is executed when the commands production is matched. * * Properties and associations are stored in simple linked lists and processed * in the order submitted by the user. */ #include #include #include #include #include #include #include #include #include #include "utils.h" #include "poolcfg.h" #define USAGE1 \ "Usage:\n" \ "%s -h\n" \ "%s -c command [ -d | [ file ] ]\n" \ "%s -f command-file [-d | [ file ] ]\n\n" #define USAGE2 \ "command:\n" \ " info [entity name]\n" \ " display configuration (or specified portion) in readable form\n" \ " create entity name [property-list]\n" \ " make an entity of the specified type and name\n" \ " destroy entity name\n" \ " remove the specified entity\n" \ " modify entity name [property-list]\n" \ " change the listed properties on the named entity\n" \ " associate pool name [resource-list]\n" \ " connect one or more resources to a pool, or replace one or more\n" \ " existing connections\n" \ " transfer to resource name [component-list]\n" \ " transfer one or more discreet components to a resource\n" \ " transfer [quantity] from resource src to tgt\n" \ " transfer a resource quantity from src to tgt\n" \ " transfer [quantity] to resource tgt from src\n" \ " transfer a resource quantity to tgt from src\n" \ " discover\n" \ " create a system entity, with one pool entity and resources to\n" \ " match current system configuration\n" \ " rename entity old_name to new_name\n" \ " change the name of the entity on the system to its new name\n\n" \ "property-list:\n" \ " ( proptype name = value [ ; proptype name = value ]* )\n" \ " where multiple definitions in the sentence for a given\n" \ " proptype, name pair are ignored; the last one provided is used.\n" \ " For property deletion, use \"~ proptype name\"\n\n" \ "resource-list:\n" \ " ( resource name [; resource name ] )\n" \ " where multiple uses of a resource are ignored; the last provided\n" \ " is the one used.\n" \ " There is no deletion syntax for resource lists.\n" \ "component-list:\n" \ " ( cpu id [; cpu id ] )\n" \ " where multiple uses of the same component cause the last provided\n" \ " to be the one used.\n" \ " There is no deletion syntax for component lists.\n" \ "entity:\n" \ " system | pool | pset | cpu\n" \ " where cpu is only valid for transfer, info and modify commands.\n" \ "resource:\n" \ " pset\n\n" \ "proptype:\n" \ " boolean | int | uint | string | float\n\n" int dofile = PO_FALSE; /* poolcfg.l uses this for errors */ int conf_edit_error = POE_OK; /* cached error for error reporting */ int conf_edit_errno = 0; /* cached errno for error reporting */ int conf_list_error = POE_OK; /* cached error for error reporting */ int conf_list_errno = 0; /* cached errno for error reporting */ static const char cmdname[] = "poolcfg"; static const char cmd_options[] = "c:df:h"; static void usage(int); static const char *max_suffix = ".max"; static const char *min_suffix = ".min"; static const char *conf_file = NULL; /* Location of target config */ static cmd_t *cmd = NULL; /* Command being processed */ static pool_conf_t *conf = NULL; /* Config to be processed */ static int edited = PO_FALSE; /* Has the configuration been changed */ /* yacc externals */ extern FILE *yyin; extern int yydebug; extern void yyerror(char *s); /* Utility functions */ static void arg_parse(const char *); static void file_parse(const char *); static cmd_t *alloc_cmd(void); static prop_t *alloc_prop(prop_op_t); static assoc_t *alloc_assoc(int, const char *); static void free_cmd(cmd_t *); static void check_conf_name(cmd_t *); static void prop_list_walk(cmd_t *, pool_elem_t *); static void assoc_list_walk(cmd_t *, pool_t *); static void transfer_list_walk(cmd_t *, pool_resource_t *); static void terminate(void); static pool_component_t *get_cpu(const char *); static void process_min_max(pool_resource_t *); /* Info Commands */ static void parser_conf_info(cmd_t *); static void parser_pool_info(cmd_t *); static void parser_resource_info(cmd_t *, const char *); static void parser_pset_info(cmd_t *); static void parser_cpu_info(cmd_t *); /* Create Commands */ static void parser_conf_create(cmd_t *); static void parser_pool_create(cmd_t *); static void parser_resource_create(cmd_t *, const char *); static void parser_pset_create(cmd_t *); /* Destroy Commands */ static void parser_conf_destroy(cmd_t *); static void parser_pool_destroy(cmd_t *); static void parser_resource_destroy(cmd_t *, const char *); static void parser_pset_destroy(cmd_t *); /* Modify Commands */ static void parser_conf_modify(cmd_t *); static void parser_pool_modify(cmd_t *); static void parser_resource_modify(cmd_t *, const char *); static void parser_pset_modify(cmd_t *); static void parser_cpu_modify(cmd_t *); /* Associate Commands */ static void parser_pool_associate(cmd_t *); /* Assign Commands */ static void parser_resource_xtransfer(cmd_t *); static void parser_resource_transfer(cmd_t *); /* Discover Commands */ static void parser_conf_discover(cmd_t *); /* Rename Commands */ static void parser_rename(cmd_t *, pool_elem_t *, const char *); static void parser_conf_rename(cmd_t *); static void parser_pool_rename(cmd_t *); static void parser_pset_rename(cmd_t *); # line 196 "poolcfg.y" typedef union #ifdef __cplusplus YYSTYPE #endif { double dval; uint64_t uval; int64_t ival; char *sval; uchar_t bval; cmd_t *cmd; prop_t *prop; pv_u val; assoc_t *assoc; } YYSTYPE; # define PCC_INFO 257 # define PCC_CREATE 258 # define PCC_DESTROY 259 # define PCC_MODIFY 260 # define PCC_ASSOC 261 # define PCC_DISC 262 # define PCC_RENAME 263 # define PCC_TRANSFER 264 # define PCK_FROM 265 # define PCK_TO 266 # define PCK_OPENLST 267 # define PCK_CLOSELST 268 # define PCK_SEPLST 269 # define PCK_ASSIGN 270 # define PCK_UNDEF 271 # define PCK_COMMAND 272 # define PCV_FILENAME 273 # define PCV_SYMBOL 274 # define PCV_VAL_INT 275 # define PCV_VAL_UINT 276 # define PCV_VAL_FLOAT 277 # define PCV_VAL_STRING 278 # define PCV_VAL_BOOLEAN 279 # define PCT_INT 280 # define PCT_UINT 281 # define PCT_BOOLEAN 282 # define PCT_FLOAT 283 # define PCT_STRING 284 # define PCE_SYSTEM 285 # define PCE_POOL 286 # define PCE_PSET 287 # define PCE_CPU 288 #include #ifdef __STDC__ #include #include #define YYCONST const #else #include #include #define YYCONST #endif #include #if defined(__cplusplus) || defined(__STDC__) #if defined(__cplusplus) && defined(__EXTERN_C__) extern "C" { #endif #ifndef yyerror #if defined(__cplusplus) void yyerror(YYCONST char *); #endif #endif #ifndef yylex int yylex(void); #endif int yyparse(void); #if defined(__cplusplus) && defined(__EXTERN_C__) } #endif #endif #define yyclearin yychar = -1 #define yyerrok yyerrflag = 0 extern int yychar; extern int yyerrflag; YYSTYPE yylval; YYSTYPE yyval; typedef int yytabelem; #ifndef YYMAXDEPTH #define YYMAXDEPTH 150 #endif #if YYMAXDEPTH > 0 int yy_yys[YYMAXDEPTH], *yys = yy_yys; YYSTYPE yy_yyv[YYMAXDEPTH], *yyv = yy_yyv; #else /* user does initial allocation */ int *yys; YYSTYPE *yyv; #endif static int yymaxdepth = YYMAXDEPTH; # define YYERRCODE 256 # line 653 "poolcfg.y" #ifndef TEXT_DOMAIN #define TEXT_DOMAIN "SYS_TEST" #endif int main(int argc, char *argv[]) { int opt; int docmd = PO_FALSE; (void) getpname(argv[0]); (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); if (atexit(terminate) != 0) { die(gettext(ERR_SET_TERM), get_errstr()); } conf_file = pool_static_location(); yydebug = 0; while ((opt = getopt(argc, argv, cmd_options)) != (int)EOF) { switch (opt) { case 'c': /* Process command line */ if (dofile == PO_TRUE) usage(1); arg_parse(optarg); docmd = PO_TRUE; break; case 'd': /* Manipulate dynamic configuration */ conf_file = pool_dynamic_location(); break; case 'f': /* Process command file */ if (docmd == PO_TRUE) usage(1); file_parse(optarg); dofile = PO_TRUE; break; case 'h': usage(2); break; case '?': default: usage(1); break; } } if (docmd == PO_FALSE && dofile == PO_FALSE) usage(1); if (optind == argc - 1) { if (strcmp(conf_file, pool_dynamic_location()) == 0) usage(1); conf_file = argv[optind]; } else if (optind < argc - 1) usage(1); if ((conf = pool_conf_alloc()) == NULL) { die(gettext(ERR_ALLOC_ELEMENT), gettext(CONFIGURATION), get_errstr()); } /* * Opening a conf is complex, since we may be opening one of the * following: * - An existing configuration that we can modify * - An existing configuration that we can't modify * - A new configuration that we can modify * - A new configuration that we can't modify * The parser_conf_discover() function closes the file and reopens * in PO_CREAT mode, so we only need be concerned here with the * first two cases. * Always try to open RDWR, if fail try RDONLY. Don't check * if that fails, since we may be trying to discover a configuration * in which case it's valid for both open attempts to fail. Later, when * processing commands, if we don't have a valid configuration and * we are trying to process a command which isn't a create or a discover * we will fail the command as there is no valid configuration to * work with. */ if (pool_conf_open(conf, conf_file, PO_RDWR) != 0) { conf_edit_error = pool_error(); conf_edit_errno = errno; if (pool_conf_open(conf, conf_file, PO_RDONLY) != 0) { conf_list_error = pool_error(); conf_list_errno = errno; } } if (yyparse() == 0) { if (pool_conf_status(conf) >= POF_VALID) { if (pool_conf_validate(conf, POV_STRICT) == PO_FAIL) { die(gettext(ERR_VALIDATION_FAILED), get_errstr()); } /* * If the user attempted to change the configuration, * then we should try to save the changes. */ if (edited == PO_TRUE) { if (pool_conf_commit(conf, 0) == PO_FAIL) { die(gettext(ERR_CONFIG_SAVE_FAILED), get_errstr()); } } pool_conf_close(conf); } } else { die(gettext(ERR_CMDPARSE_FAILED)); } /* * Cleanup is performed in terminate(), using atexit */ return (0); } /* * Info Commands * Invoke the appropriate libpool info function and display the returned * information. */ static void parser_conf_info(cmd_t *cmd) { char *info_buf; const char *tgt = cmd->cmd_tgt1; pool_value_t *pv = NULL; pool_elem_t *pe; if ((pe = pool_conf_to_elem(conf)) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), "unknown", get_errstr()); if (tgt != NULL) check_conf_name(cmd); else { if ((pv = pool_value_alloc()) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), "unknown", get_errstr()); if (pool_get_property(conf, pe, "system.name", pv) == POC_INVAL || pool_value_get_string(pv, &tgt) != PO_SUCCESS) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), "unknown", get_errstr()); } if ((info_buf = pool_conf_info(conf, PO_TRUE)) == NULL) { die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), tgt, get_errstr()); } if (pv != NULL) { pool_value_free(pv); } (void) printf("%s\n", info_buf); free(info_buf); } static void parser_pool_info(cmd_t *cmd) { pool_t *pool; char *info_buf; if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, get_errstr()); if ((info_buf = pool_info(conf, pool, PO_TRUE)) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(POOL), cmd->cmd_tgt1, get_errstr()); (void) printf("%s\n", info_buf); free(info_buf); } static void parser_resource_info(cmd_t *cmd, const char *type) { pool_resource_t *resource; char *info_buf; if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), cmd->cmd_tgt1, get_errstr()); if ((info_buf = pool_resource_info(conf, resource, PO_TRUE)) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(RESOURCE), cmd->cmd_tgt1, get_errstr()); (void) printf("%s\n", info_buf); free(info_buf); } static void parser_pset_info(cmd_t *cmd) { parser_resource_info(cmd, PSET); } static void parser_cpu_info(cmd_t *cmd) { pool_component_t *comp; char *info_buf; if ((comp = get_cpu(cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), cmd->cmd_tgt1, get_errstr()); if ((info_buf = pool_component_info(conf, comp, PO_TRUE)) == NULL) { die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CPU), cmd->cmd_tgt1, get_errstr()); } (void) printf("%s\n", info_buf); free(info_buf); } /* * Create Commands * Invoke the appropriate libpool create function and perform any requested * property operations. */ static void parser_conf_create(cmd_t *cmd) { const char *tmp_name; pool_elem_t *pe; if (conf != NULL && pool_conf_status(conf) >= POF_VALID) pool_conf_close(conf); if (pool_conf_open(conf, conf_file, PO_CREAT) != 0) { die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), cmd->cmd_tgt1, get_errstr()); } tmp_name = cmd->cmd_tgt1; cmd->cmd_tgt1 = cmd->cmd_tgt2; cmd->cmd_tgt2 = tmp_name; parser_conf_rename(cmd); if ((pe = pool_conf_to_elem(conf)) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), "unknown", get_errstr()); prop_list_walk(cmd, pe); } static void parser_pool_create(cmd_t *cmd) { pool_t *pool; if ((pool = pool_create(conf, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_CREATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, get_errstr()); prop_list_walk(cmd, pool_to_elem(conf, pool)); } static void parser_resource_create(cmd_t *cmd, const char *type) { pool_resource_t *resource; if ((resource = pool_resource_create(conf, type, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_CREATE_ELEMENT), type, cmd->cmd_tgt1, get_errstr()); process_min_max(resource); prop_list_walk(cmd, pool_resource_to_elem(conf, resource)); } static void parser_pset_create(cmd_t *cmd) { parser_resource_create(cmd, PSET); } /* * Rename Commands * Rename the target by calling pool_put_property for the name property. */ static void parser_rename(cmd_t *cmd, pool_elem_t *pe, const char *name) { pool_value_t *pv; if ((pv = pool_value_alloc()) == NULL) { die(gettext(ERR_ALLOC_ELEMENT), gettext(RESOURCE), get_errstr()); } pool_value_set_string(pv, cmd->cmd_tgt2); if (pool_put_property(conf, pe, name, pv) != 0) die(gettext(ERR_PUT_PROPERTY), name, get_errstr()); pool_value_free(pv); } static void parser_conf_rename(cmd_t *cmd) { pool_elem_t *pe; if ((pe = pool_conf_to_elem(conf)) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), "unknown", get_errstr()); if (cmd->cmd_tgt1 != NULL) check_conf_name(cmd); parser_rename(cmd, pe, SYSTEM_NAME); } static void parser_pool_rename(cmd_t *cmd) { pool_t *pool; if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, get_errstr()); parser_rename(cmd, pool_to_elem(conf, pool), POOL_NAME); } static void parser_pset_rename(cmd_t *cmd) { pool_resource_t *resource; if ((resource = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(PSET), cmd->cmd_tgt1, get_errstr()); parser_rename(cmd, pool_resource_to_elem(conf, resource), PSET_NAME); } /* * Destroy Commands * Invoke the appropriate libpool destroy function to remove the target of the * command from the configuration. */ static void parser_conf_destroy(cmd_t *cmd) { if (cmd->cmd_tgt1 != NULL) check_conf_name(cmd); if (pool_conf_remove(conf) != 0) die(gettext(ERR_DESTROY_ELEMENT), gettext(CONFIGURATION), cmd->cmd_tgt1, get_errstr()); } static void parser_pool_destroy(cmd_t *cmd) { pool_t *pool; if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, get_errstr()); if (pool_destroy(conf, pool) != 0) die(gettext(ERR_DESTROY_ELEMENT), gettext(POOL), cmd->cmd_tgt1, get_errstr()); } static void parser_resource_destroy(cmd_t *cmd, const char *type) { pool_resource_t *resource; if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), type, cmd->cmd_tgt1, get_errstr()); if (pool_resource_destroy(conf, resource) != 0) die(gettext(ERR_DESTROY_ELEMENT), type, cmd->cmd_tgt1, get_errstr()); } static void parser_pset_destroy(cmd_t *cmd) { parser_resource_destroy(cmd, PSET); } /* * Modify Commands * Perform any requested property operations. */ static void parser_conf_modify(cmd_t *cmd) { pool_elem_t *pe; if ((pe = pool_conf_to_elem(conf)) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), "unknown", get_errstr()); if (cmd->cmd_tgt1 != NULL) check_conf_name(cmd); prop_list_walk(cmd, pe); } static void parser_pool_modify(cmd_t *cmd) { pool_t *pool; if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, get_errstr()); prop_list_walk(cmd, pool_to_elem(conf, pool)); } static void parser_resource_modify(cmd_t *cmd, const char *type) { pool_resource_t *resource; if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), cmd->cmd_tgt1, get_errstr()); process_min_max(resource); prop_list_walk(cmd, pool_resource_to_elem(conf, resource)); } static void parser_pset_modify(cmd_t *cmd) { parser_resource_modify(cmd, PSET); } static void parser_cpu_modify(cmd_t *cmd) { pool_component_t *comp; if ((comp = get_cpu(cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), cmd->cmd_tgt1, get_errstr()); prop_list_walk(cmd, pool_component_to_elem(conf, comp)); } /* * Discover Commands * Invoke the libpool pool_conf_open function so that discovery will be * performed. */ /*ARGSUSED*/ static void parser_conf_discover(cmd_t *cmd) { struct utsname utsname; if (strcmp(conf_file, pool_dynamic_location()) == 0) return; if (uname(&utsname) < 0) die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), "unknown", get_errstr()); if (conf != NULL && pool_conf_status(conf) >= POF_VALID) pool_conf_close(conf); if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) != 0) { die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), utsname.nodename, get_errstr()); } if (pool_conf_export(conf, conf_file, POX_NATIVE) != 0) { die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), utsname.nodename, get_errstr()); } (void) pool_conf_close(conf); if (pool_conf_open(conf, conf_file, PO_RDWR) != 0) { die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), utsname.nodename, get_errstr()); } } /* * Associate Commands * Walk the list of specified associations so that the target pool will be * associated with the required resources. */ static void parser_pool_associate(cmd_t *cmd) { pool_t *pool; if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, get_errstr()); assoc_list_walk(cmd, pool); } /* * Assign Commands * Walk the list of specified assignations so that the required * components will be assigned to the target resource. */ static void parser_resource_xtransfer(cmd_t *cmd) { pool_resource_t *resource; if ((resource = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), cmd->cmd_tgt1, get_errstr()); transfer_list_walk(cmd, resource); } /* * Transfer Commands * Transfer the specified quantity of resource between the src and the tgt. */ static void parser_resource_transfer(cmd_t *cmd) { pool_resource_t *src; pool_resource_t *tgt; if ((src = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), cmd->cmd_tgt1, get_errstr()); if ((tgt = pool_get_resource(conf, PSET, cmd->cmd_tgt2)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), cmd->cmd_tgt2, get_errstr()); if (pool_resource_transfer(conf, src, tgt, cmd->cmd_qty) != PO_SUCCESS) die(gettext(ERR_XFER_QUANTITY), cmd->cmd_qty, cmd->cmd_tgt1, cmd->cmd_tgt2, get_errstr()); } /* * arg_parse() puts the parser into command parsing mode. Create a tmpfile * and instruct the parser to read instructions from this location by setting * yyin to the value returned by tmpfile. Write the command into the file. * Then seek back to to the start of the file so that the parser can read * the instructions. */ static void arg_parse(const char *command) { if ((yyin = tmpfile()) == NULL) die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); if (fwrite(command, strlen(command), 1, yyin) != 1) die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); if (fseek(yyin, 0, SEEK_SET) != 0) die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); } /* * file_parse() puts the parser into command file parsing mode. Firstly check * to see if the user wishes to parse from standard input, if so do nothing. * Attempt to open the specified file and instruct the parser to read * instructions from this location by setting yyin to the value returned by * fopen. */ static void file_parse(const char *file) { if (strcmp(file, "-") == 0) return; if ((yyin = fopen(file, "r")) == NULL) { die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); } } /* * free_cmd() releases the resources associated with the supplied cmd parameter. */ static void free_cmd(cmd_t *cmd) { prop_t *prop = cmd->cmd_prop_list; assoc_t *assoc = cmd->cmd_assoc_list; free((void *)cmd->cmd_tgt1); free((void *)cmd->cmd_tgt2); while (prop != NULL) { prop_t *tmp = prop; prop = prop->prop_next; pool_value_free(tmp->prop_value); free((void *)tmp->prop_name); free(tmp); } while (assoc != NULL) { assoc_t *tmp = assoc; assoc = assoc->assoc_next; free((void *)tmp->assoc_name); free(tmp); } free(cmd); } /* * alloc_cmd() allocates the required resources for a cmd_t. On failure, a * warning is issued and NULL is returned. */ static cmd_t * alloc_cmd(void) { cmd_t *cmd; if ((cmd = malloc(sizeof (cmd_t))) == NULL) { warn(gettext(ERR_CMD_LINE_ALLOC)); return (NULL); } (void) memset(cmd, 0, sizeof (cmd_t)); return (cmd); } /* * alloc_prop() allocates the required resources for a prop_t. On failure, a * warning is issued and NULL is returned. The prop_t is initialised with * the prop_op_t parameter. */ static prop_t * alloc_prop(prop_op_t op) { prop_t *prop; if ((prop = malloc(sizeof (prop_t))) == NULL) { warn(gettext(ERR_PROP_ALLOC)); return (NULL); } (void) memset(prop, 0, sizeof (prop_t)); if ((prop->prop_value = pool_value_alloc()) == NULL) { warn(gettext(ERR_PROP_ALLOC)); free(prop); return (NULL); } prop->prop_op = op; return (prop); } /* * alloc_assoc() allocates the required resources for an assoc_t. On failure, a * warning is issued and NULL is returned. The assoc_t is initialised with * the type and name of the association. */ static assoc_t * alloc_assoc(int type, const char *name) { assoc_t *assoc; if ((assoc = malloc(sizeof (assoc_t))) == NULL) { warn(gettext(ERR_ASSOC_ALLOC)); return (NULL); } (void) memset(assoc, 0, sizeof (assoc_t)); assoc->assoc_type = type; assoc->assoc_name = name; return (assoc); } /* * check_conf_name() ensures the the name of the system in the configuration * which is being manipulated matches the name of the system in the command. * If not, the command is terminated with an appropriate error message. */ static void check_conf_name(cmd_t *cmd) { pool_value_t *pv; const char *name; pool_elem_t *pe; if ((pe = pool_conf_to_elem(conf)) == NULL) die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), "unknown", get_errstr()); if ((pv = pool_value_alloc()) == NULL) { die(gettext(ERR_ALLOC_ELEMENT), gettext(RESOURCE), get_errstr()); } if (pool_get_property(conf, pe, SYSTEM_NAME, pv) == POC_INVAL) die(gettext(ERR_GET_PROPERTY), gettext(SYSTEM_NAME), get_errstr()); if (pool_value_get_string(pv, &name) == PO_FAIL) die(gettext(ERR_GET_PROPERTY), gettext(SYSTEM_NAME), get_errstr()); if (strcmp(cmd->cmd_tgt1, name) != 0) { die(gettext(ERR_WRONG_SYSTEM_NAME), cmd->cmd_tgt1); } pool_value_free(pv); } /* * usage() display brief or verbose help for the poolcfg(1) command. */ static void usage(int help) { if (help >= 1) (void) fprintf(stderr, gettext(USAGE1), cmdname, cmdname, cmdname); if (help >= 2) (void) fprintf(stderr, gettext(USAGE2)); exit(E_USAGE); } /* * prop_list_walk() walks the property manipulation requests and either puts * or removes the property as appropriate. */ static void prop_list_walk(cmd_t *cmd, pool_elem_t *pe) { prop_t *prop; for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) { switch (prop->prop_op) { case po_create: if (pool_put_property(conf, pe, prop->prop_name, prop->prop_value) != 0) die(gettext(ERR_PUT_PROPERTY), prop->prop_name, get_errstr()); break; case po_remove: if (pool_rm_property(conf, pe, prop->prop_name) != 0) die(gettext(ERR_REMOVE_PROPERTY), prop->prop_name, get_errstr()); break; } } } /* * assoc_list_walk() walks the resource association requests and attempts * to associate the pool with the specified resource. */ static void assoc_list_walk(cmd_t *cmd, pool_t *pool) { assoc_t *assoc; for (assoc = cmd->cmd_assoc_list; assoc != NULL; assoc = assoc->assoc_next) { pool_resource_t *resource; switch (assoc->assoc_type) { case PCE_PSET: if ((resource = pool_get_resource(conf, PSET, assoc->assoc_name)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(PSET), assoc->assoc_name, get_errstr()); break; default: die(gettext(ERR_UNKNOWN_RESOURCE), assoc->assoc_type); break; } if (pool_associate(conf, pool, resource) != 0) die(gettext(ERR_ASSOC_RESOURCE), assoc->assoc_name, get_errstr()); } } /* * transfer_list_walk() walks the component assign requests and attempts * to assign the component with the specified resource. */ static void transfer_list_walk(cmd_t *cmd, pool_resource_t *tgt) { assoc_t *assoc; for (assoc = cmd->cmd_assoc_list; assoc != NULL; assoc = assoc->assoc_next) { pool_component_t *comp; pool_resource_t *src; pool_component_t *xfer[2] = {NULL}; if ((comp = get_cpu(assoc->assoc_name)) == NULL) die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), assoc->assoc_name, get_errstr()); if ((src = pool_get_owning_resource(conf, comp)) == NULL) die(gettext(ERR_XFER_COMPONENT), gettext(COMPONENT), assoc->assoc_name, cmd->cmd_tgt1, get_errstr()); xfer[0] = comp; if (pool_resource_xtransfer(conf, src, tgt, xfer) != PO_SUCCESS) die(gettext(ERR_XFER_COMPONENT), gettext(COMPONENT), assoc->assoc_name, cmd->cmd_tgt1, get_errstr()); } } /* * terminate() is invoked when poolcfg exits. It cleans up * configurations and closes the parser input stream. */ static void terminate(void) { if (conf != NULL) { (void) pool_conf_close(conf); pool_conf_free(conf); } if (yyin != stdin) (void) fclose(yyin); } /* * get_cpu() takes the name of a CPU components and attempts to locate * the element with that name. If the name is not formatted correctly * (i.e. contains non-numeric characters) then the function terminates * execution. If the components cannot be uniquely identified by the * name, then NULL is returned. */ static pool_component_t * get_cpu(const char *name) { pool_component_t **components; uint_t nelem; int64_t sysid; pool_value_t *vals[3] = {NULL}; pool_component_t *ret; const char *c; if ((vals[0] = pool_value_alloc()) == NULL) return (NULL); if ((vals[1] = pool_value_alloc()) == NULL) { pool_value_free(vals[0]); return (NULL); } if (pool_value_set_string(vals[0], "cpu") != PO_SUCCESS || pool_value_set_name(vals[0], "type") != PO_SUCCESS) { pool_value_free(vals[0]); pool_value_free(vals[1]); return (NULL); } for (c = name; *c != NULL; c++) { if (!isdigit(*c)){ pool_value_free(vals[0]); pool_value_free(vals[1]); die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), cmd->cmd_tgt1, gettext("CPU id should only contain " "digits")); } } sysid = strtoll(name, NULL, 0); if (errno == ERANGE || errno == EINVAL) { pool_value_free(vals[0]); pool_value_free(vals[1]); return (NULL); } pool_value_set_int64(vals[1], sysid); if (pool_value_set_name(vals[1], CPU_SYSID) != PO_SUCCESS) { pool_value_free(vals[0]); pool_value_free(vals[1]); return (NULL); } if ((components = pool_query_components(conf, &nelem, vals)) == NULL) { pool_value_free(vals[0]); pool_value_free(vals[1]); return (NULL); } if (nelem != 1) { free(components); pool_value_free(vals[0]); pool_value_free(vals[1]); return (NULL); } pool_value_free(vals[0]); pool_value_free(vals[1]); ret = components[0]; free(components); return (ret); } /* * process_min_max() ensures that "min" and "max" properties are * processed correctly by poolcfg. libpool enforces validity * constraints on these properties and so it's important that changes * to them are supplied to the library in the correct order. */ void process_min_max(pool_resource_t *resource) { prop_t *minprop = NULL; prop_t *maxprop = NULL; prop_t *prop; /* * Before walking the list of properties, it has to be checked * to ensure there are no clashes between min and max. If * there are, then process these properties immediately. */ for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) { const char *pos; if ((pos = strstr(prop->prop_name, min_suffix)) != NULL) if (pos == prop->prop_name + strlen(prop->prop_name) - 4) minprop = prop; if ((pos = strstr(prop->prop_name, max_suffix)) != NULL) if (pos == prop->prop_name + strlen(prop->prop_name) - 4) maxprop = prop; } if (minprop && maxprop) { pool_value_t *pv; uint64_t smin, smax, dmax; const char *type; char *prop_name; pool_elem_t *pe = pool_resource_to_elem(conf, resource); if ((pv = pool_value_alloc()) == NULL) die(gettext(ERR_NOMEM)); (void) pool_get_property(conf, pe, "type", pv); (void) pool_value_get_string(pv, &type); if ((prop_name = malloc(strlen(type) + strlen(max_suffix) + 1)) == NULL) die(gettext(ERR_NOMEM)); (void) sprintf(prop_name, "%s%s", type, max_suffix); (void) pool_get_property(conf, pe, prop_name, pv); (void) pool_value_get_uint64(pv, &dmax); (void) pool_value_get_uint64(minprop->prop_value, &smin); (void) pool_value_get_uint64(maxprop->prop_value, &smax); if (smin < dmax) { (void) pool_put_property(conf, pe, minprop->prop_name, minprop->prop_value); } else { (void) pool_put_property(conf, pe, maxprop->prop_name, maxprop->prop_value); } free((void *)prop_name); pool_value_free(pv); } } static YYCONST yytabelem yyexca[] ={ -1, 1, 0, -1, -2, 0, -1, 2, 0, 1, 257, 1, 258, 1, 259, 1, 260, 1, 261, 1, 262, 1, 263, 1, 264, 1, -2, 0, }; # define YYNPROD 68 # define YYLAST 172 static YYCONST yytabelem yyact[]={ 33, 34, 35, 40, 33, 34, 35, 32, 52, 33, 34, 35, 41, 71, 61, 89, 88, 53, 54, 55, 56, 57, 53, 54, 55, 56, 57, 73, 101, 102, 103, 105, 104, 45, 97, 99, 63, 43, 91, 84, 83, 81, 80, 46, 13, 15, 16, 17, 18, 14, 21, 22, 77, 76, 74, 75, 24, 29, 26, 106, 86, 107, 96, 62, 98, 69, 59, 48, 51, 31, 25, 2, 70, 23, 60, 100, 42, 68, 28, 58, 27, 47, 49, 50, 20, 36, 37, 39, 19, 11, 12, 44, 6, 10, 9, 8, 7, 4, 5, 3, 64, 65, 66, 38, 30, 67, 1, 0, 72, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 79, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 87, 0, 0, 0, 0, 0, 92, 90, 0, 0, 93, 0, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 108 }; static YYCONST yytabelem yypact[]={ -213, -213, -200,-10000000,-10000000,-10000000,-10000000, -209,-10000000, -209, -210,-10000000,-10000000, -281,-10000000, -276, -276, -285, -274,-10000000, -230, -276, -233,-10000000,-10000000,-10000000, -263,-10000000,-10000000, -273, -238,-10000000,-10000000,-10000000,-10000000,-10000000, -238, -238, -238,-10000000, -10000000, -238,-10000000, -275, -238, -260, -211, -216,-10000000,-10000000, -10000000, -238, -258,-10000000,-10000000,-10000000,-10000000,-10000000, -227,-10000000, -238,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000, -229,-10000000, -238,-10000000, -206, -238, -271, -272, -263,-10000000, -232, -238, -273,-10000000,-10000000, -275,-10000000,-10000000, -238,-10000000, -240, -239, -10000000, -247,-10000000,-10000000,-10000000,-10000000, -207,-10000000, -204,-10000000, -10000000,-10000000,-10000000,-10000000,-10000000,-10000000, -239, -240,-10000000,-10000000 }; static YYCONST yytabelem yypgo[]={ 0, 106, 69, 68, 104, 103, 63, 62, 64, 71, 99, 98, 97, 96, 95, 94, 93, 92, 90, 89, 88, 84, 83, 82, 67, 81, 70, 66, 79, 78, 65, 77, 76, 75, 74, 72 }; static YYCONST yytabelem yyr1[]={ 0, 1, 1, 1, 9, 9, 10, 10, 12, 12, 12, 12, 12, 12, 11, 11, 13, 13, 14, 15, 15, 16, 16, 19, 19, 21, 21, 20, 20, 17, 18, 5, 5, 4, 4, 2, 2, 2, 6, 7, 8, 33, 33, 33, 33, 33, 22, 24, 24, 25, 25, 23, 26, 28, 28, 27, 34, 29, 31, 31, 32, 30, 35, 3, 3, 3, 3, 3 }; static YYCONST yytabelem yyr2[]={ 0, 3, 5, 5, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 3, 7, 7, 4, 7, 7, 4, 7, 4, 2, 2, 9, 4, 15, 15, 3, 11, 2, 3, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 7, 2, 2, 3, 7, 9, 7, 3, 7, 5, 3, 7, 3, 7, 7, 5, 3, 3, 3, 3, 3, 3 }; static YYCONST yytabelem yychk[]={ -10000000, -1, -9, -10, -12, -11, -17, -13, -14, -15, -16, -19, -18, 257, 262, 258, 259, 260, 261, -20, -21, 263, 264, -9, 256, -26, 267, -26, -29, 267, -4, -2, 288, 285, 286, 287, -2, -2, -5, -2, 288, 286, -32, 267, -2, 266, 276, -25, -24, -23, -22, -3, 271, 280, 281, 282, 283, 284, -28, -27, -34, 287, -6, 274, -6, -6, -6, -6, -31, -30, -35, 288, -6, 287, 265, 266, 269, 268, -6, -3, 269, 268, -6, 269, 268, -6, 266, -6, 287, 287, -24, 270, -6, -27, -30, -6, -7, 274, -8, 274, -33, 275, 276, 277, 279, 278, 266, 265, -8, -7 }; static YYCONST yytabelem yydef[]={ 0, -2, -2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 29, 0, 0, 0, 0, 23, 24, 0, 0, 2, 3, 17, 0, 20, 22, 0, 0, 33, 34, 35, 36, 37, 0, 0, 0, 31, 32, 0, 26, 0, 0, 0, 0, 0, 49, 47, 48, 0, 0, 63, 64, 65, 66, 67, 0, 53, 0, 56, 15, 38, 16, 18, 19, 21, 0, 58, 0, 62, 0, 0, 0, 0, 0, 52, 0, 0, 0, 57, 55, 0, 60, 61, 0, 25, 0, 0, 50, 0, 46, 54, 59, 30, 0, 39, 0, 40, 51, 41, 42, 43, 44, 45, 0, 0, 27, 28 }; typedef struct #ifdef __cplusplus yytoktype #endif { #ifdef __cplusplus const #endif char *t_name; int t_val; } yytoktype; #ifndef YYDEBUG # define YYDEBUG 0 /* don't allow debugging */ #endif #if YYDEBUG yytoktype yytoks[] = { "PCC_INFO", 257, "PCC_CREATE", 258, "PCC_DESTROY", 259, "PCC_MODIFY", 260, "PCC_ASSOC", 261, "PCC_DISC", 262, "PCC_RENAME", 263, "PCC_TRANSFER", 264, "PCK_FROM", 265, "PCK_TO", 266, "PCK_OPENLST", 267, "PCK_CLOSELST", 268, "PCK_SEPLST", 269, "PCK_ASSIGN", 270, "PCK_UNDEF", 271, "PCK_COMMAND", 272, "PCV_FILENAME", 273, "PCV_SYMBOL", 274, "PCV_VAL_INT", 275, "PCV_VAL_UINT", 276, "PCV_VAL_FLOAT", 277, "PCV_VAL_STRING", 278, "PCV_VAL_BOOLEAN", 279, "PCT_INT", 280, "PCT_UINT", 281, "PCT_BOOLEAN", 282, "PCT_FLOAT", 283, "PCT_STRING", 284, "PCE_SYSTEM", 285, "PCE_POOL", 286, "PCE_PSET", 287, "PCE_CPU", 288, "-unknown-", -1 /* ends search */ }; #ifdef __cplusplus const #endif char * yyreds[] = { "-no such reduction-", "commands : command", "commands : commands command", "commands : command error", "command : list_command", "command : edit_command", "list_command : info_command", "list_command : discover_command", "edit_command : create_command", "edit_command : destroy_command", "edit_command : modify_command", "edit_command : associate_command", "edit_command : transfer_command", "edit_command : rename_command", "info_command : PCC_INFO", "info_command : PCC_INFO info_entity name", "create_command : PCC_CREATE entity name", "create_command : create_command property_list", "destroy_command : PCC_DESTROY entity name", "modify_command : PCC_MODIFY modify_entity name", "modify_command : modify_command property_list", "associate_command : PCC_ASSOC PCE_POOL name", "associate_command : associate_command resource_list", "transfer_command : transfer_qty", "transfer_command : transfer_components", "transfer_components : PCC_TRANSFER PCK_TO PCE_PSET name", "transfer_components : transfer_components component_list", "transfer_qty : PCC_TRANSFER PCV_VAL_UINT PCK_FROM PCE_PSET src PCK_TO tgt", "transfer_qty : PCC_TRANSFER PCV_VAL_UINT PCK_TO PCE_PSET tgt PCK_FROM src", "discover_command : PCC_DISC", "rename_command : PCC_RENAME entity name PCK_TO name", "modify_entity : entity", "modify_entity : PCE_CPU", "info_entity : entity", "info_entity : PCE_CPU", "entity : PCE_SYSTEM", "entity : PCE_POOL", "entity : PCE_PSET", "name : PCV_SYMBOL", "src : PCV_SYMBOL", "tgt : PCV_SYMBOL", "value : PCV_VAL_INT", "value : PCV_VAL_UINT", "value : PCV_VAL_FLOAT", "value : PCV_VAL_BOOLEAN", "value : PCV_VAL_STRING", "prop_remove : PCK_UNDEF proptype name", "prop_op : prop_assign", "prop_op : prop_remove", "prop_ops : prop_op", "prop_ops : prop_ops PCK_SEPLST prop_op", "prop_assign : proptype name PCK_ASSIGN value", "property_list : PCK_OPENLST prop_ops PCK_CLOSELST", "resource_assigns : resource_assign", "resource_assigns : resource_assigns PCK_SEPLST resource_assign", "resource_assign : resource name", "resource : PCE_PSET", "resource_list : PCK_OPENLST resource_assigns PCK_CLOSELST", "component_assigns : component_assign", "component_assigns : component_assigns PCK_SEPLST component_assign", "component_list : PCK_OPENLST component_assigns PCK_CLOSELST", "component_assign : component name", "component : PCE_CPU", "proptype : PCT_INT", "proptype : PCT_UINT", "proptype : PCT_BOOLEAN", "proptype : PCT_FLOAT", "proptype : PCT_STRING", }; #endif /* YYDEBUG */ # line 1 "/usr/share/lib/ccs/yaccpar" /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1993 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #pragma ident "%Z%%M% %I% %E% SMI" /* ** Skeleton parser driver for yacc output */ /* ** yacc user known macros and defines */ #define YYERROR goto yyerrlab #define YYACCEPT return(0) #define YYABORT return(1) #define YYBACKUP( newtoken, newvalue )\ {\ if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\ {\ yyerror( "syntax error - cannot backup" );\ goto yyerrlab;\ }\ yychar = newtoken;\ yystate = *yyps;\ yylval = newvalue;\ goto yynewstate;\ } #define YYRECOVERING() (!!yyerrflag) #define YYNEW(type) malloc(sizeof(type) * yynewmax) #define YYCOPY(to, from, type) \ (type *) memcpy(to, (char *) from, yymaxdepth * sizeof (type)) #define YYENLARGE( from, type) \ (type *) realloc((char *) from, yynewmax * sizeof(type)) #ifndef YYDEBUG # define YYDEBUG 1 /* make debugging available */ #endif /* ** user known globals */ int yydebug; /* set to 1 to get debugging */ /* ** driver internal defines */ #define YYFLAG (-10000000) /* ** global variables used by the parser */ YYSTYPE *yypv; /* top of value stack */ int *yyps; /* top of state stack */ int yystate; /* current state */ int yytmp; /* extra var (lasts between blocks) */ int yynerrs; /* number of errors */ int yyerrflag; /* error recovery flag */ int yychar; /* current input token number */ #ifdef YYNMBCHARS #define YYLEX() yycvtok(yylex()) /* ** yycvtok - return a token if i is a wchar_t value that exceeds 255. ** If i<255, i itself is the token. If i>255 but the neither ** of the 30th or 31st bit is on, i is already a token. */ #if defined(__STDC__) || defined(__cplusplus) int yycvtok(int i) #else int yycvtok(i) int i; #endif { int first = 0; int last = YYNMBCHARS - 1; int mid; wchar_t j; if(i&0x60000000){/*Must convert to a token. */ if( yymbchars[last].character < i ){ return i;/*Giving up*/ } while ((last>=first)&&(first>=0)) {/*Binary search loop*/ mid = (first+last)/2; j = yymbchars[mid].character; if( j==i ){/*Found*/ return yymbchars[mid].tvalue; }else if( j= 0; yy_i++ ) { if ( yytoks[yy_i].t_val == yychar ) break; } printf( "%s\n", yytoks[yy_i].t_name ); } } #endif /* YYDEBUG */ if ( ++yy_ps >= &yys[ yymaxdepth ] ) /* room on stack? */ { /* ** reallocate and recover. Note that pointers ** have to be reset, or bad things will happen */ long yyps_index = (yy_ps - yys); long yypv_index = (yy_pv - yyv); long yypvt_index = (yypvt - yyv); int yynewmax; #ifdef YYEXPAND yynewmax = YYEXPAND(yymaxdepth); #else yynewmax = 2 * yymaxdepth; /* double table size */ if (yymaxdepth == YYMAXDEPTH) /* first time growth */ { char *newyys = (char *)YYNEW(int); char *newyyv = (char *)YYNEW(YYSTYPE); if (newyys != 0 && newyyv != 0) { yys = YYCOPY(newyys, yys, int); yyv = YYCOPY(newyyv, yyv, YYSTYPE); } else yynewmax = 0; /* failed */ } else /* not first time */ { yys = YYENLARGE(yys, int); yyv = YYENLARGE(yyv, YYSTYPE); if (yys == 0 || yyv == 0) yynewmax = 0; /* failed */ } #endif if (yynewmax <= yymaxdepth) /* tables not expanded */ { yyerror( "yacc stack overflow" ); YYABORT; } yymaxdepth = yynewmax; yy_ps = yys + yyps_index; yy_pv = yyv + yypv_index; yypvt = yyv + yypvt_index; } *yy_ps = yy_state; *++yy_pv = yyval; /* ** we have a new state - find out what to do */ yy_newstate: if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG ) goto yydefault; /* simple state */ #if YYDEBUG /* ** if debugging, need to mark whether new token grabbed */ yytmp = yychar < 0; #endif if ( ( yychar < 0 ) && ( ( yychar = YYLEX() ) < 0 ) ) yychar = 0; /* reached EOF */ #if YYDEBUG if ( yydebug && yytmp ) { register int yy_i; printf( "Received token " ); if ( yychar == 0 ) printf( "end-of-file\n" ); else if ( yychar < 0 ) printf( "-none-\n" ); else { for ( yy_i = 0; yytoks[yy_i].t_val >= 0; yy_i++ ) { if ( yytoks[yy_i].t_val == yychar ) break; } printf( "%s\n", yytoks[yy_i].t_name ); } } #endif /* YYDEBUG */ if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) ) goto yydefault; if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar ) /*valid shift*/ { yychar = -1; yyval = yylval; yy_state = yy_n; if ( yyerrflag > 0 ) yyerrflag--; goto yy_stack; } yydefault: if ( ( yy_n = yydef[ yy_state ] ) == -2 ) { #if YYDEBUG yytmp = yychar < 0; #endif if ( ( yychar < 0 ) && ( ( yychar = YYLEX() ) < 0 ) ) yychar = 0; /* reached EOF */ #if YYDEBUG if ( yydebug && yytmp ) { register int yy_i; printf( "Received token " ); if ( yychar == 0 ) printf( "end-of-file\n" ); else if ( yychar < 0 ) printf( "-none-\n" ); else { for ( yy_i = 0; yytoks[yy_i].t_val >= 0; yy_i++ ) { if ( yytoks[yy_i].t_val == yychar ) { break; } } printf( "%s\n", yytoks[yy_i].t_name ); } } #endif /* YYDEBUG */ /* ** look through exception table */ { register YYCONST int *yyxi = yyexca; while ( ( *yyxi != -1 ) || ( yyxi[1] != yy_state ) ) { yyxi += 2; } while ( ( *(yyxi += 2) >= 0 ) && ( *yyxi != yychar ) ) ; if ( ( yy_n = yyxi[1] ) < 0 ) YYACCEPT; } } /* ** check for syntax error */ if ( yy_n == 0 ) /* have an error */ { /* no worry about speed here! */ switch ( yyerrflag ) { case 0: /* new error */ yyerror( "syntax error" ); goto skip_init; yyerrlab: /* ** get globals into registers. ** we have a user generated syntax type error */ yy_pv = yypv; yy_ps = yyps; yy_state = yystate; skip_init: yynerrs++; /* FALLTHRU */ case 1: case 2: /* incompletely recovered error */ /* try again... */ yyerrflag = 3; /* ** find state where "error" is a legal ** shift action */ while ( yy_ps >= yys ) { yy_n = yypact[ *yy_ps ] + YYERRCODE; if ( yy_n >= 0 && yy_n < YYLAST && yychk[yyact[yy_n]] == YYERRCODE) { /* ** simulate shift of "error" */ yy_state = yyact[ yy_n ]; goto yy_stack; } /* ** current state has no shift on ** "error", pop stack */ #if YYDEBUG # define _POP_ "Error recovery pops state %d, uncovers state %d\n" if ( yydebug ) printf( _POP_, *yy_ps, yy_ps[-1] ); # undef _POP_ #endif yy_ps--; yy_pv--; } /* ** there is no state on stack with "error" as ** a valid shift. give up. */ YYABORT; case 3: /* no shift yet; eat a token */ #if YYDEBUG /* ** if debugging, look up token in list of ** pairs. 0 and negative shouldn't occur, ** but since timing doesn't matter when ** debugging, it doesn't hurt to leave the ** tests here. */ if ( yydebug ) { register int yy_i; printf( "Error recovery discards " ); if ( yychar == 0 ) printf( "token end-of-file\n" ); else if ( yychar < 0 ) printf( "token -none-\n" ); else { for ( yy_i = 0; yytoks[yy_i].t_val >= 0; yy_i++ ) { if ( yytoks[yy_i].t_val == yychar ) { break; } } printf( "token %s\n", yytoks[yy_i].t_name ); } } #endif /* YYDEBUG */ if ( yychar == 0 ) /* reached EOF. quit */ YYABORT; yychar = -1; goto yy_newstate; } }/* end if ( yy_n == 0 ) */ /* ** reduction by production yy_n ** put stack tops, etc. so things right after switch */ #if YYDEBUG /* ** if debugging, print the string that is the user's ** specification of the reduction which is just about ** to be done. */ if ( yydebug ) printf( "Reduce by (%d) \"%s\"\n", yy_n, yyreds[ yy_n ] ); #endif yytmp = yy_n; /* value to switch over */ yypvt = yy_pv; /* $vars top of value stack */ /* ** Look in goto table for next state ** Sorry about using yy_state here as temporary ** register variable, but why not, if it works... ** If yyr2[ yy_n ] doesn't have the low order bit ** set, then there is no action to be done for ** this reduction. So, no saving & unsaving of ** registers done. The only difference between the ** code just after the if and the body of the if is ** the goto yy_stack in the body. This way the test ** can be made before the choice of what to do is needed. */ { /* length of production doubled with extra bit */ register int yy_len = yyr2[ yy_n ]; if ( !( yy_len & 01 ) ) { yy_len >>= 1; yyval = ( yy_pv -= yy_len )[1]; /* $$ = $1 */ yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] + *( yy_ps -= yy_len ) + 1; if ( yy_state >= YYLAST || yychk[ yy_state = yyact[ yy_state ] ] != -yy_n ) { yy_state = yyact[ yypgo[ yy_n ] ]; } goto yy_stack; } yy_len >>= 1; yyval = ( yy_pv -= yy_len )[1]; /* $$ = $1 */ yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] + *( yy_ps -= yy_len ) + 1; if ( yy_state >= YYLAST || yychk[ yy_state = yyact[ yy_state ] ] != -yy_n ) { yy_state = yyact[ yypgo[ yy_n ] ]; } } /* save until reenter driver code */ yystate = yy_state; yyps = yy_ps; yypv = yy_pv; } /* ** code supplied by user is placed in this switch */ switch( yytmp ) { case 1: # line 244 "poolcfg.y" { if (yypvt[-0].cmd->cmd != NULL) yypvt[-0].cmd->cmd(yypvt[-0].cmd); free_cmd(yypvt[-0].cmd); } break; case 2: # line 250 "poolcfg.y" { if (yypvt[-0].cmd->cmd != NULL) yypvt[-0].cmd->cmd(yypvt[-0].cmd); free_cmd(yypvt[-0].cmd); } break; case 3: # line 255 "poolcfg.y" { YYERROR;} break; case 5: # line 259 "poolcfg.y" { if (conf_edit_error != POE_OK) { if (yypvt[-0].cmd->cmd != parser_conf_create && yypvt[-0].cmd->cmd != parser_conf_discover) { die(gettext(ERR_CONF_LOAD), conf_file, get_errstr_err(conf_edit_error, conf_edit_errno)); } } edited = PO_TRUE; } break; case 6: # line 272 "poolcfg.y" { if (conf_list_error != POE_OK) { if (yypvt[-0].cmd->cmd != parser_conf_create && yypvt[-0].cmd->cmd != parser_conf_discover) { die(gettext(ERR_CONF_LOAD), conf_file, get_errstr_err(conf_list_error, conf_list_errno)); } } } break; case 7: # line 282 "poolcfg.y" {conf_list_error = conf_edit_error = POE_OK;} break; case 14: # line 292 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; yyval.cmd->cmd = &parser_conf_info; } break; case 15: # line 299 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; switch (yypvt[-1].ival) { case PCE_SYSTEM: yyval.cmd->cmd = &parser_conf_info; break; case PCE_POOL: yyval.cmd->cmd = &parser_pool_info; break; case PCE_PSET: yyval.cmd->cmd = &parser_pset_info; break; case PCE_CPU: yyval.cmd->cmd = &parser_cpu_info; break; default: warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival); YYERROR; } yyval.cmd->cmd_tgt1 = yypvt[-0].sval; } break; case 16: # line 324 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; switch (yypvt[-1].ival) { case PCE_SYSTEM: yyval.cmd->cmd = &parser_conf_create; /* * When creating a new system element, ensure * pre-existing errors are ignored. */ conf_list_error = conf_edit_error = POE_OK; break; case PCE_POOL: yyval.cmd->cmd = &parser_pool_create; break; case PCE_PSET: yyval.cmd->cmd = &parser_pset_create; break; default: warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival); YYERROR; } yyval.cmd->cmd_tgt1 = yypvt[-0].sval; } break; case 18: # line 352 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; switch (yypvt[-1].ival) { case PCE_SYSTEM: yyval.cmd->cmd = &parser_conf_destroy; break; case PCE_POOL: yyval.cmd->cmd = &parser_pool_destroy; break; case PCE_PSET: yyval.cmd->cmd = &parser_pset_destroy; break; default: warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival); YYERROR; } yyval.cmd->cmd_tgt1 = yypvt[-0].sval; } break; case 19: # line 374 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; switch (yypvt[-1].ival) { case PCE_SYSTEM: yyval.cmd->cmd = &parser_conf_modify; break; case PCE_POOL: yyval.cmd->cmd = &parser_pool_modify; break; case PCE_PSET: yyval.cmd->cmd = &parser_pset_modify; break; case PCE_CPU: yyval.cmd->cmd = &parser_cpu_modify; break; default: warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-1].ival); YYERROR; } yyval.cmd->cmd_tgt1 = yypvt[-0].sval; } break; case 21: # line 400 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; yyval.cmd->cmd = &parser_pool_associate; cmd->cmd_tgt1 = yypvt[-0].sval; } break; case 25: # line 413 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; yyval.cmd->cmd = &parser_resource_xtransfer; cmd->cmd_tgt1 = yypvt[-0].sval; } break; case 27: # line 423 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; yyval.cmd->cmd = &parser_resource_transfer; cmd->cmd_tgt1 = yypvt[-2].sval; cmd->cmd_tgt2 = yypvt[-0].sval; cmd->cmd_qty = yypvt[-5].uval; } break; case 28: # line 433 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; yyval.cmd->cmd = &parser_resource_transfer; cmd->cmd_tgt1 = yypvt[-0].sval; cmd->cmd_tgt2 = yypvt[-2].sval; cmd->cmd_qty = yypvt[-5].uval; } break; case 29: # line 444 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; yyval.cmd->cmd = &parser_conf_discover; } break; case 30: # line 452 "poolcfg.y" { if ((yyval.cmd = alloc_cmd()) == NULL) YYERROR; cmd = yyval.cmd; switch (yypvt[-3].ival) { case PCE_SYSTEM: yyval.cmd->cmd = &parser_conf_rename; break; case PCE_POOL: yyval.cmd->cmd = &parser_pool_rename; break; case PCE_PSET: yyval.cmd->cmd = &parser_pset_rename; break; default: warn(gettext(ERR_UNKNOWN_ENTITY), yypvt[-3].ival); YYERROR; } yyval.cmd->cmd_tgt1 = yypvt[-2].sval; yyval.cmd->cmd_tgt2 = yypvt[-0].sval; } break; case 32: # line 475 "poolcfg.y" {yyval.ival = PCE_CPU;} break; case 34: # line 478 "poolcfg.y" {yyval.ival = PCE_CPU;} break; case 35: # line 480 "poolcfg.y" {yyval.ival = PCE_SYSTEM;} break; case 36: # line 481 "poolcfg.y" {yyval.ival = PCE_POOL;} break; case 37: # line 482 "poolcfg.y" {yyval.ival = PCE_PSET;} break; case 41: # line 490 "poolcfg.y" { yyval.val.i = yypvt[-0].ival;} break; case 42: # line 491 "poolcfg.y" { yyval.val.u = yypvt[-0].uval;} break; case 43: # line 492 "poolcfg.y" { yyval.val.d = yypvt[-0].dval;} break; case 44: # line 493 "poolcfg.y" { yyval.val.b = yypvt[-0].bval;} break; case 45: # line 494 "poolcfg.y" { yyval.val.s = yypvt[-0].sval;} break; case 46: # line 497 "poolcfg.y" { if ((yyval.prop = alloc_prop(po_remove)) == NULL) YYERROR; yyval.prop->prop_name = yypvt[-0].sval; } break; case 49: # line 507 "poolcfg.y" { prop_t *prop = NULL; prop_t *prev = NULL; for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) prev = prop; /* Find end of list */ if (prev != NULL) prev->prop_next = yypvt[-0].prop; else cmd->cmd_prop_list = yypvt[-0].prop; yyval.prop = cmd->cmd_prop_list; } break; case 50: # line 521 "poolcfg.y" { prop_t *prop = NULL; prop_t *prev = NULL; for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) prev = prop; /* Find end of list */ if (prev != NULL) prev->prop_next = yypvt[-0].prop; else cmd->cmd_prop_list = yypvt[-0].prop; yyval.prop = cmd->cmd_prop_list; } break; case 51: # line 537 "poolcfg.y" { if ((yyval.prop = alloc_prop(po_create)) == NULL) YYERROR; yyval.prop->prop_name = yypvt[-2].sval; switch (yypvt[-3].ival) { case PCT_INT: pool_value_set_int64(yyval.prop->prop_value, yypvt[-0].val.i); break; case PCT_UINT: pool_value_set_uint64(yyval.prop->prop_value, yypvt[-0].val.u); break; case PCT_BOOLEAN: pool_value_set_bool(yyval.prop->prop_value, yypvt[-0].val.b); break; case PCT_FLOAT: pool_value_set_double(yyval.prop->prop_value, yypvt[-0].val.d); break; case PCT_STRING: pool_value_set_string(yyval.prop->prop_value, yypvt[-0].val.s); break; } } break; case 52: # line 561 "poolcfg.y" { yyval.prop = yypvt[-1].prop; } break; case 53: # line 566 "poolcfg.y" { assoc_t *assoc = NULL; assoc_t *prev = NULL; for (assoc = cmd->cmd_assoc_list; assoc != NULL; assoc = assoc->assoc_next) prev = assoc; /* Find end of list */ if (prev != NULL) prev->assoc_next = yypvt[-0].assoc; else cmd->cmd_assoc_list = yypvt[-0].assoc; yyval.assoc = cmd->cmd_assoc_list; } break; case 54: # line 581 "poolcfg.y" { assoc_t *assoc = NULL; assoc_t *prev = NULL; for (assoc = cmd->cmd_assoc_list; assoc != NULL; assoc = assoc->assoc_next) prev = assoc; /* Find end of list */ if (prev != NULL) prev->assoc_next = yypvt[-0].assoc; yyval.assoc = yypvt[-0].assoc; } break; case 55: # line 594 "poolcfg.y" { if ((yyval.assoc = alloc_assoc(yypvt[-1].ival, yypvt[-0].sval)) == NULL) YYERROR; } break; case 56: # line 599 "poolcfg.y" {yyval.ival = PCE_PSET;} break; case 57: # line 602 "poolcfg.y" { yyval.assoc = yypvt[-1].assoc; } break; case 58: # line 607 "poolcfg.y" { assoc_t *assoc = NULL; assoc_t *prev = NULL; for (assoc = cmd->cmd_assoc_list; assoc != NULL; assoc = assoc->assoc_next) prev = assoc; /* Find end of list */ if (prev != NULL) prev->assoc_next = yypvt[-0].assoc; else cmd->cmd_assoc_list = yypvt[-0].assoc; yyval.assoc = cmd->cmd_assoc_list; } break; case 59: # line 622 "poolcfg.y" { assoc_t *assoc = NULL; assoc_t *prev = NULL; for (assoc = cmd->cmd_assoc_list; assoc != NULL; assoc = assoc->assoc_next) prev = assoc; /* Find end of list */ if (prev != NULL) prev->assoc_next = yypvt[-0].assoc; yyval.assoc = yypvt[-0].assoc; } break; case 60: # line 635 "poolcfg.y" { yyval.assoc = yypvt[-1].assoc; } break; case 61: # line 640 "poolcfg.y" { if ((yyval.assoc = alloc_assoc(yypvt[-1].ival, yypvt[-0].sval)) == NULL) YYERROR; } break; case 62: # line 645 "poolcfg.y" {yyval.ival = PCE_CPU;} break; case 63: # line 647 "poolcfg.y" {yyval.ival = PCT_INT;} break; case 64: # line 648 "poolcfg.y" {yyval.ival = PCT_UINT;} break; case 65: # line 649 "poolcfg.y" {yyval.ival = PCT_BOOLEAN;} break; case 66: # line 650 "poolcfg.y" {yyval.ival = PCT_FLOAT;} break; case 67: # line 651 "poolcfg.y" {yyval.ival = PCT_STRING;} break; # line 556 "/usr/share/lib/ccs/yaccpar" } goto yystack; /* reset registers in driver code */ }