Так как у меня есть доступ к программной оболочке Tcl, возможно ли включить функцию сбоя при ошибке?
Позвольте мне попытаться подвести итог своими словами: Вы хотите выйти изинтерактивная оболочка Tcl при ошибке, вместо того, чтобы снова предлагать приглашение?
Обновление
Я использую Tcl 8.3, что является серьезным ограничением с точки зрения доступных инструментов [.. .] только исходные патчи для кода C.
Поскольку вы, кажется, глубоко в этой кроличьей норе, почему бы не добавить еще один патч для исходного кода?
--- tclMain.c 2002-03-26 03:26:58.000000000 +0100
+++ tclMain.c.mrcalvin 2019-10-23 22:49:14.000000000 +0200
@@ -328,6 +328,7 @@
Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
Tcl_WriteChars(errChannel, "\n", 1);
}
+ Tcl_Exit(1);
} else if (tsdPtr->tty) {
resultPtr = Tcl_GetObjResult(interp);
Tcl_GetStringFromObj(resultPtr, &length);
Это не провереноисходники Tcl 8.3.5 для меня не компилируются. Но этот внутренний раздел Tcl сравним с текущими источниками, протестированными с использованием моей исходной установки Tcl 8.6.
Для записей
С обычной оболочкой (tclsh
) это немного сложновато, Я боюсь. Следующее может работать для вас (хотя, я могу представить случаи, когда это может вас подвести). Идея состоит в том, чтобы
- перехватывать записи в
stderr
(именно здесь интерактивная оболочка перенаправляет сообщения об ошибках перед возвратом к приглашению). - Чтобы различить произвольные записи в
stderr
и случаи ошибок, можно использовать глобальную переменную ::errorInfo
в качестве часового.
Шаг 1: Определить перехватчик канала
oo::class create Bouncer {
method initialize {handle mode} {
if {$mode ne "write"} {error "can't handle reading"}
return {finalize initialize write}
}
method finalize {handle} {
# NOOP
}
method write {handle bytes} {
if {[info exists ::errorInfo]} {
# This is an actual error;
# 1) Print the message (as usual), but to stdout
fconfigure stdout -translation binary
puts stdout $bytes
# 2) Call on [exit] to quit the Tcl process
exit 1
} else {
# Non-error write to stderr, proceed as usual
return $bytes
}
}
}
Шаг 2: Зарегистрируйте перехватчик для stderr
в интерактивных оболочках
if {[info exists ::tcl_interactive]} {
chan push stderr [Bouncer new]
}
После регистрации ваша интерактивная оболочка будет вести себя так:
% puts stderr "Goes, as usual!"
Goes, as usual!
% error "Bye, bye"
Bye, bye
Некоторые замечания
- Вы должны быть осторожны с методом
Bouncer
write
, сообщение об ошибке уже замаскировано для кодировки символов (следовательно, вызов fconfigure
). - Возможно, вы захотите поместить это в пакет Tcl или модуль Tcl, чтобы загрузить баунсер, используя
package req
. - Я мог бы представить, что ваша программа пишет в
stderr
и errorInfo
переменная может быть установлена (как оставленная), это вызовет непреднамеренный выход.