From: Chet Ramey Date: Sat, 3 Dec 2011 18:34:46 +0000 (-0500) Subject: commit bash-20040805 snapshot X-Git-Tag: bash-3.1-alpha~51 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8ed8525cb12f91fa80d6eab55b91dd2552e2b060;p=thirdparty%2Fbash.git commit bash-20040805 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index c4f732b8f..3da1e8ba8 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9816,3 +9816,50 @@ variables.c pcomplete.c - make sure COMP_WORDS is not invisible when bind_comp_words returns - ditto for COMPREPLY in gen_shell_function_matches + + 8/4 + --- +braces.c + - fix problem where ${ was ignored but did not increment the open + brace count. Bug reported by Tim Waugh + +variables.c + - if make_local_variable finds a variable in the correct context in + the right variable scope, make sure it's not invisible before + returning it + + 8/5 + --- +builtins/trap.def + - fixed usage message to show `action' as not optional, though it + actually is when not in posix mode (for a single argument) + + 8/7 + --- +configure.in + - kfreebsd-gnu has had its sbrk() problems fixed, and no longer needs + to be configured --without-gnu-malloc + +lib/readline/vi_mode.c + - in rl_vi_search, free any saved history line before starting the + search, so failure leaves you at that line, not the last line in + the history (assuming the current line is not the last history line). + Fix from llattanzi@apple.com to replace fix of 7/7 + + 8/9 + --- +support/Makefile.in + - renamed `mostly-clean' target to `mostlyclean' + + 8/11 + ---- +lib/readline/vi_mode.c + - make same change for EOL in multibyte character case of + rl_vi_change_char + + 8/12 + ---- +subst.c + - in verify_substring_values, fix off-by-one error checking bounds of + `offset', esp. in array values (e.g., getting the highest element + of an array) diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 7bab23254..d2bc981ad 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -9815,4 +9815,44 @@ variables.c pcomplete.c - make sure COMP_WORDS is not invisible when bind_comp_words returns - - ditto for COMPREPLY in gen_shell_function_completions + - ditto for COMPREPLY in gen_shell_function_matches + + 8/4 + --- +braces.c + - fix problem where ${ was ignored but did not increment the open + brace count. Bug reported by Tim Waugh + +variables.c + - if make_local_variable finds a variable in the correct context in + the right variable scope, make sure it's not invisible before + returning it + + 8/5 + --- +builtins/trap.def + - fixed usage message to show `action' as not optional, though it + actually is when not in posix mode (for a single argument) + + 8/7 + --- +configure.in + - kfreebsd-gnu has had its sbrk() problems fixed, and no longer needs + to be configured --without-gnu-malloc + +lib/readline/vi_mode.c + - in rl_vi_search, free any saved history line before starting the + search, so failure leaves you at that line, not the last line in + the history (assuming the current line is not the last history line). + Fix from llattanzi@apple.com to replace fix of 7/7 + + 8/9 + --- +support/Makefile.in + - renamed `mostly-clean' target to `mostlyclean' + + 8/11 + ---- +lib/readline/vi_mode.c + - make same change for EOL in multibyte character case of + rl_vi_change_char diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0 index 703bc0bd3..feeb0c0aa 100644 --- a/autom4te.cache/output.0 +++ b/autom4te.cache/output.0 @@ -1,5 +1,5 @@ @%:@! /bin/sh -@%:@ From configure.in for Bash 3.0, version 3.166, from autoconf version AC_ACVERSION. +@%:@ From configure.in for Bash 3.0, version 3.167, from autoconf version AC_ACVERSION. @%:@ Guess values for system-dependent variables and create Makefiles. @%:@ Generated by GNU Autoconf 2.57 for bash 3.0-release. @%:@ @@ -1464,7 +1464,7 @@ sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment m68k-sysv) opt_bash_malloc=no ;; # fixes file descriptor leak in closedir sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF -*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here +#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here #*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree *-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment *-aix*) opt_bash_malloc=no ;; # AIX machines diff --git a/autom4te.cache/requests b/autom4te.cache/requests index 9f0cac676..a60ef56fa 100644 --- a/autom4te.cache/requests +++ b/autom4te.cache/requests @@ -15,96 +15,96 @@ 'configure.in' ], { + 'AC_DEFINE_TRACE_LITERAL' => 1, + 'AC_STRUCT_TIMEZONE' => 1, + 'AC_FUNC_MMAP' => 1, + 'AC_PROG_YACC' => 1, + 'AC_FUNC_STRFTIME' => 1, + 'AC_PROG_RANLIB' => 1, + 'AM_AUTOMAKE_VERSION' => 1, 'AC_STRUCT_TM' => 1, - 'AC_TYPE_PID_T' => 1, - 'AC_CANONICAL_SYSTEM' => 1, - 'm4_pattern_forbid' => 1, - 'AC_FUNC_OBSTACK' => 1, - 'AC_PROG_LEX' => 1, - 'AC_FUNC_GETMNTENT' => 1, - 'AC_FUNC_REALLOC' => 1, - 'AC_FUNC_MEMCMP' => 1, + 'm4_include' => 1, + 'AC_FUNC_SETPGRP' => 1, 'AC_FUNC_GETPGRP' => 1, - 'AC_CANONICAL_HOST' => 1, + 'AC_PROG_CXX' => 1, 'AC_HEADER_DIRENT' => 1, - 'AC_PROG_AWK' => 1, + 'AC_CONFIG_HEADERS' => 1, + 'AC_PROG_CC' => 1, 'AC_HEADER_SYS_WAIT' => 1, - 'AM_CONDITIONAL' => 1, - 'AC_FUNC_ALLOCA' => 1, - 'AC_FUNC_MMAP' => 1, - 'AC_TYPE_MODE_T' => 1, - 'AC_TYPE_SIZE_T' => 1, - 'AC_C_INLINE' => 1, - 'AC_FUNC_GETGROUPS' => 1, + 'AM_PROG_CC_C_O' => 1, + 'AC_HEADER_STDC' => 1, + 'AM_GNU_GETTEXT' => 1, 'AC_FUNC_FSEEKO' => 1, - 'AM_AUTOMAKE_VERSION' => 1, + 'AC_TYPE_SIZE_T' => 1, + 'AC_FUNC_CHOWN' => 1, + 'AC_CHECK_TYPES' => 1, + 'm4_pattern_allow' => 1, + 'AH_OUTPUT' => 1, + 'AC_TYPE_UID_T' => 1, + 'AC_HEADER_STAT' => 1, + 'AC_FUNC_UTIME_NULL' => 1, + 'AC_FUNC_GETMNTENT' => 1, + 'AC_FUNC_STRTOD' => 1, + 'AC_CONFIG_FILES' => 1, + 'AC_FUNC_SETVBUF_REVERSED' => 1, + 'AC_FUNC_MEMCMP' => 1, + 'AC_FUNC_STAT' => 1, + 'AC_PROG_MAKE_SET' => 1, 'AC_FUNC_STRCOLL' => 1, - 'AC_INIT' => 1, - 'AC_CONFIG_SUBDIRS' => 1, - 'AM_MAINTAINER_MODE' => 1, - 'AM_PROG_CC_C_O' => 1, - 'AC_FUNC_STRFTIME' => 1, - 'AM_INIT_AUTOMAKE' => 1, - 'AC_TYPE_OFF_T' => 1, - 'AC_PROG_LN_S' => 1, + 'AC_FUNC_VPRINTF' => 1, + 'AC_FUNC_ERROR_AT_LINE' => 1, + 'AC_SUBST' => 1, + 'AC_FUNC_OBSTACK' => 1, 'AC_FUNC_MKTIME' => 1, + 'AC_PROG_INSTALL' => 1, + 'AC_PROG_AWK' => 1, + 'AC_PROG_LEX' => 1, + 'AC_FUNC_GETGROUPS' => 1, + 'AC_FUNC_CLOSEDIR_VOID' => 1, + 'AC_FUNC_STRNLEN' => 1, + 'AC_CANONICAL_HOST' => 1, + 'AM_INIT_AUTOMAKE' => 1, + 'AC_LIBSOURCE' => 1, + 'AC_CHECK_HEADERS' => 1, + 'include' => 1, + 'AC_PATH_X' => 1, + 'AC_HEADER_TIME' => 1, + 'AC_CONFIG_AUX_DIR' => 1, 'AC_PROG_LIBTOOL' => 1, - 'AC_TYPE_UID_T' => 1, - 'AC_FUNC_MALLOC' => 1, - 'AC_HEADER_MAJOR' => 1, 'AC_FUNC_MBRTOWC' => 1, 'AC_PROG_CPP' => 1, - 'AC_FUNC_UTIME_NULL' => 1, - 'AC_DECL_SYS_SIGLIST' => 1, - 'AC_CHECK_HEADERS' => 1, - 'm4_include' => 1, - 'AC_HEADER_STAT' => 1, - 'AC_FUNC_GETLOADAVG' => 1, - 'AC_PROG_GCC_TRADITIONAL' => 1, + 'AC_FUNC_ALLOCA' => 1, + 'AC_FUNC_LSTAT' => 1, 'AC_TYPE_SIGNAL' => 1, - 'AC_PROG_RANLIB' => 1, - 'AC_FUNC_VPRINTF' => 1, - 'AC_PROG_YACC' => 1, - 'AC_FUNC_STRNLEN' => 1, - 'AC_FUNC_FORK' => 1, - 'AH_OUTPUT' => 1, - 'AC_STRUCT_TIMEZONE' => 1, - 'AC_HEADER_TIME' => 1, - 'AC_FUNC_STAT' => 1, - 'AC_FUNC_SELECT_ARGTYPES' => 1, - 'AC_PROG_CC' => 1, - 'include' => 1, - 'AC_CHECK_MEMBERS' => 1, - 'AC_PROG_INSTALL' => 1, - 'AC_FUNC_ERROR_AT_LINE' => 1, - 'AM_GNU_GETTEXT' => 1, - 'AC_FUNC_STRTOD' => 1, - 'AC_HEADER_STDC' => 1, - 'AC_CHECK_FUNCS' => 1, - 'AC_LIBSOURCE' => 1, - 'AC_REPLACE_FNMATCH' => 1, - 'AC_CONFIG_FILES' => 1, - 'AC_CHECK_TYPES' => 1, - 'AC_CONFIG_HEADERS' => 1, - 'AC_FUNC_CLOSEDIR_VOID' => 1, + 'AC_INIT' => 1, 'AC_C_CONST' => 1, - 'AC_FUNC_STRERROR_R' => 1, - 'AC_FUNC_CHOWN' => 1, - 'AC_FUNC_SETPGRP' => 1, - 'AC_FUNC_SETVBUF_REVERSED' => 1, + 'AC_C_INLINE' => 1, + 'AC_HEADER_MAJOR' => 1, + 'AC_PROG_LN_S' => 1, + 'AC_REPLACE_FNMATCH' => 1, + 'AC_FUNC_SELECT_ARGTYPES' => 1, + 'm4_pattern_forbid' => 1, 'AC_CHECK_LIB' => 1, - 'AC_FUNC_WAIT3' => 1, - 'AC_PROG_MAKE_SET' => 1, + 'AC_FUNC_REALLOC' => 1, + 'AC_TYPE_OFF_T' => 1, + 'AC_CANONICAL_SYSTEM' => 1, + 'AC_CHECK_FUNCS' => 1, + 'AC_CONFIG_SUBDIRS' => 1, + 'AM_CONDITIONAL' => 1, + 'AC_TYPE_MODE_T' => 1, + 'AC_STRUCT_ST_BLOCKS' => 1, + 'AC_DECL_SYS_SIGLIST' => 1, + 'AC_TYPE_PID_T' => 1, 'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1, - 'AC_FUNC_LSTAT' => 1, - 'm4_pattern_allow' => 1, - 'AC_CONFIG_AUX_DIR' => 1, - 'AC_PROG_CXX' => 1, - 'AC_DEFINE_TRACE_LITERAL' => 1, + 'AC_FUNC_GETLOADAVG' => 1, + 'AC_FUNC_MALLOC' => 1, + 'AC_PROG_GCC_TRADITIONAL' => 1, + 'AC_FUNC_WAIT3' => 1, + 'AC_CHECK_MEMBERS' => 1, 'AC_C_VOLATILE' => 1, - 'AC_PATH_X' => 1, - 'AC_STRUCT_ST_BLOCKS' => 1, - 'AC_SUBST' => 1 + 'AC_FUNC_STRERROR_R' => 1, + 'AM_MAINTAINER_MODE' => 1, + 'AC_FUNC_FORK' => 1 } ], 'Request' ) ); diff --git a/braces.c b/braces.c index 8ebfb4fab..3c1efc9ce 100644 --- a/braces.c +++ b/braces.c @@ -402,6 +402,7 @@ brace_gobbler (text, tlen, indx, satisfy) { pass_next = 1; i++; + level++; continue; } #endif diff --git a/builtins/trap.def b/builtins/trap.def index 1531d208d..1ecbfbdb2 100644 --- a/builtins/trap.def +++ b/builtins/trap.def @@ -23,7 +23,7 @@ $PRODUCES trap.c $BUILTIN trap $FUNCTION trap_builtin -$SHORT_DOC trap [-lp] [[arg] signal_spec ...] +$SHORT_DOC trap [-lp] [arg signal_spec ...] The command ARG is to be read and executed when the shell receives signal(s) SIGNAL_SPEC. If ARG is absent (and a single SIGNAL_SPEC is supplied) or `-', each specified signal is reset to its original diff --git a/configure b/configure index 77b11206b..2fdac20af 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in for Bash 3.0, version 3.166, from autoconf version AC_ACVERSION. +# From configure.in for Bash 3.0, version 3.167, from autoconf version AC_ACVERSION. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57 for bash 3.0-release. # @@ -1464,7 +1464,7 @@ sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment m68k-sysv) opt_bash_malloc=no ;; # fixes file descriptor leak in closedir sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF -*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here +#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here #*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree *-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment *-aix*) opt_bash_malloc=no ;; # AIX machines diff --git a/configure.in b/configure.in index 791282d7b..e1bd98fb3 100644 --- a/configure.in +++ b/configure.in @@ -22,7 +22,7 @@ dnl Process this file with autoconf to produce a configure script. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. -AC_REVISION([for Bash 3.0, version 3.166, from autoconf version] AC_ACVERSION)dnl +AC_REVISION([for Bash 3.0, version 3.167, from autoconf version] AC_ACVERSION)dnl define(bashvers, 3.0) define(relstatus, release) @@ -73,7 +73,7 @@ sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment m68k-sysv) opt_bash_malloc=no ;; # fixes file descriptor leak in closedir sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF -*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here +#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here #*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree *-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment *-aix*) opt_bash_malloc=no ;; # AIX machines diff --git a/configure.in~ b/configure.in~ new file mode 100644 index 000000000..e9ea6378a --- /dev/null +++ b/configure.in~ @@ -0,0 +1,1026 @@ +dnl +dnl Configure script for bash-3.0 +dnl +dnl report bugs to chet@po.cwru.edu +dnl +dnl Process this file with autoconf to produce a configure script. + +# Copyright (C) 1987-2004 Free Software Foundation, Inc. + +# 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, 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. + +AC_REVISION([for Bash 3.0, version 3.166, from autoconf version] AC_ACVERSION)dnl + +define(bashvers, 3.0) +define(relstatus, release) + +AC_INIT(bash, bashvers-relstatus, bug-bash@gnu.org) + +dnl make sure we are using a recent autoconf version +AC_PREREQ(2.50) + +AC_CONFIG_SRCDIR(shell.h) +dnl where to find install.sh, config.sub, and config.guess +AC_CONFIG_AUX_DIR(./support) +AC_CONFIG_HEADERS(config.h) + +dnl checks for version info +BASHVERS=bashvers +RELSTATUS=relstatus + +dnl defaults for debug settings +case "$RELSTATUS" in +alp*|bet*|dev*|rc*) DEBUG='-DDEBUG' MALLOC_DEBUG='-DMALLOC_DEBUG' ;; +*) DEBUG= MALLOC_DEBUG= ;; +esac + +dnl canonicalize the host and os so we can do some tricky things before +dnl parsing options +AC_CANONICAL_HOST + +dnl configure defaults +opt_bash_malloc=yes +opt_purify=no +opt_purecov=no +opt_afs=no +opt_curses=no +opt_with_installed_readline=no + +#htmldir= + +dnl some systems should be configured without the bash malloc by default +dnl and some need a special compiler or loader +dnl look in the NOTES file for more +case "${host_cpu}-${host_os}" in +alpha*-*) opt_bash_malloc=no ;; # alpha running osf/1 or linux +*[[Cc]]ray*-*) opt_bash_malloc=no ;; # Crays +*-osf1*) opt_bash_malloc=no ;; # other osf/1 machines +sparc-svr4*) opt_bash_malloc=no ;; # sparc SVR4, SVR4.2 +sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment +mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment +m68k-sysv) opt_bash_malloc=no ;; # fixes file descriptor leak in closedir +sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF +#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here +#*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree +*-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment +*-aix*) opt_bash_malloc=no ;; # AIX machines +*-nextstep*) opt_bash_malloc=no ;; # NeXT machines running NeXTstep +*-macos*) opt_bash_malloc=no ;; # Apple MacOS X +*-rhapsody*) opt_bash_malloc=no ;; # Apple Rhapsody (MacOS X) +*-darwin*) opt_bash_malloc=no ;; # Apple Darwin (MacOS X) +*-dgux*) opt_bash_malloc=no ;; # DG/UX machines +*-qnx*) opt_bash_malloc=no ;; # QNX 4.2 +*-machten4) opt_bash_malloc=no ;; # MachTen 4.x +*-bsdi2.1|*-bsdi3.?) opt_bash_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins +*-beos*) opt_bash_malloc=no ;; # they say it's suitable +*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment +*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft +esac + +# memory scrambling on free() +case "${host_os}" in +sco3.2v5*|sco3.2v4*) opt_memscramble=no ;; +*) opt_memscramble=yes ;; +esac + +dnl +dnl macros for the bash debugger +dnl +AM_PATH_LISPDIR +AC_ARG_VAR(DEBUGGER_START_FILE, [location of bash debugger initialization file]) + +dnl arguments to configure +dnl packages +AC_ARG_WITH(afs, AC_HELP_STRING([--with-afs], [if you are running AFS]), opt_afs=$withval) +AC_ARG_WITH(bash-malloc, AC_HELP_STRING([--with-bash-malloc], [use the Bash version of malloc]), opt_bash_malloc=$withval) +AC_ARG_WITH(curses, AC_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval) +AC_ARG_WITH(gnu-malloc, AC_HELP_STRING([--with-gnu-malloc], [synonym for --with-bash-malloc]), opt_bash_malloc=$withval) +AC_ARG_WITH(installed-readline, AC_HELP_STRING([--with-installed-readline], [use a version of the readline library that is already installed]), opt_with_installed_readline=$withval) +AC_ARG_WITH(purecov, AC_HELP_STRING([--with-purecov], [configure to postprocess with pure coverage]), opt_purecov=$withval) +AC_ARG_WITH(purify, AC_HELP_STRING([--with-purify], [configure to postprocess with purify]), opt_purify=$withval) + +if test "$opt_bash_malloc" = yes; then + MALLOC_TARGET=malloc + MALLOC_SRC=malloc.c + + MALLOC_LIB='-lmalloc' + MALLOC_LIBRARY='$(ALLOC_LIBDIR)/libmalloc.a' + MALLOC_LDFLAGS='-L$(ALLOC_LIBDIR)' + MALLOC_DEP='$(MALLOC_LIBRARY)' + + AC_DEFINE(USING_BASH_MALLOC) +else + MALLOC_LIB= + MALLOC_LIBRARY= + MALLOC_LDFLAGS= + MALLOC_DEP= +fi + +if test "$opt_purify" = yes; then + PURIFY="purify " + AC_DEFINE(DISABLE_MALLOC_WRAPPERS) +else + PURIFY= +fi + +if test "$opt_purecov" = yes; then + PURIFY="${PURIFY}purecov" +fi + +if test "$opt_afs" = yes; then + AC_DEFINE(AFS) +fi + +if test "$opt_curses" = yes; then + prefer_curses=yes +fi + +if test -z "${DEBUGGER_START_FILE}"; then + DEBUGGER_START_FILE=${ac_default_prefix}/lib/bashdb/bashdb-main.inc +fi + +dnl optional shell features in config.h.in +opt_minimal_config=no + +opt_job_control=yes +opt_alias=yes +opt_readline=yes +opt_history=yes +opt_bang_history=yes +opt_dirstack=yes +opt_restricted=yes +opt_process_subst=yes +opt_prompt_decoding=yes +opt_select=yes +opt_help=yes +opt_array_variables=yes +opt_dparen_arith=yes +opt_extended_glob=yes +opt_brace_expansion=yes +opt_disabled_builtins=no +opt_command_timing=yes +opt_xpg_echo=no +opt_cond_command=yes +opt_cond_regexp=yes +opt_arith_for_command=yes +opt_net_redirs=yes +opt_progcomp=yes +opt_separate_help=no +opt_multibyte=yes +opt_debugger=yes + +dnl options that affect how bash is compiled and linked +opt_static_link=no +opt_profiling=no + +dnl argument parsing for optional features +AC_ARG_ENABLE(minimal-config, AC_HELP_STRING([--enable-minimal-config], [a minimal sh-like configuration]), opt_minimal_config=$enableval) + +dnl a minimal configuration turns everything off, but features can be +dnl added individually +if test $opt_minimal_config = yes; then + opt_job_control=no opt_alias=no opt_readline=no + opt_history=no opt_bang_history=no opt_dirstack=no + opt_restricted=no opt_process_subst=no opt_prompt_decoding=no + opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no + opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no + opt_extended_glob=no opt_cond_command=no opt_arith_for_command=no + opt_net_redirs=no opt_progcomp=no opt_separate_help=no + opt_multibyte=yes opt_cond_regexp=no +fi + +AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval) +AC_ARG_ENABLE(arith-for-command, AC_HELP_STRING([--enable-arith-for-command], [enable arithmetic for command]), opt_arith_for_command=$enableval) +AC_ARG_ENABLE(array-variables, AC_HELP_STRING([--enable-array-variables], [include shell array variables]), opt_array_variables=$enableval) +AC_ARG_ENABLE(bang-history, AC_HELP_STRING([--enable-bang-history], [turn on csh-style history substitution]), opt_bang_history=$enableval) +AC_ARG_ENABLE(brace-expansion, AC_HELP_STRING([--enable-brace-expansion], [include brace expansion]), opt_brace_expansion=$enableval) +AC_ARG_ENABLE(command-timing, AC_HELP_STRING([--enable-command-timing], [enable the time reserved word and command timing]), opt_command_timing=$enableval) +AC_ARG_ENABLE(cond-command, AC_HELP_STRING([--enable-cond-command], [enable the conditional command]), opt_cond_command=$enableval) +AC_ARG_ENABLE(cond-regexp, AC_HELP_STRING([--enable-cond-regexp], [enable extgended regular expression matching in conditional commands]), opt_cond_regexp=$enableval) +AC_ARG_ENABLE(debugger, AC_HELP_STRING([--enable-debugger], [enable support for bash debugger]), opt_debugger=$enableval) +AC_ARG_ENABLE(directory-stack, AC_HELP_STRING([--enable-directory-stack], [enable builtins pushd/popd/dirs]), opt_dirstack=$enableval) +AC_ARG_ENABLE(disabled-builtins, AC_HELP_STRING([--enable-disabled-builtins], [allow disabled builtins to still be invoked]), opt_disabled_builtins=$enableval) +AC_ARG_ENABLE(dparen-arithmetic, AC_HELP_STRING([--enable-dparen-arithmetic], [include ((...)) command]), opt_dparen_arith=$enableval) +AC_ARG_ENABLE(extended-glob, AC_HELP_STRING([--enable-extended-glob], [include ksh-style extended pattern matching]), opt_extended_glob=$enableval) +AC_ARG_ENABLE(help-builtin, AC_HELP_STRING([--enable-help-builtin], [include the help builtin]), opt_help=$enableval) +AC_ARG_ENABLE(history, AC_HELP_STRING([--enable-history], [turn on command history]), opt_history=$enableval) +AC_ARG_ENABLE(job-control, AC_HELP_STRING([--enable-job-control], [enable job control features]), opt_job_control=$enableval) +AC_ARG_ENABLE(multibyte, AC_HELP_STRING([--enable-multibyte], [enable multibyte characters if OS supports them]), opt_multibyte=$enableval) +AC_ARG_ENABLE(net-redirections, AC_HELP_STRING([--enable-net-redirections], [enable /dev/tcp/host/port redirection]), opt_net_redirs=$enableval) +AC_ARG_ENABLE(process-substitution, AC_HELP_STRING([--enable-process-substitution], [enable process substitution]), opt_process_subst=$enableval) +AC_ARG_ENABLE(progcomp, AC_HELP_STRING([--enable-progcomp], [enable programmable completion and the complete builtin]), opt_progcomp=$enableval) +AC_ARG_ENABLE(prompt-string-decoding, AC_HELP_STRING([--enable-prompt-string-decoding], [turn on escape character decoding in prompts]), opt_prompt_decoding=$enableval) +AC_ARG_ENABLE(readline, AC_HELP_STRING([--enable-readline], [turn on command line editing]), opt_readline=$enableval) +AC_ARG_ENABLE(restricted, AC_HELP_STRING([--enable-restricted], [enable a restricted shell]), opt_restricted=$enableval) +AC_ARG_ENABLE(select, AC_HELP_STRING([--enable-select], [include select command]), opt_select=$enableval) +AC_ARG_ENABLE(separate-helpfiles, AC_HELP_STRING([--enable-separate-helpfiles], [use external files for help builtin documentation]), opt_separate_help=$enableval) +AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval) +AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval) + +dnl options that alter how bash is compiled and linked +AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval) +AC_ARG_ENABLE(profiling, AC_HELP_STRING([--enable-profiling], [allow profiling with gprof]), opt_profiling=$enableval) +AC_ARG_ENABLE(static-link, AC_HELP_STRING([--enable-static-link], [link bash statically, for use as a root shell]), opt_static_link=$enableval) + +dnl opt_job_control is handled later, after BASH_JOB_CONTROL_MISSING runs + +dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs +dnl to be run before we can check the version of an already-installed readline +dnl library + +if test $opt_alias = yes; then +AC_DEFINE(ALIAS) +fi +if test $opt_dirstack = yes; then +AC_DEFINE(PUSHD_AND_POPD) +fi +if test $opt_restricted = yes; then +AC_DEFINE(RESTRICTED_SHELL) +fi +if test $opt_process_subst = yes; then +AC_DEFINE(PROCESS_SUBSTITUTION) +fi +if test $opt_prompt_decoding = yes; then +AC_DEFINE(PROMPT_STRING_DECODE) +fi +if test $opt_select = yes; then +AC_DEFINE(SELECT_COMMAND) +fi +if test $opt_help = yes; then +AC_DEFINE(HELP_BUILTIN) +fi +if test $opt_array_variables = yes; then +AC_DEFINE(ARRAY_VARS) +fi +if test $opt_dparen_arith = yes; then +AC_DEFINE(DPAREN_ARITHMETIC) +fi +if test $opt_brace_expansion = yes; then +AC_DEFINE(BRACE_EXPANSION) +fi +if test $opt_disabled_builtins = yes; then +AC_DEFINE(DISABLED_BUILTINS) +fi +if test $opt_command_timing = yes; then +AC_DEFINE(COMMAND_TIMING) +fi +if test $opt_xpg_echo = yes ; then +AC_DEFINE(DEFAULT_ECHO_TO_XPG) +fi +if test $opt_extended_glob = yes ; then +AC_DEFINE(EXTENDED_GLOB) +fi +if test $opt_cond_command = yes ; then +AC_DEFINE(COND_COMMAND) +fi +if test $opt_cond_regexp = yes ; then +AC_DEFINE(COND_REGEXP) +fi +if test $opt_arith_for_command = yes; then +AC_DEFINE(ARITH_FOR_COMMAND) +fi +if test $opt_net_redirs = yes; then +AC_DEFINE(NETWORK_REDIRECTIONS) +fi +if test $opt_progcomp = yes; then +AC_DEFINE(PROGRAMMABLE_COMPLETION) +fi +if test $opt_multibyte = no; then +AC_DEFINE(NO_MULTIBYTE_SUPPORT) +fi +if test $opt_debugger = yes; then +AC_DEFINE(DEBUGGER) +fi + +if test $opt_memscramble = yes; then +AC_DEFINE(MEMSCRAMBLE) +fi + +if test "$opt_minimal_config" = yes; then + TESTSCRIPT=run-minimal +else + TESTSCRIPT=run-all +fi + +HELPDIR= HELPDIRDEFINE= HELPINSTALL= +if test "$opt_separate_help" != no; then + if test "$opt_separate_help" = "yes" ; then + HELPDIR='${datadir}/bash' + else + HELPDIR=$opt_separate_help + fi + HELPDIRDEFINE='-H ${HELPDIR}' + HELPINSTALL='install-help' +fi + +dnl now substitute in the values generated by arguments +AC_SUBST(TESTSCRIPT) +AC_SUBST(PURIFY) +AC_SUBST(MALLOC_TARGET) +AC_SUBST(MALLOC_SRC) + +AC_SUBST(MALLOC_LIB) +AC_SUBST(MALLOC_LIBRARY) +AC_SUBST(MALLOC_LDFLAGS) +AC_SUBST(MALLOC_DEP) + +AC_SUBST(htmldir) + +AC_SUBST(HELPDIR) +AC_SUBST(HELPDIRDEFINE) +AC_SUBST(HELPINSTALL) + +echo "" +echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}" +echo "" + +dnl compilation checks +dnl AC_PROG_CC sets $cross_compiling to `yes' if cross-compiling for a +dnl different environment +AC_PROG_CC + +dnl test for Unix variants +AC_ISC_POSIX +AC_MINIX + +dnl test for non-Unix variants +AC_CYGWIN +AC_MINGW32 + +AC_SYS_LARGEFILE + +dnl BEGIN changes for cross-building for cygwin and BeOS + +SIGNAMES_H=lsignames.h + +dnl load up the cross-building cache file -- add more cases and cache +dnl files as necessary + +dnl Note that host and target machine are the same, and different than the +dnl build machine. +dnl Set SIGNAMES_H based on whether or not we're cross-compiling. + +if test "x$cross_compiling" = "xyes"; then + case "${host}" in + *-cygwin*) + cross_cache=${srcdir}/cross-build/cygwin32.cache + SIGNAMES_H='$(srcdir)/cross-build/win32sig.h' + ;; + i[[3456]]86-*-beos*) + cross_cache=${srcdir}/cross-build/x86-beos.cache + SIGNAMES_H='${srcdir}/cross-build/beos-sig.h' + ;; + *) echo "configure: cross-compiling for $host is not supported" >&2 + ;; + esac + if test -n "${cross_cache}" && test -r "${cross_cache}"; then + echo "loading cross-build cache file ${cross_cache}" + . ${cross_cache} + fi + unset cross_cache +fi +AC_SUBST(SIGNAMES_H) + +if test -z "$CC_FOR_BUILD"; then + if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' + else + CC_FOR_BUILD=gcc + fi +fi +AC_SUBST(CC_FOR_BUILD) + +dnl END changes for cross-building + +dnl We want these before the checks, so the checks can modify their values. +test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 + +dnl If we're using gcc and the user hasn't specified CFLAGS, add -O2 to CFLAGS. +test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O2" + +dnl handle options that alter how bash is compiled and linked +dnl these must come after the test for cc/gcc +if test "$opt_profiling" = "yes"; then + PROFILE_FLAGS=-pg + case "$host_os" in + solaris2*) ;; + *) opt_static_link=yes ;; + esac + DEBUG= MALLOC_DEBUG= +fi + +if test "$opt_static_link" = yes; then + # if we're using gcc, add `-static' to LDFLAGS, except on Solaris >= 2 + if test -n "$GCC" || test "$ac_cv_prog_gcc" = "yes"; then + STATIC_LD="-static" + case "$host_os" in + solaris2*) ;; + *) LDFLAGS="$LDFLAGS -static" ;; # XXX experimental + esac + fi +fi + +if test "X$cross_compiling" = "Xno"; then + CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-"$CPPFLAGS"} + LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-'$(LDFLAGS)'} +else + CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-""} + LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-""} +fi + +test -z "$CFLAGS_FOR_BUILD" && CFLAGS_FOR_BUILD="-g" + +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) +AC_SUBST(STATIC_LD) + +AC_SUBST(CFLAGS_FOR_BUILD) +AC_SUBST(CPPFLAGS_FOR_BUILD) +AC_SUBST(LDFLAGS_FOR_BUILD) + +AC_PROG_GCC_TRADITIONAL + +dnl BEGIN READLINE and HISTORY LIBRARY SECTION +dnl prepare to allow bash to be linked against an already-installed readline + +dnl first test that the readline version is new enough to link bash against +if test "$opt_readline" = yes && test "$opt_with_installed_readline" != "no" +then + # If the user specified --with-installed-readline=PREFIX and PREFIX + # is not `yes', set ac_cv_rl_prefix to PREFIX + test $opt_with_installed_readline != "yes" && ac_cv_rl_prefix=$opt_with_installed_readline + + RL_LIB_READLINE_VERSION + + case "$ac_cv_rl_version" in + 5*|6*|7*|8*|9*) ;; + *) opt_with_installed_readline=no + AC_MSG_WARN(installed readline library is too old to be linked with bash) + AC_MSG_WARN(using private bash version) + ;; + esac +fi + +if test $opt_readline = yes; then + AC_DEFINE(READLINE) + READLINE_LIB=-lreadline + if test "$opt_with_installed_readline" != "no" ; then + case "$opt_with_installed_readline" in + yes) RL_INCLUDE= ;; + *) case "$RL_INCLUDEDIR" in + /usr/include) ;; + *) RL_INCLUDE='-I${RL_INCLUDEDIR}' ;; + esac + ;; + esac + READLINE_DEP= + else + RL_LIBDIR='$(dot)/$(LIBSUBDIR)/readline' + READLINE_DEP='$(READLINE_LIBRARY)' + fi +else + RL_LIBDIR='$(dot)/$(LIBSUBDIR)/readline' + READLINE_LIB= READLINE_DEP= +fi +if test $opt_history = yes || test $opt_bang_history = yes; then + if test $opt_history = yes; then + AC_DEFINE(HISTORY) + fi + if test $opt_bang_history = yes; then + AC_DEFINE(BANG_HISTORY) + fi + HISTORY_LIB=-lhistory + if test "$opt_with_installed_readline" != "no"; then + HIST_LIBDIR=$RL_LIBDIR + HISTORY_DEP= + case "$opt_with_installed_readline" in + yes) RL_INCLUDE= ;; + *) case "$RL_INCLUDEDIR" in + /usr/include) ;; + *) RL_INCLUDE='-I${RL_INCLUDEDIR}' ;; + esac + ;; + esac + else + HIST_LIBDIR='$(dot)/$(LIBSUBDIR)/readline' + HISTORY_DEP='$(HISTORY_LIBRARY)' + fi +else + HIST_LIBDIR='$(dot)/$(LIBSUBDIR)/readline' + HISTORY_LIB= HISTORY_DEP= +fi +AC_SUBST(READLINE_LIB) +AC_SUBST(READLINE_DEP) +AC_SUBST(RL_LIBDIR) +AC_SUBST(RL_INCLUDEDIR) +AC_SUBST(RL_INCLUDE) +AC_SUBST(HISTORY_LIB) +AC_SUBST(HISTORY_DEP) +AC_SUBST(HIST_LIBDIR) + +dnl END READLINE and HISTORY LIBRARY SECTION + +dnl programs needed by the build and install process +AC_PROG_INSTALL +AC_CHECK_PROG(AR, ar, , ar) +dnl Set default for ARFLAGS, since autoconf does not have a macro for it. +dnl This allows people to set it when running configure or make +test -n "$ARFLAGS" || ARFLAGS="cr" +AC_PROG_RANLIB +AC_PROG_YACC +AC_PROG_MAKE_SET + +case "$host_os" in +opennt*|interix*) MAKE_SHELL="$INTERIX_ROOT/bin/sh" ;; +*) MAKE_SHELL=/bin/sh ;; +esac +AC_SUBST(MAKE_SHELL) + +dnl Turn on any extensions available in the GNU C library. +AC_DEFINE(_GNU_SOURCE, 1) + +dnl C compiler characteristics +AC_C_CONST +AC_C_INLINE +AC_C_BIGENDIAN +AC_C_STRINGIZE +AC_C_LONG_DOUBLE +AC_C_PROTOTYPES +AC_C_CHAR_UNSIGNED + +dnl initialize GNU gettext +AM_GNU_GETTEXT([no-libtool], [need-ngettext], [lib/intl]) + +dnl header files +AC_HEADER_DIRENT +AC_HEADER_TIME + +BASH_HEADER_INTTYPES + +AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \ + memory.h locale.h termcap.h termio.h termios.h dlfcn.h \ + stddef.h stdint.h netdb.h grp.h strings.h regex.h) +AC_CHECK_HEADERS(sys/ptem.h sys/pte.h sys/stream.h sys/select.h sys/file.h \ + sys/resource.h sys/param.h sys/socket.h sys/stat.h \ + sys/time.h sys/times.h sys/types.h sys/wait.h) +AC_CHECK_HEADERS(netinet/in.h arpa/inet.h) + +dnl special checks for libc functions +AC_FUNC_ALLOCA +AC_FUNC_GETPGRP +AC_FUNC_SETVBUF_REVERSED +AC_FUNC_VPRINTF +AC_FUNC_STRCOLL + +dnl if we're not using the bash malloc but require the C alloca, set things +dnl up to build a libmalloc.a containing only alloca.o + +if test "$ac_cv_func_alloca_works" = "no" && test "$opt_bash_malloc" = "no"; then + MALLOC_TARGET=alloca + MALLOC_SRC=alloca.c + + MALLOC_LIB='-lmalloc' + MALLOC_LIBRARY='$(ALLOC_LIBDIR)/libmalloc.a' + MALLOC_LDFLAGS='-L$(ALLOC_LIBDIR)' + MALLOC_DEP='$(MALLOC_LIBRARY)' +fi + +dnl if vprintf is not in libc, see if it's defined in stdio.h +if test "$ac_cv_func_vprintf" = no; then + AC_MSG_CHECKING(for declaration of vprintf in stdio.h) + AC_EGREP_HEADER([[int[ ]*vprintf[^a-zA-Z0-9]]],stdio.h,ac_cv_func_vprintf=yes) + AC_MSG_RESULT($ac_cv_func_vprintf) + if test $ac_cv_func_vprintf = yes; then + AC_DEFINE(HAVE_VPRINTF) + fi +fi + +if test "$ac_cv_func_vprintf" = no && test "$ac_cv_func__doprnt" = "yes"; then + AC_LIBOBJ(vprint) +fi + +dnl signal stuff +AC_TYPE_SIGNAL + +dnl checks for certain version-specific system calls and libc functions +AC_CHECK_FUNC(__setostype, AC_DEFINE(HAVE_SETOSTYPE)) +AC_CHECK_FUNC(wait3, AC_DEFINE(HAVE_WAIT3)) +AC_CHECK_FUNC(isinf, AC_DEFINE(HAVE_ISINF_IN_LIBC)) + +dnl checks for missing libc functions +AC_CHECK_FUNC(mkfifo,AC_DEFINE(HAVE_MKFIFO),AC_DEFINE(MKFIFO_MISSING)) + +dnl checks for system calls +AC_CHECK_FUNCS(dup2 select getdtablesize getgroups gethostname \ + setdtablesize getpagesize killpg lstat getpeername sbrk \ + getrlimit getrusage gettimeofday waitpid tcgetpgrp \ + readlink) +AC_REPLACE_FUNCS(rename) + +dnl checks for c library functions +AC_CHECK_FUNCS(bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \ + setlinebuf setvbuf setlocale strchr tcgetattr uname \ + ulimit tzset siginterrupt memmove ttyname times \ + getaddrinfo gethostbyname getservbyname getservent inet_aton \ + vsnprintf snprintf vasprintf asprintf fnmatch regcomp regexec) +AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit) +AC_REPLACE_FUNCS(getcwd strcasecmp strerror strftime strpbrk memset strstr) +AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax) + +AC_CHECK_DECLS([confstr]) +AC_CHECK_DECLS([printf]) +AC_CHECK_DECLS([sbrk]) +AC_CHECK_DECLS([strcpy]) +AC_CHECK_DECLS([strsignal]) + +dnl Extra test to detect the horribly broken HP/UX 11.00 strtold(3) +AC_CHECK_DECLS([strtold], [ + AC_MSG_CHECKING([for broken strtold]) + AC_CACHE_VAL(bash_cv_strtold_broken, + [AC_TRY_COMPILE( + [#include ], + [int main() { long double r; char *foo, bar; r = strtold(foo, &bar);}], + bash_cv_strtold_broken=no, bash_cv_strtold_broken=yes, + [AC_MSG_WARN(cannot check for broken strtold if cross-compiling, defaulting to no)]) + ] + ) + AC_MSG_RESULT($bash_cv_strtold_broken) + if test "$bash_cv_strtold_broken" = "yes" ; then + AC_DEFINE(STRTOLD_BROKEN) + fi +]) + + +BASH_CHECK_DECL(strtoimax) +BASH_CHECK_DECL(strtol) +BASH_CHECK_DECL(strtoll) +BASH_CHECK_DECL(strtoul) +BASH_CHECK_DECL(strtoull) +BASH_CHECK_DECL(strtoumax) + +AC_FUNC_MKTIME + +dnl +dnl Checks for lib/intl and related code (uses some of the output from +dnl AM_GNU_GETTEXT) +dnl + +AC_CHECK_HEADERS([argz.h errno.h fcntl.h malloc.h stdio_ext.h]) + +dnl AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_CHECK_FUNCS([__argz_count __argz_next __argz_stringify dcgettext mempcpy \ + munmap stpcpy strcspn strdup]) + +INTL_DEP= INTL_INC= LIBINTL_H= +if test "x$USE_INCLUDED_LIBINTL" = "xyes"; then + INTL_DEP='${INTL_LIBDIR}/libintl.a' + INTL_INC='-I${INTL_LIBSRC} -I${INTL_BUILDDIR}' + LIBINTL_H='${INTL_BUILDDIR}/libintl.h' +fi +AC_SUBST(INTL_DEP) +AC_SUBST(INTL_INC) +AC_SUBST(LIBINTL_H) + +dnl +dnl End of checks needed by files in lib/intl +dnl + +BASH_CHECK_MULTIBYTE + +dnl checks for the dynamic loading library functions in libc and libdl +if test "$opt_static_link" != yes; then +AC_CHECK_LIB(dl, dlopen) +AC_CHECK_FUNCS(dlopen dlclose dlsym) +fi + +dnl this defines SYS_SIGLIST_DECLARED +AC_DECL_SYS_SIGLIST + +dnl network functions -- check for inet_aton again +if test "$ac_cv_func_inet_aton" != 'yes'; then +BASH_FUNC_INET_ATON +fi + +dnl libraries +dnl this is reportedly no longer necessary for irix[56].? +case "$host_os" in +irix4*) AC_CHECK_LIB(sun, getpwent) ;; +esac + +dnl check for getpeername in the socket library only if it's not in libc +if test "$ac_cv_func_getpeername" = no; then + BASH_CHECK_LIB_SOCKET +fi +dnl check for gethostbyname in socket libraries if it's not in libc +if test "$ac_cv_func_gethostbyname" = no; then + BASH_FUNC_GETHOSTBYNAME +fi + +dnl system types +AC_TYPE_GETGROUPS +AC_TYPE_OFF_T +AC_TYPE_MODE_T +AC_TYPE_UID_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_CHECK_TYPE(ssize_t, int) +AC_CHECK_TYPE(time_t, long) + +BASH_TYPE_LONG_LONG +BASH_TYPE_UNSIGNED_LONG_LONG + +AC_TYPE_SIGNAL + +AC_CHECK_SIZEOF(char, 1) +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(char *, 4) +AC_CHECK_SIZEOF(double, 8) +AC_CHECK_SIZEOF([long long], 8) + +AC_CHECK_TYPE(u_int, [unsigned int]) +AC_CHECK_TYPE(u_long, [unsigned long]) + +BASH_TYPE_BITS16_T +BASH_TYPE_U_BITS16_T +BASH_TYPE_BITS32_T +BASH_TYPE_U_BITS32_T +BASH_TYPE_BITS64_T + +BASH_TYPE_PTRDIFF_T + +dnl structures +AC_HEADER_STAT + +dnl system services +AC_SYS_INTERPRETER +if test $ac_cv_sys_interpreter = yes; then +AC_DEFINE(HAVE_HASH_BANG_EXEC) +fi + +dnl Miscellaneous Bash tests +if test "$ac_cv_func_lstat" = "no"; then +BASH_FUNC_LSTAT +fi + +dnl behavior of system calls and library functions +BASH_FUNC_CTYPE_NONASCII +BASH_FUNC_DUP2_CLOEXEC_CHECK +BASH_SYS_PGRP_SYNC +BASH_SYS_SIGNAL_VINTAGE + +dnl checking for the presence of certain library symbols +BASH_SYS_ERRLIST +BASH_SYS_SIGLIST +BASH_UNDER_SYS_SIGLIST + +dnl various system types +BASH_TYPE_SIGHANDLER +BASH_CHECK_TYPE(clock_t, [#include ], long) +BASH_CHECK_TYPE(sigset_t, [#include ], int) +BASH_CHECK_TYPE(quad_t, , long, HAVE_QUAD_T) +BASH_CHECK_TYPE(intmax_t, , $bash_cv_type_long_long) +BASH_CHECK_TYPE(uintmax_t, , $bash_cv_type_unsigned_long_long) +if test "$ac_cv_header_sys_socket_h" = "yes"; then +BASH_CHECK_TYPE(socklen_t, [#include ], int, HAVE_SOCKLEN_T) +fi +BASH_TYPE_RLIMIT + +dnl presence and contents of structures used by system calls +BASH_STRUCT_TERMIOS_LDISC +BASH_STRUCT_TERMIO_LDISC +BASH_STRUCT_DIRENT_D_INO +BASH_STRUCT_DIRENT_D_FILENO +BASH_STRUCT_DIRENT_D_NAMLEN +BASH_STRUCT_WINSIZE +BASH_STRUCT_TIMEVAL +AC_CHECK_MEMBERS([struct stat.st_blocks]) +AC_STRUCT_TM +AC_STRUCT_TIMEZONE +BASH_STRUCT_TIMEZONE + +dnl presence and behavior of C library functions +BASH_FUNC_STRSIGNAL +BASH_FUNC_OPENDIR_CHECK +BASH_FUNC_ULIMIT_MAXFDS +BASH_FUNC_GETENV +if test "$ac_cv_func_getcwd" = "yes"; then +BASH_FUNC_GETCWD +fi +BASH_FUNC_POSIX_SETJMP +BASH_FUNC_STRCOLL + +dnl If putenv or unsetenv is not present, set the right define so the +dnl prototype and declaration in lib/sh/getenv.c will be standard-conformant + +if test "$ac_cv_func_putenv" = "yes"; then +BASH_FUNC_STD_PUTENV +else +AC_DEFINE(HAVE_STD_PUTENV) +fi +if test "$ac_cv_func_unsetenv" = "yes"; then +BASH_FUNC_STD_UNSETENV +else +AC_DEFINE(HAVE_STD_UNSETENV) +fi + +BASH_FUNC_PRINTF_A_FORMAT + +dnl presence and behavior of OS functions +BASH_SYS_REINSTALL_SIGHANDLERS +BASH_SYS_JOB_CONTROL_MISSING +BASH_SYS_NAMED_PIPES + +dnl presence of certain CPP defines +AC_HEADER_TIOCGWINSZ +BASH_HAVE_TIOCSTAT +BASH_HAVE_FIONREAD + +dnl miscellaneous +BASH_CHECK_SPEED_T +BASH_CHECK_GETPW_FUNCS +BASH_CHECK_RTSIGS +BASH_CHECK_SYS_SIGLIST + +dnl special checks +case "$host_os" in +hpux*) BASH_CHECK_KERNEL_RLIMIT ;; +esac + +if test "$opt_readline" = yes; then +dnl yuck +case "$host_os" in +aix*) prefer_curses=yes ;; +esac +BASH_CHECK_LIB_TERMCAP +fi +AC_SUBST(TERMCAP_LIB) +AC_SUBST(TERMCAP_DEP) + +BASH_CHECK_DEV_FD +BASH_CHECK_DEV_STDIN +BASH_SYS_DEFAULT_MAIL_DIR + +if test "$bash_cv_job_control_missing" = missing; then + opt_job_control=no +fi + +if test "$opt_job_control" = yes; then +AC_DEFINE(JOB_CONTROL) +JOBS_O=jobs.o +else +JOBS_O=nojobs.o +fi + +AC_SUBST(JOBS_O) + +dnl Defines that we want to propagate to the Makefiles in subdirectories, +dnl like glob and readline + +LOCAL_DEFS=-DSHELL + +dnl use this section to possibly define more cpp variables, specify local +dnl libraries, and specify any additional local cc flags +dnl +dnl this should really go away someday + +case "${host_os}" in +sysv4.2*) AC_DEFINE(SVR4_2) + AC_DEFINE(SVR4) ;; +sysv4*) AC_DEFINE(SVR4) ;; +sysv5*) AC_DEFINE(SVR5) ;; +hpux9*) LOCAL_CFLAGS="-DHPUX9 -DHPUX" ;; +hpux*) LOCAL_CFLAGS=-DHPUX ;; +dgux*) LOCAL_CFLAGS=-D_DGUX_SOURCE; LOCAL_LIBS=-ldgc ;; +isc*) LOCAL_CFLAGS=-Disc386 ;; +rhapsody*) LOCAL_CFLAGS=-DRHAPSODY ;; +darwin*) LOCAL_CFLAGS=-DMACOSX ;; +sco3.2v5*) LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;; +sco3.2v4*) LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;; +sco3.2*) LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;; +sunos4*) LOCAL_CFLAGS=-DSunOS4 ;; +solaris2.5*) LOCAL_CFLAGS=-DSunOS5 ;; +lynxos*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;; +linux*) LOCAL_LDFLAGS=-rdynamic ;; # allow dynamic loading +*qnx*) LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s" LOCAL_LIBS="-lunix -lncurses" ;; +powerux*) LOCAL_LIBS="-lgen" ;; +cygwin*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;; +opennt*|interix*) LOCAL_CFLAGS="-DNO_MAIN_ENV_ARG -DBROKEN_DIRENT_D_INO" ;; +esac + +dnl Stanza for OS/compiler pair-specific flags +case "${host_os}-${CC}" in +aix4.2*-*gcc*) LOCAL_LDFLAGS="-Xlinker -bexpall -Xlinker -brtl" ;; +aix4.2*) LOCAL_LDFLAGS="-bexpall -brtl" ;; +bsdi4*-*gcc*) LOCAL_LDFLAGS="-rdynamic" ;; # allow dynamic loading, like Linux +esac + +dnl FreeBSD-3.x can have either a.out or ELF +case "${host_os}" in +freebsd[[3-9]]*) + if test -x /usr/bin/objformat && test "`/usr/bin/objformat`" = "elf" ; then + LOCAL_LDFLAGS=-rdynamic # allow dynamic loading + fi ;; +freebsdelf*) LOCAL_LDFLAGS=-rdynamic ;; # allow dynamic loading +esac + +case "$host_cpu" in +*cray*) LOCAL_CFLAGS="-DCRAY" ;; # shell var so config.h can use it +esac + +case "$host_cpu-$host_os" in +ibmrt-*bsd4*) LOCAL_CFLAGS="-ma -U__STDC__" ;; +esac + +case "$host_cpu-$host_vendor-$host_os" in +m88k-motorola-sysv3) LOCAL_CFLAGS=-DWAITPID_BROKEN ;; +mips-pyramid-sysv4) LOCAL_CFLAGS=-Xa ;; +esac + +# +# Shared object configuration section. These values are generated by +# ${srcdir}/support/shobj-conf +# +if test "$ac_cv_func_dlopen" = "yes" && test -f ${srcdir}/support/shobj-conf +then + AC_MSG_CHECKING(shared object configuration for loadable builtins) + eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c "${host_cpu}" -o "${host_os}" -v "${host_vendor}"` + AC_SUBST(SHOBJ_CC) + AC_SUBST(SHOBJ_CFLAGS) + AC_SUBST(SHOBJ_LD) + AC_SUBST(SHOBJ_LDFLAGS) + AC_SUBST(SHOBJ_XLDFLAGS) + AC_SUBST(SHOBJ_LIBS) + AC_SUBST(SHOBJ_STATUS) + AC_MSG_RESULT($SHOBJ_STATUS) +fi + +# try to create a directory tree if the source is elsewhere +# this should be packaged into a script accessible via ${srcdir}/support +case "$srcdir" in +.) ;; +*) for d in doc tests support lib examples; do # dirs + test -d $d || mkdir $d + done + for ld in readline glob tilde malloc sh termcap; do # libdirs + test -d lib/$ld || mkdir lib/$ld + done + test -d examples/loadables || mkdir examples/loadables # loadable builtins + test -d examples/loadables/perl || mkdir examples/loadables/perl + ;; +esac + +BUILD_DIR=`pwd` + +AC_SUBST(PROFILE_FLAGS) + +AC_SUBST(incdir) +AC_SUBST(BUILD_DIR) + +AC_SUBST(YACC) +AC_SUBST(AR) +AC_SUBST(ARFLAGS) + +AC_SUBST(BASHVERS) +AC_SUBST(RELSTATUS) +AC_SUBST(DEBUG) +AC_SUBST(MALLOC_DEBUG) + +AC_SUBST(host_cpu) +AC_SUBST(host_vendor) +AC_SUBST(host_os) + +AC_SUBST(LOCAL_LIBS) +AC_SUBST(LOCAL_CFLAGS) +AC_SUBST(LOCAL_LDFLAGS) +AC_SUBST(LOCAL_DEFS) + +#AC_SUBST(ALLOCA_SOURCE) +#AC_SUBST(ALLOCA_OBJECT) + +AC_OUTPUT([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \ + lib/intl/Makefile \ + lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile \ + lib/tilde/Makefile doc/Makefile support/Makefile po/Makefile.in \ + examples/loadables/Makefile examples/loadables/perl/Makefile \ + pathnames.h], +[ +# Makefile uses this timestamp file to record whether config.h is up to date. +echo timestamp > stamp-h +]) diff --git a/doc/FAQ b/doc/FAQ index c0e902f11..f2f4e37bf 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -1,4 +1,4 @@ -This is the Bash FAQ, version 3.27, for Bash version 3.0. +This is the Bash FAQ, version 3.28, for Bash version 3.0. This document contains a set of frequently-asked questions concerning Bash, the GNU Bourne-Again Shell. Bash is a freely-available command @@ -1763,7 +1763,6 @@ These are features that may or may not appear in a future version of bash. breaking some of the shell functionality into embeddable libraries a module system like zsh's, using dynamic loading like builtins -date-stamped command history a bash programmer's guide with a chapter on creating loadable builtins a better loadable interface to perl with access to the shell builtins and variables (contributions gratefully accepted) diff --git a/lib/readline/misc.c b/lib/readline/misc.c index 3a6578f31..403313a04 100644 --- a/lib/readline/misc.c +++ b/lib/readline/misc.c @@ -276,14 +276,6 @@ rl_maybe_save_line () _rl_saved_line_for_history->line = savestring (rl_line_buffer); _rl_saved_line_for_history->data = (char *)rl_undo_list; } -#if 0 - else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0) - { - free (_rl_saved_line_for_history->line); - _rl_saved_line_for_history->line = savestring (rl_line_buffer); - _rl_saved_line_for_history->data = (char *)rl_undo_list; /* XXX possible memleak */ - } -#endif return 0; } diff --git a/lib/readline/misc.c~ b/lib/readline/misc.c~ index ab1e1337f..3a6578f31 100644 --- a/lib/readline/misc.c~ +++ b/lib/readline/misc.c~ @@ -276,12 +276,14 @@ rl_maybe_save_line () _rl_saved_line_for_history->line = savestring (rl_line_buffer); _rl_saved_line_for_history->data = (char *)rl_undo_list; } +#if 0 else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0) { free (_rl_saved_line_for_history->line); _rl_saved_line_for_history->line = savestring (rl_line_buffer); _rl_saved_line_for_history->data = (char *)rl_undo_list; /* XXX possible memleak */ } +#endif return 0; } diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index 74d8acbbc..2badaa140 100644 --- a/lib/readline/vi_mode.c +++ b/lib/readline/vi_mode.c @@ -272,10 +272,12 @@ rl_vi_search (count, key) switch (key) { case '?': + _rl_free_saved_history_line (); rl_noninc_forward_search (count, key); break; case '/': + _rl_free_saved_history_line (); rl_noninc_reverse_search (count, key); break; @@ -1310,12 +1312,16 @@ rl_vi_change_char (count, key) rl_vi_delete (1, c); #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - while (_rl_insert_char (1, c)) - { - RL_SETSTATE (RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE (RL_STATE_MOREINPUT); - } + { + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; + while (_rl_insert_char (1, c)) + { + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + } else #endif { diff --git a/lib/readline/vi_mode.c.orig b/lib/readline/vi_mode.c.orig new file mode 100644 index 000000000..74d8acbbc --- /dev/null +++ b/lib/readline/vi_mode.c.orig @@ -0,0 +1,1505 @@ +/* vi_mode.c -- A vi emulation mode for Bash. + Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ + +/* Copyright (C) 1987-2004 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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. + + The GNU Readline 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 General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +/* **************************************************************** */ +/* */ +/* VI Emulation Mode */ +/* */ +/* **************************************************************** */ +#include "rlconf.h" + +#if defined (VI_MODE) + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include + +/* Some standard library routines. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +#ifndef member +#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) +#endif + +int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ + +/* Non-zero means enter insertion mode. */ +static int _rl_vi_doing_insert; + +/* Command keys which do movement for xxx_to commands. */ +static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; + +/* Keymap used for vi replace characters. Created dynamically since + rarely used. */ +static Keymap vi_replace_map; + +/* The number of characters inserted in the last replace operation. */ +static int vi_replace_count; + +/* If non-zero, we have text inserted after a c[motion] command that put + us implicitly into insert mode. Some people want this text to be + attached to the command so that it is `redoable' with `.'. */ +static int vi_continued_command; +static char *vi_insert_buffer; +static int vi_insert_buffer_size; + +static int _rl_vi_last_repeat = 1; +static int _rl_vi_last_arg_sign = 1; +static int _rl_vi_last_motion; +#if defined (HANDLE_MULTIBYTE) +static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; +#else +static int _rl_vi_last_search_char; +#endif +static int _rl_vi_last_replacement; + +static int _rl_vi_last_key_before_insert; + +static int vi_redoing; + +/* Text modification commands. These are the `redoable' commands. */ +static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; + +/* Arrays for the saved marks. */ +static int vi_mark_chars['z' - 'a' + 1]; + +static void _rl_vi_stuff_insert PARAMS((int)); +static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); +static int rl_digit_loop1 PARAMS((void)); + +void +_rl_vi_initialize_line () +{ + register int i; + + for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) + vi_mark_chars[i] = -1; +} + +void +_rl_vi_reset_last () +{ + _rl_vi_last_command = 'i'; + _rl_vi_last_repeat = 1; + _rl_vi_last_arg_sign = 1; + _rl_vi_last_motion = 0; +} + +void +_rl_vi_set_last (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_last_command = key; + _rl_vi_last_repeat = repeat; + _rl_vi_last_arg_sign = sign; +} + +/* A convenience function that calls _rl_vi_set_last to save the last command + information and enters insertion mode. */ +void +rl_vi_start_inserting (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_set_last (key, repeat, sign); + rl_vi_insertion_mode (1, key); +} + +/* Is the command C a VI mode text modification command? */ +int +_rl_vi_textmod_command (c) + int c; +{ + return (member (c, vi_textmod)); +} + +static void +_rl_vi_stuff_insert (count) + int count; +{ + rl_begin_undo_group (); + while (count--) + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); +} + +/* Bound to `.'. Called from command mode, so we know that we have to + redo a text modification command. The default for _rl_vi_last_command + puts you back into insert mode. */ +int +rl_vi_redo (count, c) + int count, c; +{ + int r; + + if (!rl_explicit_arg) + { + rl_numeric_arg = _rl_vi_last_repeat; + rl_arg_sign = _rl_vi_last_arg_sign; + } + + r = 0; + vi_redoing = 1; + /* If we're redoing an insert with `i', stuff in the inserted text + and do not go into insertion mode. */ + if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_stuff_insert (count); + /* And back up point over the last character inserted. */ + if (rl_point > 0) + rl_point--; + } + else + r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); + vi_redoing = 0; + + return (r); +} + +/* A placeholder for further expansion. */ +int +rl_vi_undo (count, key) + int count, key; +{ + return (rl_undo_command (count, key)); +} + +/* Yank the nth arg from the previous line into this line at point. */ +int +rl_vi_yank_arg (count, key) + int count, key; +{ + /* Readline thinks that the first word on a line is the 0th, while vi + thinks the first word on a line is the 1st. Compensate. */ + if (rl_explicit_arg) + rl_yank_nth_arg (count - 1, 0); + else + rl_yank_nth_arg ('$', 0); + + return (0); +} + +/* With an argument, move back that many history lines, else move to the + beginning of history. */ +int +rl_vi_fetch_history (count, c) + int count, c; +{ + int wanted; + + /* Giving an argument of n means we want the nth command in the history + file. The command number is interpreted the same way that the bash + `history' command does it -- that is, giving an argument count of 450 + to this command would get the command listed as number 450 in the + output of `history'. */ + if (rl_explicit_arg) + { + wanted = history_base + where_history () - count; + if (wanted <= 0) + rl_beginning_of_history (0, 0); + else + rl_get_previous_history (wanted, c); + } + else + rl_beginning_of_history (count, 0); + return (0); +} + +/* Search again for the last thing searched for. */ +int +rl_vi_search_again (count, key) + int count, key; +{ + switch (key) + { + case 'n': + rl_noninc_reverse_search_again (count, key); + break; + + case 'N': + rl_noninc_forward_search_again (count, key); + break; + } + return (0); +} + +/* Do a vi style search. */ +int +rl_vi_search (count, key) + int count, key; +{ + switch (key) + { + case '?': + rl_noninc_forward_search (count, key); + break; + + case '/': + rl_noninc_reverse_search (count, key); + break; + + default: + rl_ding (); + break; + } + return (0); +} + +/* Completion, from vi's point of view. */ +int +rl_vi_complete (ignore, key) + int ignore, key; +{ + if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) + { + if (!whitespace (rl_line_buffer[rl_point + 1])) + rl_vi_end_word (1, 'E'); + rl_point++; + } + + if (key == '*') + rl_complete_internal ('*'); /* Expansion and replacement. */ + else if (key == '=') + rl_complete_internal ('?'); /* List possible completions. */ + else if (key == '\\') + rl_complete_internal (TAB); /* Standard Readline completion. */ + else + rl_complete (0, key); + + if (key == '*' || key == '\\') + rl_vi_start_inserting (key, 1, rl_arg_sign); + + return (0); +} + +/* Tilde expansion for vi mode. */ +int +rl_vi_tilde_expand (ignore, key) + int ignore, key; +{ + rl_tilde_expand (0, key); + rl_vi_start_inserting (key, 1, rl_arg_sign); + return (0); +} + +/* Previous word in vi mode. */ +int +rl_vi_prev_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_next_word (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_bWord (count, key); + else + rl_vi_bword (count, key); + + return (0); +} + +/* Next word in vi mode. */ +int +rl_vi_next_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_prev_word (-count, key)); + + if (rl_point >= (rl_end - 1)) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_fWord (count, key); + else + rl_vi_fword (count, key); + return (0); +} + +/* Move to the end of the ?next? word. */ +int +rl_vi_end_word (count, key) + int count, key; +{ + if (count < 0) + { + rl_ding (); + return -1; + } + + if (_rl_uppercase_p (key)) + rl_vi_eWord (count, key); + else + rl_vi_eword (count, key); + return (0); +} + +/* Move forward a word the way that 'W' does. */ +int +rl_vi_fWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Skip until whitespace. */ + while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + + /* Now skip whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + /* If we are at the start of a word, move back to whitespace so + we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move to the next non-whitespace character (to the start of the + next word). */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point && rl_point < rl_end) + { + /* Skip whitespace. */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Skip until whitespace. */ + while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move back to the last character of the word. */ + rl_point--; + } + } + return (0); +} + +int +rl_vi_fword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Move to white space (really non-identifer). */ + if (_rl_isident (rl_line_buffer[rl_point])) + { + while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + else /* if (!whitespace (rl_line_buffer[rl_point])) */ + { + while (!_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + + /* Move past whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + int last_is_ident; + + /* If we are at the start of a word, move back to whitespace + so we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + /* If this character and the previous character are `opposite', move + back so we don't get messed up by the rl_point++ down there in + the while loop. Without this code, words like `l;' screw up the + function. */ + last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); + if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || + (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); + else + while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < rl_end - 1) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point < rl_end) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); + else + while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) + && !whitespace (rl_line_buffer[rl_point])); + } + rl_point--; + } + return (0); +} + +int +rl_vi_insert_beg (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + rl_vi_insertion_mode (1, key); + return (0); +} + +int +rl_vi_append_mode (count, key) + int count, key; +{ + if (rl_point < rl_end) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + rl_point++; + else + { + int point = rl_point; + rl_forward_char (1, key); + if (point == rl_point) + rl_point = rl_end; + } + } + rl_vi_insertion_mode (1, key); + return (0); +} + +int +rl_vi_append_eol (count, key) + int count, key; +{ + rl_end_of_line (1, key); + rl_vi_append_mode (1, key); + return (0); +} + +/* What to do in the case of C-d. */ +int +rl_vi_eof_maybe (count, c) + int count, c; +{ + return (rl_newline (1, '\n')); +} + +/* Insertion mode stuff. */ + +/* Switching from one mode to the other really just involves + switching keymaps. */ +int +rl_vi_insertion_mode (count, key) + int count, key; +{ + _rl_keymap = vi_insertion_keymap; + _rl_vi_last_key_before_insert = key; + return (0); +} + +static void +_rl_vi_save_insert (up) + UNDO_LIST *up; +{ + int len, start, end; + + if (up == 0) + { + if (vi_insert_buffer_size >= 1) + vi_insert_buffer[0] = '\0'; + return; + } + + start = up->start; + end = up->end; + len = end - start + 1; + if (len >= vi_insert_buffer_size) + { + vi_insert_buffer_size += (len + 32) - (len % 32); + vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); + } + strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); + vi_insert_buffer[len-1] = '\0'; +} + +void +_rl_vi_done_inserting () +{ + if (_rl_vi_doing_insert) + { + /* The `C', `s', and `S' commands set this. */ + rl_end_undo_group (); + /* Now, the text between rl_undo_list->next->start and + rl_undo_list->next->end is what was inserted while in insert + mode. It gets copied to VI_INSERT_BUFFER because it depends + on absolute indices into the line which may change (though they + probably will not). */ + _rl_vi_doing_insert = 0; + _rl_vi_save_insert (rl_undo_list->next); + vi_continued_command = 1; + } + else + { + if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list) + _rl_vi_save_insert (rl_undo_list); + /* XXX - Other keys probably need to be checked. */ + else if (_rl_vi_last_key_before_insert == 'C') + rl_end_undo_group (); + while (_rl_undo_group_level > 0) + rl_end_undo_group (); + vi_continued_command = 0; + } +} + +int +rl_vi_movement_mode (count, key) + int count, key; +{ + if (rl_point > 0) + rl_backward_char (1, key); + + _rl_keymap = vi_movement_keymap; + _rl_vi_done_inserting (); + return (0); +} + +int +rl_vi_arg_digit (count, c) + int count, c; +{ + if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) + return (rl_beg_of_line (1, c)); + else + return (rl_digit_argument (count, c)); +} + +/* Change the case of the next COUNT characters. */ +#if defined (HANDLE_MULTIBYTE) +static int +_rl_vi_change_mbchar_case (count) + int count; +{ + wchar_t wc; + char mb[MB_LEN_MAX+1]; + int mblen; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) + count--; + while (count-- && rl_point < rl_end) + { + mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); + if (iswupper (wc)) + wc = towlower (wc); + else if (iswlower (wc)) + wc = towupper (wc); + else + { + /* Just skip over chars neither upper nor lower case */ + rl_forward_char (1, 0); + continue; + } + + /* Vi is kind of strange here. */ + if (wc) + { + mblen = wcrtomb (mb, wc, &ps); + if (mblen >= 0) + mb[mblen] = '\0'; + rl_begin_undo_group (); + rl_delete (1, 0); + rl_insert_text (mb); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, 0); + } + + return 0; +} +#endif + +int +rl_vi_change_case (count, ignore) + int count, ignore; +{ + int c, p; + + /* Don't try this on an empty line. */ + if (rl_point >= rl_end) + return (0); + + c = 0; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + return (_rl_vi_change_mbchar_case (count)); +#endif + + while (count-- && rl_point < rl_end) + { + if (_rl_uppercase_p (rl_line_buffer[rl_point])) + c = _rl_to_lower (rl_line_buffer[rl_point]); + else if (_rl_lowercase_p (rl_line_buffer[rl_point])) + c = _rl_to_upper (rl_line_buffer[rl_point]); + else + { + /* Just skip over characters neither upper nor lower case. */ + rl_forward_char (1, c); + continue; + } + + /* Vi is kind of strange here. */ + if (c) + { + p = rl_point; + rl_begin_undo_group (); + rl_vi_delete (1, c); + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; + _rl_insert_char (1, c); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, c); + } + return (0); +} + +int +rl_vi_put (count, key) + int count, key; +{ + if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) + rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + + while (count--) + rl_yank (1, key); + + rl_backward_char (1, key); + return (0); +} + +int +rl_vi_check () +{ + if (rl_point && rl_point == rl_end) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; + } + return (0); +} + +int +rl_vi_column (count, key) + int count, key; +{ + if (count > rl_end) + rl_end_of_line (1, key); + else + rl_point = count - 1; + return (0); +} + +int +rl_vi_domove (key, nextkey) + int key, *nextkey; +{ + int c, save; + int old_end; + + rl_mark = rl_point; + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + *nextkey = c; + + if (!member (c, vi_motion)) + { + if (_rl_digit_p (c)) + { + save = rl_numeric_arg; + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + rl_digit_loop1 (); + rl_numeric_arg *= save; + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); /* real command */ + RL_UNSETSTATE(RL_STATE_MOREINPUT); + *nextkey = c; + } + else if (key == c && (key == 'd' || key == 'y' || key == 'c')) + { + rl_mark = rl_end; + rl_beg_of_line (1, c); + _rl_vi_last_motion = c; + return (0); + } + else + return (-1); + } + + _rl_vi_last_motion = c; + + /* Append a blank character temporarily so that the motion routines + work right at the end of the line. */ + old_end = rl_end; + rl_line_buffer[rl_end++] = ' '; + rl_line_buffer[rl_end] = '\0'; + + _rl_dispatch (c, _rl_keymap); + + /* Remove the blank that we added. */ + rl_end = old_end; + rl_line_buffer[rl_end] = '\0'; + if (rl_point > rl_end) + rl_point = rl_end; + + /* No change in position means the command failed. */ + if (rl_mark == rl_point) + return (-1); + + /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next + word. If we are not at the end of the line, and we are on a + non-whitespace character, move back one (presumably to whitespace). */ + if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && + !whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* If cw or cW, back up to the end of a word, so the behaviour of ce + or cE is the actual result. Brute-force, no subtlety. */ + if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) + { + /* Don't move farther back than where we started. */ + while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* Posix.2 says that if cw or cW moves the cursor towards the end of + the line, the character under the cursor should be deleted. */ + if (rl_point == rl_mark) + rl_point++; + else + { + /* Move past the end of the word so that the kill doesn't + remove the last letter of the previous word. Only do this + if we are not at the end of the line. */ + if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + } + } + + if (rl_mark < rl_point) + SWAP (rl_point, rl_mark); + + return (0); +} + +/* A simplified loop for vi. Don't dispatch key at end. + Don't recognize minus sign? + Should this do rl_save_prompt/rl_restore_prompt? */ +static int +rl_digit_loop1 () +{ + int key, c; + + RL_SETSTATE(RL_STATE_NUMERICARG); + while (1) + { + if (rl_numeric_arg > 1000000) + { + rl_explicit_arg = rl_numeric_arg = 0; + rl_ding (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return 1; + } + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + RL_SETSTATE(RL_STATE_MOREINPUT); + key = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c >= 0 && _rl_keymap[c].type == ISFUNC && + _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + continue; + } + + c = UNMETA (c); + if (_rl_digit_p (c)) + { + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); + else + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + } + else + { + rl_clear_message (); + rl_stuff_char (key); + break; + } + } + + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (0); +} + +int +rl_vi_delete_to (count, key) + int count, key; +{ + int c; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_kill_text (rl_point, rl_mark); + return (0); +} + +int +rl_vi_change_to (count, key) + int count, key; +{ + int c, start_pos; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + start_pos = rl_point; + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. c[wW] are handled by special-case code in rl_vi_domove(), + and already leave the mark at the correct location. */ + if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + /* The cursor never moves with c[wW]. */ + if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) + rl_point = start_pos; + + if (vi_redoing) + { + if (vi_insert_buffer && *vi_insert_buffer) + rl_begin_undo_group (); + rl_delete_text (rl_point, rl_mark); + if (vi_insert_buffer && *vi_insert_buffer) + { + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); + } + } + else + { + rl_begin_undo_group (); /* to make the `u' command work */ + rl_kill_text (rl_point, rl_mark); + /* `C' does not save the text inserted for undoing or redoing. */ + if (_rl_uppercase_p (key) == 0) + _rl_vi_doing_insert = 1; + rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign); + } + + return (0); +} + +int +rl_vi_yank_to (count, key) + int count, key; +{ + int c, save = rl_point; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_begin_undo_group (); + rl_kill_text (rl_point, rl_mark); + rl_end_undo_group (); + rl_do_undo (); + rl_point = save; + + return (0); +} + +int +rl_vi_delete (count, key) + int count, key; +{ + int end; + + if (rl_end == 0) + { + rl_ding (); + return -1; + } + + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + else + end = rl_point + count; + + if (end >= rl_end) + end = rl_end; + + rl_kill_text (rl_point, end); + + if (rl_point > 0 && rl_point == rl_end) + rl_backward_char (1, key); + return (0); +} + +int +rl_vi_back_to_indent (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + return (0); +} + +int +rl_vi_first_print (count, key) + int count, key; +{ + return (rl_vi_back_to_indent (1, key)); +} + +int +rl_vi_char_search (count, key) + int count, key; +{ +#if defined (HANDLE_MULTIBYTE) + static char *target; + static int mb_len; +#else + static char target; +#endif + static int orig_dir, dir; + + if (key == ';' || key == ',') + dir = key == ';' ? orig_dir : -orig_dir; + else + { + if (vi_redoing) +#if defined (HANDLE_MULTIBYTE) + target = _rl_vi_last_search_mbchar; +#else + target = _rl_vi_last_search_char; +#endif + else + { +#if defined (HANDLE_MULTIBYTE) + mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + target = _rl_vi_last_search_mbchar; +#else + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_search_char = target = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); +#endif + } + + switch (key) + { + case 't': + orig_dir = dir = FTO; + break; + + case 'T': + orig_dir = dir = BTO; + break; + + case 'f': + orig_dir = dir = FFIND; + break; + + case 'F': + orig_dir = dir = BFIND; + break; + } + } + +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (count, dir, target, mb_len)); +#else + return (_rl_char_search_internal (count, dir, target)); +#endif +} + +/* Match brackets */ +int +rl_vi_match (ignore, key) + int ignore, key; +{ + int count = 1, brack, pos, tmp, pre; + + pos = rl_point; + if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + pre = rl_point; + rl_forward_char (1, key); + if (pre == rl_point) + break; + } + } + else + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && + rl_point < rl_end - 1) + rl_forward_char (1, key); + + if (brack <= 0) + { + rl_point = pos; + rl_ding (); + return -1; + } + } + + pos = rl_point; + + if (brack < 0) + { + while (count) + { + tmp = pos; + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos--; + else + { + pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); + if (tmp == pos) + pos--; + } + if (pos >= 0) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + else + { /* brack > 0 */ + while (count) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos++; + else + pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY); + + if (pos < rl_end) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + rl_point = pos; + return (0); +} + +int +rl_vi_bracktype (c) + int c; +{ + switch (c) + { + case '(': return 1; + case ')': return -1; + case '[': return 2; + case ']': return -2; + case '{': return 3; + case '}': return -3; + default: return 0; + } +} + +/* XXX - think about reading an entire mbchar with _rl_read_mbchar and + inserting it in one bunch instead of the loop below (like in + rl_vi_char_search or _rl_vi_change_mbchar_case). Set c to mbchar[0] + for test against 033 or ^C. Make sure that _rl_read_mbchar does + this right. */ +int +rl_vi_change_char (count, key) + int count, key; +{ + int c, p; + + if (vi_redoing) + c = _rl_vi_last_replacement; + else + { + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_replacement = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + } + + if (c == '\033' || c == CTRL ('C')) + return -1; + + rl_begin_undo_group (); + while (count-- && rl_point < rl_end) + { + p = rl_point; + rl_vi_delete (1, c); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + while (_rl_insert_char (1, c)) + { + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + else +#endif + { + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; + _rl_insert_char (1, c); + } + } + rl_end_undo_group (); + + return (0); +} + +int +rl_vi_subst (count, key) + int count, key; +{ + /* If we are redoing, rl_vi_change_to will stuff the last motion char */ + if (vi_redoing == 0) + rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */ + + return (rl_vi_change_to (count, 'c')); +} + +int +rl_vi_overstrike (count, key) + int count, key; +{ + if (_rl_vi_doing_insert == 0) + { + _rl_vi_doing_insert = 1; + rl_begin_undo_group (); + } + + if (count > 0) + { + _rl_overwrite_char (count, key); + vi_replace_count += count; + } + + return (0); +} + +int +rl_vi_overstrike_delete (count, key) + int count, key; +{ + int i, s; + + for (i = 0; i < count; i++) + { + if (vi_replace_count == 0) + { + rl_ding (); + break; + } + s = rl_point; + + if (rl_do_undo ()) + vi_replace_count--; + + if (rl_point == s) + rl_backward_char (1, key); + } + + if (vi_replace_count == 0 && _rl_vi_doing_insert) + { + rl_end_undo_group (); + rl_do_undo (); + _rl_vi_doing_insert = 0; + } + return (0); +} + +int +rl_vi_replace (count, key) + int count, key; +{ + int i; + + vi_replace_count = 0; + + if (!vi_replace_map) + { + vi_replace_map = rl_make_bare_keymap (); + + for (i = ' '; i < KEYMAP_SIZE; i++) + vi_replace_map[i].function = rl_vi_overstrike; + + vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; + vi_replace_map[ESC].function = rl_vi_movement_mode; + vi_replace_map[RETURN].function = rl_newline; + vi_replace_map[NEWLINE].function = rl_newline; + + /* If the normal vi insertion keymap has ^H bound to erase, do the + same here. Probably should remove the assignment to RUBOUT up + there, but I don't think it will make a difference in real life. */ + if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && + vi_insertion_keymap[CTRL ('H')].function == rl_rubout) + vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; + + } + _rl_keymap = vi_replace_map; + return (0); +} + +#if 0 +/* Try to complete the word we are standing on or the word that ends with + the previous character. A space matches everything. Word delimiters are + space and ;. */ +int +rl_vi_possible_completions() +{ + int save_pos = rl_point; + + if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') + { + while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && + rl_line_buffer[rl_point] != ';') + rl_point++; + } + else if (rl_line_buffer[rl_point - 1] == ';') + { + rl_ding (); + return (0); + } + + rl_possible_completions (); + rl_point = save_pos; + + return (0); +} +#endif + +/* Functions to save and restore marks. */ +int +rl_vi_set_mark (count, key) + int count, key; +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch < 'a' || ch > 'z') + { + rl_ding (); + return -1; + } + ch -= 'a'; + vi_mark_chars[ch] = rl_point; + return 0; +} + +int +rl_vi_goto_mark (count, key) + int count, key; +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch == '`') + { + rl_point = rl_mark; + return 0; + } + else if (ch < 'a' || ch > 'z') + { + rl_ding (); + return -1; + } + + ch -= 'a'; + if (vi_mark_chars[ch] == -1) + { + rl_ding (); + return -1; + } + rl_point = vi_mark_chars[ch]; + return 0; +} + +#endif /* VI_MODE */ diff --git a/lib/readline/vi_mode.c~ b/lib/readline/vi_mode.c~ new file mode 100644 index 000000000..2badaa140 --- /dev/null +++ b/lib/readline/vi_mode.c~ @@ -0,0 +1,1511 @@ +/* vi_mode.c -- A vi emulation mode for Bash. + Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ + +/* Copyright (C) 1987-2004 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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. + + The GNU Readline 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 General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +/* **************************************************************** */ +/* */ +/* VI Emulation Mode */ +/* */ +/* **************************************************************** */ +#include "rlconf.h" + +#if defined (VI_MODE) + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include + +/* Some standard library routines. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +#ifndef member +#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) +#endif + +int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ + +/* Non-zero means enter insertion mode. */ +static int _rl_vi_doing_insert; + +/* Command keys which do movement for xxx_to commands. */ +static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; + +/* Keymap used for vi replace characters. Created dynamically since + rarely used. */ +static Keymap vi_replace_map; + +/* The number of characters inserted in the last replace operation. */ +static int vi_replace_count; + +/* If non-zero, we have text inserted after a c[motion] command that put + us implicitly into insert mode. Some people want this text to be + attached to the command so that it is `redoable' with `.'. */ +static int vi_continued_command; +static char *vi_insert_buffer; +static int vi_insert_buffer_size; + +static int _rl_vi_last_repeat = 1; +static int _rl_vi_last_arg_sign = 1; +static int _rl_vi_last_motion; +#if defined (HANDLE_MULTIBYTE) +static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; +#else +static int _rl_vi_last_search_char; +#endif +static int _rl_vi_last_replacement; + +static int _rl_vi_last_key_before_insert; + +static int vi_redoing; + +/* Text modification commands. These are the `redoable' commands. */ +static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; + +/* Arrays for the saved marks. */ +static int vi_mark_chars['z' - 'a' + 1]; + +static void _rl_vi_stuff_insert PARAMS((int)); +static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); +static int rl_digit_loop1 PARAMS((void)); + +void +_rl_vi_initialize_line () +{ + register int i; + + for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) + vi_mark_chars[i] = -1; +} + +void +_rl_vi_reset_last () +{ + _rl_vi_last_command = 'i'; + _rl_vi_last_repeat = 1; + _rl_vi_last_arg_sign = 1; + _rl_vi_last_motion = 0; +} + +void +_rl_vi_set_last (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_last_command = key; + _rl_vi_last_repeat = repeat; + _rl_vi_last_arg_sign = sign; +} + +/* A convenience function that calls _rl_vi_set_last to save the last command + information and enters insertion mode. */ +void +rl_vi_start_inserting (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_set_last (key, repeat, sign); + rl_vi_insertion_mode (1, key); +} + +/* Is the command C a VI mode text modification command? */ +int +_rl_vi_textmod_command (c) + int c; +{ + return (member (c, vi_textmod)); +} + +static void +_rl_vi_stuff_insert (count) + int count; +{ + rl_begin_undo_group (); + while (count--) + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); +} + +/* Bound to `.'. Called from command mode, so we know that we have to + redo a text modification command. The default for _rl_vi_last_command + puts you back into insert mode. */ +int +rl_vi_redo (count, c) + int count, c; +{ + int r; + + if (!rl_explicit_arg) + { + rl_numeric_arg = _rl_vi_last_repeat; + rl_arg_sign = _rl_vi_last_arg_sign; + } + + r = 0; + vi_redoing = 1; + /* If we're redoing an insert with `i', stuff in the inserted text + and do not go into insertion mode. */ + if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_stuff_insert (count); + /* And back up point over the last character inserted. */ + if (rl_point > 0) + rl_point--; + } + else + r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); + vi_redoing = 0; + + return (r); +} + +/* A placeholder for further expansion. */ +int +rl_vi_undo (count, key) + int count, key; +{ + return (rl_undo_command (count, key)); +} + +/* Yank the nth arg from the previous line into this line at point. */ +int +rl_vi_yank_arg (count, key) + int count, key; +{ + /* Readline thinks that the first word on a line is the 0th, while vi + thinks the first word on a line is the 1st. Compensate. */ + if (rl_explicit_arg) + rl_yank_nth_arg (count - 1, 0); + else + rl_yank_nth_arg ('$', 0); + + return (0); +} + +/* With an argument, move back that many history lines, else move to the + beginning of history. */ +int +rl_vi_fetch_history (count, c) + int count, c; +{ + int wanted; + + /* Giving an argument of n means we want the nth command in the history + file. The command number is interpreted the same way that the bash + `history' command does it -- that is, giving an argument count of 450 + to this command would get the command listed as number 450 in the + output of `history'. */ + if (rl_explicit_arg) + { + wanted = history_base + where_history () - count; + if (wanted <= 0) + rl_beginning_of_history (0, 0); + else + rl_get_previous_history (wanted, c); + } + else + rl_beginning_of_history (count, 0); + return (0); +} + +/* Search again for the last thing searched for. */ +int +rl_vi_search_again (count, key) + int count, key; +{ + switch (key) + { + case 'n': + rl_noninc_reverse_search_again (count, key); + break; + + case 'N': + rl_noninc_forward_search_again (count, key); + break; + } + return (0); +} + +/* Do a vi style search. */ +int +rl_vi_search (count, key) + int count, key; +{ + switch (key) + { + case '?': + _rl_free_saved_history_line (); + rl_noninc_forward_search (count, key); + break; + + case '/': + _rl_free_saved_history_line (); + rl_noninc_reverse_search (count, key); + break; + + default: + rl_ding (); + break; + } + return (0); +} + +/* Completion, from vi's point of view. */ +int +rl_vi_complete (ignore, key) + int ignore, key; +{ + if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) + { + if (!whitespace (rl_line_buffer[rl_point + 1])) + rl_vi_end_word (1, 'E'); + rl_point++; + } + + if (key == '*') + rl_complete_internal ('*'); /* Expansion and replacement. */ + else if (key == '=') + rl_complete_internal ('?'); /* List possible completions. */ + else if (key == '\\') + rl_complete_internal (TAB); /* Standard Readline completion. */ + else + rl_complete (0, key); + + if (key == '*' || key == '\\') + rl_vi_start_inserting (key, 1, rl_arg_sign); + + return (0); +} + +/* Tilde expansion for vi mode. */ +int +rl_vi_tilde_expand (ignore, key) + int ignore, key; +{ + rl_tilde_expand (0, key); + rl_vi_start_inserting (key, 1, rl_arg_sign); + return (0); +} + +/* Previous word in vi mode. */ +int +rl_vi_prev_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_next_word (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_bWord (count, key); + else + rl_vi_bword (count, key); + + return (0); +} + +/* Next word in vi mode. */ +int +rl_vi_next_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_prev_word (-count, key)); + + if (rl_point >= (rl_end - 1)) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_fWord (count, key); + else + rl_vi_fword (count, key); + return (0); +} + +/* Move to the end of the ?next? word. */ +int +rl_vi_end_word (count, key) + int count, key; +{ + if (count < 0) + { + rl_ding (); + return -1; + } + + if (_rl_uppercase_p (key)) + rl_vi_eWord (count, key); + else + rl_vi_eword (count, key); + return (0); +} + +/* Move forward a word the way that 'W' does. */ +int +rl_vi_fWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Skip until whitespace. */ + while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + + /* Now skip whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + /* If we are at the start of a word, move back to whitespace so + we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move to the next non-whitespace character (to the start of the + next word). */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point && rl_point < rl_end) + { + /* Skip whitespace. */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Skip until whitespace. */ + while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move back to the last character of the word. */ + rl_point--; + } + } + return (0); +} + +int +rl_vi_fword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Move to white space (really non-identifer). */ + if (_rl_isident (rl_line_buffer[rl_point])) + { + while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + else /* if (!whitespace (rl_line_buffer[rl_point])) */ + { + while (!_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + + /* Move past whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + int last_is_ident; + + /* If we are at the start of a word, move back to whitespace + so we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + /* If this character and the previous character are `opposite', move + back so we don't get messed up by the rl_point++ down there in + the while loop. Without this code, words like `l;' screw up the + function. */ + last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); + if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || + (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); + else + while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < rl_end - 1) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point < rl_end) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); + else + while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) + && !whitespace (rl_line_buffer[rl_point])); + } + rl_point--; + } + return (0); +} + +int +rl_vi_insert_beg (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + rl_vi_insertion_mode (1, key); + return (0); +} + +int +rl_vi_append_mode (count, key) + int count, key; +{ + if (rl_point < rl_end) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + rl_point++; + else + { + int point = rl_point; + rl_forward_char (1, key); + if (point == rl_point) + rl_point = rl_end; + } + } + rl_vi_insertion_mode (1, key); + return (0); +} + +int +rl_vi_append_eol (count, key) + int count, key; +{ + rl_end_of_line (1, key); + rl_vi_append_mode (1, key); + return (0); +} + +/* What to do in the case of C-d. */ +int +rl_vi_eof_maybe (count, c) + int count, c; +{ + return (rl_newline (1, '\n')); +} + +/* Insertion mode stuff. */ + +/* Switching from one mode to the other really just involves + switching keymaps. */ +int +rl_vi_insertion_mode (count, key) + int count, key; +{ + _rl_keymap = vi_insertion_keymap; + _rl_vi_last_key_before_insert = key; + return (0); +} + +static void +_rl_vi_save_insert (up) + UNDO_LIST *up; +{ + int len, start, end; + + if (up == 0) + { + if (vi_insert_buffer_size >= 1) + vi_insert_buffer[0] = '\0'; + return; + } + + start = up->start; + end = up->end; + len = end - start + 1; + if (len >= vi_insert_buffer_size) + { + vi_insert_buffer_size += (len + 32) - (len % 32); + vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); + } + strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); + vi_insert_buffer[len-1] = '\0'; +} + +void +_rl_vi_done_inserting () +{ + if (_rl_vi_doing_insert) + { + /* The `C', `s', and `S' commands set this. */ + rl_end_undo_group (); + /* Now, the text between rl_undo_list->next->start and + rl_undo_list->next->end is what was inserted while in insert + mode. It gets copied to VI_INSERT_BUFFER because it depends + on absolute indices into the line which may change (though they + probably will not). */ + _rl_vi_doing_insert = 0; + _rl_vi_save_insert (rl_undo_list->next); + vi_continued_command = 1; + } + else + { + if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list) + _rl_vi_save_insert (rl_undo_list); + /* XXX - Other keys probably need to be checked. */ + else if (_rl_vi_last_key_before_insert == 'C') + rl_end_undo_group (); + while (_rl_undo_group_level > 0) + rl_end_undo_group (); + vi_continued_command = 0; + } +} + +int +rl_vi_movement_mode (count, key) + int count, key; +{ + if (rl_point > 0) + rl_backward_char (1, key); + + _rl_keymap = vi_movement_keymap; + _rl_vi_done_inserting (); + return (0); +} + +int +rl_vi_arg_digit (count, c) + int count, c; +{ + if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) + return (rl_beg_of_line (1, c)); + else + return (rl_digit_argument (count, c)); +} + +/* Change the case of the next COUNT characters. */ +#if defined (HANDLE_MULTIBYTE) +static int +_rl_vi_change_mbchar_case (count) + int count; +{ + wchar_t wc; + char mb[MB_LEN_MAX+1]; + int mblen; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) + count--; + while (count-- && rl_point < rl_end) + { + mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); + if (iswupper (wc)) + wc = towlower (wc); + else if (iswlower (wc)) + wc = towupper (wc); + else + { + /* Just skip over chars neither upper nor lower case */ + rl_forward_char (1, 0); + continue; + } + + /* Vi is kind of strange here. */ + if (wc) + { + mblen = wcrtomb (mb, wc, &ps); + if (mblen >= 0) + mb[mblen] = '\0'; + rl_begin_undo_group (); + rl_delete (1, 0); + rl_insert_text (mb); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, 0); + } + + return 0; +} +#endif + +int +rl_vi_change_case (count, ignore) + int count, ignore; +{ + int c, p; + + /* Don't try this on an empty line. */ + if (rl_point >= rl_end) + return (0); + + c = 0; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + return (_rl_vi_change_mbchar_case (count)); +#endif + + while (count-- && rl_point < rl_end) + { + if (_rl_uppercase_p (rl_line_buffer[rl_point])) + c = _rl_to_lower (rl_line_buffer[rl_point]); + else if (_rl_lowercase_p (rl_line_buffer[rl_point])) + c = _rl_to_upper (rl_line_buffer[rl_point]); + else + { + /* Just skip over characters neither upper nor lower case. */ + rl_forward_char (1, c); + continue; + } + + /* Vi is kind of strange here. */ + if (c) + { + p = rl_point; + rl_begin_undo_group (); + rl_vi_delete (1, c); + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; + _rl_insert_char (1, c); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, c); + } + return (0); +} + +int +rl_vi_put (count, key) + int count, key; +{ + if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) + rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + + while (count--) + rl_yank (1, key); + + rl_backward_char (1, key); + return (0); +} + +int +rl_vi_check () +{ + if (rl_point && rl_point == rl_end) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; + } + return (0); +} + +int +rl_vi_column (count, key) + int count, key; +{ + if (count > rl_end) + rl_end_of_line (1, key); + else + rl_point = count - 1; + return (0); +} + +int +rl_vi_domove (key, nextkey) + int key, *nextkey; +{ + int c, save; + int old_end; + + rl_mark = rl_point; + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + *nextkey = c; + + if (!member (c, vi_motion)) + { + if (_rl_digit_p (c)) + { + save = rl_numeric_arg; + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + rl_digit_loop1 (); + rl_numeric_arg *= save; + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); /* real command */ + RL_UNSETSTATE(RL_STATE_MOREINPUT); + *nextkey = c; + } + else if (key == c && (key == 'd' || key == 'y' || key == 'c')) + { + rl_mark = rl_end; + rl_beg_of_line (1, c); + _rl_vi_last_motion = c; + return (0); + } + else + return (-1); + } + + _rl_vi_last_motion = c; + + /* Append a blank character temporarily so that the motion routines + work right at the end of the line. */ + old_end = rl_end; + rl_line_buffer[rl_end++] = ' '; + rl_line_buffer[rl_end] = '\0'; + + _rl_dispatch (c, _rl_keymap); + + /* Remove the blank that we added. */ + rl_end = old_end; + rl_line_buffer[rl_end] = '\0'; + if (rl_point > rl_end) + rl_point = rl_end; + + /* No change in position means the command failed. */ + if (rl_mark == rl_point) + return (-1); + + /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next + word. If we are not at the end of the line, and we are on a + non-whitespace character, move back one (presumably to whitespace). */ + if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && + !whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* If cw or cW, back up to the end of a word, so the behaviour of ce + or cE is the actual result. Brute-force, no subtlety. */ + if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) + { + /* Don't move farther back than where we started. */ + while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* Posix.2 says that if cw or cW moves the cursor towards the end of + the line, the character under the cursor should be deleted. */ + if (rl_point == rl_mark) + rl_point++; + else + { + /* Move past the end of the word so that the kill doesn't + remove the last letter of the previous word. Only do this + if we are not at the end of the line. */ + if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + } + } + + if (rl_mark < rl_point) + SWAP (rl_point, rl_mark); + + return (0); +} + +/* A simplified loop for vi. Don't dispatch key at end. + Don't recognize minus sign? + Should this do rl_save_prompt/rl_restore_prompt? */ +static int +rl_digit_loop1 () +{ + int key, c; + + RL_SETSTATE(RL_STATE_NUMERICARG); + while (1) + { + if (rl_numeric_arg > 1000000) + { + rl_explicit_arg = rl_numeric_arg = 0; + rl_ding (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return 1; + } + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + RL_SETSTATE(RL_STATE_MOREINPUT); + key = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c >= 0 && _rl_keymap[c].type == ISFUNC && + _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + continue; + } + + c = UNMETA (c); + if (_rl_digit_p (c)) + { + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); + else + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + } + else + { + rl_clear_message (); + rl_stuff_char (key); + break; + } + } + + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (0); +} + +int +rl_vi_delete_to (count, key) + int count, key; +{ + int c; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_kill_text (rl_point, rl_mark); + return (0); +} + +int +rl_vi_change_to (count, key) + int count, key; +{ + int c, start_pos; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + start_pos = rl_point; + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. c[wW] are handled by special-case code in rl_vi_domove(), + and already leave the mark at the correct location. */ + if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + /* The cursor never moves with c[wW]. */ + if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) + rl_point = start_pos; + + if (vi_redoing) + { + if (vi_insert_buffer && *vi_insert_buffer) + rl_begin_undo_group (); + rl_delete_text (rl_point, rl_mark); + if (vi_insert_buffer && *vi_insert_buffer) + { + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); + } + } + else + { + rl_begin_undo_group (); /* to make the `u' command work */ + rl_kill_text (rl_point, rl_mark); + /* `C' does not save the text inserted for undoing or redoing. */ + if (_rl_uppercase_p (key) == 0) + _rl_vi_doing_insert = 1; + rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign); + } + + return (0); +} + +int +rl_vi_yank_to (count, key) + int count, key; +{ + int c, save = rl_point; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_begin_undo_group (); + rl_kill_text (rl_point, rl_mark); + rl_end_undo_group (); + rl_do_undo (); + rl_point = save; + + return (0); +} + +int +rl_vi_delete (count, key) + int count, key; +{ + int end; + + if (rl_end == 0) + { + rl_ding (); + return -1; + } + + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + else + end = rl_point + count; + + if (end >= rl_end) + end = rl_end; + + rl_kill_text (rl_point, end); + + if (rl_point > 0 && rl_point == rl_end) + rl_backward_char (1, key); + return (0); +} + +int +rl_vi_back_to_indent (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + return (0); +} + +int +rl_vi_first_print (count, key) + int count, key; +{ + return (rl_vi_back_to_indent (1, key)); +} + +int +rl_vi_char_search (count, key) + int count, key; +{ +#if defined (HANDLE_MULTIBYTE) + static char *target; + static int mb_len; +#else + static char target; +#endif + static int orig_dir, dir; + + if (key == ';' || key == ',') + dir = key == ';' ? orig_dir : -orig_dir; + else + { + if (vi_redoing) +#if defined (HANDLE_MULTIBYTE) + target = _rl_vi_last_search_mbchar; +#else + target = _rl_vi_last_search_char; +#endif + else + { +#if defined (HANDLE_MULTIBYTE) + mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + target = _rl_vi_last_search_mbchar; +#else + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_search_char = target = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); +#endif + } + + switch (key) + { + case 't': + orig_dir = dir = FTO; + break; + + case 'T': + orig_dir = dir = BTO; + break; + + case 'f': + orig_dir = dir = FFIND; + break; + + case 'F': + orig_dir = dir = BFIND; + break; + } + } + +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (count, dir, target, mb_len)); +#else + return (_rl_char_search_internal (count, dir, target)); +#endif +} + +/* Match brackets */ +int +rl_vi_match (ignore, key) + int ignore, key; +{ + int count = 1, brack, pos, tmp, pre; + + pos = rl_point; + if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + pre = rl_point; + rl_forward_char (1, key); + if (pre == rl_point) + break; + } + } + else + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && + rl_point < rl_end - 1) + rl_forward_char (1, key); + + if (brack <= 0) + { + rl_point = pos; + rl_ding (); + return -1; + } + } + + pos = rl_point; + + if (brack < 0) + { + while (count) + { + tmp = pos; + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos--; + else + { + pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); + if (tmp == pos) + pos--; + } + if (pos >= 0) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + else + { /* brack > 0 */ + while (count) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos++; + else + pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY); + + if (pos < rl_end) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + rl_point = pos; + return (0); +} + +int +rl_vi_bracktype (c) + int c; +{ + switch (c) + { + case '(': return 1; + case ')': return -1; + case '[': return 2; + case ']': return -2; + case '{': return 3; + case '}': return -3; + default: return 0; + } +} + +/* XXX - think about reading an entire mbchar with _rl_read_mbchar and + inserting it in one bunch instead of the loop below (like in + rl_vi_char_search or _rl_vi_change_mbchar_case). Set c to mbchar[0] + for test against 033 or ^C. Make sure that _rl_read_mbchar does + this right. */ +int +rl_vi_change_char (count, key) + int count, key; +{ + int c, p; + + if (vi_redoing) + c = _rl_vi_last_replacement; + else + { + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_replacement = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + } + + if (c == '\033' || c == CTRL ('C')) + return -1; + + rl_begin_undo_group (); + while (count-- && rl_point < rl_end) + { + p = rl_point; + rl_vi_delete (1, c); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; + while (_rl_insert_char (1, c)) + { + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + } + else +#endif + { + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; + _rl_insert_char (1, c); + } + } + rl_end_undo_group (); + + return (0); +} + +int +rl_vi_subst (count, key) + int count, key; +{ + /* If we are redoing, rl_vi_change_to will stuff the last motion char */ + if (vi_redoing == 0) + rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */ + + return (rl_vi_change_to (count, 'c')); +} + +int +rl_vi_overstrike (count, key) + int count, key; +{ + if (_rl_vi_doing_insert == 0) + { + _rl_vi_doing_insert = 1; + rl_begin_undo_group (); + } + + if (count > 0) + { + _rl_overwrite_char (count, key); + vi_replace_count += count; + } + + return (0); +} + +int +rl_vi_overstrike_delete (count, key) + int count, key; +{ + int i, s; + + for (i = 0; i < count; i++) + { + if (vi_replace_count == 0) + { + rl_ding (); + break; + } + s = rl_point; + + if (rl_do_undo ()) + vi_replace_count--; + + if (rl_point == s) + rl_backward_char (1, key); + } + + if (vi_replace_count == 0 && _rl_vi_doing_insert) + { + rl_end_undo_group (); + rl_do_undo (); + _rl_vi_doing_insert = 0; + } + return (0); +} + +int +rl_vi_replace (count, key) + int count, key; +{ + int i; + + vi_replace_count = 0; + + if (!vi_replace_map) + { + vi_replace_map = rl_make_bare_keymap (); + + for (i = ' '; i < KEYMAP_SIZE; i++) + vi_replace_map[i].function = rl_vi_overstrike; + + vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; + vi_replace_map[ESC].function = rl_vi_movement_mode; + vi_replace_map[RETURN].function = rl_newline; + vi_replace_map[NEWLINE].function = rl_newline; + + /* If the normal vi insertion keymap has ^H bound to erase, do the + same here. Probably should remove the assignment to RUBOUT up + there, but I don't think it will make a difference in real life. */ + if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && + vi_insertion_keymap[CTRL ('H')].function == rl_rubout) + vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; + + } + _rl_keymap = vi_replace_map; + return (0); +} + +#if 0 +/* Try to complete the word we are standing on or the word that ends with + the previous character. A space matches everything. Word delimiters are + space and ;. */ +int +rl_vi_possible_completions() +{ + int save_pos = rl_point; + + if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') + { + while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && + rl_line_buffer[rl_point] != ';') + rl_point++; + } + else if (rl_line_buffer[rl_point - 1] == ';') + { + rl_ding (); + return (0); + } + + rl_possible_completions (); + rl_point = save_pos; + + return (0); +} +#endif + +/* Functions to save and restore marks. */ +int +rl_vi_set_mark (count, key) + int count, key; +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch < 'a' || ch > 'z') + { + rl_ding (); + return -1; + } + ch -= 'a'; + vi_mark_chars[ch] = rl_point; + return 0; +} + +int +rl_vi_goto_mark (count, key) + int count, key; +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch == '`') + { + rl_point = rl_mark; + return 0; + } + else if (ch < 'a' || ch > 'z') + { + rl_ding (); + return -1; + } + + ch -= 'a'; + if (vi_mark_chars[ch] == -1) + { + rl_ding (); + return -1; + } + rl_point = vi_mark_chars[ch]; + return 0; +} + +#endif /* VI_MODE */ diff --git a/subst.c b/subst.c index c449a830a..5a6654dfd 100644 --- a/subst.c +++ b/subst.c @@ -4911,7 +4911,7 @@ verify_substring_values (value, substr, vtype, e1p, e2p) if (*e1p < 0) /* negative offsets count from end */ *e1p += len; - if (*e1p >= len || *e1p < 0) + if (*e1p > len || *e1p < 0) return (-1); #if defined (ARRAY_VARS) diff --git a/subst.c~ b/subst.c~ index e8bc9f65f..75ecfe188 100644 --- a/subst.c~ +++ b/subst.c~ @@ -4911,7 +4911,11 @@ verify_substring_values (value, substr, vtype, e1p, e2p) if (*e1p < 0) /* negative offsets count from end */ *e1p += len; +#if 0 if (*e1p >= len || *e1p < 0) +#else + if (*e1p > len || *e1p < 0) +#endif return (-1); #if defined (ARRAY_VARS) @@ -5002,7 +5006,7 @@ get_var_and_type (varname, value, quoted, varp, valp) else return -1; } - else if ((v = find_variable (varname)) && invisible_p (v) == 0 && array_p (v)) + else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && array_p (v)) { vtype = VT_ARRAYMEMBER; *varp = v; diff --git a/support/Makefile.in b/support/Makefile.in index 9aacc2f55..b49bd45de 100644 --- a/support/Makefile.in +++ b/support/Makefile.in @@ -81,7 +81,7 @@ man2html$(EXEEXT): $(OBJ1) clean: $(RM) man2html$(EXEEXT) -distclean maintainer-clean mostly-clean: clean +distclean maintainer-clean mostlyclean: clean $(RM) $(OBJ1) man2html.o: man2html.c diff --git a/support/Makefile.in~ b/support/Makefile.in~ new file mode 100644 index 000000000..9aacc2f55 --- /dev/null +++ b/support/Makefile.in~ @@ -0,0 +1,87 @@ +# +# Simple Makefile for the support programs. +# +# documentation support: man2html +# testing support: printenv recho zecho +# +# bashbug lives here but is created by the top-level makefile +# +# Currently only man2html is built +# +# +# Copyright (C) 1998 Free Software Foundation, Inc. + +# 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, 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 USA. + +# +# Boilerplate +# +topdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = .:@srcdir@ +BUILD_DIR = @BUILD_DIR@ + +RM = rm -f +SHELL = @MAKE_SHELL@ +CC = @CC@ +CC_FOR_BUILD = @CC_FOR_BUILD@ + +EXEEXT = @EXEEXT@ + +# +# Compiler options: +# +PROFILE_FLAGS = @PROFILE_FLAGS@ + +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +DEFS = @DEFS@ +LOCAL_DEFS = @LOCAL_DEFS@ + +LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS) +LDFLAGS_FOR_BUILD = $(LDFLAGS) + +INCLUDES = -I${BUILD_DIR} -I${topdir} + +BASE_CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) \ + ${INCLUDES} $(LOCAL_CFLAGS) + +CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS) +CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) + +SRC1 = man2html.c +OBJ1 = man2html.o + +.c.o: + $(RM) $@ + $(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $< + +all: man2html$(EXEEXT) + +man2html$(EXEEXT): $(OBJ1) + $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) $(OBJ1) -o $@ ${LIBS} + +clean: + $(RM) man2html$(EXEEXT) + +distclean maintainer-clean mostly-clean: clean + $(RM) $(OBJ1) + +man2html.o: man2html.c diff --git a/tests/errors.right b/tests/errors.right index 1f3487be2..9d8e18534 100644 --- a/tests/errors.right +++ b/tests/errors.right @@ -85,7 +85,7 @@ command: usage: command [-pVv] command [arg ...] ./errors.tests: line 213: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") ./errors.tests: line 216: trap: NOSIG: invalid signal specification ./errors.tests: line 219: trap: -s: invalid option -trap: usage: trap [-lp] [[arg] signal_spec ...] +trap: usage: trap [-lp] [arg signal_spec ...] ./errors.tests: line 225: return: can only `return' from a function or sourced script ./errors.tests: line 229: break: 0: loop count out of range ./errors.tests: line 233: continue: 0: loop count out of range diff --git a/tests/errors.right~ b/tests/errors.right~ new file mode 100644 index 000000000..1f3487be2 --- /dev/null +++ b/tests/errors.right~ @@ -0,0 +1,100 @@ +./errors.tests: line 17: alias: -x: invalid option +alias: usage: alias [-p] [name[=value] ... ] +./errors.tests: line 18: unalias: -x: invalid option +unalias: usage: unalias [-a] name [name ...] +./errors.tests: line 19: alias: hoowah: not found +./errors.tests: line 20: unalias: hoowah: not found +./errors.tests: line 23: `1': not a valid identifier +declare -fr func +./errors.tests: line 36: func: readonly function +./errors.tests: line 39: unset: -x: invalid option +unset: usage: unset [-f] [-v] [name ...] +./errors.tests: line 42: unset: func: cannot unset: readonly function +./errors.tests: line 45: declare: func: readonly function +./errors.tests: line 49: unset: XPATH: cannot unset: readonly variable +./errors.tests: line 52: unset: `/bin/sh': not a valid identifier +./errors.tests: line 55: unset: cannot simultaneously unset a function and a variable +./errors.tests: line 58: declare: -z: invalid option +declare: usage: declare [-afFirtx] [-p] [name[=value] ...] +./errors.tests: line 60: declare: `-z': not a valid identifier +./errors.tests: line 61: declare: `/bin/sh': not a valid identifier +./errors.tests: line 65: declare: cannot use `-f' to make functions +./errors.tests: line 68: exec: -i: invalid option +exec: usage: exec [-cl] [-a name] file [redirection ...] +./errors.tests: line 72: export: XPATH: not a function +./errors.tests: line 75: break: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 76: continue: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 79: shift: label: numeric argument required +./errors.tests: line 84: shift: too many arguments +./errors.tests: line 90: let: expression expected +./errors.tests: line 93: local: can only be used in a function +./errors.tests: line 96: logout: not login shell: use `exit' +./errors.tests: line 99: hash: notthere: not found +./errors.tests: line 102: hash: -v: invalid option +hash: usage: hash [-lr] [-p pathname] [-dt] [name ...] +./errors.tests: line 106: hash: hashing disabled +./errors.tests: line 109: export: `AA[4]': not a valid identifier +./errors.tests: line 110: readonly: `AA[4]': not a valid identifier +./errors.tests: line 113: [-2]: bad array subscript +./errors.tests: line 117: AA: readonly variable +./errors.tests: line 121: AA: readonly variable +./errors.tests: line 129: shift: 5: shift count out of range +./errors.tests: line 130: shift: -2: shift count out of range +./errors.tests: line 133: shopt: no_such_option: invalid shell option name +./errors.tests: line 134: shopt: no_such_option: invalid shell option name +./errors.tests: line 137: umask: 09: octal number out of range +./errors.tests: line 138: umask: `:': invalid symbolic mode character +./errors.tests: line 139: umask: `:': invalid symbolic mode operator +./errors.tests: line 142: umask: -i: invalid option +umask: usage: umask [-p] [-S] [mode] +./errors.tests: line 146: umask: `u': invalid symbolic mode character +./errors.tests: line 155: VAR: readonly variable +./errors.tests: line 158: declare: VAR: readonly variable +./errors.tests: line 159: declare: VAR: readonly variable +./errors.tests: line 161: declare: unset: not found +./errors.tests: line 164: VAR: readonly variable +./errors.tests: command substitution: line 168: syntax error: unexpected end of file +./errors.tests: command substitution: line 168: syntax error near unexpected token `done' +./errors.tests: command substitution: line 168: ` for z in 1 2 3; done ' +./errors.tests: line 171: cd: HOME not set +./errors.tests: line 172: cd: /tmp/xyz.bash: No such file or directory +./errors.tests: line 174: cd: OLDPWD not set +./errors.tests: line 175: cd: /bin/sh: Not a directory +./errors.tests: line 177: cd: /tmp/cd-notthere: No such file or directory +./errors.tests: line 180: .: filename argument required +.: usage: . filename [arguments] +./errors.tests: line 181: source: filename argument required +source: usage: source filename [arguments] +./errors.tests: line 184: .: -i: invalid option +.: usage: . filename [arguments] +./errors.tests: line 187: set: -q: invalid option +set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...] +./errors.tests: line 190: enable: sh: not a shell builtin +./errors.tests: line 190: enable: bash: not a shell builtin +./errors.tests: line 193: shopt: cannot set and unset shell options simultaneously +./errors.tests: line 196: read: var: invalid timeout specification +./errors.tests: line 199: read: `/bin/sh': not a valid identifier +./errors.tests: line 202: VAR: readonly variable +./errors.tests: line 205: readonly: -x: invalid option +readonly: usage: readonly [-af] [name[=value] ...] or readonly -p +./errors.tests: line 208: eval: -i: invalid option +eval: usage: eval [arg ...] +./errors.tests: line 209: command: -i: invalid option +command: usage: command [-pVv] command [arg ...] +./errors.tests: line 212: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 213: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 216: trap: NOSIG: invalid signal specification +./errors.tests: line 219: trap: -s: invalid option +trap: usage: trap [-lp] [[arg] signal_spec ...] +./errors.tests: line 225: return: can only `return' from a function or sourced script +./errors.tests: line 229: break: 0: loop count out of range +./errors.tests: line 233: continue: 0: loop count out of range +./errors.tests: line 238: builtin: bash: not a shell builtin +./errors.tests: line 242: bg: no job control +./errors.tests: line 243: fg: no job control +./errors.tests: line 246: kill: -s: option requires an argument +./errors.tests: line 248: kill: S: invalid signal specification +./errors.tests: line 250: kill: `': not a pid or valid job spec +kill: usage: kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec] +./errors.tests: line 255: set: trackall: invalid option name +./errors.tests: line 262: `!!': not a valid identifier diff --git a/variables.c b/variables.c index f32e2dc1f..d1a9c30a0 100644 --- a/variables.c +++ b/variables.c @@ -1599,7 +1599,10 @@ make_local_variable (name) /* local foo; local foo; is a no-op. */ old_var = find_variable (name); if (old_var && local_p (old_var) && old_var->context == variable_context) - return (old_var); + { + VUNSETATTR (old_var, att_invisible); + return (old_var); + } was_tmpvar = old_var && tempvar_p (old_var); if (was_tmpvar)