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