Home | History | Annotate | Download | only in bltins
      1 /***********************************************************************
      2 *                                                                      *
      3 *               This software is part of the ast package               *
      4 *          Copyright (c) 1982-2009 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 (at) 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 	Shell_t	*shp = *(Shell_t**)(dp+1);
     39 	Stk_t	*stkp = shp->stk;
     40 	if(nv_search(s,sh.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 
     53 int	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, r=0;
     58 	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
     59 	char value[2], key[2];
     60 	int jmpval,extended;
     61 	struct checkpt buff, *pp;
     62 	struct {
     63 	        Optdisc_t	hdr;
     64 		Shell_t		*sh;
     65 	} disc;
     66         memset(&disc, 0, sizeof(disc));
     67         disc.hdr.version = OPT_VERSION;
     68         disc.hdr.infof = infof;
     69 	disc.sh = shp;
     70 	value[1] = 0;
     71 	key[1] = 0;
     72 	while((flag = optget(argv,sh_optgetopts))) switch(flag)
     73 	{
     74 	    case 'a':
     75 		options = opt_info.arg;
     76 		break;
     77 	    case ':':
     78 		errormsg(SH_DICT,2, "%s", opt_info.arg);
     79 		break;
     80 	    case '?':
     81 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
     82 		break;
     83 	}
     84 	argv += opt_info.index;
     85 	argc -= opt_info.index;
     86 	if(error_info.errors || argc<2)
     87 		errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
     88 	error_info.context->flags |= ERROR_SILENT;
     89 	error_info.id = options;
     90 	options = argv[0];
     91 	np = nv_open(argv[1],shp->var_tree,NV_NOASSIGN|NV_VARNAME);
     92 	if(argc>2)
     93 	{
     94 		argv +=1;
     95 		argc -=1;
     96 	}
     97 	else
     98 	{
     99 		argv = shp->st.dolv;
    100 		argc = shp->st.dolc;
    101 	}
    102 	opt_info.index = shp->st.optindex;
    103 	opt_info.offset = shp->st.optchar;
    104 	if(mode= (*options==':'))
    105 		options++;
    106 	extended = *options=='\n' && *(options+1)=='[' || *options=='[' && *(options+1)=='-';
    107 	sh_pushcontext(&buff,1);
    108 	jmpval = sigsetjmp(buff.buff,0);
    109 	if(jmpval)
    110 	{
    111 		sh_popcontext(&buff);
    112 		pp = (struct checkpt*)shp->jmplist;
    113 		pp->mode = SH_JMPERREXIT;
    114 		sh_exit(2);
    115 	}
    116         opt_info.disc = &disc.hdr;
    117 	switch(opt_info.index>=0 && opt_info.index<=argc?(opt_info.num= LONG_MIN,flag=optget(argv,options)):0)
    118 	{
    119 	    case '?':
    120 		if(mode==0)
    121 			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
    122 		opt_info.option[1] = '?';
    123 		/* FALL THRU */
    124 	    case ':':
    125 		key[0] = opt_info.option[1];
    126 		if(strmatch(opt_info.arg,"*unknown*"))
    127 			flag = '?';
    128 		if(mode)
    129 			opt_info.arg = key;
    130 		else
    131 		{
    132 			errormsg(SH_DICT,2, "%s", opt_info.arg);
    133 			opt_info.arg = 0;
    134 			flag = '?';
    135 		}
    136 		*(options = value) = flag;
    137 		shp->st.opterror = 1;
    138 		if (opt_info.offset != 0 && !argv[opt_info.index][opt_info.offset])
    139 		{
    140 			opt_info.offset = 0;
    141 			opt_info.index++;
    142 		}
    143 		break;
    144 	    case 0:
    145 		if(shp->st.opterror)
    146 		{
    147 			char *com[2];
    148 			com[0] = "-?";
    149 			com[1] = 0;
    150 			flag = opt_info.index;
    151 			opt_info.index = 0;
    152 			optget(com,options);
    153 			opt_info.index = flag;
    154 			if(!mode && strchr(options,' '))
    155 				errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
    156 		}
    157 		opt_info.arg = 0;
    158 		options = value;
    159 		*options = '?';
    160 		r=1;
    161 		opt_info.offset = 0;
    162 		break;
    163 	    default:
    164 		options = opt_info.option + (*opt_info.option!='+');
    165 	}
    166 	error_info.context->flags &= ~ERROR_SILENT;
    167 	shp->st.optindex = opt_info.index;
    168 	shp->st.optchar = opt_info.offset;
    169 	nv_putval(np, options, 0);
    170 	nv_close(np);
    171 	np = nv_open(nv_name(OPTARGNOD),shp->var_tree,NV_NOSCOPE);
    172 	if(opt_info.num == LONG_MIN)
    173 		nv_putval(np, opt_info.arg, NV_RDONLY);
    174 	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] != '+')
    175 	{
    176 		key[0] = (char)opt_info.num;
    177 		key[1] = 0;
    178 		nv_putval(np, key, NV_RDONLY);
    179 	}
    180 	else if(extended)
    181 	{
    182 		Sfdouble_t d;
    183 		d = opt_info.number;
    184 		nv_putval(np, (char*)&d, NV_LDOUBLE|NV_RDONLY);
    185 	}
    186 	else
    187 		nv_putval(np, opt_info.arg, NV_RDONLY);
    188 	nv_close(np);
    189 	sh_popcontext(&buff);
    190         opt_info.disc = 0;
    191 	return(r);
    192 }
    193 
    194