mod_export char * parse_subscript(char *s, int sub) { int l = strlen(s), err; char *t; if (!*s || *s == ']') return 0; lexsave(); untokenize(t = dupstring(s)); inpush(t, 0, NULL); strinbeg(0); len = 0; bptr = tokstr = s; bsiz = l + 1; err = dquote_parse(']', sub); if (err) { err = *bptr; *bptr = 0; untokenize(s); *bptr = err; s = 0; } else s = bptr; strinend(); inpop(); DPUTS(cmdsp, "BUG: parse_subscript: cmdstack not empty."); lexrestore(); return s; }
mod_export char * parse_subscript(char *s, int sub, int endchar) { int l = strlen(s), err; char *t; if (!*s || *s == endchar) return 0; zcontext_save(); untokenize(t = dupstring(s)); inpush(t, 0, NULL); strinbeg(0); lexbuf.len = 0; lexbuf.ptr = tokstr = s; lexbuf.siz = l + 1; err = dquote_parse(endchar, sub); if (err) { err = *lexbuf.ptr; *lexbuf.ptr = '\0'; untokenize(s); *lexbuf.ptr = err; s = NULL; } else { s = lexbuf.ptr; } strinend(); inpop(); DPUTS(cmdsp, "BUG: parse_subscript: cmdstack not empty."); zcontext_restore(); return s; }
static int checkalias(void) { Alias an; if (!zshlextext) return 0; if (!noaliases && isset(ALIASESOPT) && (!isset(POSIXALIASES) || (tok == STRING && !reswdtab->getnode(reswdtab, zshlextext)))) { char *suf; an = (Alias) aliastab->getnode(aliastab, zshlextext); if (an && !an->inuse && ((an->node.flags & ALIAS_GLOBAL) || (incmdpos && tok == STRING) || inalmore)) { if (!lexstop) { /* * Tokens that don't require a space after, get one, * because they are treated as if preceded by one. */ int c = hgetc(); hungetc(c); if (!iblank(c)) inpush(" ", INP_ALIAS, 0); } inpush(an->text, INP_ALIAS, an); if (an->text[0] == ' ' && !(an->node.flags & ALIAS_GLOBAL)) aliasspaceflag = 1; lexstop = 0; return 1; } if ((suf = strrchr(zshlextext, '.')) && suf[1] && suf > zshlextext && suf[-1] != Meta && (an = (Alias)sufaliastab->getnode(sufaliastab, suf+1)) && !an->inuse && incmdpos) { inpush(dupstring(zshlextext), INP_ALIAS, NULL); inpush(" ", INP_ALIAS, NULL); inpush(an->text, INP_ALIAS, an); lexstop = 0; return 1; } } return 0; }
void inungetc(int c) { if (!lexstop) { if (inbufptr != inbuf) { #ifdef DEBUG /* Just for debugging: enable only if foul play suspected. */ if (inbufptr[-1] != (char) c) fprintf(stderr, "Warning: backing up wrong character.\n"); #endif /* Just decrement the pointer: if it's not the same * character being pushed back, we're in trouble anyway. */ inbufptr--; inbufct++; inbufleft++; if (((inbufflags & INP_LINENO) || !strin) && c == '\n') lineno--; } #ifdef DEBUG else if (!(inbufflags & INP_CONT)) { /* Just for debugging */ fprintf(stderr, "Attempt to inungetc() at start of input.\n"); } #endif else { /* * The character is being backed up from a previous input stack * layer. However, there was an expansion in the middle, so we * can't back up where we want to. Instead, we just push it * onto the input stack as an extra character. */ char *cback = (char *)zshcalloc(2); cback[0] = (char) c; inpush(cback, INP_FREE|INP_CONT, NULL); } /* If we are back at the start of a segment, * we may need to restore an alias popped from the stack. * Note this may be a dummy (history expansion) entry. */ if (inbufptr == inbufpush && inbufflags & INP_ALCONT) { /* * Go back up the stack over all entries which were alias * expansions and were pushed with nothing remaining to read. */ do { if (instacktop->alias) instacktop->alias->inuse = 1; instacktop++; } while ((instacktop->flags & INP_ALCONT) && !instacktop->bufleft); inbufflags = INP_CONT|INP_ALIAS; inbufleft = 0; inbuf = inbufptr = ""; } } }
mod_export char * parse_subscript(char *s, int sub, int endchar) { int l = strlen(s), err, toklen; char *t; if (!*s || *s == endchar) return 0; zcontext_save(); untokenize(t = dupstring(s)); inpush(t, 0, NULL); strinbeg(0); /* * Warning to Future Generations: * * This way of passing the subscript through the lexer is brittle. * Code above this for several layers assumes that when we tokenise * the input it goes into the same place as the original string. * However, the lexer may overwrite later bits of the string or * reallocate it, in particular when expanding aliaes. To get * around this, we copy the string and then copy it back. This is a * bit more robust but still relies on the underlying assumption of * length preservation. */ lexbuf.len = 0; lexbuf.ptr = tokstr = dupstring(s); lexbuf.siz = l + 1; err = dquote_parse(endchar, sub); toklen = (int)(lexbuf.ptr - tokstr); DPUTS(toklen > l, "Bad length for parsed subscript"); memcpy(s, tokstr, toklen); if (err) { char *strend = s + toklen; err = *strend; *strend = '\0'; untokenize(s); *strend = err; s = NULL; } else { s += toklen; } strinend(); inpop(); DPUTS(cmdsp, "BUG: parse_subscript: cmdstack not empty."); zcontext_restore(); return s; }
mod_export int parsestrnoerr(char *s) { int l = strlen(s), err; lexsave(); untokenize(s); inpush(dupstring(s), 0, NULL); strinbeg(0); len = 0; bptr = tokstr = s; bsiz = l + 1; err = dquote_parse('\0', 1); *bptr = '\0'; strinend(); inpop(); DPUTS(cmdsp, "BUG: parsestr: cmdstack not empty."); lexrestore(); return err; }
mod_export int parsestrnoerr(char **s) { int l = strlen(*s), err; zcontext_save(); untokenize(*s); inpush(dupstring(*s), 0, NULL); strinbeg(0); lexbuf.len = 0; lexbuf.ptr = tokstr = *s; lexbuf.siz = l + 1; err = dquote_parse('\0', 1); if (tokstr) *s = tokstr; *lexbuf.ptr = '\0'; strinend(); inpop(); DPUTS(cmdsp, "BUG: parsestr: cmdstack not empty."); zcontext_restore(); return err; }
mod_export int parse_subst_string(char *s) { int c, l = strlen(s), err, olen, lexstop_ret; if (!*s || !strcmp(s, nulstring)) return 0; lexsave(); untokenize(s); inpush(dupstring(s), 0, NULL); strinbeg(0); len = 0; bptr = tokstr = s; bsiz = l + 1; c = hgetc(); lexstop_ret = lexstop; c = gettokstr(c, 1); err = errflag; strinend(); inpop(); DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty."); olen = len; lexrestore(); errflag = err; if (c == LEXERR) { untokenize(s); return 1; } #ifdef DEBUG if (c != STRING || olen != l || errflag) { fprintf(stderr, "Oops. Bug in parse_subst_string: %s\n", olen < l ? "len < l" : errflag ? "errflag" : "c != STRING"); fflush(stderr); untokenize(s); return 1; } #endif return 0; }
mod_export int parse_subst_string(char *s) { int c, l = strlen(s), err; char *ptr; enum lextok ctok; if (!*s || !strcmp(s, nulstring)) return 0; zcontext_save(); untokenize(s); inpush(dupstring(s), 0, NULL); strinbeg(0); lexbuf.len = 0; lexbuf.ptr = tokstr = s; lexbuf.siz = l + 1; c = hgetc(); ctok = gettokstr(c, 1); err = errflag; strinend(); inpop(); DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty."); zcontext_restore(); /* Keep any interrupt error status */ errflag = err | (errflag & ERRFLAG_INT); if (ctok == LEXERR) { untokenize(s); return 1; } #ifdef DEBUG /* * Historical note: we used to check here for olen (the value of lexbuf.len * before zcontext_restore()) == l, but that's not necessarily the case if * we stripped an RCQUOTE. */ if (ctok != STRING || (errflag && !noerrs)) { fprintf(stderr, "Oops. Bug in parse_subst_string: %s\n", errflag ? "errflag" : "ctok != STRING"); fflush(stderr); untokenize(s); return 1; } #endif /* Check for $'...' quoting. This needs special handling. */ for (ptr = s; *ptr; ) { if (*ptr == String && ptr[1] == Snull) { char *t; int len, tlen, diff; t = getkeystring(ptr + 2, &len, GETKEYS_DOLLARS_QUOTE, NULL); len += 2; tlen = strlen(t); diff = len - tlen; /* * Yuk. * parse_subst_string() currently handles strings in-place. * That's not so easy to fix without knowing whether * additional memory should come off the heap or * otherwise. So we cheat by copying the unquoted string * into place, unless it's too long. That's not the * normal case, but I'm worried there are pathological * cases with converting metafied multibyte strings. * If someone can prove there aren't I will be very happy. */ if (diff < 0) { DPUTS(1, "$'...' subst too long: fix get_parse_string()"); return 1; } memcpy(ptr, t, tlen); ptr += tlen; if (diff > 0) { char *dptr = ptr; char *sptr = ptr + diff; while ((*dptr++ = *sptr++)) ; } } else ptr++; } return 0; }
int exalias(void) { Alias an; Reswd rw; hwend(); if (interact && isset(SHINSTDIN) && !strin && !incasepat && tok == STRING && !nocorrect && !(inbufflags & INP_ALIAS) && (isset(CORRECTALL) || (isset(CORRECT) && incmdpos))) spckword(&tokstr, 1, incmdpos, 1); if (!tokstr) { yytext = tokstrings[tok]; return 0; } else { VARARR(char, copy, (strlen(tokstr) + 1)); if (has_token(tokstr)) { char *p, *t; yytext = p = copy; for (t = tokstr; (*p++ = itok(*t) ? ztokens[*t++ - Pound] : *t++);); } else yytext = tokstr; if (zleparse && !(inbufflags & INP_ALIAS)) { int zp = zleparse; gotword(); if (zp == 1 && !zleparse) { if (yytext == copy) yytext = tokstr; return 0; } } if (tok == STRING) { /* Check for an alias */ if (!noaliases && isset(ALIASESOPT)) { char *suf; an = (Alias) aliastab->getnode(aliastab, yytext); if (an && !an->inuse && ((an->flags & ALIAS_GLOBAL) || incmdpos || inalmore)) { inpush(an->text, INP_ALIAS, an); if (an->text[0] == ' ') aliasspaceflag = 1; lexstop = 0; if (yytext == copy) yytext = tokstr; return 1; } if ((suf = strrchr(yytext, '.')) && suf[1] && suf > yytext && suf[-1] != Meta && (an = (Alias)sufaliastab->getnode(sufaliastab, suf+1)) && !an->inuse && incmdpos) { inpush(dupstring(yytext), INP_ALIAS, NULL); inpush(" ", INP_ALIAS, NULL); inpush(an->text, INP_ALIAS, an); lexstop = 0; if (yytext == copy) yytext = tokstr; return 1; } } /* Then check for a reserved word */ if ((incmdpos || (unset(IGNOREBRACES) && yytext[0] == '}' && !yytext[1])) && (rw = (Reswd) reswdtab->getnode(reswdtab, yytext))) { tok = rw->token; if (tok == DINBRACK) incond = 1; } else if (incond && !strcmp(yytext, "]]")) { tok = DOUTBRACK; incond = 0; } else if (incond == 1 && yytext[0] == '!' && !yytext[1]) tok = BANG; } inalmore = 0; if (yytext == copy) yytext = tokstr; } return 0; }