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