xref: /onnv-gate/usr/src/lib/libshell/common/bltins/enum.c (revision 12068:08a39a083754)
18462SApril.Chin@Sun.COM /***********************************************************************
28462SApril.Chin@Sun.COM *                                                                      *
38462SApril.Chin@Sun.COM *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1982-2010 AT&T Intellectual Property          *
58462SApril.Chin@Sun.COM *                      and is licensed under the                       *
68462SApril.Chin@Sun.COM *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
88462SApril.Chin@Sun.COM *                                                                      *
98462SApril.Chin@Sun.COM *                A copy of the License is available at                 *
108462SApril.Chin@Sun.COM *            http://www.opensource.org/licenses/cpl1.0.txt             *
118462SApril.Chin@Sun.COM *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
128462SApril.Chin@Sun.COM *                                                                      *
138462SApril.Chin@Sun.COM *              Information and Software Systems Research               *
148462SApril.Chin@Sun.COM *                            AT&T Research                             *
158462SApril.Chin@Sun.COM *                           Florham Park NJ                            *
168462SApril.Chin@Sun.COM *                                                                      *
178462SApril.Chin@Sun.COM *                  David Korn <dgk@research.att.com>                   *
188462SApril.Chin@Sun.COM *                                                                      *
198462SApril.Chin@Sun.COM ***********************************************************************/
208462SApril.Chin@Sun.COM #pragma prototyped
218462SApril.Chin@Sun.COM #include	<shell.h>
228462SApril.Chin@Sun.COM 
238462SApril.Chin@Sun.COM static const char enum_usage[] =
248462SApril.Chin@Sun.COM "[-?@(#)$Id: enum (AT&T Research) 2008-01-08 $\n]"
258462SApril.Chin@Sun.COM USAGE_LICENSE
268462SApril.Chin@Sun.COM "[+NAME?enum - create an enumeration type]"
278462SApril.Chin@Sun.COM "[+DESCRIPTION?\benum\b is a declaration command that creates an enumeration "
288462SApril.Chin@Sun.COM     "type \atypename\a that can only store any one of the values in the indexed "
298462SApril.Chin@Sun.COM     "array variable \atypename\a.]"
30*12068SRoger.Faulkner@Oracle.COM "[+?If the list of \avalue\as is omitted, then \atypename\a must name an "
318462SApril.Chin@Sun.COM     "indexed array variable with at least two elements.]"
328462SApril.Chin@Sun.COM "[i:ignorecase?The values are case insensitive.]"
338462SApril.Chin@Sun.COM "\n"
348462SApril.Chin@Sun.COM "\n\atypename\a[\b=(\b \avalue\a ... \b)\b]\n"
358462SApril.Chin@Sun.COM "\n"
368462SApril.Chin@Sun.COM "[+EXIT STATUS]"
378462SApril.Chin@Sun.COM     "{"
388462SApril.Chin@Sun.COM         "[+0?Successful completion.]"
398462SApril.Chin@Sun.COM         "[+>0?An error occurred.]"
408462SApril.Chin@Sun.COM     "}"
418462SApril.Chin@Sun.COM "[+SEE ALSO?\bksh\b(1), \btypeset\b(1).]"
428462SApril.Chin@Sun.COM ;
438462SApril.Chin@Sun.COM 
448462SApril.Chin@Sun.COM static const char enum_type[] =
458462SApril.Chin@Sun.COM "[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-01-08 $\n]"
468462SApril.Chin@Sun.COM USAGE_LICENSE
478462SApril.Chin@Sun.COM "[+NAME?\f?\f - create an instance of type \b\f?\f\b]"
488462SApril.Chin@Sun.COM "[+DESCRIPTION?\b\f?\f\b creates a variable for each \aname\a with "
498462SApril.Chin@Sun.COM     "enumeration type \b\f?\f\b where \b\f?\f\b is a type that has been "
508462SApril.Chin@Sun.COM     "created with the \benum\b(1) command.]"
518462SApril.Chin@Sun.COM "[+?The variable can have one of the following values\fvalues\f.  "
528462SApril.Chin@Sun.COM     "The the values are \fcase\fcase sensitive.]"
538462SApril.Chin@Sun.COM "[+?If \b=\b\avalue\a is omitted, the default is \fdefault\f.]"
548462SApril.Chin@Sun.COM "[+?If no \aname\as are specified then the names and values of all "
558462SApril.Chin@Sun.COM         "variables of this type are written to standard output.]"
568462SApril.Chin@Sun.COM "[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
578462SApril.Chin@Sun.COM         "field splitting and pathname expansion are not performed on "
588462SApril.Chin@Sun.COM         "the arguments.  Tilde expansion occurs on \avalue\a.]"
598462SApril.Chin@Sun.COM "[r?Enables readonly.  Once enabled, the value cannot be changed or unset.]"
608462SApril.Chin@Sun.COM "[a?index array.  Each \aname\a will converted to an index "
618462SApril.Chin@Sun.COM         "array of type \b\f?\f\b.  If a variable already exists, the current "
628462SApril.Chin@Sun.COM         "value will become index \b0\b.]"
638462SApril.Chin@Sun.COM "[A?Associative array.  Each \aname\a will converted to an associate "
648462SApril.Chin@Sun.COM         "array of type \b\f?\f\b.  If a variable already exists, the current "
658462SApril.Chin@Sun.COM         "value will become subscript \b0\b.]"
668462SApril.Chin@Sun.COM "[h]:[string?Used within a type definition to provide a help string  "
678462SApril.Chin@Sun.COM         "for variable \aname\a.  Otherwise, it is ignored.]"
688462SApril.Chin@Sun.COM "[S?Used with a type definition to indicate that the variable is shared by "
698462SApril.Chin@Sun.COM         "each instance of the type.  When used inside a function defined "
708462SApril.Chin@Sun.COM         "with the \bfunction\b reserved word, the specified variables "
718462SApril.Chin@Sun.COM         "will have function static scope.  Otherwise, the variable is "
728462SApril.Chin@Sun.COM         "unset prior to processing the assignment list.]"
738462SApril.Chin@Sun.COM #if 0
748462SApril.Chin@Sun.COM "[p?Causes the output to be in a form of \b\f?\f\b commands that can be "
758462SApril.Chin@Sun.COM         "used as input to the shell to recreate the current type of "
768462SApril.Chin@Sun.COM         "these variables.]"
778462SApril.Chin@Sun.COM #endif
788462SApril.Chin@Sun.COM "\n"
798462SApril.Chin@Sun.COM "\n[name[=value]...]\n"
808462SApril.Chin@Sun.COM "\n"
818462SApril.Chin@Sun.COM "[+EXIT STATUS?]{"
828462SApril.Chin@Sun.COM         "[+0?Successful completion.]"
838462SApril.Chin@Sun.COM         "[+>0?An error occurred.]"
848462SApril.Chin@Sun.COM "}"
858462SApril.Chin@Sun.COM 
868462SApril.Chin@Sun.COM "[+SEE ALSO?\benum\b(1), \btypeset\b(1)]"
878462SApril.Chin@Sun.COM ;
888462SApril.Chin@Sun.COM 
898462SApril.Chin@Sun.COM struct Enum
908462SApril.Chin@Sun.COM {
918462SApril.Chin@Sun.COM 	Namfun_t	hdr;
928462SApril.Chin@Sun.COM 	short		nelem;
938462SApril.Chin@Sun.COM 	short		iflag;
948462SApril.Chin@Sun.COM 	const char	*values[1];
958462SApril.Chin@Sun.COM };
968462SApril.Chin@Sun.COM 
enuminfo(Opt_t * op,Sfio_t * out,const char * str,Optdisc_t * fp)978462SApril.Chin@Sun.COM static int enuminfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
988462SApril.Chin@Sun.COM {
998462SApril.Chin@Sun.COM 	Namval_t	*np;
1008462SApril.Chin@Sun.COM 	struct Enum	*ep;
1018462SApril.Chin@Sun.COM 	int		n=0;
1028462SApril.Chin@Sun.COM 	const char	*v;
1038462SApril.Chin@Sun.COM 	np = *(Namval_t**)(fp+1);
1048462SApril.Chin@Sun.COM 	ep = (struct Enum*)np->nvfun;
1058462SApril.Chin@Sun.COM 	if(strcmp(str,"default")==0)
1068462SApril.Chin@Sun.COM #if 0
1078462SApril.Chin@Sun.COM 		sfprintf(out,"\b%s\b%c",ep->values[0],0);
1088462SApril.Chin@Sun.COM #else
1098462SApril.Chin@Sun.COM 		sfprintf(out,"\b%s\b",ep->values[0]);
1108462SApril.Chin@Sun.COM #endif
1118462SApril.Chin@Sun.COM 	else if(strcmp(str,"case")==0)
1128462SApril.Chin@Sun.COM 	{
1138462SApril.Chin@Sun.COM 		if(ep->iflag)
1148462SApril.Chin@Sun.COM 			sfprintf(out,"not ");
1158462SApril.Chin@Sun.COM 	}
1168462SApril.Chin@Sun.COM 	else while(v=ep->values[n++])
1178462SApril.Chin@Sun.COM 	{
1188462SApril.Chin@Sun.COM 		sfprintf(out,", \b%s\b",v);
1198462SApril.Chin@Sun.COM 	}
1208462SApril.Chin@Sun.COM 	return(0);
1218462SApril.Chin@Sun.COM }
1228462SApril.Chin@Sun.COM 
clone_enum(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)1238462SApril.Chin@Sun.COM static Namfun_t *clone_enum(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
1248462SApril.Chin@Sun.COM {
1258462SApril.Chin@Sun.COM 	struct Enum	*ep, *pp=(struct Enum*)fp;
1268462SApril.Chin@Sun.COM 	ep = newof(0,struct Enum,1,pp->nelem*sizeof(char*));
1278462SApril.Chin@Sun.COM 	memcpy((void*)ep,(void*)pp,sizeof(struct Enum)+pp->nelem*sizeof(char*));
1288462SApril.Chin@Sun.COM 	return(&ep->hdr);
1298462SApril.Chin@Sun.COM }
1308462SApril.Chin@Sun.COM 
put_enum(Namval_t * np,const char * val,int flags,Namfun_t * fp)1318462SApril.Chin@Sun.COM static void put_enum(Namval_t* np,const char *val,int flags,Namfun_t *fp)
1328462SApril.Chin@Sun.COM {
1338462SApril.Chin@Sun.COM 	struct Enum 		*ep = (struct Enum*)fp;
1348462SApril.Chin@Sun.COM 	register const char	*v;
1358462SApril.Chin@Sun.COM 	unsigned short		i=0, n;
1368462SApril.Chin@Sun.COM 	if(!val)
1378462SApril.Chin@Sun.COM 	{
1388462SApril.Chin@Sun.COM 		nv_disc(np,&ep->hdr,NV_POP);
1398462SApril.Chin@Sun.COM 		if(!ep->hdr.nofree)
1408462SApril.Chin@Sun.COM 			free((void*)ep);
1418462SApril.Chin@Sun.COM 		nv_putv(np, val, flags,fp);
1428462SApril.Chin@Sun.COM 		return;
1438462SApril.Chin@Sun.COM 	}
1448462SApril.Chin@Sun.COM 	if(flags&NV_INTEGER)
1458462SApril.Chin@Sun.COM 	{
1468462SApril.Chin@Sun.COM 		nv_putv(np,val,flags,fp);
1478462SApril.Chin@Sun.COM 		return;
1488462SApril.Chin@Sun.COM 	}
1498462SApril.Chin@Sun.COM 	while(v=ep->values[i])
1508462SApril.Chin@Sun.COM 	{
1518462SApril.Chin@Sun.COM 		if(ep->iflag)
1528462SApril.Chin@Sun.COM 			n = strcasecmp(v,val);
1538462SApril.Chin@Sun.COM 		else
1548462SApril.Chin@Sun.COM 			n = strcmp(v,val);
1558462SApril.Chin@Sun.COM 		if(n==0)
1568462SApril.Chin@Sun.COM 		{
1578462SApril.Chin@Sun.COM 			nv_putv(np, (char*)&i, NV_UINT16, fp);
1588462SApril.Chin@Sun.COM 			return;
1598462SApril.Chin@Sun.COM 		}
1608462SApril.Chin@Sun.COM 		i++;
1618462SApril.Chin@Sun.COM 	}
1628462SApril.Chin@Sun.COM 	error(ERROR_exit(1), "%s:  invalid value %s",nv_name(np),val);
1638462SApril.Chin@Sun.COM }
1648462SApril.Chin@Sun.COM 
get_enum(register Namval_t * np,Namfun_t * fp)1658462SApril.Chin@Sun.COM static char* get_enum(register Namval_t* np, Namfun_t *fp)
1668462SApril.Chin@Sun.COM {
1678462SApril.Chin@Sun.COM 	static char buff[6];
1688462SApril.Chin@Sun.COM 	struct Enum *ep = (struct Enum*)fp;
1698462SApril.Chin@Sun.COM 	long n = nv_getn(np,fp);
1708462SApril.Chin@Sun.COM 	if(n < ep->nelem)
1718462SApril.Chin@Sun.COM 		return((char*)ep->values[n]);
1728462SApril.Chin@Sun.COM 	sfsprintf(buff,sizeof(buff),"%u%c",n,0);
1738462SApril.Chin@Sun.COM 	return(buff);
1748462SApril.Chin@Sun.COM }
1758462SApril.Chin@Sun.COM 
get_nenum(register Namval_t * np,Namfun_t * fp)1768462SApril.Chin@Sun.COM static Sfdouble_t get_nenum(register Namval_t* np, Namfun_t *fp)
1778462SApril.Chin@Sun.COM {
1788462SApril.Chin@Sun.COM 	return(nv_getn(np,fp));
1798462SApril.Chin@Sun.COM }
1808462SApril.Chin@Sun.COM 
1818462SApril.Chin@Sun.COM const Namdisc_t ENUM_disc        = {  0, put_enum, get_enum, get_nenum, 0,0,clone_enum };
1828462SApril.Chin@Sun.COM 
1838462SApril.Chin@Sun.COM #ifdef STANDALONE
enum_create(int argc,char ** argv,void * context)1848462SApril.Chin@Sun.COM static int enum_create(int argc, char** argv, void* context)
1858462SApril.Chin@Sun.COM #else
1868462SApril.Chin@Sun.COM int b_enum(int argc, char** argv, void* context)
1878462SApril.Chin@Sun.COM #endif
1888462SApril.Chin@Sun.COM {
1898462SApril.Chin@Sun.COM 	int			sz,i,n,iflag = 0;
1908462SApril.Chin@Sun.COM 	Namval_t		*np, *tp;
1918462SApril.Chin@Sun.COM 	Namarr_t		*ap;
1928462SApril.Chin@Sun.COM 	char			*cp,*sp;
1938462SApril.Chin@Sun.COM 	struct Enum		*ep;
1948462SApril.Chin@Sun.COM 	Shell_t			*shp = ((Shbltin_t*)context)->shp;
1958462SApril.Chin@Sun.COM 	struct {
1968462SApril.Chin@Sun.COM 	    Optdisc_t	opt;
1978462SApril.Chin@Sun.COM 	    Namval_t	*np;
1988462SApril.Chin@Sun.COM 	}			optdisc;
1998462SApril.Chin@Sun.COM 
2008462SApril.Chin@Sun.COM 	cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
2018462SApril.Chin@Sun.COM 	for (;;)
2028462SApril.Chin@Sun.COM 	{
2038462SApril.Chin@Sun.COM 		switch (optget(argv, enum_usage))
2048462SApril.Chin@Sun.COM 		{
2058462SApril.Chin@Sun.COM 		case 'i':
2068462SApril.Chin@Sun.COM 			iflag = 'i';
2078462SApril.Chin@Sun.COM 			continue;
2088462SApril.Chin@Sun.COM 		case '?':
2098462SApril.Chin@Sun.COM 			error(ERROR_USAGE|4, "%s", opt_info.arg);
2108462SApril.Chin@Sun.COM 			break;
2118462SApril.Chin@Sun.COM 		case ':':
2128462SApril.Chin@Sun.COM 			error(2, "%s", opt_info.arg);
2138462SApril.Chin@Sun.COM 			break;
2148462SApril.Chin@Sun.COM 		}
2158462SApril.Chin@Sun.COM 		break;
2168462SApril.Chin@Sun.COM 	}
2178462SApril.Chin@Sun.COM 	argv += opt_info.index;
2188462SApril.Chin@Sun.COM 	if (error_info.errors || !*argv || *(argv + 1))
2198462SApril.Chin@Sun.COM 	{
2208462SApril.Chin@Sun.COM 		error(ERROR_USAGE|2, "%s", optusage(NiL));
2218462SApril.Chin@Sun.COM 		return 1;
2228462SApril.Chin@Sun.COM 	}
2238462SApril.Chin@Sun.COM 	while(cp = *argv++)
2248462SApril.Chin@Sun.COM 	{
2258462SApril.Chin@Sun.COM 		if(!(np = nv_open(cp, (void*)0, NV_VARNAME|NV_NOADD))  || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem&(((1L<<ARRAY_BITS)-1))) < 2)
2268462SApril.Chin@Sun.COM 			error(ERROR_exit(1), "%s must name an array  containing at least two elements",cp);
2278462SApril.Chin@Sun.COM 		n = staktell();
2288462SApril.Chin@Sun.COM 		sfprintf(stkstd,"%s.%s%c",NV_CLASS,np->nvname,0);
2298462SApril.Chin@Sun.COM 		tp = nv_open(stakptr(n), shp->var_tree, NV_VARNAME);
2308462SApril.Chin@Sun.COM 		stakseek(n);
2318462SApril.Chin@Sun.COM 		n = sz;
2328462SApril.Chin@Sun.COM 		i = 0;
2338462SApril.Chin@Sun.COM 		nv_onattr(tp, NV_UINT16);
2348462SApril.Chin@Sun.COM 		nv_putval(tp, (char*)&i, NV_INTEGER);
2358462SApril.Chin@Sun.COM 		nv_putsub(np, (char*)0, ARRAY_SCAN);
2368462SApril.Chin@Sun.COM 		do
2378462SApril.Chin@Sun.COM 		{
2388462SApril.Chin@Sun.COM 			sz += strlen(nv_getval(np));
2398462SApril.Chin@Sun.COM 		}
2408462SApril.Chin@Sun.COM 		while(nv_nextsub(np));
2418462SApril.Chin@Sun.COM 		sz += n*sizeof(char*);
2428462SApril.Chin@Sun.COM 		if(!(ep = newof(0,struct Enum,1,sz)))
2438462SApril.Chin@Sun.COM 			error(ERROR_system(1), "out of space");
2448462SApril.Chin@Sun.COM 		ep->iflag = iflag;
2458462SApril.Chin@Sun.COM 		ep->nelem = n;
2468462SApril.Chin@Sun.COM 		cp = (char*)&ep->values[n+1];
2478462SApril.Chin@Sun.COM 		nv_putsub(np, (char*)0, ARRAY_SCAN);
2488462SApril.Chin@Sun.COM 		ep->values[n] = 0;
2498462SApril.Chin@Sun.COM 		i = 0;
2508462SApril.Chin@Sun.COM 		do
2518462SApril.Chin@Sun.COM 		{
2528462SApril.Chin@Sun.COM 			ep->values[i++] = cp;
2538462SApril.Chin@Sun.COM 			sp =  nv_getval(np);
2548462SApril.Chin@Sun.COM 			n = strlen(sp);
2558462SApril.Chin@Sun.COM 			memcpy(cp,sp,n+1);
2568462SApril.Chin@Sun.COM 			cp += n+1;
2578462SApril.Chin@Sun.COM 		}
2588462SApril.Chin@Sun.COM 		while(nv_nextsub(np));
2598462SApril.Chin@Sun.COM 		ep->hdr.dsize = sizeof(struct Enum)+sz;
2608462SApril.Chin@Sun.COM 		ep->hdr.disc = &ENUM_disc;
2618462SApril.Chin@Sun.COM 		ep->hdr.type = tp;
2628462SApril.Chin@Sun.COM 		nv_onattr(tp, NV_RDONLY);
2638462SApril.Chin@Sun.COM 		nv_disc(tp, &ep->hdr,NV_FIRST);
2648462SApril.Chin@Sun.COM 		memset(&optdisc,0,sizeof(optdisc));
2658462SApril.Chin@Sun.COM 		optdisc.opt.infof = enuminfo;
2668462SApril.Chin@Sun.COM 		optdisc.np = tp;
2678462SApril.Chin@Sun.COM 		nv_addtype(tp, enum_type, &optdisc.opt, sizeof(optdisc));
2688462SApril.Chin@Sun.COM 	}
2698462SApril.Chin@Sun.COM 	return error_info.errors != 0;
2708462SApril.Chin@Sun.COM }
2718462SApril.Chin@Sun.COM 
2728462SApril.Chin@Sun.COM #ifdef STANDALONE
lib_init(int flag,void * context)2738462SApril.Chin@Sun.COM void lib_init(int flag, void* context)
2748462SApril.Chin@Sun.COM {
2758462SApril.Chin@Sun.COM 	Shell_t		*shp = ((Shbltin_t*)context)->shp;
2768462SApril.Chin@Sun.COM 	Namval_t	*mp,*bp;
2778462SApril.Chin@Sun.COM 	if(flag)
2788462SApril.Chin@Sun.COM 		return;
2798462SApril.Chin@Sun.COM 	bp = sh_addbuiltin("Enum", enum_create, (void*)0);
2808462SApril.Chin@Sun.COM 	mp = nv_search("typeset",shp->bltin_tree,0);
2818462SApril.Chin@Sun.COM 	nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
2828462SApril.Chin@Sun.COM }
2838462SApril.Chin@Sun.COM #endif
284