From 58580d31f593021e2ed4bfad8362e3b01bf396f3 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 11 May 2008 19:55:21 +0000 Subject: 24996: improve xtrace output for patterns --- ChangeLog | 3 +++ Src/cond.c | 14 +++++++------- Src/exec.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Src/glob.c | 19 +++++++++++-------- Src/loop.c | 6 +++--- Src/zsh.h | 9 +++++++++ 6 files changed, 93 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index d015c5da6..2fb0dedba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2008-05-11 Peter Stephenson + * 24996: Src/cond.c, Src/exec.c, Src/glob.c, Src/loop.c, + Src/zsh.h: improve xtrace output for patterns. + * users/12848: Test/A01grammar.ztst, Src/loops.c: return, break and continue are allowed in "always" block and will override try block if set. diff --git a/Src/cond.c b/Src/cond.c index cabe64446..2d073fc46 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -182,16 +182,16 @@ evalcond(Estate state, char *fromtest) } if (tracingcond) { if (ctype < COND_MOD) { - char *rt = (char *) right; - if (ctype == COND_STREQ || ctype == COND_STRNEQ) { - rt = dupstring(ecrawstr(state->prog, state->pc, NULL)); - singsub(&rt); - untokenize(rt); - } fputc(' ',xtrerr); quotedzputs(left, xtrerr); fprintf(xtrerr, " %s ", condstr[ctype]); - quotedzputs(rt, xtrerr); + if (ctype == COND_STREQ || ctype == COND_STRNEQ) { + char *rt = dupstring(ecrawstr(state->prog, state->pc, NULL)); + singsub(&rt); + quote_tokenized_output(rt, xtrerr); + } + else + quotedzputs((char *)right, xtrerr); } else { fprintf(xtrerr, " -%c ", ctype); quotedzputs(left, xtrerr); diff --git a/Src/exec.c b/Src/exec.c index 9ec49e11a..fd6f45f93 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1609,6 +1609,66 @@ untokenize(char *s) } } + +/* + * Given a tokenized string, output it to standard output in + * such a way that it's clear which tokens are active. + * Hence Star becomes an unquoted "*", while a "*" becomes "\*". + * + * The code here is a kind of amalgamation of the tests in + * zshtokenize() and untokenize() with some outputting. + */ + +/**/ +void +quote_tokenized_output(char *str, FILE *file) +{ + char *s = str; + + for (; *s; s++) { + switch (*s) { + case Meta: + putc(*++s ^ 32, file); + continue; + + case Nularg: + /* Do nothing. I think. */ + continue; + + case '\\': + case '<': + case '>': + case '(': + case '|': + case ')': + case '^': + case '#': + case '~': + case '[': + case ']': + case '*': + case '?': + case '$': + putc('\\', file); + break; + + case '=': + if (s == str) + putc('\\', file); + break; + + default: + if (itok(*s)) { + putc(ztokens[*s - Pound], file); + continue; + } + break; + } + + putc(*s, file); + } +} + /* Check that we can use a parameter for allocating a file descriptor. */ static int diff --git a/Src/glob.c b/Src/glob.c index cc1db0937..96bce0ed2 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2987,7 +2987,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, mod_export void tokenize(char *s) { - zshtokenize(s, 0, 0); + zshtokenize(s, 0); } /* @@ -3004,12 +3004,15 @@ tokenize(char *s) mod_export void shtokenize(char *s) { - zshtokenize(s, 1, isset(SHGLOB)); + int flags = ZSHTOK_SUBST; + if (isset(SHGLOB)) + flags |= ZSHTOK_SHGLOB; + zshtokenize(s, flags); } /**/ static void -zshtokenize(char *s, int glbsbst, int shglob) +zshtokenize(char *s, int flags) { char *t; int bslash = 0; @@ -3021,16 +3024,16 @@ zshtokenize(char *s, int glbsbst, int shglob) case Bnullkeep: case '\\': if (bslash) { - s[-1] = glbsbst ? Bnullkeep : Bnull; + s[-1] = (flags & ZSHTOK_SUBST) ? Bnullkeep : Bnull; break; } bslash = 1; continue; case '<': - if (shglob) + if (flags & ZSHTOK_SHGLOB) break; if (bslash) { - s[-1] = glbsbst ? Bnullkeep : Bnull; + s[-1] = (flags & ZSHTOK_SUBST) ? Bnullkeep : Bnull; break; } t = s; @@ -3046,7 +3049,7 @@ zshtokenize(char *s, int glbsbst, int shglob) case '(': case '|': case ')': - if (shglob) + if (flags & ZSHTOK_SHGLOB) break; case '>': case '^': @@ -3060,7 +3063,7 @@ zshtokenize(char *s, int glbsbst, int shglob) for (t = ztokens; *t; t++) if (*t == *s) { if (bslash) - s[-1] = glbsbst ? Bnullkeep : Bnull; + s[-1] = (flags & ZSHTOK_SUBST) ? Bnullkeep : Bnull; else *s = (t - ztokens) + Pound; break; diff --git a/Src/loop.c b/Src/loop.c index 3a6296d45..0de963318 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -559,10 +559,10 @@ execcase(Estate state, int do_exec) save = (!(state->prog->flags & EF_HEAP) && !strcmp(pat, opat) && *spprog != dummy_patprog2); - pat2 = dupstring(pat); - untokenize(pat2); printprompt4(); - fprintf(xtrerr, "case %s (%s)\n", word, pat2); + fprintf(xtrerr, "case %s (", word); + quote_tokenized_output(pat, xtrerr); + fprintf(xtrerr, ")\n"); fflush(xtrerr); } state->pc += 2; diff --git a/Src/zsh.h b/Src/zsh.h index 13bae0585..7617e2281 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1516,6 +1516,15 @@ struct repldata { }; typedef struct repldata *Repldata; +/* + * Flags to zshtokenize. + */ +enum { + /* Do glob substitution */ + ZSHTOK_SUBST = 0x0001, + /* Use sh-style globbing */ + ZSHTOK_SHGLOB = 0x0002 +}; /* Flags as the second argument to prefork */ #define PF_TYPESET 0x01 /* argument handled like typeset foo=bar */ -- cgit 1.4.1