1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2010 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 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