1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgk@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * getopts optstring name [arg...]
23 *
24 * David Korn
25 * AT&T Labs
26 * research!dgk
27 *
28 */
29
30 #include "defs.h"
31 #include "variables.h"
32 #include <error.h>
33 #include <nval.h>
34 #include "builtins.h"
35
infof(Opt_t * op,Sfio_t * sp,const char * s,Optdisc_t * dp)36 static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
37 {
38 Shell_t *shp = *(Shell_t**)(dp+1);
39 Stk_t *stkp = shp->stk;
40 #if SHOPT_NAMESPACE
41 if((shp->namespace && sh_fsearch(shp,s,0)) || nv_search(s,shp->fun_tree,0))
42 #else
43 if(nv_search(s,shp->fun_tree,0))
44 #endif /* SHOPT_NAMESPACE */
45 {
46 int savtop = stktell(stkp);
47 char *savptr = stkfreeze(stkp,0);
48 sfputc(stkp,'$');
49 sfputc(stkp,'(');
50 sfputr(stkp,s,')');
51 sfputr(sp,sh_mactry(shp,stkfreeze(stkp,1)),-1);
52 stkset(stkp,savptr,savtop);
53 }
54 return(1);
55 }
56
b_getopts(int argc,char * argv[],Shbltin_t * context)57 int b_getopts(int argc,char *argv[],Shbltin_t *context)
58 {
59 register char *options=error_info.context->id;
60 register Namval_t *np;
61 register int flag, mode;
62 register Shell_t *shp = context->shp;
63 char value[2], key[2];
64 int jmpval;
65 volatile int extended, r= -1;
66 struct checkpt buff, *pp;
67 struct {
68 Optdisc_t hdr;
69 Shell_t *sh;
70 } disc;
71 memset(&disc, 0, sizeof(disc));
72 disc.hdr.version = OPT_VERSION;
73 disc.hdr.infof = infof;
74 disc.sh = shp;
75 value[1] = 0;
76 key[1] = 0;
77 while((flag = optget(argv,sh_optgetopts))) switch(flag)
78 {
79 case 'a':
80 options = opt_info.arg;
81 break;
82 case ':':
83 errormsg(SH_DICT,2, "%s", opt_info.arg);
84 break;
85 case '?':
86 errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
87 break;
88 }
89 argv += opt_info.index;
90 argc -= opt_info.index;
91 if(error_info.errors || argc<2)
92 errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
93 error_info.context->flags |= ERROR_SILENT;
94 error_info.id = options;
95 options = argv[0];
96 np = nv_open(argv[1],shp->var_tree,NV_NOASSIGN|NV_VARNAME);
97 if(argc>2)
98 {
99 argv +=1;
100 argc -=1;
101 }
102 else
103 {
104 argv = shp->st.dolv;
105 argc = shp->st.dolc;
106 }
107 opt_info.index = shp->st.optindex;
108 opt_info.offset = shp->st.optchar;
109 if(mode= (*options==':'))
110 options++;
111 extended = *options=='\n' && *(options+1)=='[' || *options=='[' && *(options+1)=='-';
112 sh_pushcontext(shp,&buff,1);
113 jmpval = sigsetjmp(buff.buff,0);
114 if(jmpval)
115 {
116 sh_popcontext(shp,&buff);
117 shp->st.opterror = 1;
118 if(r==0)
119 return(2);
120 pp = (struct checkpt*)shp->jmplist;
121 pp->mode = SH_JMPERREXIT;
122 sh_exit(2);
123 }
124 opt_info.disc = &disc.hdr;
125 switch(opt_info.index>=0 && opt_info.index<=argc?(opt_info.num= LONG_MIN,flag=optget(argv,options)):0)
126 {
127 case '?':
128 if(mode==0)
129 errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
130 opt_info.option[1] = '?';
131 /* FALL THRU */
132 case ':':
133 key[0] = opt_info.option[1];
134 if(strmatch(opt_info.arg,"*unknown*"))
135 flag = '?';
136 if(mode)
137 opt_info.arg = key;
138 else
139 {
140 errormsg(SH_DICT,2, "%s", opt_info.arg);
141 opt_info.arg = 0;
142 flag = '?';
143 }
144 *(options = value) = flag;
145 shp->st.opterror = 1;
146 if (opt_info.offset != 0 && !argv[opt_info.index][opt_info.offset])
147 {
148 opt_info.offset = 0;
149 opt_info.index++;
150 }
151 break;
152 case 0:
153 if(shp->st.opterror)
154 {
155 char *com[2];
156 com[0] = "-?";
157 com[1] = 0;
158 flag = opt_info.index;
159 opt_info.index = 0;
160 optget(com,options);
161 opt_info.index = flag;
162 if(!mode && strchr(options,' '))
163 errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
164 }
165 opt_info.arg = 0;
166 options = value;
167 *options = '?';
168 r=1;
169 opt_info.offset = 0;
170 break;
171 default:
172 options = opt_info.option + (*opt_info.option!='+');
173 }
174 if(r<0)
175 r = 0;
176 error_info.context->flags &= ~ERROR_SILENT;
177 shp->st.optindex = opt_info.index;
178 shp->st.optchar = opt_info.offset;
179 nv_putval(np, options, 0);
180 nv_close(np);
181 np = nv_open(nv_name(OPTARGNOD),shp->var_tree,0);
182 if(opt_info.num == LONG_MIN)
183 nv_putval(np, opt_info.arg, NV_RDONLY);
184 else if (opt_info.arg && opt_info.num > 0 && isalpha((char)opt_info.num) && !isdigit(opt_info.arg[0]) && opt_info.arg[0] != '-' && opt_info.arg[0] != '+')
185 {
186 key[0] = (char)opt_info.num;
187 key[1] = 0;
188 nv_putval(np, key, NV_RDONLY);
189 }
190 else if(extended)
191 {
192 Sfdouble_t d;
193 d = opt_info.number;
194 nv_putval(np, (char*)&d, NV_LDOUBLE|NV_RDONLY);
195 }
196 else
197 nv_putval(np, opt_info.arg, NV_RDONLY);
198 nv_close(np);
199 sh_popcontext(shp,&buff);
200 opt_info.disc = 0;
201 return(r);
202 }
203
204