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