|
Packit Service |
a8c26c |
/***********************************************************************
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* This software is part of the ast package *
|
|
Packit Service |
a8c26c |
* Copyright (c) 1982-2012 AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* and is licensed under the *
|
|
Packit Service |
a8c26c |
* Eclipse Public License, Version 1.0 *
|
|
Packit Service |
a8c26c |
* by AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* A copy of the License is available at *
|
|
Packit Service |
a8c26c |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit Service |
a8c26c |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Information and Software Systems Research *
|
|
Packit Service |
a8c26c |
* AT&T Research *
|
|
Packit Service |
a8c26c |
* Florham Park NJ *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* David Korn <dgk@research.att.com> *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
***********************************************************************/
|
|
Packit Service |
a8c26c |
#pragma prototyped
|
|
Packit Service |
a8c26c |
#include <shell.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static const char enum_usage[] =
|
|
Packit Service |
a8c26c |
"[-?@(#)$Id: enum (AT&T Research) 2008-01-08 $\n]"
|
|
Packit Service |
a8c26c |
USAGE_LICENSE
|
|
Packit Service |
a8c26c |
"[+NAME?enum - create an enumeration type]"
|
|
Packit Service |
a8c26c |
"[+DESCRIPTION?\benum\b is a declaration command that creates an enumeration "
|
|
Packit Service |
a8c26c |
"type \atypename\a that can only store any one of the values in the indexed "
|
|
Packit Service |
a8c26c |
"array variable \atypename\a.]"
|
|
Packit Service |
a8c26c |
"[+?If the list of \avalue\as is omitted, then \atypename\a must name an "
|
|
Packit Service |
a8c26c |
"indexed array variable with at least two elements.]"
|
|
Packit Service |
a8c26c |
"[i:ignorecase?The values are case insensitive.]"
|
|
Packit Service |
a8c26c |
"\n"
|
|
Packit Service |
a8c26c |
"\n\atypename\a[\b=(\b \avalue\a ... \b)\b]\n"
|
|
Packit Service |
a8c26c |
"\n"
|
|
Packit Service |
a8c26c |
"[+EXIT STATUS]"
|
|
Packit Service |
a8c26c |
"{"
|
|
Packit Service |
a8c26c |
"[+0?Successful completion.]"
|
|
Packit Service |
a8c26c |
"[+>0?An error occurred.]"
|
|
Packit Service |
a8c26c |
"}"
|
|
Packit Service |
a8c26c |
"[+SEE ALSO?\bksh\b(1), \btypeset\b(1).]"
|
|
Packit Service |
a8c26c |
;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static const char enum_type[] =
|
|
Packit Service |
a8c26c |
"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-01-08 $\n]"
|
|
Packit Service |
a8c26c |
USAGE_LICENSE
|
|
Packit Service |
a8c26c |
"[+NAME?\f?\f - create an instance of type \b\f?\f\b]"
|
|
Packit Service |
a8c26c |
"[+DESCRIPTION?\b\f?\f\b creates a variable for each \aname\a with "
|
|
Packit Service |
a8c26c |
"enumeration type \b\f?\f\b where \b\f?\f\b is a type that has been "
|
|
Packit Service |
a8c26c |
"created with the \benum\b(1) command.]"
|
|
Packit Service |
a8c26c |
"[+?The variable can have one of the following values\fvalues\f. "
|
|
Packit Service |
a8c26c |
"The the values are \fcase\fcase sensitive.]"
|
|
Packit Service |
a8c26c |
"[+?If \b=\b\avalue\a is omitted, the default is \fdefault\f.]"
|
|
Packit Service |
a8c26c |
"[+?If no \aname\as are specified then the names and values of all "
|
|
Packit Service |
a8c26c |
"variables of this type are written to standard output.]"
|
|
Packit Service |
a8c26c |
"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
|
|
Packit Service |
a8c26c |
"field splitting and pathname expansion are not performed on "
|
|
Packit Service |
a8c26c |
"the arguments. Tilde expansion occurs on \avalue\a.]"
|
|
Packit Service |
a8c26c |
"[r?Enables readonly. Once enabled, the value cannot be changed or unset.]"
|
|
Packit Service |
a8c26c |
"[a?index array. Each \aname\a will converted to an index "
|
|
Packit Service |
a8c26c |
"array of type \b\f?\f\b. If a variable already exists, the current "
|
|
Packit Service |
a8c26c |
"value will become index \b0\b.]"
|
|
Packit Service |
a8c26c |
"[A?Associative array. Each \aname\a will converted to an associate "
|
|
Packit Service |
a8c26c |
"array of type \b\f?\f\b. If a variable already exists, the current "
|
|
Packit Service |
a8c26c |
"value will become subscript \b0\b.]"
|
|
Packit Service |
a8c26c |
"[h]:[string?Used within a type definition to provide a help string "
|
|
Packit Service |
a8c26c |
"for variable \aname\a. Otherwise, it is ignored.]"
|
|
Packit Service |
a8c26c |
"[S?Used with a type definition to indicate that the variable is shared by "
|
|
Packit Service |
a8c26c |
"each instance of the type. When used inside a function defined "
|
|
Packit Service |
a8c26c |
"with the \bfunction\b reserved word, the specified variables "
|
|
Packit Service |
a8c26c |
"will have function static scope. Otherwise, the variable is "
|
|
Packit Service |
a8c26c |
"unset prior to processing the assignment list.]"
|
|
Packit Service |
a8c26c |
#if 0
|
|
Packit Service |
a8c26c |
"[p?Causes the output to be in a form of \b\f?\f\b commands that can be "
|
|
Packit Service |
a8c26c |
"used as input to the shell to recreate the current type of "
|
|
Packit Service |
a8c26c |
"these variables.]"
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
"\n"
|
|
Packit Service |
a8c26c |
"\n[name[=value]...]\n"
|
|
Packit Service |
a8c26c |
"\n"
|
|
Packit Service |
a8c26c |
"[+EXIT STATUS?]{"
|
|
Packit Service |
a8c26c |
"[+0?Successful completion.]"
|
|
Packit Service |
a8c26c |
"[+>0?An error occurred.]"
|
|
Packit Service |
a8c26c |
"}"
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
"[+SEE ALSO?\benum\b(1), \btypeset\b(1)]"
|
|
Packit Service |
a8c26c |
;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
struct Enum
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Namfun_t hdr;
|
|
Packit Service |
a8c26c |
short nelem;
|
|
Packit Service |
a8c26c |
short iflag;
|
|
Packit Service |
a8c26c |
const char *values[1];
|
|
Packit Service |
a8c26c |
};
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static int enuminfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Namval_t *np;
|
|
Packit Service |
a8c26c |
struct Enum *ep;
|
|
Packit Service |
a8c26c |
int n=0;
|
|
Packit Service |
a8c26c |
const char *v;
|
|
Packit Service |
a8c26c |
np = *(Namval_t**)(fp+1);
|
|
Packit Service |
a8c26c |
ep = (struct Enum*)np->nvfun;
|
|
Packit Service |
a8c26c |
if(strcmp(str,"default")==0)
|
|
Packit Service |
a8c26c |
#if 0
|
|
Packit Service |
a8c26c |
sfprintf(out,"\b%s\b%c",ep->values[0],0);
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
sfprintf(out,"\b%s\b",ep->values[0]);
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
else if(strcmp(str,"case")==0)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if(ep->iflag)
|
|
Packit Service |
a8c26c |
sfprintf(out,"not ");
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else while(v=ep->values[n++])
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
sfprintf(out,", \b%s\b",v);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
return(0);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static Namfun_t *clone_enum(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
struct Enum *ep, *pp=(struct Enum*)fp;
|
|
Packit Service |
a8c26c |
ep = newof(0,struct Enum,1,pp->nelem*sizeof(char*));
|
|
Packit Service |
a8c26c |
memcpy((void*)ep,(void*)pp,sizeof(struct Enum)+pp->nelem*sizeof(char*));
|
|
Packit Service |
a8c26c |
return(&ep->hdr);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static void put_enum(Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
struct Enum *ep = (struct Enum*)fp;
|
|
Packit Service |
a8c26c |
register const char *v;
|
|
Packit Service |
a8c26c |
unsigned short i=0, n;
|
|
Packit Service |
a8c26c |
if(!val)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
nv_putv(np, val, flags,fp);
|
|
Packit Service |
a8c26c |
nv_disc(np,&ep->hdr,NV_POP);
|
|
Packit Service |
a8c26c |
if(!ep->hdr.nofree)
|
|
Packit Service |
a8c26c |
free((void*)ep);
|
|
Packit Service |
a8c26c |
return;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(flags&NV_INTEGER)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
nv_putv(np,val,flags,fp);
|
|
Packit Service |
a8c26c |
return;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
while(v=ep->values[i])
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if(ep->iflag)
|
|
Packit Service |
a8c26c |
n = strcasecmp(v,val);
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
n = strcmp(v,val);
|
|
Packit Service |
a8c26c |
if(n==0)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
nv_putv(np, (char*)&i, NV_UINT16, fp);
|
|
Packit Service |
a8c26c |
return;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
i++;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(nv_isattr(np,NV_NOFREE))
|
|
Packit Service |
a8c26c |
error(ERROR_exit(1), "%s: invalid value %s",nv_name(np),val);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static char* get_enum(register Namval_t* np, Namfun_t *fp)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
static char buff[6];
|
|
Packit Service |
a8c26c |
struct Enum *ep = (struct Enum*)fp;
|
|
Packit Service |
a8c26c |
long n = nv_getn(np,fp);
|
|
Packit Service |
a8c26c |
if(n < ep->nelem)
|
|
Packit Service |
a8c26c |
return((char*)ep->values[n]);
|
|
Packit Service |
a8c26c |
sfsprintf(buff,sizeof(buff),"%u%c",n,0);
|
|
Packit Service |
a8c26c |
return(buff);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static Sfdouble_t get_nenum(register Namval_t* np, Namfun_t *fp)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
return(nv_getn(np,fp));
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
const Namdisc_t ENUM_disc = { 0, put_enum, get_enum, get_nenum, 0,0,clone_enum };
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#ifdef STANDALONE
|
|
Packit Service |
a8c26c |
static int enum_create(int argc, char** argv, Shbltin_t *context)
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
int b_enum(int argc, char** argv, Shbltin_t *context)
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
int sz,i,n,iflag = 0;
|
|
Packit Service |
a8c26c |
Namval_t *np, *tp;
|
|
Packit Service |
a8c26c |
Namarr_t *ap;
|
|
Packit Service |
a8c26c |
char *cp,*sp;
|
|
Packit Service |
a8c26c |
struct Enum *ep;
|
|
Packit Service |
a8c26c |
Shell_t *shp = context->shp;
|
|
Packit Service |
a8c26c |
struct {
|
|
Packit Service |
a8c26c |
Optdisc_t opt;
|
|
Packit Service |
a8c26c |
Namval_t *np;
|
|
Packit Service |
a8c26c |
} optdisc;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
|
|
Packit Service |
a8c26c |
for (;;)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
switch (optget(argv, enum_usage))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
case 'i':
|
|
Packit Service |
a8c26c |
iflag = 'i';
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
case '?':
|
|
Packit Service |
a8c26c |
error(ERROR_USAGE|4, "%s", opt_info.arg);
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case ':':
|
|
Packit Service |
a8c26c |
error(2, "%s", opt_info.arg);
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
argv += opt_info.index;
|
|
Packit Service |
a8c26c |
if (error_info.errors || !*argv || *(argv + 1))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
error(ERROR_USAGE|2, "%s", optusage(NiL));
|
|
Packit Service |
a8c26c |
return 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
while(cp = *argv++)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if(!(np = nv_open(cp, (void*)0, NV_VARNAME|NV_NOADD)) || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem&(((1L<
|
|
Packit Service |
a8c26c |
error(ERROR_exit(1), "%s must name an array containing at least two elements",cp);
|
|
Packit Service |
a8c26c |
n = staktell();
|
|
Packit Service |
a8c26c |
sfprintf(stkstd,"%s.%s%c",NV_CLASS,np->nvname,0);
|
|
Packit Service |
a8c26c |
tp = nv_open(stakptr(n), shp->var_tree, NV_VARNAME);
|
|
Packit Service |
a8c26c |
stakseek(n);
|
|
Packit Service |
a8c26c |
n = sz;
|
|
Packit Service |
a8c26c |
i = 0;
|
|
Packit Service |
a8c26c |
nv_onattr(tp, NV_UINT16);
|
|
Packit Service |
a8c26c |
nv_putval(tp, (char*)&i, NV_INTEGER);
|
|
Packit Service |
a8c26c |
nv_putsub(np, (char*)0, ARRAY_SCAN);
|
|
Packit Service |
a8c26c |
do
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
sz += strlen(nv_getval(np));
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
while(nv_nextsub(np));
|
|
Packit Service |
a8c26c |
sz += n*sizeof(char*);
|
|
Packit Service |
a8c26c |
if(!(ep = newof(0,struct Enum,1,sz)))
|
|
Packit Service |
a8c26c |
error(ERROR_system(1), "out of space");
|
|
Packit Service |
a8c26c |
ep->iflag = iflag;
|
|
Packit Service |
a8c26c |
ep->nelem = n;
|
|
Packit Service |
a8c26c |
cp = (char*)&ep->values[n+1];
|
|
Packit Service |
a8c26c |
nv_putsub(np, (char*)0, ARRAY_SCAN);
|
|
Packit Service |
a8c26c |
ep->values[n] = 0;
|
|
Packit Service |
a8c26c |
i = 0;
|
|
Packit Service |
a8c26c |
do
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
ep->values[i++] = cp;
|
|
Packit Service |
a8c26c |
sp = nv_getval(np);
|
|
Packit Service |
a8c26c |
n = strlen(sp);
|
|
Packit Service |
a8c26c |
memcpy(cp,sp,n+1);
|
|
Packit Service |
a8c26c |
cp += n+1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
while(nv_nextsub(np));
|
|
Packit Service |
a8c26c |
ep->hdr.dsize = sizeof(struct Enum)+sz;
|
|
Packit Service |
a8c26c |
ep->hdr.disc = &ENUM_disc;
|
|
Packit Service |
a8c26c |
ep->hdr.type = tp;
|
|
Packit Service |
a8c26c |
nv_onattr(tp, NV_RDONLY);
|
|
Packit Service |
a8c26c |
nv_disc(tp, &ep->hdr,NV_FIRST);
|
|
Packit Service |
a8c26c |
memset(&optdisc,0,sizeof(optdisc));
|
|
Packit Service |
a8c26c |
optdisc.opt.infof = enuminfo;
|
|
Packit Service |
a8c26c |
optdisc.np = tp;
|
|
Packit Service |
a8c26c |
nv_addtype(tp, enum_type, &optdisc.opt, sizeof(optdisc));
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
return error_info.errors != 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#ifdef STANDALONE
|
|
Packit Service |
a8c26c |
void lib_init(int flag, void* context)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Shell_t *shp = ((Shbltin_t*)context)->shp;
|
|
Packit Service |
a8c26c |
Namval_t *mp,*bp;
|
|
Packit Service |
a8c26c |
if(flag)
|
|
Packit Service |
a8c26c |
return;
|
|
Packit Service |
a8c26c |
bp = sh_addbuiltin("Enum", enum_create, (void*)0);
|
|
Packit Service |
a8c26c |
mp = nv_search("typeset",shp->bltin_tree,0);
|
|
Packit Service |
a8c26c |
nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#endif
|