about summary refs log tree commit diff
path: root/Src/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/loop.c')
-rw-r--r--Src/loop.c88
1 files changed, 51 insertions, 37 deletions
diff --git a/Src/loop.c b/Src/loop.c
index d025fbb9f..e4e8e2df8 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -545,7 +545,7 @@ execcase(Estate state, int do_exec)
     Wordcode end, next;
     wordcode code = state->pc[-1];
     char *word, *pat;
-    int npat, save;
+    int npat, save, nalts, ialt, patok;
     Patprog *spprog, pprog;
 
     end = state->pc + WC_CASE_SKIP(code);
@@ -561,60 +561,74 @@ execcase(Estate state, int do_exec)
 	if (wc_code(code) != WC_CASE)
 	    break;
 
-	pat = NULL;
-	pprog = NULL;
 	save = 0;
-	npat = state->pc[1];
-	spprog = state->prog->pats + npat;
-
 	next = state->pc + WC_CASE_SKIP(code);
+	nalts = *state->pc++;
+	ialt = patok = 0;
 
 	if (isset(XTRACE)) {
-	    char *opat;
-
-	    pat = dupstring(opat = ecrawstr(state->prog, state->pc, NULL));
-	    singsub(&pat);
-	    save = (!(state->prog->flags & EF_HEAP) &&
-		    !strcmp(pat, opat) && *spprog != dummy_patprog2);
-
 	    printprompt4();
 	    fprintf(xtrerr, "case %s (", word);
-	    quote_tokenized_output(pat, xtrerr);
-	    fprintf(xtrerr, ")\n");
-	    fflush(xtrerr);
 	}
-	state->pc += 2;
 
-	if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
-	    pprog = *spprog;
-
-	if (!pprog) {
-	    if (!pat) {
-		char *opat;
+	while (!patok && nalts) {
+	    npat = state->pc[1];
+	    spprog = state->prog->pats + npat;
+	    pprog = NULL;
+	    pat = NULL;
+	
+	    if (isset(XTRACE)) {
 		int htok = 0;
-
-		pat = dupstring(opat = ecrawstr(state->prog,
-						state->pc - 2, &htok));
+		pat = dupstring(ecrawstr(state->prog, state->pc, &htok));
 		if (htok)
 		    singsub(&pat);
-		save = (!(state->prog->flags & EF_HEAP) &&
-			!strcmp(pat, opat) && *spprog != dummy_patprog2);
+
+		if (ialt++)
+		    fprintf(stderr, " | ");
+		quote_tokenized_output(pat, xtrerr);
 	    }
-	    if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
-				     NULL)))
-		zerr("bad pattern: %s", pat);
-	    else if (save)
-		*spprog = pprog;
+
+	    if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
+		pprog = *spprog;
+
+	    if (!pprog) {
+		if (!pat) {
+		    char *opat;
+		    int htok = 0;
+
+		    pat = dupstring(opat = ecrawstr(state->prog,
+						    state->pc, &htok));
+		    if (htok)
+			singsub(&pat);
+		    save = (!(state->prog->flags & EF_HEAP) &&
+			    !strcmp(pat, opat) && *spprog != dummy_patprog2);
+		}
+		if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
+					 NULL)))
+		    zerr("bad pattern: %s", pat);
+		else if (save)
+		    *spprog = pprog;
+	    }
+	    if (pprog && pattry(pprog, word))
+		patok = 1;
+	    state->pc += 2;
+	    nalts--;
+	}
+	state->pc += 2 * nalts;
+	if (isset(XTRACE)) {
+	    fprintf(xtrerr, ")\n");
+	    fflush(xtrerr);
 	}
-	if (pprog && pattry(pprog, word)) {
+	if (patok) {
 	    execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
 				do_exec));
 	    while (!retflag && wc_code(code) == WC_CASE &&
 		   WC_CASE_TYPE(code) == WC_CASE_AND) {
 		state->pc = next;
-		code = *state->pc;
-		state->pc += 3;
-		next = state->pc + WC_CASE_SKIP(code) - 2;
+		code = *state->pc++;
+		next = state->pc + WC_CASE_SKIP(code);
+		nalts = *state->pc++;
+		state->pc += 2 * nalts;
 		execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
 				    do_exec));
 	    }