diff options
| author | Chet Ramey <chet.ramey@case.edu> | 2011-12-07 09:10:14 -0500 |
|---|---|---|
| committer | Chet Ramey <chet.ramey@case.edu> | 2011-12-07 09:10:14 -0500 |
| commit | 70694d2e64454909085315102edd4cb09509bef6 (patch) | |
| tree | 4120893d621a787bdc47c7223288978e6aacee50 | |
| parent | 234d8729630122c9bac113ed19bd196912c72a1e (diff) | |
| download | bash-70694d2e64454909085315102edd4cb09509bef6.tar.gz | |
commit bash-20070712 snapshot
| -rw-r--r-- | CWRU/CWRU.chlog | 25 | ||||
| -rw-r--r-- | CWRU/CWRU.chlog~ | 23 | ||||
| -rw-r--r-- | MANIFEST | 10 | ||||
| -rw-r--r-- | examples/INDEX.html | 8 | ||||
| -rw-r--r-- | examples/INDEX.txt | 4 | ||||
| -rw-r--r-- | examples/obashdb/README | 15 | ||||
| -rwxr-xr-x[-rw-r--r--] | examples/obashdb/bashdb | 596 | ||||
| -rw-r--r-- | examples/obashdb/bashdb.el | 177 | ||||
| -rw-r--r-- | examples/obashdb/bashdb.vaughan | 561 | ||||
| -rw-r--r-- | lib/readline/display.c | 4 | ||||
| -rw-r--r-- | lib/readline/display.c~ | 12 | ||||
| -rw-r--r-- | lib/readline/rltty.c | 2 | ||||
| -rw-r--r-- | lib/sh/getcwd.c | 4 | ||||
| -rw-r--r-- | lib/sh/getcwd.c~ | 313 | ||||
| -rw-r--r-- | variables.c | 12 | ||||
| -rw-r--r-- | variables.c~ | 8 |
16 files changed, 1705 insertions, 69 deletions
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 2e7f5c15..be430f41 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -14759,3 +14759,28 @@ lib/readline/display.c second line and the redisplay draws the invisible character. Fixes redisplay bug reported by Andreas Schwab <schwab@suse.de> + + 7/11 + ---- + +lib/readline/rltty.c + - enable flush-output code for systems other than AIX 4.1. Problem + reported by Jan Kratochvil <jan.kratochvil@redhat.com> + + 7/12 + ---- +lib/readline/display.c + - set prompt_invis_chars_first_line from the portion of the prompt + following the final newline, instead of from the prefix. Fixes + bug reported on the Ubuntu bug list by dAniel hAhler + <ubuntu@thequod.de> + + 7/13 + ---- +variables.c + - use native __QNX__ and __QNXNTO__ cpp defines instead of qnx and + qnx6, respectively. Patch from Sean Boudreau <seanb@qnx.com> + +lib/sh/getcwd.c + - #undef HAVE_LSTAT on qnx, so it uses stat instead. Patch from + Sean Boudreau <seanb@qnx.com> diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 45392150..84ca7910 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -14757,5 +14757,26 @@ lib/readline/display.c - change _rl_move_cursor_relative to adjust _rl_last_c_pos in a multibyte environment when the prompt has invisible chars on the second line and the redisplay draws the invisible character. Fixes - bug reported by Andreas Schwab <schwab@suse.de> + redisplay bug reported by Andreas Schwab <schwab@suse.de> + + 7/11 + ---- + +lib/readline/rltty.c + - enable flush-output code for systems other than AIX 4.1. Problem + reported by Jan Kratochvil <jan.kratochvil@redhat.com> + + 7/12 + ---- +lib/readline/display.c + - set prompt_invis_chars_first_line from the portion of the prompt + following the final newline, instead of from the prefix. Fixes + bug reported on the Ubuntu bug list by dAniel hAhler + <ubuntu@thequod.de> + + 7/13 + ---- +variables.c + - use native __QNX__ and __QNXNTO__ cpp defines instead of qnx and + qnx6, respectively. Patch from Sean Boudreau <seanb@qnx.com> @@ -10,7 +10,6 @@ builtins d cross-build d doc d examples d -examples/bashdb d examples/obashdb d examples/complete d examples/functions d @@ -535,15 +534,10 @@ support/shobj-conf f 755 support/rlvers.sh f 755 examples/INDEX.txt f examples/INDEX.html f -examples/bashdb/PERMISSION f -examples/bashdb/README f -examples/bashdb/bashdb f -examples/bashdb/bashdb.el f examples/obashdb/PERMISSION f examples/obashdb/README f -examples/obashdb/bashdb f -examples/obashdb/bashdb.fns f -examples/obashdb/bashdb.pre f +examples/obashdb/bashdb f +examples/obashdb/bashdb.el f examples/complete/complete-examples f examples/complete/complete.ianmac f examples/complete/complete2.ianmac f diff --git a/examples/INDEX.html b/examples/INDEX.html index c3ba24d7..150701ca 100644 --- a/examples/INDEX.html +++ b/examples/INDEX.html @@ -5,7 +5,7 @@ <th>X-Ref</th> </tr> <tr> - <td>./bashdb</td> + <td>./obashdb</td> <td>Deprecated sample implementation of a bash debugger</td> </tr> <tr> @@ -437,12 +437,6 @@ <tr> </tr> <tr> - <td>./obashdb</td> - <td>Modified version of the Korn Shell debugger from Bill Rosenblatt's 'Learning the Korn Shell'.</td> - </tr> - <tr> - </tr> - <tr> <td>./scripts.noah</td> <td>Noah Friedman's collection of scripts (updated to bash v2 syntax by Chet Ramey)</td> </tr> diff --git a/examples/INDEX.txt b/examples/INDEX.txt index 1be1cc63..ab69e6cb 100644 --- a/examples/INDEX.txt +++ b/examples/INDEX.txt @@ -1,5 +1,5 @@ Path Description X-Ref -./bashdb Deprecated sample implementation of a bash debugger +./obashdb Deprecated sample implementation of a bash debugger ./complete Shell completion code @@ -103,8 +103,6 @@ Path Description X-Ref ./misc/README README ./misc/suncmd.termcap SunView TERMCAP string. -./obashdb Modified version of the Korn Shell debugger from Bill Rosenblatt's 'Learning the Korn Shell'. - ./scripts.noah Noah Friedman's collection of scripts (updated to bash v2 syntax by Chet Ramey) ./scripts.noah/aref.bash Pseudo-arrays and substring indexing examples. ./scripts.noah/bash.sub.bash Library functions used by require.bash. diff --git a/examples/obashdb/README b/examples/obashdb/README index 3373f5f8..2f643d19 100644 --- a/examples/obashdb/README +++ b/examples/obashdb/README @@ -1,12 +1,3 @@ -This is a modified version of the Korn Shell debugger from Bill -Rosenblatt's `Learning the Korn Shell', published by O'Reilly -and Associates (ISBN 1-56592-054-6). - -The original `kshdb' is available for anonymous FTP with the URL - -http://examples.oreilly.com/korn/ksh.tar.Z - -A revised edition is available at: - -http://examples.oreilly.com/korn2/korn2_examples.tar.gz - +This is a sample implementation of a bash debugger. It is not the same +as the project available from http://bashdb.sourceforge.net, and has been +deprecated in favor of that implementation. diff --git a/examples/obashdb/bashdb b/examples/obashdb/bashdb index 97d287dd..560cb7cc 100644..100755 --- a/examples/obashdb/bashdb +++ b/examples/obashdb/bashdb @@ -1,33 +1,581 @@ -# kshdb - Korn Shell Debugger main file -# adapted from 'Learning the Korn Shell' by Bill Rosenblatt (O'Reilly) -# by Cigy Cyriac (cigy@felix.tulblr.unisys.com) -# Main driver: constructs full script (with preamble) and runs it +#! /bin/bash +# bashdb - Bash shell debugger +# +# Adapted from an idea in O'Reilly's `Learning the Korn Shell' +# Copyright (C) 1993-1994 O'Reilly and Associates, Inc. +# Copyright (C) 1998, 1999, 2001 Gary V. Vaughan <gvv@techie.com>> +# +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. -echo 'Bourne-Again Shell Debugger version 0.1' +# NOTE: +# +# This program requires bash 2.x. +# If bash 2.x is installed as "bash2", you can invoke bashdb like this: +# +# DEBUG_SHELL=/bin/bash2 /bin/bash2 bashdb script.sh -_pname=${0##*/} +# TODO: +# +# break [regexp] +# cond [break] [condition] +# tbreak [regexp|+lines] +# restart +# Variable watchpoints +# Instrument `source' and `.' files in $_potbelliedpig +# be cleverer about lines we allow breakpoints to be set on +# break [function_name] -[ $# -eq 0 ] && { - echo "${_pname}: usage: ${_pname} <script_file>" - exit 1 -} +echo 'Bash Debugger version 1.2.4' + +export _dbname=${0##*/} + +if test $# -lt 1; then + echo "$_dbname: Usage: $_dbname filename" >&2 + exit 1 +fi _guineapig=$1 -[ -r $_guineapig ] || { - echo "${_pname}: cannot read $_guineapig." >&2 - exit 1 -} +if test ! -r $1; then + echo "$_dbname: Cannot read file '$_guineapig'." >&2 + exit 1 +fi + shift -_tmpdir=/tmp -_libdir=. -_dbgfile=$_tmpdir/bashdb$$ #temp file for script being debugged +__debug=${TMPDIR-/tmp}/bashdb.$$ +sed -e '/^# bashdb - Bash shell debugger/,/^# -- DO NOT DELETE THIS LINE -- /d' "$0" > $__debug +cat $_guineapig >> $__debug +exec ${DEBUG_SHELL-bash} $__debug $_guineapig "$@" -cat $_libdir/bashdb.pre $_guineapig > $_dbgfile -if [ -f "$BASH" ]; then - exec $BASH $_dbgfile $_guineapig $_tmpdir $_libdir "$@" -else - exec bash $_dbgfile $_guineapig $_tmpdir $_libdir "$@" -fi -# end of bashdb +exit 1 + +# -- DO NOT DELETE THIS LINE -- The program depends on it + +#bashdb preamble +# $1 name of the original guinea pig script + +__debug=$0 +_guineapig=$1 +__steptrap_calls=0 + +shift + +shopt -s extglob # turn on extglob so we can parse the debugger funcs + +function _steptrap +{ + local i=0 + + _curline=$1 + + if (( ++__steptrap_calls > 1 && $_curline == 1 )); then + return + fi + + if [ -n "$_disps" ]; then + while (( $i < ${#_disps[@]} )) + do + if [ -n "${_disps[$i]}" ]; then + _msg "${_disps[$i]}: \c" + eval _msg ${_disps[$i]} + fi + let i=$i+1 + done + fi + + if (( $_trace )); then + _showline $_curline + fi + + if (( $_steps >= 0 )); then + let _steps="$_steps - 1" + fi + + if _at_linenumbp ; then + _msg "Reached breakpoint at line $_curline" + _showline $_curline + _cmdloop + elif [ -n "$_brcond" ] && eval $_brcond; then + _msg "Break condition $_brcond true at line $_curline" + _showline $_curline + _cmdloop + elif (( $_steps == 0 )); then + # Assuming a real script will have the "#! /bin/sh" at line 1, + # assume that when $_curline == 1 we are inside backticks. + if (( ! $_trace )); then + _msg "Stopped at line $_curline" + _showline $_curline + fi + _cmdloop + fi +} + +function _setbp +{ + local i f line _x + + if [ -z "$1" ]; then + _listbp + return + fi + + eval "$_seteglob" + + if [[ $1 == *(\+)[1-9]*([0-9]) ]]; then + case $1 in + +*) + # normalize argument, then double it (+2 -> +2 + 2 = 4) + _x=${1##*([!1-9])} # cut off non-numeric prefix + _x=${x%%*([!0-9])} # cut off non-numeric suffix + f=$(( $1 + $_x )) + ;; + *) + f=$(( $1 )) + ;; + esac + + # find the next valid line + line="${_lines[$f]}" + while _invalidbreakp $f + do + (( f++ )) + line="${_lines[$f]}" + done + + if (( $f != $1 )) + then + _msg "Line $1 is not a valid breakpoint" + fi + + if [ -n "${_lines[$f]}" ]; then + _linebp[$1]=$1; + _msg "Breakpoint set at line $f" + else + _msg "Breakpoints can only be set on executable lines" + fi + else + _msg "Please specify a numeric line number" + fi + + eval "$_resteglob" +} + +function _listbp +{ + local i + + if [ -n "$_linebp" ]; then + _msg "Breakpoints:" + for i in ${_linebp[*]}; do + _showline $i + done + else + _msg "No breakpoints have been set" + fi +} + +function _clearbp +{ + local i + + if [ -z "$1" ]; then + read -e -p "Delete all breakpoints? " + case $REPLY in + [yY]*) + unset _linebp[*] + _msg "All breakpoints have been cleared" + ;; + esac + return 0 + fi + + eval "$_seteglob" + + if [[ $1 == [1-9]*([0-9]) ]]; then + unset _linebp[$1] + _msg "Breakpoint cleared at line $1" + else + _msg "Please specify a numeric line number" + fi + + eval "$_resteglob" +} + +function _setbc +{ + if (( $# > 0 )); then + _brcond=$@ + _msg "Break when true: $_brcond" + else + _brcond= + _msg "Break condition cleared" + fi +} + +function _setdisp +{ + if [ -z "$1" ]; then + _listdisp + else + _disps[${#_disps[@]}]="$1" + if (( ${#_disps[@]} < 10 )) + then + _msg " ${#_disps[@]}: $1" + else + _msg "${#_disps[@]}: $1" + fi + fi +} + +function _listdisp +{ + local i=0 j + + if [ -n "$_disps" ]; then + while (( $i < ${#_disps[@]} )) + do + let j=$i+1 + if (( ${#_disps[@]} < 10 )) + then + _msg " $j: ${_disps[$i]}" + else + _msg "$j: ${_disps[$i]}" + fi + let i=$j + done + else + _msg "No displays have been set" + fi +} + +function _cleardisp +{ + if (( $# < 1 )) ; then + read -e -p "Delete all display expressions? " + case $REPLY in + [Yy]*) + unset _disps[*] + _msg "All breakpoints have been cleared" + ;; + esac + return 0 + fi + + eval "$_seteglob" + + if [[ $1 == [1-9]*([0-9]) ]]; then + unset _disps[$1] + _msg "Display $i has been cleared" + else + _listdisp + _msg "Please specify a numeric display number" + fi + + eval "$_resteglob" +} + +# usage _ftrace -u funcname [funcname...] +function _ftrace +{ + local _opt=-t _tmsg="enabled" _func + if [[ $1 == -u ]]; then + _opt=+t + _tmsg="disabled" + shift + fi + for _func; do + declare -f $_opt $_func + _msg "Tracing $_tmsg for function $_func" + done +} + +function _cmdloop +{ + local cmd args + + while read -e -p "bashdb> " cmd args; do + test -n "$cmd" && history -s "$cmd $args" # save on history list + test -n "$cmd" || { set $_lastcmd; cmd=$1; shift; args=$*; } + if [ -n "$cmd" ] + then + case $cmd in + b|br|bre|brea|break) + _setbp $args + _lastcmd="break $args" + ;; + co|con) + _msg "ambiguous command: '$cmd', condition, continue?" + ;; + cond|condi|condit|conditi|conditio|condition) + _setbc $args + _lastcmd="condition $args" + ;; + c|cont|conti|contin|continu|continue) + _lastcmd="continue" + return + ;; + d) + _msg "ambiguous command: '$cmd', delete, display?" + ;; + de|del|dele|delet|delete) + _clearbp $args + _lastcmd="delete $args" + ;; + di|dis|disp|displ|displa|display) + _setdisp $args + _lastcmd="display $args" + ;; + f|ft|ftr|ftra|ftrace) + _ftrace $args + _lastcmd="ftrace $args" + ;; + \?|h|he|hel|help) + _menu + _lastcmd="help" + ;; + l|li|lis|list) + _displayscript $args + # _lastcmd is set in the _displayscript function + ;; + p|pr|pri|prin|print) + _examine $args + _lastcmd="print $args" + ;; + q|qu|qui|quit) + exit + ;; + s|st|ste|step|n|ne|nex|next) + let _steps=${args:-1} + _lastcmd="next $args" + return + ;; + t|tr|tra|trac|trace) + _xtrace + ;; + u|un|und|undi|undis|undisp|undispl|undispla|undisplay) + _cleardisp $args + _lastcmd="undisplay $args" + ;; + !*) + eval ${cmd#!} $args + _lastcmd="$cmd $args" + ;; + *) + _msg "Invalid command: '$cmd'" + ;; + esac + fi + done +} + +function _at_linenumbp +{ + [[ -n ${_linebp[$_curline]} ]] +} + +function _invalidbreakp +{ + local line=${_lines[$1]} + + # XXX - should use shell patterns + if test -z "$line" \ + || expr "$line" : '[ \t]*#.*' > /dev/null \ + || expr "$line" : '[ \t]*;;[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*;;[ \t]*#.**$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*;;[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*;;*[ \t]*#.*$' > /dev/null + then + return 0 + fi + + return 1 +} + +function _examine +{ + if [ -n "$*" ]; then + _msg "$args: \c" + eval _msg $args + else + _msg "Nothing to print" + fi +} + +function _displayscript +{ + local i j start end bp cl + + if (( $# == 1 )); then # list 5 lines on either side of $1 + if [ $1 = "%" ]; then + let start=1 + let end=${#_lines[@]} + else + let start=$1-5 + let end=$1+5 + fi + elif (( $# > 1 )); then # list between start and end + if [ $1 = "^" ]; then + let start=1 + else + let start=$1 + fi + + if [ $2 = "\$" ]; then + let end=${#_lines[@]} + else + let end=$2 + fi + else # list 5 lines on either side of current line + let start=$_curline-5 + let end=$_curline+5 + fi + + # normalize start and end + if (( $start < 1 )); then + start=1 + fi + if (( $end > ${#_lines[@]} )); then + end=${#_lines[@]} + fi + + cl=$(( $end - $start )) + if (( $cl > ${LINES-24} )); then + pager=${PAGER-more} + else + pager=cat + fi + + i=$start + ( while (( $i <= $end )); do + _showline $i + let i=$i+1 + done ) 2>&1 | $pager + + # calculate the next block of lines + start=$(( $end + 1 )) + end=$(( $start + 11 )) + if (( $end > ${#_lines[@]} )) + then + end=${#_lines[@]} + fi + + _lastcmd="list $start $end" +} + +function _xtrace +{ + let _trace="! $_trace" + if (( $_trace )); then + _msg "Execution trace on" + else + _msg "Execution trace off" + fi +} + +function _msg +{ + echo -e "$@" >&2 +} + +function _showline +{ + local i=0 bp=' ' line=$1 cl=' ' + + if [[ -n ${_linebp[$line]} ]]; then + bp='*' + fi + + if (( $_curline == $line )); then + cl=">" + fi + + if (( $line < 100 )); then + _msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}" + elif (( $line < 10 )); then + _msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}" + elif (( $line > 0 )); then + _msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}" + fi +} + +function _cleanup +{ + rm -f $__debug $_potbelliedpig 2> /dev/null +} + +function _menu +{ + _msg 'bashdb commands: + break N set breakpoint at line N + break list breakpoints & break condition + condition foo set break condition to foo + condition clear break condition + delete N clear breakpoint at line N + delete clear all breakpoints + display EXP evaluate and display EXP for each debug step + display show a list of display expressions + undisplay N remove display expression N + list N M display all lines of script between N and M + list N display 5 lines of script either side of line N + list display 5 lines if script either side of current line + continue continue execution upto next breakpoint + next [N] execute [N] statements (default 1) + print expr prints the value of an expression + trace toggle execution trace on/off + ftrace [-u] func make the debugger step into function FUNC + (-u turns off tracing FUNC) + help print this menu + ! string passes string to a shell + quit quit' +} + +shopt -u extglob + +HISTFILE=~/.bashdb_history +set -o history +set +H + +# strings to save and restore the setting of `extglob' in debugger functions +# that need it +_seteglob='local __eopt=-u ; shopt -q extglob && __eopt=-s ; shopt -s extglob' +_resteglob='shopt $__eopt extglob' + +_linebp=() +let _trace=0 +let _i=1 + +# Be careful about quoted newlines +_potbelliedpig=${TMPDIR-/tmp}/${_guineapig/*\//}.$$ +sed 's,\\$,\\\\,' $_guineapig > $_potbelliedpig + +_msg "Reading source from file: $_guineapig" +while read; do + _lines[$_i]=$REPLY + let _i=$_i+1 +done < $_potbelliedpig + +trap _cleanup EXIT +# Assuming a real script will have the "#! /bin/sh" at line 1, +# don't stop at line 1 on the first run +let _steps=1 +LINENO=-1 +trap '_steptrap $LINENO' DEBUG diff --git a/examples/obashdb/bashdb.el b/examples/obashdb/bashdb.el new file mode 100644 index 00000000..40584dd2 --- /dev/null +++ b/examples/obashdb/bashdb.el @@ -0,0 +1,177 @@ +;;; bashdb.el --- Grand Unified Debugger mode for running bashdb +;; Copyright (C) 2000, 2001 Masatake YAMATO + +;; Author: Masatake YAMATO <jet@gyve.org> + +;; This program 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 of the License, or +;; (at your option) any later version. + +;; This program 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 this program; if not, write to the Free Software Foundation, +;; Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +;; Commentary: +;; This program may run on Emacs 21.0.91 and XEmacs 21.1. +;; +;; Put +;; (autoload 'bashdb "bashdb" "Run bashdb" t nil) +;; to your .emacs. +;; M-x bashdb +;; Run bashdb (like this): bashdb target.sh +;; +;; About bashdb: +;; You can get bashdb from +;; http://www.oranda.demon.co.uk/development.html +;; +;; bashdb.el is based on perldb in gud.el in XEmacs 21.1. + +;; Revision: +;; $Revision: 1.6 $ +;; $Log: bashdb.el,v $ +;; Revision 1.6 2001/01/06 12:18:06 masata-y +;; Write note about XEmacs. +;; +;; + + +;;; Code: +(require 'gud) + +;; User customizable variable +(defcustom gud-bashdb-command-name "bashdb" + "File name for executing Bashdb." + :type 'string + :group 'gud) + +;; History of argument lists passed to bashdb. +(defvar gud-bashdb-history nil) + +(defun gud-bashdb-massage-args (file args) + (if xemacsp + (cons (file-name-nondirectory file) args) + args)) + +;; There's no guarantee that Emacs will hand the filter the entire +;; marker at once; it could be broken up across several strings. We +;; might even receive a big chunk with several markers in it. If we +;; receive a chunk of text which looks like it might contain the +;; beginning of a marker, we save it here between calls to the +;; filter. +(if xemacsp + (defvar gud-bashdb-marker-acc "")) +(defun gud-bashdb-marker-acc () + (if xemacsp + gud-bashdb-marker-acc + gud-marker-acc)) +(defun gud-bashdb-marker-acc-quote () + (if xemacsp + 'gud-bashdb-marker-acc + 'gud-marker-acc)) + +(defun gud-bashdb-marker-filter (string) + (save-match-data + (set (gud-bashdb-marker-acc-quote) + (concat (gud-bashdb-marker-acc) string)) + (let ((output "")) + ;; Process all the complete markers in this chunk. + (while (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>.*\n" + (gud-bashdb-marker-acc)) + (setq + ;; Extract the frame position from the marker. + gud-last-frame (cons + (substring (gud-bashdb-marker-acc) + (match-beginning 1) + (match-end 1)) + (string-to-int + (substring (gud-bashdb-marker-acc) + (match-beginning 2) + (match-end 2)))) + ;; Append any text before the marker to the output we're going + ;; to return - we don't include the marker in this text. + output (concat output + (substring (gud-bashdb-marker-acc) 0 (match-beginning 0)))) + ;; Set the accumulator to the remaining text. + (set + (gud-bashdb-marker-acc-quote) (substring + (gud-bashdb-marker-acc) (match-end 0)))) + + ;; Does the remaining text look like it might end with the + ;; beginning of another marker? If it does, then keep it in + ;; (gud-bashdb-marker-acc) until we receive the rest of it. Since we + ;; know the full marker regexp above failed, it's pretty simple to + ;; test for marker starts. + (if (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>" (gud-bashdb-marker-acc)) + (progn + ;; Everything before the potential marker start can be output. + (setq output (concat output (substring (gud-bashdb-marker-acc) + 0 (match-beginning 0)))) + ;; Everything after, we save, to combine with later input. + (set (gud-bashdb-marker-acc-quote) + (substring (gud-bashdb-marker-acc) (match-beginning 0)))) + + (setq output (concat output (gud-bashdb-marker-acc))) + (set (gud-bashdb-marker-acc-quote) "")) + + output))) + +(defun gud-bashdb-find-file (f) + (find-file-noselect f)) + +;;;###autoload +(defun bashdb (command-line) + "Run bashdb on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger." + (interactive + (if xemacsp + (list (read-from-minibuffer "Run bashdb (like this): " + (if (consp gud-bashdb-history) + (car gud-bashdb-history) + (format "%s " gud-bashdb-command-name)) + nil nil + '(gud-bashdb-history . 1))) + (list (gud-query-cmdline 'bashdb)) + )) + + (if xemacsp + (progn + (gud-overload-functions '((gud-massage-args . gud-bashdb-massage-args) + (gud-marker-filter . gud-bashdb-marker-filter) + (gud-find-file . gud-bashdb-find-file))) + (gud-common-init command-line gud-bashdb-command-name)) + (gud-common-init command-line 'gud-bashdb-massage-args + 'gud-bashdb-marker-filter 'gud-bashdb-find-file) + (set (make-local-variable 'gud-minor-mode) 'bashdb)) + +;; Unsupported commands +;; condition foo set break condition to foo +;; condition clear break condition +;; display EXP evaluate and display EXP for each debug step +;; display show a list of display expressions +;; undisplay N remove display expression N +;; ! string passes string to a shell +;; quit quit + + (gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.") + (gud-def gud-list-break "break" "b" "List breakpoints & break condition.") + (gud-def gud-remove "delete %l" "\C-d" "Remove breakpoint at current line") + (gud-def gud-remove-all "delete" "d" "Clear all breakpoints") + (gud-def gud-cont "continue" "\C-r" "Continue with display.") + (gud-def gud-next "next" "\C-n" "Step one line (skip functions).") + (gud-def gud-print "print %e" "\C-p" "Evaluate bash expression at point.") + (gud-def gud-help "help" "h" "Show all commands.") + (gud-def gud-trace "trace" "t" "Toggle execution trace on/off") + + (setq comint-prompt-regexp "^bashdb> ") + (setq paragraph-start comint-prompt-regexp) + (run-hooks 'bashdb-mode-hook)) + +(provide 'bashdb) +;; bashdb.el ends here diff --git a/examples/obashdb/bashdb.vaughan b/examples/obashdb/bashdb.vaughan new file mode 100644 index 00000000..6a24973e --- /dev/null +++ b/examples/obashdb/bashdb.vaughan @@ -0,0 +1,561 @@ +#! /bin/bash +# bashdb - Bash shell debugger +# +# Adapted from an idea in O'Reilly's `Learning the Korn Shell' +# Copyright (C) 1993-1994 O'Reilly and Associates, Inc. +# Copyright (C) 1998, 1999, 2001 Gary V. Vaughan <gvv@techie.com>> +# +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# NOTE: +# +# This program requires bash 2.x. +# If bash 2.x is installed as "bash2", you can invoke bashdb like this: +# +# DEBUG_SHELL=/bin/bash2 /bin/bash2 bashdb script.sh + +# TODO: +# +# break [regexp] +# cond [break] [condition] +# tbreak [regexp|+lines] +# restart +# Variable watchpoints +# Output colourization +# History with csh ^ substitution? Or write a readline frontend? +# Instrument shell functions with the _steptrap in $_potbelliedpig +# Instrument `source' and `.' files in $_potbelliedpig +# be cleverer about lines we allow breakpoints to be set on +# break [function_name] + + +echo 'Bash Debugger version 1.2.4' + +export _dbname=$(echo "X$0"|sed -e 's,^X,,' -e 's,^.*/,,') + +if test $# -lt 1; then + echo "$_dbname: Usage: $_dbname <filename>" >&2 + exit 1 +fi + +_guineapig=$1 + +if test ! -r $1; then + echo "$_dbname: Cannot read file '$_guineapig'." >&2 + exit 1 +fi + +shift + +__debug=${TMPDIR-/tmp}/bashdb.$$ +sed -e '/^# bashdb - Bash shell debugger/,/^# -- DO NOT DELETE THIS LINE -- /d' "$0" > $__debug +cat $_guineapig >> $__debug +exec ${DEBUG_SHELL-bash} $__debug $_guineapig "$@" + +exit 1 + +# -- DO NOT DELETE THIS LINE -- The program depends on it + +#bashdb preamble +# $1 name of the original guinea pig script + +__debug=$0 +_guineapig=$1 + +shift + +function _steptrap +{ + local i=0 + + _curline=$1 + + if [ -n "$_disps" ] + then + while (( $i < ${#_disps[@]} )) + do + if [ -n "${_disps[$i]}" ] + then + _msg "${_disps[$i]}: \c" + eval _msg ${_disps[$i]} + fi + let i=$i+1 + done + fi + + if (( $_trace )); then + _showline $_curline + fi + + if (( $_steps >= 0 )); then + let _steps="$_steps - 1" + fi + + if _at_linenumbp ; then + _msg "Reached breakpoint at line $_curline" + _showline $_curline + _cmdloop + elif [ -n "$_brcond" ] && eval $_brcond; then + _msg "Break condition $_brcond true at line $_curline" + _showline $_curline + _cmdloop + elif (( $_steps == 0 && $_curline > 1)); then + # Assuming a real script will have the "#! /bin/sh" at line 1, + # assume that when $_curline == 1 we are inside backticks. + if (( ! $_trace )); then + _msg "Stopped at line $_curline" + _showline $_curline + fi + _cmdloop + fi +} + +function _setbp +{ + local i f line + + if [ -z "$1" ] + then + _listbp + elif [ $(echo $1 | grep '^\+*[1-9][0-9]*') ] + then + case $1 in + +*) + let f="$1 + `expr $1 : '+*\([1-9][0-9]*\)'`" + ;; + *) + let f=$1 + ;; + esac + + # find the next valid line + line="${_lines[$f]}" + while _invalidbreakp $f + do + let f="$f + 1" + line="${_lines[$f]}" + done + + if (( $f != $1 )) + then + _msg "Line $1 is not a valid breakpoint" + fi + + if [ -n "${_lines[$f]}" ] + then + _linebp=($(echo $( (for i in ${_linebp[*]} $1; do + echo $i; done) | sort -n) )) + _msg "Breakpoint set at line $f" + else + _msg "Breakpoints can only be set on executable lines" + fi + else + _msg "Please specify a numeric line number" + fi +} + +function _listbp +{ + local i + + if [ -n "$_linebp" ] + then + _msg "Breakpoints:" + for i in ${_linebp[*]}; do + _showline $i + done + else + _msg "No breakpoints have been set" + fi +} + +function _clearbp +{ + local i + if [ -z "$1" ]; then + read -e -p "Delete all breakpoints? " + case $REPLY in + y*) + unset _linebp[*] + _msg "All breakpoints have been cleared" + ;; + esac + elif [ $(echo $1 | grep '^[0-9]*') ]; then + _linebp=($(echo $(for i in ${_linebp[*]}; do + if (( $1 != $i )); then echo $1; fi; done) )) + _msg "Breakpoint cleared at line $1" + else + _msg "Please specify a numeric line number" + fi +} + +function _setbc +{ + if [ -n "$*" ] + then + _brcond=$args + _msg "Break when true: $_brcond" + else + _brcond= + _msg "Break condition cleared" + fi +} + +function _setdisp +{ + if [ -z "$1" ] + then + _listdisp + else + _disps[${#_disps[@]}]="$1" + if (( ${#_disps[@]} < 10 )) + then + _msg " ${#_disps[@]}: $1" + else + _msg "${#_disps[@]}: $1" + fi + fi +} + +function _listdisp +{ + local i=0 j + + if [ -n "$_disps" ] + then + while (( $i < ${#_disps[@]} )) + do + let j=$i+1 + if (( ${#_disps[@]} < 10 )) + then + _msg " $j: ${_disps[$i]}" + else + _msg "$j: ${_disps[$i]}" + fi + let i=$j + done + else + _msg "No displays have been set" + fi +} + +function _cleardisp +{ + if (( $# < 1 )) + then + read -e -p "Delete all display expressions? " + case $REPLY in + y*) + unset _disps[*] + _msg "All breakpoints have been cleared" + ;; + esac + elif [ $(echo $1 | grep '^[0-9]*') ] + then + unset _disps[$1] + _msg "Display $i has been cleared" + else + _listdisp + _msg "Please specify a numeric display number" + fi +} + +function _cmdloop +{ + local cmd args + + while read -e -p "bashdb> " cmd args; do + test -n "$cmd" || { set $_lastcmd; cmd=$1; shift; args=$*; } + if [ -n "$cmd" ] + then + case $cmd in + b|br|bre|brea|break) + _setbp $args + _lastcmd="break $args" + ;; + co|con) + _msg "ambiguous command: '$cmd', condition, continue?" + ;; + cond|condi|condit|conditi|conditio|condition) + _setbc $args + _lastcmd="condition $args" + ;; + c|cont|conti|contin|continu|continue) + _lastcmd="continue" + return + ;; + d) + _msg "ambiguous command: '$cmd', delete, display?" + ;; + de|del|dele|delet|delete) + _clearbp $args + _lastcmd="delete $args" + ;; + di|dis|disp|displ|displa|display) + _setdisp $args + _lastcmd="display $args" + ;; + \?|h|he|hel|help) + _menu + _lastcmd="help" + ;; + l|li|lis|list) + _displayscript $args + # _lastcmd is set in the _displayscript function + ;; + p|pr|pri|prin|print) + _examine $args + _lastcmd="print $args" + ;; + q|qu|qui|quit) + exit + ;; + s|st|ste|step|n|ne|nex|next) + let _steps=${args:-1} + _lastcmd="next $args" + return + ;; + t|tr|tra|trac|trace) + _xtrace + ;; + u|un|und|undi|undis|undisp|undispl|undispla|undisplay) + _cleardisp $args + _lastcmd="undisplay $args" + ;; + !*) + eval ${cmd#!} $args + _lastcmd="$cmd $args" + ;; + *) + _msg "Invalid command: '$cmd'" + ;; + esac + fi + done +} + +function _at_linenumbp +{ + local i=0 + + if [ "$_linebp" ] + then + while (( $i < ${#_linebp[@]} )); do + if (( ${_linebp[$i]} == $_curline )); then + return 0 + fi + let i=$i+1 + done + fi + + return 1 +} + +function _invalidbreakp +{ + local line=${_lines[$1]} + + if test -z "$line" \ + || expr "$line" : '[ \t]*#.*' > /dev/null \ + || expr "$line" : '[ \t]*;;[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*;;[ \t]*#.**$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*;;[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*;;*[ \t]*#.*$' > /dev/null + then + return 0 + fi + + return 1 +} + +function _examine +{ + if [ -n "$*" ] + then + _msg "$args: \c" + eval _msg $args + else + _msg "Nothing to print" + fi +} + +function _displayscript +{ + local i j start end bp cl + + if (( $# == 1 )) + then + if test $1 = "%" + then + let start=1 + let end=${#_lines[@]} + else + let start=$1-5 + let end=$1+5 + fi + elif (( $# > 1 )) + then + if test $1 = "^" + then + let start=1 + else + let start=$1 + fi + + if test $2 = "\$" + then + let end=${#_lines[@]} + else + let end=$2 + fi + else + let start=$_curline-5 + let end=$_curline+5 + fi + + if (( $start < 1 )) + then + start=1 + fi + if (( $end > ${#_lines[@]} )) + then + end=${#_lines[@]} + fi + + let cl=$end-$start + if (( $cl > ${LINES-24} )) + then + pager=${PAGER-more} + else + pager=cat + fi + + i=$start + ( while (( $i <= $end )); do + _showline $i + let i=$i+1 + done ) 2>&1 | $pager + + # calculate the next block of lines + let start=$end+1 + let end=$start+11 + if (( $end > ${#_lines[@]} )) + then + end=${#_lines[@]} + fi + + _lastcmd="list $start $end" +} + +function _xtrace +{ + let _trace="! $_trace" + if (( $_trace )); then + _msg "Execution trace on" + else + _msg "Execution trace off" + fi +} + +function _msg +{ + echo -e "$@" >&2 +} + +function _showline +{ + local i=0 bp=' ' line=$1 + + while (( $i < ${#_linebp[@]} )) + do + if [ ${_linebp[$i]} ] && (( ${_linebp[$i]} == $line )) + then + bp='*' + fi + let i=$i+1 + done + + if (( $_curline == $line )); then + cl=">" + else + cl=" " + fi + + if (( $line < 100 )); then + _msg "$_guineapig:$line $bp $cl${_lines[$line]}" + elif (( $line < 10 )); then + _msg "$_guineapig:$line $bp $cl${_lines[$line]}" + elif (( $line > 0 )); then + _msg "$_guineapig:$line $bp $cl${_lines[$line]}" + fi +} + +function _cleanup +{ + rm -f $__debug $_potbelliedpig 2> /dev/null +} + +function _menu +{ + _msg 'bashdb commands: + break N set breakpoint at line N + break list breakpoints & break condition + condition foo set break condition to foo + condition clear break condition + delete N clear breakpoint at line N + delete clear all breakpoints + display EXP evaluate and display EXP for each debug step + display show a list of display expressions + undisplay N remove display expression N + list N M display all lines of script between N and M + list N display 5 lines of script either side of line N + list display 5 lines if script either side of current line + continue continue execution upto next breakpoint + next [N] execute [N] statements (default 1) + print expr prints the value of an expression + trace toggle execution trace on/off + help print this menu + ! string passes string to a shell + quit quit' +} + + +_linebp= +let _trace=0 +let _i=1 + +# Be careful about quoted newlines +_potbelliedpig=${TMPDIR-/tmp}/$_guineapig.$$ +sed 's,\\$,\\\\,' $_guineapig > $_potbelliedpig + +_msg "Reading source from file: $_guineapig" +while read; do + _lines[$_i]=$REPLY + let _i=$_i+1 +done < $_potbelliedpig + +trap _cleanup EXIT +# Assuming a real script will have the "#! /bin/sh" at line 1, +# don't stop at line 1 on the first run +let _steps=2 +LINENO=-2 +trap '_steptrap $LINENO' DEBUG +: diff --git a/lib/readline/display.c b/lib/readline/display.c index e37a4181..ddad1676 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -419,14 +419,14 @@ rl_expand_prompt (prompt) t = ++p; local_prompt = expand_prompt (p, &prompt_visible_length, &prompt_last_invisible, - (int *)NULL, + &prompt_invis_chars_first_line, &prompt_physical_chars); c = *t; *t = '\0'; /* The portion of the prompt string up to and including the final newline is now null-terminated. */ local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, (int *)NULL, - &prompt_invis_chars_first_line, + (int *)NULL, (int *)NULL); *t = c; local_prompt_len = local_prompt ? strlen (local_prompt) : 0; diff --git a/lib/readline/display.c~ b/lib/readline/display.c~ index acd261e8..3b964302 100644 --- a/lib/readline/display.c~ +++ b/lib/readline/display.c~ @@ -419,14 +419,14 @@ rl_expand_prompt (prompt) t = ++p; local_prompt = expand_prompt (p, &prompt_visible_length, &prompt_last_invisible, - (int *)NULL, + &prompt_invis_chars_first_line, &prompt_physical_chars); c = *t; *t = '\0'; /* The portion of the prompt string up to and including the final newline is now null-terminated. */ local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, (int *)NULL, - &prompt_invis_chars_first_line, + (int *)NULL, (int *)NULL); *t = c; local_prompt_len = local_prompt ? strlen (local_prompt) : 0; @@ -938,7 +938,7 @@ rl_redisplay () second and subsequent lines start at inv_lbreaks[N], offset by OFFSET (which has already been calculated above). */ -#define WRAP_OFFSET(line, offset) ((line == 0) \ +#define WRAP_OFFSET<(line, offset) ((line == 0) \ ? (offset ? prompt_invis_chars_first_line : 0) \ : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0)) #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) @@ -1009,7 +1009,8 @@ rl_redisplay () out (e.g., when printing the i-search prompt). In general, the case of the new line being shorter than the old. Incomplete */ - else if (linenum == 1 && prompt_physical_chars > _rl_screenwidth && + else if (linenum == prompt_last_screen_line && + prompt_physical_chars > _rl_screenwidth && wrap_offset != prompt_invis_chars_first_line && _rl_last_c_pos == out && #endif @@ -1842,7 +1843,8 @@ _rl_move_cursor_relative (new, data) prompt string, since they're both buffer indices and DPOS is a desired display position. */ if ((new > prompt_last_invisible) || /* XXX - don't use woff here */ - (prompt_physical_chars > _rl_screenwidth && _rl_last_v_pos == 1 && + (prompt_physical_chars > _rl_screenwidth && + _rl_last_v_pos == prompt_last_screen_line && wrap_offset != woff && new > (prompt_last_invisible-_rl_screenwidth-wrap_offset))) { diff --git a/lib/readline/rltty.c b/lib/readline/rltty.c index c455b150..a51fe2da 100644 --- a/lib/readline/rltty.c +++ b/lib/readline/rltty.c @@ -500,7 +500,7 @@ _get_tty_settings (tty, tiop) } if (OUTPUT_BEING_FLUSHED (tiop)) { -#if defined (FLUSHO) && defined (_AIX41) +#if defined (FLUSHO) _rl_errmsg ("warning: turning off output flushing"); tiop->c_lflag &= ~FLUSHO; break; diff --git a/lib/sh/getcwd.c b/lib/sh/getcwd.c index cd724f6f..694cc066 100644 --- a/lib/sh/getcwd.c +++ b/lib/sh/getcwd.c @@ -26,6 +26,10 @@ #pragma alloca #endif /* _AIX && RISC6000 && !__GNUC__ */ +#if defined (__QNX__) +# undef HAVE_LSTAT +#endif + #include <bashtypes.h> #include <errno.h> diff --git a/lib/sh/getcwd.c~ b/lib/sh/getcwd.c~ new file mode 100644 index 00000000..cd724f6f --- /dev/null +++ b/lib/sh/getcwd.c~ @@ -0,0 +1,313 @@ +/* getcwd.c -- stolen from the GNU C library and modified to work with bash. */ + +/* Copyright (C) 1991 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include <config.h> + +#if !defined (HAVE_GETCWD) + +#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) + #pragma alloca +#endif /* _AIX && RISC6000 && !__GNUC__ */ + +#include <bashtypes.h> +#include <errno.h> + +#if defined (HAVE_LIMITS_H) +# include <limits.h> +#endif + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include <posixdir.h> +#include <posixstat.h> +#include <maxpath.h> +#include <memalloc.h> + +#include <bashansi.h> + +#include <xmalloc.h> + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#if !defined (HAVE_LSTAT) +# define lstat stat +#endif + +#if !defined (NULL) +# define NULL 0 +#endif + +/* Get the pathname of the current working directory, + and put it in SIZE bytes of BUF. Returns NULL if the + directory couldn't be determined or SIZE was too small. + If successful, returns BUF. In GNU, if BUF is NULL, + an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE <= 0, in which case it is as + big as necessary. */ +#if defined (__STDC__) +char * +getcwd (char *buf, size_t size) +#else /* !__STDC__ */ +char * +getcwd (buf, size) + char *buf; + size_t size; +#endif /* !__STDC__ */ +{ + static const char dots[] + = "../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../.."; + const char *dotp, *dotlist; + size_t dotsize; + dev_t rootdev, thisdev; + ino_t rootino, thisino; + char path[PATH_MAX + 1]; + register char *pathp; + char *pathbuf; + size_t pathsize; + struct stat st; + int saved_errno; + + if (buf != NULL && size == 0) + { + errno = EINVAL; + return ((char *)NULL); + } + + pathsize = sizeof (path); + pathp = &path[pathsize]; + *--pathp = '\0'; + pathbuf = path; + + if (stat (".", &st) < 0) + return ((char *)NULL); + thisdev = st.st_dev; + thisino = st.st_ino; + + if (stat ("/", &st) < 0) + return ((char *)NULL); + rootdev = st.st_dev; + rootino = st.st_ino; + + saved_errno = 0; + + dotsize = sizeof (dots) - 1; + dotp = &dots[sizeof (dots)]; + dotlist = dots; + while (!(thisdev == rootdev && thisino == rootino)) + { + register DIR *dirstream; + register struct dirent *d; + dev_t dotdev; + ino_t dotino; + char mount_point; + int namlen; + + /* Look at the parent directory. */ + if (dotp == dotlist) + { + /* My, what a deep directory tree you have, Grandma. */ + char *new; + if (dotlist == dots) + { + new = (char *)malloc (dotsize * 2 + 1); + if (new == NULL) + goto lose; + memcpy (new, dots, dotsize); + } + else + { + new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1); + if (new == NULL) + goto lose; + } + memcpy (&new[dotsize], new, dotsize); + dotp = &new[dotsize]; + dotsize *= 2; + new[dotsize] = '\0'; + dotlist = new; + } + + dotp -= 3; + + /* Figure out if this directory is a mount point. */ + if (stat (dotp, &st) < 0) + goto lose; + dotdev = st.st_dev; + dotino = st.st_ino; + mount_point = dotdev != thisdev; + + /* Search for the last directory. */ + dirstream = opendir (dotp); + if (dirstream == NULL) + goto lose; + while ((d = readdir (dirstream)) != NULL) + { + if (d->d_name[0] == '.' && + (d->d_name[1] == '\0' || + (d->d_name[1] == '.' && d->d_name[2] == '\0'))) + continue; + if (mount_point || d->d_fileno == thisino) + { + char *name; + + namlen = D_NAMLEN(d); + name = (char *) + alloca (dotlist + dotsize - dotp + 1 + namlen + 1); + memcpy (name, dotp, dotlist + dotsize - dotp); + name[dotlist + dotsize - dotp] = '/'; + memcpy (&name[dotlist + dotsize - dotp + 1], + d->d_name, namlen + 1); + if (lstat (name, &st) < 0) + { +#if 0 + int save = errno; + (void) closedir (dirstream); + errno = save; + goto lose; +#else + saved_errno = errno; +#endif + } + if (st.st_dev == thisdev && st.st_ino == thisino) + break; + } + } + if (d == NULL) + { +#if 0 + int save = errno; +#else + int save = errno ? errno : saved_errno; +#endif + (void) closedir (dirstream); + errno = save; + goto lose; + } + else + { + size_t space; + + while ((space = pathp - pathbuf) <= namlen) + { + char *new; + + if (pathbuf == path) + { + new = (char *)malloc (pathsize * 2); + if (!new) + goto lose; + } + else + { + new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2)); + if (!new) + goto lose; + pathp = new + space; + } + (void) memcpy (new + pathsize + space, pathp, pathsize - space); + pathp = new + pathsize + space; + pathbuf = new; + pathsize *= 2; + } + + pathp -= namlen; + (void) memcpy (pathp, d->d_name, namlen); + *--pathp = '/'; + (void) closedir (dirstream); + } + + thisdev = dotdev; + thisino = dotino; + } + + if (pathp == &path[sizeof(path) - 1]) + *--pathp = '/'; + + if (dotlist != dots) + free ((PTR_T) dotlist); + + { + size_t len = pathbuf + pathsize - pathp; + if (buf == NULL) + { + if (len < (size_t) size) + len = size; + buf = (char *) malloc (len); + if (buf == NULL) + goto lose2; + } + else if ((size_t) size < len) + { + errno = ERANGE; + goto lose2; + } + (void) memcpy((PTR_T) buf, (PTR_T) pathp, len); + } + + if (pathbuf != path) + free (pathbuf); + + return (buf); + + lose: + if ((dotlist != dots) && dotlist) + { + int e = errno; + free ((PTR_T) dotlist); + errno = e; + } + + lose2: + if ((pathbuf != path) && pathbuf) + { + int e = errno; + free ((PTR_T) pathbuf); + errno = e; + } + return ((char *)NULL); +} + +#if defined (TEST) +# include <stdio.h> +main (argc, argv) + int argc; + char **argv; +{ + char b[PATH_MAX]; + + if (getcwd(b, sizeof(b))) + { + printf ("%s\n", b); + exit (0); + } + else + { + perror ("cwd: getcwd"); + exit (1); + } +} +#endif /* TEST */ +#endif /* !HAVE_GETCWD */ diff --git a/variables.c b/variables.c index 3bb0ce79..b8645aa3 100644 --- a/variables.c +++ b/variables.c @@ -24,13 +24,13 @@ #include "posixstat.h" #include "posixtime.h" -#if defined (qnx) -# if defined (qnx6) +#if defined (__QNX__) +# if defined (__QNXNTO__) # include <sys/netmgr.h> # else # include <sys/vc.h> -# endif /* !qnx6 */ -#endif /* qnx */ +# endif /* !__QNXNTO__ */ +#endif /* __QNX__ */ #if defined (HAVE_UNISTD_H) # include <unistd.h> @@ -391,11 +391,11 @@ initialize_shell_variables (env, privmode) set_auto_export (temp_var); /* XXX */ #endif -#if defined (qnx) +#if defined (__QNX__) /* set node id -- don't import it from the environment */ { char node_name[22]; -# if defined (qnx6) +# if defined (__QNXNTO__) netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name)); # else qnx_nidtostr (getnid (), node_name, sizeof (node_name)); diff --git a/variables.c~ b/variables.c~ index 0e37af21..3bb0ce79 100644 --- a/variables.c~ +++ b/variables.c~ @@ -1604,7 +1604,11 @@ FUNCTION_DEF * find_function_def (name) const char *name; { +#if defined (DEBUGGER) return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs)); +#else + return ((FUNCTION_DEF *)0); +#endif } /* Return the value of VAR. VAR is assumed to have been the result of a @@ -2147,6 +2151,7 @@ bind_function (name, value) return (entry); } +#if defined (DEBUGGER) /* Bind a function definition, which includes source file and line number information in addition to the command, into the FUNCTION_DEF hash table.*/ void @@ -2175,6 +2180,7 @@ bind_function_def (name, value) elt->data = (PTR_T *)entry; } } +#endif /* DEBUGGER */ /* Add STRING, which is of the form foo=bar, to the temporary environment HASH_TABLE (temporary_env). The functions in execute_cmd.c are @@ -2367,6 +2373,7 @@ unbind_func (name) return 0; } +#if defined (DEBUGGER) int unbind_function_def (name) const char *name; @@ -2388,6 +2395,7 @@ unbind_function_def (name) return 0; } +#endif /* DEBUGGER */ /* Make the variable associated with NAME go away. HASH_LIST is the hash table from which this variable should be deleted (either |
