File: fns.sh

package info (click to toggle)
bashdb 4.0.0.4-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 4,820 kB
  • ctags: 942
  • sloc: sh: 10,581; lisp: 885; makefile: 449; ansic: 325
file content (292 lines) | stat: -rw-r--r-- 8,034 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# -*- shell-script -*-
# fns.sh - Bourne Again Shell Debugger Utility Functions
#
#   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 Rocky Bernstein
#   rocky@gnu.org
#
#   bashdb is free software; you can redistribute it and/or modify it under
#   the terms of the GNU General Public License as published by the Free
#   Software Foundation; either version 2, or (at your option) any later
#   version.
#
#   bashdb is distributed in the hope that it will be useful, but WITHOUT ANY
#   WARRANTY; without even the implied warranty of MERCHANTABILITY or
#   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
#   for more details.
#   
#   You should have received a copy of the GNU General Public License along
#   with bashdb; see the file COPYING.  If not, write to the Free Software
#   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.

# Return $2 copies of $1. If successful, $? is 0 and the return value
# is in result.  Otherwise $? is 1 and result ''
function _Dbg_copies { 
    result=''
    (( $# < 2 )) && return 1
    typeset -r string=$1
    typeset -i count=$2 || return 2;
    (( count > 0 )) || return 3
    builtin printf -v result "%${count}s" ' ' || return 3
    result=${result// /$string}
    return 0
}

# _Dbg_defined returns 0 if $1 is a defined variable or 1 otherwise. 
_Dbg_defined() {
  typeset -p $1 &>/dev/null
  if [[ $? != 0 ]] ; then 
    return 1
  else
    return 0
  fi
}

# Add escapes to a string $1 so that when it is read back via "$1"
# it is the same as $1.
function _Dbg_esc_dq {
  builtin printf "%q\n" "$1"
}

# Print "on" or "off" depending on whether $1 is true (0) or false
# (nonzero).
function _Dbg_onoff {
  typeset onoff='off.'
  (( $1 != 0 )) && onoff='on.'
  builtin echo $onoff
}

# Set $? to $1 if supplied or the saved entry value of $?. 
function _Dbg_set_dol_q {
  return ${1:-$_Dbg_debugged_exit_code}
}

# Split $2 using $1 as the split character.  We accomplish this by
# temporarily resetting the variable IFS (input field separator).
#
# Example:
# typeset -a a=($(_Dbg_split ':' "file:line"))
# a[0] will have file and a{1] will have line.

function _Dbg_split {
  typeset old_IFS=$IFS
  typeset new_ifs=${1:-' '}
  shift
  typeset -r text="$*"
  typeset -a array
  IFS="$new_ifs"
  array=( $text )
  echo ${array[@]}
  IFS=$old_IFS
}

# Return value of eval($1$2). Until bash has associative arrays,
# this is how we simulate such a datatype. In Perl this would be returning
# the value of  $1{$2}.

function _Dbg_get_assoc_scalar_entry {
    typeset prefix=$1
    typeset entry=${2:-''}
    typeset cmd="echo \$${prefix}${entry}"
    eval $cmd
}

# Set eval($1$2)=$2. Until bash has associative arrays,
# this is how we simulate such a datatype. In Perl this would be
# $1{$2}=$3.

function _Dbg_set_assoc_scalar_entry {
  typeset prefix=$1
  typeset entry=$2
  typeset value=$3
  typeset cmd="${prefix}${entry}=$value"
  eval $cmd

  typeset dq_value=$(_Dbg_esc_dq "$value")
  _Dbg_write_journal "${prefix}${entry}=\"$dq_value\""

}

# Return value of eval($1[$2]). If $2 is omitted, use _curline.  Until
# bash has associative arrays which can contain array elements this is
# how we simulate such a datatype.

function _Dbg_get_assoc_array_entry {
  typeset prefix=$1
  typeset lineno=${2:-$_curline}

  [[ -z $prefix ]] && _Dbg_msg "Internal debug error (gae) bad prefix"
  typeset entry="$prefix[$lineno]"
  typeset cmd="echo \"\${$entry}\""
  eval $cmd
}

# Evaluate eval($1[$2]=$3). If $2 is omitted, use _curline.  Until
# bash has associative arrays cich can contain array elements this is
# how we simulate such a datatype.

function _Dbg_set_assoc_array_entry {
  typeset prefix=$1
  typeset lineno=$2
  shift; shift
  typeset value=$*
  
  [[ -z "$prefix" ]] && _Dbg_msg "Internal debug error (sae1) bad prefix"
  [[ -z "$lineno" ]] && _Dbg_msg "Internal debug error (sae2) bad lineno"
  [[ -z "$value" ]] && _Dbg_msg "Internal debug error (sae3) bad value"

  typeset entry="$prefix[$lineno]"
  typeset cmd="$entry=\"$value\""
  eval $cmd

  typeset dq_value=$(_Dbg_esc_dq "$value")
  _Dbg_write_journal "$entry=\"$dq_value\""
}

# _get_function echoes a list of all of the functions.
# if $1 is nonzero, system functions, i.e. those whose name starts with
# an underscore (_), are included in the search.
# FIXME add parameter search pattern.
_Dbg_get_functions() {
    typeset -i include_system=${1:-0}
    typeset    pat=${2:-*}
    typeset -a fns_a
    fns_a=( $(declare -F) )
    typeset -a ret_fns=()
    typeset -i i
    typeset -i invert=0;

    if [[ $pat == !* ]] ; then 
	# Remove leading !
	pat=#{$pat#!}
	invert=1
    fi	

    # Iterate skipping over consecutive single tokens "declare" and "-F"
    for (( i=2; (( i < ${#fns_a[@]} )) ; i += 3 )) ; do
	typeset fn="${fns_a[$i]}"
	[[ $fn == _* ]] && (( ! $include_system )) && continue
	if [[ $fn == $pat ]] ; then 
	     [[ $invert == 0 ]] && ret_fns[${#ret_fns[@]}]=$fn
	else
	     [[ $invert != 0 ]] && ret_fns[${#ret_fns[@]}]=$fn
	fi

    done
    echo ${ret_fns[@]}
}

# _Dbg_is_function returns 0 if $1 is a defined function or nonzero otherwise. 
# if $2 is nonzero, system functions, i.e. those whose name starts with
# an underscore (_), are included in the search.
_Dbg_is_function() {
    (( 0 == $# )) && return 1
    typeset needed_fn=$1
    typeset -i include_system=${2:-0}
    [[ ${needed_fn:0:1} == '_' ]] && ((!include_system)) && {
	return 1
    }
    declare -F $needed_fn >/dev/null 2>&1
    return $?
}

# Return 0 if set -x tracing is on
_Dbg_is_traced() {
    # Is "x" in set options? 
    if [[ $- == *x* ]] ; then
	return 0
    else
	return 1
    fi
}

# Common routine for setup of commands that take a single
# linespec argument. We assume the following variables 
# which we store into:
#  filename, line_number, full_filename

function _Dbg_linespec_setup {
  typeset linespec=${1:-''}
  if [[ -z $linespec ]] ; then
    _Dbg_errmsg "Invalid line specification, null given"
  fi
  typeset -a word
  eval "word=($(_Dbg_parse_linespec $linespec))"
  if [[ ${#word[@]} == 0 ]] ; then
    _Dbg_errmsg "Invalid line specification: $linespec"
    return
  fi
  
  filename="${word[2]}"
  typeset -ir is_function=${word[1]}
  line_number=${word[0]}
  full_filename=$(_Dbg_is_file "$filename")

  if (( is_function )) ; then
      if [[ -z $full_filename ]] ; then 
	  _Dbg_readin "$filename"
	  full_filename=$(_Dbg_is_file "$filename")
      fi
  fi
}

# Parse linespec in $1 which should be one of
#   int
#   file:line
#   function-num
# Return triple (line,  is-function?, filename,)
# We return the filename last since that can have embedded blanks.
function _Dbg_parse_linespec {
  typeset linespec=$1
  eval "$_seteglob"
  case "$linespec" in

    # line number only - use _Dbg_frame_last_filename for filename
    $int_pat )	
      echo "$linespec 0 \"$_Dbg_frame_last_filename\""
      ;;
    
    # file:line
    [^:][^:]*[:]$int_pat )
      # Split the POSIX way
      typeset line_word=${linespec##*:}
      typeset file_word=${linespec%${line_word}}
      file_word=${file_word%?}
      echo "$line_word 0 \"$file_word\""
      ;;

    # Function name or error
    * )
      if _Dbg_is_function $linespec $_Dbg_debug_debugger ; then 
	local -a word=( $(declare -F $linespec) )
	if [[ $? && ${#word[@]} > 2 ]]; then 
	  builtin echo "${word[1]} 1 ${word[2]}"
	else
	  builtin echo ''
	fi
      else  
	builtin echo ''
      fi
      ;;
   esac
}

# usage _Dbg_set_ftrace [-u] funcname [funcname...]
# Sets or unsets a function for stopping by setting 
# the -t or +t property to the function declaration.
#
function _Dbg_set_ftrace {
  typeset opt=-t tmsg="enabled" func 
  if [[ $1 == -u ]]; then
	opt=+t
	tmsg="disabled"
	shift
  fi
  for func; do
	  declare -f $opt $func
	  # _Dbg_msg "Tracing $tmsg for function $func"
  done
}

# This is put at the end so we have something at the end when we debug this.
[[ -z $_Dbg_fns_ver ]] && typeset -r _Dbg_fns_ver=\
'$Id: fns.sh,v 1.8 2008/10/18 10:27:16 rockyb Exp $'