1# -*- shell-script -*-
2# save-restore.sh - saves, sets and restores debugger vars on hook entry
3#
4#   Copyright (C) 2002-2005, 2007-2011,
5#   2014, 2017 Rocky Bernstein <rocky@gnu.org>
6#
7#   This program is free software; you can redistribute it and/or
8#   modify it under the terms of the GNU General Public License as
9#   published by the Free Software Foundation; either version 2, or
10#   (at your option) any later version.
11#
12#   This program is distributed in the hope that it will be useful,
13#   but WITHOUT ANY WARRANTY; without even the implied warranty of
14#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15#   General Public License for more details.
16#
17#   You should have received a copy of the GNU General Public License
18#   along with this program; see the file COPYING.  If not, write to
19#   the Free Software Foundation, 59 Temple Place, Suite 330, Boston,
20#   MA 02111 USA.
21
22# Does things to after on entry of after an eval to set some debugger
23# internal settings
24function _Dbg_set_debugger_internal {
25  IFS="$_Dbg_space_IFS";
26  PS4='+ dbg (${BASH_SOURCE}:${LINENO}[$BASH_SUBSHELL]): ${FUNCNAME[0]}\n'
27}
28
29function _Dbg_restore_user_vars {
30  IFS="$_Dbg_space_IFS";
31  (( _Dbg_old_set_nullglob == 0 )) && shopt -s nullglob
32  set -$_Dbg_old_set_opts
33  IFS="$_Dbg_old_IFS";
34  PS4="$_Dbg_old_PS4"
35}
36
37_Dbg_save_args() {
38
39    # Save values of $1 $2 $3 when debugged program was stopped
40    # We use the loop below rather than _Dbg_set_args="(@)" because
41    # we want to preserve embedded blanks in the arguments.
42    typeset -i _Dbg_n=${#@}
43    typeset -i _Dbg_i
44    typeset -i _Dbg_arg_max=${#_Dbg_arg[@]}
45
46    # If there has been a shift since the last time we entered,
47    # it is possible that _Dbg_arg will contain too many values.
48    # So remove those that have disappeared.
49    for (( _Dbg_i=_Dbg_arg_max; _Dbg_i > _Dbg_n ; _Dbg_i-- )) ; do
50	unset _Dbg_arg[$_Dbg_i]
51    done
52
53    _Dbg_dollar_0=$0
54    # Populate _Dbg_arg with $1, $2, etc.
55    for (( _Dbg_i=1 ; _Dbg_n > 0; _Dbg_n-- )) ; do
56	_Dbg_arg[$_Dbg_i]="$1"
57	((_Dbg_i++))
58	shift
59    done
60    unset _Dbg_arg[0]       # Get rid of line number; makes array count
61                            # correct; also listing all _Dbg_arg works
62                            # like $*.
63}
64
65# Do things for debugger entry. Set some global debugger variables
66# Remove trapping ourselves.
67# We assume that we are nested two calls deep from the point of debug
68# or signal fault. If this isn't the constant 2, then consider adding
69# a parameter to this routine.
70
71function _Dbg_set_debugger_entry {
72  # Nuke DEBUG trap
73  trap '' DEBUG
74
75  # How many function are on the stack that are part of the debugger?
76  # Normally this gets called from the trace hook. so this routine plus
77  # the trace hook should are on the FUNCNAME stack and should be ignored
78  typeset -li discard_top_fn_count=${1:-2}
79
80  _Dbg_cur_fn=${FUNCNAME[$discard_top_fn_count]}
81  _Dbg_frame_last_lineno=${BASH_LINENO[1]}
82  ((_Dbg_frame_last_lineno < 1)) && let _Dbg_frame_last_lineno=1
83
84  _Dbg_old_IFS="$IFS"
85  _Dbg_old_PS4="$PS4"
86  ((_Dbg_stack_size = ${#FUNCNAME[@]} + 1 - discard_top_fn_count))
87  _Dbg_stack_pos=_0
88  _Dbg_listline=_Dbg_frame_last_lineno
89  _Dbg_set_debugger_internal
90  _Dbg_frame_last_filename=${BASH_SOURCE[$discard_top_fn_count]:-$_Dbg_bogus_file}
91  _Dbg_frame_last_filename=$(_Dbg_resolve_expand_filename "$_Dbg_frame_last_filename")
92
93  # Read in the journal to pick up variable settings that might have
94  # been left from a subshell.
95  _Dbg_source_journal
96
97  if (( _Dbg_QUIT_LEVELS > 0 )) ; then
98    _Dbg_do_quit $_Dbg_debugged_exit_code
99  fi
100}
101
102function _Dbg_set_to_return_from_debugger {
103
104  _Dbg_stop_reason=''
105  _Dbg_listline=0
106  # FIXME: put in a frame setup routine and remove from set_entry
107  _Dbg_last_lineno=${_Dbg_frame_last_lineno}
108  if (( $1 != 0 )) ; then
109      _Dbg_last_bash_command="$_Dbg_bash_command"
110      _Dbg_last_source_file="$_Dbg_frame_last_filename"
111  else
112      _Dbg_last_lineno=${BASH_LINENO[1]}
113      _Dbg_last_source_file=${BASH_SOURCE[2]:-$_Dbg_bogus_file}
114      _Dbg_last_bash_command="**unsaved _bashdb command**"
115  fi
116
117  if (( _Dbg_restore_debug_trap )) ; then
118    trap '_Dbg_debug_trap_handler 0 "$BASH_COMMAND" "$@"' DEBUG
119  else
120    trap - DEBUG
121  fi
122
123  _Dbg_restore_user_vars
124}
125
126_Dbg_save_state() {
127  _Dbg_statefile=$(_Dbg_tempname statefile)
128  echo '' > $_Dbg_statefile
129  _Dbg_save_breakpoints
130  _Dbg_save_actions
131  _Dbg_save_watchpoints
132  _Dbg_save_display
133  _Dbg_save_Dbg_set
134  echo "unset DBG_RESTART_FILE" >> $_Dbg_statefile
135  echo "rm $_Dbg_statefile" >> $_Dbg_statefile
136  export DBG_RESTART_FILE="$_Dbg_statefile"
137  _Dbg_write_journal "export DBG_RESTART_FILE=\"$_Dbg_statefile\""
138}
139
140_Dbg_save_Dbg_set() {
141  declare -p _Dbg_set_basename     >> $_Dbg_statefile
142  declare -p _Dbg_set_debug        >> $_Dbg_statefile
143  declare -p _Dbg_edit             >> $_Dbg_statefile
144  declare -p _Dbg_set_listsize     >> $_Dbg_statefile
145  declare -p _Dbg_prompt_str       >> $_Dbg_statefile
146  declare -p _Dbg_set_show_command >> $_Dbg_statefile
147}
148
149_Dbg_restore_state() {
150  typeset statefile=$1
151  . $1
152}
153
154# Things we do when coming back from a nested shell.
155# "shell", and "debug" create nested shells.
156_Dbg_restore_from_nested_shell() {
157    rm -f $_Dbg_shell_temp_profile 2>&1 >/dev/null
158    if [[ -r $_Dbg_restore_info ]] ; then
159	. $_Dbg_restore_info
160	rm $_Dbg_restore_info
161    fi
162}
163