util.hook.sh (41735B)
1 # -*- mode: sh; mode: sh-bash -*- 2 3 #------------------------------------------------------------------------------ 4 # blehook 5 6 ## @fn blehook/.print 7 ## @var[in] flags 8 function blehook/.print { 9 (($#)) || return 0 10 11 local out= q=\' Q="'\''" nl=$'\n' 12 local sgr0= sgr1= sgr2= sgr3= 13 if [[ $flags == *c* ]]; then 14 local ret 15 ble/color/face2sgr command_function; sgr1=$ret 16 ble/color/face2sgr syntax_varname; sgr2=$ret 17 ble/color/face2sgr syntax_quoted; sgr3=$ret 18 sgr0=$_ble_term_sgr0 19 Q=$q$sgr0"\'"$sgr3$q 20 fi 21 22 local elem op_assign code=' 23 if ((${#_ble_hook_h_NAME[@]})); then 24 op_assign== 25 for elem in "${_ble_hook_h_NAME[@]}"; do 26 out="${out}${sgr1}blehook$sgr0 ${sgr2}NAME$sgr0$op_assign${sgr3}$q${elem//$q/$Q}$q$sgr0$nl" 27 op_assign=+= 28 done 29 else 30 out="${out}${sgr1}blehook$sgr0 ${sgr2}NAME$sgr0=$nl" 31 fi' 32 33 local hookname 34 for hookname; do 35 ble/is-array "$hookname" || continue 36 builtin eval -- "${code//NAME/${hookname#_ble_hook_h_}}" 37 done 38 ble/util/put "$out" 39 } 40 function blehook/.print-help { 41 ble/util/print-lines \ 42 'usage: blehook [NAME[[=|+=|-=|-+=]COMMAND]]...' \ 43 ' Add or remove hooks. Without arguments, this prints all the existing hooks.' \ 44 '' \ 45 ' Options:' \ 46 ' --help Print this help.' \ 47 ' -a, --all Print all hooks including the internal ones.' \ 48 ' --color[=always|never|auto]' \ 49 ' Change color settings.' \ 50 '' \ 51 ' Arguments:' \ 52 ' NAME Print the corresponding hooks.' \ 53 ' NAME=COMMAND Set hook after removing the existing hooks.' \ 54 ' NAME+=COMMAND Add hook.' \ 55 ' NAME-=COMMAND Remove hook.' \ 56 ' NAME!=COMMAND Add hook if the command is not registered.' \ 57 ' NAME-+=COMMAND Append the hook and remove the duplicates.' \ 58 ' NAME+-=COMMAND Prepend the hook and remove the duplicates.' \ 59 '' \ 60 ' NAME:' \ 61 ' The hook name. The character `@'\'' may be used as a wildcard.' \ 62 '' 63 } 64 65 ## @fn blehook/.read-arguments args... 66 ## @var[out] flags 67 function blehook/.read-arguments { 68 flags= print=() process=() 69 local opt_color=auto 70 while (($#)); do 71 local arg=$1; shift 72 if [[ $arg == -* ]]; then 73 case $arg in 74 (--help) 75 flags=H$flags ;; 76 (--color) opt_color=always ;; 77 (--color=always|--color=auto|--color=never) 78 opt_color=${arg#*=} ;; 79 (--color=*) 80 ble/util/print "blehook: '${arg#*=}': unrecognized option argument for '--color'." >&2 81 flags=E$flags ;; 82 (--all) flags=a$flags ;; 83 (--*) 84 ble/util/print "blehook: unrecognized long option '$arg'." >&2 85 flags=E$flags ;; 86 (-) 87 ble/util/print "blehook: unrecognized argument '$arg'." >&2 88 flags=E$flags ;; 89 (*) 90 local i c 91 for ((i=1;i<${#arg};i++)); do 92 c=${arg:i:1} 93 case $c in 94 (a) flags=a$flags ;; 95 (*) 96 ble/util/print "blehook: unrecognized option '-$c'." >&2 97 flags=E$flags ;; 98 esac 99 done ;; 100 esac 101 elif [[ $arg =~ $rex1 ]]; then 102 if [[ $arg == *@* ]] || ble/is-array "_ble_hook_h_$arg"; then 103 ble/array#push print "$arg" 104 else 105 ble/util/print "blehook: undefined hook '$arg'." >&2 106 fi 107 elif [[ $arg =~ $rex2 ]]; then 108 local name=${BASH_REMATCH[1]} 109 if [[ $name == *@* ]]; then 110 if [[ ${BASH_REMATCH[2]} == :* ]]; then 111 ble/util/print "blehook: hook pattern cannot be combined with '${BASH_REMATCH[2]}'." >&2 112 flags=E$flags 113 continue 114 fi 115 else 116 local var_counter=_ble_hook_c_$name 117 if [[ ! ${!var_counter+set} ]]; then 118 if [[ ${BASH_REMATCH[2]} == :* ]]; then 119 (($var_counter=0)) 120 else 121 ble/util/print "blehook: hook \"$name\" is not defined." >&2 122 flags=E$flags 123 continue 124 fi 125 fi 126 fi 127 ble/array#push process "$arg" 128 else 129 ble/util/print "blehook: invalid hook spec \"$arg\"" >&2 130 flags=E$flags 131 fi 132 done 133 134 # resolve patterns 135 local pat ret out; out=() 136 for pat in "${print[@]}"; do 137 if [[ $pat == *@* ]]; then 138 bleopt/expand-variable-pattern "_ble_hook_h_$pat" 139 ble/array#filter ret ble/is-array 140 [[ $pat == *[a-z]* || $flags == *a* ]] || 141 ble/array#remove-by-glob ret '_ble_hook_h_*[a-z]*' 142 if ((!${#ret[@]})); then 143 ble/util/print "blehook: '$pat': matching hook not found." >&2 144 flags=E$flags 145 continue 146 fi 147 else 148 ret=("_ble_hook_h_$pat") 149 fi 150 ble/array#push out "${ret[@]}" 151 done 152 print=("${out[@]}") 153 154 out=() 155 for pat in "${process[@]}"; do 156 [[ $pat =~ $rex2 ]] 157 local name=${BASH_REMATCH[1]} 158 if [[ $name == *@* ]]; then 159 local type=${BASH_REMATCH[3]} 160 local value=${BASH_REMATCH[4]} 161 162 bleopt/expand-variable-pattern "_ble_hook_h_$pat" 163 ble/array#filter ret ble/is-array 164 [[ $pat == *[a-z]* || $flags == *a* ]] || 165 ble/array#remove-by-glob ret '_ble_hook_h_*[a-z]*' 166 if ((!${#ret[@]})); then 167 ble/util/print "blehook: '$pat': matching hook not found." >&2 168 flags=E$flags 169 continue 170 fi 171 if ((_ble_bash>=40300)) && ! shopt -q compat42; then 172 ret=("${ret[@]/%/"$type$value"}") # WA #D1570 #D1751 checked 173 else 174 ret=("${ret[@]/%/$type$value}") # WA #D1570 #D1738 checked 175 fi 176 else 177 ret=("_ble_hook_h_$pat") 178 fi 179 ble/array#push out "${ret[@]}" 180 done 181 process=("${out[@]}") 182 183 [[ $opt_color == always || $opt_color == auto && -t 1 ]] && flags=c$flags 184 } 185 186 function blehook { 187 local set shopt 188 ble/base/adjust-BASH_REMATCH 189 ble/base/.adjust-bash-options set shopt 190 191 local flags print process 192 local rex1='^([_a-zA-Z@][_a-zA-Z0-9@]*)$' 193 local rex2='^([_a-zA-Z@][_a-zA-Z0-9@]*)(:?([-+!]|-\+|\+-)?=)(.*)$' 194 blehook/.read-arguments "$@" 195 if [[ $flags == *[HE]* ]]; then 196 if [[ $flags == *H* ]]; then 197 [[ $flags == *E* ]] && 198 ble/util/print >&2 199 blehook/.print-help 200 fi 201 [[ $flags != *E* ]]; local ext=$? 202 ble/base/.restore-bash-options set shopt 203 ble/base/restore-BASH_REMATCH 204 return "$ext" 205 fi 206 207 if ((${#print[@]}==0&&${#process[@]}==0)); then 208 print=("${!_ble_hook_h_@}") 209 [[ $flags == *a* ]] || ble/array#remove-by-glob print '_ble_hook_h_*[a-z]*' 210 fi 211 212 local proc ext=0 213 for proc in "${process[@]}"; do 214 [[ $proc =~ $rex2 ]] 215 local name=${BASH_REMATCH[1]} 216 local type=${BASH_REMATCH[3]} 217 local value=${BASH_REMATCH[4]} 218 219 local append=$value 220 case $type in 221 (*-*) # -=, -+=, +-= 222 local ret 223 ble/array#last-index "$name" "$value" 224 if ((ret>=0)); then 225 ble/array#remove-at "$name" "$ret" 226 elif [[ ${type#:} == '-=' ]]; then 227 ext=1 228 fi 229 230 if [[ $type != -+ ]]; then 231 append= 232 [[ $type == +- ]] && 233 ble/array#unshift "$name" "$value" 234 fi ;; 235 236 ('!') # != 237 local ret 238 ble/array#last-index "$name" "$value" 239 ((ret>=0)) && append= ;; 240 241 ('') builtin eval "$name=()" ;; # = 242 ('+'|*) ;; # += 243 esac 244 [[ $append ]] && ble/array#push "$name" "$append" 245 done 246 247 if ((${#print[@]})); then 248 blehook/.print "${print[@]}" 249 fi 250 251 ble/base/.restore-bash-options set shopt 252 ble/base/restore-BASH_REMATCH 253 return "$ext" 254 } 255 blehook/.compatibility-ble-0.3 256 257 function blehook/has-hook { 258 builtin eval "local count=\${#_ble_hook_h_$1[@]}" 259 ((count)) 260 } 261 ## @fn blehook/invoke.sandbox 262 ## @var[in] _ble_local_hook _ble_local_lastexit _ble_local_lastarg 263 function blehook/invoke.sandbox { 264 if type "$_ble_local_hook" &>/dev/null; then 265 ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg" 266 "$_ble_local_hook" "$@" 2>&3 267 else 268 ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg" 269 builtin eval -- "$_ble_local_hook" 2>&3 270 fi 271 } 272 function blehook/invoke { 273 local _ble_local_lastexit=$? _ble_local_lastarg=$_ FUNCNEST= 274 ((_ble_hook_c_$1++)) 275 local -a _ble_local_hooks 276 builtin eval "_ble_local_hooks=(\"\${_ble_hook_h_$1[@]}\")"; shift 277 local _ble_local_hook _ble_local_ext=0 278 for _ble_local_hook in "${_ble_local_hooks[@]}"; do 279 blehook/invoke.sandbox "$@" || _ble_local_ext=$? 280 done 281 return "$_ble_local_ext" 282 } 3>&2 2>/dev/null # set -x 対策 #D0930 283 function blehook/eval-after-load { 284 local hook_name=${1}_load value=$2 285 if ((_ble_hook_c_$hook_name)); then 286 builtin eval -- "$value" 287 else 288 blehook "$hook_name+=$value" 289 fi 290 } 291 292 #------------------------------------------------------------------------------ 293 # blehook 294 295 _ble_builtin_trap_inside= # ble/builtin/trap 処理中かどうか 296 297 ## @fn ble/builtin/trap/.read-arguments args... 298 ## @var[out] flags 299 function ble/builtin/trap/.read-arguments { 300 flags= command= sigspecs=() 301 while (($#)); do 302 local arg=$1; shift 303 if [[ $arg == -?* && flags != *A* ]]; then 304 if [[ $arg == -- ]]; then 305 flags=A$flags 306 continue 307 elif [[ $arg == --* ]]; then 308 case $arg in 309 (--help) 310 flags=h$flags 311 continue ;; 312 (*) 313 ble/util/print "ble/builtin/trap: unknown long option \"$arg\"." >&2 314 flags=E$flags 315 continue ;; 316 esac 317 fi 318 319 local i 320 for ((i=1;i<${#arg};i++)); do 321 case ${arg:i:1} in 322 (l) flags=l$flags ;; 323 (p) flags=p$flags ;; 324 (P) flags=P$flags ;; 325 (*) 326 ble/util/print "ble/builtin/trap: unknown option \"-${arg:i:1}\"." >&2 327 flags=E$flags ;; 328 esac 329 done 330 else 331 if [[ $flags != *[pc]* ]]; then 332 command=$arg 333 flags=c$flags 334 else 335 ble/array#push sigspecs "$arg" 336 fi 337 fi 338 done 339 340 if [[ $flags != *[hlpPE]* ]]; then 341 if [[ $flags != *c* ]]; then 342 flags=p$flags 343 elif ((${#sigspecs[@]}==0)); then 344 sigspecs=("$command") 345 command=- 346 fi 347 elif [[ $flags == *p* && $flags == *P* ]]; then 348 ble/util/print "ble/builtin/trap: cannot specify both -p and -P" >&2 349 flags=E${flags//[pP]} 350 fi 351 } 352 353 builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_trap_name2sig}" 354 _ble_builtin_trap_sig_name=() 355 _ble_builtin_trap_sig_opts=() 356 _ble_builtin_trap_sig_base=1000 357 _ble_builtin_trap_EXIT= 358 _ble_builtin_trap_DEBUG= 359 _ble_builtin_trap_RETURN= 360 _ble_builtin_trap_ERR= 361 function ble/builtin/trap/sig#register { 362 local sig=$1 name=$2 363 _ble_builtin_trap_sig_name[sig]=$name 364 ble/gdict#set _ble_builtin_trap_name2sig "$name" "$sig" 365 } 366 function ble/builtin/trap/sig#reserve { 367 local ret 368 ble/builtin/trap/sig#resolve "$1" || return 1 369 _ble_builtin_trap_sig_opts[ret]=${2:-1} 370 } 371 ## @fn ble/builtin/trap/sig#resolve sigspec 372 ## @var[out] ret 373 function ble/builtin/trap/sig#resolve { 374 ble/builtin/trap/sig#init 375 if [[ $1 && ! ${1//[0-9]} ]]; then 376 ret=$1 377 return 0 378 else 379 ble/gdict#get _ble_builtin_trap_name2sig "$1" 380 [[ $ret ]] && return 0 381 382 ble/string#toupper "$1"; local upper=$ret 383 ble/gdict#get _ble_builtin_trap_name2sig "$upper" || 384 ble/gdict#get _ble_builtin_trap_name2sig "SIG$upper" || 385 return 1 386 ble/gdict#set _ble_builtin_trap_name2sig "$1" "$ret" 387 return 0 388 fi 389 } 390 ## @fn ble/builtin/trap/sig#new sig [opts] 391 ## @param[in,opt] opts 392 ## 393 ## builtin (internal use) 394 ## reserve the special handling of the corresponding builtin trap. Used 395 ## for DEBUG, RETURN, and ERR. 396 ## 397 ## override-builtin-signal (internal use) 398 ## indicates that the builtin trap handler is overridden by ble.sh. The 399 ## user traps should be restored on ble-unload. 400 ## 401 ## user-trap-in-postproc 402 ## evaluate user traps outside the trap-handler function. When this is 403 ## enabled, the last argument $_ is not modified by the user trap 404 ## handlers because of the limitation of the implementation. 405 ## 406 function ble/builtin/trap/sig#new { 407 local name=$1 opts=$2 408 local sig=$((_ble_builtin_trap_$name=_ble_builtin_trap_sig_base++)) 409 ble/builtin/trap/sig#register "$sig" "$name" 410 if [[ :$opts: != *:builtin:* ]]; then 411 ble/builtin/trap/sig#reserve "$sig" "$opts" 412 fi 413 } 414 function ble/builtin/trap/sig#init { 415 function ble/builtin/trap/sig#init { :; } 416 local ret i 417 ble/util/assign-words ret 'builtin trap -l' 2>/dev/null 418 for ((i=0;i<${#ret[@]};i+=2)); do 419 local index=${ret[i]%')'} 420 local name=${ret[i+1]} 421 ble/builtin/trap/sig#register "$index" "$name" 422 done 423 424 _ble_builtin_trap_EXIT=0 425 ble/builtin/trap/sig#register "$_ble_builtin_trap_EXIT" EXIT 426 ble/builtin/trap/sig#new DEBUG builtin 427 ble/builtin/trap/sig#new RETURN builtin 428 ble/builtin/trap/sig#new ERR builtin 429 } 430 431 _ble_builtin_trap_handlers=() 432 _ble_builtin_trap_handlers_RETURN=() 433 ## @fn ble/builtin/trap/user-handler#load sig 434 ## @param[in] sig 435 ## トラップ番号を指定します。 436 ## @var[out] _ble_trap_handler 437 ## ユーザートラップを格納します。 438 ## @exit 439 ## ユーザートラップが設定されている時に 0 を返します。 440 function ble/builtin/trap/user-handler#load { 441 local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} 442 if [[ $name == RETURN ]]; then 443 ble/builtin/trap/user-handler#load:RETURN 444 else 445 _ble_trap_handler=${_ble_builtin_trap_handlers[sig]-} 446 [[ ${_ble_builtin_trap_handlers[sig]+set} ]] 447 fi 448 } 449 ## @fn ble/builtin/trap/user-handler#save sig handler 450 ## 指定したトラップに対するハンドラーを記録します。 451 ## @param[in] sig handler 452 ## トラップ番号を指定します。 453 ## @var[out] _ble_trap_handler 454 ## ユーザートラップを格納します。 455 ## @exit 456 ## ユーザートラップが設定されている時に 0 を返します。 457 function ble/builtin/trap/user-handler#save { 458 local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} handler=$2 459 if [[ $name == RETURN ]]; then 460 ble/builtin/trap/user-handler#save:RETURN "$handler" 461 else 462 if [[ $handler == - ]]; then 463 builtin unset -v '_ble_builtin_trap_handlers[sig]' 464 else 465 _ble_builtin_trap_handlers[sig]=$handler 466 fi 467 fi 468 return 0 469 } 470 function ble/builtin/trap/user-handler#save:RETURN { 471 local handler=$1 472 473 local offset= 474 for ((offset=1;offset<${#FUNCNAME[@]};offset++)); do 475 case ${FUNCNAME[offset]} in 476 (trap | ble/builtin/trap) ;; 477 (ble/builtin/trap/user-handler#save) ;; 478 (*) break ;; 479 esac 480 done 481 local current_level=$((${#FUNCNAME[@]}-offset)) 482 483 local level 484 for level in "${!_ble_builtin_trap_handlers_RETURN[@]}"; do 485 if ((level>current_level)); then 486 builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' 487 fi 488 done 489 490 if [[ $handler == - ]]; then 491 if [[ $- == *T* ]] || shopt -q extdebug; then 492 for ((level=current_level;level>=0;level--)); do 493 builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' 494 done 495 else 496 for ((level=current_level;level>=0;level--,offset++)); do 497 builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' 498 ((level)) && ble/function#has-attr "${FUNCNAME[offset]}" t || break 499 done 500 fi 501 else 502 _ble_builtin_trap_handlers_RETURN[current_level]=$handler 503 fi 504 return 0 505 } 506 function ble/builtin/trap/user-handler#load:RETURN { 507 # この関数の呼び出し文脈・handler 探索開始関数レベルの決定 508 local offset= in_trap= 509 for ((offset=1;offset<${#FUNCNAME[@]};offset++)); do 510 case ${FUNCNAME[offset]} in 511 (trap | ble/builtin/trap) ;; 512 (ble/builtin/trap/.handler) ;; 513 (ble/builtin/trap/user-handler#load) ;; 514 (ble/builtin/trap/user-handler#has) ;; 515 (ble/builtin/trap/finalize) ;; 516 (ble/builtin/trap/install-hook) ;; 517 (ble/builtin/trap/invoke) ;; 518 (*) break ;; 519 esac 520 done 521 local search_level= 522 if [[ $- == *T* ]] || shopt -q extdebug; then 523 search_level=0 524 else 525 for ((;offset<${#FUNCNAME[@]};offset++)); do 526 ble/function#has-attr "${FUNCNAME[offset]}" t || break 527 done 528 search_level=$((${#FUNCNAME[@]}-offset)) 529 fi 530 531 # search_level 以降の最大 index に記録されている handler を取得 532 local level found= handler= 533 for level in "${!_ble_builtin_trap_handlers_RETURN[@]}"; do 534 ((level>=search_level)) || continue 535 found=1 handler=${_ble_builtin_trap_handlers_RETURN[level]} 536 done 537 538 _ble_trap_handler=$handler 539 [[ $found ]] 540 } 541 ## @fn ble/builtin/trap/user-handler#update:RETURN 542 ## 関数が戻る時に呼び出して RETURN トラップの呼び出し元への継承を実行します。 543 ## この関数は ble/builtin/trap/.handler から呼び出される事を想定しています。 544 function ble/builtin/trap/user-handler#update:RETURN { 545 # この関数の呼び出し文脈の取得 546 local offset=2 # ... ble/builtin/trap/.handler から直接呼び出されると仮定 547 local current_level=$((${#FUNCNAME[@]}-offset)) 548 ((current_level>0)) || return 0 549 550 # current_level 以降の最大 index に記録されている handler を取得 551 local level found= handler= 552 for level in "${!_ble_builtin_trap_handlers_RETURN[@]}"; do 553 ((level>=current_level)) || continue 554 found=1 handler=${_ble_builtin_trap_handlers_RETURN[level]} 555 556 # 自身及びそれ以下のレベルに記録した handler は削除する。見つかった handler 557 # は後でひとつ上のレベルにコピーする。 558 if ((level>=current_level)); then 559 builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' 560 fi 561 done 562 if [[ $found ]]; then 563 _ble_builtin_trap_handlers_RETURN[current_level-1]=$handler 564 fi 565 } 566 function ble/builtin/trap/user-handler#has { 567 local _ble_trap_handler 568 ble/builtin/trap/user-handler#load "$1" 569 } 570 function ble/builtin/trap/user-handler#init { 571 local script _ble_builtin_trap_user_handler_init=1 572 ble/util/assign script 'builtin trap -p' 573 builtin eval -- "$script" 574 } 575 function ble/builtin/trap/user-handler/is-internal { 576 case $1 in 577 ('ble/builtin/trap/'*) return 0 ;; # ble-0.4 578 ('ble/base/unload'*|'ble-edit/'*) return 0 ;; # bash-0.3 以前 579 (*) return 1 ;; 580 esac 581 } 582 583 function ble/builtin/trap/finalize { 584 _ble_builtin_trap_handlers_reload=() 585 586 local sig unload_opts=$1 587 for sig in "${!_ble_builtin_trap_sig_opts[@]}"; do 588 local name=${_ble_builtin_trap_sig_name[sig]} 589 local opts=${_ble_builtin_trap_sig_opts[sig]} 590 [[ $name && :$opts: == *:override-builtin-signal:* ]] || continue 591 592 # Note (#D2021): reload の為に一旦設定を復元する時は readline によ 593 # る WINCH trap を破壊しない様に WINCH だけはそのままにして置く。 594 # 元々のユーザートラップは _ble_builtin_trap_handlers_reload に記 595 # 録し、後の ble/builtin/trap/install-hook で読み取る。 596 if [[ :$opts: == *:readline:* && :$unload_opts: == *:reload:* ]]; then 597 if local _ble_trap_handler; ble/builtin/trap/user-handler#load "$sig"; then 598 local q=\' Q="'\''" 599 _ble_builtin_trap_handlers_reload[sig]="trap -- '${_ble_trap_handler//$q/$Q}' $name" 600 else 601 _ble_builtin_trap_handlers_reload[sig]= 602 fi 603 continue 604 fi 605 606 if local _ble_trap_handler; ble/builtin/trap/user-handler#load "$sig"; then 607 builtin trap -- "$_ble_trap_handler" "$name" 608 else 609 builtin trap -- - "$name" 610 fi 611 done 612 } 613 function ble/builtin/trap { 614 local set shopt; ble/base/.adjust-bash-options set shopt 615 local flags command sigspecs 616 ble/builtin/trap/.read-arguments "$@" 617 618 if [[ $flags == *h* ]]; then 619 builtin trap --help 620 ble/base/.restore-bash-options set shopt 621 return 2 622 elif [[ $flags == *E* ]]; then 623 builtin trap --usage 2>&1 1>/dev/null | ble/bin/grep ^trap >&2 624 ble/base/.restore-bash-options set shopt 625 return 2 626 elif [[ $flags == *l* ]]; then 627 builtin trap -l 628 fi 629 630 [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && 631 ble/base/adjust-BASH_REMATCH 632 633 if [[ $flags == *[pP]* ]]; then 634 local -a indices=() 635 if ((${#sigspecs[@]})); then 636 local spec ret 637 for spec in "${sigspecs[@]}"; do 638 if ! ble/builtin/trap/sig#resolve "$spec"; then 639 ble/util/print "ble/builtin/trap: invalid signal specification \"$spec\"." >&2 640 continue 641 fi 642 ble/array#push indices "$ret" 643 done 644 else 645 indices=("${!_ble_builtin_trap_handlers[@]}" "$_ble_builtin_trap_RETURN") 646 fi 647 648 local q=\' Q="'\''" index _ble_trap_handler 649 for index in "${indices[@]}"; do 650 if ble/builtin/trap/user-handler#load "$index"; then 651 if [[ $flags == *p* ]]; then 652 local n=${_ble_builtin_trap_sig_name[index]} 653 _ble_trap_handler="trap -- '${_ble_trap_handler//$q/$Q}' $n" 654 fi 655 ble/util/print "$_ble_trap_handler" 656 fi 657 done 658 else 659 # Ignore ble.sh handlers of the previous session 660 [[ $_ble_builtin_trap_user_handler_init ]] && 661 ble/builtin/trap/user-handler/is-internal "$command" && 662 return 0 663 664 local _ble_builtin_trap_inside=1 665 local spec ret 666 for spec in "${sigspecs[@]}"; do 667 if ! ble/builtin/trap/sig#resolve "$spec"; then 668 ble/util/print "ble/builtin/trap: invalid signal specification \"$spec\"." >&2 669 continue 670 fi 671 local sig=$ret 672 local name=${_ble_builtin_trap_sig_name[sig]} 673 ble/builtin/trap/user-handler#save "$sig" "$command" 674 [[ $_ble_builtin_trap_user_handler_init ]] && continue 675 676 local trap_command='builtin trap -- "$command" "$spec"' 677 local install_opts=${_ble_builtin_trap_sig_opts[sig]} 678 if [[ $install_opts ]]; then 679 local custom_trap=ble/builtin/trap:$name 680 if ble/is-function "$custom_trap"; then 681 trap_command='"$custom_trap" "$command" "$spec"' 682 elif [[ :$install_opts: == *:readline:* ]] && ! ble/util/is-running-in-subshell; then 683 # Note (#D1345 #D1862): readline 介入を破壊しない為に親シェル内部では 684 # builtin trap 再設定はしない。 685 trap_command= 686 elif [[ $command == - ]]; then 687 if [[ :$install_opts: == *:inactive:* ]]; then 688 # Note #D1858: 単に ble/builtin/trap/.handler 経由で処理する trap の場合。 689 # trap を解除する時にはそのまま解除して良い。 690 trap_command='builtin trap - "$spec"' 691 else 692 # Note #D1858: 内部処理の為に trap は常設しているので、trap の削除 693 # はしない。だからと言って改めて内部処理の為のコマンドを登録する訳 694 # でもない (特に subshell の中で改めて実行したい訳でもなければ)。 695 trap_command= 696 fi 697 elif [[ :$install_opts: == *:override-builtin-signal:* ]]; then 698 # Note #D1862: 内部処理の為に trap を常設していたとしても EXIT 等の 699 # 様に subshell に継承されない trap があるので毎回明示的に builtin 700 # trap を実行する。 701 ble/builtin/trap/install-hook/.compose-trap_command "$sig" 702 trap_command="builtin $trap_command" 703 else 704 # ble/builtin/trap/{.register,reserve} で登録したカスタム trap の場合 705 # は builtin trap 関係の操作は何もしない。発火の制御に関しては 706 # ble/builtin/trap/invoke を適切な場所で呼び出す様に実装するべき。 707 trap_command= 708 fi 709 fi 710 711 if [[ $trap_command ]]; then 712 # Note #D1858: set -E (-o errtrace) が設定されていない限り、関数の中か 713 # ら trap ERR を削除する事はできない。仕方がないので空の command を 714 # trap として設定する事にする。元々 trap ERR が設定されていない時の動作 715 # は「何もしない」なので空文字列で問題ないはず。 716 if [[ $name == ERR && $command == - && $- != *E* ]]; then 717 command= 718 fi 719 builtin eval -- "$trap_command" 720 fi 721 done 722 fi 723 724 [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && 725 ble/base/restore-BASH_REMATCH 726 ble/base/.restore-bash-options set shopt 727 return 0 728 } 729 function trap { ble/builtin/trap "$@"; } 730 ble/builtin/trap/user-handler#init 731 732 function ble/builtin/trap/.TRAPRETURN { 733 local IFS=$_ble_term_IFS 734 local backtrace=" ${BLE_TRAP_FUNCNAME[*]-} " 735 case $backtrace in 736 # 呼び出し元が RETURN trap の設置に用いた trap の時は RETURN は無視する。それ 737 # 以外の trap 呼び出しについても無視して良い。 738 (' trap '* | ' ble/builtin/trap '*) return 126 ;; 739 # ble/builtin/trap/.handler 内部処理に対する RETURN は無視するが、 740 # ble/builtin/trap/.handler から更に呼び出された blehook / trap_string の中で 741 # 呼び出されている関数については RETURN を発火させる。 742 (*' ble/builtin/trap/.handler '*) 743 case ${backtrace%%' ble/builtin/trap/.handler '*}' ' in 744 (' '*' blehook/invoke.sandbox '* | ' '*' ble/builtin/trap/invoke.sandbox '*) ;; 745 (*) return 126 ;; 746 esac ;; 747 # 待避処理をしていないユーザーコマンド実行後に呼び出される関数達。 748 (*' ble-edit/exec:gexec/.save-lastarg ' | ' _ble_edit_exec_gexec__TRAPDEBUG_adjust ') return 126 ;; 749 esac 750 return 0 751 } 752 blehook internal_RETURN!=ble/builtin/trap/.TRAPRETURN 753 754 # user trap handler 専用の $?, $_ の記録。 755 _ble_builtin_trap_user_lastcmd= 756 _ble_builtin_trap_user_lastarg= 757 _ble_builtin_trap_user_lastexit= 758 ## @fn ble/builtin/trap/invoke.sandbox params... 759 ## @param[in] params... 760 ## @var[in] _ble_trap_handler 761 ## @var[out] _ble_trap_done 762 ## @var[in,out] _ble_trap_lastexit _ble_trap_lastarg 763 function ble/builtin/trap/invoke.sandbox { 764 local _ble_trap_count 765 for ((_ble_trap_count=0;_ble_trap_count<1;_ble_trap_count++)); do 766 _ble_trap_done=return 767 # Note #D1757: そのまま制御を変更せずに trap handler の実行が終わっ 768 # た時は $? $_ を保存する。同じ eval の中でないと $_ が eval を抜 769 # けた時に eval の最終引数に置き換えられてしまう事に注意する。 770 ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" 771 builtin eval -- "$_ble_trap_handler"$'\n_ble_trap_lastexit=$? _ble_trap_lastarg=$_' 2>&3 772 _ble_trap_done=done 773 return 0 774 done 775 _ble_trap_lastexit=$? _ble_trap_lastarg=$_ 776 777 # break/continue 検出 778 if ((_ble_trap_count==0)); then 779 _ble_trap_done=break 780 else 781 _ble_trap_done=continue 782 fi 783 return 0 784 } 785 ## @fn ble/builtin/trap/invoke sig params... 786 ## @param[in] sig 787 ## @param[in] params... 788 ## @var[in] ? _ 789 ## @var[in,out] _ble_builtin_trap_postproc[sig] 790 ## @var[in,out] _ble_builtin_trap_lastarg[sig] 791 function ble/builtin/trap/invoke { 792 local _ble_trap_lastexit=$? _ble_trap_lastarg=$_ _ble_trap_sig=$1; shift 793 if [[ ${_ble_trap_sig//[0-9]} ]]; then 794 local ret 795 ble/builtin/trap/sig#resolve "$_ble_trap_sig" || return 1 796 _ble_trap_sig=$ret 797 ble/util/unlocal ret 798 fi 799 800 local _ble_trap_handler 801 ble/builtin/trap/user-handler#load "$_ble_trap_sig" 802 [[ $_ble_trap_handler ]] || return 0 803 804 # restore $_ and $? for user trap handlers 805 if [[ $_ble_attached && ! $_ble_edit_exec_inside_userspace ]]; then 806 if [[ $_ble_builtin_trap_user_lastcmd != $_ble_edit_CMD ]]; then 807 _ble_builtin_trap_user_lastcmd=$_ble_edit_CMD 808 _ble_builtin_trap_user_lastexit=$_ble_edit_exec_lastexit 809 _ble_builtin_trap_user_lastarg=$_ble_edit_exec_lastarg 810 fi 811 _ble_trap_lastexit=$_ble_builtin_trap_user_lastexit 812 _ble_trap_lastarg=$_ble_builtin_trap_user_lastarg 813 fi 814 815 local _ble_trap_done= 816 ble/builtin/trap/invoke.sandbox "$@"; local ext=$? 817 case $_ble_trap_done in 818 (done) 819 _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg 820 _ble_builtin_trap_postproc[_ble_trap_sig]="ble/util/setexit $_ble_trap_lastexit" ;; 821 (break | continue) 822 _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg 823 if ble/string#match "$_ble_trap_lastarg" '^-?[0-9]+$'; then 824 _ble_builtin_trap_postproc[_ble_trap_sig]="$_ble_trap_done $_ble_trap_lastarg" 825 else 826 _ble_builtin_trap_postproc[_ble_trap_sig]=$_ble_trap_done 827 fi ;; 828 (return) 829 # Note #D1757: return 自体の lastarg は最早取得できないが、もし 830 # 仮に直接 builtin trap で実行されたとしても、return で関数を抜 831 # けた時に lastarg は書き換えられるので取得できない。精々関数を 832 # 呼び出す前の lastarg を設定して置いて return が失敗した時に前 833 # の状態を keep するぐらいしかない気がする。 834 _ble_builtin_trap_lastarg[_ble_trap_sig]=$ext 835 _ble_builtin_trap_postproc[_ble_trap_sig]="return $ext" ;; 836 (exit) 837 # Note #D1782: trap handler の中で ble/builtin/exit (edit.sh) を呼 838 # び出した時は、即座に bash を終了せずに取り敢えずは trap の処理 839 # は完了させる。TRAPDEBUGによって _ble_trap_done=exit が設定され 840 # る。また、元々 exit に渡された引数は $_ble_trap_lastarg に設定 841 # される。 842 # Note #D1782: 他の trap の中で更にまた DEBUG trap が起動している 843 # 時などの為に、builtin exit ではなく ble/builtin/exit を再度呼 844 # び出し直す。 845 _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg 846 _ble_builtin_trap_postproc[_ble_trap_sig]="ble/builtin/exit $_ble_trap_lastarg" ;; 847 esac 848 849 # save $_ and $? for user trap handlers 850 if [[ $_ble_attached && ! $_ble_edit_exec_inside_userspace ]]; then 851 _ble_builtin_trap_user_lastexit=$_ble_trap_lastexit 852 _ble_builtin_trap_user_lastarg=$_ble_trap_lastarg 853 fi 854 855 return 0 856 } 3>&2 2>/dev/null # set -x 対策 #D0930 857 858 ## @var _ble_builtin_trap_processing 859 ## ble/builtin/trap/.handler 実行中かどうかを表すローカル変数です。 860 ## 以下の二つの形式の内のどちらかを取ります。 861 ## 862 ## SUBSHELL/SIG 863 ## SUBSHELL は trap 処理の実行元のサブシェルの深さ (呼び出し元にお 864 ## ける BASH_SUBSHELL の値) を記録します。SIG はシグナルを表す整数 865 ## 値です。 866 ## 867 ## SUBSHELL/exit:EXIT 868 ## EXIT は ble/builtin/exit に渡された終了ステータスで、これは最終 869 ## 的な exit で使われる終了ステータスです。 870 ## 871 _ble_builtin_trap_processing= 872 _ble_builtin_trap_postproc=() 873 _ble_builtin_trap_lastarg=() 874 function ble/builtin/trap/install-hook/.compose-trap_command { 875 local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} 876 local handler='ble/builtin/trap/.handler SIGNUM "$BASH_COMMAND" "$@"; builtin eval -- "${_ble_builtin_trap_postproc[SIGNUM]}" \# "${_ble_builtin_trap_lastarg[SIGNUM]}"' 877 trap_command="trap -- '${handler//SIGNUM/$sig}' $name" # WA #D1738 checked (sig is integer) 878 } 879 880 _ble_trap_builtin_handler_DEBUG_filter= 881 882 ## @fn ble/builtin/trap/.handler sig bash_command params... 883 ## @param[in] sig 884 ## Specifies the signal number 885 ## @param[in] bash_command 886 ## Specifies the value of BASH_COMMAND in the original context 887 ## @param[in] params... 888 ## Specifies the positional parameters in the original context 889 ## @var[in] _ble_builtin_trap_depth 890 ## @var[out] _ble_builtin_trap_xlastarg[_ble_builtin_trap_depth] 891 ## @var[out] _ble_builtin_trap_xpostproc[_ble_builtin_trap_depth] 892 function ble/builtin/trap/.handler { 893 local _ble_trap_lastexit=$? _ble_trap_lastarg=$_ FUNCNEST= IFS=$_ble_term_IFS 894 local _ble_trap_sig=$1 _ble_trap_bash_command=$2 895 shift 2 896 897 # Note: bash-5.2 では read -t の最中に WINCH が来るとその場で発火して変なこと 898 # が色々起こる。(1) 内部で ble/util/msleep を実行しようとすると外側の 899 # timeout 設定が削除されて、外側の read -t が永遠に終わらない状態になる。特 900 # に msleep では終端しないストリームから読み出そうとするのでデッドロックす 901 # る。(2) 中でコマンド置換 $() や mapfile を使おうとすると、 902 # run_pending_trap (trap.c) が途中で予期せず中断してしまって running_trap 903 # が放置された状態になる。trap 処理入れ子状態になってしまってずっと WINCH 904 # を受信できない状態になってしまう。 905 if [[ $_ble_bash_read_winch && ${_ble_builtin_trap_sig_name[_ble_trap_sig]} == SIGWINCH ]]; then 906 local ret 907 ble/string#quote-command "$FUNCNAME" "$_ble_trap_sig" "$_ble_trap_bash_command" "$@" 908 _ble_bash_read_winch=$ret$'\n''builtin eval -- "${_ble_builtin_trap_postproc['$_ble_trap_sig']}"' 909 return 0 910 fi 911 912 # Early filter for frequently called DEBUG (set by edit.sh) 913 if ((_ble_trap_sig==_ble_builtin_trap_DEBUG)) && 914 ! builtin eval -- "$_ble_trap_builtin_handler_DEBUG_filter"; then 915 _ble_builtin_trap_lastarg[_ble_trap_sig]=${_ble_trap_lastarg//*$_ble_term_nl*} 916 _ble_builtin_trap_postproc[_ble_trap_sig]="ble/util/setexit $_ble_trap_lastexit" 917 return 0 918 fi 919 920 # Adjust trap context 921 local _ble_trap_set _ble_trap_shopt; ble/base/.adjust-bash-options _ble_trap_set _ble_trap_shopt 922 local _ble_trap_name=${_ble_builtin_trap_sig_name[_ble_trap_sig]#SIG} 923 local -a _ble_trap_args; _ble_trap_args=("$@") 924 if [[ ! $_ble_trap_bash_command ]] || ((_ble_bash<30200)); then 925 # Note: Bash 3.0, 3.1 は trap 中でも BASH_COMMAND は trap 発動対象ではなく 926 # て現在実行中のコマンドになっている。_ble_trap_bash_command には単に 927 # ble/builtin/trap/.handler が入っているので別の適当な値で置き換える。 928 if [[ $_ble_attached ]]; then 929 _ble_trap_bash_command=$_ble_edit_exec_BASH_COMMAND 930 else 931 ble/util/assign _ble_trap_bash_command 'HISTTIMEFORMAT=__ble_ext__ builtin history 1' 932 _ble_trap_bash_command=${_ble_trap_bash_command#*__ble_ext__} 933 fi 934 fi 935 936 local _ble_builtin_trap_processing=${BASH_SUBSHELL:-0}/$_ble_trap_sig 937 _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg 938 _ble_builtin_trap_postproc[_ble_trap_sig]="ble/util/setexit $_ble_trap_lastexit" 939 940 # Note #D1782: ble/builtin/exit で "builtin exit ... &>/dev/null" と 941 # したリダイレクションを元に戻す。元々 builtin exit が出力するエラー 942 # を無視する為のリダイレクトだが、続いて呼び出される EXIT trap に 943 # 対してもこのリダイレクションが有効なままになる (但し、 944 # bash-4.4..5.1 ではバグで top-level まで制御を戻してから EXIT 945 # trap 他の処理が実行されるので、EXIT trap は tty に繋がった状態で 946 # 実行される)。他の trap が予期せず呼び出された場合にも同様の事が 947 # 起こる。trap handler を exit を実行した文脈での stdout/stderr で 948 # 実行する為に、stdout/stderr を保存していた物に繋ぎ戻す。 949 if [[ $_ble_builtin_exit_processing ]]; then 950 exec 1>&- 1>&"$_ble_builtin_exit_stdout" 951 exec 2>&- 2>&"$_ble_builtin_exit_stderr" 952 fi 953 954 local BLE_TRAP_FUNCNAME BLE_TRAP_SOURCE BLE_TRAP_LINENO 955 BLE_TRAP_FUNCNAME=("${FUNCNAME[@]:1}") 956 BLE_TRAP_SOURCE=("${BASH_SOURCE[@]:1}") 957 BLE_TRAP_LINENO=("${BASH_LINENO[@]}") 958 [[ $_ble_attached ]] && 959 BLE_TRAP_LINENO[${#BASH_LINENO[@]}-1]=$_ble_edit_LINENO 960 961 # ble.sh internal hook 962 ble/util/joblist.check 963 ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" 964 blehook/invoke "internal_$_ble_trap_name"; local internal_ext=$? 965 ble/util/joblist.check ignore-volatile-jobs 966 967 if ((internal_ext!=126)); then 968 if ! ble/util/is-running-in-subshell; then 969 # blehook (only activated in parent shells) 970 ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" 971 BASH_COMMAND=$_ble_trap_bash_command \ 972 blehook/invoke "$_ble_trap_name" 973 ble/util/joblist.check ignore-volatile-jobs 974 fi 975 976 # user hook 977 local install_opts=${_ble_builtin_trap_sig_opts[_ble_trap_sig]} 978 if [[ :$_ble_tra_opts: == *:user-trap-in-postproc:* ]]; then 979 # ユーザートラップを外で実行 (Note: user-trap lastarg は反映されず) 980 local q=\' Q="'\''" _ble_trap_handler postproc= 981 ble/builtin/trap/user-handler#load "$_ble_trap_sig" 982 if [[ $_ble_trap_handler == *[![:space:]]* ]]; then 983 postproc="ble/util/setexit $_ble_trap_lastexit '${_ble_trap_lastarg//$q/$Q}'" 984 postproc=$postproc";LINENO=$BLE_TRAP_LINENO builtin eval -- '${_ble_trap_handler//$q/$Q}'" 985 else 986 postproc="ble/util/setexit $_ble_trap_lastexit" 987 fi 988 _ble_builtin_trap_postproc[_ble_trap_sig]=$postproc 989 else 990 ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" 991 BASH_COMMAND=$_ble_trap_bash_command LINENO=$BLE_TRAP_LINENO \ 992 ble/builtin/trap/invoke "$_ble_trap_sig" "${_ble_trap_args[@]}" 993 fi 994 fi 995 996 # 何処かの時点で exit が要求された場合 997 if [[ $_ble_builtin_trap_processing == */exit:* && ${_ble_builtin_trap_postproc[_ble_trap_sig]} != 'ble/builtin/exit '* ]]; then 998 _ble_builtin_trap_postproc[_ble_trap_sig]="ble/builtin/exit ${_ble_builtin_trap_processing#*/exit:}" 999 fi 1000 1001 # Note #D1757: 現在 eval が終わった後の $_ を設定する為には eval に 1002 # '#' "$lastarg" を余分に渡すしかないので改行を含める事はできない。 1003 # 中途半端な値を設定するよりは最初から何も設定しない事にする。ここ設 1004 # 定する lastarg は一見して誰も使わない様な気がするが、裸で設定され 1005 # た user trap が参照するかもしれないので一応設定する。 1006 [[ ${_ble_builtin_trap_lastarg[_ble_trap_sig]} == *$'\n'* ]] && 1007 _ble_builtin_trap_lastarg[_ble_trap_sig]= 1008 1009 if ((_ble_trap_sig==_ble_builtin_trap_EXIT)); then 1010 # Note #D1797: EXIT に対する ble/base/unload は trap handler のできるだけ最 1011 # 後に実行する。勝手に削除されても困るし、他の handler が ble.sh の機能を使っ 1012 # た時に問題が起こらない様にする為。 1013 ble/base/unload EXIT 1014 elif ((_ble_trap_sig==_ble_builtin_trap_RETURN)); then 1015 # Note #D1863: RETURN trap の呼び出し元への継承処理を実行する。 1016 ble/builtin/trap/user-handler#update:RETURN 1017 fi 1018 1019 ble/base/.restore-bash-options _ble_trap_set _ble_trap_shopt 1020 } 1021 1022 ## @fn ble/builtin/trap/install-hook sig [opts] 1023 ## @param[in] sig 1024 ## シグナル名、もしくは番号 1025 ## @param[in,opt] opts 1026 ## readline readline による処理が追加されることが期待される trap handler で 1027 ## ある事を示します。既に設定済みのハンドラーが存在している場合に 1028 ## はハンドラーの再設定を行いません。 1029 ## inactive ユーザートラップが設定されていない時は builtin trap からハンド 1030 ## ラの登録を削除します。 1031 function ble/builtin/trap/install-hook { 1032 local ret opts=${2-} 1033 ble/builtin/trap/sig#resolve "$1" 1034 local sig=$ret name=${_ble_builtin_trap_sig_name[ret]} 1035 ble/builtin/trap/sig#reserve "$sig" "override-builtin-signal:$opts" 1036 1037 local trap_command; ble/builtin/trap/install-hook/.compose-trap_command "$sig" 1038 local trap_string; ble/util/assign trap_string "builtin trap -p $name" 1039 1040 if [[ :$opts: == *:readline:* ]] && ! ble/util/is-running-in-subshell; then 1041 # Note #D1345: ble.sh の内部で "builtin trap -- WINCH" 等とすると 1042 # readline の処理が行われなくなってしまう (COLUMNS, LINES が更新さ 1043 # れない)。 1044 # 1045 # Bash では TSTP, TTIN, TTOU, INT, TERM, HUP, QUIT, WINCH について 1046 # は readline が処理を追加している。builtin trap を実行すると、一旦 1047 # は trap の設定した trap_handler が設定されるが、"コマンド実行後" 1048 # に readline が rl_maybe_set_sighandler という関数を用いて上書きし 1049 # てreadline 特有の処理を挿入する。ble.sh は readline の "コマンド 1050 # 実行"を使わないので、readline による追加処理が消滅する。 1051 # 1052 # 対策として、今から登録しようとしている文字列が既に登録されている 1053 # 物と一致する場合には、builtin trap の呼び出しを省略する。 1054 # 1055 # - 現状では問題になっているのは WINCH だけなので取り敢えず WINCH 1056 # だけ対策をする。 1057 # - INT は bind -x 内だと改めて設定しないと有効にならない(?)様なの 1058 # で既に登録されていても、builtin trap は省略できない。 1059 # 1060 [[ $trap_command == "$trap_string" ]] && trap_command= trap_string= 1061 1062 # Note (#D2021): reload 時に元の trap が保存されていればそれを読み取る。 1063 [[ $trap_string ]] || trap_string=${_ble_builtin_trap_handlers_reload[sig]-} 1064 fi 1065 1066 [[ ! $trap_command || :$opts: == *:inactive:* && ! $trap_string ]] || 1067 builtin eval "builtin $trap_command"; local ext=$? 1068 1069 local q=\' 1070 if [[ $trap_string == "trap -- '"* ]] && ! ble/builtin/trap/user-handler/is-internal "${trap_string#*$q}"; then 1071 # Note: 1000 以上はデバグ用の trap (DEBUG, RETURN, EXIT) で既定では trapが 1072 # 関数呼び出しで継承されないので、trap_string の内容は信用できない。 1073 ((sig<1000)) && 1074 # Note: 既存の handler がない時のみ設定を読み取る。既存の設定がある時は 1075 # ble.sh をロードしてから trap が実行された事を意味する。一方で、ble.sh 1076 # がロードされて以降に builtin trap の設定がユーザーによって直接変更され 1077 # る事は想定していないので、builtin trap から読み取った結果は ble.sh ロー 1078 # ド前と想定して良い。 1079 ! ble/builtin/trap/user-handler#has "$sig" && 1080 builtin eval -- "ble/builtin/$trap_string" 1081 fi 1082 1083 return "$ext" 1084 }