about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Src/cond.c14
-rw-r--r--Src/exec.c60
-rw-r--r--Src/glob.c19
-rw-r--r--Src/loop.c6
-rw-r--r--Src/zsh.h9
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  <p.w.stephenson@ntlworld.com>
 
+	* 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 */