commit bash-20080501 snapshot

This commit is contained in:
Chet Ramey
2011-12-07 09:23:10 -05:00
parent 245a493cfb
commit 4ac1ff9885
71 changed files with 5030 additions and 430 deletions
+122
View File
@@ -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
View File
@@ -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
+3
View File
@@ -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
+46 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
+36 -1
View File
@@ -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.
+37 -2
View File
@@ -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++] = '[';
+2 -1
View File
@@ -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 *));
+2
View File
@@ -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
View File
@@ -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;
}
+10
View File
@@ -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 *
+378
View File
@@ -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 */
+370
View File
@@ -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 */
+57
View File
@@ -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_ */
+54
View File
@@ -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_ */
+2 -1
View File
@@ -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
View File
@@ -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,
+3 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 },
+3
View File
@@ -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
+3
View File
@@ -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
Vendored
+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+19
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+102 -1
View File
@@ -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
View File
@@ -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 */
+5 -1
View File
@@ -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
View File
@@ -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));
+2 -2
View File
@@ -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
View File
@@ -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 *));
+18 -25
View File
@@ -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 */
+18 -26
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -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
View File
@@ -317,7 +317,7 @@ rl_macro_bind (keyseq, macro, map)
if (rl_translate_keyseq (macro, macro_keys, &macro_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
+1 -1
View File
@@ -1709,7 +1709,7 @@ sv_histsize (value)
{
nval = atoi (value);
if (nval < 0)
nval = 0;
return 1;
}
stifle_history (nval);
return 0;
+173 -6
View File
@@ -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, &quote_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, &quote_char);
}
else
{
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_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
View File
@@ -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, &quote_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, &quote_char);
}
else
{
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
append_to_match (matches[match_list_index], delimiter, quote_char,
strcmp (orig_text, matches[match_list_index]));
}
completion_changed_buffer = 1;
return (0);
}
+276
View File
@@ -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, &quote_char);
}
else
{
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_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, &quote_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, &quote_char);
}
else
{
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
append_to_match (matches[match_list_index], delimiter, quote_char,
strcmp (orig_text, matches[match_list_index]));
}
completion_changed_buffer = 1;
return (0);
}
+4
View File
@@ -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.
+2 -1
View File
@@ -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));
-18
View File
@@ -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
+2 -2
View File
@@ -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
{
+19
View File
@@ -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
+59
View File
@@ -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_ */
+28 -17
View File
@@ -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
View File
@@ -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;
}
+3 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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"}
+560
View File
@@ -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"}
+13
View File
@@ -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
+6
View File
@@ -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
+4
View File
@@ -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);
}