diff --git a/gash/built-ins/break.scm b/gash/built-ins/break.scm index 30fdba8..817a312 100644 --- a/gash/built-ins/break.scm +++ b/gash/built-ins/break.scm @@ -37,7 +37,10 @@ "gash: break: argument must be a positive integer~%") EXIT_FAILURE) (n (set-status! 0) - (sh:break (1- n))))) + (sh:break (1- n)) + (format (current-error-port) + "gash: break: no loop to break from~%") + EXIT_SUCCESS))) (_ (format (current-error-port) "gash: break: too many arguments~%") EXIT_FAILURE))) diff --git a/gash/built-ins/continue.scm b/gash/built-ins/continue.scm index 53b46ba..8dd9141 100644 --- a/gash/built-ins/continue.scm +++ b/gash/built-ins/continue.scm @@ -37,7 +37,10 @@ "gash: continue: argument must be a positive integer~%") EXIT_FAILURE) (n (set-status! 0) - (sh:continue (1- n))))) + (sh:continue (1- n)) + (format (current-error-port) + "gash: continue: no loop to continue from~%") + EXIT_SUCCESS))) (_ (format (current-error-port) "gash: continue: too many arguments~%") EXIT_FAILURE))) diff --git a/gash/built-ins/return.scm b/gash/built-ins/return.scm index 87b55b6..4369820 100644 --- a/gash/built-ins/return.scm +++ b/gash/built-ins/return.scm @@ -36,7 +36,11 @@ (#f (format (current-error-port) "gash: return: argument must be a number from 0 to 255~%") EXIT_FAILURE) - (n (sh:return n)))) + (n (sh:return n) + (format (current-error-port) + (string-append "gash: return: no function " + "or sourced script to return from~%")) + EXIT_SUCCESS))) (_ (format (current-error-port) "gash: return: too many arguments~%") EXIT_FAILURE))) diff --git a/gash/environment.scm b/gash/environment.scm index a8338b8..c545511 100644 --- a/gash/environment.scm +++ b/gash/environment.scm @@ -334,8 +334,9 @@ exit the dynamic extent of @var{thunk}." (define* (sh:continue #:optional (n 0)) "Exit to the closest invocation of @code{call-with-continue}. If -@var{n} is set, exit to the @math{n + 1}th closest invocation." - (abort-to-prompt *continue-tag* n)) +@var{n} is set, exit to the @math{n + 1}th closest invocation. If not +called from within @code{call-with-continue}, return @code{#f}." + (false-if-exception (abort-to-prompt *continue-tag* n))) (define *break-tag* (make-prompt-tag)) @@ -351,8 +352,9 @@ exit the dynamic extent of @var{thunk}." (define* (sh:break #:optional (n 0)) "Exit to the closest invocation of @code{call-with-break}. If -@var{n} is set, exit to the @math{n + 1}th closest invocation." - (abort-to-prompt *break-tag* n)) +@var{n} is set, exit to the @math{n + 1}th closest invocation. If not +called from within @code{call-with-break}, return @code{#f}." + (false-if-exception (abort-to-prompt *break-tag* n))) (define *return-tag* (make-prompt-tag)) @@ -367,8 +369,9 @@ exit the dynamic extent of @var{thunk}." (define* (sh:return #:optional (status (get-status))) "Exit to the closest invocation of @code{call-with-return} setting status to @var{status}. If @var{status} is not set, keep the current -status." - (abort-to-prompt *return-tag* status)) +status. If not called from within @code{call-with-return}, return +@code{#f}." + (false-if-exception (abort-to-prompt *return-tag* status))) (define *atexit* #f) (define *exiting?* #f) diff --git a/tests/functions.org b/tests/functions.org index af9ef71..7248179 100644 --- a/tests/functions.org +++ b/tests/functions.org @@ -83,3 +83,10 @@ foo #+end_src :status: 1 + +* Top-level return +:script: +#+begin_src sh + return +#+end_src +:status: 0 diff --git a/tests/spec/oil.scm b/tests/spec/oil.scm index 8b33057..dc91d65 100644 --- a/tests/spec/oil.scm +++ b/tests/spec/oil.scm @@ -159,7 +159,6 @@ ("while in pipe with subshell" ("\\$\\(\\(i\\+1\\)\\)" "$(expr $i + 1)")) ;; Gash needs to be fixed to pass these tests. - ("continue at top level") ("continue in subshell") ("continue in subshell aborts with errexit") ;; The Oil shell handles this statically. We