/* * change '['identifier']' to identifier * character before <str> must be a '[' * returns pointer to last character */ char *sh_checkid(char *str, char *last) { register unsigned char *cp = (unsigned char*)str; register unsigned char *v = cp; register int c; if(c= *cp++,isaletter(c)) while(c= *cp++,isaname(c)); if(c==']' && (!last || ((char*)cp==last))) { /* eliminate [ and ] */ while(v < cp) { v[-1] = *v; v++; } if(last) last -=2; else { while(*v) { v[-2] = *v; v++; } v[-2] = 0; last = (char*)v; } } return(last); }
/* * returns pointer to beginning of expansion and sets type of expansion */ static char *find_begin(char outbuff[], char *last, int endchar, int *type) { register char *cp=outbuff, *bp, *xp; register int c,inquote = 0, inassign=0; int mode=*type; bp = outbuff; *type = 0; while(cp < last) { xp = cp; switch(c= mbchar(cp)) { case '\'': case '"': if(!inquote) { inquote = c; bp = xp; break; } if(inquote==c) inquote = 0; break; case '\\': if(inquote != '\'') mbchar(cp); break; case '$': if(inquote == '\'') break; c = *(unsigned char*)cp; if(mode!='*' && (isaletter(c) || c=='{')) { int dot = '.'; if(c=='{') { xp = cp; mbchar(cp); c = *(unsigned char*)cp; if(c!='.' && !isaletter(c)) break; } else dot = 'a'; while(cp < last) { if((c= mbchar(cp)) , c!=dot && !isaname(c)) break; } if(cp>=last) { if(c==dot || isaname(c)) { *type='$'; return(++xp); } if(c!='}') bp = cp; } } else if(c=='(') { *type = mode; xp = find_begin(cp,last,')',type); if(*(cp=xp)!=')') bp = xp; else cp++; } break; case '=': if(!inquote) { bp = cp; inassign = 1; } break; case ':': if(!inquote && inassign) bp = cp; break; case '~': if(*cp=='(') break; /* fall through */ default: if(c && c==endchar) return(xp); if(!inquote && ismeta(c)) { bp = cp; inassign = 0; } break; } } if(inquote && *bp==inquote) *type = *bp++; return(bp); }
// // Returns pointer to beginning of expansion and sets type of expansion. // static char *find_begin(char outbuff[], char *last, int endchar, int *type) { char *cp = outbuff, *bp, *xp; int c, inquote = 0, inassign = 0; int mode = *type; bp = outbuff; *type = 0; while (cp < last) { xp = cp; switch (c = mb1char(&cp)) { case '\'': case '"': { if (!inquote) { inquote = c; bp = xp; break; } if (inquote == c) inquote = 0; break; } case '\\': { if (inquote != '\'') (void)mb1char(&cp); break; } case '$': { if (inquote == '\'') break; c = *(unsigned char *)cp; if (mode != '*' && (isaletter(c) || c == '{')) { int dot = '.'; if (c == '{') { xp = cp; (void)mb1char(&cp); c = *(unsigned char *)cp; if (c != '.' && !isaletter(c)) break; } else { dot = 'a'; } while (cp < last) { if ((c = mb1char(&cp)), c != dot && !isaname(c)) break; } if (cp >= last) { if (c == dot || isaname(c)) { *type = '$'; return ++xp; } if (c != '}') bp = cp; } } else if (c == '(') { *type = mode; xp = find_begin(cp, last, ')', type); if (*(cp = xp) != ')') { bp = xp; } else { cp++; } } break; } case '=': { if (!inquote) { bp = cp; inassign = 1; } break; } case ':': { if (!inquote && inassign) bp = cp; break; } case '~': { if (*cp == '(') break; } // FALLTHRU default: { if (c && c == endchar) return xp; if (!inquote && ismeta(c)) { bp = cp; inassign = 0; } break; } } } if (inquote && *bp == inquote) { *type = *bp++; } else { if (*cp == 0 && cp[-1] == ' ') return cp; } return bp; }
/* * print <str> quoting chars so that it can be read by the shell * puts null terminated result on stack, but doesn't freeze it * single!=0 limits quoting to '...' * fold>0 prints raw newlines and inserts appropriately * escaped newlines every (fold-x) chars */ char *sh_fmtqf(const char *string, int single, int fold) { register const char *cp = string; register const char *bp; register const char *vp; register int c; register int n; register int q; register int a; int offset; if (--fold < 8) fold = 0; if (!cp || !*cp || !single && !fold || fold && strlen(string) < fold) return sh_fmtq(cp); offset = staktell(); single = single ? 1 : 3; c = mbchar(string); a = isaletter(c) ? '=' : 0; vp = cp + 1; do { q = 0; n = fold; bp = cp; while ((!n || n-- > 0) && (c = mbchar(cp))) { if (a && !isaname(c)) a = 0; #if SHOPT_MULTIBYTE if (c >= 0x200) continue; if (c == '\'' || !iswprint(c)) #else if (c == '\'' || !isprint(c)) #endif /* SHOPT_MULTIBYTE */ { q = single; break; } if (c == '\n') q = 1; else if (c == a) { stakwrite(bp, cp - bp); bp = cp; vp = cp + 1; a = 0; } else if ((c == '#' || c == '~') && cp == vp || c == ']' || c != ':' && (c = sh_lexstates[ST_NORM][c]) && c != S_EPAT) q = 1; } if (q & 2) { stakputc('$'); stakputc('\''); cp = bp; n = fold - 3; q = 1; while (c = mbchar(cp)) { switch (c) { case ('a'==97?'\033':39): c = 'E'; break; case '\n': q = 0; n = fold - 1; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; case '\f': c = 'f'; break; case '\b': c = 'b'; break; case '\a': c = 'a'; break; case '\\': if (*cp == 'n') { c = '\n'; q = 0; n = fold - 1; break; } case '\'': break; default: #if SHOPT_MULTIBYTE if(!iswprint(c)) #else if(!isprint(c)) #endif { if ((n -= 4) <= 0) { stakwrite("'\\\n$'", 5); n = fold - 7; } sfprintf(staksp, "\\%03o", c); continue; } q = 0; break; } if ((n -= q + 1) <= 0) { if (!q) { stakputc('\''); cp = bp; break; } stakwrite("'\\\n$'", 5); n = fold - 5; } if (q) stakputc('\\'); else q = 1; stakputc(c); bp = cp; } if (!c) stakputc('\''); } else if (q & 1) { stakputc('\''); cp = bp; n = fold ? (fold - 2) : 0; while (c = mbchar(cp)) { if (c == '\n') n = fold - 1; else if (n && --n <= 0) { n = fold - 2; stakwrite(bp, --cp - bp); bp = cp; stakwrite("'\\\n'", 4); } else if (n == 1 && *cp == '\'') { n = fold - 5; stakwrite(bp, --cp - bp); bp = cp; stakwrite("'\\\n\\''", 6); } else if (c == '\'') { stakwrite(bp, cp - bp - 1); bp = cp; if (n && (n -= 4) <= 0) { n = fold - 5; stakwrite("'\\\n\\''", 6); } else stakwrite("'\\''", 4); } } stakwrite(bp, cp - bp - 1); stakputc('\''); } else if (n = fold) { cp = bp; while (c = mbchar(cp)) { if (--n <= 0) { n = fold; stakwrite(bp, --cp - bp); bp = cp; stakwrite("\\\n", 2); } } stakwrite(bp, cp - bp - 1); } else stakwrite(bp, cp - bp); if (c) { stakputc('\\'); stakputc('\n'); } } while (c); stakputc(0); return(stakptr(offset)); }
/* * print <str> quoting chars so that it can be read by the shell * puts null terminated result on stack, but doesn't freeze it */ char *sh_fmtq(const char *string) { register const char *cp = string, *op; register int c, state; int offset; if(!cp) return((char*)0); offset = staktell(); #if SHOPT_MULTIBYTE state = ((c= mbchar(cp))==0); #else state = ((c= *(unsigned char*)cp++)==0); #endif if(isaletter(c)) { #if SHOPT_MULTIBYTE while((c=mbchar(cp)),isaname(c)); #else while((c = *(unsigned char*)cp++),isaname(c)); #endif if(c==0) return((char*)string); if(c=='=') { if(*cp==0) return((char*)string); c = cp - string; stakwrite(string,c); string = cp; #if SHOPT_MULTIBYTE c = mbchar(cp); #else c = *(unsigned char*)cp++; #endif } } if(c==0 || c=='#' || c=='~') state = 1; #if SHOPT_MULTIBYTE for(;c;c= mbchar(cp)) #else for(;c; c= *(unsigned char*)cp++) #endif { #if SHOPT_MULTIBYTE if(c=='\'' || !iswprint(c)) #else if(c=='\'' || !isprint(c)) #endif /* SHOPT_MULTIBYTE */ state = 2; else if(c==']' || (c!=':' && c<=0xff && (c=sh_lexstates[ST_NORM][c]) && c!=S_EPAT)) state |=1; } if(state<2) { if(state==1) stakputc('\''); if(c = --cp - string) stakwrite(string,c); if(state==1) stakputc('\''); } else { stakwrite("$'",2); cp = string; #if SHOPT_MULTIBYTE while(op = cp, c= mbchar(cp)) #else while(op = cp, c= *(unsigned char*)cp++) #endif { state=1; switch(c) { case ('a'==97?'\033':39): c = 'E'; break; case '\n': c = 'n'; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; case '\f': c = 'f'; break; case '\b': c = 'b'; break; case '\a': c = 'a'; break; case '\\': case '\'': break; default: #if SHOPT_MULTIBYTE if(!iswprint(c)) { while(op<cp) sfprintf(staksp,"\\%.3o",*(unsigned char*)op++); continue; } #else if(!isprint(c)) { sfprintf(staksp,"\\%.3o",c); continue; } #endif state=0; break; } if(state) { stakputc('\\'); stakputc(c); } else stakwrite(op, cp-op); } stakputc('\''); } stakputc(0); return(stakptr(offset)); }