summaryrefslogtreecommitdiff
path: root/Functions/Exceptions
diff options
context:
space:
mode:
Diffstat (limited to 'Functions/Exceptions')
-rw-r--r--Functions/Exceptions/catch41
-rw-r--r--Functions/Exceptions/throw29
2 files changed, 70 insertions, 0 deletions
diff --git a/Functions/Exceptions/catch b/Functions/Exceptions/catch
new file mode 100644
index 000000000..5f3876228
--- /dev/null
+++ b/Functions/Exceptions/catch
@@ -0,0 +1,41 @@
+# Catch an exception. Returns 0 if the exception in question was caught.
+# The first argument gives the exception to catch, which may be a
+# pattern.
+# This must be within an always-block. A typical set of handlers looks
+# like:
+# {
+# # try block; something here throws exceptions
+# } always {
+# if catch MyExcept; then
+# # Handler code goes here.
+# print Handling exception MyExcept
+# elif catch *; then
+# # This is the way to implement a catch-all.
+# print Handling any other exception
+# fi
+# }
+# As with other languages, exceptions do not need to be handled
+# within an always block and may propagate to a handler further up the
+# call chain.
+#
+# It is possible to throw an exception from within the handler by
+# using "throw".
+#
+# The shell variable $CAUGHT is set to the last exception caught,
+# which is useful if the argument to "catch" was a pattern.
+#
+# Use "function" keyword in case catch is already an alias.
+function catch {
+ if [[ $TRY_BLOCK_ERROR -gt 0 && $EXCEPTION = ${~1} ]]; then
+ (( TRY_BLOCK_ERROR = 0 ))
+ CAUGHT="$EXCEPTION"
+ unset EXCEPTION
+ return 0
+ fi
+
+ return 1
+}
+# Never use globbing with "catch".
+alias catch="noglob catch"
+
+catch "$@"
diff --git a/Functions/Exceptions/throw b/Functions/Exceptions/throw
new file mode 100644
index 000000000..a5478fb9c
--- /dev/null
+++ b/Functions/Exceptions/throw
@@ -0,0 +1,29 @@
+# Throw an exception.
+# The first argument is a string giving the exception. Other arguments
+# are ignored.
+#
+# This is designed to be called somewhere inside a "try-block", i.e.
+# some code of the form:
+# {
+# # try-block
+# } always {
+# # always-block
+# }
+# although as normal with exceptions it might be hidden deep inside
+# other code. Note, however, that it must be code running within the
+# current shell; with shells, unlike other languages, it is quite easy
+# to miss points at which the shell forks.
+#
+# If there is nothing to catch an exception, this behaves like any
+# other shell error, aborting to the command prompt or abandoning a
+# script.
+
+# The following must not be local.
+EXCEPTION="$1"
+if (( TRY_BLOCK_ERROR == 0 )); then
+ # We are throwing an exception from the middle of an always-block.
+ # We can do this by restoring the error status from the try-block.
+ (( TRY_BLOCK_ERROR = 1 ))
+fi
+# Raise an error, but don't show an error message.
+{ ${:?THROW} } 2>/dev/null