1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1982-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* David Korn <dgk@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#pragma prototyped
1N/A/*
1N/A * getopts optstring name [arg...]
1N/A *
1N/A * David Korn
1N/A * AT&T Labs
1N/A * research!dgk
1N/A *
1N/A */
1N/A
1N/A#include "defs.h"
1N/A#include "variables.h"
1N/A#include <error.h>
1N/A#include <nval.h>
1N/A#include "builtins.h"
1N/A
1N/Astatic int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
1N/A{
1N/A Shell_t *shp = *(Shell_t**)(dp+1);
1N/A Stk_t *stkp = shp->stk;
1N/A if(nv_search(s,shp->fun_tree,0))
1N/A {
1N/A int savtop = stktell(stkp);
1N/A char *savptr = stkfreeze(stkp,0);
1N/A sfputc(stkp,'$');
1N/A sfputc(stkp,'(');
1N/A sfputr(stkp,s,')');
1N/A sfputr(sp,sh_mactry(shp,stkfreeze(stkp,1)),-1);
1N/A stkset(stkp,savptr,savtop);
1N/A }
1N/A return(1);
1N/A}
1N/A
1N/Aint b_getopts(int argc,char *argv[],void *extra)
1N/A{
1N/A register char *options=error_info.context->id;
1N/A register Namval_t *np;
1N/A register int flag, mode;
1N/A register Shell_t *shp = ((Shbltin_t*)extra)->shp;
1N/A char value[2], key[2];
1N/A int jmpval,extended;
1N/A volatile int r= -1;
1N/A struct checkpt buff, *pp;
1N/A struct {
1N/A Optdisc_t hdr;
1N/A Shell_t *sh;
1N/A } disc;
1N/A memset(&disc, 0, sizeof(disc));
1N/A disc.hdr.version = OPT_VERSION;
1N/A disc.hdr.infof = infof;
1N/A disc.sh = shp;
1N/A value[1] = 0;
1N/A key[1] = 0;
1N/A while((flag = optget(argv,sh_optgetopts))) switch(flag)
1N/A {
1N/A case 'a':
1N/A options = opt_info.arg;
1N/A break;
1N/A case ':':
1N/A errormsg(SH_DICT,2, "%s", opt_info.arg);
1N/A break;
1N/A case '?':
1N/A errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
1N/A break;
1N/A }
1N/A argv += opt_info.index;
1N/A argc -= opt_info.index;
1N/A if(error_info.errors || argc<2)
1N/A errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
1N/A error_info.context->flags |= ERROR_SILENT;
1N/A error_info.id = options;
1N/A options = argv[0];
1N/A np = nv_open(argv[1],shp->var_tree,NV_NOASSIGN|NV_VARNAME);
1N/A if(argc>2)
1N/A {
1N/A argv +=1;
1N/A argc -=1;
1N/A }
1N/A else
1N/A {
1N/A argv = shp->st.dolv;
1N/A argc = shp->st.dolc;
1N/A }
1N/A opt_info.index = shp->st.optindex;
1N/A opt_info.offset = shp->st.optchar;
1N/A if(mode= (*options==':'))
1N/A options++;
1N/A extended = *options=='\n' && *(options+1)=='[' || *options=='[' && *(options+1)=='-';
1N/A sh_pushcontext(shp,&buff,1);
1N/A jmpval = sigsetjmp(buff.buff,0);
1N/A if(jmpval)
1N/A {
1N/A sh_popcontext(shp,&buff);
1N/A shp->st.opterror = 1;
1N/A if(r==0)
1N/A return(2);
1N/A pp = (struct checkpt*)shp->jmplist;
1N/A pp->mode = SH_JMPERREXIT;
1N/A sh_exit(2);
1N/A }
1N/A opt_info.disc = &disc.hdr;
1N/A switch(opt_info.index>=0 && opt_info.index<=argc?(opt_info.num= LONG_MIN,flag=optget(argv,options)):0)
1N/A {
1N/A case '?':
1N/A if(mode==0)
1N/A errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
1N/A opt_info.option[1] = '?';
1N/A /* FALL THRU */
1N/A case ':':
1N/A key[0] = opt_info.option[1];
1N/A if(strmatch(opt_info.arg,"*unknown*"))
1N/A flag = '?';
1N/A if(mode)
1N/A opt_info.arg = key;
1N/A else
1N/A {
1N/A errormsg(SH_DICT,2, "%s", opt_info.arg);
1N/A opt_info.arg = 0;
1N/A flag = '?';
1N/A }
1N/A *(options = value) = flag;
1N/A shp->st.opterror = 1;
1N/A if (opt_info.offset != 0 && !argv[opt_info.index][opt_info.offset])
1N/A {
1N/A opt_info.offset = 0;
1N/A opt_info.index++;
1N/A }
1N/A break;
1N/A case 0:
1N/A if(shp->st.opterror)
1N/A {
1N/A char *com[2];
1N/A com[0] = "-?";
1N/A com[1] = 0;
1N/A flag = opt_info.index;
1N/A opt_info.index = 0;
1N/A optget(com,options);
1N/A opt_info.index = flag;
1N/A if(!mode && strchr(options,' '))
1N/A errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
1N/A }
1N/A opt_info.arg = 0;
1N/A options = value;
1N/A *options = '?';
1N/A r=1;
1N/A opt_info.offset = 0;
1N/A break;
1N/A default:
1N/A options = opt_info.option + (*opt_info.option!='+');
1N/A }
1N/A if(r<0)
1N/A r = 0;
1N/A error_info.context->flags &= ~ERROR_SILENT;
1N/A shp->st.optindex = opt_info.index;
1N/A shp->st.optchar = opt_info.offset;
1N/A nv_putval(np, options, 0);
1N/A nv_close(np);
1N/A np = nv_open(nv_name(OPTARGNOD),shp->var_tree,NV_NOSCOPE);
1N/A if(opt_info.num == LONG_MIN)
1N/A nv_putval(np, opt_info.arg, NV_RDONLY);
1N/A 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] != '+')
1N/A {
1N/A key[0] = (char)opt_info.num;
1N/A key[1] = 0;
1N/A nv_putval(np, key, NV_RDONLY);
1N/A }
1N/A else if(extended)
1N/A {
1N/A Sfdouble_t d;
1N/A d = opt_info.number;
1N/A nv_putval(np, (char*)&d, NV_LDOUBLE|NV_RDONLY);
1N/A }
1N/A else
1N/A nv_putval(np, opt_info.arg, NV_RDONLY);
1N/A nv_close(np);
1N/A sh_popcontext(shp,&buff);
1N/A opt_info.disc = 0;
1N/A return(r);
1N/A}
1N/A