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 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 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 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 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 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 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 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