mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-30 17:09:50 +02:00
commit bash-20080501 snapshot
This commit is contained in:
+122
@@ -15613,3 +15613,125 @@ doc/{bash.1,bashref.texi}
|
||||
|
||||
configure.in
|
||||
- change default version to bash-4.0-devel
|
||||
|
||||
4/28
|
||||
----
|
||||
variables.c
|
||||
- change push_func_var and push_exported_var to call
|
||||
stupidly_hack_special_variables if the temporary variable is going
|
||||
to be disposed. This undoes any internal changes caused by a local
|
||||
variable assignment in the environment or in a shell function. Bug
|
||||
reported by Morita Sho <morita-pub-en-debian@inz.sakura.ne.jp> in
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=478096
|
||||
|
||||
5/3
|
||||
---
|
||||
builtins/fc.def
|
||||
- fixed a problem caused by change of 1/21 to use remember_on_history,
|
||||
since it's turned off by parse_and_execute(), but can cause the
|
||||
last command in history to be deleted and leave last_hist pointing
|
||||
beyond the end of the history list. edit_and_execute_command can
|
||||
do this.
|
||||
|
||||
bashline.c
|
||||
- new define, RL_BOOLEAN_VAR_VALUE, to take a readline boolean variable
|
||||
and get its value as 0 or 1 (consider making readline global)
|
||||
- put tty back into canonical mode before calling parse_and_execute in
|
||||
edit_and_execute_command and then back into raw mode after it
|
||||
returns. Fixes problem identified by <koersen@gmail.com>.
|
||||
|
||||
5/4
|
||||
---
|
||||
lib/glob/glob.c
|
||||
- code to support `globstar' option: GX_GLOBSTAR and two internal
|
||||
flags. Changes to skipname, glob_vector, mbskipname, glob_filename.
|
||||
New function finddirs().
|
||||
|
||||
lib/glob/glob.h
|
||||
- new defines to support globstar code
|
||||
|
||||
builtins/shopt.def
|
||||
- new shell option, `globstar', enables special handling of `**' in
|
||||
glob patterns -- matches all directories recursively
|
||||
|
||||
pathexp.h
|
||||
- extern declaration for glob_star
|
||||
|
||||
pathexp.c
|
||||
- break inline code out of quote_globbing_chars into a separate
|
||||
function to decide whether a character is a globbing char:
|
||||
glob_char_p
|
||||
- change shell_glob_filename to call glob_filename with the
|
||||
GX_GLOBSTAR flag if glob_star is set
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new `globstar' shell option
|
||||
|
||||
arrayfunc.c
|
||||
- new function, broken out of quote_array_assignment_chars:
|
||||
quote_assign; extended from old code to make sure that globbing
|
||||
chars and chars in $IFS are quoted when displaying assignment
|
||||
statements, especially in compound array assignments
|
||||
|
||||
5/5
|
||||
---
|
||||
bashline.c
|
||||
- new variable, dircomplete_spelling, controls spelling correction
|
||||
of directory names when doing filename completion
|
||||
- change bash_directory_completion_hook to incorporate spelling
|
||||
correction if initial canonicalization of directory name fails
|
||||
|
||||
builtins/shopt.def
|
||||
- new shell option, `dirspell', enables and disables spelling
|
||||
correction of directory names during word completion
|
||||
|
||||
builtins/read.def
|
||||
- support for fractional timeout values (ival.uval); uses uconvert
|
||||
and falarm/setitimer
|
||||
|
||||
config.h.in
|
||||
- new `HAVE_SETITIMER' define
|
||||
|
||||
configure.in
|
||||
- look for setitimer(2), define HAVE_SETITIMER if found
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new `dirspell' shopt option
|
||||
- document new fractional values to `read -t timeout'
|
||||
|
||||
5/6
|
||||
---
|
||||
assoc.[ch]
|
||||
- new files, basic support for associative array implementation
|
||||
|
||||
general.h
|
||||
- new extern declarations for sh_openpipe, sh_closepipe, trim_pathname
|
||||
|
||||
general.c
|
||||
- new functions: sh_openpipe to create a pipe and move the file
|
||||
descriptors to a high range; sh_closepipe, to close pipe fds and
|
||||
clean up, and trim_pathname, to replace portions of a pathname
|
||||
with `...' (for prompting)
|
||||
|
||||
jobs.c
|
||||
- don't set last_asynchronous_pid in child shell (messes up $!, among
|
||||
other things)
|
||||
|
||||
parse.y,parser.h
|
||||
- moved definitions of parser flags to parser.h
|
||||
|
||||
array.c
|
||||
- imported array_modcase (case-changing operations on arrays) from
|
||||
4.0-devel branch
|
||||
|
||||
array.h
|
||||
- new extern declaration for array_modcase
|
||||
|
||||
lib/readline/complete.c
|
||||
- new variable, rl_menu_completion_entry_function, generator for
|
||||
rl_menu_complete
|
||||
- new menu completion `browsing' implementation, with several
|
||||
improvements over the old code. Inspired by Sami
|
||||
|
||||
lib/readline/readline.h
|
||||
- extern declaration for rl_menu_completion_entry_function
|
||||
|
||||
+121
-1
@@ -15331,7 +15331,7 @@ lib/readline/rltty.c
|
||||
3/6
|
||||
---
|
||||
{MANIFEST,Makefile.in},lib/sh/{casemod,uconvert,ufuncs}.c
|
||||
- new library sources from bash-4.0-devel triee
|
||||
- new library sources from bash-4.0-devel tree
|
||||
|
||||
lib/sh/spell.c
|
||||
- moved cdspell() here from builtins/cd.def, renamed dirspell()
|
||||
@@ -15613,3 +15613,123 @@ doc/{bash.1,bashref.texi}
|
||||
|
||||
configure.in
|
||||
- change default version to bash-4.0-devel
|
||||
|
||||
4/28
|
||||
----
|
||||
variables.c
|
||||
- change push_func_var and push_exported_var to call
|
||||
stupidly_hack_special_variables if the temporary variable is going
|
||||
to be disposed. This undoes any internal changes caused by a local
|
||||
variable assignment in the environment or in a shell function. Bug
|
||||
reported by Morita Sho <morita-pub-en-debian@inz.sakura.ne.jp> in
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=478096
|
||||
|
||||
5/3
|
||||
---
|
||||
builtins/fc.def
|
||||
- fixed a problem caused by change of 1/21 to use remember_on_history,
|
||||
since it's turned off by parse_and_execute(), but can cause the
|
||||
last command in history to be deleted and leave last_hist pointing
|
||||
beyond the end of the history list. edit_and_execute_command can
|
||||
do this.
|
||||
|
||||
bashline.c
|
||||
- new define, RL_BOOLEAN_VAR_VALUE, to take a readline boolean variable
|
||||
and get its value as 0 or 1 (consider making readline global)
|
||||
- put tty back into canonical mode before calling parse_and_execute in
|
||||
edit_and_execute_command and then back into raw mode after it
|
||||
returns. Fixes problem identified by <koersen@gmail.com>.
|
||||
|
||||
5/4
|
||||
---
|
||||
lib/glob/glob.c
|
||||
- code to support `globstar' option: GX_GLOBSTAR and two internal
|
||||
flags. Changes to skipname, glob_vector, mbskipname, glob_filename.
|
||||
New function finddirs().
|
||||
|
||||
lib/glob/glob.h
|
||||
- new defines to support globstar code
|
||||
|
||||
builtins/shopt.def
|
||||
- new shell option, `globstar', enables special handling of `**' in
|
||||
glob patterns -- matches all directories recursively
|
||||
|
||||
pathexp.h
|
||||
- extern declaration for glob_star
|
||||
|
||||
pathexp.c
|
||||
- break inline code out of quote_globbing_chars into a separate
|
||||
function to decide whether a character is a globbing char:
|
||||
glob_char_p
|
||||
- change shell_glob_filename to call glob_filename with the
|
||||
GX_GLOBSTAR flag if glob_star is set
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new `globstar' shell option
|
||||
|
||||
arrayfunc.c
|
||||
- new function, broken out of quote_array_assignment_chars:
|
||||
quote_assign; extended from old code to make sure that globbing
|
||||
chars and chars in $IFS are quoted when displaying assignment
|
||||
statements, especially in compound array assignments
|
||||
|
||||
5/5
|
||||
---
|
||||
bashline.c
|
||||
- new variable, dircomplete_spelling, controls spelling correction
|
||||
of directory names when doing filename completion
|
||||
- change bash_directory_completion_hook to incorporate spelling
|
||||
correction if initial canonicalization of directory name fails
|
||||
|
||||
builtins/shopt.def
|
||||
- new shell option, `dirspell', enables and disables spelling
|
||||
correction of directory names during word completion
|
||||
|
||||
builtins/read.def
|
||||
- support for fractional timeout values (ival.uval); uses uconvert
|
||||
and falarm/setitimer
|
||||
|
||||
config.h.in
|
||||
- new `HAVE_SETITIMER' define
|
||||
|
||||
configure.in
|
||||
- look for setitimer(2), define HAVE_SETITIMER if found
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new `dirspell' shopt option
|
||||
- document new fractional values to `read -t timeout'
|
||||
|
||||
5/6
|
||||
---
|
||||
assoc.[ch]
|
||||
- new files, basic support for associative array implementation
|
||||
|
||||
general.h
|
||||
- new extern declarations for sh_openpipe, sh_closepipe, trim_pathname
|
||||
|
||||
general.c
|
||||
- new functions: sh_openpipe to create a pipe and move the file
|
||||
descriptors to a high range; sh_closepipe, to close pipe fds and
|
||||
clean up, and trim_pathname, to replace portions of a pathname
|
||||
with `...' (for prompting)
|
||||
|
||||
jobs.c
|
||||
- don't set last_asynchronous_pid in child shell (messes up $!, among
|
||||
other things)
|
||||
|
||||
parse.y,parser.h
|
||||
- moved definitions of parser flags to parser.h
|
||||
|
||||
array.c
|
||||
- imported array_modcase (case-changing operations on arrays) from
|
||||
4.0-devel branch
|
||||
|
||||
array.h
|
||||
- new extern declaration for array_modcase
|
||||
|
||||
lib/readline/complete.c
|
||||
- new variable, rl_menu_completion_entry_function, generator for
|
||||
rl_menu_complete
|
||||
|
||||
lib/readline/readline.h
|
||||
- extern declaration for rl_menu_completion_entry_function
|
||||
|
||||
@@ -60,6 +60,7 @@ config.h.in f
|
||||
aclocal.m4 f
|
||||
array.c f
|
||||
arrayfunc.c f
|
||||
assoc.c f
|
||||
eval.c f
|
||||
print_cmd.c f
|
||||
general.c f
|
||||
@@ -110,6 +111,7 @@ patchlevel.h f
|
||||
variables.h f
|
||||
array.h f
|
||||
arrayfunc.h f
|
||||
assoc.h f
|
||||
jobs.h f
|
||||
findcmd.h f
|
||||
hashlib.h f
|
||||
@@ -857,6 +859,7 @@ tests/new-exp3.sub f
|
||||
tests/new-exp4.sub f
|
||||
tests/new-exp5.sub f
|
||||
tests/new-exp6.sub f
|
||||
tests/new-exp7.sub f
|
||||
tests/new-exp.right f
|
||||
tests/nquote.tests f
|
||||
tests/nquote.right f
|
||||
|
||||
@@ -60,6 +60,7 @@ config.h.in f
|
||||
aclocal.m4 f
|
||||
array.c f
|
||||
arrayfunc.c f
|
||||
assoc.c f
|
||||
eval.c f
|
||||
print_cmd.c f
|
||||
general.c f
|
||||
@@ -110,6 +111,7 @@ patchlevel.h f
|
||||
variables.h f
|
||||
array.h f
|
||||
arrayfunc.h f
|
||||
assoc.h f
|
||||
jobs.h f
|
||||
findcmd.h f
|
||||
hashlib.h f
|
||||
@@ -176,6 +178,7 @@ builtins/let.def f
|
||||
builtins/history.def f
|
||||
builtins/jobs.def f
|
||||
builtins/kill.def f
|
||||
builtins/mapfile.def f
|
||||
builtins/mkbuiltins.c f
|
||||
builtins/printf.def f
|
||||
builtins/pushd.def f
|
||||
@@ -464,24 +467,55 @@ po/LINGUAS f
|
||||
po/Makefile.in.in f
|
||||
po/Makevars f
|
||||
po/POTFILES.in f
|
||||
po/README f
|
||||
po/Rules-builtins f
|
||||
po/Rules-quot f
|
||||
po/bash.pot f
|
||||
po/boldquot.sed f
|
||||
po/en@quot.header f
|
||||
po/en@boldquot.gmo f
|
||||
po/en@boldquot.header f
|
||||
po/en@quot.po f
|
||||
po/en@boldquot.po f
|
||||
po/en@quot.gmo f
|
||||
po/en@boldquot.gmo f
|
||||
po/bg.po f
|
||||
po/en@quot.header f
|
||||
po/en@quot.po f
|
||||
po/af.gmo f
|
||||
po/af.po f
|
||||
po/bg.gmo f
|
||||
po/ru.po f
|
||||
po/bg.po f
|
||||
po/ca.gmo f
|
||||
po/ca.po f
|
||||
po/de.gmo f
|
||||
po/de.po f
|
||||
po/eo.gmo f
|
||||
po/eo.po f
|
||||
po/es.gmo f
|
||||
po/es.po f
|
||||
po/et.gmo f
|
||||
po/et.po f
|
||||
po/fr.gmo f
|
||||
po/fr.po f
|
||||
po/hu.gmo f
|
||||
po/hu.po f
|
||||
po/ja.gmo f
|
||||
po/ja.po f
|
||||
po/nl.gmo f
|
||||
po/nl.po f
|
||||
po/pl.gmo f
|
||||
po/pl.po f
|
||||
po/pt_BR.gmo f
|
||||
po/pt_BR.po f
|
||||
po/ro.gmo f
|
||||
po/ro.po f
|
||||
po/ru.gmo f
|
||||
po/sk.po f
|
||||
po/ru.po f
|
||||
po/sk.gmo f
|
||||
po/sv.po f
|
||||
po/sk.po f
|
||||
po/sv.gmo f
|
||||
po/sv.po f
|
||||
po/tr.gmo f
|
||||
po/tr.po f
|
||||
po/vi.gmo f
|
||||
po/vi.po f
|
||||
po/insert-header.sin f
|
||||
po/quot.sed f
|
||||
po/remove-potcdate.sin f
|
||||
@@ -772,6 +806,7 @@ tests/func.right f
|
||||
tests/func1.sub f
|
||||
tests/func2.sub f
|
||||
tests/func3.sub f
|
||||
tests/func4.sub f
|
||||
tests/getopts.tests f
|
||||
tests/getopts.right f
|
||||
tests/getopts1.sub f
|
||||
@@ -813,6 +848,9 @@ tests/jobs2.sub f
|
||||
tests/jobs3.sub f
|
||||
tests/jobs4.sub f
|
||||
tests/jobs.right f
|
||||
tests/mapfile.data f
|
||||
tests/mapfile.right f
|
||||
tests/mapfile.tests f
|
||||
tests/more-exp.tests f
|
||||
tests/more-exp.right f
|
||||
tests/new-exp.tests f
|
||||
@@ -906,6 +944,7 @@ tests/run-intl f
|
||||
tests/run-iquote f
|
||||
tests/run-invert f
|
||||
tests/run-jobs f
|
||||
tests/run-mapfile f
|
||||
tests/run-more-exp f
|
||||
tests/run-new-exp f
|
||||
tests/run-nquote f
|
||||
|
||||
+11
-3
@@ -411,7 +411,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \
|
||||
dispose_cmd.c execute_cmd.c variables.c $(GLOBC) version.c \
|
||||
expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \
|
||||
test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \
|
||||
input.c bashhist.c array.c arrayfunc.c sig.c pathexp.c \
|
||||
input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \
|
||||
unwind_prot.c siglist.c bashline.c bracecomp.c error.c \
|
||||
list.c stringlib.c locale.c findcmd.c redir.c \
|
||||
pcomplete.c pcomplib.c syntax.c xmalloc.c
|
||||
@@ -422,7 +422,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \
|
||||
command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \
|
||||
subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \
|
||||
array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \
|
||||
execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h \
|
||||
execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h \
|
||||
$(BASHINCFILES)
|
||||
|
||||
SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS)
|
||||
@@ -440,7 +440,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
|
||||
dispose_cmd.o execute_cmd.o variables.o copy_cmd.o error.o \
|
||||
expr.o flags.o $(JOBS_O) subst.o hashcmd.o hashlib.o mailcheck.o \
|
||||
trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \
|
||||
alias.o array.o arrayfunc.o braces.o bracecomp.o bashhist.o \
|
||||
alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \
|
||||
bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \
|
||||
pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O)
|
||||
|
||||
@@ -1076,6 +1076,14 @@ arrayfunc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
|
||||
arrayfunc.o: make_cmd.h subst.h sig.h pathnames.h externs.h
|
||||
arrayfunc.o: $(DEFSRC)/common.h
|
||||
arrayfunc.o: ${BASHINCDIR}/shmbutil.h
|
||||
assoc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
assoc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
assoc.o: command.h ${BASHINCDIR}/stdc.h error.h
|
||||
assoc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
|
||||
assoc.o: assoc.h hashlib.h
|
||||
assoc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
|
||||
assoc.o: make_cmd.h subst.h sig.h pathnames.h externs.h
|
||||
assoc.o: $(DEFSRC)/common.h
|
||||
braces.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
braces.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
|
||||
braces.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
|
||||
|
||||
+13
-7
@@ -1,6 +1,6 @@
|
||||
# Makefile for bash-3.1, version 2.159
|
||||
# Makefile for bash-4.0, version 3.4
|
||||
#
|
||||
# Copyright (C) 1996-2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2008 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
|
||||
@@ -411,7 +411,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \
|
||||
dispose_cmd.c execute_cmd.c variables.c $(GLOBC) version.c \
|
||||
expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \
|
||||
test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \
|
||||
input.c bashhist.c array.c arrayfunc.c sig.c pathexp.c \
|
||||
input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \
|
||||
unwind_prot.c siglist.c bashline.c bracecomp.c error.c \
|
||||
list.c stringlib.c locale.c findcmd.c redir.c \
|
||||
pcomplete.c pcomplib.c syntax.c xmalloc.c
|
||||
@@ -422,7 +422,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \
|
||||
command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \
|
||||
subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \
|
||||
array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \
|
||||
execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h \
|
||||
execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h \
|
||||
$(BASHINCFILES)
|
||||
|
||||
SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS)
|
||||
@@ -440,7 +440,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
|
||||
dispose_cmd.o execute_cmd.o variables.o copy_cmd.o error.o \
|
||||
expr.o flags.o $(JOBS_O) subst.o hashcmd.o hashlib.o mailcheck.o \
|
||||
trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \
|
||||
alias.o array.o arrayfunc.o braces.o bracecomp.o bashhist.o \
|
||||
alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \
|
||||
bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \
|
||||
pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O)
|
||||
|
||||
@@ -465,7 +465,8 @@ BUILTIN_DEFS = $(DEFSRC)/alias.def $(DEFSRC)/bind.def $(DEFSRC)/break.def \
|
||||
$(DEFSRC)/times.def $(DEFSRC)/trap.def $(DEFSRC)/type.def \
|
||||
$(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \
|
||||
$(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \
|
||||
$(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def
|
||||
$(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def \
|
||||
$(DEFSRC)/mapfile.def
|
||||
BUILTIN_C_SRC = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \
|
||||
$(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \
|
||||
$(DEFSRC)/bashgetopt.c $(GETOPT_SOURCE)
|
||||
@@ -484,7 +485,7 @@ BUILTIN_OBJS = $(DEFDIR)/alias.o $(DEFDIR)/bind.o $(DEFDIR)/break.o \
|
||||
$(DEFDIR)/source.o $(DEFDIR)/suspend.o $(DEFDIR)/test.o \
|
||||
$(DEFDIR)/times.o $(DEFDIR)/trap.o $(DEFDIR)/type.o \
|
||||
$(DEFDIR)/ulimit.o $(DEFDIR)/umask.o $(DEFDIR)/wait.o \
|
||||
$(DEFDIR)/getopts.o $(BUILTIN_C_OBJ)
|
||||
$(DEFDIR)/getopts.o $(DEFDIR)/mapfile.o $(BUILTIN_C_OBJ)
|
||||
GETOPT_SOURCE = $(DEFSRC)/getopt.c $(DEFSRC)/getopt.h
|
||||
PSIZE_SOURCE = $(DEFSRC)/psize.sh $(DEFSRC)/psize.c
|
||||
|
||||
@@ -1383,6 +1384,9 @@ builtins/complete.o: bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
builtins/complete.o: builtins.h
|
||||
builtins/complete.o: pcomplete.h
|
||||
builtins/complete.o: ${DEFSRC}/common.h ${DEFSRC}/bashgetopt.h
|
||||
builtins/mapfile.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
|
||||
builtins/mapfile.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
|
||||
builtins/mapfile.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
|
||||
|
||||
# libintl dependencies
|
||||
builtins/bind.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
@@ -1406,6 +1410,7 @@ builtins/inlib.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
builtins/jobs.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
builtins/kill.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
builtins/let.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
builtins/mapfile.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
builtins/mkbuiltins.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
builtins/printf.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
builtins/pushd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
@@ -1457,6 +1462,7 @@ builtins/inlib.o: $(DEFSRC)/inlib.def
|
||||
builtins/jobs.o: $(DEFSRC)/jobs.def
|
||||
builtins/kill.o: $(DEFSRC)/kill.def
|
||||
builtins/let.o: $(DEFSRC)/let.def
|
||||
builtins/mapfile.o: $(DEFSRC)/mapfile.def
|
||||
builtins/pushd.o: $(DEFSRC)/pushd.def
|
||||
builtins/read.o: $(DEFSRC)/read.def
|
||||
builtins/reserved.o: $(DEFSRC)/reserved.def
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* chet@ins.cwru.edu
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1997-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1997-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -418,6 +418,41 @@ int mflags;
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
array_modcase (a, pat, modop, mflags)
|
||||
ARRAY *a;
|
||||
char *pat;
|
||||
int modop;
|
||||
int mflags;
|
||||
{
|
||||
ARRAY *a2;
|
||||
ARRAY_ELEMENT *e;
|
||||
char *t, *sifs;
|
||||
|
||||
if (a == 0 || array_head(a) == 0 || array_empty(a))
|
||||
return ((char *)NULL);
|
||||
|
||||
a2 = array_copy(a);
|
||||
for (e = element_forw(a2->head); e != a2->head; e = element_forw(e)) {
|
||||
t = sh_modcase(element_value(e), pat, modop);
|
||||
FREE(element_value(e));
|
||||
e->value = t;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
array_quote(a2);
|
||||
else
|
||||
array_quote_escapes(a2);
|
||||
if (mflags & MATCH_STARSUB) {
|
||||
sifs = ifs_firstchar((int *)NULL);
|
||||
t = array_to_string (a2, sifs, 0);
|
||||
free(sifs);
|
||||
} else
|
||||
t = array_to_string (a2, " ", 0);
|
||||
array_dispose (a2);
|
||||
|
||||
return t;
|
||||
}
|
||||
/*
|
||||
* Allocate and return a new array element with index INDEX and value
|
||||
* VALUE.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* chet@ins.cwru.edu
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1997-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1997-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -418,6 +418,41 @@ int mflags;
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
array_modcase (a, pat, modop, mflags)
|
||||
ARRAY *a;
|
||||
char *pat;
|
||||
int modop;
|
||||
int mflags;
|
||||
{
|
||||
ARRAY *a2;
|
||||
ARRAY_ELEMENT *e;
|
||||
char *t, *ifs, sifs[2];
|
||||
|
||||
if (a == 0 || array_head(a) == 0 || array_empty(a))
|
||||
return ((char *)NULL);
|
||||
|
||||
a2 = array_copy(a);
|
||||
for (e = element_forw(a2->head); e != a2->head; e = element_forw(e)) {
|
||||
t = sh_modcase(element_value(e), pat, modop);
|
||||
FREE(element_value(e));
|
||||
e->value = t;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
array_quote(a2);
|
||||
else
|
||||
array_quote_escapes(a2);
|
||||
if (mflags & MATCH_STARSUB) {
|
||||
sifs = ifs_firstchar((int *)NULL);
|
||||
t = array_to_string (a2, sifs, 0);
|
||||
free(sifs);
|
||||
} else
|
||||
t = array_to_string (a2, " ", 0);
|
||||
array_dispose (a2);
|
||||
|
||||
return t;
|
||||
}
|
||||
/*
|
||||
* Allocate and return a new array element with index INDEX and value
|
||||
* VALUE.
|
||||
@@ -693,7 +728,7 @@ int quoted;
|
||||
is = inttostr (element_index(ae), indstr, sizeof(indstr));
|
||||
valstr = element_value (ae) ? sh_double_quote (element_value(ae))
|
||||
: (char *)NULL;
|
||||
elen = STRLEN (indstr) + 8 + STRLEN (valstr);
|
||||
elen = STRLEN (is) + 8 + STRLEN (valstr);
|
||||
RESIZE_MALLOCED_BUFFER (result, rlen, (elen + 1), rsize, rsize);
|
||||
|
||||
result[rlen++] = '[';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* array.h -- definitions for the interface exported by array.c that allows
|
||||
the rest of the shell to manipulate array variables. */
|
||||
|
||||
/* Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1997-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -59,6 +59,7 @@ extern ARRAY *array_quote_escapes __P((ARRAY *));
|
||||
|
||||
extern char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int));
|
||||
extern char *array_patsub __P((ARRAY *, char *, char *, int));
|
||||
extern char *array_modcase __P((ARRAY *, char *, int, int));
|
||||
|
||||
/* Basic operations on array elements. */
|
||||
extern ARRAY_ELEMENT *array_create_element __P((arrayind_t, char *));
|
||||
|
||||
@@ -55,9 +55,11 @@ extern int array_rshift __P((ARRAY *, int, char *));
|
||||
extern ARRAY_ELEMENT *array_unshift_element __P((ARRAY *));
|
||||
extern int array_shift_element __P((ARRAY *, char *));
|
||||
extern ARRAY *array_quote __P((ARRAY *));
|
||||
extern ARRAY *array_quote_escapes __P((ARRAY *));
|
||||
|
||||
extern char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int));
|
||||
extern char *array_patsub __P((ARRAY *, char *, char *, int));
|
||||
extern char *array_modcase __P((ARRAY *, char *, int, int));
|
||||
|
||||
/* Basic operations on array elements. */
|
||||
extern ARRAY_ELEMENT *array_create_element __P((arrayind_t, char *));
|
||||
|
||||
+31
-13
@@ -41,6 +41,7 @@ extern int array_needs_making;
|
||||
|
||||
static SHELL_VAR *bind_array_var_internal __P((SHELL_VAR *, arrayind_t, char *, int));
|
||||
|
||||
static char *quote_assign __P((const char *));
|
||||
static void quote_array_assignment_chars __P((WORD_LIST *));
|
||||
static char *array_value_internal __P((char *, int, int, int *));
|
||||
|
||||
@@ -423,6 +424,34 @@ assign_array_var_from_string (var, value, flags)
|
||||
return (var);
|
||||
}
|
||||
|
||||
static char *
|
||||
quote_assign (string)
|
||||
const char *string;
|
||||
{
|
||||
size_t slen;
|
||||
int saw_eq;
|
||||
char *temp, *t;
|
||||
const char *s, *send;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
t = temp = (char *)xmalloc (slen * 2 + 1);
|
||||
saw_eq = 0;
|
||||
for (s = string; *s; )
|
||||
{
|
||||
if (*s == '=')
|
||||
saw_eq = 1;
|
||||
if (saw_eq == 0 && (glob_char_p (s) || isifs (*s)))
|
||||
*t++ = '\\';
|
||||
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
*t = '\0';
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* For each word in a compound array assignment, if the word looks like
|
||||
[ind]=value, quote the `[' and `]' before the `=' to protect them from
|
||||
unwanted filename expansion. */
|
||||
@@ -430,8 +459,7 @@ static void
|
||||
quote_array_assignment_chars (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *s, *t, *nword;
|
||||
int saw_eq;
|
||||
char *nword;
|
||||
WORD_LIST *l;
|
||||
|
||||
for (l = list; l; l = l->next)
|
||||
@@ -441,17 +469,7 @@ quote_array_assignment_chars (list)
|
||||
/* Don't bother if it doesn't look like [ind]=value */
|
||||
if (l->word->word[0] != '[' || xstrchr (l->word->word, '=') == 0) /* ] */
|
||||
continue;
|
||||
s = nword = (char *)xmalloc (strlen (l->word->word) * 2 + 1);
|
||||
saw_eq = 0;
|
||||
for (t = l->word->word; *t; )
|
||||
{
|
||||
if (*t == '=')
|
||||
saw_eq = 1;
|
||||
if (saw_eq == 0 && (*t == '[' || *t == ']'))
|
||||
*s++ = '\\';
|
||||
*s++ = *t++;
|
||||
}
|
||||
*s = '\0';
|
||||
nword = quote_assign (l->word->word);
|
||||
free (l->word->word);
|
||||
l->word->word = nword;
|
||||
}
|
||||
|
||||
@@ -160,6 +160,16 @@ bind_array_variable (name, ind, value, flags)
|
||||
return (bind_array_var_internal (entry, ind, value, flags));
|
||||
}
|
||||
|
||||
SHELL_VAR *
|
||||
bind_array_element (entry, ind, value, flags)
|
||||
SHELL_VAR *entry;
|
||||
arrayind_t ind;
|
||||
char *value;
|
||||
int flags;
|
||||
{
|
||||
return (bind_array_var_internal (entry, ind, value, flags));
|
||||
}
|
||||
|
||||
/* Parse NAME, a lhs of an assignment statement of the form v[s], and
|
||||
assign VALUE to that array element by calling bind_array_variable(). */
|
||||
SHELL_VAR *
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* assoc.c - functions to manipulate associative arrays
|
||||
*
|
||||
* Associative arrays are standard shell hash tables.
|
||||
*
|
||||
* Chet Ramey
|
||||
* chet@ins.cwru.edu
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bashansi.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "array.h"
|
||||
#include "assoc.h"
|
||||
#include "builtins/common.h"
|
||||
|
||||
static WORD_LIST *assoc_to_word_list_internal __P((HASH_TABLE *, int));
|
||||
|
||||
/* assoc_create == hash_create */
|
||||
|
||||
void
|
||||
assoc_dispose (hash)
|
||||
HASH_TABLE *hash;
|
||||
{
|
||||
if (hash)
|
||||
{
|
||||
hash_flush (hash, 0);
|
||||
hash_dispose (hash);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
assoc_flush (hash)
|
||||
HASH_TABLE *hash;
|
||||
{
|
||||
hash_flush (hash, 0);
|
||||
}
|
||||
|
||||
int
|
||||
assoc_insert (hash, key, value)
|
||||
HASH_TABLE *hash;
|
||||
char *key;
|
||||
char *value;
|
||||
{
|
||||
BUCKET_CONTENTS *b;
|
||||
|
||||
b = hash_search (key, hash, HASH_CREATE);
|
||||
if (b == 0)
|
||||
return -1;
|
||||
FREE (b->data);
|
||||
b->data = value ? savestring (value) : (char *)0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
assoc_remove (hash, string)
|
||||
HASH_TABLE *hash;
|
||||
char *string;
|
||||
{
|
||||
BUCKET_CONTENTS *b;
|
||||
|
||||
b = hash_remove (string, hash, 0);
|
||||
if (b)
|
||||
{
|
||||
free ((char *)b->data);
|
||||
free (b->key);
|
||||
free (b);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_reference (hash, string)
|
||||
HASH_TABLE *hash;
|
||||
char *string;
|
||||
{
|
||||
BUCKET_CONTENTS *b;
|
||||
|
||||
if (hash == 0)
|
||||
return (char *)0;
|
||||
|
||||
b = hash_search (string, hash, 0);
|
||||
return (b ? (char *)b->data : 0);
|
||||
}
|
||||
|
||||
/* Quote the data associated with each element of the hash table ASSOC,
|
||||
using quote_string */
|
||||
HASH_TABLE *
|
||||
assoc_quote (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
int i;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
char *t;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((HASH_TABLE *)NULL);
|
||||
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = quote_string ((char *)tlist->data);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Quote escape characters in the data associated with each element
|
||||
of the hash table ASSOC, using quote_escapes */
|
||||
HASH_TABLE *
|
||||
assoc_quote_escapes (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
int i;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
char *t;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((HASH_TABLE *)NULL);
|
||||
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = quote_escapes ((char *)tlist->data);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_patsub (h, pat, rep, mflags)
|
||||
HASH_TABLE *h;
|
||||
char *pat, *rep;
|
||||
int mflags;
|
||||
{
|
||||
BUCKET_CONTENTS *tlist;
|
||||
int i;
|
||||
HASH_TABLE *h2;
|
||||
char *t, *sifs;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((char *)NULL);
|
||||
|
||||
h2 = assoc_copy (h);
|
||||
for (i = 0; i < h2->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h2); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = pat_subst ((char *)tlist->data, pat, rep, mflags);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
assoc_quote (h2);
|
||||
else
|
||||
assoc_quote_escapes (h2);
|
||||
|
||||
if (mflags & MATCH_STARSUB)
|
||||
{
|
||||
sifs = ifs_firstchar ((int *)NULL);
|
||||
t = assoc_to_string (h2, sifs, 0);
|
||||
free (sifs);
|
||||
}
|
||||
else
|
||||
t = assoc_to_string (h2, " ", 0);
|
||||
|
||||
assoc_dispose (h2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_modcase (h, pat, modop, mflags)
|
||||
HASH_TABLE *h;
|
||||
char *pat;
|
||||
int modop;
|
||||
int mflags;
|
||||
{
|
||||
BUCKET_CONTENTS *tlist;
|
||||
int i;
|
||||
HASH_TABLE *h2;
|
||||
char *t, *sifs;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((char *)NULL);
|
||||
|
||||
h2 = assoc_copy (h);
|
||||
for (i = 0; i < h2->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h2); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = sh_modcase ((char *)tlist->data, pat, modop);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
assoc_quote (h2);
|
||||
else
|
||||
assoc_quote_escapes (h2);
|
||||
|
||||
if (mflags & MATCH_STARSUB)
|
||||
{
|
||||
sifs = ifs_firstchar ((int *)NULL);
|
||||
t = assoc_to_string (h2, sifs, 0);
|
||||
free (sifs);
|
||||
}
|
||||
else
|
||||
t = assoc_to_string (h2, " ", 0);
|
||||
|
||||
assoc_dispose (h2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_to_assign (hash, quoted)
|
||||
HASH_TABLE *hash;
|
||||
int quoted;
|
||||
{
|
||||
char *ret;
|
||||
char *istr, *vstr;
|
||||
int i, rsize, rlen, elen;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
|
||||
if (hash == 0 || assoc_empty (hash))
|
||||
return (char *)0;
|
||||
|
||||
ret = xmalloc (rsize = 128);
|
||||
ret[0] = '(';
|
||||
rlen = 1;
|
||||
|
||||
for (i = 0; i < hash->nbuckets; i++)
|
||||
for (tlist = hash_items (i, hash); tlist; tlist = tlist->next)
|
||||
{
|
||||
istr = tlist->key;
|
||||
vstr = tlist->data ? sh_double_quote ((char *)tlist->data) : (char *)0;
|
||||
|
||||
elen = STRLEN (istr) + 8 + STRLEN (vstr);
|
||||
RESIZE_MALLOCED_BUFFER (ret, rlen, (elen+1), rsize, rsize);
|
||||
|
||||
ret[rlen++] = '[';
|
||||
strcpy (ret+rlen, istr);
|
||||
rlen += STRLEN (istr);
|
||||
ret[rlen++] = ']';
|
||||
ret[rlen++] = '=';
|
||||
if (vstr)
|
||||
{
|
||||
strcpy (ret + rlen, vstr);
|
||||
rlen += STRLEN (vstr);
|
||||
}
|
||||
ret[rlen++] = ' ';
|
||||
|
||||
FREE (vstr);
|
||||
}
|
||||
|
||||
RESIZE_MALLOCED_BUFFER (ret, rlen, 1, rsize, 8);
|
||||
ret[rlen++] = ')';
|
||||
ret[rlen] = '\0';
|
||||
|
||||
if (quoted)
|
||||
{
|
||||
vstr = sh_single_quote (ret);
|
||||
free (ret);
|
||||
ret = vstr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WORD_LIST *
|
||||
assoc_to_word_list_internal (h, t)
|
||||
HASH_TABLE *h;
|
||||
int t;
|
||||
{
|
||||
WORD_LIST *list;
|
||||
int i;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
char *w;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return((WORD_LIST *)NULL);
|
||||
list = (WORD_LIST *)NULL;
|
||||
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
w = (t == 0) ? (char *)tlist->data : (char *)tlist->key;
|
||||
list = make_word_list (make_bare_word(w), list);
|
||||
}
|
||||
return (REVERSE_LIST(list, WORD_LIST *));
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
assoc_to_word_list (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
return (assoc_to_word_list_internal (h, 0));
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
assoc_keys_to_word_list (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
return (assoc_to_word_list_internal (h, 1));
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_to_string (h, sep, quoted)
|
||||
HASH_TABLE *h;
|
||||
char *sep;
|
||||
int quoted;
|
||||
{
|
||||
BUCKET_CONTENTS *tlist;
|
||||
int i;
|
||||
char *result, *t, *w;
|
||||
WORD_LIST *list, *l;
|
||||
|
||||
if (h == 0)
|
||||
return ((char *)NULL);
|
||||
if (assoc_empty (h))
|
||||
return (savestring (""));
|
||||
|
||||
result = NULL;
|
||||
list = NULL;
|
||||
/* This might be better implemented directly, but it's simple to implement
|
||||
by converting to a word list first, possibly quoting the data, then
|
||||
using list_string */
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
w = (char *)tlist->data;
|
||||
if (w == 0)
|
||||
continue;
|
||||
t = quoted ? quote_string (w) : savestring (w);
|
||||
list = make_word_list (make_bare_word(t), list);
|
||||
FREE (t);
|
||||
}
|
||||
|
||||
l = REVERSE_LIST(list, WORD_LIST *);
|
||||
|
||||
result = l ? string_list_internal (l, sep) : savestring ("");
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* ARRAY_VARS */
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* assoc.c - functions to manipulate associative arrays
|
||||
*
|
||||
* Associative arrays are standard shell hash tables.
|
||||
*
|
||||
* Chet Ramey
|
||||
* chet@ins.cwru.edu
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bashansi.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "array.h"
|
||||
#include "assoc.h"
|
||||
#include "builtins/common.h"
|
||||
|
||||
static WORD_LIST *assoc_to_word_list_internal __P((HASH_TABLE *, int));
|
||||
|
||||
/* assoc_create == hash_create */
|
||||
|
||||
void
|
||||
assoc_dispose (hash)
|
||||
HASH_TABLE *hash;
|
||||
{
|
||||
if (hash)
|
||||
{
|
||||
hash_flush (hash, 0);
|
||||
hash_dispose (hash);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
assoc_flush (hash)
|
||||
HASH_TABLE *hash;
|
||||
{
|
||||
hash_flush (hash, 0);
|
||||
}
|
||||
|
||||
int
|
||||
assoc_insert (hash, key, value)
|
||||
HASH_TABLE *hash;
|
||||
char *key;
|
||||
char *value;
|
||||
{
|
||||
BUCKET_CONTENTS *b;
|
||||
|
||||
b = hash_search (key, hash, HASH_CREATE);
|
||||
if (b == 0)
|
||||
return -1;
|
||||
FREE (b->data);
|
||||
b->data = value ? savestring (value) : (char *)0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
assoc_remove (hash, string)
|
||||
HASH_TABLE *hash;
|
||||
char *string;
|
||||
{
|
||||
BUCKET_CONTENTS *b;
|
||||
|
||||
b = hash_remove (string, hash, 0);
|
||||
if (b)
|
||||
{
|
||||
free ((char *)b->data);
|
||||
free (b->key);
|
||||
free (b);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_reference (hash, string)
|
||||
HASH_TABLE *hash;
|
||||
char *string;
|
||||
{
|
||||
BUCKET_CONTENTS *b;
|
||||
|
||||
if (hash == 0)
|
||||
return (char *)0;
|
||||
|
||||
b = hash_search (string, hash, 0);
|
||||
return (b ? (char *)b->data : 0);
|
||||
}
|
||||
|
||||
/* Quote the data associated with each element of the hash table ASSOC,
|
||||
using quote_string */
|
||||
HASH_TABLE *
|
||||
assoc_quote (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
int i;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
char *t;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((HASH_TABLE *)NULL);
|
||||
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = quote_string ((char *)tlist->data);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Quote escape characters in the data associated with each element
|
||||
of the hash table ASSOC, using quote_escapes */
|
||||
HASH_TABLE *
|
||||
assoc_quote_escapes (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
int i;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
char *t;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((HASH_TABLE *)NULL);
|
||||
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = quote_escapes ((char *)tlist->data);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_patsub (h, pat, rep, mflags)
|
||||
HASH_TABLE *h;
|
||||
char *pat, *rep;
|
||||
int mflags;
|
||||
{
|
||||
BUCKET_CONTENTS *tlist;
|
||||
int i;
|
||||
HASH_TABLE *h2;
|
||||
char *t, *ifs, sifs[2];
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((char *)NULL);
|
||||
|
||||
h2 = assoc_copy (h);
|
||||
for (i = 0; i < h2->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h2); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = pat_subst ((char *)tlist->data, pat, rep, mflags);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_STARSUB)
|
||||
{
|
||||
ifs = getifs();
|
||||
sifs[0] = ifs ? *ifs : '\0';
|
||||
sifs[1] = '\0';
|
||||
t = assoc_to_string (h2, sifs, (mflags & MATCH_QUOTED));
|
||||
}
|
||||
else
|
||||
t = assoc_to_string (h2, " ", (mflags & MATCH_QUOTED));
|
||||
|
||||
assoc_dispose (h2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_modcase (h, pat, modop, mflags)
|
||||
HASH_TABLE *h;
|
||||
char *pat;
|
||||
int modop;
|
||||
int mflags;
|
||||
{
|
||||
BUCKET_CONTENTS *tlist;
|
||||
int i;
|
||||
HASH_TABLE *h2;
|
||||
char *t, *ifs, sifs[2];
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((char *)NULL);
|
||||
|
||||
h2 = assoc_copy (h);
|
||||
for (i = 0; i < h2->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h2); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = sh_modcase ((char *)tlist->data, pat, modop);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_STARSUB)
|
||||
{
|
||||
ifs = getifs();
|
||||
sifs[0] = ifs ? *ifs : '\0';
|
||||
sifs[1] = '\0';
|
||||
t = assoc_to_string (h2, sifs, (mflags & MATCH_QUOTED));
|
||||
}
|
||||
else
|
||||
t = assoc_to_string (h2, " ", (mflags & MATCH_QUOTED));
|
||||
|
||||
assoc_dispose (h2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_to_assign (hash, quoted)
|
||||
HASH_TABLE *hash;
|
||||
int quoted;
|
||||
{
|
||||
char *ret;
|
||||
char *istr, *vstr;
|
||||
int i, rsize, rlen, elen;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
|
||||
if (hash == 0 || assoc_empty (hash))
|
||||
return (char *)0;
|
||||
|
||||
ret = xmalloc (rsize = 128);
|
||||
ret[0] = '(';
|
||||
rlen = 1;
|
||||
|
||||
for (i = 0; i < hash->nbuckets; i++)
|
||||
for (tlist = hash_items (i, hash); tlist; tlist = tlist->next)
|
||||
{
|
||||
istr = tlist->key;
|
||||
vstr = tlist->data ? sh_double_quote ((char *)tlist->data) : (char *)0;
|
||||
|
||||
elen = STRLEN (istr) + 8 + STRLEN (vstr);
|
||||
RESIZE_MALLOCED_BUFFER (ret, rlen, (elen+1), rsize, rsize);
|
||||
|
||||
ret[rlen++] = '[';
|
||||
strcpy (ret+rlen, istr);
|
||||
rlen += STRLEN (istr);
|
||||
ret[rlen++] = ']';
|
||||
ret[rlen++] = '=';
|
||||
if (vstr)
|
||||
{
|
||||
strcpy (ret + rlen, vstr);
|
||||
rlen += STRLEN (vstr);
|
||||
}
|
||||
ret[rlen++] = ' ';
|
||||
|
||||
FREE (vstr);
|
||||
}
|
||||
|
||||
RESIZE_MALLOCED_BUFFER (ret, rlen, 1, rsize, 8);
|
||||
ret[rlen++] = ')';
|
||||
ret[rlen] = '\0';
|
||||
|
||||
if (quoted)
|
||||
{
|
||||
vstr = sh_single_quote (ret);
|
||||
free (ret);
|
||||
ret = vstr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WORD_LIST *
|
||||
assoc_to_word_list_internal (h, t)
|
||||
HASH_TABLE *h;
|
||||
int t;
|
||||
{
|
||||
WORD_LIST *list;
|
||||
int i;
|
||||
BUCKET_CONTENTS *tlist;
|
||||
char *w;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return((WORD_LIST *)NULL);
|
||||
list = (WORD_LIST *)NULL;
|
||||
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
w = (t == 0) ? (char *)tlist->data : (char *)tlist->key;
|
||||
list = make_word_list (make_bare_word(w), list);
|
||||
}
|
||||
return (REVERSE_LIST(list, WORD_LIST *));
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
assoc_to_word_list (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
return (assoc_to_word_list_internal (h, 0));
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
assoc_keys_to_word_list (h)
|
||||
HASH_TABLE *h;
|
||||
{
|
||||
return (assoc_to_word_list_internal (h, 1));
|
||||
}
|
||||
|
||||
char *
|
||||
assoc_to_string (h, sep, quoted)
|
||||
HASH_TABLE *h;
|
||||
char *sep;
|
||||
int quoted;
|
||||
{
|
||||
BUCKET_CONTENTS *tlist;
|
||||
int i;
|
||||
char *result, *t, *w;
|
||||
WORD_LIST *list, *l;
|
||||
|
||||
if (h == 0)
|
||||
return ((char *)NULL);
|
||||
if (assoc_empty (h))
|
||||
return (savestring (""));
|
||||
|
||||
result = NULL;
|
||||
list = NULL;
|
||||
/* This might be better implemented directly, but it's simple to implement
|
||||
by converting to a word list first, possibly quoting the data, then
|
||||
using list_string */
|
||||
for (i = 0; i < h->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
||||
{
|
||||
w = (char *)tlist->data;
|
||||
if (w == 0)
|
||||
continue;
|
||||
t = quoted ? quote_string (w) : savestring (w);
|
||||
list = make_word_list (make_bare_word(t), list);
|
||||
FREE (t);
|
||||
}
|
||||
|
||||
l = REVERSE_LIST(list, WORD_LIST *);
|
||||
|
||||
result = l ? string_list_internal (l, sep) : savestring ("");
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* ARRAY_VARS */
|
||||
@@ -0,0 +1,57 @@
|
||||
/* assoc.h -- definitions for the interface exported by assoc.c that allows
|
||||
the rest of the shell to manipulate associative array variables. */
|
||||
|
||||
/* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef _ASSOC_H_
|
||||
#define _ASSOC_H_
|
||||
|
||||
#include "stdc.h"
|
||||
#include "hashlib.h"
|
||||
|
||||
#define assoc_empty(h) ((h)->nentries == 0)
|
||||
#define assoc_num_elements(h) ((h)->nentries)
|
||||
|
||||
#define assoc_create(n) (hash_create((n)))
|
||||
|
||||
#define assoc_copy(h) (hash_copy((h), 0))
|
||||
|
||||
#define assoc_walk(h, f) (hash_walk((h), (f))
|
||||
|
||||
extern void assoc_dispose __P((HASH_TABLE *));
|
||||
extern void assoc_flush __P((HASH_TABLE *));
|
||||
|
||||
extern int assoc_insert __P((HASH_TABLE *, char *, char *));
|
||||
extern void assoc_remove __P((HASH_TABLE *, char *));
|
||||
|
||||
extern char *assoc_reference __P((HASH_TABLE *, char *));
|
||||
|
||||
extern char *assoc_patsub __P((HASH_TABLE *, char *, char *, int));
|
||||
extern char *assoc_modcase __P((HASH_TABLE *, char *, int, int));
|
||||
|
||||
extern HASH_TABLE *assoc_quote __P((HASH_TABLE *));
|
||||
extern HASH_TABLE *assoc_quote_escapes __P((HASH_TABLE *));
|
||||
|
||||
extern char *assoc_to_assign __P((HASH_TABLE *, int));
|
||||
|
||||
extern WORD_LIST *assoc_to_word_list __P((HASH_TABLE *));
|
||||
extern WORD_LIST *assoc_keys_to_word_list __P((HASH_TABLE *));
|
||||
|
||||
extern char *assoc_to_string __P((HASH_TABLE *, char *, int));
|
||||
#endif /* _ASSOC_H_ */
|
||||
@@ -0,0 +1,54 @@
|
||||
/* assoc.h -- definitions for the interface exported by assoc.c that allows
|
||||
the rest of the shell to manipulate associative array variables. */
|
||||
|
||||
/* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef _ASSOC_H_
|
||||
#define _ASSOC_H_
|
||||
|
||||
#include "stdc.h"
|
||||
#include "hashlib.h"
|
||||
|
||||
#define assoc_empty(h) ((h)->nentries == 0)
|
||||
#define assoc_num_elements(h) ((h)->nentries)
|
||||
|
||||
#define assoc_create(n) (hash_create((n)))
|
||||
|
||||
#define assoc_copy(h) (hash_copy((h), 0))
|
||||
|
||||
extern void assoc_dispose __P((HASH_TABLE *));
|
||||
extern void assoc_flush __P((HASH_TABLE *));
|
||||
|
||||
extern int assoc_insert __P((HASH_TABLE *, char *, char *));
|
||||
extern void assoc_remove __P((HASH_TABLE *, char *));
|
||||
|
||||
extern char *assoc_reference __P((HASH_TABLE *, char *));
|
||||
|
||||
extern char *assoc_patsub __P((HASH_TABLE *, char *, char *, int));
|
||||
extern char *assoc_modcase __P((HASH_TABLE *, char *, int, int));
|
||||
|
||||
extern HASH_TABLE *assoc_quote __P((HASH_TABLE *));
|
||||
|
||||
extern char *assoc_to_assign __P((HASH_TABLE *, int));
|
||||
|
||||
extern WORD_LIST *assoc_to_word_list __P((HASH_TABLE *));
|
||||
extern WORD_LIST *assoc_keys_to_word_list __P((HASH_TABLE *));
|
||||
|
||||
extern char *assoc_to_string __P((HASH_TABLE *, char *, int));
|
||||
#endif /* _ASSOC_H_ */
|
||||
@@ -13824,12 +13824,13 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_func in dup2 eaccess fcntl getdtablesize getgroups gethostname \
|
||||
getpagesize getpeername getrlimit getrusage gettimeofday \
|
||||
kill killpg lstat readlink sbrk select setdtablesize \
|
||||
tcgetpgrp uname ulimit waitpid
|
||||
setitimer tcgetpgrp uname ulimit waitpid
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
|
||||
+21
-128
@@ -15,26 +15,26 @@
|
||||
'configure.in'
|
||||
],
|
||||
{
|
||||
'AM_PROG_F77_C_O' => 1,
|
||||
'_LT_AC_TAGCONFIG' => 1,
|
||||
'AM_PROG_F77_C_O' => 1,
|
||||
'm4_pattern_forbid' => 1,
|
||||
'AC_CANONICAL_TARGET' => 1,
|
||||
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
||||
'AC_C_VOLATILE' => 1,
|
||||
'AC_TYPE_OFF_T' => 1,
|
||||
'AC_C_VOLATILE' => 1,
|
||||
'AC_FUNC_CLOSEDIR_VOID' => 1,
|
||||
'AC_REPLACE_FNMATCH' => 1,
|
||||
'AC_PROG_LIBTOOL' => 1,
|
||||
'AC_FUNC_STAT' => 1,
|
||||
'AC_FUNC_WAIT3' => 1,
|
||||
'AC_HEADER_TIME' => 1,
|
||||
'AC_FUNC_LSTAT' => 1,
|
||||
'AC_FUNC_WAIT3' => 1,
|
||||
'AC_STRUCT_TM' => 1,
|
||||
'AC_FUNC_LSTAT' => 1,
|
||||
'AM_AUTOMAKE_VERSION' => 1,
|
||||
'AC_FUNC_GETMNTENT' => 1,
|
||||
'AC_TYPE_MODE_T' => 1,
|
||||
'AC_CHECK_HEADERS' => 1,
|
||||
'AC_FUNC_GETMNTENT' => 1,
|
||||
'AC_FUNC_STRTOD' => 1,
|
||||
'AC_CHECK_HEADERS' => 1,
|
||||
'LT_CONFIG_LTDL_DIR' => 1,
|
||||
'AC_FUNC_STRNLEN' => 1,
|
||||
'm4_sinclude' => 1,
|
||||
@@ -53,179 +53,72 @@
|
||||
'AC_FUNC_MBRTOWC' => 1,
|
||||
'AC_STRUCT_ST_BLOCKS' => 1,
|
||||
'AC_TYPE_SIGNAL' => 1,
|
||||
'AC_CANONICAL_BUILD' => 1,
|
||||
'AM_PROG_FC_C_O' => 1,
|
||||
'AC_CANONICAL_BUILD' => 1,
|
||||
'AC_TYPE_UID_T' => 1,
|
||||
'AC_PROG_MAKE_SET' => 1,
|
||||
'AC_CONFIG_AUX_DIR' => 1,
|
||||
'_AM_SUBST_NOTMAKE' => 1,
|
||||
'm4_pattern_allow' => 1,
|
||||
'AC_CONFIG_AUX_DIR' => 1,
|
||||
'sinclude' => 1,
|
||||
'm4_pattern_allow' => 1,
|
||||
'AC_DEFINE_TRACE_LITERAL' => 1,
|
||||
'AC_FUNC_STRERROR_R' => 1,
|
||||
'AC_PROG_CC' => 1,
|
||||
'AC_DECL_SYS_SIGLIST' => 1,
|
||||
'AC_FUNC_FORK' => 1,
|
||||
'AC_FUNC_STRCOLL' => 1,
|
||||
'AC_DECL_SYS_SIGLIST' => 1,
|
||||
'AC_FUNC_VPRINTF' => 1,
|
||||
'AC_FUNC_STRCOLL' => 1,
|
||||
'AC_PROG_YACC' => 1,
|
||||
'AC_SUBST_TRACE' => 1,
|
||||
'AC_INIT' => 1,
|
||||
'AC_STRUCT_TIMEZONE' => 1,
|
||||
'AC_INIT' => 1,
|
||||
'AC_FUNC_CHOWN' => 1,
|
||||
'AC_SUBST' => 1,
|
||||
'AC_FUNC_ALLOCA' => 1,
|
||||
'AC_FC_SRCEXT' => 1,
|
||||
'AC_CANONICAL_HOST' => 1,
|
||||
'AC_FC_SRCEXT' => 1,
|
||||
'AC_FUNC_GETPGRP' => 1,
|
||||
'AC_PROG_RANLIB' => 1,
|
||||
'AM_INIT_AUTOMAKE' => 1,
|
||||
'AC_FUNC_SETPGRP' => 1,
|
||||
'AM_INIT_AUTOMAKE' => 1,
|
||||
'AC_CONFIG_SUBDIRS' => 1,
|
||||
'AC_FUNC_MMAP' => 1,
|
||||
'AC_FUNC_REALLOC' => 1,
|
||||
'AC_TYPE_SIZE_T' => 1,
|
||||
'AC_CHECK_TYPES' => 1,
|
||||
'AC_CONFIG_LINKS' => 1,
|
||||
'AC_REQUIRE_AUX_FILE' => 1,
|
||||
'AC_CHECK_TYPES' => 1,
|
||||
'LT_SUPPORTED_TAG' => 1,
|
||||
'AC_CHECK_MEMBERS' => 1,
|
||||
'AM_MAINTAINER_MODE' => 1,
|
||||
'AC_FUNC_UTIME_NULL' => 1,
|
||||
'AC_FUNC_SELECT_ARGTYPES' => 1,
|
||||
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
|
||||
'AC_HEADER_STAT' => 1,
|
||||
'AC_FUNC_STRFTIME' => 1,
|
||||
'AC_PROG_CPP' => 1,
|
||||
'AC_C_INLINE' => 1,
|
||||
'AC_PROG_LEX' => 1,
|
||||
'AC_C_CONST' => 1,
|
||||
'AC_TYPE_PID_T' => 1,
|
||||
'AC_PROG_LEX' => 1,
|
||||
'AM_ENABLE_MULTILIB' => 1,
|
||||
'AC_C_CONST' => 1,
|
||||
'AC_CONFIG_FILES' => 1,
|
||||
'include' => 1,
|
||||
'AC_FUNC_SETVBUF_REVERSED' => 1,
|
||||
'AC_PROG_INSTALL' => 1,
|
||||
'AM_GNU_GETTEXT' => 1,
|
||||
'AC_CHECK_LIB' => 1,
|
||||
'AC_FUNC_OBSTACK' => 1,
|
||||
'AC_CHECK_LIB' => 1,
|
||||
'AC_FUNC_MALLOC' => 1,
|
||||
'AC_FUNC_GETGROUPS' => 1,
|
||||
'AC_FUNC_GETLOADAVG' => 1,
|
||||
'AC_FC_FREEFORM' => 1,
|
||||
'AH_OUTPUT' => 1,
|
||||
'AC_FUNC_FSEEKO' => 1,
|
||||
'AM_PROG_CC_C_O' => 1,
|
||||
'AC_FUNC_MKTIME' => 1,
|
||||
'AC_CANONICAL_SYSTEM' => 1,
|
||||
'AM_CONDITIONAL' => 1,
|
||||
'AC_CONFIG_HEADERS' => 1,
|
||||
'AC_HEADER_SYS_WAIT' => 1,
|
||||
'AC_PROG_LN_S' => 1,
|
||||
'AC_FUNC_MEMCMP' => 1,
|
||||
'm4_include' => 1,
|
||||
'AC_HEADER_DIRENT' => 1,
|
||||
'AC_CHECK_FUNCS' => 1
|
||||
}
|
||||
], 'Autom4te::Request' ),
|
||||
bless( [
|
||||
'1',
|
||||
1,
|
||||
[
|
||||
'/usr/local/share/autoconf'
|
||||
],
|
||||
[
|
||||
'/usr/local/share/autoconf/autoconf/autoconf.m4f',
|
||||
'aclocal.m4',
|
||||
'configure.in'
|
||||
],
|
||||
{
|
||||
'm4_pattern_forbid' => 1,
|
||||
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
||||
'AC_C_VOLATILE' => 1,
|
||||
'AC_TYPE_OFF_T' => 1,
|
||||
'AC_FUNC_CLOSEDIR_VOID' => 1,
|
||||
'AC_REPLACE_FNMATCH' => 1,
|
||||
'AC_PROG_LIBTOOL' => 1,
|
||||
'AC_FUNC_STAT' => 1,
|
||||
'AC_FUNC_WAIT3' => 1,
|
||||
'AC_HEADER_TIME' => 1,
|
||||
'AC_FUNC_LSTAT' => 1,
|
||||
'AC_STRUCT_TM' => 1,
|
||||
'AM_AUTOMAKE_VERSION' => 1,
|
||||
'AC_FUNC_GETMNTENT' => 1,
|
||||
'AC_TYPE_MODE_T' => 1,
|
||||
'AC_FUNC_STRTOD' => 1,
|
||||
'AC_CHECK_HEADERS' => 1,
|
||||
'AC_FUNC_STRNLEN' => 1,
|
||||
'm4_sinclude' => 1,
|
||||
'AC_PROG_CXX' => 1,
|
||||
'AC_PATH_X' => 1,
|
||||
'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
|
||||
'AC_PROG_AWK' => 1,
|
||||
'_m4_warn' => 1,
|
||||
'AC_HEADER_STDC' => 1,
|
||||
'AC_HEADER_MAJOR' => 1,
|
||||
'AC_FUNC_ERROR_AT_LINE' => 1,
|
||||
'AC_PROG_GCC_TRADITIONAL' => 1,
|
||||
'AC_LIBSOURCE' => 1,
|
||||
'AC_FUNC_MBRTOWC' => 1,
|
||||
'AC_STRUCT_ST_BLOCKS' => 1,
|
||||
'AC_TYPE_SIGNAL' => 1,
|
||||
'AC_TYPE_UID_T' => 1,
|
||||
'AC_PROG_MAKE_SET' => 1,
|
||||
'AC_CONFIG_AUX_DIR' => 1,
|
||||
'm4_pattern_allow' => 1,
|
||||
'sinclude' => 1,
|
||||
'AC_DEFINE_TRACE_LITERAL' => 1,
|
||||
'AC_FUNC_STRERROR_R' => 1,
|
||||
'AC_PROG_CC' => 1,
|
||||
'AC_FUNC_FORK' => 1,
|
||||
'AC_DECL_SYS_SIGLIST' => 1,
|
||||
'AC_FUNC_STRCOLL' => 1,
|
||||
'AC_FUNC_VPRINTF' => 1,
|
||||
'AC_PROG_YACC' => 1,
|
||||
'AC_INIT' => 1,
|
||||
'AC_STRUCT_TIMEZONE' => 1,
|
||||
'AC_FUNC_CHOWN' => 1,
|
||||
'AC_SUBST' => 1,
|
||||
'AC_FUNC_ALLOCA' => 1,
|
||||
'AC_CANONICAL_HOST' => 1,
|
||||
'AC_FUNC_GETPGRP' => 1,
|
||||
'AC_PROG_RANLIB' => 1,
|
||||
'AM_INIT_AUTOMAKE' => 1,
|
||||
'AC_FUNC_SETPGRP' => 1,
|
||||
'AC_CONFIG_SUBDIRS' => 1,
|
||||
'AC_FUNC_MMAP' => 1,
|
||||
'AC_FUNC_REALLOC' => 1,
|
||||
'AC_TYPE_SIZE_T' => 1,
|
||||
'AC_CONFIG_LINKS' => 1,
|
||||
'AC_CHECK_TYPES' => 1,
|
||||
'AC_CHECK_MEMBERS' => 1,
|
||||
'AM_MAINTAINER_MODE' => 1,
|
||||
'AC_FUNC_UTIME_NULL' => 1,
|
||||
'AC_FUNC_SELECT_ARGTYPES' => 1,
|
||||
'AC_HEADER_STAT' => 1,
|
||||
'AC_FUNC_STRFTIME' => 1,
|
||||
'AC_PROG_CPP' => 1,
|
||||
'AC_C_INLINE' => 1,
|
||||
'AC_TYPE_PID_T' => 1,
|
||||
'AC_PROG_LEX' => 1,
|
||||
'AC_C_CONST' => 1,
|
||||
'AC_CONFIG_FILES' => 1,
|
||||
'include' => 1,
|
||||
'AC_FUNC_SETVBUF_REVERSED' => 1,
|
||||
'AC_PROG_INSTALL' => 1,
|
||||
'AM_GNU_GETTEXT' => 1,
|
||||
'AC_CHECK_LIB' => 1,
|
||||
'AC_FUNC_OBSTACK' => 1,
|
||||
'AC_FUNC_MALLOC' => 1,
|
||||
'AC_FUNC_GETGROUPS' => 1,
|
||||
'AC_FUNC_GETLOADAVG' => 1,
|
||||
'AH_OUTPUT' => 1,
|
||||
'AC_FUNC_FSEEKO' => 1,
|
||||
'AM_PROG_CC_C_O' => 1,
|
||||
'AC_FUNC_MKTIME' => 1,
|
||||
'AC_CANONICAL_SYSTEM' => 1,
|
||||
'AM_CONDITIONAL' => 1,
|
||||
'AC_CANONICAL_SYSTEM' => 1,
|
||||
'AC_CONFIG_HEADERS' => 1,
|
||||
'AC_HEADER_SYS_WAIT' => 1,
|
||||
'AC_PROG_LN_S' => 1,
|
||||
|
||||
@@ -1264,7 +1264,7 @@ m4trace:configure.in:695: -2- m4_pattern_allow([^MKFIFO_MISSING$])
|
||||
m4trace:configure.in:701: -1- AC_CHECK_FUNCS([dup2 eaccess fcntl getdtablesize getgroups gethostname \
|
||||
getpagesize getpeername getrlimit getrusage gettimeofday \
|
||||
kill killpg lstat readlink sbrk select setdtablesize \
|
||||
tcgetpgrp uname ulimit waitpid])
|
||||
setitimer tcgetpgrp uname ulimit waitpid])
|
||||
m4trace:configure.in:701: -1- AH_OUTPUT([HAVE_DUP2], [/* Define to 1 if you have the `dup2\' function. */
|
||||
#undef HAVE_DUP2])
|
||||
m4trace:configure.in:701: -1- AH_OUTPUT([HAVE_EACCESS], [/* Define to 1 if you have the `eaccess\' function. */
|
||||
@@ -1301,6 +1301,8 @@ m4trace:configure.in:701: -1- AH_OUTPUT([HAVE_SELECT], [/* Define to 1 if you ha
|
||||
#undef HAVE_SELECT])
|
||||
m4trace:configure.in:701: -1- AH_OUTPUT([HAVE_SETDTABLESIZE], [/* Define to 1 if you have the `setdtablesize\' function. */
|
||||
#undef HAVE_SETDTABLESIZE])
|
||||
m4trace:configure.in:701: -1- AH_OUTPUT([HAVE_SETITIMER], [/* Define to 1 if you have the `setitimer\' function. */
|
||||
#undef HAVE_SETITIMER])
|
||||
m4trace:configure.in:701: -1- AH_OUTPUT([HAVE_TCGETPGRP], [/* Define to 1 if you have the `tcgetpgrp\' function. */
|
||||
#undef HAVE_TCGETPGRP])
|
||||
m4trace:configure.in:701: -1- AH_OUTPUT([HAVE_UNAME], [/* Define to 1 if you have the `uname\' function. */
|
||||
|
||||
+28
-3
@@ -73,6 +73,8 @@
|
||||
# define VI_EDITING_MODE 0
|
||||
#endif
|
||||
|
||||
#define RL_BOOLEAN_VARIABLE_VALUE(s) ((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
|
||||
|
||||
#if defined (BRACE_COMPLETION)
|
||||
extern int bash_brace_completion __P((int, int));
|
||||
#endif /* BRACE_COMPLETION */
|
||||
@@ -222,6 +224,9 @@ int no_empty_command_completion;
|
||||
are the only possible matches, even if FIGNORE says to. */
|
||||
int force_fignore = 1;
|
||||
|
||||
/* Perform spelling correction on directory names during word completion */
|
||||
int dircomplete_spelling = 0;
|
||||
|
||||
static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
|
||||
static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
|
||||
/* )) */
|
||||
@@ -814,8 +819,8 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
int count, c, editing_mode;
|
||||
char *edit_command;
|
||||
{
|
||||
char *command;
|
||||
int r, cclc, rrs;
|
||||
char *command, *metaval;
|
||||
int r, cclc, rrs, metaflag;
|
||||
|
||||
rrs = rl_readline_state;
|
||||
cclc = current_command_line_count;
|
||||
@@ -842,10 +847,17 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
command = savestring (edit_command);
|
||||
}
|
||||
|
||||
metaval = rl_variable_value ("input-meta");
|
||||
metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval);
|
||||
|
||||
/* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
|
||||
temporary file should be placed into the history. We don't do that
|
||||
yet. */
|
||||
if (rl_deprep_term_function)
|
||||
(*rl_deprep_term_function) ();
|
||||
r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (metaflag);
|
||||
|
||||
current_command_line_count = cclc;
|
||||
|
||||
@@ -1260,7 +1272,7 @@ command_word_completion_function (hint_text, state)
|
||||
val = (char *)NULL;
|
||||
|
||||
temp = rl_variable_value ("completion-ignore-case");
|
||||
igncase = strcmp (temp, "on") == 0;
|
||||
igncase = RL_BOOLEAN_VARIABLE_VALUE (temp);
|
||||
|
||||
if (glob_matches)
|
||||
{
|
||||
@@ -2481,6 +2493,19 @@ bash_directory_completion_hook (dirname)
|
||||
temp1 = make_absolute (local_dirname, t);
|
||||
free (t);
|
||||
temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
||||
|
||||
/* Try spelling correction if initial canonicalization fails. */
|
||||
if (temp2 == 0 && dircomplete_spelling)
|
||||
{
|
||||
temp2 = dirspell (temp1);
|
||||
if (temp2)
|
||||
{
|
||||
free (temp1);
|
||||
temp1 = temp2;
|
||||
temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
||||
return_value = temp2 != 0;
|
||||
}
|
||||
}
|
||||
/* If we can't canonicalize, bail. */
|
||||
if (temp2 == 0)
|
||||
{
|
||||
|
||||
+29
-40
@@ -73,6 +73,8 @@
|
||||
# define VI_EDITING_MODE 0
|
||||
#endif
|
||||
|
||||
#define RL_BOOLEAN_VARIABLE_VALUE(s) ((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
|
||||
|
||||
#if defined (BRACE_COMPLETION)
|
||||
extern int bash_brace_completion __P((int, int));
|
||||
#endif /* BRACE_COMPLETION */
|
||||
@@ -222,6 +224,9 @@ int no_empty_command_completion;
|
||||
are the only possible matches, even if FIGNORE says to. */
|
||||
int force_fignore = 1;
|
||||
|
||||
/* Perform spelling correction on directory names during word completion */
|
||||
int dircomplete_spelling = 1;
|
||||
|
||||
static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
|
||||
static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
|
||||
/* )) */
|
||||
@@ -814,8 +819,8 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
int count, c, editing_mode;
|
||||
char *edit_command;
|
||||
{
|
||||
char *command;
|
||||
int r, cclc, rrs;
|
||||
char *command, *metaval;
|
||||
int r, cclc, rrs, metaflag;
|
||||
|
||||
rrs = rl_readline_state;
|
||||
cclc = current_command_line_count;
|
||||
@@ -842,10 +847,17 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
command = savestring (edit_command);
|
||||
}
|
||||
|
||||
metaval = rl_variable_value ("input-meta");
|
||||
metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval);
|
||||
|
||||
/* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
|
||||
temporary file should be placed into the history. We don't do that
|
||||
yet. */
|
||||
if (rl_deprep_term_function)
|
||||
(*rl_deprep_term_function) ();
|
||||
r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (metaflag);
|
||||
|
||||
current_command_line_count = cclc;
|
||||
|
||||
@@ -1260,7 +1272,7 @@ command_word_completion_function (hint_text, state)
|
||||
val = (char *)NULL;
|
||||
|
||||
temp = rl_variable_value ("completion-ignore-case");
|
||||
igncase = strcmp (temp, "on") == 0;
|
||||
igncase = RL_BOOLEAN_VARIABLE_VALUE (temp);
|
||||
|
||||
if (glob_matches)
|
||||
{
|
||||
@@ -1546,43 +1558,7 @@ globword:
|
||||
/* If we performed tilde expansion, restore the original
|
||||
filename. */
|
||||
if (*hint_text == '~')
|
||||
{
|
||||
int l, vl, dl2, xl;
|
||||
char *dh2, *expdir;
|
||||
|
||||
vl = strlen (val);
|
||||
|
||||
#if 0
|
||||
/* XXX -- don't need this or RD or DL */
|
||||
rd = savestring (filename_hint);
|
||||
bash_directory_expansion (&rd);
|
||||
dl = strlen (rd);
|
||||
free (rd);
|
||||
#endif
|
||||
|
||||
dh2 = directory_part ? bash_dequote_filename (directory_part, 0) : 0;
|
||||
bash_directory_expansion (&dh2);
|
||||
dl2 = strlen (dh2);
|
||||
|
||||
expdir = bash_tilde_expand (directory_part, 0);
|
||||
xl = strlen (expdir);
|
||||
free (expdir);
|
||||
|
||||
/*
|
||||
dh2 = unexpanded but dequoted tilde-prefix
|
||||
dl2 = length of tilde-prefix
|
||||
expdir = tilde-expanded tilde-prefix
|
||||
xl = length of expanded tilde-prefix
|
||||
l = length of remainder after tilde-prefix
|
||||
*/
|
||||
l = (vl - xl) + 1;
|
||||
|
||||
temp = (char *)xmalloc (dl2 + 2 + l);
|
||||
strcpy (temp, dh2);
|
||||
strcpy (temp + dl2, val + xl);
|
||||
|
||||
free (dh2);
|
||||
}
|
||||
temp = restore_tilde (val, directory_part);
|
||||
else
|
||||
temp = savestring (val);
|
||||
freetemp = 1;
|
||||
@@ -2517,6 +2493,19 @@ bash_directory_completion_hook (dirname)
|
||||
temp1 = make_absolute (local_dirname, t);
|
||||
free (t);
|
||||
temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
||||
|
||||
/* Try spelling correction if initial canonicalization fails. */
|
||||
if (temp2 == 0 && dircomplete_spelling)
|
||||
{
|
||||
temp2 = dirspell (temp1);
|
||||
if (temp2)
|
||||
{
|
||||
free (temp1);
|
||||
temp1 = temp2;
|
||||
temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
||||
return_value = temp2 != 0;
|
||||
}
|
||||
}
|
||||
/* If we can't canonicalize, bail. */
|
||||
if (temp2 == 0)
|
||||
{
|
||||
|
||||
+11
-1
@@ -325,7 +325,17 @@ fc_builtin (list)
|
||||
/* "When not listing, the fc command that caused the editing shall not be
|
||||
entered into the history list." */
|
||||
if (listing == 0 && hist_last_line_added)
|
||||
delete_last_history ();
|
||||
{
|
||||
delete_last_history ();
|
||||
/* If we're editing a single command -- the last command in the
|
||||
history -- and we just removed the dummy command added by
|
||||
edit_and_execute_command (), we need to check whether or not we
|
||||
just removed the last command in the history and need to back
|
||||
the pointer up. remember_on_history is off because we're running
|
||||
in parse_and_execute(). */
|
||||
if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
|
||||
last_hist = histbeg = --histend;
|
||||
}
|
||||
|
||||
/* We print error messages for line specifications out of range. */
|
||||
if ((histbeg < 0) || (histend < 0))
|
||||
|
||||
+16
-1
@@ -45,6 +45,9 @@ re-executed after the substitution OLD=NEW is performed.
|
||||
A useful alias to use with this is r='fc -s', so that typing `r cc'
|
||||
runs the last command beginning with `cc' and typing `r' re-executes
|
||||
the last command.
|
||||
|
||||
Exit Status:
|
||||
Returns success or status of executed command; non-zero if an error occurs.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
@@ -322,7 +325,19 @@ fc_builtin (list)
|
||||
/* "When not listing, the fc command that caused the editing shall not be
|
||||
entered into the history list." */
|
||||
if (listing == 0 && hist_last_line_added)
|
||||
delete_last_history ();
|
||||
{
|
||||
delete_last_history ();
|
||||
/* If we're editing a single command -- the last command in the
|
||||
history -- and we just removed the dummy command added by
|
||||
edit_and_execute_command (), we need to check whether or not we
|
||||
just removed the last command in the history and need to back
|
||||
the pointer up. remember_on_history is off because we're running
|
||||
in parse_and_execute(). */
|
||||
if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
|
||||
last_hist = histbeg = --histend;
|
||||
}
|
||||
|
||||
itrace ("fc: last_hist = %d histbeg = %d histend = %d", last_hist, histbeg, histend);
|
||||
|
||||
/* We print error messages for line specifications out of range. */
|
||||
if ((histbeg < 0) || (histend < 0))
|
||||
|
||||
+25
-18
@@ -50,7 +50,8 @@ Options:
|
||||
-s do not echo input coming from a terminal
|
||||
-t timeout time out and return failure if a complete line of input is
|
||||
not read withint TIMEOUT seconds. The value of the TMOUT
|
||||
variable is the default timeout.
|
||||
variable is the default timeout. TIMEOUT may be a
|
||||
fractional number.
|
||||
-u fd read from file descriptor FD instead of the standard input
|
||||
|
||||
Exit Status:
|
||||
@@ -135,7 +136,7 @@ static void
|
||||
reset_alarm ()
|
||||
{
|
||||
set_signal_handler (SIGALRM, old_alrm);
|
||||
alarm (0);
|
||||
falarm (0, 0);
|
||||
}
|
||||
|
||||
/* Read the value of the shell variables whose names follow.
|
||||
@@ -152,7 +153,8 @@ read_builtin (list)
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
|
||||
int raw, edit, nchars, silent, have_timeout, fd;
|
||||
unsigned int tmout;
|
||||
unsigned int tmsec, tmusec;
|
||||
long ival, uval;
|
||||
intmax_t intval;
|
||||
char c;
|
||||
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
|
||||
@@ -177,7 +179,8 @@ read_builtin (list)
|
||||
USE_VAR(input_is_pipe);
|
||||
/* USE_VAR(raw); */
|
||||
USE_VAR(edit);
|
||||
USE_VAR(tmout);
|
||||
USE_VAR(tmsec);
|
||||
USE_VAR(tmusec);
|
||||
USE_VAR(nchars);
|
||||
USE_VAR(silent);
|
||||
USE_VAR(ifs_chars);
|
||||
@@ -202,7 +205,7 @@ read_builtin (list)
|
||||
rlind = 0;
|
||||
#endif
|
||||
|
||||
tmout = 0; /* no timeout */
|
||||
tmsec = tmusec = 0; /* no timeout */
|
||||
nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
|
||||
delim = '\n'; /* read until newline */
|
||||
|
||||
@@ -236,8 +239,8 @@ read_builtin (list)
|
||||
break;
|
||||
#endif
|
||||
case 't':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned int)intval)
|
||||
code = uconvert (list_optarg, &ival, &uval);
|
||||
if (code == 0 || ival < 0 || uval < 0)
|
||||
{
|
||||
builtin_error (_("%s: invalid timeout specification"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
@@ -245,7 +248,8 @@ read_builtin (list)
|
||||
else
|
||||
{
|
||||
have_timeout = 1;
|
||||
tmout = intval;
|
||||
tmsec = ival;
|
||||
tmusec = uval;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
@@ -286,7 +290,7 @@ read_builtin (list)
|
||||
/* `read -t 0 var' returns failure immediately. XXX - should it test
|
||||
whether input is available with select/FIONREAD, and fail if those
|
||||
are unavailable? */
|
||||
if (have_timeout && tmout == 0)
|
||||
if (have_timeout && tmsec == 0 && tmusec == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
/* IF IFS is unset, we use the default of " \t\n". */
|
||||
@@ -302,11 +306,14 @@ read_builtin (list)
|
||||
/* $TMOUT, if set, is the default timeout for read. */
|
||||
if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
|
||||
{
|
||||
code = legal_number (e, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned int)intval)
|
||||
tmout = 0;
|
||||
code = uconvert (e, &ival, &uval);
|
||||
if (code == 0 || ival < 0 || uval < 0)
|
||||
tmsec = tmusec = 0;
|
||||
else
|
||||
tmout = intval;
|
||||
{
|
||||
tmsec = ival;
|
||||
tmusec = uval;
|
||||
}
|
||||
}
|
||||
|
||||
begin_unwind_frame ("read_builtin");
|
||||
@@ -349,15 +356,15 @@ read_builtin (list)
|
||||
pass_next = 0; /* Non-zero signifies last char was backslash. */
|
||||
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
|
||||
|
||||
if (tmout > 0)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
{
|
||||
/* Turn off the timeout if stdin is a regular file (e.g. from
|
||||
input redirection). */
|
||||
if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
|
||||
tmout = 0;
|
||||
tmsec = tmusec = 0;
|
||||
}
|
||||
|
||||
if (tmout > 0)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
{
|
||||
code = setjmp (alrmbuf);
|
||||
if (code)
|
||||
@@ -377,7 +384,7 @@ read_builtin (list)
|
||||
if (edit)
|
||||
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
|
||||
#endif
|
||||
alarm (tmout);
|
||||
falarm (tmsec, tmusec);
|
||||
}
|
||||
|
||||
/* If we've been asked to read only NCHARS chars, or we're using some
|
||||
@@ -563,7 +570,7 @@ add_char:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmout > 0)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
reset_alarm ();
|
||||
|
||||
if (nchars > 0 || delim != '\n')
|
||||
|
||||
+27
-19
@@ -50,9 +50,11 @@ Options:
|
||||
-s do not echo input coming from a terminal
|
||||
-t timeout time out and return failure if a complete line of input is
|
||||
not read withint TIMEOUT seconds. The value of the TMOUT
|
||||
variable is the default timeout.
|
||||
variable is the default timeout. TIMEOUT may be a
|
||||
fractional number.
|
||||
-u fd read from file descriptor FD instead of the standard input
|
||||
|
||||
Exit Status:
|
||||
The return code is zero, unless end-of-file is encountered, read times out,
|
||||
or an invalid file descriptor is supplied as the argument to -u.
|
||||
$END
|
||||
@@ -134,7 +136,7 @@ static void
|
||||
reset_alarm ()
|
||||
{
|
||||
set_signal_handler (SIGALRM, old_alrm);
|
||||
alarm (0);
|
||||
falarm (0, 0);
|
||||
}
|
||||
|
||||
/* Read the value of the shell variables whose names follow.
|
||||
@@ -151,7 +153,8 @@ read_builtin (list)
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
|
||||
int raw, edit, nchars, silent, have_timeout, fd;
|
||||
unsigned int tmout;
|
||||
unsigned int tmsec, tmusec;
|
||||
long ival, uval;
|
||||
intmax_t intval;
|
||||
char c;
|
||||
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
|
||||
@@ -176,7 +179,8 @@ read_builtin (list)
|
||||
USE_VAR(input_is_pipe);
|
||||
/* USE_VAR(raw); */
|
||||
USE_VAR(edit);
|
||||
USE_VAR(tmout);
|
||||
USE_VAR(tmsec);
|
||||
USE_VAR(tmusec);
|
||||
USE_VAR(nchars);
|
||||
USE_VAR(silent);
|
||||
USE_VAR(ifs_chars);
|
||||
@@ -201,7 +205,7 @@ read_builtin (list)
|
||||
rlind = 0;
|
||||
#endif
|
||||
|
||||
tmout = 0; /* no timeout */
|
||||
tmsec = tmusec = 0; /* no timeout */
|
||||
nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
|
||||
delim = '\n'; /* read until newline */
|
||||
|
||||
@@ -235,8 +239,8 @@ read_builtin (list)
|
||||
break;
|
||||
#endif
|
||||
case 't':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned int)intval)
|
||||
code = uconvert (list_optarg, &ival, &uval);
|
||||
if (code == 0 || ival < 0 || uval < 0)
|
||||
{
|
||||
builtin_error (_("%s: invalid timeout specification"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
@@ -244,7 +248,8 @@ read_builtin (list)
|
||||
else
|
||||
{
|
||||
have_timeout = 1;
|
||||
tmout = intval;
|
||||
tmsec = ival;
|
||||
tmusec = uval;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
@@ -285,7 +290,7 @@ read_builtin (list)
|
||||
/* `read -t 0 var' returns failure immediately. XXX - should it test
|
||||
whether input is available with select/FIONREAD, and fail if those
|
||||
are unavailable? */
|
||||
if (have_timeout && tmout == 0)
|
||||
if (have_timeout && tmsec == 0 && tmusec == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
/* IF IFS is unset, we use the default of " \t\n". */
|
||||
@@ -301,11 +306,14 @@ read_builtin (list)
|
||||
/* $TMOUT, if set, is the default timeout for read. */
|
||||
if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
|
||||
{
|
||||
code = legal_number (e, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned int)intval)
|
||||
tmout = 0;
|
||||
code = uconvert (e, &ival, &uval);
|
||||
if (code == 0 || ival < 0 || uval < 0)
|
||||
tmsec = tmusec = 0;
|
||||
else
|
||||
tmout = intval;
|
||||
{
|
||||
tmsec = ival;
|
||||
tmusec = uval;
|
||||
}
|
||||
}
|
||||
|
||||
begin_unwind_frame ("read_builtin");
|
||||
@@ -348,15 +356,15 @@ read_builtin (list)
|
||||
pass_next = 0; /* Non-zero signifies last char was backslash. */
|
||||
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
|
||||
|
||||
if (tmout > 0)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
{
|
||||
/* Turn off the timeout if stdin is a regular file (e.g. from
|
||||
input redirection). */
|
||||
if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
|
||||
tmout = 0;
|
||||
tmsec = tmusec = 0;
|
||||
}
|
||||
|
||||
if (tmout > 0)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
{
|
||||
code = setjmp (alrmbuf);
|
||||
if (code)
|
||||
@@ -376,7 +384,7 @@ read_builtin (list)
|
||||
if (edit)
|
||||
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
|
||||
#endif
|
||||
alarm (tmout);
|
||||
falarm (tmsec, tmusec);
|
||||
}
|
||||
|
||||
/* If we've been asked to read only NCHARS chars, or we're using some
|
||||
@@ -562,10 +570,10 @@ add_char:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmout > 0)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
reset_alarm ();
|
||||
|
||||
if (nchars > 0 || delim != '\n')
|
||||
< if (nchars > 0 || delim != '\n')
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
|
||||
+4
-1
@@ -71,7 +71,7 @@ extern int allow_null_glob_expansion, fail_glob_expansion, glob_dot_filenames;
|
||||
extern int cdable_vars, mail_warning, source_uses_path;
|
||||
extern int no_exit_on_failed_exec, print_shift_error;
|
||||
extern int check_hashed_filenames, promptvars;
|
||||
extern int cdspelling, expand_aliases;
|
||||
extern int cdspelling, dircomplete_spelling, expand_aliases;
|
||||
extern int extended_quote;
|
||||
extern int check_window_size;
|
||||
extern int glob_ignore_case, match_ignore_case;
|
||||
@@ -80,6 +80,7 @@ extern int xpg_echo;
|
||||
extern int gnu_error_format;
|
||||
extern int check_jobs_at_exit;
|
||||
extern int autocd;
|
||||
extern int glob_star;
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
extern int extended_glob;
|
||||
@@ -142,6 +143,7 @@ static struct {
|
||||
{ "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "compat31", &shopt_compat31, set_compatibility_level },
|
||||
{ "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
|
||||
{ "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
|
||||
{ "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL },
|
||||
{ "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL },
|
||||
@@ -156,6 +158,7 @@ static struct {
|
||||
#if defined (READLINE)
|
||||
{ "force_fignore", &force_fignore, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "globstar", &glob_star, (shopt_set_func_t *)NULL },
|
||||
{ "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL },
|
||||
#if defined (HISTORY)
|
||||
{ "histappend", &force_append_history, (shopt_set_func_t *)NULL },
|
||||
|
||||
+5
-1
@@ -71,7 +71,7 @@ extern int allow_null_glob_expansion, fail_glob_expansion, glob_dot_filenames;
|
||||
extern int cdable_vars, mail_warning, source_uses_path;
|
||||
extern int no_exit_on_failed_exec, print_shift_error;
|
||||
extern int check_hashed_filenames, promptvars;
|
||||
extern int cdspelling, expand_aliases;
|
||||
extern int cdspelling, dircomplete_spelling, expand_aliases;
|
||||
extern int extended_quote;
|
||||
extern int check_window_size;
|
||||
extern int glob_ignore_case, match_ignore_case;
|
||||
@@ -80,6 +80,7 @@ extern int xpg_echo;
|
||||
extern int gnu_error_format;
|
||||
extern int check_jobs_at_exit;
|
||||
extern int autocd;
|
||||
extern int glob_star;
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
extern int extended_glob;
|
||||
@@ -134,7 +135,9 @@ static struct {
|
||||
{ "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL },
|
||||
{ "cdspell", &cdspelling, (shopt_set_func_t *)NULL },
|
||||
{ "checkhash", &check_hashed_filenames, (shopt_set_func_t *)NULL },
|
||||
#if defined (JOB_CONTROL)
|
||||
{ "checkjobs", &check_jobs_at_exit, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "checkwinsize", &check_window_size, (shopt_set_func_t *)NULL },
|
||||
#if defined (HISTORY)
|
||||
{ "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL },
|
||||
@@ -154,6 +157,7 @@ static struct {
|
||||
#if defined (READLINE)
|
||||
{ "force_fignore", &force_fignore, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "globstar", &glob_star, (shopt_set_func_t *)NULL },
|
||||
{ "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL },
|
||||
#if defined (HISTORY)
|
||||
{ "histappend", &force_append_history, (shopt_set_func_t *)NULL },
|
||||
|
||||
@@ -686,6 +686,9 @@
|
||||
/* Define if you have the setenv function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define if you have the setitimer function. */
|
||||
#undef HAVE_SETITIMER
|
||||
|
||||
/* Define if you have the setlinebuf function. */
|
||||
#undef HAVE_SETLINEBUF
|
||||
|
||||
|
||||
@@ -638,6 +638,9 @@
|
||||
/* Define if you have the mbrtowc function. */
|
||||
#undef HAVE_MBRTOWC
|
||||
|
||||
/* Define if you have the mbscmp function. */
|
||||
#undef HAVE_MBSCMP
|
||||
|
||||
/* Define if you have the mbsrtowcs function. */
|
||||
#undef HAVE_MBSRTOWCS
|
||||
|
||||
|
||||
@@ -13824,12 +13824,13 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_func in dup2 eaccess fcntl getdtablesize getgroups gethostname \
|
||||
getpagesize getpeername getrlimit getrusage gettimeofday \
|
||||
kill killpg lstat readlink sbrk select setdtablesize \
|
||||
tcgetpgrp uname ulimit waitpid
|
||||
setitimer tcgetpgrp uname ulimit waitpid
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
|
||||
+1
-1
@@ -698,7 +698,7 @@ dnl checks for system calls
|
||||
AC_CHECK_FUNCS(dup2 eaccess fcntl getdtablesize getgroups gethostname \
|
||||
getpagesize getpeername getrlimit getrusage gettimeofday \
|
||||
kill killpg lstat readlink sbrk select setdtablesize \
|
||||
tcgetpgrp uname ulimit waitpid)
|
||||
setitimer tcgetpgrp uname ulimit waitpid)
|
||||
AC_REPLACE_FUNCS(rename)
|
||||
|
||||
dnl checks for c library functions
|
||||
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
dnl
|
||||
dnl Configure script for bash-3.2
|
||||
dnl Configure script for bash-4.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-2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1987-2008 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
|
||||
@@ -22,10 +22,10 @@ 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.2, version 3.197])dnl
|
||||
AC_REVISION([for Bash 4.0, version 4.001])dnl
|
||||
|
||||
define(bashvers, 3.2)
|
||||
define(relstatus, maint)
|
||||
define(bashvers, 4.0)
|
||||
define(relstatus, devel)
|
||||
|
||||
AC_INIT([bash], bashvers-relstatus, [bug-bash@gnu.org])
|
||||
|
||||
|
||||
+22
-2
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Fri Apr 25 12:26:57 EDT 2008
|
||||
.\" Last Change: Sun May 4 22:27:45 EDT 2008
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2008 April 25" "GNU Bash-4.0"
|
||||
.TH BASH 1 "2008 May 4" "GNU Bash-4.0"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -2872,6 +2872,12 @@ The special pattern characters have the following meanings:
|
||||
.TP
|
||||
.B *
|
||||
Matches any string, including the null string.
|
||||
When the \fBglobstar\fP shell option is enabled, and \fB*\fP is used in
|
||||
a filename expansion context, two adjacent \fB*\fPs used as a single
|
||||
pattern will match all files and zero or more directories and
|
||||
subdirectories.
|
||||
If followed by a \fB/\fP, two adjacent \fB*\fPs will match only directories
|
||||
and subdirectories.
|
||||
.TP
|
||||
.B ?
|
||||
Matches any single character.
|
||||
@@ -7670,6 +7676,8 @@ not echoed.
|
||||
.B \-t \fItimeout\fP
|
||||
Cause \fBread\fP to time out and return failure if a complete line of
|
||||
input is not read within \fItimeout\fP seconds.
|
||||
\fItimeout\fP may be a decimal number with a fractional portion following
|
||||
the decimal point.
|
||||
This option has no effect if \fBread\fP is not reading input from the
|
||||
terminal or a pipe.
|
||||
.TP
|
||||
@@ -8205,6 +8213,12 @@ If set,
|
||||
changes its behavior to that of version 3.1 with respect to quoted
|
||||
arguments to the conditional command's =~ operator.
|
||||
.TP 8
|
||||
.B dirspell
|
||||
If set,
|
||||
.B bash
|
||||
attempts spelling correction on directory names during word completion
|
||||
if the directory name initially supplied does not exist.
|
||||
.TP 8
|
||||
.B dotglob
|
||||
If set,
|
||||
.B bash
|
||||
@@ -8282,6 +8296,12 @@ See
|
||||
above for a description of \fBFIGNORE\fP.
|
||||
This option is enabled by default.
|
||||
.TP 8
|
||||
.B globstar
|
||||
If set, the pattern \fB**\fP used in a filename expansion context will
|
||||
match a files and zero or more directories and subdirectories.
|
||||
If the pattern is followed by a \fB/\fP, only directories and
|
||||
subdirectories match.
|
||||
.TP 8
|
||||
.B gnu_errfmt
|
||||
If set, shell error messages are written in the standard GNU error
|
||||
message format.
|
||||
|
||||
+27
-3
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Sat Apr 12 17:15:24 EDT 2008
|
||||
.\" Last Change: Sun May 4 22:27:45 EDT 2008
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2008 April 12" "GNU Bash-3.2"
|
||||
.TH BASH 1 "2008 May 4" "GNU Bash-4.0"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -2872,6 +2872,12 @@ The special pattern characters have the following meanings:
|
||||
.TP
|
||||
.B *
|
||||
Matches any string, including the null string.
|
||||
When the \fBglobstar\fP shell option is enabled, and \fB*\fP is used in
|
||||
a filename expansion context, two adjacent \fB*\fPs used as a single
|
||||
pattern will match all files and zero or more directories and
|
||||
subdirectories.
|
||||
If followed by a \fB/\fP, two adjacent \fB*\fPs will match only directories
|
||||
and subdirectories.
|
||||
.TP
|
||||
.B ?
|
||||
Matches any single character.
|
||||
@@ -3791,7 +3797,12 @@ A full search of the directories in
|
||||
.SM
|
||||
.B PATH
|
||||
is performed only if the command is not found in the hash table.
|
||||
If the search is unsuccessful, the shell prints an error
|
||||
If the search is unsuccessful, the shell searches for a defined shell
|
||||
function named \fBcommand_not_found_handle\fP.
|
||||
If that function exists, it is invoked with the original command and
|
||||
the original command's arguments as its arguments, and the function's
|
||||
exit status becomes the exit status of the shell.
|
||||
If that function is not defined, the shell prints an error
|
||||
message and returns an exit status of 127.
|
||||
.PP
|
||||
If the search is successful, or if the command name contains
|
||||
@@ -7665,6 +7676,7 @@ not echoed.
|
||||
.B \-t \fItimeout\fP
|
||||
Cause \fBread\fP to time out and return failure if a complete line of
|
||||
input is not read within \fItimeout\fP seconds.
|
||||
\fItimeout\fP may be a decimal number with a fractional portion.
|
||||
This option has no effect if \fBread\fP is not reading input from the
|
||||
terminal or a pipe.
|
||||
.TP
|
||||
@@ -8200,6 +8212,12 @@ If set,
|
||||
changes its behavior to that of version 3.1 with respect to quoted
|
||||
arguments to the conditional command's =~ operator.
|
||||
.TP 8
|
||||
.B dirspell
|
||||
If set,
|
||||
.B bash
|
||||
attempts spelling correction on directory names during word completion
|
||||
if the directory name initially supplied does not exist.
|
||||
.TP 8
|
||||
.B dotglob
|
||||
If set,
|
||||
.B bash
|
||||
@@ -8277,6 +8295,12 @@ See
|
||||
above for a description of \fBFIGNORE\fP.
|
||||
This option is enabled by default.
|
||||
.TP 8
|
||||
.B globstar
|
||||
If set, the pattern \fB**\fP used in a filename expansion context will
|
||||
match a files and zero or more directories and subdirectories.
|
||||
If the pattern is followed by a \fB/\fP, only directories and
|
||||
subdirectories match.
|
||||
.TP 8
|
||||
.B gnu_errfmt
|
||||
If set, shell error messages are written in the standard GNU error
|
||||
message format.
|
||||
|
||||
@@ -1886,6 +1886,12 @@ The special pattern characters have the following meanings:
|
||||
@table @code
|
||||
@item *
|
||||
Matches any string, including the null string.
|
||||
When the @code{globstar} shell option is enabled, and @samp{*} is used in
|
||||
a filename expansion context, two adjacent @samp{*}s used as a single
|
||||
pattern will match all files and zero or more directories and
|
||||
subdirectories.
|
||||
If followed by a @samp{/}, two adjacent @samp{*}s will match only
|
||||
directories and subdirectories.
|
||||
@item ?
|
||||
Matches any single character.
|
||||
@item [@dots{}]
|
||||
@@ -3604,6 +3610,8 @@ not echoed.
|
||||
@item -t @var{timeout}
|
||||
Cause @code{read} to time out and return failure if a complete line of
|
||||
input is not read within @var{timeout} seconds.
|
||||
@var{timeout} may be a decimal number with a fractional portion following
|
||||
the decimal point.
|
||||
This option has no effect if @code{read} is not reading input from the
|
||||
terminal or a pipe.
|
||||
|
||||
@@ -4143,6 +4151,11 @@ If set, Bash
|
||||
changes its behavior to that of version 3.1 with respect to quoted
|
||||
arguments to the conditional command's =~ operator.
|
||||
|
||||
@item dirspell
|
||||
If set, Bash
|
||||
attempts spelling correction on directory names during word completion
|
||||
if the directory name initially supplied does not exist.
|
||||
|
||||
@item dotglob
|
||||
If set, Bash includes filenames beginning with a `.' in
|
||||
the results of filename expansion.
|
||||
@@ -4212,6 +4225,12 @@ the ignored words are the only possible completions.
|
||||
@xref{Bash Variables}, for a description of @env{FIGNORE}.
|
||||
This option is enabled by default.
|
||||
|
||||
@item globstar
|
||||
If set, the pattern @samp{**} used in a filename expansion context will
|
||||
match a files and zero or more directories and subdirectories.
|
||||
If the pattern is followed by a @samp{/}, only directories and
|
||||
subdirectories match.
|
||||
|
||||
@item gnu_errfmt
|
||||
If set, shell error messages are written in the standard @sc{gnu} error
|
||||
message format.
|
||||
|
||||
+23
-1
@@ -1886,6 +1886,12 @@ The special pattern characters have the following meanings:
|
||||
@table @code
|
||||
@item *
|
||||
Matches any string, including the null string.
|
||||
When the @code{globstar} shell option is enabled, and @samp{*} is used in
|
||||
a filename expansion context, two adjacent @samp{*}s used as a single
|
||||
pattern will match all files and zero or more directories and
|
||||
subdirectories.
|
||||
If followed by a @samp{/}, two adjacent @samp{*}s will match only
|
||||
directories and subdirectories.
|
||||
@item ?
|
||||
Matches any single character.
|
||||
@item [@dots{}]
|
||||
@@ -2301,7 +2307,12 @@ pathnames of executable files to avoid multiple @env{PATH} searches
|
||||
(see the description of @code{hash} in @ref{Bourne Shell Builtins}).
|
||||
A full search of the directories in @env{$PATH}
|
||||
is performed only if the command is not found in the hash table.
|
||||
If the search is unsuccessful, the shell prints an error
|
||||
If the search is unsuccessful, the shell searches for a defined shell
|
||||
function named @code{command_not_found_handle}.
|
||||
If that function exists, it is invoked with the original command and
|
||||
the original command's arguments as its arguments, and the function's
|
||||
exit status becomes the exit status of the shell.
|
||||
If that function is not defined, the shell prints an error
|
||||
message and returns an exit status of 127.
|
||||
|
||||
@item
|
||||
@@ -4138,6 +4149,11 @@ If set, Bash
|
||||
changes its behavior to that of version 3.1 with respect to quoted
|
||||
arguments to the conditional command's =~ operator.
|
||||
|
||||
@item dirspell
|
||||
If set, Bash
|
||||
attempts spelling correction on directory names during word completion
|
||||
if the directory name initially supplied does not exist.
|
||||
|
||||
@item dotglob
|
||||
If set, Bash includes filenames beginning with a `.' in
|
||||
the results of filename expansion.
|
||||
@@ -4207,6 +4223,12 @@ the ignored words are the only possible completions.
|
||||
@xref{Bash Variables}, for a description of @env{FIGNORE}.
|
||||
This option is enabled by default.
|
||||
|
||||
@item globstar
|
||||
If set, the pattern @samp{**} used in a filename expansion context will
|
||||
match a files and zero or more directories and subdirectories.
|
||||
If the pattern is followed by a @samp{/}, only directories and
|
||||
subdirectories match.
|
||||
|
||||
@item gnu_errfmt
|
||||
If set, shell error messages are written in the standard @sc{gnu} error
|
||||
message format.
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2008 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Fri Apr 25 12:33:01 EDT 2008
|
||||
@set LASTCHANGE Sun May 4 22:23:58 EDT 2008
|
||||
|
||||
@set EDITION 4.0
|
||||
@set VERSION 4.0
|
||||
@set UPDATED 25 April 2008
|
||||
@set UPDATED-MONTH April 2008
|
||||
@set UPDATED 4 May 2008
|
||||
@set UPDATED-MONTH May 2008
|
||||
|
||||
+4
-4
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2008 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Sat Apr 12 17:15:43 EDT 2008
|
||||
@set LASTCHANGE Fri Apr 25 12:33:01 EDT 2008
|
||||
|
||||
@set EDITION 3.2
|
||||
@set VERSION 3.2
|
||||
@set UPDATED 12 April 2008
|
||||
@set EDITION 4.0
|
||||
@set VERSION 4.0
|
||||
@set UPDATED 25 April 2008
|
||||
@set UPDATED-MONTH April 2008
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* general.c -- Stuff that is used by all files. */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -489,6 +489,41 @@ check_binary_file (sample, sample_len)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to manipulate pipes */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
int
|
||||
sh_openpipe (pv)
|
||||
int *pv;
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = pipe (pv)) < 0)
|
||||
return r;
|
||||
|
||||
pv[0] = move_to_high_fd (pv[0], 1, 64);
|
||||
pv[1] = move_to_high_fd (pv[1], 1, 64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sh_closepipe (pv)
|
||||
int *pv;
|
||||
{
|
||||
if (pv[0] >= 0)
|
||||
close (pv[0]);
|
||||
|
||||
if (pv[1] >= 0)
|
||||
close (pv[1]);
|
||||
|
||||
pv[0] = pv[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to inspect pathnames */
|
||||
@@ -642,6 +677,72 @@ polite_directory_format (name)
|
||||
return (name);
|
||||
}
|
||||
|
||||
/* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
|
||||
keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
|
||||
and replace the intervening characters with `...' */
|
||||
char *
|
||||
trim_pathname (name, maxlen)
|
||||
char *name;
|
||||
int maxlen;
|
||||
{
|
||||
int nlen, ndirs;
|
||||
intmax_t nskip;
|
||||
char *nbeg, *nend, *ntail, *v;
|
||||
|
||||
if (name == 0 || (nlen = strlen (name)) == 0)
|
||||
return name;
|
||||
nend = name + nlen;
|
||||
|
||||
v = get_string_value ("PROMPT_DIRTRIM");
|
||||
if (v == 0 || *v == 0)
|
||||
return name;
|
||||
if (legal_number (v, &nskip) == 0 || nskip <= 0)
|
||||
return name;
|
||||
|
||||
/* Skip over tilde prefix */
|
||||
nbeg = name;
|
||||
if (name[0] == '~')
|
||||
for (nbeg = name; *nbeg; nbeg++)
|
||||
if (*nbeg == '/')
|
||||
{
|
||||
nbeg++;
|
||||
break;
|
||||
}
|
||||
if (*nbeg == 0)
|
||||
return name;
|
||||
|
||||
for (ndirs = 0, ntail = nbeg; *ntail; ntail++)
|
||||
if (*ntail == '/')
|
||||
ndirs++;
|
||||
if (ndirs <= nskip)
|
||||
return name;
|
||||
|
||||
for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--)
|
||||
{
|
||||
if (*ntail == '/')
|
||||
nskip--;
|
||||
if (nskip == 0)
|
||||
break;
|
||||
}
|
||||
if (ntail == nbeg)
|
||||
return name;
|
||||
|
||||
/* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
|
||||
nlen = ntail - nbeg;
|
||||
if (nlen <= 3)
|
||||
return name;
|
||||
|
||||
*nbeg++ = '.';
|
||||
*nbeg++ = '.';
|
||||
*nbeg++ = '.';
|
||||
|
||||
nlen = nend - ntail;
|
||||
memcpy (nbeg, ntail, nlen);
|
||||
nbeg[nlen] = '\0';
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Given a string containing units of information separated by colons,
|
||||
return the next one pointed to by (P_INDEX), or NULL if there are no more.
|
||||
Advance (P_INDEX) to the character after the colon. */
|
||||
|
||||
+37
-1
@@ -1,6 +1,6 @@
|
||||
/* general.c -- Stuff that is used by all files. */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -69,6 +69,7 @@ posix_initialize (on)
|
||||
if (on != 0)
|
||||
{
|
||||
interactive_comments = source_uses_path = expand_aliases = 1;
|
||||
source_searches_cwd = 0;
|
||||
}
|
||||
|
||||
/* Things that should be turned on when posix mode is disabled. */
|
||||
@@ -488,6 +489,41 @@ check_binary_file (sample, sample_len)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to manipulate pipes */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
int
|
||||
sh_openpipe (pv)
|
||||
int *pv;
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = pipe (pv)) < 0)
|
||||
return r;
|
||||
|
||||
pv[0] = move_to_high_fd (pv[0], 1, 64);
|
||||
pv[1] = move_to_high_fd (pv[1], 1, 64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sh_closepipe (pv)
|
||||
int *pv;
|
||||
{
|
||||
if (pv[0] >= 0)
|
||||
close (pv[0]);
|
||||
|
||||
if (pv[1] >= 0)
|
||||
close (pv[1]);
|
||||
|
||||
pv[0] = pv[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to inspect pathnames */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* general.h -- defines that everybody likes to use. */
|
||||
|
||||
/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -297,6 +297,9 @@ extern int check_binary_file __P((char *, int));
|
||||
extern int same_file __P((char *, char *, struct stat *, struct stat *));
|
||||
#endif
|
||||
|
||||
extern int sh_openpipe __P((int *));
|
||||
extern int sh_closepipe __P((int *));
|
||||
|
||||
extern int file_isdir __P((char *));
|
||||
extern int file_iswdir __P((char *));
|
||||
extern int absolute_pathname __P((const char *));
|
||||
@@ -306,6 +309,7 @@ extern char *make_absolute __P((char *, char *));
|
||||
extern char *base_pathname __P((char *));
|
||||
extern char *full_pathname __P((char *));
|
||||
extern char *polite_directory_format __P((char *));
|
||||
extern char *trim_pathname __P((char *, int));
|
||||
|
||||
extern char *extract_colon_unit __P((char *, int *));
|
||||
|
||||
|
||||
+1
-1
@@ -281,7 +281,7 @@ extern void print_rlimtype __P((RLIMTYPE, int));
|
||||
#endif
|
||||
|
||||
extern int all_digits __P((char *));
|
||||
extern int legal_number __P((char *, intmax_t *));
|
||||
extern int legal_number __P((const char *, intmax_t *));
|
||||
extern int legal_identifier __P((char *));
|
||||
extern int check_identifier __P((WORD_DESC *, int));
|
||||
extern int legal_alias_name __P((char *, int));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hashcmd.h - Common defines for hashing filenames. */
|
||||
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
extern HASH_TABLE *hashed_filenames;
|
||||
|
||||
typedef struct {
|
||||
typedef struct _pathdata {
|
||||
char *path; /* The full pathname of the file. */
|
||||
int flags;
|
||||
} PATH_DATA;
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/* hashcmd.h - Common defines for hashing filenames. */
|
||||
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include "stdc.h"
|
||||
#include "hashlib.h"
|
||||
|
||||
#define FILENAME_HASH_BUCKETS 64 /* must be power of two */
|
||||
|
||||
extern HASH_TABLE *hashed_filenames;
|
||||
|
||||
typedef struct {
|
||||
char *path; /* The full pathname of the file. */
|
||||
int flags;
|
||||
} PATH_DATA;
|
||||
|
||||
#define HASH_RELPATH 0x01 /* this filename is a relative pathname. */
|
||||
#define HASH_CHKDOT 0x02 /* check `.' since it was earlier in $PATH */
|
||||
|
||||
#define pathdata(x) ((PATH_DATA *)(x)->data)
|
||||
|
||||
extern void phash_create __P((void));
|
||||
extern void phash_flush __P((void));
|
||||
|
||||
extern void phash_insert __P((char *, char *, int, int));
|
||||
extern int phash_remove __P((const char *));
|
||||
extern char *phash_search __P((const char *));
|
||||
@@ -3,7 +3,7 @@
|
||||
/* This file works with both POSIX and BSD systems. It implements job
|
||||
control. */
|
||||
|
||||
/* Copyright (C) 1989-2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -272,7 +272,6 @@ static void mark_dead_jobs_as_notified __P((int));
|
||||
static void restore_sigint_handler __P((void));
|
||||
#if defined (PGRP_PIPE)
|
||||
static void pipe_read __P((int *));
|
||||
static void pipe_close __P((int *));
|
||||
#endif
|
||||
|
||||
static struct pidstat *bgp_alloc __P((pid_t, int));
|
||||
@@ -455,7 +454,7 @@ start_pipeline ()
|
||||
cleanup_the_pipeline ();
|
||||
pipeline_pgrp = 0;
|
||||
#if defined (PGRP_PIPE)
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -485,7 +484,7 @@ stop_pipeline (async, deferred)
|
||||
|
||||
#if defined (PGRP_PIPE)
|
||||
/* The parent closes the process group synchronization pipe. */
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
|
||||
cleanup_dead_jobs ();
|
||||
@@ -1104,7 +1103,7 @@ add_process (name, pid)
|
||||
internal_warning (_("add_process: process %5ld (%s) in the_pipeline"), (long)p->pid, p->command);
|
||||
# endif
|
||||
if (PALIVE (p))
|
||||
internal_warning ("add_process: pid %5ld (%s) marked as still alive", (long)p->pid, p->command);
|
||||
internal_warning (_("add_process: pid %5ld (%s) marked as still alive"), (long)p->pid, p->command);
|
||||
p->running = PS_RECYCLED; /* mark as recycled */
|
||||
}
|
||||
#endif
|
||||
@@ -1793,16 +1792,18 @@ make_child (command, async_p)
|
||||
|
||||
#if defined (PGRP_PIPE)
|
||||
/* Release the process group pipe, since our call to setpgid ()
|
||||
is done. The last call to pipe_close is done in stop_pipeline. */
|
||||
pipe_close (pgrp_pipe);
|
||||
is done. The last call to sh_closepipe is done in stop_pipeline. */
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
#if 0
|
||||
/* Don't set last_asynchronous_pid in the child */
|
||||
if (async_p)
|
||||
last_asynchronous_pid = mypid; /* XXX */
|
||||
else
|
||||
#endif
|
||||
#if defined (RECYCLES_PIDS)
|
||||
else if (last_asynchronous_pid == mypid)
|
||||
if (last_asynchronous_pid == mypid)
|
||||
/* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
|
||||
last_asynchronous_pid = 1;
|
||||
#endif
|
||||
@@ -2213,6 +2214,7 @@ wait_sigint_handler (sig)
|
||||
/* XXX - should this be interrupt_state? If it is, the shell will act
|
||||
as if it got the SIGINT interrupt. */
|
||||
wait_sigint_received = 1;
|
||||
|
||||
/* Otherwise effectively ignore the SIGINT and allow the running job to
|
||||
be killed. */
|
||||
SIGRETURN (0);
|
||||
@@ -3032,6 +3034,7 @@ waitchld (wpid, block)
|
||||
if (sigchld || block == 0)
|
||||
waitpid_flags |= WNOHANG;
|
||||
CHECK_TERMSIG;
|
||||
|
||||
pid = WAITPID (-1, &status, waitpid_flags);
|
||||
|
||||
/* WCONTINUED may be rejected by waitpid as invalid even when defined */
|
||||
@@ -3078,7 +3081,11 @@ waitchld (wpid, block)
|
||||
a pipeline in backquote substitution. Even so, I'm not
|
||||
sure child is ever non-zero. */
|
||||
if (child == 0)
|
||||
continue;
|
||||
{
|
||||
if (WIFEXITED (status) || WIFSIGNALED (status))
|
||||
js.c_reaped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remember status, and whether or not the process is running. */
|
||||
child->status = status;
|
||||
@@ -4073,7 +4080,7 @@ without_job_control ()
|
||||
stop_making_children ();
|
||||
start_pipeline ();
|
||||
#if defined (PGRP_PIPE)
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
delete_all_jobs (0);
|
||||
set_job_control (0);
|
||||
@@ -4136,25 +4143,11 @@ pipe_read (pp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the read and write ends of PP, an array of file descriptors. */
|
||||
static void
|
||||
pipe_close (pp)
|
||||
int *pp;
|
||||
{
|
||||
if (pp[0] >= 0)
|
||||
close (pp[0]);
|
||||
|
||||
if (pp[1] >= 0)
|
||||
close (pp[1]);
|
||||
|
||||
pp[0] = pp[1] = -1;
|
||||
}
|
||||
|
||||
/* Functional interface closes our local-to-job-control pipes. */
|
||||
void
|
||||
close_pgrp_pipe ()
|
||||
{
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
}
|
||||
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* This file works with both POSIX and BSD systems. It implements job
|
||||
control. */
|
||||
|
||||
/* Copyright (C) 1989-2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -272,7 +272,6 @@ static void mark_dead_jobs_as_notified __P((int));
|
||||
static void restore_sigint_handler __P((void));
|
||||
#if defined (PGRP_PIPE)
|
||||
static void pipe_read __P((int *));
|
||||
static void pipe_close __P((int *));
|
||||
#endif
|
||||
|
||||
static struct pidstat *bgp_alloc __P((pid_t, int));
|
||||
@@ -455,7 +454,7 @@ start_pipeline ()
|
||||
cleanup_the_pipeline ();
|
||||
pipeline_pgrp = 0;
|
||||
#if defined (PGRP_PIPE)
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -485,7 +484,7 @@ stop_pipeline (async, deferred)
|
||||
|
||||
#if defined (PGRP_PIPE)
|
||||
/* The parent closes the process group synchronization pipe. */
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
|
||||
cleanup_dead_jobs ();
|
||||
@@ -1104,7 +1103,7 @@ add_process (name, pid)
|
||||
internal_warning (_("add_process: process %5ld (%s) in the_pipeline"), (long)p->pid, p->command);
|
||||
# endif
|
||||
if (PALIVE (p))
|
||||
internal_warning ("add_process: pid %5ld (%s) marked as still alive", (long)p->pid, p->command);
|
||||
internal_warning (_("add_process: pid %5ld (%s) marked as still alive"), (long)p->pid, p->command);
|
||||
p->running = PS_RECYCLED; /* mark as recycled */
|
||||
}
|
||||
#endif
|
||||
@@ -1793,16 +1792,18 @@ make_child (command, async_p)
|
||||
|
||||
#if defined (PGRP_PIPE)
|
||||
/* Release the process group pipe, since our call to setpgid ()
|
||||
is done. The last call to pipe_close is done in stop_pipeline. */
|
||||
pipe_close (pgrp_pipe);
|
||||
is done. The last call to sh_closepipe is done in stop_pipeline. */
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
#if 0
|
||||
/* Don't set last_asynchronous_pid in the child */
|
||||
if (async_p)
|
||||
last_asynchronous_pid = mypid; /* XXX */
|
||||
else
|
||||
#endif
|
||||
#if defined (RECYCLES_PIDS)
|
||||
else if (last_asynchronous_pid == mypid)
|
||||
if (last_asynchronous_pid == mypid)
|
||||
/* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
|
||||
last_asynchronous_pid = 1;
|
||||
#endif
|
||||
@@ -3032,6 +3033,7 @@ waitchld (wpid, block)
|
||||
if (sigchld || block == 0)
|
||||
waitpid_flags |= WNOHANG;
|
||||
CHECK_TERMSIG;
|
||||
|
||||
pid = WAITPID (-1, &status, waitpid_flags);
|
||||
|
||||
/* WCONTINUED may be rejected by waitpid as invalid even when defined */
|
||||
@@ -3078,7 +3080,11 @@ waitchld (wpid, block)
|
||||
a pipeline in backquote substitution. Even so, I'm not
|
||||
sure child is ever non-zero. */
|
||||
if (child == 0)
|
||||
continue;
|
||||
{
|
||||
if (WIFEXITED (status) || WIFSIGNALED (status))
|
||||
js.c_reaped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remember status, and whether or not the process is running. */
|
||||
child->status = status;
|
||||
@@ -3893,7 +3899,7 @@ count_all_jobs ()
|
||||
{
|
||||
#if defined (DEBUG)
|
||||
if (i < js.j_firstj && jobs[i])
|
||||
itrace<("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
|
||||
itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
|
||||
if (i > js.j_lastj && jobs[i])
|
||||
itrace("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
|
||||
#endif
|
||||
@@ -4073,7 +4079,7 @@ without_job_control ()
|
||||
stop_making_children ();
|
||||
start_pipeline ();
|
||||
#if defined (PGRP_PIPE)
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
delete_all_jobs (0);
|
||||
set_job_control (0);
|
||||
@@ -4136,25 +4142,11 @@ pipe_read (pp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the read and write ends of PP, an array of file descriptors. */
|
||||
static void
|
||||
pipe_close (pp)
|
||||
int *pp;
|
||||
{
|
||||
if (pp[0] >= 0)
|
||||
close (pp[0]);
|
||||
|
||||
if (pp[1] >= 0)
|
||||
close (pp[1]);
|
||||
|
||||
pp[0] = pp[1] = -1;
|
||||
}
|
||||
|
||||
/* Functional interface closes our local-to-job-control pipes. */
|
||||
void
|
||||
close_pgrp_pipe ()
|
||||
{
|
||||
pipe_close (pgrp_pipe);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
}
|
||||
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
+201
-25
@@ -1,6 +1,6 @@
|
||||
/* glob.c -- file-name wildcard pattern matching for Bash.
|
||||
|
||||
Copyright (C) 1985-2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1985-2008 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
|
||||
@@ -45,7 +45,8 @@
|
||||
|
||||
#include "stdc.h"
|
||||
#include "memalloc.h"
|
||||
#include "quit.h"
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#include "glob.h"
|
||||
#include "strmatch.h"
|
||||
@@ -72,8 +73,15 @@
|
||||
# define ALLOCA_MAX 100000
|
||||
#endif
|
||||
|
||||
struct globval
|
||||
{
|
||||
struct globval *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
extern void throw_to_top_level __P((void));
|
||||
extern int sh_eaccess __P((char *, int));
|
||||
extern char *sh_makepath __P((const char *, const char *, int));
|
||||
|
||||
extern int extended_glob;
|
||||
|
||||
@@ -88,10 +96,12 @@ int glob_ignore_case = 0;
|
||||
/* Global variable to return to signify an error in globbing. */
|
||||
char *glob_error_return;
|
||||
|
||||
static struct globval finddirs_error_return;
|
||||
|
||||
/* Some forward declarations. */
|
||||
static int skipname __P((char *, char *));
|
||||
static int skipname __P((char *, char *, int));
|
||||
#if HANDLE_MULTIBYTE
|
||||
static int mbskipname __P((char *, char *));
|
||||
static int mbskipname __P((char *, char *, int));
|
||||
#endif
|
||||
#if HANDLE_MULTIBYTE
|
||||
static void udequote_pathname __P((char *));
|
||||
@@ -154,9 +164,10 @@ glob_pattern_p (pattern)
|
||||
with matching leading `.'. */
|
||||
|
||||
static int
|
||||
skipname (pat, dname)
|
||||
skipname (pat, dname, flags)
|
||||
char *pat;
|
||||
char *dname;
|
||||
int flags;
|
||||
{
|
||||
/* If a leading dot need not be explicitly matched, and the pattern
|
||||
doesn't start with a `.', don't match `.' or `..' */
|
||||
@@ -179,8 +190,9 @@ skipname (pat, dname)
|
||||
characters in PAT and DNAME. Mostly concerned with matching leading `.'. */
|
||||
|
||||
static int
|
||||
mbskipname (pat, dname)
|
||||
mbskipname (pat, dname, flags)
|
||||
char *pat, *dname;
|
||||
int flags;
|
||||
{
|
||||
int ret;
|
||||
wchar_t *pat_wc, *dn_wc;
|
||||
@@ -315,6 +327,75 @@ glob_testdir (dir)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Recursively scan SDIR for directories matching PAT (PAT is always `**').
|
||||
FLAGS is simply passed down to the recursive call to glob_vector. Returns
|
||||
a list of matching directory names. EP, if non-null, is set to the last
|
||||
element of the returned list. NP, if non-null, is set to the number of
|
||||
directories in the returned list. These two variables exist for the
|
||||
convenience of the caller (always glob_vector). */
|
||||
static struct globval *
|
||||
finddirs (pat, sdir, flags, ep, np)
|
||||
char *pat;
|
||||
char *sdir;
|
||||
int flags;
|
||||
struct globval **ep;
|
||||
int *np;
|
||||
{
|
||||
char **r, *n;
|
||||
int ndirs;
|
||||
struct globval *ret, *e, *g;
|
||||
|
||||
/*itrace("finddirs: pat = `%s' sdir = `%s' flags = 0x%x", pat, sdir, flags);*/
|
||||
e = ret = 0;
|
||||
r = glob_vector (pat, sdir, flags);
|
||||
if (r == 0 || r[0] == 0)
|
||||
{
|
||||
if (np)
|
||||
*np = 0;
|
||||
if (ep)
|
||||
*ep = 0;
|
||||
if (r)
|
||||
free (r);
|
||||
return (struct globval *)0;
|
||||
}
|
||||
for (ndirs = 0; r[ndirs] != 0; ndirs++)
|
||||
{
|
||||
g = (struct globval *) malloc (sizeof (struct globval));
|
||||
if (g == 0)
|
||||
{
|
||||
while (ret) /* free list built so far */
|
||||
{
|
||||
g = ret->next;
|
||||
free (ret);
|
||||
ret = g;
|
||||
}
|
||||
|
||||
free (r);
|
||||
if (np)
|
||||
*np = 0;
|
||||
if (ep)
|
||||
*ep = 0;
|
||||
return (&finddirs_error_return);
|
||||
}
|
||||
if (e == 0)
|
||||
e = g;
|
||||
|
||||
g->next = ret;
|
||||
ret = g;
|
||||
|
||||
g->name = r[ndirs];
|
||||
}
|
||||
|
||||
free (r);
|
||||
if (ep)
|
||||
*ep = e;
|
||||
if (np)
|
||||
*np = ndirs;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Return a vector of names of files in directory DIR
|
||||
whose names match glob pattern PAT.
|
||||
The names are not in any particular order.
|
||||
@@ -337,31 +418,27 @@ glob_vector (pat, dir, flags)
|
||||
char *dir;
|
||||
int flags;
|
||||
{
|
||||
struct globval
|
||||
{
|
||||
struct globval *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
DIR *d;
|
||||
register struct dirent *dp;
|
||||
struct globval *lastlink;
|
||||
struct globval *lastlink, *e, *dirlist;
|
||||
register struct globval *nextlink;
|
||||
register char *nextname, *npat;
|
||||
register char *nextname, *npat, *subdir;
|
||||
unsigned int count;
|
||||
int lose, skip;
|
||||
int lose, skip, ndirs, isdir, sdlen, add_current;
|
||||
register char **name_vector;
|
||||
register unsigned int i;
|
||||
int mflags; /* Flags passed to strmatch (). */
|
||||
int pflags; /* flags passed to sh_makepath () */
|
||||
int nalloca;
|
||||
struct globval *firstmalloc, *tmplink;
|
||||
|
||||
lastlink = 0;
|
||||
count = lose = skip = 0;
|
||||
count = lose = skip = add_current = 0;
|
||||
|
||||
firstmalloc = 0;
|
||||
nalloca = 0;
|
||||
|
||||
/*itrace("glob_vector: pat = `%s' dir = `%s' flags = 0x%x", pat, dir, flags);*/
|
||||
/* If PAT is empty, skip the loop, but return one (empty) filename. */
|
||||
if (pat == 0 || *pat == '\0')
|
||||
{
|
||||
@@ -463,6 +540,8 @@ glob_vector (pat, dir, flags)
|
||||
if (extended_glob)
|
||||
mflags |= FNM_EXTMATCH;
|
||||
|
||||
add_current = ((flags & (GX_ALLDIRS|GX_ADDCURDIR)) == (GX_ALLDIRS|GX_ADDCURDIR));
|
||||
|
||||
/* Scan the directory, finding all names that match.
|
||||
For each name that matches, allocate a struct globval
|
||||
on the stack and store the name in it.
|
||||
@@ -490,13 +569,69 @@ glob_vector (pat, dir, flags)
|
||||
#endif
|
||||
|
||||
#if HANDLE_MULTIBYTE
|
||||
if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name))
|
||||
if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name, flags))
|
||||
continue;
|
||||
else
|
||||
#endif
|
||||
if (skipname (pat, dp->d_name))
|
||||
if (skipname (pat, dp->d_name, flags))
|
||||
continue;
|
||||
|
||||
/* If we're only interested in directories, don't bother with files */
|
||||
if (flags & (GX_MATCHDIRS|GX_ALLDIRS))
|
||||
{
|
||||
pflags = (flags & GX_ALLDIRS) ? MP_RMDOT : 0;
|
||||
if (flags & GX_NULLDIR)
|
||||
pflags |= MP_IGNDOT;
|
||||
subdir = sh_makepath (dir, dp->d_name, pflags);
|
||||
isdir = glob_testdir (subdir);
|
||||
if (isdir < 0 && (flags & GX_MATCHDIRS))
|
||||
{
|
||||
free (subdir);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & GX_ALLDIRS)
|
||||
{
|
||||
if (isdir == 0)
|
||||
{
|
||||
dirlist = finddirs (pat, subdir, (flags & ~GX_ADDCURDIR), &e, &ndirs);
|
||||
if (dirlist == &finddirs_error_return)
|
||||
{
|
||||
free (subdir);
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
if (ndirs) /* add recursive directories to list */
|
||||
{
|
||||
if (firstmalloc == 0)
|
||||
firstmalloc = e;
|
||||
e->next = lastlink;
|
||||
lastlink = dirlist;
|
||||
count += ndirs;
|
||||
}
|
||||
}
|
||||
|
||||
nextlink = (struct globval *) malloc (sizeof (struct globval));
|
||||
if (firstmalloc == 0)
|
||||
firstmalloc = nextlink;
|
||||
sdlen = strlen (subdir);
|
||||
nextname = (char *) malloc (sdlen + 1);
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
{
|
||||
free (subdir);
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
nextlink->next = lastlink;
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
bcopy (subdir, nextname, sdlen + 1);
|
||||
free (subdir);
|
||||
++count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strmatch (pat, dp->d_name, mflags) != FNM_NOMATCH)
|
||||
{
|
||||
if (nalloca < ALLOCA_MAX)
|
||||
@@ -510,6 +645,7 @@ glob_vector (pat, dir, flags)
|
||||
if (firstmalloc == 0)
|
||||
firstmalloc = nextlink;
|
||||
}
|
||||
|
||||
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
{
|
||||
@@ -527,6 +663,27 @@ glob_vector (pat, dir, flags)
|
||||
(void) closedir (d);
|
||||
}
|
||||
|
||||
/* compat: if GX_ALLDIRS, add the passed directory also */
|
||||
if (add_current)
|
||||
{
|
||||
sdlen = strlen (dir);
|
||||
nextname = (char *)malloc (sdlen + 1);
|
||||
nextlink = (struct globval *) malloc (sizeof (struct globval));
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
lose = 1;
|
||||
else
|
||||
{
|
||||
nextlink->name = nextname;
|
||||
nextlink->next = lastlink;
|
||||
lastlink = nextlink;
|
||||
if (flags & GX_NULLDIR)
|
||||
nextname[0] = '\0';
|
||||
else
|
||||
bcopy (dir, nextname, sdlen + 1);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
if (lose == 0)
|
||||
{
|
||||
name_vector = (char **) malloc ((count + 1) * sizeof (char *));
|
||||
@@ -585,7 +742,7 @@ glob_vector (pat, dir, flags)
|
||||
free (tmplink);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (name_vector);
|
||||
}
|
||||
|
||||
@@ -678,9 +835,10 @@ glob_filename (pathname, flags)
|
||||
{
|
||||
char **result;
|
||||
unsigned int result_size;
|
||||
char *directory_name, *filename;
|
||||
char *directory_name, *filename, *dname;
|
||||
unsigned int directory_len;
|
||||
int free_dirname; /* flag */
|
||||
int dflags;
|
||||
|
||||
result = (char **) malloc (sizeof (char *));
|
||||
result_size = 1;
|
||||
@@ -721,10 +879,14 @@ glob_filename (pathname, flags)
|
||||
char **directories;
|
||||
register unsigned int i;
|
||||
|
||||
dflags = flags & ~GX_MARKDIRS;
|
||||
if ((flags & GX_GLOBSTAR) && directory_name[0] == '*' && directory_name[1] == '*' && (directory_name[2] == '/' || directory_name[2] == '\0'))
|
||||
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
|
||||
|
||||
if (directory_name[directory_len - 1] == '/')
|
||||
directory_name[directory_len - 1] = '\0';
|
||||
|
||||
directories = glob_filename (directory_name, flags & ~GX_MARKDIRS);
|
||||
directories = glob_filename (directory_name, dflags);
|
||||
|
||||
if (free_dirname)
|
||||
{
|
||||
@@ -753,10 +915,19 @@ glob_filename (pathname, flags)
|
||||
{
|
||||
char **temp_results;
|
||||
|
||||
/* Scan directory even on a NULL pathname. That way, `*h/'
|
||||
/* Scan directory even on a NULL filename. That way, `*h/'
|
||||
returns only directories ending in `h', instead of all
|
||||
files ending in `h' with a `/' appended. */
|
||||
temp_results = glob_vector (filename, directories[i], flags & ~GX_MARKDIRS);
|
||||
dname = directories[i];
|
||||
dflags = flags & ~GX_MARKDIRS;
|
||||
if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
|
||||
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
|
||||
if (dname[0] == '\0' && filename[0])
|
||||
{
|
||||
dflags |= GX_NULLDIR;
|
||||
dname = "."; /* treat null directory name and non-null filename as current directory */
|
||||
}
|
||||
temp_results = glob_vector (filename, dname, dflags);
|
||||
|
||||
/* Handle error cases. */
|
||||
if (temp_results == NULL)
|
||||
@@ -830,9 +1001,14 @@ glob_filename (pathname, flags)
|
||||
|
||||
/* Just return what glob_vector () returns appended to the
|
||||
directory name. */
|
||||
dflags = flags & ~GX_MARKDIRS;
|
||||
if (directory_len == 0)
|
||||
dflags |= GX_NULLDIR;
|
||||
if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
|
||||
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
|
||||
temp_results = glob_vector (filename,
|
||||
(directory_len == 0 ? "." : directory_name),
|
||||
flags & ~GX_MARKDIRS);
|
||||
dflags);
|
||||
|
||||
if (temp_results == NULL || temp_results == (char **)&glob_error_return)
|
||||
{
|
||||
@@ -841,7 +1017,7 @@ glob_filename (pathname, flags)
|
||||
return (temp_results);
|
||||
}
|
||||
|
||||
result = glob_dir_to_array (directory_name, temp_results, flags);
|
||||
result = glob_dir_to_array ((dflags & GX_ALLDIRS) ? "" : directory_name, temp_results, flags);
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
return (result);
|
||||
|
||||
+1067
File diff suppressed because it is too large
Load Diff
+5
-2
@@ -23,8 +23,11 @@
|
||||
#define GX_MARKDIRS 0x001 /* mark directory names with trailing `/' */
|
||||
#define GX_NOCASE 0x002 /* ignore case */
|
||||
#define GX_MATCHDOT 0x004 /* match `.' literally */
|
||||
#define GX_ALLDIRS 0x008 /* match all directories */
|
||||
#define GX_MATCHDIRS 0x010 /* return only matching directory names */
|
||||
#define GX_MATCHDIRS 0x008 /* match only directory names */
|
||||
#define GX_ALLDIRS 0x010 /* match all directory names, no others */
|
||||
#define GX_NULLDIR 0x100 /* internal -- no directory preceding pattern */
|
||||
#define GX_ADDCURDIR 0x200 /* internal -- add passed directory name */
|
||||
#define GX_GLOBSTAR 0x400 /* turn on special handling of ** */
|
||||
|
||||
extern int glob_pattern_p __P((const char *));
|
||||
extern char **glob_vector __P((char *, char *, int));
|
||||
|
||||
+24
-24
@@ -317,7 +317,7 @@ rl_macro_bind (keyseq, macro, map)
|
||||
|
||||
if (rl_translate_keyseq (macro, macro_keys, ¯o_keys_len))
|
||||
{
|
||||
free (macro_keys);
|
||||
xfree (macro_keys);
|
||||
return -1;
|
||||
}
|
||||
rl_generic_bind (ISMACR, keyseq, macro_keys, map);
|
||||
@@ -347,7 +347,7 @@ rl_generic_bind (type, keyseq, data, map)
|
||||
if (keyseq == 0 || *keyseq == 0)
|
||||
{
|
||||
if (type == ISMACR)
|
||||
free (data);
|
||||
xfree (data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ rl_generic_bind (type, keyseq, data, map)
|
||||
KEYS into KEYS_LEN. */
|
||||
if (rl_translate_keyseq (keyseq, keys, &keys_len))
|
||||
{
|
||||
free (keys);
|
||||
xfree (keys);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ rl_generic_bind (type, keyseq, data, map)
|
||||
ic = uc;
|
||||
if (ic < 0 || ic >= KEYMAP_SIZE)
|
||||
{
|
||||
free (keys);
|
||||
xfree (keys);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -414,7 +414,7 @@ rl_generic_bind (type, keyseq, data, map)
|
||||
else
|
||||
{
|
||||
if (map[ic].type == ISMACR)
|
||||
free ((char *)map[ic].function);
|
||||
xfree ((char *)map[ic].function);
|
||||
else if (map[ic].type == ISKMAP)
|
||||
{
|
||||
map = FUNCTION_TO_KEYMAP (map, ic);
|
||||
@@ -427,7 +427,7 @@ rl_generic_bind (type, keyseq, data, map)
|
||||
|
||||
rl_binding_keymap = map;
|
||||
}
|
||||
free (keys);
|
||||
xfree (keys);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -793,7 +793,7 @@ _rl_read_file (filename, sizep)
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
free (buffer);
|
||||
xfree (buffer);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
@@ -863,7 +863,7 @@ _rl_read_init_file (filename, include_level)
|
||||
|
||||
openname = tilde_expand (filename);
|
||||
buffer = _rl_read_file (openname, &file_size);
|
||||
free (openname);
|
||||
xfree (openname);
|
||||
|
||||
if (buffer == 0)
|
||||
return (errno);
|
||||
@@ -911,7 +911,7 @@ _rl_read_init_file (filename, include_level)
|
||||
current_readline_init_lineno++;
|
||||
}
|
||||
|
||||
free (buffer);
|
||||
xfree (buffer);
|
||||
currently_reading_init_file = 0;
|
||||
return (0);
|
||||
}
|
||||
@@ -1002,7 +1002,7 @@ parser_if (args)
|
||||
`$if term=sun-cmd' into their .inputrc. */
|
||||
_rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
|
||||
_rl_stricmp (args + 5, rl_terminal_name);
|
||||
free (tname);
|
||||
xfree (tname);
|
||||
}
|
||||
#if defined (VI_MODE)
|
||||
else if (_rl_strnicmp (args, "mode=", 5) == 0)
|
||||
@@ -1352,7 +1352,7 @@ rl_parse_and_bind (string)
|
||||
else
|
||||
rl_bind_keyseq (seq, rl_named_function (funname));
|
||||
|
||||
free (seq);
|
||||
xfree (seq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1695,7 +1695,7 @@ sv_isrchterm (value)
|
||||
rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end);
|
||||
_rl_isearch_terminators[end] = '\0';
|
||||
|
||||
free (v);
|
||||
xfree (v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1856,7 +1856,7 @@ rl_list_funmap_names ()
|
||||
for (i = 0; funmap_names[i]; i++)
|
||||
fprintf (rl_outstream, "%s\n", funmap_names[i]);
|
||||
|
||||
free (funmap_names);
|
||||
xfree (funmap_names);
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -2022,7 +2022,7 @@ rl_invoking_keyseqs_in_map (function, map)
|
||||
}
|
||||
|
||||
strcat (keyname, seqs[i]);
|
||||
free (seqs[i]);
|
||||
xfree (seqs[i]);
|
||||
|
||||
if (result_index + 2 > result_size)
|
||||
{
|
||||
@@ -2034,7 +2034,7 @@ rl_invoking_keyseqs_in_map (function, map)
|
||||
result[result_index] = (char *)NULL;
|
||||
}
|
||||
|
||||
free (seqs);
|
||||
xfree (seqs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2086,10 +2086,10 @@ rl_function_dumper (print_readably)
|
||||
{
|
||||
fprintf (rl_outstream, "\"%s\": %s\n",
|
||||
invokers[j], name);
|
||||
free (invokers[j]);
|
||||
xfree (invokers[j]);
|
||||
}
|
||||
|
||||
free (invokers);
|
||||
xfree (invokers);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2113,9 +2113,9 @@ rl_function_dumper (print_readably)
|
||||
fprintf (rl_outstream, "...\n");
|
||||
|
||||
for (j = 0; invokers[j]; j++)
|
||||
free (invokers[j]);
|
||||
xfree (invokers[j]);
|
||||
|
||||
free (invokers);
|
||||
xfree (invokers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2161,8 +2161,8 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
|
||||
fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
|
||||
keyname,
|
||||
out ? out : "");
|
||||
free (keyname);
|
||||
free (out);
|
||||
xfree (keyname);
|
||||
xfree (out);
|
||||
break;
|
||||
case ISFUNC:
|
||||
break;
|
||||
@@ -2185,13 +2185,13 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
|
||||
out = (char *)xmalloc (strlen (keyname) + prefix_len + 1);
|
||||
strcpy (out, prefix);
|
||||
strcpy (out + prefix_len, keyname);
|
||||
free (keyname);
|
||||
xfree (keyname);
|
||||
keyname = out;
|
||||
}
|
||||
}
|
||||
|
||||
_rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
|
||||
free (keyname);
|
||||
xfree (keyname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2252,7 +2252,7 @@ _rl_get_string_variable_value (name)
|
||||
if (ret)
|
||||
{
|
||||
strncpy (numbuf, ret, sizeof (numbuf) - 1);
|
||||
free (ret);
|
||||
xfree (ret);
|
||||
numbuf[sizeof(numbuf) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1709,7 +1709,7 @@ sv_histsize (value)
|
||||
{
|
||||
nval = atoi (value);
|
||||
if (nval < 0)
|
||||
nval = 0;
|
||||
return 1;
|
||||
}
|
||||
stifle_history (nval);
|
||||
return 0;
|
||||
|
||||
+173
-6
@@ -1,6 +1,6 @@
|
||||
/* complete.c -- filename completion for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 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.
|
||||
@@ -188,6 +188,10 @@ int rl_complete_with_tilde_expansion = 0;
|
||||
completer. */
|
||||
rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL;
|
||||
|
||||
/* Pointer to generator function for rl_menu_complete (). NULL means to use
|
||||
*rl_completion_entry_function (see above). */
|
||||
rl_compentry_func_t *rl_menu_completion_entry_function = (rl_compentry_func_t *)NULL;
|
||||
|
||||
/* Pointer to alternative function to create matches.
|
||||
Function is called with TEXT, START, and END.
|
||||
START and END are indices in RL_LINE_BUFFER saying what the boundaries
|
||||
@@ -336,6 +340,9 @@ int rl_sort_completion_matches = 1;
|
||||
/* Local variable states what happened during the last completion attempt. */
|
||||
static int completion_changed_buffer;
|
||||
|
||||
/* The result of the query to the user about displaying completion matches */
|
||||
static int completion_y_or_n;
|
||||
|
||||
/*************************************/
|
||||
/* */
|
||||
/* Bindable completion functions */
|
||||
@@ -1186,8 +1193,7 @@ compute_lcd_of_matches (match_list, matches, text)
|
||||
}
|
||||
|
||||
/* sort the list to get consistent answers. */
|
||||
if (rl_sort_completion_matches)
|
||||
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
|
||||
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
|
||||
|
||||
si = strlen (text);
|
||||
if (si <= low)
|
||||
@@ -1433,7 +1439,7 @@ display_matches (matches)
|
||||
rl_crlf ();
|
||||
fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
|
||||
fflush (rl_outstream);
|
||||
if (get_y_or_n (0) == 0)
|
||||
if ((completion_y_or_n = get_y_or_n (0)) == 0)
|
||||
{
|
||||
rl_crlf ();
|
||||
|
||||
@@ -2140,7 +2146,7 @@ rl_filename_completion_function (text, state)
|
||||
hit the end of the match list, we restore the original unmatched text,
|
||||
ring the bell, and reset the counter to zero. */
|
||||
int
|
||||
rl_menu_complete (count, invoking_key)
|
||||
rl_old_menu_complete (count, invoking_key)
|
||||
int count, invoking_key;
|
||||
{
|
||||
rl_compentry_func_t *our_func;
|
||||
@@ -2171,7 +2177,9 @@ rl_menu_complete (count, invoking_key)
|
||||
/* Only the completion entry function can change these. */
|
||||
set_completion_defaults ('%');
|
||||
|
||||
our_func = rl_completion_entry_function
|
||||
our_func = rl_menu_completion_entry_function;
|
||||
if (our_func == 0)
|
||||
our_func = rl_completion_entry_function
|
||||
? rl_completion_entry_function
|
||||
: rl_filename_completion_function;
|
||||
|
||||
@@ -2212,6 +2220,10 @@ rl_menu_complete (count, invoking_key)
|
||||
;
|
||||
/* matches[0] is lcd if match_list_size > 1, but the circular buffer
|
||||
code below should take care of it. */
|
||||
|
||||
if
|
||||
(match_list_size > 1 && _rl_complete_show_all)
|
||||
display_matches (matches);
|
||||
}
|
||||
|
||||
/* Now we have the list of matches. Replace the text between
|
||||
@@ -2248,3 +2260,158 @@ rl_menu_complete (count, invoking_key)
|
||||
completion_changed_buffer = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_menu_complete (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
rl_compentry_func_t *our_func;
|
||||
int matching_filenames, found_quote;
|
||||
|
||||
static char *orig_text;
|
||||
static char **matches = (char **)0;
|
||||
static int match_list_index = 0;
|
||||
static int match_list_size = 0;
|
||||
static int nontrivial_lcd = 0;
|
||||
static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
|
||||
static int orig_start, orig_end;
|
||||
static char quote_char;
|
||||
static int delimiter;
|
||||
|
||||
/* The first time through, we generate the list of matches and set things
|
||||
up to insert them. */
|
||||
if (rl_last_func != rl_menu_complete || full_completion)
|
||||
{
|
||||
/* Clean up from previous call, if any. */
|
||||
FREE (orig_text);
|
||||
if (matches)
|
||||
_rl_free_match_list (matches);
|
||||
|
||||
match_list_index = match_list_size = 0;
|
||||
matches = (char **)NULL;
|
||||
|
||||
full_completion = 0;
|
||||
|
||||
/* Only the completion entry function can change these. */
|
||||
set_completion_defaults ('%');
|
||||
|
||||
our_func = rl_menu_completion_entry_function;
|
||||
if (our_func == 0)
|
||||
our_func = rl_completion_entry_function
|
||||
? rl_completion_entry_function
|
||||
: rl_filename_completion_function;
|
||||
|
||||
/* We now look backwards for the start of a filename/variable word. */
|
||||
orig_end = rl_point;
|
||||
found_quote = delimiter = 0;
|
||||
quote_char = '\0';
|
||||
|
||||
if (rl_point)
|
||||
/* This (possibly) changes rl_point. If it returns a non-zero char,
|
||||
we know we have an open quote. */
|
||||
quote_char = _rl_find_completion_word (&found_quote, &delimiter);
|
||||
|
||||
orig_start = rl_point;
|
||||
rl_point = orig_end;
|
||||
|
||||
orig_text = rl_copy_text (orig_start, orig_end);
|
||||
matches = gen_completion_matches (orig_text, orig_start, orig_end,
|
||||
our_func, found_quote, quote_char);
|
||||
|
||||
nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 0;
|
||||
|
||||
/* If we are matching filenames, the attempted completion function will
|
||||
have set rl_filename_completion_desired to a non-zero value. The basic
|
||||
rl_filename_completion_function does this. */
|
||||
matching_filenames = rl_filename_completion_desired;
|
||||
|
||||
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
FREE (orig_text);
|
||||
orig_text = (char *)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (match_list_size = 0; matches[match_list_size]; match_list_size++)
|
||||
;
|
||||
|
||||
if (match_list_size == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
match_list_index = 0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* matches[0] is lcd if match_list_size > 1, but the circular buffer
|
||||
code below should take care of it. */
|
||||
if (*matches[0])
|
||||
{
|
||||
insert_match (matches[0], orig_start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
orig_end = orig_start + strlen (matches[0]);
|
||||
completion_changed_buffer = STREQ (orig_text, matches[0]) == 0;
|
||||
}
|
||||
|
||||
if (match_list_size > 1 && _rl_complete_show_all)
|
||||
{
|
||||
display_matches (matches);
|
||||
/* If there are so many matches that the user has to be asked
|
||||
whether or not he wants to see the matches, menu completion
|
||||
is unwieldy. */
|
||||
if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else if (match_list_size <= 1)
|
||||
{
|
||||
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have the list of matches. Replace the text between
|
||||
rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
|
||||
matches[match_list_index], and add any necessary closing char. */
|
||||
|
||||
if (matches == 0 || match_list_size == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
match_list_index += count;
|
||||
if (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
else
|
||||
match_list_index %= match_list_size;
|
||||
|
||||
if (match_list_index == 0 && match_list_size > 1)
|
||||
{
|
||||
rl_ding ();
|
||||
insert_match (matches[0], orig_start, MULT_MATCH, "e_char);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char);
|
||||
append_to_match (matches[match_list_index], delimiter, quote_char,
|
||||
strcmp (orig_text, matches[match_list_index]));
|
||||
}
|
||||
|
||||
completion_changed_buffer = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
+176
-5
@@ -1,6 +1,6 @@
|
||||
/* complete.c -- filename completion for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 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.
|
||||
@@ -188,6 +188,10 @@ int rl_complete_with_tilde_expansion = 0;
|
||||
completer. */
|
||||
rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL;
|
||||
|
||||
/* Pointer to generator function for rl_menu_complete (). NULL means to use
|
||||
*rl_completion_entry_function (see above). */
|
||||
rl_compentry_func_t *rl_menu_completion_entry_function = (rl_compentry_func_t *)NULL;
|
||||
|
||||
/* Pointer to alternative function to create matches.
|
||||
Function is called with TEXT, START, and END.
|
||||
START and END are indices in RL_LINE_BUFFER saying what the boundaries
|
||||
@@ -336,6 +340,9 @@ int rl_sort_completion_matches = 1;
|
||||
/* Local variable states what happened during the last completion attempt. */
|
||||
static int completion_changed_buffer;
|
||||
|
||||
/* The result of the query to the user about displaying completion matches */
|
||||
static int completion_y_or_n;
|
||||
|
||||
/*************************************/
|
||||
/* */
|
||||
/* Bindable completion functions */
|
||||
@@ -405,7 +412,7 @@ rl_completion_mode (cfunc)
|
||||
/* */
|
||||
/************************************/
|
||||
|
||||
/* Reset readline state on a signal. */
|
||||
/* Reset readline state on a signal or other event. */
|
||||
void
|
||||
_rl_reset_completion_state ()
|
||||
{
|
||||
@@ -1433,7 +1440,7 @@ display_matches (matches)
|
||||
rl_crlf ();
|
||||
fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
|
||||
fflush (rl_outstream);
|
||||
if (get_y_or_n (0) == 0)
|
||||
if ((completion_y_or_n = get_y_or_n (0)) == 0)
|
||||
{
|
||||
rl_crlf ();
|
||||
|
||||
@@ -1705,6 +1712,7 @@ rl_complete_internal (what_to_do)
|
||||
FREE (saved_line_buffer);
|
||||
completion_changed_buffer = 0;
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
_rl_reset_completion_state ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1719,6 +1727,7 @@ rl_complete_internal (what_to_do)
|
||||
FREE (saved_line_buffer);
|
||||
completion_changed_buffer = 0;
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
_rl_reset_completion_state ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1773,6 +1782,7 @@ rl_complete_internal (what_to_do)
|
||||
rl_ding ();
|
||||
FREE (saved_line_buffer);
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
_rl_reset_completion_state ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1786,6 +1796,7 @@ rl_complete_internal (what_to_do)
|
||||
}
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
_rl_reset_completion_state ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2136,7 +2147,7 @@ rl_filename_completion_function (text, state)
|
||||
hit the end of the match list, we restore the original unmatched text,
|
||||
ring the bell, and reset the counter to zero. */
|
||||
int
|
||||
rl_menu_complete (count, invoking_key)
|
||||
rl_old_menu_complete (count, invoking_key)
|
||||
int count, invoking_key;
|
||||
{
|
||||
rl_compentry_func_t *our_func;
|
||||
@@ -2167,7 +2178,9 @@ rl_menu_complete (count, invoking_key)
|
||||
/* Only the completion entry function can change these. */
|
||||
set_completion_defaults ('%');
|
||||
|
||||
our_func = rl_completion_entry_function
|
||||
our_func = rl_menu_completion_entry_function;
|
||||
if (our_func == 0)
|
||||
our_func = rl_completion_entry_function
|
||||
? rl_completion_entry_function
|
||||
: rl_filename_completion_function;
|
||||
|
||||
@@ -2208,6 +2221,9 @@ rl_menu_complete (count, invoking_key)
|
||||
;
|
||||
/* matches[0] is lcd if match_list_size > 1, but the circular buffer
|
||||
code below should take care of it. */
|
||||
|
||||
if (match_list_size > 1 && _rl_complete_show_all)
|
||||
display_matches (matches);
|
||||
}
|
||||
|
||||
/* Now we have the list of matches. Replace the text between
|
||||
@@ -2244,3 +2260,158 @@ rl_menu_complete (count, invoking_key)
|
||||
completion_changed_buffer = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_menu_complete (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
rl_compentry_func_t *our_func;
|
||||
int matching_filenames, found_quote;
|
||||
|
||||
static char *orig_text;
|
||||
static char **matches = (char **)0;
|
||||
static int match_list_index = 0;
|
||||
static int match_list_size = 0;
|
||||
static int nontrivial_lcd = 0;
|
||||
static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
|
||||
static int orig_start, orig_end;
|
||||
static char quote_char;
|
||||
static int delimiter;
|
||||
|
||||
/* The first time through, we generate the list of matches and set things
|
||||
up to insert them. */
|
||||
if (rl_last_func != rl_menu_complete || full_completion)
|
||||
{
|
||||
/* Clean up from previous call, if any. */
|
||||
FREE (orig_text);
|
||||
if (matches)
|
||||
_rl_free_match_list (matches);
|
||||
|
||||
match_list_index = match_list_size = 0;
|
||||
matches = (char **)NULL;
|
||||
|
||||
full_completion = 0;
|
||||
|
||||
/* Only the completion entry function can change these. */
|
||||
set_completion_defaults ('%');
|
||||
|
||||
our_func = rl_menu_completion_entry_function;
|
||||
if (our_func == 0)
|
||||
our_func = rl_completion_entry_function
|
||||
? rl_completion_entry_function
|
||||
: rl_filename_completion_function;
|
||||
|
||||
/* We now look backwards for the start of a filename/variable word. */
|
||||
orig_end = rl_point;
|
||||
found_quote = delimiter = 0;
|
||||
quote_char = '\0';
|
||||
|
||||
if (rl_point)
|
||||
/* This (possibly) changes rl_point. If it returns a non-zero char,
|
||||
we know we have an open quote. */
|
||||
quote_char = _rl_find_completion_word (&found_quote, &delimiter);
|
||||
|
||||
orig_start = rl_point;
|
||||
rl_point = orig_end;
|
||||
|
||||
orig_text = rl_copy_text (orig_start, orig_end);
|
||||
matches = gen_completion_matches (orig_text, orig_start, orig_end,
|
||||
our_func, found_quote, quote_char);
|
||||
|
||||
nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 0;
|
||||
|
||||
/* If we are matching filenames, the attempted completion function will
|
||||
have set rl_filename_completion_desired to a non-zero value. The basic
|
||||
rl_filename_completion_function does this. */
|
||||
matching_filenames = rl_filename_completion_desired;
|
||||
|
||||
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
FREE (orig_text);
|
||||
orig_text = (char *)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (match_list_size = 0; matches[match_list_size]; match_list_size++)
|
||||
;
|
||||
|
||||
if (match_list_size == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
match_list_index = 0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* matches[0] is lcd if match_list_size > 1, but the circular buffer
|
||||
code below should take care of it. */
|
||||
if (*matches[0])
|
||||
{
|
||||
insert_match (matches[0], orig_start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
orig_end = orig_start + strlen (matches[0]);
|
||||
completion_changed_buffer = STREQ (orig_text, matches[0]) == 0;
|
||||
}
|
||||
|
||||
if (match_list_size > 1 && _rl_complete_show_all)
|
||||
{
|
||||
display_matches (matches);
|
||||
/* If there are so many matches that the user has to be asked
|
||||
whether or not he wants to see the matches, menu completion
|
||||
is unwieldy. */
|
||||
if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else if (match_list_size <= 1)
|
||||
{
|
||||
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have the list of matches. Replace the text between
|
||||
rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
|
||||
matches[match_list_index], and add any necessary closing char. */
|
||||
|
||||
if (matches == 0 || match_list_size == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
match_list_index += count;
|
||||
if (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
else
|
||||
match_list_index %= match_list_size;
|
||||
|
||||
if (match_list_index == 0 && match_list_size > 1)
|
||||
{
|
||||
rl_ding ();
|
||||
insert_match (matches[0], orig_start, MULT_MATCH, "e_char);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char);
|
||||
append_to_match (matches[match_list_index], delimiter, quote_char,
|
||||
strcmp (orig_text, matches[match_list_index]));
|
||||
}
|
||||
|
||||
completion_changed_buffer = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
/* An initial implementation of a menu completion function a la tcsh. The
|
||||
first time (if the last readline command was not rl_menu_complete), we
|
||||
generate the list of matches. This code is very similar to the code in
|
||||
rl_complete_internal -- there should be a way to combine the two. Then,
|
||||
for each item in the list of matches, we insert the match in an undoable
|
||||
fashion, with the appropriate character appended (this happens on the
|
||||
second and subsequent consecutive calls to rl_menu_complete). When we
|
||||
hit the end of the match list, we restore the original unmatched text,
|
||||
ring the bell, and reset the counter to zero. */
|
||||
int
|
||||
rl_old_menu_complete (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
rl_compentry_func_t *our_func;
|
||||
int matching_filenames, found_quote;
|
||||
|
||||
static char *orig_text;
|
||||
static char **matches = (char **)0;
|
||||
static int match_list_index = 0;
|
||||
static int match_list_size = 0;
|
||||
static int orig_start, orig_end;
|
||||
static char quote_char;
|
||||
static int delimiter;
|
||||
|
||||
/* The first time through, we generate the list of matches and set things
|
||||
up to insert them. */
|
||||
if (rl_last_func != rl_menu_complete)
|
||||
{
|
||||
/* Clean up from previous call, if any. */
|
||||
FREE (orig_text);
|
||||
if (matches)
|
||||
_rl_free_match_list (matches);
|
||||
|
||||
match_list_index = match_list_size = 0;
|
||||
matches = (char **)NULL;
|
||||
|
||||
/* Only the completion entry function can change these. */
|
||||
set_completion_defaults ('%');
|
||||
|
||||
our_func = rl_menu_completion_entry_function;
|
||||
if (our_func == 0)
|
||||
our_func = rl_completion_entry_function
|
||||
? rl_completion_entry_function
|
||||
: rl_filename_completion_function;
|
||||
|
||||
/* We now look backwards for the start of a filename/variable word. */
|
||||
orig_end = rl_point;
|
||||
found_quote = delimiter = 0;
|
||||
quote_char = '\0';
|
||||
|
||||
if (rl_point)
|
||||
/* This (possibly) changes rl_point. If it returns a non-zero char,
|
||||
we know we have an open quote. */
|
||||
quote_char = _rl_find_completion_word (&found_quote, &delimiter);
|
||||
|
||||
orig_start = rl_point;
|
||||
rl_point = orig_end;
|
||||
|
||||
orig_text = rl_copy_text (orig_start, orig_end);
|
||||
matches = gen_completion_matches (orig_text, orig_start, orig_end,
|
||||
our_func, found_quote, quote_char);
|
||||
|
||||
/* If we are matching filenames, the attempted completion function will
|
||||
have set rl_filename_completion_desired to a non-zero value. The basic
|
||||
rl_filename_completion_function does this. */
|
||||
matching_filenames = rl_filename_completion_desired;
|
||||
|
||||
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
FREE (orig_text);
|
||||
orig_text = (char *)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (match_list_size = 0; matches[match_list_size]; match_list_size++)
|
||||
;
|
||||
/* matches[0] is lcd if match_list_size > 1, but the circular buffer
|
||||
code below should take care of it. */
|
||||
|
||||
if (match_list_size > 1 && _rl_complete_show_all)
|
||||
display_matches (matches);
|
||||
}
|
||||
|
||||
/* Now we have the list of matches. Replace the text between
|
||||
rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
|
||||
matches[match_list_index], and add any necessary closing char. */
|
||||
|
||||
if (matches == 0 || match_list_size == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
match_list_index += count;
|
||||
if (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
else
|
||||
match_list_index %= match_list_size;
|
||||
|
||||
if (match_list_index == 0 && match_list_size > 1)
|
||||
{
|
||||
rl_ding ();
|
||||
insert_match (orig_text, orig_start, MULT_MATCH, "e_char);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char);
|
||||
append_to_match (matches[match_list_index], delimiter, quote_char,
|
||||
strcmp (orig_text, matches[match_list_index]));
|
||||
}
|
||||
|
||||
completion_changed_buffer = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_menu_complete (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
rl_compentry_func_t *our_func;
|
||||
int matching_filenames, found_quote;
|
||||
|
||||
static char *orig_text;
|
||||
static char **matches = (char **)0;
|
||||
static int match_list_index = 0;
|
||||
static int match_list_size = 0;
|
||||
static int nontrivial_lcd = 0;
|
||||
static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
|
||||
static int orig_start, orig_end;
|
||||
static char quote_char;
|
||||
static int delimiter;
|
||||
|
||||
/* The first time through, we generate the list of matches and set things
|
||||
up to insert them. */
|
||||
if (rl_last_func != rl_menu_complete || full_completion)
|
||||
{
|
||||
/* Clean up from previous call, if any. */
|
||||
FREE (orig_text);
|
||||
if (matches)
|
||||
_rl_free_match_list (matches);
|
||||
|
||||
match_list_index = match_list_size = 0;
|
||||
matches = (char **)NULL;
|
||||
|
||||
full_completion = 0;
|
||||
|
||||
/* Only the completion entry function can change these. */
|
||||
set_completion_defaults ('%');
|
||||
|
||||
our_func = rl_menu_completion_entry_function;
|
||||
if (our_func == 0)
|
||||
our_func = rl_completion_entry_function
|
||||
? rl_completion_entry_function
|
||||
: rl_filename_completion_function;
|
||||
|
||||
/* We now look backwards for the start of a filename/variable word. */
|
||||
orig_end = rl_point;
|
||||
found_quote = delimiter = 0;
|
||||
quote_char = '\0';
|
||||
|
||||
if (rl_point)
|
||||
/* This (possibly) changes rl_point. If it returns a non-zero char,
|
||||
we know we have an open quote. */
|
||||
quote_char = _rl_find_completion_word (&found_quote, &delimiter);
|
||||
|
||||
orig_start = rl_point;
|
||||
rl_point = orig_end;
|
||||
|
||||
orig_text = rl_copy_text (orig_start, orig_end);
|
||||
matches = gen_completion_matches (orig_text, orig_start, orig_end,
|
||||
our_func, found_quote, quote_char);
|
||||
|
||||
nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 0;
|
||||
|
||||
/* If we are matching filenames, the attempted completion function will
|
||||
have set rl_filename_completion_desired to a non-zero value. The basic
|
||||
rl_filename_completion_function does this. */
|
||||
matching_filenames = rl_filename_completion_desired;
|
||||
|
||||
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
FREE (orig_text);
|
||||
orig_text = (char *)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (match_list_size = 0; matches[match_list_size]; match_list_size++)
|
||||
;
|
||||
|
||||
if (match_list_size == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
match_list_index = 0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* matches[0] is lcd if match_list_size > 1, but the circular buffer
|
||||
code below should take care of it. */
|
||||
if (*matches[0])
|
||||
{
|
||||
insert_match (matches[0], orig_start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
orig_end = orig_start + strlen (matches[0]);
|
||||
completion_changed_buffer = STREQ (orig_text, matches[0]) == 0;
|
||||
}
|
||||
|
||||
if (match_list_size > 1 && _rl_complete_show_all)
|
||||
{
|
||||
display_matches (matches);
|
||||
/* If there are so many matches that the user has to be asked
|
||||
whether or not he wants to see the matches, menu completion
|
||||
is unwieldy. */
|
||||
if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else if (match_list_size <= 1)
|
||||
{
|
||||
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have the list of matches. Replace the text between
|
||||
rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
|
||||
matches[match_list_index], and add any necessary closing char. */
|
||||
|
||||
if (matches == 0 || match_list_size == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
completion_changed_buffer = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
match_list_index += count;
|
||||
if (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
else
|
||||
match_list_index %= match_list_size;
|
||||
|
||||
if (match_list_index == 0 && match_list_size > 1)
|
||||
{
|
||||
rl_ding ();
|
||||
insert_match (matches[0], orig_start, MULT_MATCH, "e_char);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char);
|
||||
append_to_match (matches[match_list_index], delimiter, quote_char,
|
||||
strcmp (orig_text, matches[match_list_index]));
|
||||
}
|
||||
|
||||
completion_changed_buffer = 1;
|
||||
return (0);
|
||||
}
|
||||
@@ -605,6 +605,10 @@ extern int rl_catch_sigwinch;
|
||||
filename completer. */
|
||||
extern rl_compentry_func_t *rl_completion_entry_function;
|
||||
|
||||
/* Optional generator for menu completion. Default is
|
||||
rl_completion_entry_function (rl_filename_completion_function). */
|
||||
extern rl_compentry_func_t *rl_menu_completion_entry_function;
|
||||
|
||||
/* If rl_ignore_some_completions_function is non-NULL it is the address
|
||||
of a function to call after all of the possible matches have been
|
||||
generated, but before the actual completion is done to the input line.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Readline.h -- the names of functions callable from within readline. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 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.
|
||||
@@ -233,6 +233,7 @@ extern int rl_vi_append_mode PARAMS((int, int));
|
||||
extern int rl_vi_append_eol PARAMS((int, int));
|
||||
extern int rl_vi_eof_maybe PARAMS((int, int));
|
||||
extern int rl_vi_insertion_mode PARAMS((int, int));
|
||||
extern int rl_vi_insert_mode PARAMS((int, int));
|
||||
extern int rl_vi_movement_mode PARAMS((int, int));
|
||||
extern int rl_vi_arg_digit PARAMS((int, int));
|
||||
extern int rl_vi_change_case PARAMS((int, int));
|
||||
|
||||
@@ -1013,24 +1013,6 @@ timespec: TIME
|
||||
;
|
||||
%%
|
||||
|
||||
/* Possible states for the parser that require it to do special things. */
|
||||
#define PST_CASEPAT 0x0001 /* in a case pattern list */
|
||||
#define PST_ALEXPNEXT 0x0002 /* expand next word for aliases */
|
||||
#define PST_ALLOWOPNBRC 0x0004 /* allow open brace for function def */
|
||||
#define PST_NEEDCLOSBRC 0x0008 /* need close brace */
|
||||
#define PST_DBLPAREN 0x0010 /* double-paren parsing */
|
||||
#define PST_SUBSHELL 0x0020 /* ( ... ) subshell */
|
||||
#define PST_CMDSUBST 0x0040 /* $( ... ) command substitution */
|
||||
#define PST_CASESTMT 0x0080 /* parsing a case statement */
|
||||
#define PST_CONDCMD 0x0100 /* parsing a [[...]] command */
|
||||
#define PST_CONDEXPR 0x0200 /* parsing the guts of [[...]] */
|
||||
#define PST_ARITHFOR 0x0400 /* parsing an arithmetic for command */
|
||||
#define PST_ALEXPAND 0x0800 /* OK to expand aliases - unused */
|
||||
#define PST_CMDTOKEN 0x1000 /* command token OK - unused */
|
||||
#define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */
|
||||
#define PST_ASSIGNOK 0x4000 /* assignment statement ok in this context */
|
||||
#define PST_REGEXP 0x8000 /* parsing an ERE/BRE as a single word */
|
||||
|
||||
/* Initial size to allocate for tokens, and the
|
||||
amount to grow them by. */
|
||||
#define TOKEN_DEFAULT_INITIAL_SIZE 496
|
||||
|
||||
@@ -2616,9 +2616,9 @@ read_token (command)
|
||||
/* If '<' then we could be at "<<" or at "<<-". We have to
|
||||
look ahead one more character. */
|
||||
peek_char = shell_getc (1);
|
||||
if (peek_char == '-')
|
||||
if MBTEST(peek_char == '-')
|
||||
return (LESS_LESS_MINUS);
|
||||
else if (peek_char == '<')
|
||||
else if MBTEST(peek_char == '<')
|
||||
return (LESS_LESS_LESS);
|
||||
else
|
||||
{
|
||||
|
||||
@@ -25,6 +25,25 @@
|
||||
# include "command.h"
|
||||
# include "input.h"
|
||||
|
||||
/* Possible states for the parser that require it to do special things. */
|
||||
#define PST_CASEPAT 0x00001 /* in a case pattern list */
|
||||
#define PST_ALEXPNEXT 0x00002 /* expand next word for aliases */
|
||||
#define PST_ALLOWOPNBRC 0x00004 /* allow open brace for function def */
|
||||
#define PST_NEEDCLOSBRC 0x00008 /* need close brace */
|
||||
#define PST_DBLPAREN 0x00010 /* double-paren parsing */
|
||||
#define PST_SUBSHELL 0x00020 /* ( ... ) subshell */
|
||||
#define PST_CMDSUBST 0x00040 /* $( ... ) command substitution */
|
||||
#define PST_CASESTMT 0x00080 /* parsing a case statement */
|
||||
#define PST_CONDCMD 0x00100 /* parsing a [[...]] command */
|
||||
#define PST_CONDEXPR 0x00200 /* parsing the guts of [[...]] */
|
||||
#define PST_ARITHFOR 0x00400 /* parsing an arithmetic for command */
|
||||
#define PST_ALEXPAND 0x00800 /* OK to expand aliases - unused */
|
||||
#define PST_CMDTOKEN 0x01000 /* command token OK - unused */
|
||||
#define PST_COMPASSIGN 0x02000 /* parsing x=(...) compound assignment */
|
||||
#define PST_ASSIGNOK 0x04000 /* assignment statement ok in this context */
|
||||
#define PST_EOFTOKEN 0x08000 /* yylex checks against shell_eof_token */
|
||||
#define PST_REGEXP 0x10000 /* parsing an ERE/BRE as a single word */
|
||||
|
||||
/* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */
|
||||
struct dstack {
|
||||
/* DELIMITERS is a stack of the nested delimiters that we have
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* parser.h -- Everything you wanted to know about the parser, but were
|
||||
afraid to ask. */
|
||||
|
||||
/* Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#if !defined (_PARSER_H_)
|
||||
# define _PARSER_H_
|
||||
|
||||
# include "command.h"
|
||||
# include "input.h"
|
||||
|
||||
/* Possible states for the parser that require it to do special things. */
|
||||
#define PST_CASEPAT 0x00001 /* in a case pattern list */
|
||||
#define PST_ALEXPNEXT 0x00002 /* expand next word for aliases */
|
||||
#define PST_ALLOWOPNBRC 0x00004 /* allow open brace for function def */
|
||||
#define PST_NEEDCLOSBRC 0x00008 /* need close brace */
|
||||
#define PST_DBLPAREN 0x00010 /* double-paren parsing */
|
||||
#define PST_SUBSHELL 0x00020 /* ( ... ) subshell */
|
||||
#define PST_CMDSUBST 0x00040 /* $( ... ) command substitution */
|
||||
#define PST_CASESTMT 0x00080 /* parsing a case statement */
|
||||
#define PST_CONDCMD 0x00100 /* parsing a [[...]] command */
|
||||
#define PST_CONDEXPR 0x00200 /* parsing the guts of [[...]] */
|
||||
#define PST_ARITHFOR 0x00400 /* parsing an arithmetic for command */
|
||||
#define PST_ALEXPAND 0x00800 /* OK to expand aliases - unused */
|
||||
#define PST_CMDTOKEN 0x01000 /* command token OK - unused */
|
||||
#define PST_COMPASSIGN 0x02000 /* parsing x=(...) compound assignment */
|
||||
#define PST_ASSIGNOK 0x04000 /* assignment statement ok in this context */
|
||||
#define PST_REGEXP 0x08000 /* parsing an ERE/BRE as a single word */
|
||||
|
||||
/* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */
|
||||
struct dstack {
|
||||
/* DELIMITERS is a stack of the nested delimiters that we have
|
||||
encountered so far. */
|
||||
char *delimiters;
|
||||
|
||||
/* Offset into the stack of delimiters. */
|
||||
int delimiter_depth;
|
||||
|
||||
/* How many slots are allocated to DELIMITERS. */
|
||||
int delimiter_space;
|
||||
};
|
||||
|
||||
#endif /* _PARSER_H_ */
|
||||
@@ -53,6 +53,9 @@ int glob_dot_filenames;
|
||||
/* Control whether the extended globbing features are enabled. */
|
||||
int extended_glob = 0;
|
||||
|
||||
/* Control enabling special handling of `**' */
|
||||
int glob_star = 0;
|
||||
|
||||
/* Return nonzero if STRING has any unquoted special globbing chars in it. */
|
||||
int
|
||||
unquoted_glob_pattern_p (string)
|
||||
@@ -137,6 +140,28 @@ ere_char (c)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
glob_char_p (s)
|
||||
const char *s;
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case '*':
|
||||
case '[':
|
||||
case ']':
|
||||
case '?':
|
||||
case '\\':
|
||||
return 1;
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
if (s[1] == '(') /*(*/
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PATHNAME can contain characters prefixed by CTLESC; this indicates
|
||||
that the character is to be quoted. We quote it here in the style
|
||||
that the glob library recognizes. If flags includes QGLOB_CVTNULL,
|
||||
@@ -204,22 +229,8 @@ quote_globbing_chars (string)
|
||||
temp = (char *)xmalloc (slen * 2 + 1);
|
||||
for (t = temp, s = string; *s; )
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case '*':
|
||||
case '[':
|
||||
case ']':
|
||||
case '?':
|
||||
case '\\':
|
||||
*t++ = '\\';
|
||||
break;
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
if (s[1] == '(') /*(*/
|
||||
*t++ = '\\';
|
||||
break;
|
||||
}
|
||||
if (glob_char_p (s))
|
||||
*t++ = '\\';
|
||||
|
||||
/* Copy a single (possibly multibyte) character from s to t,
|
||||
incrementing both. */
|
||||
@@ -287,7 +298,7 @@ shell_glob_filename (pathname)
|
||||
noglob_dot_filenames = glob_dot_filenames == 0;
|
||||
|
||||
temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
|
||||
results = glob_filename (temp, 0);
|
||||
results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
|
||||
free (temp);
|
||||
|
||||
if (results && ((GLOB_FAILED (results)) == 0))
|
||||
|
||||
+485
@@ -0,0 +1,485 @@
|
||||
/* pathexp.c -- The shell interface to the globbing library. */
|
||||
|
||||
/* Copyright (C) 1995-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "pathexp.h"
|
||||
#include "flags.h"
|
||||
|
||||
#include "shmbutil.h"
|
||||
|
||||
#include <glob/strmatch.h>
|
||||
|
||||
static int glob_name_is_acceptable __P((const char *));
|
||||
static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
|
||||
|
||||
#if defined (USE_POSIX_GLOB_LIBRARY)
|
||||
# include <glob.h>
|
||||
typedef int posix_glob_errfunc_t __P((const char *, int));
|
||||
#else
|
||||
# include <glob/glob.h>
|
||||
#endif
|
||||
|
||||
/* Control whether * matches .files in globbing. */
|
||||
int glob_dot_filenames;
|
||||
|
||||
/* Control whether the extended globbing features are enabled. */
|
||||
int extended_glob = 0;
|
||||
|
||||
/* Control enabling special handling of `**' */
|
||||
int glob_star = 0;
|
||||
|
||||
/* Return nonzero if STRING has any unquoted special globbing chars in it. */
|
||||
int
|
||||
unquoted_glob_pattern_p (string)
|
||||
register char *string;
|
||||
{
|
||||
register int c;
|
||||
char *send;
|
||||
int open;
|
||||
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
open = 0;
|
||||
send = string + strlen (string);
|
||||
|
||||
while (c = *string++)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
case '*':
|
||||
return (1);
|
||||
|
||||
case '[':
|
||||
open++;
|
||||
continue;
|
||||
|
||||
case ']':
|
||||
if (open)
|
||||
return (1);
|
||||
continue;
|
||||
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
if (*string == '(') /*)*/
|
||||
return (1);
|
||||
continue;
|
||||
|
||||
case CTLESC:
|
||||
case '\\':
|
||||
if (*string++ == '\0')
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Advance one fewer byte than an entire multibyte character to
|
||||
account for the auto-increment in the loop above. */
|
||||
#ifdef HANDLE_MULTIBYTE
|
||||
string--;
|
||||
ADVANCE_CHAR_P (string, send - string);
|
||||
string++;
|
||||
#else
|
||||
ADVANCE_CHAR_P (string, send - string);
|
||||
#endif
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
|
||||
be quoted to match itself. */
|
||||
static inline int
|
||||
ere_char (c)
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
case '[':
|
||||
case '\\':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '+':
|
||||
case '?':
|
||||
case '{':
|
||||
case '|':
|
||||
case '^':
|
||||
case '$':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
glob_char_p (s)
|
||||
const char *s;
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case '*':
|
||||
case '[':
|
||||
case ']':
|
||||
case '?':
|
||||
case '\\':
|
||||
return 1;
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
if (s[1] == '(') /*(*/
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PATHNAME can contain characters prefixed by CTLESC; this indicates
|
||||
that the character is to be quoted. We quote it here in the style
|
||||
that the glob library recognizes. If flags includes QGLOB_CVTNULL,
|
||||
we change quoted null strings (pathname[0] == CTLNUL) into empty
|
||||
strings (pathname[0] == 0). If this is called after quote removal
|
||||
is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
|
||||
removal has not been done (for example, before attempting to match a
|
||||
pattern while executing a case statement), flags should include
|
||||
QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
|
||||
to match a filename should be performed. */
|
||||
char *
|
||||
quote_string_for_globbing (pathname, qflags)
|
||||
const char *pathname;
|
||||
int qflags;
|
||||
{
|
||||
char *temp;
|
||||
register int i, j;
|
||||
|
||||
temp = (char *)xmalloc (strlen (pathname) + 1);
|
||||
|
||||
if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
|
||||
{
|
||||
temp[0] = '\0';
|
||||
return temp;
|
||||
}
|
||||
|
||||
for (i = j = 0; pathname[i]; i++)
|
||||
{
|
||||
if (pathname[i] == CTLESC)
|
||||
{
|
||||
if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
|
||||
continue;
|
||||
if ((qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
|
||||
continue;
|
||||
temp[j++] = '\\';
|
||||
i++;
|
||||
if (pathname[i] == '\0')
|
||||
break;
|
||||
}
|
||||
else if (pathname[i] == '\\')
|
||||
{
|
||||
temp[j++] = '\\';
|
||||
i++;
|
||||
if (pathname[i] == '\0')
|
||||
break;
|
||||
}
|
||||
temp[j++] = pathname[i];
|
||||
}
|
||||
temp[j] = '\0';
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
||||
char *
|
||||
quote_globbing_chars (string)
|
||||
char *string;
|
||||
{
|
||||
size_t slen;
|
||||
char *temp, *s, *t, *send;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
temp = (char *)xmalloc (slen * 2 + 1);
|
||||
for (t = temp, s = string; *s; )
|
||||
{
|
||||
if (glob_char_p (*s))
|
||||
*t++ = '\\';
|
||||
|
||||
/* Copy a single (possibly multibyte) character from s to t,
|
||||
incrementing both. */
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
*t = '\0';
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* Call the glob library to do globbing on PATHNAME. */
|
||||
char **
|
||||
shell_glob_filename (pathname)
|
||||
const char *pathname;
|
||||
{
|
||||
#if defined (USE_POSIX_GLOB_LIBRARY)
|
||||
register int i;
|
||||
char *temp, **results;
|
||||
glob_t filenames;
|
||||
int glob_flags;
|
||||
|
||||
temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
|
||||
|
||||
filenames.gl_offs = 0;
|
||||
|
||||
# if defined (GLOB_PERIOD)
|
||||
glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
|
||||
# else
|
||||
glob_flags = 0;
|
||||
# endif /* !GLOB_PERIOD */
|
||||
|
||||
glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
|
||||
|
||||
i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
|
||||
|
||||
free (temp);
|
||||
|
||||
if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
|
||||
return ((char **)NULL);
|
||||
else if (i == GLOB_NOMATCH)
|
||||
filenames.gl_pathv = (char **)NULL;
|
||||
else if (i != 0) /* other error codes not in POSIX.2 */
|
||||
filenames.gl_pathv = (char **)NULL;
|
||||
|
||||
results = filenames.gl_pathv;
|
||||
|
||||
if (results && ((GLOB_FAILED (results)) == 0))
|
||||
{
|
||||
if (should_ignore_glob_matches ())
|
||||
ignore_glob_matches (results);
|
||||
if (results && results[0])
|
||||
strvec_sort (results);
|
||||
else
|
||||
{
|
||||
FREE (results);
|
||||
results = (char **)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (results);
|
||||
|
||||
#else /* !USE_POSIX_GLOB_LIBRARY */
|
||||
|
||||
char *temp, **results;
|
||||
|
||||
noglob_dot_filenames = glob_dot_filenames == 0;
|
||||
|
||||
temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
|
||||
results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
|
||||
free (temp);
|
||||
|
||||
if (results && ((GLOB_FAILED (results)) == 0))
|
||||
{
|
||||
if (should_ignore_glob_matches ())
|
||||
ignore_glob_matches (results);
|
||||
if (results && results[0])
|
||||
strvec_sort (results);
|
||||
else
|
||||
{
|
||||
FREE (results);
|
||||
results = (char **)&glob_error_return;
|
||||
}
|
||||
}
|
||||
|
||||
return (results);
|
||||
#endif /* !USE_POSIX_GLOB_LIBRARY */
|
||||
}
|
||||
|
||||
/* Stuff for GLOBIGNORE. */
|
||||
|
||||
static struct ignorevar globignore =
|
||||
{
|
||||
"GLOBIGNORE",
|
||||
(struct ign *)0,
|
||||
0,
|
||||
(char *)0,
|
||||
(sh_iv_item_func_t *)0,
|
||||
};
|
||||
|
||||
/* Set up to ignore some glob matches because the value of GLOBIGNORE
|
||||
has changed. If GLOBIGNORE is being unset, we also need to disable
|
||||
the globbing of filenames beginning with a `.'. */
|
||||
void
|
||||
setup_glob_ignore (name)
|
||||
char *name;
|
||||
{
|
||||
char *v;
|
||||
|
||||
v = get_string_value (name);
|
||||
setup_ignore_patterns (&globignore);
|
||||
|
||||
if (globignore.num_ignores)
|
||||
glob_dot_filenames = 1;
|
||||
else if (v == 0)
|
||||
glob_dot_filenames = 0;
|
||||
}
|
||||
|
||||
int
|
||||
should_ignore_glob_matches ()
|
||||
{
|
||||
return globignore.num_ignores;
|
||||
}
|
||||
|
||||
/* Return 0 if NAME matches a pattern in the globignore.ignores list. */
|
||||
static int
|
||||
glob_name_is_acceptable (name)
|
||||
const char *name;
|
||||
{
|
||||
struct ign *p;
|
||||
int flags;
|
||||
|
||||
/* . and .. are never matched */
|
||||
if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
|
||||
return (0);
|
||||
|
||||
flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
|
||||
for (p = globignore.ignores; p->val; p++)
|
||||
{
|
||||
if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Internal function to test whether filenames in NAMES should be
|
||||
ignored. NAME_FUNC is a pointer to a function to call with each
|
||||
name. It returns non-zero if the name is acceptable to the particular
|
||||
ignore function which called _ignore_names; zero if the name should
|
||||
be removed from NAMES. */
|
||||
|
||||
static void
|
||||
ignore_globbed_names (names, name_func)
|
||||
char **names;
|
||||
sh_ignore_func_t *name_func;
|
||||
{
|
||||
char **newnames;
|
||||
int n, i;
|
||||
|
||||
for (i = 0; names[i]; i++)
|
||||
;
|
||||
newnames = strvec_create (i + 1);
|
||||
|
||||
for (n = i = 0; names[i]; i++)
|
||||
{
|
||||
if ((*name_func) (names[i]))
|
||||
newnames[n++] = names[i];
|
||||
else
|
||||
free (names[i]);
|
||||
}
|
||||
|
||||
newnames[n] = (char *)NULL;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
names[0] = (char *)NULL;
|
||||
free (newnames);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy the acceptable names from NEWNAMES back to NAMES and set the
|
||||
new array end. */
|
||||
for (n = 0; newnames[n]; n++)
|
||||
names[n] = newnames[n];
|
||||
names[n] = (char *)NULL;
|
||||
free (newnames);
|
||||
}
|
||||
|
||||
void
|
||||
ignore_glob_matches (names)
|
||||
char **names;
|
||||
{
|
||||
if (globignore.num_ignores == 0)
|
||||
return;
|
||||
|
||||
ignore_globbed_names (names, glob_name_is_acceptable);
|
||||
}
|
||||
|
||||
void
|
||||
setup_ignore_patterns (ivp)
|
||||
struct ignorevar *ivp;
|
||||
{
|
||||
int numitems, maxitems, ptr;
|
||||
char *colon_bit, *this_ignoreval;
|
||||
struct ign *p;
|
||||
|
||||
this_ignoreval = get_string_value (ivp->varname);
|
||||
|
||||
/* If nothing has changed then just exit now. */
|
||||
if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
|
||||
(!this_ignoreval && !ivp->last_ignoreval))
|
||||
return;
|
||||
|
||||
/* Oops. The ignore variable has changed. Re-parse it. */
|
||||
ivp->num_ignores = 0;
|
||||
|
||||
if (ivp->ignores)
|
||||
{
|
||||
for (p = ivp->ignores; p->val; p++)
|
||||
free(p->val);
|
||||
free (ivp->ignores);
|
||||
ivp->ignores = (struct ign *)NULL;
|
||||
}
|
||||
|
||||
if (ivp->last_ignoreval)
|
||||
{
|
||||
free (ivp->last_ignoreval);
|
||||
ivp->last_ignoreval = (char *)NULL;
|
||||
}
|
||||
|
||||
if (this_ignoreval == 0 || *this_ignoreval == '\0')
|
||||
return;
|
||||
|
||||
ivp->last_ignoreval = savestring (this_ignoreval);
|
||||
|
||||
numitems = maxitems = ptr = 0;
|
||||
|
||||
while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
|
||||
{
|
||||
if (numitems + 1 >= maxitems)
|
||||
{
|
||||
maxitems += 10;
|
||||
ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
|
||||
}
|
||||
ivp->ignores[numitems].val = colon_bit;
|
||||
ivp->ignores[numitems].len = strlen (colon_bit);
|
||||
ivp->ignores[numitems].flags = 0;
|
||||
if (ivp->item_func)
|
||||
(*ivp->item_func) (&ivp->ignores[numitems]);
|
||||
numitems++;
|
||||
}
|
||||
ivp->ignores[numitems].val = (char *)NULL;
|
||||
ivp->num_ignores = numitems;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pathexp.h -- The shell interface to the globbing library. */
|
||||
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -46,6 +46,7 @@ extern char *glob_error_return;
|
||||
|
||||
extern int glob_dot_filenames;
|
||||
extern int extended_glob;
|
||||
extern int glob_star;
|
||||
extern int match_ignore_case; /* doesn't really belong here */
|
||||
|
||||
extern int unquoted_glob_pattern_p __P((char *));
|
||||
@@ -62,6 +63,7 @@ extern int unquoted_glob_pattern_p __P((char *));
|
||||
to match a filename should be performed. */
|
||||
extern char *quote_string_for_globbing __P((const char *, int));
|
||||
|
||||
extern int glob_char_p __P((const char *));
|
||||
extern char *quote_globbing_chars __P((char *));
|
||||
|
||||
/* Call the glob library to do globbing on PATHNAME. */
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* pathexp.h -- The shell interface to the globbing library. */
|
||||
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#if !defined (_PATHEXP_H_)
|
||||
#define _PATHEXP_H_
|
||||
|
||||
#if defined (USE_POSIX_GLOB_LIBRARY)
|
||||
# define GLOB_FAILED(glist) !(glist)
|
||||
#else /* !USE_POSIX_GLOB_LIBRARY */
|
||||
# define GLOB_FAILED(glist) (glist) == (char **)&glob_error_return
|
||||
extern int noglob_dot_filenames;
|
||||
extern char *glob_error_return;
|
||||
#endif /* !USE_POSIX_GLOB_LIBRARY */
|
||||
|
||||
/* Flag values for quote_string_for_globbing */
|
||||
#define QGLOB_CVTNULL 0x01 /* convert QUOTED_NULL strings to '\0' */
|
||||
#define QGLOB_FILENAME 0x02 /* do correct quoting for matching filenames */
|
||||
#define QGLOB_REGEXP 0x04 /* quote an ERE for regcomp/regexec */
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
/* Flags to OR with other flag args to strmatch() to enabled the extended
|
||||
pattern matching. */
|
||||
# define FNMATCH_EXTFLAG (extended_glob ? FNM_EXTMATCH : 0)
|
||||
#else
|
||||
# define FNMATCH_EXTFLAG 0
|
||||
#endif /* !EXTENDED_GLOB */
|
||||
|
||||
#define FNMATCH_IGNCASE (match_ignore_case ? FNM_CASEFOLD : 0)
|
||||
|
||||
extern int glob_dot_filenames;
|
||||
extern int extended_glob;
|
||||
extern int glob_star;
|
||||
extern int match_ignore_case; /* doesn't really belong here */
|
||||
|
||||
extern int unquoted_glob_pattern_p __P((char *));
|
||||
|
||||
/* PATHNAME can contain characters prefixed by CTLESC; this indicates
|
||||
that the character is to be quoted. We quote it here in the style
|
||||
that the glob library recognizes. If flags includes QGLOB_CVTNULL,
|
||||
we change quoted null strings (pathname[0] == CTLNUL) into empty
|
||||
strings (pathname[0] == 0). If this is called after quote removal
|
||||
is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
|
||||
removal has not been done (for example, before attempting to match a
|
||||
pattern while executing a case statement), flags should include
|
||||
QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
|
||||
to match a filename should be performed. */
|
||||
extern char *quote_string_for_globbing __P((const char *, int));
|
||||
|
||||
extern char *quote_globbing_chars __P((char *));
|
||||
|
||||
/* Call the glob library to do globbing on PATHNAME. */
|
||||
extern char **shell_glob_filename __P((const char *));
|
||||
|
||||
/* Filename completion ignore. Used to implement the "fignore" facility of
|
||||
tcsh and GLOBIGNORE (like ksh-93 FIGNORE).
|
||||
|
||||
It is passed a NULL-terminated array of (char *)'s that must be
|
||||
free()'d if they are deleted. The first element (names[0]) is the
|
||||
least-common-denominator string of the matching patterns (i.e.
|
||||
u<TAB> produces names[0] = "und", names[1] = "under.c", names[2] =
|
||||
"undun.c", name[3] = NULL). */
|
||||
|
||||
struct ign {
|
||||
char *val;
|
||||
int len, flags;
|
||||
};
|
||||
|
||||
typedef int sh_iv_item_func_t __P((struct ign *));
|
||||
|
||||
struct ignorevar {
|
||||
char *varname; /* FIGNORE or GLOBIGNORE */
|
||||
struct ign *ignores; /* Store the ignore strings here */
|
||||
int num_ignores; /* How many are there? */
|
||||
char *last_ignoreval; /* Last value of variable - cached for speed */
|
||||
sh_iv_item_func_t *item_func; /* Called when each item is parsed from $`varname' */
|
||||
};
|
||||
|
||||
extern void setup_ignore_patterns __P((struct ignorevar *));
|
||||
|
||||
extern void setup_glob_ignore __P((char *));
|
||||
extern int should_ignore_glob_matches __P((void));
|
||||
extern void ignore_glob_matches __P((char **));
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
+16
-1
@@ -520,4 +520,19 @@ argv[1] = <12>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = </tmp/test/TEST>
|
||||
./new-exp.tests: line 560: ABXD: parameter unset
|
||||
foo is a function
|
||||
foo ()
|
||||
{
|
||||
echo < <(cat x1)
|
||||
}
|
||||
foo ()
|
||||
{
|
||||
echo < <(cat x1)
|
||||
}
|
||||
bar () { echo < <(cat x1) }
|
||||
bar is a function
|
||||
bar ()
|
||||
{
|
||||
echo < <(cat x1)
|
||||
}
|
||||
./new-exp.tests: line 562: ABXD: parameter unset
|
||||
|
||||
@@ -555,6 +555,8 @@ echo ${var##?}
|
||||
|
||||
${THIS_SH} ./new-exp6.sub
|
||||
|
||||
${THIS_SH} ./new-exp7.sub
|
||||
|
||||
# this must be last!
|
||||
expect $0: 'ABXD: parameter unset'
|
||||
recho ${ABXD:?"parameter unset"}
|
||||
|
||||
@@ -0,0 +1,560 @@
|
||||
# must do this because posix mode causes process substitution to be disabled
|
||||
# and flagged as a syntax error, which causes the shell to exit
|
||||
set +o posix
|
||||
|
||||
expect()
|
||||
{
|
||||
echo expect "$@"
|
||||
}
|
||||
|
||||
HOME=/usr/homes/chet # to make the check against new-exp.right work
|
||||
expect '<foo bar>'
|
||||
recho "${undef-"foo bar"}" # should be foo bar
|
||||
expect '<foo>'
|
||||
recho "${und="foo"}" # should be foo
|
||||
|
||||
expect "<$HOME>"
|
||||
recho ${HOME-"}"}
|
||||
expect "<$HOME>"
|
||||
recho "${HOME-'}'}"
|
||||
expect "<$HOME>"
|
||||
recho "${HOME-"}"}"
|
||||
|
||||
expect $0: 'HOME: }: syntax error: operand expected (error token is "}")'
|
||||
recho "${HOME:`echo }`}" # should be a math error -- bad substring substitution
|
||||
|
||||
expect unset
|
||||
_ENV=oops
|
||||
x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]}
|
||||
echo ${x:-unset}
|
||||
|
||||
expect "<$HOME>"
|
||||
recho ${HOME}
|
||||
expect "<$HOME>"
|
||||
recho ${HOME:-`echo }`}
|
||||
expect "<$HOME>"
|
||||
recho ${HOME:-`echo "}"`}
|
||||
expect "<$HOME>"
|
||||
recho "${HOME:-`echo "}"`}"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "${HOME}")"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "$(echo ${HOME})")"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "$(echo "${HOME}")")"
|
||||
|
||||
P=*@*
|
||||
expect '<*@>'
|
||||
recho "${P%"*"}" #
|
||||
expect '<*@>'
|
||||
recho "${P%'*'}" #
|
||||
expect '<@*>'
|
||||
recho "${P#\*}" # should be @*
|
||||
|
||||
expect '<)>'
|
||||
recho "$(echo ")")" # should be )
|
||||
expect '<")">'
|
||||
recho "$(echo "\")\"")" # should be ")"
|
||||
|
||||
foo='abcd '
|
||||
expect '<-abcd> <->'
|
||||
recho -${foo}- # should be -abcd -
|
||||
expect '<-abcd> <->'
|
||||
recho -${foo% *}- # should be -abcd -
|
||||
expect '<-abcd->'
|
||||
recho -${foo%% *}- # should be -abcd-
|
||||
|
||||
foo=bar
|
||||
expect '<bar foo>'
|
||||
echo -n $foo' ' ; echo foo
|
||||
|
||||
expect '<bar foo>'
|
||||
echo -n $foo" " ; echo foo
|
||||
|
||||
expect '<bar foo>'
|
||||
echo -n "$foo " ; echo foo
|
||||
|
||||
expect '<barfoo>'
|
||||
echo -e "$foo\c " ; echo foo
|
||||
|
||||
expect '<barfoo>'
|
||||
echo -e $foo"\c " ; echo foo
|
||||
|
||||
# make sure backslashes are preserved in front of characters that are not
|
||||
# valid backslash escapes
|
||||
expect '<\x>'
|
||||
echo -e '\x'
|
||||
|
||||
# substring tests
|
||||
z=abcdefghijklmnop
|
||||
expect '<abcd>'
|
||||
recho ${z:0:4}
|
||||
|
||||
expect '<efg> <nop>'
|
||||
recho ${z:4:3} ${z:${#z}-3:3}
|
||||
|
||||
expect '<efg> <nop>'
|
||||
recho ${z:4:3} ${z: -3:3}
|
||||
|
||||
expect '<hijklmnop>'
|
||||
recho ${z:7:30}
|
||||
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${z:0:100}
|
||||
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${z:0:${#z}}
|
||||
|
||||
set 'ab cd' 'ef' 'gh ij' 'kl mn' 'op'
|
||||
expect '<ab cd> <ef>'
|
||||
recho "${@:1:2}"
|
||||
|
||||
expect '<gh ij> <kl mn>'
|
||||
recho "${@:3:2}"
|
||||
|
||||
expect '<gh ij> <kl mn> <op>'
|
||||
recho "${@:3:4}"
|
||||
|
||||
expect '<ab cd> <ef> <gh ij> <kl mn> <op>'
|
||||
recho "${@:1:$#}"
|
||||
|
||||
# code to ad-hoc parse arithmetic expressions in substring expansions was
|
||||
# broken until post-2.04
|
||||
base=/home/chet/foo//bar
|
||||
string1=$base/abcabcabc
|
||||
x=1 j=4
|
||||
|
||||
expect '</home/chet/foo//bar/abcabcabc>'
|
||||
recho ${string1:0}
|
||||
|
||||
expect '<home/chet/foo//bar/abcabcabc>'
|
||||
recho ${string1:1}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:(j?1:0):j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:j?1:0:j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:(j?(x?1:0):0):j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:j?(x?1:0):0:j}
|
||||
|
||||
unset base string1 x j
|
||||
|
||||
# indirect variable references
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${!9:-$z}
|
||||
|
||||
ef=4
|
||||
expect '<4>'
|
||||
recho ${!2}
|
||||
|
||||
expect '<op>'
|
||||
recho ${!#}
|
||||
|
||||
set a b c d e
|
||||
a=
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${a:-$z}
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${!1:-$z}
|
||||
|
||||
expect nothing
|
||||
recho ${a-$z}
|
||||
expect nothing
|
||||
recho ${!1-$z}
|
||||
|
||||
set -u
|
||||
expect $0: ABX: unbound variable
|
||||
( recho ${ABX} )
|
||||
set +u
|
||||
|
||||
expect $0: '$6: cannot assign in this way'
|
||||
recho ${6="arg6"}
|
||||
|
||||
v=abcde
|
||||
|
||||
# sed-like variable substitution
|
||||
expect '<xxcde>'
|
||||
recho ${v/a[a-z]/xx}
|
||||
expect '<axxde>'
|
||||
recho ${v/a??/axx}
|
||||
expect '<abxyz>'
|
||||
recho ${v/c??/xyz}
|
||||
expect '<abbcde>'
|
||||
recho ${v/#a/ab}
|
||||
expect '<abcde>'
|
||||
recho ${v/#d/ab}
|
||||
expect '<abcabe>'
|
||||
recho ${v/d/ab}
|
||||
expect '<abcdlast>'
|
||||
recho ${v/%?/last}
|
||||
expect '<abcde>'
|
||||
recho ${v/%x/last}
|
||||
|
||||
av=(abcd efgh ijkl mnop qrst uvwx)
|
||||
|
||||
expect '<xxcd>'
|
||||
recho ${av/??/xx}
|
||||
expect '<abxx>'
|
||||
recho ${av/%??/xx}
|
||||
expect '<xxgh>'
|
||||
recho ${av[1]/??/xx}
|
||||
expect '<efgh>'
|
||||
recho ${av[1]/%ab/xx}
|
||||
expect '<xxfgh>'
|
||||
recho ${av[1]/#?/xx}
|
||||
expect '<zagh>'
|
||||
recho ${av[1]/??/za}
|
||||
expect '<zaza>'
|
||||
recho ${av[1]//??/za}
|
||||
expect '<zagh>'
|
||||
recho ${av[1]/#??/za}
|
||||
expect '<efza>'
|
||||
recho ${av[1]/%??/za}
|
||||
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/*/yyy}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/#*/yyy}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/%*/yyy}
|
||||
expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>'
|
||||
recho ${av[@]/a*/yyy}
|
||||
expect '<abxx> <efxx> <ijxx> <mnxx> <qrxx> <uvxx>'
|
||||
recho ${av[@]/%??/xx}
|
||||
|
||||
set abcd efgh ijkl mnop qrst uvwx
|
||||
|
||||
expect '<xxcd>'
|
||||
recho ${1/??/xx}
|
||||
expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>'
|
||||
recho ${@/??/xx}
|
||||
expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>'
|
||||
recho ${@/%??/xx}
|
||||
expect '<zaza>'
|
||||
recho ${3//??/za}
|
||||
expect '<efza>'
|
||||
recho ${3/%??/za}
|
||||
expect '<zaza> <zaza> <zaza> <zaza> <zaza> <zaza>'
|
||||
recho ${@//??/za}
|
||||
expect '<zacd> <zagh> <zakl> <zaop> <zast> <zawx>'
|
||||
recho ${@/#??/za}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${@//*/yyy}
|
||||
expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>'
|
||||
recho ${@//a*/yyy}
|
||||
expect '<abcd> <efgh> <ijkl> <mnop> <qrst> <uvwyyy>'
|
||||
recho ${@/%x*/yyy}
|
||||
|
||||
expect a newline
|
||||
echo $abmcde
|
||||
|
||||
# sneaky way to replace a newline in a variable value with something else
|
||||
AVAR=$'This\nstring\nhas\nmultiple\nlines.'
|
||||
echo "${AVAR}"
|
||||
|
||||
eval BVAR=\"\${AVAR//$'\n'/-}\"
|
||||
echo "$BVAR"
|
||||
|
||||
unset AVAR BVAR
|
||||
|
||||
# run process substitution tests in a subshell so that syntax errors
|
||||
# caused by a shell not implementing process substitution (e.g., one
|
||||
# built on a NeXT) will not cause the whole test to exit prematurely
|
||||
${THIS_SH} ./new-exp1.sub
|
||||
|
||||
# run the tests of $(<filename) in a subshell to avoid cluttering up
|
||||
# this script
|
||||
${THIS_SH} ./new-exp2.sub
|
||||
|
||||
expect '<6>'
|
||||
recho ${#:-foo}
|
||||
expect $0: '${#:}: bad substitution'
|
||||
echo ${#:}
|
||||
|
||||
expect "<'>"
|
||||
recho "'"
|
||||
expect '<">'
|
||||
recho '"'
|
||||
expect '<"hello">'
|
||||
recho "\"hello\""
|
||||
|
||||
shift $#
|
||||
unset foo
|
||||
z=abcdef
|
||||
z1='abc def'
|
||||
|
||||
expect '<>'
|
||||
recho ${foo:-""}
|
||||
expect nothing
|
||||
recho ${foo:-"$@"}
|
||||
expect '<>'
|
||||
recho "${foo:-$@}"
|
||||
|
||||
# unset var
|
||||
expect '<>'
|
||||
recho ${foo:-"$zbcd"}
|
||||
expect nothing
|
||||
recho ${foo:-$zbcd}
|
||||
|
||||
# set var
|
||||
expect '<abcdef>'
|
||||
recho ${foo:-"$z"}
|
||||
expect '<abc def>'
|
||||
recho ${foo:-"$z1"}
|
||||
|
||||
expect '<abcdef>'
|
||||
recho ${foo:-$z}
|
||||
expect '<abc> <def>'
|
||||
recho ${foo:-$z1}
|
||||
|
||||
expect '<abcdef>'
|
||||
recho "${foo:-$z}"
|
||||
expect '<abc def>'
|
||||
recho "${foo:-$z1}"
|
||||
|
||||
expect '<abcdef>'
|
||||
recho "${foo:-"$z"}"
|
||||
# this disagrees with sh and ksh, but I think it is right according
|
||||
# to posix.2.
|
||||
expect '<abc def>'
|
||||
recho "${foo:-"$z1"}"
|
||||
|
||||
set ab cd ef gh
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho ${foo:-"$@"}
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho "${foo:-$@}"
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho "${foo:-"$@"}"
|
||||
|
||||
shift $#
|
||||
expect nothing
|
||||
recho $xxx"$@"
|
||||
expect nothing
|
||||
recho ${foo:-$xxx"$@"}
|
||||
expect '<>'
|
||||
recho "${foo:-$xxx$@}"
|
||||
expect '<>'
|
||||
recho "${foo:-$xxx"$@"}"
|
||||
|
||||
expect nothing
|
||||
recho $xxx"$@"
|
||||
expect nothing
|
||||
recho "$xxx$@"
|
||||
expect nothing
|
||||
recho "$@"$xxx
|
||||
|
||||
expect '<>'
|
||||
recho $xxx""
|
||||
expect '<>'
|
||||
recho $xxx''
|
||||
expect '<>'
|
||||
recho ''$xxx
|
||||
expect '<>'
|
||||
recho ""$xxx
|
||||
|
||||
AB='abcdefghijklmnopqrstuvwxyz'
|
||||
|
||||
recho ${AB:7:15}
|
||||
recho ${AB:15:7}
|
||||
|
||||
recho ${AB:20}
|
||||
|
||||
recho ${AB:0}
|
||||
recho ${AB:0:20}
|
||||
|
||||
recho ${AB:10:7}
|
||||
recho ${AB:10:3+4}
|
||||
recho ${AB:20/2:3+4}
|
||||
|
||||
set 1 2 3 4 5 6
|
||||
recho \""${*:2:2}"\"
|
||||
|
||||
IFS=:
|
||||
recho \""${*:2:2}"\"
|
||||
|
||||
IFS=$' \t\n'
|
||||
|
||||
z=123456
|
||||
|
||||
recho \""${z:2:2}"\"
|
||||
recho \""${z:2}"\"
|
||||
recho \""${z:2:4}"\"
|
||||
recho \""${z:2:6}"\"
|
||||
|
||||
set $'\1' $'\2' $'\177'
|
||||
|
||||
recho $*
|
||||
recho $@
|
||||
|
||||
recho ${*}
|
||||
recho ${@}
|
||||
|
||||
xx=one/two/two
|
||||
recho ${xx%/*}
|
||||
recho ${xx/\/two}
|
||||
|
||||
yy=oneonetwo
|
||||
recho ${yy//one}
|
||||
recho ${yy/\/one}
|
||||
|
||||
xx=oneonetwo
|
||||
|
||||
recho ${xx/one}
|
||||
recho ${xx//one}
|
||||
recho ${xx/\/one}
|
||||
|
||||
# out-of-range substrings
|
||||
var=abc
|
||||
c=${var:3}
|
||||
expect nothing
|
||||
recho $c
|
||||
c=${var:4}
|
||||
expect nothing
|
||||
recho $c
|
||||
expect '<./new-exp.tests: -2: substring expression < 0>'
|
||||
c=${var:0:-2}
|
||||
|
||||
var=abcdefghi
|
||||
c=${var:3:12}
|
||||
recho $c
|
||||
c=${var:4:20}
|
||||
recho $c
|
||||
|
||||
# make sure null patterns work
|
||||
xxx=endocrine
|
||||
yyy=n
|
||||
unset zzz
|
||||
|
||||
recho ${xxx/$yyy/*}
|
||||
recho ${xxx//$yyy/*}
|
||||
|
||||
recho ${xxx/$zzz/*}
|
||||
recho ${xxx//$zzz/*}
|
||||
|
||||
recho ${xxx//%${zzz}/}
|
||||
recho ${xxx//%${zzz}}
|
||||
recho ${xxx//#${zzz}/}
|
||||
recho ${xxx//#${zzz}}
|
||||
|
||||
# another case that caused a core dump in bash-2.0
|
||||
XPATH=/usr/bin:/bin:/usr/local/bin:/usr/gnu/bin::/usr/bin/X11:/sbin:/usr/sbin
|
||||
|
||||
recho ${XPATH//:/ }
|
||||
|
||||
xx=(ar as at au av aw ax ay az)
|
||||
|
||||
recho ${xx[@]/a/}
|
||||
recho ${xx[@]//a/}
|
||||
|
||||
recho ${xx[*]/a/}
|
||||
recho ${xx[*]//a/}
|
||||
|
||||
recho ${xx[@]%?}
|
||||
recho ${xx[*]%?}
|
||||
|
||||
recho ${xx[@]#?}
|
||||
recho ${xx[*]#?}
|
||||
|
||||
set -- ar as at au av aw ax ay az
|
||||
|
||||
recho ${@/a/}
|
||||
recho ${@//a/}
|
||||
|
||||
recho ${*/a/}
|
||||
recho ${*//a/}
|
||||
|
||||
recho ${@%?}
|
||||
recho ${*%?}
|
||||
|
||||
recho ${@#?}
|
||||
recho ${*#?}
|
||||
|
||||
shift $#
|
||||
set -u
|
||||
( recho $9 ; echo after 1)
|
||||
( recho ${9} ; echo after 2)
|
||||
( recho $UNSET ; echo after 3)
|
||||
( recho ${UNSET} ; echo after 4)
|
||||
( recho "$UNSET" ; echo after 5)
|
||||
( recho "${UNSET}" ; echo after 6)
|
||||
( recho "${#UNSET}" ; echo after 7)
|
||||
set +u
|
||||
|
||||
RECEIVED="12345"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED="12345#"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED="#"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED=""
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
|
||||
# tests of new prefix expansion ${!prefix*}
|
||||
${THIS_SH} ./new-exp3.sub
|
||||
|
||||
# bug with indirect expansion through bash-2.05b
|
||||
${THIS_SH} ./new-exp4.sub
|
||||
|
||||
# these caused errors and core dumps in versions before bash-2.04
|
||||
c=""
|
||||
echo ${c//${$(($#-1))}/x/}
|
||||
|
||||
set a b c d e f g
|
||||
recho "$@"
|
||||
|
||||
set -- ${@:1:$(($# - 2))}
|
||||
recho "$@"
|
||||
|
||||
set a b
|
||||
recho ${@:1:$(($# - 2))}
|
||||
|
||||
recho ${@:1:0}
|
||||
recho ${@:1:1}
|
||||
recho ${@:1:2}
|
||||
|
||||
recho "${*:1:0}"
|
||||
|
||||
# this is an error -- negative expression
|
||||
set a
|
||||
recho ${@:1:$(($# - 2))}
|
||||
|
||||
XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
|
||||
set $( IFS=: ; echo $XPATH )
|
||||
|
||||
recho ${@##*/}
|
||||
recho ${@%%[!/]*}
|
||||
|
||||
recho ${@#/*}
|
||||
recho ${@%*/}
|
||||
|
||||
set /full/path/to/x16 /another/full/path
|
||||
|
||||
recho ${1%/*}
|
||||
recho ${1%%[!/]*}
|
||||
recho ${1#*/}
|
||||
recho ${1##*/}
|
||||
|
||||
${THIS_SH} ./new-exp5.sub
|
||||
|
||||
unset var
|
||||
var=blah
|
||||
|
||||
# these had better agree
|
||||
echo ${var[@]:3}
|
||||
echo ${var:3}
|
||||
echo ${var[@]/#/--}
|
||||
echo ${var/#/--}
|
||||
echo ${var[@]##?}
|
||||
echo ${var##?}
|
||||
|
||||
${THIS_SH} ./new-exp6.sub
|
||||
|
||||
# this must be last!
|
||||
expect $0: 'ABXD: parameter unset'
|
||||
recho ${ABXD:?"parameter unset"}
|
||||
@@ -0,0 +1,13 @@
|
||||
foo()
|
||||
{
|
||||
echo < <(cat x1)
|
||||
}
|
||||
|
||||
type foo
|
||||
|
||||
declare -f foo
|
||||
|
||||
echo $(declare -f foo | sed 's:foo:bar:')
|
||||
eval "$(declare -f foo | sed 's:foo:bar:')"
|
||||
|
||||
type bar
|
||||
@@ -9,6 +9,7 @@ shopt -u checkjobs
|
||||
shopt -u checkwinsize
|
||||
shopt -s cmdhist
|
||||
shopt -u compat31
|
||||
shopt -u dirspell
|
||||
shopt -u dotglob
|
||||
shopt -u execfail
|
||||
shopt -s expand_aliases
|
||||
@@ -17,6 +18,7 @@ shopt -u extglob
|
||||
shopt -s extquote
|
||||
shopt -u failglob
|
||||
shopt -s force_fignore
|
||||
shopt -u globstar
|
||||
shopt -u gnu_errfmt
|
||||
shopt -u histappend
|
||||
shopt -u histreedit
|
||||
@@ -59,11 +61,13 @@ shopt -u checkhash
|
||||
shopt -u checkjobs
|
||||
shopt -u checkwinsize
|
||||
shopt -u compat31
|
||||
shopt -u dirspell
|
||||
shopt -u dotglob
|
||||
shopt -u execfail
|
||||
shopt -u extdebug
|
||||
shopt -u extglob
|
||||
shopt -u failglob
|
||||
shopt -u globstar
|
||||
shopt -u gnu_errfmt
|
||||
shopt -u histappend
|
||||
shopt -u histreedit
|
||||
@@ -86,11 +90,13 @@ checkhash off
|
||||
checkjobs off
|
||||
checkwinsize off
|
||||
compat31 off
|
||||
dirspell off
|
||||
dotglob off
|
||||
execfail off
|
||||
extdebug off
|
||||
extglob off
|
||||
failglob off
|
||||
globstar off
|
||||
gnu_errfmt off
|
||||
histappend off
|
||||
histreedit off
|
||||
|
||||
@@ -3518,6 +3518,8 @@ push_func_var (data)
|
||||
shell_variables->flags |= VC_HASTMPVAR;
|
||||
v->attributes |= var->attributes;
|
||||
}
|
||||
else
|
||||
stupidly_hack_special_variables (var->name); /* XXX */
|
||||
|
||||
dispose_variable (var);
|
||||
}
|
||||
@@ -3604,6 +3606,8 @@ push_exported_var (data)
|
||||
var->attributes &= ~att_propagate;
|
||||
v->attributes |= var->attributes;
|
||||
}
|
||||
else
|
||||
stupidly_hack_special_variables (var->name); /* XXX */
|
||||
|
||||
dispose_variable (var);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user