1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * David Korn <dgk@research.att.com> *
19 ***********************************************************************/
23 static const char enum_usage
[] =
24 "[-?@(#)$Id: enum (AT&T Research) 2008-01-08 $\n]"
26 "[+NAME?enum - create an enumeration type]"
27 "[+DESCRIPTION?\benum\b is a declaration command that creates an enumeration "
28 "type \atypename\a that can only store any one of the values in the indexed "
29 "array variable \atypename\a.]"
30 "[+?If the list of \avalue\as is omitted, then \atypename\a must name an "
31 "indexed array variable with at least two elements.]"
32 "[i:ignorecase?The values are case insensitive.]"
34 "\n\atypename\a[\b=(\b \avalue\a ... \b)\b]\n"
38 "[+0?Successful completion.]"
39 "[+>0?An error occurred.]"
41 "[+SEE ALSO?\bksh\b(1), \btypeset\b(1).]"
44 static const char enum_type
[] =
45 "[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-01-08 $\n]"
47 "[+NAME?\f?\f - create an instance of type \b\f?\f\b]"
48 "[+DESCRIPTION?\b\f?\f\b creates a variable for each \aname\a with "
49 "enumeration type \b\f?\f\b where \b\f?\f\b is a type that has been "
50 "created with the \benum\b(1) command.]"
51 "[+?The variable can have one of the following values\fvalues\f. "
52 "The the values are \fcase\fcase sensitive.]"
53 "[+?If \b=\b\avalue\a is omitted, the default is \fdefault\f.]"
54 "[+?If no \aname\as are specified then the names and values of all "
55 "variables of this type are written to standard output.]"
56 "[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
57 "field splitting and pathname expansion are not performed on "
58 "the arguments. Tilde expansion occurs on \avalue\a.]"
59 "[r?Enables readonly. Once enabled, the value cannot be changed or unset.]"
60 "[a?index array. Each \aname\a will converted to an index "
61 "array of type \b\f?\f\b. If a variable already exists, the current "
62 "value will become index \b0\b.]"
63 "[A?Associative array. Each \aname\a will converted to an associate "
64 "array of type \b\f?\f\b. If a variable already exists, the current "
65 "value will become subscript \b0\b.]"
66 "[h]:[string?Used within a type definition to provide a help string "
67 "for variable \aname\a. Otherwise, it is ignored.]"
68 "[S?Used with a type definition to indicate that the variable is shared by "
69 "each instance of the type. When used inside a function defined "
70 "with the \bfunction\b reserved word, the specified variables "
71 "will have function static scope. Otherwise, the variable is "
72 "unset prior to processing the assignment list.]"
74 "[p?Causes the output to be in a form of \b\f?\f\b commands that can be "
75 "used as input to the shell to recreate the current type of "
79 "\n[name[=value]...]\n"
82 "[+0?Successful completion.]"
83 "[+>0?An error occurred.]"
86 "[+SEE ALSO?\benum\b(1), \btypeset\b(1)]"
94 const char *values
[1];
97 static int enuminfo(Opt_t
* op
, Sfio_t
*out
, const char *str
, Optdisc_t
*fp
)
103 np
= *(Namval_t
**)(fp
+1);
104 ep
= (struct Enum
*)np
->nvfun
;
105 if(strcmp(str
,"default")==0)
107 sfprintf(out
,"\b%s\b%c",ep
->values
[0],0);
109 sfprintf(out
,"\b%s\b",ep
->values
[0]);
111 else if(strcmp(str
,"case")==0)
114 sfprintf(out
,"not ");
116 else while(v
=ep
->values
[n
++])
118 sfprintf(out
,", \b%s\b",v
);
123 static Namfun_t
*clone_enum(Namval_t
* np
, Namval_t
*mp
, int flags
, Namfun_t
*fp
)
125 struct Enum
*ep
, *pp
=(struct Enum
*)fp
;
126 ep
= newof(0,struct Enum
,1,pp
->nelem
*sizeof(char*));
127 memcpy((void*)ep
,(void*)pp
,sizeof(struct Enum
)+pp
->nelem
*sizeof(char*));
131 static void put_enum(Namval_t
* np
,const char *val
,int flags
,Namfun_t
*fp
)
133 struct Enum
*ep
= (struct Enum
*)fp
;
134 register const char *v
;
135 unsigned short i
=0, n
;
138 nv_disc(np
,&ep
->hdr
,NV_POP
);
141 nv_putv(np
, val
, flags
,fp
);
146 nv_putv(np
,val
,flags
,fp
);
149 while(v
=ep
->values
[i
])
152 n
= strcasecmp(v
,val
);
157 nv_putv(np
, (char*)&i
, NV_UINT16
, fp
);
162 error(ERROR_exit(1), "%s: invalid value %s",nv_name(np
),val
);
165 static char* get_enum(register Namval_t
* np
, Namfun_t
*fp
)
168 struct Enum
*ep
= (struct Enum
*)fp
;
169 long n
= nv_getn(np
,fp
);
171 return((char*)ep
->values
[n
]);
172 sfsprintf(buff
,sizeof(buff
),"%u%c",n
,0);
176 static Sfdouble_t
get_nenum(register Namval_t
* np
, Namfun_t
*fp
)
178 return(nv_getn(np
,fp
));
181 const Namdisc_t ENUM_disc
= { 0, put_enum
, get_enum
, get_nenum
, 0,0,clone_enum
};
184 static int enum_create(int argc
, char** argv
, void* context
)
186 int b_enum(int argc
, char** argv
, void* context
)
189 int sz
,i
,n
,iflag
= 0;
194 Shell_t
*shp
= ((Shbltin_t
*)context
)->shp
;
200 cmdinit(argc
, argv
, context
, ERROR_CATALOG
, ERROR_NOTIFY
);
203 switch (optget(argv
, enum_usage
))
209 error(ERROR_USAGE
|4, "%s", opt_info
.arg
);
212 error(2, "%s", opt_info
.arg
);
217 argv
+= opt_info
.index
;
218 if (error_info
.errors
|| !*argv
|| *(argv
+ 1))
220 error(ERROR_USAGE
|2, "%s", optusage(NiL
));
225 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)
226 error(ERROR_exit(1), "%s must name an array containing at least two elements",cp
);
228 sfprintf(stkstd
,"%s.%s%c",NV_CLASS
,np
->nvname
,0);
229 tp
= nv_open(stakptr(n
), shp
->var_tree
, NV_VARNAME
);
233 nv_onattr(tp
, NV_UINT16
);
234 nv_putval(tp
, (char*)&i
, NV_INTEGER
);
235 nv_putsub(np
, (char*)0, ARRAY_SCAN
);
238 sz
+= strlen(nv_getval(np
));
240 while(nv_nextsub(np
));
241 sz
+= n
*sizeof(char*);
242 if(!(ep
= newof(0,struct Enum
,1,sz
)))
243 error(ERROR_system(1), "out of space");
246 cp
= (char*)&ep
->values
[n
+1];
247 nv_putsub(np
, (char*)0, ARRAY_SCAN
);
252 ep
->values
[i
++] = cp
;
258 while(nv_nextsub(np
));
259 ep
->hdr
.dsize
= sizeof(struct Enum
)+sz
;
260 ep
->hdr
.disc
= &ENUM_disc
;
262 nv_onattr(tp
, NV_RDONLY
);
263 nv_disc(tp
, &ep
->hdr
,NV_FIRST
);
264 memset(&optdisc
,0,sizeof(optdisc
));
265 optdisc
.opt
.infof
= enuminfo
;
267 nv_addtype(tp
, enum_type
, &optdisc
.opt
, sizeof(optdisc
));
269 return error_info
.errors
!= 0;
273 void lib_init(int flag
, void* context
)
275 Shell_t
*shp
= ((Shbltin_t
*)context
)->shp
;
279 bp
= sh_addbuiltin("Enum", enum_create
, (void*)0);
280 mp
= nv_search("typeset",shp
->bltin_tree
,0);
281 nv_onattr(bp
,nv_isattr(mp
,NV_PUBLIC
));