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.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/Src/loop.c b/Src/loop.c
index 19d7f733e..f7eae307b 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -208,6 +208,7 @@ execfor(Estate state, int do_exec)
     loops--;
     simple_pline = old_simple_pline;
     state->pc = end;
+    this_noerrexit = 1;
     return lastval;
 }
 
@@ -289,6 +290,8 @@ execselect(Estate state, UNUSED(int do_exec))
 	    	}
 	    } else
 		str = (char *)getlinknode(bufstack);
+            if (!str && !errflag)
+                setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */
 	    if (!str || errflag) {
 		if (breaks)
 		    breaks--;
@@ -333,6 +336,7 @@ execselect(Estate state, UNUSED(int do_exec))
     loops--;
     simple_pline = old_simple_pline;
     state->pc = end;
+    this_noerrexit = 1;
     return lastval;
 }
 
@@ -437,13 +441,12 @@ execwhile(Estate state, UNUSED(int do_exec))
             if (!((lastval == 0) ^ isuntil)) {
                 if (breaks)
                     breaks--;
-                lastval = oldval;
+		if (!retflag)
+		    lastval = oldval;
                 break;
             }
-            if (retflag) {
-                lastval = oldval;
+            if (retflag)
                 break;
-            }
 
 	    /* In case the loop body is also a functional no-op,
 	     * make sure signal handlers recognize ^C as above. */
@@ -471,6 +474,7 @@ execwhile(Estate state, UNUSED(int do_exec))
     popheap();
     loops--;
     state->pc = end;
+    this_noerrexit = 1;
     return lastval;
 }
 
@@ -522,6 +526,7 @@ execrepeat(Estate state, UNUSED(int do_exec))
     loops--;
     simple_pline = old_simple_pline;
     state->pc = end;
+    this_noerrexit = 1;
     return lastval;
 }
 
@@ -568,9 +573,11 @@ execif(Estate state, int do_exec)
 	cmdpop();
     } else {
 	noerrexit = olderrexit;
-	lastval = 0;
+	if (!retflag)
+	    lastval = 0;
     }
     state->pc = end;
+    this_noerrexit = 1;
 
     return lastval;
 }
@@ -582,7 +589,7 @@ execcase(Estate state, int do_exec)
     Wordcode end, next;
     wordcode code = state->pc[-1];
     char *word, *pat;
-    int npat, save, nalts, ialt, patok;
+    int npat, save, nalts, ialt, patok, anypatok;
     Patprog *spprog, pprog;
 
     end = state->pc + WC_CASE_SKIP(code);
@@ -590,7 +597,7 @@ execcase(Estate state, int do_exec)
     word = ecgetstr(state, EC_DUP, NULL);
     singsub(&word);
     untokenize(word);
-    lastval = 0;
+    anypatok = 0;
 
     cmdpush(CS_CASE);
     while (state->pc < end) {
@@ -613,7 +620,9 @@ execcase(Estate state, int do_exec)
 	    spprog = state->prog->pats + npat;
 	    pprog = NULL;
 	    pat = NULL;
-	
+
+	    queue_signals();
+
 	    if (isset(XTRACE)) {
 		int htok = 0;
 		pat = dupstring(ecrawstr(state->prog, state->pc, &htok));
@@ -647,9 +656,11 @@ execcase(Estate state, int do_exec)
 		    *spprog = pprog;
 	    }
 	    if (pprog && pattry(pprog, word))
-		patok = 1;
+		patok = anypatok = 1;
 	    state->pc += 2;
 	    nalts--;
+
+	    unqueue_signals();
 	}
 	state->pc += 2 * nalts;
 	if (isset(XTRACE)) {
@@ -660,7 +671,7 @@ execcase(Estate state, int do_exec)
 	    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) {
+		   WC_CASE_TYPE(code) == WC_CASE_AND && state->pc < end) {
 		state->pc = next;
 		code = *state->pc++;
 		next = state->pc + WC_CASE_SKIP(code);
@@ -678,6 +689,10 @@ execcase(Estate state, int do_exec)
 
     state->pc = end;
 
+    if (!anypatok)
+	lastval = 0;
+    this_noerrexit = 1;
+
     return lastval;
 }