Handle 'break' and 'continue' errors.
* gash/built-ins/utils.scm (string->positive-integer): New function. * gash/built-ins/break.scm (main): Use it to simplify argument checking; check for too many arguments; and print messages on errors. * gash/built-ins/continue.scm (main): Ditto. * gash/shell.scm (sh:exec-let): Throw an error if a special built-in fails. * tests/spec/oil.scm: Enable and adjust previously failing tests.
This commit is contained in:
parent
7d2298d15b
commit
ffe9fc1f47
|
@ -17,8 +17,10 @@
|
||||||
;;; along with Gash. If not, see <http://www.gnu.org/licenses/>.
|
;;; along with Gash. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
(define-module (gash built-ins break)
|
(define-module (gash built-ins break)
|
||||||
|
#:use-module (gash built-ins utils)
|
||||||
#:use-module (gash compat)
|
#:use-module (gash compat)
|
||||||
#:use-module (gash environment))
|
#:use-module (gash environment)
|
||||||
|
#:use-module (ice-9 match))
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
@ -27,11 +29,15 @@
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(define (main . args)
|
(define (main . args)
|
||||||
(let* ((arg (and (pair? args) (car args)))
|
(match args
|
||||||
(n (string->number (or arg "1"))))
|
(() (main "1"))
|
||||||
(if (and arg (or (not n) (not (exact-integer? n)) (< n 1)))
|
((arg)
|
||||||
1
|
(match (string->positive-integer arg)
|
||||||
(begin
|
(#f (format (current-error-port)
|
||||||
;; Since we do not return, we have to set the status here.
|
"gash: break: argument must be a positive integer~%")
|
||||||
(set-status! 0)
|
EXIT_FAILURE)
|
||||||
(sh:break (1- n))))))
|
(n (set-status! 0)
|
||||||
|
(sh:break (1- n)))))
|
||||||
|
(_ (format (current-error-port)
|
||||||
|
"gash: break: too many arguments~%")
|
||||||
|
EXIT_FAILURE)))
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
;;; along with Gash. If not, see <http://www.gnu.org/licenses/>.
|
;;; along with Gash. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
(define-module (gash built-ins continue)
|
(define-module (gash built-ins continue)
|
||||||
|
#:use-module (gash built-ins utils)
|
||||||
#:use-module (gash compat)
|
#:use-module (gash compat)
|
||||||
#:use-module (gash environment))
|
#:use-module (gash environment)
|
||||||
|
#:use-module (ice-9 match))
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
@ -27,11 +29,15 @@
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(define (main . args)
|
(define (main . args)
|
||||||
(let* ((arg (and (pair? args) (car args)))
|
(match args
|
||||||
(n (string->number (or arg "1"))))
|
(() (main "1"))
|
||||||
(if (and arg (or (not n) (not (exact-integer? n)) (< n 1)))
|
((arg)
|
||||||
1
|
(match (string->positive-integer arg)
|
||||||
(begin
|
(#f (format (current-error-port)
|
||||||
;; Since we do not return, we have to set the status here.
|
"gash: continue: argument must be a positive integer~%")
|
||||||
(set-status! 0)
|
EXIT_FAILURE)
|
||||||
(sh:continue (1- n))))))
|
(n (set-status! 0)
|
||||||
|
(sh:continue (1- n)))))
|
||||||
|
(_ (format (current-error-port)
|
||||||
|
"gash: continue: too many arguments~%")
|
||||||
|
EXIT_FAILURE)))
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:export (get-evaluator
|
#:export (get-evaluator
|
||||||
built-in?
|
built-in?
|
||||||
split-assignment))
|
split-assignment
|
||||||
|
string->positive-integer))
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
@ -53,3 +54,14 @@
|
||||||
(match (substring assignment (1+ index))
|
(match (substring assignment (1+ index))
|
||||||
((? string-null?) (values name #f))
|
((? string-null?) (values name #f))
|
||||||
(value (values name value)))))))
|
(value (values name value)))))))
|
||||||
|
|
||||||
|
(define char-set:ascii-digit
|
||||||
|
(char-set-intersection char-set:ascii char-set:digit))
|
||||||
|
|
||||||
|
(define (string->positive-integer s)
|
||||||
|
"Return the positive integer represented by the string @var{s}. If
|
||||||
|
@var{s} does not represent a positive, decimal integer in return
|
||||||
|
@code{#f}."
|
||||||
|
(and=> (and (string-every char-set:ascii-digit s) (string->number s))
|
||||||
|
(lambda (n)
|
||||||
|
(and (exact-integer? n) (> n 0) n))))
|
||||||
|
|
|
@ -131,6 +131,8 @@ environment variable bindings @var{bindings}."
|
||||||
(setvar! name value)))
|
(setvar! name value)))
|
||||||
bindings)
|
bindings)
|
||||||
(let ((exit-val (apply proc args)))
|
(let ((exit-val (apply proc args)))
|
||||||
|
(unless (= exit-val EXIT_SUCCESS)
|
||||||
|
(throw 'shell-error))
|
||||||
(set-status! exit-val))))
|
(set-status! exit-val))))
|
||||||
(and=> (getfun name)
|
(and=> (getfun name)
|
||||||
(lambda (proc)
|
(lambda (proc)
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
out)))
|
out)))
|
||||||
(loop (read-line in 'concat) transformers))))))))
|
(loop (read-line in 'concat) transformers))))))))
|
||||||
(tests-to-filter
|
(tests-to-filter
|
||||||
'(("spec/case_.test.sh"
|
`(("spec/case_.test.sh"
|
||||||
(;; These two are Bash specific.
|
(;; These two are Bash specific.
|
||||||
("Case statement with ;;&")
|
("Case statement with ;;&")
|
||||||
("Case statement with ;&")))
|
("Case statement with ;&")))
|
||||||
|
@ -162,8 +162,16 @@
|
||||||
("continue at top level")
|
("continue at top level")
|
||||||
("continue in subshell")
|
("continue in subshell")
|
||||||
("continue in subshell aborts with errexit")
|
("continue in subshell aborts with errexit")
|
||||||
("bad arg to break")
|
;; The Oil shell handles this statically. We
|
||||||
("too many args to continue")))
|
;; will treat it as a fatal run-time error (for
|
||||||
|
;; now).
|
||||||
|
("too many args to continue"
|
||||||
|
("## status: 2" ,(string-append
|
||||||
|
"## status: 2\n"
|
||||||
|
"## OK gash status: 1\n"
|
||||||
|
"## OK gash STDOUT:\n"
|
||||||
|
"a\n"
|
||||||
|
"## END")))))
|
||||||
("spec/quote.test.sh"
|
("spec/quote.test.sh"
|
||||||
(;; We match KornShell on these two tests.
|
(;; We match KornShell on these two tests.
|
||||||
("Unterminated single quote"
|
("Unterminated single quote"
|
||||||
|
|
Loading…
Reference in New Issue