1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1982-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
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
36static 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(nv_search(s,shp->fun_tree,0))
41	{
42		int savtop = stktell(stkp);
43		char *savptr = stkfreeze(stkp,0);
44		sfputc(stkp,'$');
45		sfputc(stkp,'(');
46		sfputr(stkp,s,')');
47		sfputr(sp,sh_mactry(shp,stkfreeze(stkp,1)),-1);
48		stkset(stkp,savptr,savtop);
49	}
50        return(1);
51}
52
53int	b_getopts(int argc,char *argv[],void *extra)
54{
55	register char *options=error_info.context->id;
56	register Namval_t *np;
57	register int flag, mode;
58	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
59	char value[2], key[2];
60	int jmpval,extended;
61	volatile int r= -1;
62	struct checkpt buff, *pp;
63	struct {
64	        Optdisc_t	hdr;
65		Shell_t		*sh;
66	} disc;
67        memset(&disc, 0, sizeof(disc));
68        disc.hdr.version = OPT_VERSION;
69        disc.hdr.infof = infof;
70	disc.sh = shp;
71	value[1] = 0;
72	key[1] = 0;
73	while((flag = optget(argv,sh_optgetopts))) switch(flag)
74	{
75	    case 'a':
76		options = opt_info.arg;
77		break;
78	    case ':':
79		errormsg(SH_DICT,2, "%s", opt_info.arg);
80		break;
81	    case '?':
82		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
83		break;
84	}
85	argv += opt_info.index;
86	argc -= opt_info.index;
87	if(error_info.errors || argc<2)
88		errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
89	error_info.context->flags |= ERROR_SILENT;
90	error_info.id = options;
91	options = argv[0];
92	np = nv_open(argv[1],shp->var_tree,NV_NOASSIGN|NV_VARNAME);
93	if(argc>2)
94	{
95		argv +=1;
96		argc -=1;
97	}
98	else
99	{
100		argv = shp->st.dolv;
101		argc = shp->st.dolc;
102	}
103	opt_info.index = shp->st.optindex;
104	opt_info.offset = shp->st.optchar;
105	if(mode= (*options==':'))
106		options++;
107	extended = *options=='\n' && *(options+1)=='[' || *options=='[' && *(options+1)=='-';
108	sh_pushcontext(shp,&buff,1);
109	jmpval = sigsetjmp(buff.buff,0);
110	if(jmpval)
111	{
112		sh_popcontext(shp,&buff);
113		shp->st.opterror = 1;
114		if(r==0)
115			return(2);
116		pp = (struct checkpt*)shp->jmplist;
117		pp->mode = SH_JMPERREXIT;
118		sh_exit(2);
119	}
120        opt_info.disc = &disc.hdr;
121	switch(opt_info.index>=0 && opt_info.index<=argc?(opt_info.num= LONG_MIN,flag=optget(argv,options)):0)
122	{
123	    case '?':
124		if(mode==0)
125			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
126		opt_info.option[1] = '?';
127		/* FALL THRU */
128	    case ':':
129		key[0] = opt_info.option[1];
130		if(strmatch(opt_info.arg,"*unknown*"))
131			flag = '?';
132		if(mode)
133			opt_info.arg = key;
134		else
135		{
136			errormsg(SH_DICT,2, "%s", opt_info.arg);
137			opt_info.arg = 0;
138			flag = '?';
139		}
140		*(options = value) = flag;
141		shp->st.opterror = 1;
142		if (opt_info.offset != 0 && !argv[opt_info.index][opt_info.offset])
143		{
144			opt_info.offset = 0;
145			opt_info.index++;
146		}
147		break;
148	    case 0:
149		if(shp->st.opterror)
150		{
151			char *com[2];
152			com[0] = "-?";
153			com[1] = 0;
154			flag = opt_info.index;
155			opt_info.index = 0;
156			optget(com,options);
157			opt_info.index = flag;
158			if(!mode && strchr(options,' '))
159				errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
160		}
161		opt_info.arg = 0;
162		options = value;
163		*options = '?';
164		r=1;
165		opt_info.offset = 0;
166		break;
167	    default:
168		options = opt_info.option + (*opt_info.option!='+');
169	}
170	if(r<0)
171		r = 0;
172	error_info.context->flags &= ~ERROR_SILENT;
173	shp->st.optindex = opt_info.index;
174	shp->st.optchar = opt_info.offset;
175	nv_putval(np, options, 0);
176	nv_close(np);
177	np = nv_open(nv_name(OPTARGNOD),shp->var_tree,NV_NOSCOPE);
178	if(opt_info.num == LONG_MIN)
179		nv_putval(np, opt_info.arg, NV_RDONLY);
180	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] != '+')
181	{
182		key[0] = (char)opt_info.num;
183		key[1] = 0;
184		nv_putval(np, key, NV_RDONLY);
185	}
186	else if(extended)
187	{
188		Sfdouble_t d;
189		d = opt_info.number;
190		nv_putval(np, (char*)&d, NV_LDOUBLE|NV_RDONLY);
191	}
192	else
193		nv_putval(np, opt_info.arg, NV_RDONLY);
194	nv_close(np);
195	sh_popcontext(shp,&buff);
196        opt_info.disc = 0;
197	return(r);
198}
199
200