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