parse.c revision 34f9b3eef6fdadbda0a846aa4d68691ac40eace5
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz* Copyright (c) 1982-2009 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * UNIX shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * S. R. Bourne
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Rewritten by David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is the parser for a shell language
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define HERE_MEM 1024 /* size of here-docs kept in memory */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* These routines are local to this module */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *makeparent(Lex_t*, int, Shnode_t*);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *makelist(Lex_t*, int, Shnode_t*, Shnode_t*);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic struct ionod *inout(Lex_t*,struct ionod*, int);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *simple(Lex_t*,int, struct ionod*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* NIL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct stdata
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define getnode(type) ((Shnode_t*)stakalloc(sizeof(struct type)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * write out entities for each item in the list
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * type=='V' for variable assignment lists
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Otherwise type is determined by the command */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic unsigned long writedefs(Lex_t *lexp,struct argnod *arglist, int line, int type, struct argnod *cmd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n,eline;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long r=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while((n= *++cp))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin parent=kiaentity(lexp,sh_argstr(cmd),-1,'p',-1,-1,lexp->unknown,'b',0,"");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((cp=strchr(argp->argval,'='))||(cp=strchr(argp->argval,'?')))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r=kiaentity(lexp,argp->argval,n,type,line,eline,parent,justify,width,atbuff);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiatmp,"p;%..64d;v;%..64d;%d;%d;s;\n",lexp->current,r,line,eline);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void typeset_order(const char *str,int line)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int c,n=0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin static unsigned char *table;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(cp=(unsigned char*)"bflmnprstuxACHS";c = *cp; cp++)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(cp=(unsigned char*)"aiEFLRXhTZ";c = *cp; cp++)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(cp=(unsigned char*)str; c= *cp++; n=table[c])
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),e_lextypeset,line,str);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * add type definitions when compiling with -n
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(ap->argflag&ARG_RAW) || memcmp(ap->argval,"--",2))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Make a parent node for fork() or io-redirection
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *makeparent(Lex_t *lp, int flag, Shnode_t *child)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *getanode(Lex_t *lp, struct argnod *ap)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Make a node corresponding to a command list
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!l || !r)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * entry to shell parser
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Flag can be the union of SH_EOF|SH_NL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(shp->binscript && (sffileno(iop)==shp->infd || (flag&SH_FUNEVAL)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(NIL(void*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if( cp[0]==CNTL('k') && cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sffileno(iop)==shp->infd || (flag&SH_FUNEVAL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* unstack any completed alias expansions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((void*)t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine parses up the matching right parenthesis and returns
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the parse tree
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t=0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->sh->inlineno = error_info.line+lp->sh->st.firstline;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* ((...)) arithmetic expression */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This code handles the case where string has been converted
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * to a file by an alias setup
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * remove temporary files and stacks
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * increase reference count for each stack in function list when flag>0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * decrease reference count for each stack in function list when flag<=0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * stack is freed when reference count is zero
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * list & [ cmd ]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * list [ ; cmd ]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* (...)& -> {...;} & */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * list && term
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * list || term
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * unfortunately, these are equal precedence
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *list(Lex_t *lexp, register int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int token;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * item | term
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *term(Lex_t *lexp,register int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int token;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check to see if pipeline is to be timed */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * case statement
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic struct regnod* syncase(Lex_t *lexp,register int esym)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct regnod *r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine creates the parse tree for the arithmetic for
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * When called, shlex.arg contains the string inside ((...))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * When the first argument is missing, a while node is returned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Otherise a list containing an arithmetic command and a while
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * is returned.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *arithfor(Lex_t *lexp,register Shnode_t *tf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int offset;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save current input */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* split ((...)) into three expressions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(n=0; ; n++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* copy up to ; onto the stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* remove trailing white space */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for empty initialization expression */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for empty condition and treat as while((1)) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check whether the increment is present */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n==';')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int flag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->funct.functloc = sfseek(shp->hist_ptr->histfp,(off_t)0,SEEK_CUR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* copy source to temporary file */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,"");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->funct.functargs = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* create a new stak frame to compile the command */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * store the pathname of function definition file on stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * in name field of fake for node
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* copy current word token to current stak frame */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore the old stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,"");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Compound assignment
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int tdef)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* shift right */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(n > 0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(n && n!=FUNCTSYM)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(n!=FUNCTSYM && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)|| np==SYSDOT)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(n>0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|array,NIL(struct ionod*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((n!=FUNCTSYM) && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)||np==SYSDOT)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for sys5 style function */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * ( cmd ) [ < in ] [ > out ]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * word word* [ < in ] [ > out ]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if ... then ... else ... fi
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * for ... while ... do ... done
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * case ... in ... esac
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * begin ... end
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* [[ ... ]] test expression */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* ((...)) arithmetic expression */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* case statement */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if statement */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI):
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* for and select statement */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* arithmetic for */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* some Linux scripts assume this */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n'));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* 'for i;do cmd' is valid syntax */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* This is the code for parsing function definitions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_NAMESPACE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* while and until */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* command group with {...} */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz t->par.partre=sh_cmd(lexp,RPAREN,SH_NL|SH_SEMI);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* simple command */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(t->com.comarg && lexp->intypeset && (lexp->sh->shcomp || sh_isoption(SH_NOEXEC) || sh.dot_depth))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzstatic struct argnod *process_sub(Lex_t *lexp,int tok)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz argp = (struct argnod*)stkalloc(lexp->sh->stk,sizeof(struct argnod));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is for a simple command, for list, or compound assignment
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct comnod *t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int tok;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set command line number for error messages */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for assignment argument */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* alias substitutions allowed */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for builtin command */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_DEVFD */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(t->comnamp==SYSTYPESET && t->comarg->argnxt.ap && strcmp(t->comarg->argnxt.ap->argval,"-T")==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* SVR2 style function */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long r=0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin writedefs(lexp,argp,line,'u',NIL(struct argnod*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* convert break/continue labels to numbers */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') &&
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* expand argument list if possible */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(t->comarg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((Shnode_t*)t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * skip past newlines but issue prompt if interactive
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int token;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * check for and process and i/o redirections
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if flag>0 then an alias can be in the next word
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if flag<0 only one redirection will be processed
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int iof = lexp->digits, token=lexp->token;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int errout=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n>0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if(((token==IPROCSYM && !(iof&IOPUT)) || (token==OPROCSYM && (iof&IOPUT))) && !(iof&(IOLSEEK|IOREWRITE|IOMOV|IODOC)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* allow alias substitutions and parameter assignments */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;%c;%d\n",lexp->current,r,n,n,(iof&IOPUT)?((iof&IOAPP)?'a':'w'):((iof&IODOC)?'h':'r'),iof&IOUFD);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* redirect standard output to standard error */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert argument chain to argument list when no special arguments
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char **cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int special=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* special hack for test -t compatibility */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char *message;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* leave space for an extra argument at the front */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert =~ into == ~(E)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void ere_match(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int line = lexp->sh->inlineno- (lexp->token==NL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long r;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT),
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* binary test operators */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT),
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int line = lexp->sh->inlineno- (lexp->token==NL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long r;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long r;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return an entity checksum
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The entity is created if it doesn't exist
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinunsigned long kiaentity(Lex_t *lexp,const char *name,int len,int type,int first,int last,unsigned long parent, int pkind, int width, const char *attr)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiafile,"%..64d;%c;%.*s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,len,name,first,last,parent,lexp->fscript,pkind,width,attr);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiafile,"%..64d;%c;%s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,name,first,last,parent,lexp->fscript,pkind,width,attr);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),"");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nRELATIONSHIP;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin),(Sflong_t)off1,(size_t)(off2-off1));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */