diff options
Diffstat (limited to 'usr/src/lib/libshell/common/sh/macro.c')
-rw-r--r-- | usr/src/lib/libshell/common/sh/macro.c | 94 |
1 files changed, 71 insertions, 23 deletions
diff --git a/usr/src/lib/libshell/common/sh/macro.c b/usr/src/lib/libshell/common/sh/macro.c index cb938764d6..684e2d0464 100644 --- a/usr/src/lib/libshell/common/sh/macro.c +++ b/usr/src/lib/libshell/common/sh/macro.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1982-2008 AT&T Intellectual Property * +* Copyright (c) 1982-2009 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -38,6 +38,7 @@ #include "variables.h" #include "shlex.h" #include "io.h" +#include "jobs.h" #include "shnodes.h" #include "path.h" #include "national.h" @@ -529,8 +530,13 @@ static void copyto(register Mac_t *mp,int endch, int newquote) { /* preserve \digit for pattern matching */ /* also \alpha for extended patterns */ - if(!mp->lit && !mp->quote && (n==S_DIG || ((paren+ere) && sh_lexstates[ST_DOL][*(unsigned char*)cp]==S_ALP))) - break; + if(!mp->lit && !mp->quote) + { + if((n==S_DIG || ((paren+ere) && sh_lexstates[ST_DOL][*(unsigned char*)cp]==S_ALP))) + break; + if(ere && mp->pattern==1 && strchr(".[()*+?{|^$&!",*cp)) + break; + } /* followed by file expansion */ if(!mp->lit && (n==S_ESC || (!mp->quote && (n==S_PAT||n==S_ENDCH||n==S_SLASH||n==S_BRACT||*cp=='-')))) @@ -647,8 +653,14 @@ static void copyto(register Mac_t *mp,int endch, int newquote) int offset=0,oldpat = mp->pattern; int oldarith = mp->arith, oldsub=mp->subcopy; sfwrite(stkp,first,++c); - if((mp->assign&1) && first[c-2]=='.') - offset = stktell(stkp); + if(mp->assign&1) + { + if(first[c-2]=='.') + offset = stktell(stkp); + if(isastchar(*cp) && cp[1]==']') + errormsg(SH_DICT,ERROR_exit(1), +e_badsubscript,*cp); + } first = fcseek(c); mp->pattern = 4; mp->arith = 0; @@ -678,7 +690,7 @@ static void copyto(register Mac_t *mp,int endch, int newquote) { char *p = cp; while((c=mbchar(p)) && c!=RPAREN && c!='E'); - ere = c=='E'; + ere = (c=='E'||c=='A'); } } else if(n==RPAREN) @@ -892,7 +904,7 @@ static char *getdolarg(Shell_t *shp, int n, int *size) static char *prefix(Shell_t *shp, char *id) { Namval_t *np; - register char *cp = strchr(id,'.'); + register char *sub=0, *cp = strchr(id,'.'); if(cp) { *cp = 0; @@ -905,11 +917,23 @@ static char *prefix(Shell_t *shp, char *id) int n; char *sp; shp->argaddr = 0; - while(nv_isref(np)) + while(nv_isref(np) && np->nvalue.cp) + { + sub = nv_refsub(np); np = nv_refnode(np); - id = (char*)malloc(strlen(cp)+1+(n=strlen(sp=nv_name(np)))+1); - strcpy(&id[n],cp); + if(sub) + nv_putsub(np,sub,0L); + } + id = (char*)malloc(strlen(cp)+1+(n=strlen(sp=nv_name(np)))+ (sub?strlen(sub)+3:1)); memcpy(id,sp,n); + if(sub) + { + id[n++] = '['; + strcpy(&id[n],sub); + n+= strlen(sub)+1; + id[n-1] = ']'; + } + strcpy(&id[n],cp); return(id); } } @@ -961,7 +985,7 @@ int sh_macfun(Shell_t *shp, const char *name, int offset) tp = (Shnode_t*)&node; tp->com.comarg = (struct argnod*)dp; tp->com.comline = shp->inlineno; - dp->dolnum = 2; + dp->dolnum = 1; dp->dolval[0] = strdup(name); stkseek(shp->stk,offset); comsubst((Mac_t*)shp->mac_context,tp,2); @@ -1009,14 +1033,14 @@ static int varsub(Mac_t *mp) Namarr_t *ap=0; int dolmax=0, vsize= -1, offset= -1, nulflg, replen=0, bysub=0; char idbuff[3], *id = idbuff, *pattern=0, *repstr, *arrmax=0; - int addsub=0,oldpat=mp->pattern,idnum=0,flag=0,d; + int var=1,addsub=0,oldpat=mp->pattern,idnum=0,flag=0,d; Stk_t *stkp = mp->shp->stk; retry1: mp->zeros = 0; idbuff[0] = 0; idbuff[1] = 0; c = fcget(); - switch(c>0x7f?S_ALP:sh_lexstates[ST_DOL][c]) + switch(isascii(c)?sh_lexstates[ST_DOL][c]:S_ALP) { case S_RBRA: if(type<M_SIZE) @@ -1053,6 +1077,7 @@ retry1: } /* FALL THRU */ case S_SPC2: + var = 0; *id = c; v = special(mp->shp,c); if(isastchar(c)) @@ -1081,6 +1106,7 @@ retry1: comsubst(mp,(Shnode_t*)0,1); return(1); case S_DIG: + var = 0; c -= '0'; mp->shp->argaddr = 0; if(type) @@ -1117,7 +1143,7 @@ retry1: np = 0; do sfputc(stkp,c); - while(((c=fcget()),(c>0x7f||isaname(c)))||type && c=='.'); + while(((c=fcget()),(!isascii(c)||isaname(c)))||type && c=='.'); while(c==LBRACT && (type||mp->arrayok)) { mp->shp->argaddr=0; @@ -1204,10 +1230,14 @@ retry1: } else #endif /* SHOPT_FILESCAN */ - if(mp->shp->argaddr) - flag &= ~NV_NOADD; - np = nv_open(id,mp->shp->var_tree,flag|NV_NOFAIL); - if((!np || nv_isnull(np)) && type==M_BRACE && c==RBRACE && !(flag&NV_ARRAY)) + { + if(mp->shp->argaddr) + flag &= ~NV_NOADD; + np = nv_open(id,mp->shp->var_tree,flag|NV_NOFAIL); + } + if(isastchar(mode)) + var = 0; + if((!np || nv_isnull(np)) && type==M_BRACE && c==RBRACE && !(flag&NV_ARRAY) && strchr(id,'.')) { if(sh_macfun(mp->shp,id,offset)) { @@ -1215,6 +1245,13 @@ retry1: return(1); } } + if(np && (flag&NV_NOADD) && nv_isnull(np)) + { + if(nv_isattr(np,NV_NOFREE)) + nv_offattr(np,NV_NOFREE); + else + np = 0; + } ap = np?nv_arrayptr(np):0; if(type) { @@ -1299,7 +1336,15 @@ retry1: v = nv_getvtree(np,(Namfun_t*)0); else { - v = nv_getval(np); + if(type && fcpeek(0)=='+') + { + if(ap) + v = nv_arrayisset(np,ap)?(char*)"x":0; + else + v = nv_isnull(np)?0:(char*)"x"; + } + else + v = nv_getval(np); /* special case --- ignore leading zeros */ if( (mp->arith||mp->let) && (np->nvfun || nv_isattr(np,(NV_LJUST|NV_RJUST|NV_ZFILL))) && (offset==0 || !isalnum(c))) mp->zeros = 1; @@ -1345,6 +1390,7 @@ retry1: mac_error(np); if(type==M_NAMESCAN || type==M_NAMECOUNT) { + mp->shp->last_root = mp->shp->var_tree; id = prefix(mp->shp,id); stkseek(stkp,offset); if(type==M_NAMECOUNT) @@ -1432,6 +1478,7 @@ retry1: int quoted = mp->quoted; int arith = mp->arith; int zeros = mp->zeros; + int assign = mp->assign; if(newops) { type = fcget(); @@ -1446,6 +1493,7 @@ retry1: mp->pattern = 1+(c=='/'); mp->split = 0; mp->quoted = 0; + mp->assign &= ~1; mp->arith = mp->zeros = 0; newquote = 0; } @@ -1459,6 +1507,7 @@ retry1: mp->quoted = quoted; mp->arith = arith; mp->zeros = zeros; + mp->assign = assign; /* add null byte */ sfputc(stkp,0); stkseek(stkp,stktell(stkp)-1); @@ -1803,7 +1852,7 @@ retry2: mac_error(np); } } - else if(sh_isoption(SH_NOUNSET) && (!np || nv_isnull(np) || (nv_isarray(np) && !np->nvalue.cp))) + else if(var && sh_isoption(SH_NOUNSET) && (!np || nv_isnull(np) || (nv_isarray(np) && !np->nvalue.cp))) { if(np) { @@ -2467,7 +2516,6 @@ static char *sh_tilde(Shell_t *shp,register const char *string) */ static char *special(Shell_t *shp,register int c) { - register Namval_t *np; if(c!='$') shp->argaddr = 0; switch(c) @@ -2497,10 +2545,10 @@ static char *special(Shell_t *shp,register int c) case '?': return(ltos(shp->savexit)); case 0: - if(sh_isstate(SH_PROFILE) || !error_info.id || ((np=nv_search(error_info.id,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC))) + if(sh_isstate(SH_PROFILE) || shp->fn_depth==0 || !shp->st.cmdname) return(shp->shname); else - return(error_info.id); + return(shp->st.cmdname); } return(NIL(char*)); } |