#tcl
#tcl
Вопрос:
Когда я создаю файл tcl, при запуске неизвестной команды будет сообщаться об ошибке.
Tcl> source run.tcl
$inside tcl file$$> setup_desgin
Design setup...
Done
$inside tcl file$$> my_prove
Info: proving started
Info: ....
Info: ....
$inside tcl file$$> ::unknown my_pro
invalid command name "my_pro"
Есть ли способ показать номер строки строки ошибки в файле tcl, как показано ниже?
Tcl> source run.tcl
$inside tcl file$$> setup_desgin
Design setup...
Done
$inside tcl file$$> my_prove
Info: proving started
Info: ....
Info: ....
$inside tcl file$$> ::unknown my_pro
invalid command name "my_pro" (run.tcl:5)
Мы хотим этого, потому что у нас может быть очень большой run.tcl с приспешниками line.
Ответ №1:
На самом деле довольно сложно получить эту информацию в целом. Точная информация о номере строки доступна только в настоящее время, когда код находится в стеке выполнения. К счастью, вы можете узнать, что происходит, с помощью трассировки с шагом оставления (перехват unknown
будет работать только для неизвестных команд; трассировка позволяет перехватывать все ошибки). В приведенном ниже коде я включил его eval
, но в более практическом примере вы бы включили его source
или что-то в этом роде.
set errorlineSet 0
proc LEAVESTEP {cmd code result op args} {
global errorline errorlineSet
if {$code == 1} {
if {!$errorlineSet} {
set errorline [dict get [info frame -4] line]
}
set errorlineSet 1
} else {
set errorlineSet 0
}
}
try {
trace add execution eval leavestep LEAVESTEP
eval {
sdfgsldfjg; # This is line 17
}
} on error {msg opt} {
puts "ERROR: $msg (line: $errorline) (local line: [dict get $opt -errorline])"
} finally {
trace remove execution eval leavestep LEAVESTEP
}
Когда я сохраняю все это в файл и запускаю его, он выводит это:
ERROR: invalid command name "sdfgsldfjg" (line: 17) (local line: 3)
Как вы можете видеть, в -errorline
словаре параметров результата также есть ключ, но 3
в данном случае он сопоставлен, и это довольно вводит в заблуждение! Он использует это значение из-за обратной совместимости, но я не уверен, что это все так полезно.
Комментарии:
1. Это
-4
было обнаружено экспериментально; Мне всегда приходится искать, пока я не получу правильное значение экспериментальным путем. Наличие трассировок шагов выполнения влияет на это значение.2. Кажется, tcl8.4 не поддерживает опцию «frame» для команды «info»
Ответ №2:
Вы можете переопределить unknown
команду и использовать info frame
команду в ней, чтобы получить местоположение. Что-то вроде:
# Save the default unknown if you want
rename ::unknown ::original_unknown
proc ::unknown {name args} {
set caller [info frame -1]
dict with caller {
switch $type {
source {
puts stderr "invalid command name "$name" (in file $file:$line)"
}
proc {
if {[info exists lambda]} {
puts stderr "invalid command name "$name" (in lambda $lambda:$line)"
} else {
puts stderr "invalid command name "$name" (in proc $proc:$line)"
}
}
eval {
puts stderr "invalid command name "$name" (in eval {$cmd}:$line)"
}
precompiled {
puts stderr "Invalid command name "$name""
}
}
}
}
Пример использования:
% source my_unknown.tcl
% source bad.tcl
invalid command name "put" (in file /home/shawn/src/bad.tcl:3)