lex.c revision 7c2fbfb345896881c631598ee3852ce9ce33fb07
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* Copyright (c) 1982-2008 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 * KornShell lexical analyzer
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Written by David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* KSHELL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define STACK_ARRAY 3 /* size of depth match stack growth */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_iswblank < 0 /* set in lexstates.h to enable this code */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This structure allows for arbitrary depth nesting of (...), {...}, [...]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define pushlevel(lp,c,s) ((lp->lexd.level>=lp->lexd.lex_max?stack_grow(lp):1) &&\
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ((lp->lexd.lex_match[lp->lexd.level++]=lp->lexd.lastc),\
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define setchar(lp,c) (lp->lexd.lastc = ((lp->lexd.lastc&~0xff)|(c)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define poplevel(lp) (lp->lexd.lastc=lp->lexd.lex_match[--lp->lexd.level])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int alias_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL };
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin off_t off = (fcseek(0)-(type+1))-(lp->lexd.first?lp->lexd.first:fcfirst());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long r;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r=kiaentity(lp,lp->lexd.first+lp->lexd.kiaoff+type,off-lp->lexd.kiaoff,'v',-1,-1,lp->current,'v',0,"");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* variable starts on stak, copy remainder */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* variable in data buffer */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r=kiaentity(lp,begin,n,'v',-1,-1,lp->current,'v',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lp->kiatmp,"p;%..64d;v;%..64d;%d;%d;r;\n",lp->current,r,shp->inlineno,shp->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine gets called when reading across a buffer boundary
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If lexd.nocopy is off, then current token is saved on the stack
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void lex_advance(Sfio_t *iop, const char *buff, register int size, void *context)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* write to history file and to stderr if necessary */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fill up another input buffer
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * preserves lexical state
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * mode=1 for reinitialization
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->lex.intest = lp->lex.incase = lp->lex.skipword = lp->lexd.warn = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh_isoption(SH_DICTIONARY) && sh_isoption(SH_NOEXEC))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->lexd.noarg = lp->lexd.level= lp->lexd.dolparen = lp->lexd.balance = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->lexd.nocopy = lp->lexd.docword = lp->lexd.nest = lp->lexd.paren = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int flag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"line %d: %o:%s%s%s%s %s\n",shp->inlineno,tok,quoted,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Get the next word and put it on the top of the stak
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * A pointer to the current word is stored in lp->arg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Returns the token type
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const char *state;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int inlevel=lp->lexd.level, assignment=0, ingrave=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_MULTIBYTE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c=='<')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c>0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over characters in the current state */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for zero byte in file */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n==0 && fcfile())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* end-of-file */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip one or more comment line(s) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(c=='#');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for here-document */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over new-lines */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* implicit RPAREN for =~ test operator */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* return operator token */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='<')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n==LPAREN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c=='&')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n=='&')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n==LPAREN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n=='|')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->lex.incase = (c==BREAKCASESYM || c==FALLTHRUSYM);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((n=fcpeek(0))!=RPAREN && n!=LPAREN && lp->lexd.warn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexspace,shp->inlineno,c,n);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(c==LPAREN && lp->comp_assign && !lp->lex.intest && !lp->lex.incase)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for \<new-line> */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n=='\r')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_CRNL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n=='\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* synchronize */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* remove \new-line */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexfuture,shp->inlineno,n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* STR_MAXIMAL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip new-line joining */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(oldmode(lp)==ST_NONE && !lp->lexd.noarg) /* in ((...)) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((c=fcpeek(0))==LPAREN || c==RPAREN || c=='$' || c==LBRACE || c==RBRACE || c=='[' || c==']')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(oldmode(lp)==ST_QUOTE) /* $' within "" or `` */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for multi-line single-quoted string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* \ inside '' */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n=='\n')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lexd.warn && (mode!=ST_QUOTE || endchar(lp)!='`'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete1,shp->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(oldmode(lp)==ST_NONE && lp->lexd.arith) /* in ((...)) */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't check syntax inside `` */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->lexd.kiaoff = stktell(stkp)+fcseek(0)-fcfirst();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* end $identifier */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lexd.warn && c==LBRACT && !lp->lex.intest && !lp->lexd.arith && oldmode(lp)!= ST_NESTED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexusebrace,shp->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure next character is alpha */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n=='=')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n==RBRACE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_TYPEDEF */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='*' || (n=sh_lexstates[ST_BRACE][c])!=S_MOD1 && n!=S_MOD2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether inside `...` */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(oldmode(lp)==ST_QUOTE || oldmode(lp)==ST_NONE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* allow ' inside "${...}" */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!c || (fcgetc(n)>0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c!='%')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexquote,shp->inlineno,'%');
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((n=sh_lexstates[ST_BEGIN][c])==0 || n==S_OP || n==S_NLTOK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n!='$')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lexd.warn && c!='/' && sh_lexstates[ST_NORM][c]!=S_BREAK && (c!='"' || mode==ST_QUOTE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lexd.level==inlevel+1 && lp->lex.incase>=TEST_RE && !lp->lex.intest)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexescape,shp->inlineno,c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* quotes in subscript need expansion */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for ((...)) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* backward compatibility */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for possible subscript */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (mode==ST_NAME && (lp->assignok||lp->lexd.level)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(mode==ST_BEGIN && (lp->lex.reservok||lp->comsub))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin isfirst = (lp->lexd.first&&fcseek(0)==lp->lexd.first+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for {} */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for reserved word { or } */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lex.reservok && state[n]==S_BREAK && isfirst)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* add balancing character if necessary */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for numbered redirection */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(n=='~')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(assignment || (lp->lex.intest&&!lp->lex.incase) || mode==ST_NONE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* eliminate trailing )) */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(c==0 || (c&(ARG_MAC|ARG_EXP)) || (lp->lexd.warn && !lp->lexd.docword))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete2,shp->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete3,shp->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c==TEST_REP)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lex.reservok /* && !lp->lex.incase*/ && n<=2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for {, }, ! */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(!lp->lex.incase && c==LBRACT && state[1]==LBRACT)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(n>1 && lp->lex.reservok==1 && mode==ST_NAME &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c==ESACSYM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c==TIMESYM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* yech - POSIX requires time -p */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n=='-')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(wordflags&ARG_QUOTED) && (lp->lex.reservok||lp->aliasok))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for aliases */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!lp->lex.incase && !assignment && fcpeek(0)!=LPAREN &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin && (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* KSHELL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * read to end of command substitution
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* look for case and esac */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip leading white space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c && (c!='#' || n==0))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* fall through*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * here-doc nested in $(...)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * allocate ionode with delimiter filled in without disturbing stak
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int n,offset;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * skip to <close> character
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <copy> is non,zero, then the characters are copied to the stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * <state> is the initial lexical state
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinvoid sh_lexskip(Lex_t *lp,int close, register int copy, int state)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char *cp = (const char*)buff, *next=cp, *ep = cp + n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int m=0,k;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(m>0?m:-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(m>0?m:-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(m+k);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_CRNL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * read in here-document from script
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * quoted here documents, and here-documents without special chars are
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * noted with the IOQUOTE flag
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * returns 1 for complete here-doc, 0 for EOF
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int here_copy(Lex_t *lp,register struct ionod *iop)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const char *state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c,n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for and strip quoted characters in delimiter string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over leading tabs in document */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c==' ')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over regular characters */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_CRNL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* write out line */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over tabs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c==' ')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else while(c=='\t')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_CRNL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The match for delimiter failed.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * nsave>0 only when a buffer boundary
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * was crossed while checking the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * delimiter
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='\r')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_CRNL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* new-line joining */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!lp->lexd.dolparen && (n=(fcseek(0)-bufp)-n)>0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * generates string for given token
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *fmttoken(Lex_t *lp, register int sym, char *tok)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->lex.intest && lp->arg && *lp->arg->argval)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * print a bad syntax message
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *tokstr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd])))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* clear out any pending input */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(fcget()>0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic char *stack_shift(Stk_t *stkp, register char *sp,char *dp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *ep;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Assumes that current word is unfrozen on top of the stak
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If <mode> is zero, gets rid of quoting and consider argument as string
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and returns pointer to frozen arg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If mode==1, just replace $"..." strings with international strings
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The result is left on the stak
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If mode==2, the each $"" string is printed on standard output
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int inquote=0, inlit=0; /* set within quoted strings */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * None of the state tables contain
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * entries for multibyte characters,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * however, they should be treated
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the same as any other alph
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * character. Therefore, we'll use
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the state of the 'a' character.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(n == 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_MULTIBYTE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_CRNL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_DOS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n=='\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(bracket++==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * None of the state tables contain
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * entries for multibyte characters,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * however, they should be treated
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the same as any other alph
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * character. Therefore, we'll use
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the state of the 'a' character.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(n == 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_MULTIBYTE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This code gets called whenever an end of string is found with alias
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This code gets called whenever an end of string is found with alias
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if last character is a blank, then next work can be alias */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void setupalias(Lex_t *lp, const char *string,Namval_t *np)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct alias *ap = (struct alias*)malloc(sizeof(struct alias));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long r;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin r=kiaentity(lp,nv_name(np),-1,'p',0,0,lp->current,'a',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(lp->kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",lp->current,r,lp->sh->inlineno,lp->sh->inlineno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * grow storage stack for nested constructs by STACK_ARRAY
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->lexd.lex_match = (int*)realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY);