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