14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * getopts optstring name [arg...] 234887Schin * 244887Schin * David Korn 254887Schin * AT&T Labs 264887Schin * research!dgk 274887Schin * 284887Schin */ 294887Schin 304887Schin #include "defs.h" 314887Schin #include "variables.h" 324887Schin #include <error.h> 334887Schin #include <nval.h> 344887Schin #include "builtins.h" 354887Schin 364887Schin static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp) 374887Schin { 38*8462SApril.Chin@Sun.COM Shell_t *shp = *(Shell_t**)(dp+1); 39*8462SApril.Chin@Sun.COM Stk_t *stkp = shp->stk; 404887Schin if(nv_search(s,sh.fun_tree,0)) 414887Schin { 42*8462SApril.Chin@Sun.COM int savtop = stktell(stkp); 43*8462SApril.Chin@Sun.COM char *savptr = stkfreeze(stkp,0); 44*8462SApril.Chin@Sun.COM sfputc(stkp,'$'); 45*8462SApril.Chin@Sun.COM sfputc(stkp,'('); 46*8462SApril.Chin@Sun.COM sfputr(stkp,s,')'); 47*8462SApril.Chin@Sun.COM sfputr(sp,sh_mactry(shp,stkfreeze(stkp,1)),-1); 48*8462SApril.Chin@Sun.COM stkset(stkp,savptr,savtop); 494887Schin } 504887Schin return(1); 514887Schin } 524887Schin 534887Schin int b_getopts(int argc,char *argv[],void *extra) 544887Schin { 554887Schin register char *options=error_info.context->id; 564887Schin register Namval_t *np; 574887Schin register int flag, mode, r=0; 58*8462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp; 594887Schin char value[2], key[2]; 60*8462SApril.Chin@Sun.COM int jmpval,extended; 614887Schin struct checkpt buff, *pp; 62*8462SApril.Chin@Sun.COM struct { 63*8462SApril.Chin@Sun.COM Optdisc_t hdr; 64*8462SApril.Chin@Sun.COM Shell_t *sh; 65*8462SApril.Chin@Sun.COM } disc; 664887Schin memset(&disc, 0, sizeof(disc)); 67*8462SApril.Chin@Sun.COM disc.hdr.version = OPT_VERSION; 68*8462SApril.Chin@Sun.COM disc.hdr.infof = infof; 69*8462SApril.Chin@Sun.COM disc.sh = shp; 704887Schin value[1] = 0; 714887Schin key[1] = 0; 724887Schin while((flag = optget(argv,sh_optgetopts))) switch(flag) 734887Schin { 744887Schin case 'a': 754887Schin options = opt_info.arg; 764887Schin break; 774887Schin case ':': 784887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 794887Schin break; 804887Schin case '?': 814887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 824887Schin break; 834887Schin } 844887Schin argv += opt_info.index; 854887Schin argc -= opt_info.index; 864887Schin if(error_info.errors || argc<2) 874887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0)); 884887Schin error_info.context->flags |= ERROR_SILENT; 894887Schin error_info.id = options; 904887Schin options = argv[0]; 914887Schin np = nv_open(argv[1],shp->var_tree,NV_NOASSIGN|NV_VARNAME); 924887Schin if(argc>2) 934887Schin { 944887Schin argv +=1; 954887Schin argc -=1; 964887Schin } 974887Schin else 984887Schin { 994887Schin argv = shp->st.dolv; 1004887Schin argc = shp->st.dolc; 1014887Schin } 1024887Schin opt_info.index = shp->st.optindex; 1034887Schin opt_info.offset = shp->st.optchar; 1044887Schin if(mode= (*options==':')) 1054887Schin options++; 106*8462SApril.Chin@Sun.COM extended = *options=='\n' && *(options+1)=='[' || *options=='[' && *(options+1)=='-'; 1074887Schin sh_pushcontext(&buff,1); 1084887Schin jmpval = sigsetjmp(buff.buff,0); 1094887Schin if(jmpval) 1104887Schin { 1114887Schin sh_popcontext(&buff); 1124887Schin pp = (struct checkpt*)shp->jmplist; 1134887Schin pp->mode = SH_JMPERREXIT; 1144887Schin sh_exit(2); 1154887Schin } 116*8462SApril.Chin@Sun.COM opt_info.disc = &disc.hdr; 1174887Schin switch(opt_info.index>=0 && opt_info.index<=argc?(opt_info.num= LONG_MIN,flag=optget(argv,options)):0) 1184887Schin { 1194887Schin case '?': 1204887Schin if(mode==0) 1214887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 1224887Schin opt_info.option[1] = '?'; 1234887Schin /* FALL THRU */ 1244887Schin case ':': 1254887Schin key[0] = opt_info.option[1]; 1264887Schin if(strmatch(opt_info.arg,"*unknown*")) 1274887Schin flag = '?'; 1284887Schin if(mode) 1294887Schin opt_info.arg = key; 1304887Schin else 1314887Schin { 1324887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 1334887Schin opt_info.arg = 0; 1344887Schin flag = '?'; 1354887Schin } 1364887Schin *(options = value) = flag; 1374887Schin shp->st.opterror = 1; 1384887Schin if (opt_info.offset != 0 && !argv[opt_info.index][opt_info.offset]) 1394887Schin { 1404887Schin opt_info.offset = 0; 1414887Schin opt_info.index++; 1424887Schin } 1434887Schin break; 1444887Schin case 0: 1454887Schin if(shp->st.opterror) 1464887Schin { 1474887Schin char *com[2]; 1484887Schin com[0] = "-?"; 1494887Schin com[1] = 0; 1504887Schin flag = opt_info.index; 1514887Schin opt_info.index = 0; 1524887Schin optget(com,options); 1534887Schin opt_info.index = flag; 1544887Schin if(!mode && strchr(options,' ')) 1554887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0)); 1564887Schin } 1574887Schin opt_info.arg = 0; 1584887Schin options = value; 1594887Schin *options = '?'; 1604887Schin r=1; 1614887Schin opt_info.offset = 0; 1624887Schin break; 1634887Schin default: 1644887Schin options = opt_info.option + (*opt_info.option!='+'); 1654887Schin } 1664887Schin error_info.context->flags &= ~ERROR_SILENT; 1674887Schin shp->st.optindex = opt_info.index; 1684887Schin shp->st.optchar = opt_info.offset; 1694887Schin nv_putval(np, options, 0); 1704887Schin nv_close(np); 1714887Schin np = nv_open(nv_name(OPTARGNOD),shp->var_tree,NV_NOSCOPE); 1724887Schin if(opt_info.num == LONG_MIN) 1734887Schin nv_putval(np, opt_info.arg, NV_RDONLY); 174*8462SApril.Chin@Sun.COM 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] != '+') 1754887Schin { 1764887Schin key[0] = (char)opt_info.num; 1774887Schin key[1] = 0; 1784887Schin nv_putval(np, key, NV_RDONLY); 1794887Schin } 180*8462SApril.Chin@Sun.COM else if(extended) 1814887Schin { 1824887Schin Sfdouble_t d; 1834887Schin d = opt_info.number; 1844887Schin nv_putval(np, (char*)&d, NV_LDOUBLE|NV_RDONLY); 1854887Schin } 186*8462SApril.Chin@Sun.COM else 187*8462SApril.Chin@Sun.COM nv_putval(np, opt_info.arg, NV_RDONLY); 1884887Schin nv_close(np); 1894887Schin sh_popcontext(&buff); 1904887Schin opt_info.disc = 0; 1914887Schin return(r); 1924887Schin } 1934887Schin 194