From 55a182b4e42f7391feb814ad78f36670593eee0d Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Thu, 25 Aug 2022 15:46:14 +0900 Subject: [PATCH] util (ble/builtin/trap): refactor --- contrib | 2 +- docs/ChangeLog.md | 30 ++++--- lib/test-util.sh | 3 +- make_command.sh | 3 +- note.txt | 39 ++++++++- src/edit.sh | 4 +- src/history.sh | 4 +- src/util.hook.sh | 214 ++++++++++++++++++++++++++-------------------- 8 files changed, 184 insertions(+), 115 deletions(-) diff --git a/contrib b/contrib index 4345a10a..53a10409 160000 --- a/contrib +++ b/contrib @@ -1 +1 @@ -Subproject commit 4345a10a9484250fe9a4f83259c21e05c20a7153 +Subproject commit 53a104092ee8bbc644979c12a29444a12b73567c diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index ad818197..90bd0742 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -56,7 +56,7 @@ - util (`bleopt`): do no select obsoleted options by wildcards `#D1595` f4312df - util (`bleopt`): fix error messages for unknown options `#D1610` 66df3e2 - util (`bleopt`, `bind`): fix error message and exit status, respectively `#D1640` b663cee - - util (`blehook`): support wildcards `#D1861` XXXXXXX + - util (`blehook`): support wildcards `#D1861` 480b7b3 - progcomp: support quoted commands and better `progcomp_alias` `#D1581` `#D1583` dbe87c3 - progcomp: fix a bug that command names may stray into completer function names `#D1611` 1f2d45f - syntax: highlight quotes of the `\?` form `#D1584` 5076a03 @@ -106,7 +106,7 @@ - util: suppress false warnings of `bind` inside non-interactive shells (reported by wukuan405) `#D1823` 1e19a67 - history: support `bleopt history_erasedups_limit` (motivated by SuperSandro2000) `#D1822` e4afb5a 3110967 - prompt: support `bleopt prompt_{emacs,vi}_mode_indicator` (motivated by ferdinandyb) `#D1843` 2b905f8 -- util (`ble-import`): support option `-q` `#D1859` XXXXXXX +- util (`ble-import`): support option `-q` `#D1859` 1ca87a9 ## Changes @@ -134,7 +134,7 @@ - prompt: update `PS0` between multiple commands (motivated by tycho-kirchner) `#D1560` 8f29203 - edit (`widget:display-shell-version`): include `ble.sh` version `#D1545` 750ca38 - edit (`display-shell-version`): detect configurations and print details `#D1781` 5015cb56 - - edit (`display-shell-version`): show information of the OS distribution and properly handle saved locales `#D1854` 066ec63 XXXXXXX + - edit (`display-shell-version`): show information of the OS distribution and properly handle saved locales `#D1854` 066ec63 bdb7dd6 - complete (`ble-sabbrev`): support colored output `#D1546` 750ca38 - decode (`ble-bind`): support colored output `#D1547` 750ca38 - decode (`ble-bind`): output bindings of the specified keymaps with `ble-bind -m KEYMAP` (fixup 750ca38) `#D1559` 6e0245a @@ -174,12 +174,16 @@ - complete: do not show option descriptions for the empty-word completion (requested by geekscrapy) `#D1846` 1c7f7a1 - syntax (`extract-command`): extract unexpected command names as commands `#D1848` 5b63459 - main (`ble-reload`): preserve the original initialization options `#D1852` d8c92cc -- blehook: print reusable code to restore the user hooks `#D1857` XXXXXXX - - blehook: separate internal and user hooks `#D1856` XXXXXXX -- trap,hook: refactor `ERR` `#D1858` XXXXXXX - - blehook: rename `ERR{ => EXEC}` and separate from the `ERR` trap - - trap: remove the support for the shell function `TRAPERR` - - trap: preserve `BASH_COMMAND` in trap handlers +- blehook: print reusable code to restore the user hooks `#D1857` b763677 + - blehook: separate internal and user hooks `#D1856` b763677 +- trap: refactor + - trap,blehook: rename `ERR{ => EXEC}` and separate from the `ERR` trap `#D1858` 94d1371 + - trap: remove the support for the shell function `TRAPERR` `#D1858` 94d1371 + - trap: preserve `BASH_COMMAND` in trap handlers `#D1858` 94d1371 + - trap,blehook: move to a new file `util.hook.sh` `#D1864` XXXXXXX + - trap (`trap -p`): fix unprinted existing user traps `#D1864` XXXXXXX + - trap (`ble/builtin/trap/finalize`): fix a failure of restoring the original trap `#D1864` XXXXXXX + - trap (`trap -p`): print also custom traps `#D1864` XXXXXXX ## Fixes @@ -289,8 +293,8 @@ - complete: fix wrong `COMP_POINT` with `progcomp_alias` `#D1841` 369f7c0 - main (`ble-update`): fix error message with system-wide installation of `ble.sh` (fixed by tars0x9752) 1d2a9c1 a450775 - main. util: fix problems of readlink etc. found by test in macOS (reported by aiotter) `#D1849` fa955c1 `#D1855` a22e145 -- util (`ble/builtin/trap`): run EXIT trap in subshells `#D1862` XXXXXXX -- util (`ble/builtin/trap`): fix the RETURN trap `#D1863` XXXXXXX +- util (`ble/builtin/trap`): run EXIT trap in subshells `#D1862` 5b351e8 +- util (`ble/builtin/trap`): fix the RETURN trap `#D1863` 793dfad ## Documentation @@ -430,8 +434,8 @@ - util (`fd#alloc`): limit the search range of free fds `#D1813` 43be0e4 4c90072 - github/workflows: define an action for the nightly builds (contributed by uyha) `#D1814` a3082a0 - global: quote numbers for unexpected `IFS` `#D1835` 0179afc -- history: refactor hooks `history_{{delete,clear,insert} => change}` `#D1860` XXXXXXX -- history: rename the hook `history_{on => }leave` `#D1860` XXXXXXX +- history: refactor hooks `history_{{delete,clear,insert} => change}` `#D1860` c393c93 +- history: rename the hook `history_{on => }leave` `#D1860` c393c93 ## Contrib diff --git a/lib/test-util.sh b/lib/test-util.sh index d2a3a3c4..a016f786 100644 --- a/lib/test-util.sh +++ b/lib/test-util.sh @@ -1158,8 +1158,7 @@ function is-global() (readonly "$1"; ! local "$1" 2>/dev/null) ble/test 'ble/builtin/trap/invoke HUP' stdout= # 9999 / CUSTOM (custom trap) - ble/builtin/trap/.register 9999 CUSTOM - ble/builtin/trap/reserve CUSTOM + ble/builtin/trap/sig#new CUSTOM ble/builtin/trap 'echo custom trap' CUSTOM ble/test 'ble/builtin/trap/invoke CUSTOM' stdout='custom trap' function ble/builtin/trap:CUSTOM { echo "__set_handler__ ($2) $1"; } diff --git a/make_command.sh b/make_command.sh index 72844de6..32d587c9 100755 --- a/make_command.sh +++ b/make_command.sh @@ -1353,8 +1353,7 @@ function sub:scan { \Zline = "bind"Zd \Ztrap_command=["'\'']trap -- Zd \Zlocal trap$Zd - \Z\$\{content#"trap -- '\''"\}Zd - \Z\("trap -- '\''.*"\*\)Zd + \Z"trap -- '\''"Zd \Z\(trap \| ble/builtin/trap\) .*;;Zd \Zble/function#trace trap Zd \Z# EXIT trapZd diff --git a/note.txt b/note.txt index ff68abcf..40012c60 100644 --- a/note.txt +++ b/note.txt @@ -6634,9 +6634,46 @@ bash_tips Done (実装ログ) ------------------------------------------------------------------------------- +2022-08-25 + + * trap: refactor and fix ble/builtin/trap [#D1864] + + * ble/builtin/trap 及び blehook 関連のコードが util.sh の中で肥大化して、他 + の util 内の関数に対する依存性が問題になってきている。より後ろで定義され + ている関数に依存しているので初期化を遅延させるなどしなければならず不都合 + である。コードをもっと後ろに移動する代わりに、ファイルを分離する事にした。 + + * fixed: 元からあった trap は出力されるのか + + これは実装を確認してみると出力されない気がする。実際に試してみるとやはり + 出力されない。修正した。 + + * fixed: そもそも ble/base/unload した時に元の trap を復元するべきなのでは + ないかという気がする。と思って確認してみた所、元から復元する様になってい + た。然しちゃんと動いていない。 + + * fixed: 然し、trap - INT という設定が外側に伝播しない様だ。EXIT はちゃん + と解除されるが INT と WINCH は外側へ行かない。 + + と思ったら単に $sig を参照する所を存在しない変数 $index を参照して trap + に渡すシグナル名を決めていたのが原因だった。修正した。 + + * fixed: というか復元するコードでカスタムシグナルに対しても勝手に trap が + 呼び出されてしまう。これは修正するべき。特に install-hook 等を通して設 + 定された物だけを復元する。 + + * ok: ble-reload した時に元々ある _ble_builtin_trap_handlers を保持するべき + なのではないか? 現在は上書きしてしまっているので install-hook 経由で設定 + されている hook 等は消滅してしまう気がする。 + + →これは ble/base/unload の際にちゃんと builtin trap を復元する様にしたら + 動く様になったので良しとする。 + + * done: trap CUSTOM なども trap -p で出力 + 2022-08-24 - * RETURN trap はちゃんと動くのだろうか [#D1863] + * trap: RETURN trap はちゃんと動くのだろうか [#D1863] 現在の trap の実装で RETURN はちゃんと設定できるのだろうか? → 試してみた所、 ちゃんと意図した箇所で RETURN trap が呼び出されているが、関係ない場所でも diff --git a/src/edit.sh b/src/edit.sh index c6d100a9..07d1b552 100644 --- a/src/edit.sh +++ b/src/edit.sh @@ -6116,7 +6116,7 @@ _ble_edit_exec_TRAPDEBUG_EXIT= _ble_edit_exec_inside_begin= _ble_edit_exec_inside_prologue= _ble_edit_exec_inside_userspace= -ble/builtin/trap/reserve DEBUG +ble/builtin/trap/sig#reserve DEBUG override-builtin-signal ## @fn ble-edit/exec:gexec/.TRAPDEBUG/trap [opts] ## @param[in] opts @@ -6155,7 +6155,7 @@ ble/function#trace _ble_edit_exec_gexec__TRAPDEBUG_adjust function ble-edit/exec:gexec/.TRAPDEBUG/restore { _ble_edit_exec_TRAPDEBUG_adjusted= local opts=$1 - ble/builtin/trap/.initialize + ble/builtin/trap/sig#init if [[ ${_ble_builtin_trap_handlers[_ble_builtin_trap_DEBUG]} ]]; then ble-edit/exec:gexec/.TRAPDEBUG/trap "$opts" fi diff --git a/src/history.sh b/src/history.sh index 3d6752c8..c02b5611 100644 --- a/src/history.sh +++ b/src/history.sh @@ -56,7 +56,7 @@ else ((stat)) || return 0 local ret=11 - ble/builtin/trap/.get-sig-index SIGSEGV + ble/builtin/trap/sig#resolve SIGSEGV ((stat==128+ret)) || return 0 local msg="bash: SIGSEGV: suspicious timestamp in HISTFILE" @@ -102,7 +102,7 @@ if ((_ble_bash<40000)); then if ((ext==142)); then printf 'ble.sh: timeout: builtin history %s' "$*" >/dev/tty local ret=11 - ble/builtin/trap/.get-sig-index SIGSEGV + ble/builtin/trap/sig#resolve SIGSEGV ((ext=128+ret)) fi ble/builtin/history/.check-timestamp-sigsegv "$ext" diff --git a/src/util.hook.sh b/src/util.hook.sh index a85113d1..22a7a7e8 100644 --- a/src/util.hook.sh +++ b/src/util.hook.sh @@ -292,6 +292,9 @@ function blehook/eval-after-load { #------------------------------------------------------------------------------ # blehook +_ble_builtin_trap_inside= # ble/builtin/trap 処理中かどうか +_ble_builtin_trap_processing= # ble/buitlin/trap/.handler 実行中かどうか + ## @fn ble/builtin/trap/.read-arguments args... ## @var[out] flags function ble/builtin/trap/.read-arguments { @@ -343,69 +346,88 @@ function ble/builtin/trap/.read-arguments { fi fi } -_ble_builtin_trap_signames=() -_ble_builtin_trap_reserved=() -_ble_builtin_trap_handlers=() -_ble_builtin_trap_handlers_RETURN=() + +builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_trap_name2sig}" +_ble_builtin_trap_sig_name=() +_ble_builtin_trap_sig_opts=() +_ble_builtin_trap_sig_base=1000 +_ble_builtin_trap_EXIT= _ble_builtin_trap_DEBUG= -_ble_builtin_trap_inside= # ble/builtin/trap 処理中かどうか -_ble_builtin_trap_processing= # ble/buitlin/trap/.handler 実行中かどうか -builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_trap_n2i}" -function ble/builtin/trap/.register { - local index=$1 name=$2 - _ble_builtin_trap_signames[index]=$name - ble/gdict#set _ble_builtin_trap_n2i "$name" "$index" +_ble_builtin_trap_RETURN= +_ble_builtin_trap_ERR= +function ble/builtin/trap/sig#register { + local sig=$1 name=$2 + _ble_builtin_trap_sig_name[sig]=$name + ble/gdict#set _ble_builtin_trap_name2sig "$name" "$sig" +} +function ble/builtin/trap/sig#reserve { + local ret + ble/builtin/trap/sig#resolve "$1" || return 1 + _ble_builtin_trap_sig_opts[ret]=${2:-1} } -function ble/builtin/trap/.get-sig-index { +## @fn ble/builtin/trap/sig#resolve sigspec +## @var[out] ret +function ble/builtin/trap/sig#resolve { + ble/builtin/trap/sig#init if [[ $1 && ! ${1//[0-9]} ]]; then ret=$1 return 0 else - ble/gdict#get _ble_builtin_trap_n2i "$1" + ble/gdict#get _ble_builtin_trap_name2sig "$1" [[ $ret ]] && return 0 ble/string#toupper "$1"; local upper=$ret - ble/gdict#get _ble_builtin_trap_n2i "$upper" || - ble/gdict#get _ble_builtin_trap_n2i "SIG$upper" || + ble/gdict#get _ble_builtin_trap_name2sig "$upper" || + ble/gdict#get _ble_builtin_trap_name2sig "SIG$upper" || return 1 - ble/gdict#set _ble_builtin_trap_n2i "$1" "$ret" + ble/gdict#set _ble_builtin_trap_name2sig "$1" "$ret" return 0 fi } -function ble/builtin/trap/.initialize { - function ble/builtin/trap/.initialize { :; } +function ble/builtin/trap/sig#new { + local name=$1 opts=$2 + local sig=$((_ble_builtin_trap_$name=_ble_builtin_trap_sig_base++)) + ble/builtin/trap/sig#register "$sig" "$name" + if [[ :$opts: != *:builtin:* ]]; then + ble/builtin/trap/sig#reserve "$sig" "$opts" + fi +} +function ble/builtin/trap/sig#init { + function ble/builtin/trap/sig#init { :; } local ret i ble/util/assign-words ret 'builtin trap -l' 2>/dev/null for ((i=0;i<${#ret[@]};i+=2)); do local index=${ret[i]%')'} local name=${ret[i+1]} - ble/builtin/trap/.register "$index" "$name" + ble/builtin/trap/sig#register "$index" "$name" done - ble/builtin/trap/.register 0 EXIT - ble/builtin/trap/.register 1000 DEBUG - ble/builtin/trap/.register 1001 RETURN - ble/builtin/trap/.register 1002 ERR - _ble_builtin_trap_DEBUG=1000 + _ble_builtin_trap_EXIT=0 + ble/builtin/trap/sig#register "$_ble_builtin_trap_EXIT" EXIT + ble/builtin/trap/sig#new DEBUG builtin + ble/builtin/trap/sig#new RETURN builtin + ble/builtin/trap/sig#new ERR builtin } -## @fn ble/builtin/trap/.load-user-handler sig +_ble_builtin_trap_handlers=() +_ble_builtin_trap_handlers_RETURN=() +## @fn ble/builtin/trap/user-handler#load sig ## @param[in] sig ## トラップ番号を指定します。 ## @var[out] _ble_trap_handler ## ユーザートラップを格納します。 ## @exit ## ユーザートラップが設定されている時に 0 を返します。 -function ble/builtin/trap/.load-user-handler { - local sig=$1 name=${_ble_builtin_trap_signames[$1]} +function ble/builtin/trap/user-handler#load { + local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} if [[ $name == RETURN ]]; then - ble/builtin/trap/.load-user-handler:RETURN + ble/builtin/trap/user-handler#load:RETURN else _ble_trap_handler=${_ble_builtin_trap_handlers[sig]-} [[ ${_ble_builtin_trap_handlers[sig]+set} ]] fi } -## @fn ble/builtin/trap/.save-user-handler sig handler +## @fn ble/builtin/trap/user-handler#save sig handler ## 指定したトラップに対するハンドラーを記録します。 ## @param[in] sig handler ## トラップ番号を指定します。 @@ -413,10 +435,10 @@ function ble/builtin/trap/.load-user-handler { ## ユーザートラップを格納します。 ## @exit ## ユーザートラップが設定されている時に 0 を返します。 -function ble/builtin/trap/.save-user-handler { - local sig=$1 name=${_ble_builtin_trap_signames[$1]} handler=$2 +function ble/builtin/trap/user-handler#save { + local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} handler=$2 if [[ $name == RETURN ]]; then - ble/builtin/trap/.save-user-handler:RETURN "$handler" + ble/builtin/trap/user-handler#save:RETURN "$handler" else if [[ $handler == - ]]; then builtin unset -v '_ble_builtin_trap_handlers[sig]' @@ -426,14 +448,14 @@ function ble/builtin/trap/.save-user-handler { fi return 0 } -function ble/builtin/trap/.save-user-handler:RETURN { +function ble/builtin/trap/user-handler#save:RETURN { local handler=$1 local offset= for ((offset=1;offset<${#FUNCNAME[@]};offset++)); do case ${FUNCNAME[offset]} in (trap | ble/builtin/trap) ;; - (ble/builtin/trap/.save-user-handler) ;; + (ble/builtin/trap/user-handler#save) ;; (*) break ;; esac done @@ -462,14 +484,15 @@ function ble/builtin/trap/.save-user-handler:RETURN { fi return 0 } -function ble/builtin/trap/.load-user-handler:RETURN { +function ble/builtin/trap/user-handler#load:RETURN { # この関数の呼び出し文脈・handler 探索開始関数レベルの決定 local offset= in_trap= for ((offset=1;offset<${#FUNCNAME[@]};offset++)); do case ${FUNCNAME[offset]} in (trap | ble/builtin/trap) ;; (ble/builtin/trap/.handler) ;; - (ble/builtin/trap/.load-user-handler) ;; + (ble/builtin/trap/user-handler#load) ;; + (ble/builtin/trap/user-handler#has) ;; (ble/builtin/trap/finalize) ;; (ble/builtin/trap/install-hook) ;; (ble/builtin/trap/invoke) ;; @@ -496,10 +519,10 @@ function ble/builtin/trap/.load-user-handler:RETURN { _ble_trap_handler=$handler [[ $found ]] } -## @fn ble/builtin/trap/.update-user-handler:RETURN +## @fn ble/builtin/trap/user-handler#update:RETURN ## 関数が戻る時に呼び出して RETURN トラップの呼び出し元への継承を実行します。 ## この関数は ble/builtin/trap/.handler から呼び出される事を想定しています。 -function ble/builtin/trap/.update-user-handler:RETURN { +function ble/builtin/trap/user-handler#update:RETURN { # この関数の呼び出し文脈の取得 local offset=2 # ... ble/builtin/trap/.handler から直接呼び出されると仮定 local current_level=$((${#FUNCNAME[@]}-offset)) @@ -521,27 +544,36 @@ function ble/builtin/trap/.update-user-handler:RETURN { _ble_builtin_trap_handlers_RETURN[current_level-1]=$handler fi } - -function ble/builtin/trap/reserve { - local ret - ble/builtin/trap/.initialize - ble/builtin/trap/.get-sig-index "$1" || return 1 - _ble_builtin_trap_reserved[ret]=${2:-1} +function ble/builtin/trap/user-handler#has { + local _ble_trap_handler + ble/builtin/trap/user-handler#load "$1" +} +function ble/builtin/trap/user-handler#init { + local script _ble_builtin_trap_user_handler_init=1 + ble/util/assign script 'builtin trap -p' + builtin eval -- "$script" } +function ble/builtin/trap/user-handler/is-internal { + case $1 in + ('ble/builtin/trap/'*) return 0 ;; # ble-0.4 + ('ble/base/unload'*|'ble-edit/'*) return 0 ;; # bash-0.3 以前 + (*) return 1 ;; + esac +} + function ble/builtin/trap/finalize { local sig - for sig in "${!_ble_builtin_trap_reserved[@]}"; do - local name=${_ble_builtin_trap_signames[index]} - [[ $name && ${_ble_builtin_trap_reserved[sig]} ]] || continue - local _ble_trap_handler - if ble/builtin/trap/.load-user-handler "$sig"; then + for sig in "${!_ble_builtin_trap_sig_opts[@]}"; do + local name=${_ble_builtin_trap_sig_name[sig]} + local opts=${_ble_builtin_trap_sig_opts[sig]} + [[ $name && :$opts: == *:override-builtin-signal:* ]] || continue + if local _ble_trap_handler; ble/builtin/trap/user-handler#load "$sig"; then builtin trap -- "$_ble_trap_handler" "$name" else builtin trap -- - "$name" fi done } - function ble/builtin/trap { local set shopt; ble/base/.adjust-bash-options set shopt local flags command sigspecs @@ -563,45 +595,48 @@ function ble/builtin/trap { ble/base/adjust-BASH_REMATCH if [[ $flags == *p* ]]; then - ble/builtin/trap/.initialize local -a indices=() if ((${#sigspecs[@]})); then local spec ret for spec in "${sigspecs[@]}"; do - if ! ble/builtin/trap/.get-sig-index "$spec"; then + if ! ble/builtin/trap/sig#resolve "$spec"; then ble/util/print "ble/builtin/trap: invalid signal specification \"$spec\"." >&2 continue fi ble/array#push indices "$ret" done else - # Note: 1001 は RETURN - indices=("${!_ble_builtin_trap_handlers[@]}" 1001) + indices=("${!_ble_builtin_trap_handlers[@]}" "$_ble_builtin_trap_RETURN") fi local q=\' Q="'\''" index _ble_trap_handler for index in "${indices[@]}"; do - if ble/builtin/trap/.load-user-handler "$index"; then - local n=${_ble_builtin_trap_signames[index]} + if ble/builtin/trap/user-handler#load "$index"; then + local n=${_ble_builtin_trap_sig_name[index]} ble/util/print "trap -- '${_ble_trap_handler//$q/$Q}' $n" fi done else + # Ignore ble.sh handlers of the previous session + [[ $_ble_builtin_trap_user_handler_init ]] && + ble/builtin/trap/user-handler/is-internal "$command" && + return 0 + local _ble_builtin_trap_inside=1 local spec ret for spec in "${sigspecs[@]}"; do - if ! ble/builtin/trap/.get-sig-index "$spec"; then + if ! ble/builtin/trap/sig#resolve "$spec"; then ble/util/print "ble/builtin/trap: invalid signal specification \"$spec\"." >&2 continue fi - local isig=$ret - local name=${_ble_builtin_trap_signames[isig]} - - ble/builtin/trap/.save-user-handler "$isig" "$command" + local sig=$ret + local name=${_ble_builtin_trap_sig_name[sig]} + ble/builtin/trap/user-handler#save "$sig" "$command" + [[ $_ble_builtin_trap_user_handler_init ]] && continue local trap_command='builtin trap -- "$command" "$spec"' - local install_opts=${_ble_builtin_trap_reserved[isig]} + local install_opts=${_ble_builtin_trap_sig_opts[sig]} if [[ $install_opts ]]; then local custom_trap=ble/builtin/trap:$name if ble/is-function "$custom_trap"; then @@ -621,11 +656,11 @@ function ble/builtin/trap { # でもない (特に subshell の中で改めて実行したい訳でもなければ)。 trap_command= fi - elif [[ :$install_opts: == *:install-hook:* ]]; then + elif [[ :$install_opts: == *:override-builtin-signal:* ]]; then # Note #D1862: 内部処理の為に trap を常設していたとしても EXIT 等の # 様に subshell に継承されない trap があるので毎回明示的に builtin # trap を実行する。 - ble/builtin/trap/install-hook/.compose-trap_command "$isig" + ble/builtin/trap/install-hook/.compose-trap_command "$sig" trap_command="builtin $trap_command" else # ble/builtin/trap/{.register,reserve} で登録したカスタム trap の場合 @@ -654,6 +689,7 @@ function ble/builtin/trap { return 0 } function trap { ble/builtin/trap "$@"; } +ble/builtin/trap/user-handler#init function ble/builtin/trap/.TRAPRETURN { local i=1 @@ -708,14 +744,13 @@ function ble/builtin/trap/invoke { local _ble_trap_lastexit=$? _ble_trap_lastarg=$_ _ble_trap_sig=$1 if [[ ${_ble_trap_sig//[0-9]} ]]; then local ret - ble/builtin/trap/.initialize - ble/builtin/trap/.get-sig-index "$1" || return 1 + ble/builtin/trap/sig#resolve "$1" || return 1 _ble_trap_sig=$ret ble/util/unlocal ret fi local _ble_trap_handler - ble/builtin/trap/.load-user-handler "$_ble_trap_sig" + ble/builtin/trap/user-handler#load "$_ble_trap_sig" [[ $_ble_trap_handler ]] || return 0 # restore $_ and $? for user trap handlers @@ -854,21 +889,21 @@ function ble/builtin/trap/.handler { [[ $_ble_builtin_trap_lastarg == *$'\n'* ]] && _ble_builtin_trap_lastarg= - if ((_ble_trap_sig==0)); then + if ((_ble_trap_sig==_ble_builtin_trap_EXIT)); then # Note #D1797: EXIT に対する ble/base/unload は trap handler のできるだけ最 # 後に実行する。勝手に削除されても困るし、他の handler が ble.sh の機能を使っ # た時に問題が起こらない様にする為。 ble/base/unload - elif ((_ble_trap_sig==1001)); then + elif ((_ble_trap_sig==_ble_builtin_trap_RETURN)); then # Note #D1863: RETURN trap の呼び出し元への継承処理を実行する。 - ble/builtin/trap/.update-user-handler:RETURN + ble/builtin/trap/user-handler#update:RETURN fi ble/base/.restore-bash-options set shopt } function ble/builtin/trap/install-hook/.compose-trap_command { - local sig=$1 name=${_ble_builtin_trap_signames[$1]} + local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} local handler="ble/builtin/trap/.handler $sig ${name#SIG} \"\$BASH_COMMAND\"; builtin eval -- \"\$_ble_builtin_trap_postproc\" \\# \"\${_ble_builtin_trap_lastarg%%\$_ble_term_nl*}\"" trap_command="trap -- '$handler' $name" } @@ -884,10 +919,9 @@ function ble/builtin/trap/install-hook/.compose-trap_command { ## ラの登録を削除します。 function ble/builtin/trap/install-hook { local ret opts=${2-} - ble/builtin/trap/.initialize - ble/builtin/trap/.get-sig-index "$1" - local sig=$ret name=${_ble_builtin_trap_signames[ret]} - ble/builtin/trap/reserve "$sig" "install-hook:$opts" + ble/builtin/trap/sig#resolve "$1" + local sig=$ret name=${_ble_builtin_trap_sig_name[ret]} + ble/builtin/trap/sig#reserve "$sig" "override-builtin-signal:$opts" local trap_command; ble/builtin/trap/install-hook/.compose-trap_command "$sig" local trap_string; ble/util/assign trap_string "builtin trap -p $name" @@ -918,23 +952,19 @@ function ble/builtin/trap/install-hook { [[ :$opts: == *:inactive:* && ! $trap_string ]] || builtin eval "builtin $trap_command"; local ext=$? - case $trap_string in - ("trap -- 'ble/builtin/trap/"*) ;; # ble-0.4 - ("trap -- 'ble/base/unload"*|"trap -- 'ble-edit/"*) ;; # bash-0.3 以前 - ("trap -- '"*) - # Note: 既存の handler がない時のみ設定を読み取る。既存の設定がある時は - # ble.sh をロードしてから trap が実行された事を意味する。一方で、ble.sh が - # ロードされて以降に builtin trap の設定がユーザーによって直接変更される事 - # は想定していないので、builtin trap から読み取った結果は ble.sh ロード前と - # 想定して良い。 - local _ble_trap_handler - ! ble/builtin/trap/.load-user-handler "$sig" && - # Note: 1000 以上はデバグ用の trap (DEBUG, RETURN, EXIT) で既定では trap - # が関数呼び出しで継承されないので、trap_string の内容は信用できない。 - ((sig<1000)) && - builtin eval -- "ble/builtin/$trap_string" ;; - esac + local q=\' + if [[ $trap_string == "trap -- '"* ]] && ! ble/builtin/trap/user-handler/is-internal "${trap_string#*$q}"; then + # Note: 1000 以上はデバグ用の trap (DEBUG, RETURN, EXIT) で既定では trapが + # 関数呼び出しで継承されないので、trap_string の内容は信用できない。 + ((sig<1000)) && + # Note: 既存の handler がない時のみ設定を読み取る。既存の設定がある時は + # ble.sh をロードしてから trap が実行された事を意味する。一方で、ble.sh + # がロードされて以降に builtin trap の設定がユーザーによって直接変更され + # る事は想定していないので、builtin trap から読み取った結果は ble.sh ロー + # ド前と想定して良い。 + ! ble/builtin/trap/user-handler#has "$sig" && + builtin eval -- "ble/builtin/$trap_string" + fi return "$ext" } -