diff options
-rw-r--r-- | CWRU/CWRU.chlog | 20 | ||||
-rw-r--r-- | CWRU/CWRU.chlog~ | 20 | ||||
-rw-r--r-- | autom4te.cache/output.0 | 5 | ||||
-rw-r--r-- | autom4te.cache/requests | 150 | ||||
-rw-r--r-- | autom4te.cache/traces.0 | 4 | ||||
-rw-r--r-- | builtins/pushd.def | 6 | ||||
-rw-r--r-- | config.h.in | 3 | ||||
-rw-r--r-- | config.h.in~ | 7 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | configure.in~ | 4 | ||||
-rw-r--r-- | doc/bash.1 | 8 | ||||
-rw-r--r-- | doc/bash.1~ | 20 | ||||
-rw-r--r-- | doc/bashref.texi | 4 | ||||
-rw-r--r-- | doc/bashref.texi~ | 17 | ||||
-rw-r--r-- | doc/version.texi | 5 | ||||
-rw-r--r-- | doc/version.texi~ | 4 | ||||
-rw-r--r-- | examples/loadables/Makefile.in | 17 | ||||
-rw-r--r-- | examples/loadables/sprintf.c | 2 | ||||
-rw-r--r-- | lib/intl/dcigettext.c | 4 | ||||
-rw-r--r-- | lib/intl/dcigettext.c~ | 1238 | ||||
-rw-r--r-- | lib/malloc/trace.c | 4 | ||||
-rw-r--r-- | lib/malloc/trace.c~ | 122 | ||||
-rw-r--r-- | lib/readline/display.c | 3 | ||||
-rw-r--r-- | lib/readline/display.c~ | 11 | ||||
-rw-r--r-- | lib/sh/getenv.c | 4 | ||||
-rwxr-xr-x | tests/RUN-ONE-TEST | 2 |
27 files changed, 1583 insertions, 110 deletions
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 7c235d22..9c5bfbe0 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -10551,3 +10551,23 @@ builtins/declare.def builtins/setattr.def - add support for `+=' assignment for rest of `assignment builtins': export, readonly + + 11/12 + ----- +lib/readline/display.c + - make sure prompt_physical_chars and prompt_invis_chars_first_line + are reset to 0 if the prompt string passed to rl_expand_prompt is + NULL or empty + + 11/14 + ----- +{configure,config.h}.in + - check for `raise', define HAVE_RAISE if available + +lib/intl/dcigettext.c + - make sure `raise' is defined if HAVE_RAISE is not before + eval-plurah.h is included + +lib/malloc/trace.c + - put extern declaration for imalloc_fopen inside the MALLOC_TRACE + #ifdef diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index d65cdd00..7c33ff46 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -10547,3 +10547,23 @@ builtins/declare.def before the assignment is performed, which has implications for things like `-i' -- if -i is supplied, arithmetic evaluation and increment will be performed + +builtins/setattr.def + - add support for `+=' assignment for rest of `assignment builtins': + export, readonly + + 11/12 + ----- +lib/readline/display.c + - make sure prompt_physical_chars and prompt_invis_chars_first_line + are reset to 0 if the prompt string passed to rl_expand_prompt is + NULL or empty + + 11/14 + ----- +{configure,config.h}.in + - check for `raise', define HAVE_RAISE if available + +lib/intl/dcigettext.c + - make sure `raise' is defined if HAVE_RAISE is not before + eval-plurah.h is included diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0 index 798e4cc0..2548feec 100644 --- a/autom4te.cache/output.0 +++ b/autom4te.cache/output.0 @@ -1,5 +1,5 @@ @%:@! /bin/sh -@%:@ From configure.in for Bash 3.0, version 3.170, from autoconf version AC_ACVERSION. +@%:@ From configure.in for Bash 3.0, version 3.171, from autoconf version AC_ACVERSION. @%:@ Guess values for system-dependent variables and create Makefiles. @%:@ Generated by GNU Autoconf 2.57 for bash 3.1-devel. @%:@ @@ -11351,9 +11351,10 @@ done + for ac_func in bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \ setlinebuf setvbuf setlocale strchr tcgetattr uname \ - ulimit tzset siginterrupt memmove ttyname times \ + ulimit tzset siginterrupt memmove ttyname times raise \ getaddrinfo gethostbyname getservbyname getservent inet_aton \ vsnprintf snprintf vasprintf asprintf fnmatch regcomp regexec do diff --git a/autom4te.cache/requests b/autom4te.cache/requests index f04b8a0d..b2ba2eeb 100644 --- a/autom4te.cache/requests +++ b/autom4te.cache/requests @@ -15,96 +15,96 @@ 'configure.in' ], { - 'AM_INIT_AUTOMAKE' => 1, - 'AC_DECL_SYS_SIGLIST' => 1, - 'AC_STRUCT_TIMEZONE' => 1, - 'AC_FUNC_STRNLEN' => 1, + 'AM_GNU_GETTEXT' => 1, + 'AC_FUNC_CHOWN' => 1, + 'AC_FUNC_GETGROUPS' => 1, + 'AM_MAINTAINER_MODE' => 1, + 'AC_FUNC_MALLOC' => 1, + 'AC_CANONICAL_HOST' => 1, + 'AM_CONDITIONAL' => 1, + 'AC_FUNC_LSTAT' => 1, + 'AC_C_CONST' => 1, 'AC_FUNC_STRFTIME' => 1, + 'AC_CONFIG_AUX_DIR' => 1, + 'AC_FUNC_GETMNTENT' => 1, + 'AC_PROG_LN_S' => 1, + 'AC_LIBSOURCE' => 1, + 'AC_PROG_CC' => 1, + 'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1, + 'AC_FUNC_MEMCMP' => 1, + 'AC_FUNC_ALLOCA' => 1, + 'm4_pattern_forbid' => 1, + 'AC_PROG_RANLIB' => 1, + 'AC_STRUCT_ST_BLOCKS' => 1, + 'AC_FUNC_WAIT3' => 1, + 'AC_C_VOLATILE' => 1, 'AC_FUNC_GETPGRP' => 1, 'AC_CANONICAL_SYSTEM' => 1, - 'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1, - 'AC_CONFIG_FILES' => 1, - 'AC_PROG_CPP' => 1, + 'AC_HEADER_MAJOR' => 1, + 'AC_PROG_LIBTOOL' => 1, + 'AC_TYPE_SIZE_T' => 1, + 'AC_TYPE_PID_T' => 1, + 'm4_pattern_allow' => 1, + 'AC_PROG_CXX' => 1, + 'AM_AUTOMAKE_VERSION' => 1, + 'AC_TYPE_SIGNAL' => 1, + 'AC_CHECK_HEADERS' => 1, + 'AC_FUNC_OBSTACK' => 1, + 'AC_SUBST' => 1, + 'AC_FUNC_UTIME_NULL' => 1, + 'AC_FUNC_MMAP' => 1, + 'AC_DECL_SYS_SIGLIST' => 1, + 'AC_PROG_LEX' => 1, + 'AC_PROG_AWK' => 1, + 'AC_REPLACE_FNMATCH' => 1, + 'AM_PROG_CC_C_O' => 1, 'AC_CHECK_TYPES' => 1, - 'AC_LIBSOURCE' => 1, - 'AC_STRUCT_TM' => 1, - 'AC_C_CONST' => 1, - 'AC_FUNC_FORK' => 1, + 'AC_FUNC_GETLOADAVG' => 1, + 'AC_PATH_X' => 1, + 'include' => 1, + 'AC_PROG_GCC_TRADITIONAL' => 1, + 'AC_FUNC_REALLOC' => 1, 'AC_HEADER_SYS_WAIT' => 1, - 'AM_GNU_GETTEXT' => 1, - 'AC_INIT' => 1, - 'AC_FUNC_UTIME_NULL' => 1, - 'AM_AUTOMAKE_VERSION' => 1, - 'AC_HEADER_STDC' => 1, - 'AC_PROG_CXX' => 1, + 'm4_include' => 1, + 'AC_HEADER_TIME' => 1, + 'AC_CONFIG_SUBDIRS' => 1, 'AC_FUNC_STRERROR_R' => 1, - 'AC_PROG_YACC' => 1, + 'AC_INIT' => 1, 'AC_FUNC_STRCOLL' => 1, - 'AC_FUNC_VPRINTF' => 1, - 'AC_PROG_RANLIB' => 1, - 'AC_PROG_LEX' => 1, - 'AM_PROG_CC_C_O' => 1, + 'AC_CHECK_MEMBERS' => 1, 'AC_CHECK_FUNCS' => 1, - 'AC_SUBST' => 1, - 'AC_FUNC_MBRTOWC' => 1, - 'AC_FUNC_GETGROUPS' => 1, - 'AC_PROG_LN_S' => 1, - 'AC_FUNC_CHOWN' => 1, - 'AC_FUNC_GETMNTENT' => 1, - 'AC_PROG_MAKE_SET' => 1, - 'AC_TYPE_MODE_T' => 1, 'AH_OUTPUT' => 1, - 'AC_C_VOLATILE' => 1, - 'AC_FUNC_ALLOCA' => 1, - 'AC_TYPE_UID_T' => 1, - 'AM_MAINTAINER_MODE' => 1, - 'AC_FUNC_SETVBUF_REVERSED' => 1, - 'AC_STRUCT_ST_BLOCKS' => 1, - 'm4_include' => 1, - 'AC_CONFIG_AUX_DIR' => 1, - 'AC_FUNC_FSEEKO' => 1, - 'AC_FUNC_OBSTACK' => 1, - 'AC_FUNC_MEMCMP' => 1, - 'AC_FUNC_MKTIME' => 1, - 'AC_FUNC_STRTOD' => 1, - 'AC_FUNC_GETLOADAVG' => 1, - 'AC_CHECK_HEADERS' => 1, - 'AC_FUNC_SETPGRP' => 1, - 'AC_CHECK_LIB' => 1, - 'AC_FUNC_SELECT_ARGTYPES' => 1, + 'AC_FUNC_VPRINTF' => 1, 'AC_TYPE_OFF_T' => 1, + 'AC_CHECK_LIB' => 1, + 'AC_FUNC_STRNLEN' => 1, + 'AC_STRUCT_TM' => 1, + 'AC_PROG_CPP' => 1, + 'AC_FUNC_MBRTOWC' => 1, + 'AC_PROG_MAKE_SET' => 1, 'AC_DEFINE_TRACE_LITERAL' => 1, - 'AC_HEADER_STAT' => 1, - 'AC_PROG_LIBTOOL' => 1, - 'm4_pattern_forbid' => 1, - 'AC_TYPE_PID_T' => 1, - 'AC_TYPE_SIZE_T' => 1, - 'AC_FUNC_MALLOC' => 1, 'AC_HEADER_DIRENT' => 1, - 'AC_PROG_INSTALL' => 1, - 'AC_CONFIG_SUBDIRS' => 1, 'AC_FUNC_ERROR_AT_LINE' => 1, - 'AC_FUNC_MMAP' => 1, - 'AC_HEADER_TIME' => 1, - 'AC_FUNC_REALLOC' => 1, - 'include' => 1, - 'm4_pattern_allow' => 1, - 'AC_FUNC_WAIT3' => 1, - 'AC_PROG_AWK' => 1, - 'AC_HEADER_MAJOR' => 1, - 'AM_CONDITIONAL' => 1, - 'AC_PROG_CC' => 1, - 'AC_CHECK_MEMBERS' => 1, - 'AC_TYPE_SIGNAL' => 1, - 'AC_C_INLINE' => 1, - 'AC_FUNC_CLOSEDIR_VOID' => 1, - 'AC_FUNC_LSTAT' => 1, + 'AC_HEADER_STDC' => 1, + 'AC_FUNC_SELECT_ARGTYPES' => 1, + 'AC_STRUCT_TIMEZONE' => 1, + 'AC_HEADER_STAT' => 1, + 'AC_TYPE_MODE_T' => 1, + 'AC_FUNC_SETPGRP' => 1, + 'AC_FUNC_MKTIME' => 1, + 'AC_TYPE_UID_T' => 1, + 'AC_FUNC_FORK' => 1, 'AC_CONFIG_HEADERS' => 1, - 'AC_REPLACE_FNMATCH' => 1, - 'AC_PATH_X' => 1, + 'AC_FUNC_CLOSEDIR_VOID' => 1, + 'AC_FUNC_STRTOD' => 1, + 'AC_PROG_INSTALL' => 1, + 'AC_CONFIG_FILES' => 1, 'AC_FUNC_STAT' => 1, - 'AC_PROG_GCC_TRADITIONAL' => 1, - 'AC_CANONICAL_HOST' => 1 + 'AM_INIT_AUTOMAKE' => 1, + 'AC_FUNC_FSEEKO' => 1, + 'AC_C_INLINE' => 1, + 'AC_FUNC_SETVBUF_REVERSED' => 1, + 'AC_PROG_YACC' => 1 } ], 'Request' ) ); diff --git a/autom4te.cache/traces.0 b/autom4te.cache/traces.0 index 9d125d4a..e2b6bedb 100644 --- a/autom4te.cache/traces.0 +++ b/autom4te.cache/traces.0 @@ -642,7 +642,7 @@ m4trace:configure.in:640: -1- AH_OUTPUT([HAVE_RENAME], [/* Define to 1 if you ha m4trace:configure.in:640: -1- AC_SUBST([LIB@&t@OBJS]) m4trace:configure.in:647: -1- AC_CHECK_FUNCS([bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \ setlinebuf setvbuf setlocale strchr tcgetattr uname \ - ulimit tzset siginterrupt memmove ttyname times \ + ulimit tzset siginterrupt memmove ttyname times raise \ getaddrinfo gethostbyname getservbyname getservent inet_aton \ vsnprintf snprintf vasprintf asprintf fnmatch regcomp regexec]) m4trace:configure.in:647: -1- AH_OUTPUT([HAVE_BCOPY], [/* Define to 1 if you have the `bcopy\' function. */ @@ -685,6 +685,8 @@ m4trace:configure.in:647: -1- AH_OUTPUT([HAVE_TTYNAME], [/* Define to 1 if you h #undef HAVE_TTYNAME]) m4trace:configure.in:647: -1- AH_OUTPUT([HAVE_TIMES], [/* Define to 1 if you have the `times\' function. */ #undef HAVE_TIMES]) +m4trace:configure.in:647: -1- AH_OUTPUT([HAVE_RAISE], [/* Define to 1 if you have the `raise\' function. */ +#undef HAVE_RAISE]) m4trace:configure.in:647: -1- AH_OUTPUT([HAVE_GETADDRINFO], [/* Define to 1 if you have the `getaddrinfo\' function. */ #undef HAVE_GETADDRINFO]) m4trace:configure.in:647: -1- AH_OUTPUT([HAVE_GETHOSTBYNAME], [/* Define to 1 if you have the `gethostbyname\' function. */ diff --git a/builtins/pushd.def b/builtins/pushd.def index bc5504c7..473631b0 100644 --- a/builtins/pushd.def +++ b/builtins/pushd.def @@ -653,7 +653,7 @@ get_directory_stack () } #ifdef LOADABLE_BUILTIN -static char *dirs_doc[] = { +static char * const dirs_doc[] = { N_("Display the list of currently remembered directories. Directories"), N_("find their way onto the list with the `pushd' command; you can get"), N_("back up through the list with the `popd' command."), @@ -674,7 +674,7 @@ static char *dirs_doc[] = { (char *)NULL }; -static char *pushd_doc[] = { +static char * const pushd_doc[] = { N_("Adds a directory to the top of the directory stack, or rotates"), N_("the stack, making the new top of the stack the current working"), N_("directory. With no arguments, exchanges the top two directories."), @@ -697,7 +697,7 @@ static char *pushd_doc[] = { (char *)NULL }; -static char *popd_doc[] = { +static char * const popd_doc[] = { N_("Removes entries from the directory stack. With no arguments,"), N_("removes the top directory from the stack, and cd's to the new"), N_("top directory."), diff --git a/config.h.in b/config.h.in index 3bfc4624..27dea996 100644 --- a/config.h.in +++ b/config.h.in @@ -606,6 +606,9 @@ /* Define if you have the putenv function. */ #undef HAVE_PUTENV +/* Define if you have the raise function. */ +#undef HAVE_RAISE + /* Define if you have the readlink function. */ #undef HAVE_READLINK diff --git a/config.h.in~ b/config.h.in~ index 753b18a8..3bfc4624 100644 --- a/config.h.in~ +++ b/config.h.in~ @@ -386,7 +386,6 @@ #undef HAVE_LIBC_FNM_EXTMATCH - #undef HAVE_DECL_CONFSTR #undef HAVE_DECL_PRINTF @@ -403,6 +402,9 @@ #undef HAVE_MBSTATE_T +/* Define if WCONTINUED is defined in system headers, but rejected by waitpid */ +#undef WCONTINUED_BROKEN + /* These are checked with BASH_CHECK_DECL */ #undef HAVE_DECL_STRTOIMAX @@ -664,6 +666,9 @@ /* Define if you have the strftime function. */ #undef HAVE_STRFTIME +/* Define if you have the strnlen function. */ +#undef HAVE_STRNLEN + /* Define if you have the strpbrk function. */ #undef HAVE_STRPBRK @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in for Bash 3.0, version 3.170, from autoconf version AC_ACVERSION. +# From configure.in for Bash 3.0, version 3.171, from autoconf version AC_ACVERSION. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57 for bash 3.1-devel. # @@ -11351,9 +11351,10 @@ done + for ac_func in bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \ setlinebuf setvbuf setlocale strchr tcgetattr uname \ - ulimit tzset siginterrupt memmove ttyname times \ + ulimit tzset siginterrupt memmove ttyname times raise \ getaddrinfo gethostbyname getservbyname getservent inet_aton \ vsnprintf snprintf vasprintf asprintf fnmatch regcomp regexec do diff --git a/configure.in b/configure.in index 19dfe611..1e885992 100644 --- a/configure.in +++ b/configure.in @@ -22,7 +22,7 @@ dnl Process this file with autoconf to produce a configure script. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. -AC_REVISION([for Bash 3.0, version 3.170, from autoconf version] AC_ACVERSION)dnl +AC_REVISION([for Bash 3.0, version 3.171, from autoconf version] AC_ACVERSION)dnl define(bashvers, 3.1) define(relstatus, devel) @@ -642,7 +642,7 @@ AC_REPLACE_FUNCS(rename) dnl checks for c library functions AC_CHECK_FUNCS(bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \ setlinebuf setvbuf setlocale strchr tcgetattr uname \ - ulimit tzset siginterrupt memmove ttyname times \ + ulimit tzset siginterrupt memmove ttyname times raise \ getaddrinfo gethostbyname getservbyname getservent inet_aton \ vsnprintf snprintf vasprintf asprintf fnmatch regcomp regexec) AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit) diff --git a/configure.in~ b/configure.in~ index d1fc8048..302000aa 100644 --- a/configure.in~ +++ b/configure.in~ @@ -22,7 +22,7 @@ dnl Process this file with autoconf to produce a configure script. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. -AC_REVISION([for Bash 3.0, version 3.169, from autoconf version] AC_ACVERSION)dnl +AC_REVISION([for Bash 3.0, version 3.171, from autoconf version] AC_ACVERSION)dnl define(bashvers, 3.1) define(relstatus, devel) @@ -860,6 +860,8 @@ AC_HEADER_TIOCGWINSZ BASH_HAVE_TIOCSTAT BASH_HAVE_FIONREAD +BASH_CHECK_WCONTINUED + dnl miscellaneous BASH_CHECK_SPEED_T BASH_CHECK_GETPW_FUNCS @@ -6,12 +6,12 @@ .\" Case Western Reserve University .\" chet@po.CWRU.Edu .\" -.\" Last Change: Sun Nov 7 14:53:18 EST 2004 +.\" Last Change: Sat Nov 13 15:05:55 EST 2004 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2004 Nov 7" "GNU Bash-3.1-devel" +.TH BASH 1 "2004 Nov 13" "GNU Bash-3.1-devel" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -2373,6 +2373,10 @@ parameters beginning at \fIoffset\fP. If \fIparameter\fP is an array name indexed by @ or *, the result is the \fIlength\fP members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}. +A negative \fIoffset\fP is taken relative to one greater than the maximum +index of the specified array. +Note that a negative offset must be separated from the colon by at least +one space to avoid being confused with the :- expansion. Substring indexing is zero-based unless the positional parameters are used, in which case the indexing starts at 1. .TP diff --git a/doc/bash.1~ b/doc/bash.1~ index e607d98b..24eda81a 100644 --- a/doc/bash.1~ +++ b/doc/bash.1~ @@ -6,12 +6,12 @@ .\" Case Western Reserve University .\" chet@po.CWRU.Edu .\" -.\" Last Change: Sat Oct 30 22:24:07 EDT 2004 +.\" Last Change: Tue Nov 9 16:30:56 EST 2004 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2004 Oct 30" "GNU Bash-3.1-devel" +.TH BASH 1 "2004 Nov 9" "GNU Bash-3.1-devel" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -1076,6 +1076,20 @@ Assignment statements may also appear as arguments to the and .B local builtin commands. +.PP +In the context where an assignment statement is assigning a value +to a shell variable or array index, the += operator can be used to +append to or add to the variable's previous value. +When += is applied to a variable for which the integer attribute has been +set, \fIvalue\fP is evaluated as an arithmetic expression and added to the +variable's current value, which is also evaluated. +When += is applied to an array variable using compound assignment (see +.B Arrays +below), the +variable's value is not unset (as it is when using =), and new values are +appended to the array beginning at one greater than the array's maximum index. +When applied to a string-valued variable, \fIvalue\fP is expanded and +appended to the variable's value. .SS Positional Parameters .PP A @@ -2359,6 +2373,8 @@ parameters beginning at \fIoffset\fP. If \fIparameter\fP is an array name indexed by @ or *, the result is the \fIlength\fP members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}. +A negative \fIoffset\fP is taken relative to one greater than the maximum +index of the specified array. Substring indexing is zero-based unless the positional parameters are used, in which case the indexing starts at 1. .TP diff --git a/doc/bashref.texi b/doc/bashref.texi index ef24755c..79985e79 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -1599,6 +1599,10 @@ parameters beginning at @var{offset}. If @var{parameter} is an array name indexed by @samp{@@} or @samp{*}, the result is the @var{length} members of the array beginning with @code{$@{@var{parameter}[@var{offset}]@}}. +A negative @var{offset} is taken relative to one greater than the maximum +index of the specified array. +Note that a negative offset must be separated from the colon by at least +one space to avoid being confused with the @samp{:-} expansion. Substring indexing is zero-based unless the positional parameters are used, in which case the indexing starts at 1. diff --git a/doc/bashref.texi~ b/doc/bashref.texi~ index b581aaab..fe170764 100644 --- a/doc/bashref.texi~ +++ b/doc/bashref.texi~ @@ -1208,6 +1208,21 @@ Assignment statements may also appear as arguments to the @code{declare}, @code{typeset}, @code{export}, @code{readonly}, and @code{local} builtin commands. +In the context where an assignment statement is assigning a value +to a shell variable or array index (@pxref{Arrays}), the @samp{+=} +operator can be used to +append to or add to the variable's previous value. +When @samp{+=} is applied to a variable for which the integer attribute +has been set, @var{value} is evaluated as an arithmetic expression and +added to the variable's current value, which is also evaluated. +When @samp{+=} is applied to an array variable using compound assignment +(@pxref{Arrays}), the +variable's value is not unset (as it is when using @samp{=}), and new +values are appended to the array beginning at one greater than the array's +maximum index. +When applied to a string-valued variable, @var{value} is expanded and +appended to the variable's value. + @node Positional Parameters @subsection Positional Parameters @cindex parameters, positional @@ -1584,6 +1599,8 @@ parameters beginning at @var{offset}. If @var{parameter} is an array name indexed by @samp{@@} or @samp{*}, the result is the @var{length} members of the array beginning with @code{$@{@var{parameter}[@var{offset}]@}}. +A negative @var{offset} is taken relative to one greater than the maximum +index of the specified array. Substring indexing is zero-based unless the positional parameters are used, in which case the indexing starts at 1. diff --git a/doc/version.texi b/doc/version.texi index 3c858bd4..cea6a587 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,9 +2,10 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc. @end ignore +@set LASTCHANGE Sat Nov 13 15:06:31 EST 2004 + @set EDITION 3.1-devel @set VERSION 3.1-devel -@set UPDATED 7 November 2004 +@set UPDATED 13 November 2004 @set UPDATED-MONTH November 2004 -@set LASTCHANGE Sun Nov 7 15:09:53 EST 2004 diff --git a/doc/version.texi~ b/doc/version.texi~ index 8f7b8209..a0062859 100644 --- a/doc/version.texi~ +++ b/doc/version.texi~ @@ -4,7 +4,7 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc. @set EDITION 3.1-devel @set VERSION 3.1-devel -@set UPDATED 7 November 2004 +@set UPDATED 9 November 2004 @set UPDATED-MONTH November 2004 -@set LASTCHANGE +@set LASTCHANGE Tue Nov 9 16:30:45 EST 2004 diff --git a/examples/loadables/Makefile.in b/examples/loadables/Makefile.in index 356baef3..f6208f5c 100644 --- a/examples/loadables/Makefile.in +++ b/examples/loadables/Makefile.in @@ -46,6 +46,17 @@ LOCAL_CFLAGS = @LOCAL_CFLAGS@ DEFS = @DEFS@ LOCAL_DEFS = @LOCAL_DEFS@ +CPPFLAGS = @CPPFLAGS@ + +BASHINCDIR = ${topdir}/include + +LIBBUILD = ${BUILD_DIR}/lib + +INTL_LIBSRC = ${topdir}/lib/intl +INTL_BUILDDIR = ${LIBBUILD}/intl +INTL_INC = @INTL_INC@ +LIBINTL_H = @LIBINTL_H@ + CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS) # @@ -63,8 +74,8 @@ SHOBJ_LIBS = @SHOBJ_LIBS@ SHOBJ_STATUS = @SHOBJ_STATUS@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \ - -I$(topdir)/include -I$(BUILD_DIR) -I$(BUILD_DIR)/lib \ - -I$(BUILD_DIR)/builtins + -I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \ + -I$(BUILD_DIR)/builtins $(INTL_INC) .c.o: $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $< @@ -184,7 +195,7 @@ pushd.c: ${topdir}/builtins/pushd.def pushd.o: pushd.c $(RM) $@ - $(SHOBJ_CC) -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(INC) -c -o $@ $< + $(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $< pushd: pushd.o $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS) diff --git a/examples/loadables/sprintf.c b/examples/loadables/sprintf.c index b8cb824b..a56a49b3 100644 --- a/examples/loadables/sprintf.c +++ b/examples/loadables/sprintf.c @@ -159,7 +159,7 @@ sprintf_builtin (list) r = sprintf_main (c, v); free (v); - var = bind_variable (varname, outstr); + var = bind_variable (varname, outstr, 0); if (readonly_p (var)) { builtin_error ("%s: readonly variable", varname); diff --git a/lib/intl/dcigettext.c b/lib/intl/dcigettext.c index f6edb95c..d4ea843f 100644 --- a/lib/intl/dcigettext.c +++ b/lib/intl/dcigettext.c @@ -417,6 +417,10 @@ static int enable_secure; } #endif +#ifndef HAVE_RAISE +# define raise(x) kill (getpid (), (x)) +#endif + /* Get the function to evaluate the plural expression. */ #include "eval-plural.h" diff --git a/lib/intl/dcigettext.c~ b/lib/intl/dcigettext.c~ new file mode 100644 index 00000000..f6edb95c --- /dev/null +++ b/lib/intl/dcigettext.c~ @@ -0,0 +1,1238 @@ +/* Implementation of the internal dcigettext function. + Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* Tell glibc's <string.h> to provide a prototype for mempcpy(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> + +#ifdef __GNUC__ +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include <errno.h> +#ifndef errno +extern int errno; +#endif +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#if defined HAVE_UNISTD_H || defined _LIBC +# include <unistd.h> +#endif + +#include <locale.h> + +#ifdef _LIBC + /* Guess whether integer division by zero raises signal SIGFPE. + Set to 1 only if you know for sure. In case of doubt, set to 0. */ +# if defined __alpha__ || defined __arm__ || defined __i386__ \ + || defined __m68k__ || defined __s390__ +# define INTDIV0_RAISES_SIGFPE 1 +# else +# define INTDIV0_RAISES_SIGFPE 0 +# endif +#endif +#if !INTDIV0_RAISES_SIGFPE +# include <signal.h> +#endif + +#if defined HAVE_SYS_PARAM_H || defined _LIBC +# include <sys/param.h> +#endif + +#include "gettextP.h" +#include "plural-exp.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif +#include "hash-string.h" + +/* Thread safetyness. */ +#ifdef _LIBC +# include <bits/libc-lock.h> +#else +/* Provide dummy implementation if this is outside glibc. */ +# define __libc_lock_define_initialized(CLASS, NAME) +# define __libc_lock_lock(NAME) +# define __libc_lock_unlock(NAME) +# define __libc_rwlock_define_initialized(CLASS, NAME) +# define __libc_rwlock_rdlock(NAME) +# define __libc_rwlock_unlock(NAME) +#endif + +/* Alignment of types. */ +#if defined __GNUC__ && __GNUC__ >= 2 +# define alignof(TYPE) __alignof__ (TYPE) +#else +# define alignof(TYPE) \ + ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) +#endif + +/* The internal variables in the standalone libintl.a must have different + names than the internal variables in GNU libc, otherwise programs + using libintl.a cannot be linked statically. */ +#if !defined _LIBC +# define _nl_default_default_domain libintl_nl_default_default_domain +# define _nl_current_default_domain libintl_nl_current_default_domain +# define _nl_default_dirname libintl_nl_default_dirname +# define _nl_domain_bindings libintl_nl_domain_bindings +#endif + +/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ +#ifndef offsetof +# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) +#endif + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ANSI C functions. This is required by the standard + because some ANSI C functions will require linking with this object + file and the name space must not be polluted. */ +# define getcwd __getcwd +# ifndef stpcpy +# define stpcpy __stpcpy +# endif +# define tfind __tfind +#else +# if !defined HAVE_GETCWD +char *getwd (); +# define getcwd(buf, max) getwd (buf) +# else +char *getcwd (); +# endif +# ifndef HAVE_STPCPY +static char *stpcpy PARAMS ((char *dest, const char *src)); +# endif +# ifndef HAVE_MEMPCPY +static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); +# endif +#endif + +/* Amount to increase buffer size by in each try. */ +#define PATH_INCR 32 + +/* The following is from pathmax.h. */ +/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define + PATH_MAX but might cause redefinition warnings when sys/param.h is + later included (as on MORE/BSD 4.3). */ +#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) +# include <limits.h> +#endif + +#ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 255 +#endif + +#if !defined PATH_MAX && defined _PC_PATH_MAX +# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) +#endif + +/* Don't include sys/param.h if it already has been. */ +#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN +# include <sys/param.h> +#endif + +#if !defined PATH_MAX && defined MAXPATHLEN +# define PATH_MAX MAXPATHLEN +#endif + +#ifndef PATH_MAX +# define PATH_MAX _POSIX_PATH_MAX +#endif + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, + it may be concatenated to a directory pathname. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +#endif + +/* This is the type used for the search tree where known translations + are stored. */ +struct known_translation_t +{ + /* Domain in which to search. */ + char *domainname; + + /* The category. */ + int category; + + /* State of the catalog counter at the point the string was found. */ + int counter; + + /* Catalog where the string was found. */ + struct loaded_l10nfile *domain; + + /* And finally the translation. */ + const char *translation; + size_t translation_length; + + /* Pointer to the string in question. */ + char msgid[ZERO]; +}; + +/* Root of the search tree with known translations. We can use this + only if the system provides the `tsearch' function family. */ +#if defined HAVE_TSEARCH || defined _LIBC +# include <search.h> + +static void *root; + +# ifdef _LIBC +# define tsearch __tsearch +# endif + +/* Function to compare two entries in the table of known translations. */ +static int transcmp PARAMS ((const void *p1, const void *p2)); +static int +transcmp (p1, p2) + const void *p1; + const void *p2; +{ + const struct known_translation_t *s1; + const struct known_translation_t *s2; + int result; + + s1 = (const struct known_translation_t *) p1; + s2 = (const struct known_translation_t *) p2; + + result = strcmp (s1->msgid, s2->msgid); + if (result == 0) + { + result = strcmp (s1->domainname, s2->domainname); + if (result == 0) + /* We compare the category last (though this is the cheapest + operation) since it is hopefully always the same (namely + LC_MESSAGES). */ + result = s1->category - s2->category; + } + + return result; +} +#endif + +#ifndef INTVARDEF +# define INTVARDEF(name) +#endif +#ifndef INTUSE +# define INTUSE(name) name +#endif + +/* Name of the default domain used for gettext(3) prior any call to + textdomain(3). The default value for this is "messages". */ +const char _nl_default_default_domain[] attribute_hidden = "messages"; + +/* Value used as the default domain for gettext(3). */ +const char *_nl_current_default_domain attribute_hidden + = _nl_default_default_domain; + +/* Contains the default location of the message catalogs. */ +#if defined __EMX__ +extern const char _nl_default_dirname[]; +#else +const char _nl_default_dirname[] = LOCALEDIR; +INTVARDEF (_nl_default_dirname) +#endif + +/* List with bindings of specific domains created by bindtextdomain() + calls. */ +struct binding *_nl_domain_bindings; + +/* Prototypes for local functions. */ +static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, + unsigned long int n, + const char *translation, + size_t translation_len)) + internal_function; +static const char *guess_category_value PARAMS ((int category, + const char *categoryname)) + internal_function; +#ifdef _LIBC +# include "../locale/localeinfo.h" +# define category_to_name(category) _nl_category_names[category] +#else +static const char *category_to_name PARAMS ((int category)) internal_function; +#endif + + +/* For those loosing systems which don't have `alloca' we have to add + some additional code emulating it. */ +#ifdef HAVE_ALLOCA +/* Nothing has to be done. */ +# define freea(p) /* nothing */ +# define ADD_BLOCK(list, address) /* nothing */ +# define FREE_BLOCKS(list) /* nothing */ +#else +struct block_list +{ + void *address; + struct block_list *next; +}; +# define ADD_BLOCK(list, addr) \ + do { \ + struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ + /* If we cannot get a free block we cannot add the new element to \ + the list. */ \ + if (newp != NULL) { \ + newp->address = (addr); \ + newp->next = (list); \ + (list) = newp; \ + } \ + } while (0) +# define FREE_BLOCKS(list) \ + do { \ + while (list != NULL) { \ + struct block_list *old = list; \ + list = list->next; \ + free (old->address); \ + free (old); \ + } \ + } while (0) +# undef alloca +# define alloca(size) (malloc (size)) +# define freea(p) free (p) +#endif /* have alloca */ + + +#ifdef _LIBC +/* List of blocks allocated for translations. */ +typedef struct transmem_list +{ + struct transmem_list *next; + char data[ZERO]; +} transmem_block_t; +static struct transmem_list *transmem_list; +#else +typedef unsigned char transmem_block_t; +#endif + + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DCIGETTEXT __dcigettext +#else +# define DCIGETTEXT libintl_dcigettext +#endif + +/* Lock variable to protect the global data in the gettext implementation. */ +#ifdef _LIBC +__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden) +#endif + +/* Checking whether the binaries runs SUID must be done and glibc provides + easier methods therefore we make a difference here. */ +#ifdef _LIBC +# define ENABLE_SECURE __libc_enable_secure +# define DETERMINE_SECURE +#else +# ifndef HAVE_GETUID +# define getuid() 0 +# endif +# ifndef HAVE_GETGID +# define getgid() 0 +# endif +# ifndef HAVE_GETEUID +# define geteuid() getuid() +# endif +# ifndef HAVE_GETEGID +# define getegid() getgid() +# endif +static int enable_secure; +# define ENABLE_SECURE (enable_secure == 1) +# define DETERMINE_SECURE \ + if (enable_secure == 0) \ + { \ + if (getuid () != geteuid () || getgid () != getegid ()) \ + enable_secure = 1; \ + else \ + enable_secure = -1; \ + } +#endif + +/* Get the function to evaluate the plural expression. */ +#include "eval-plural.h" + +/* Look up MSGID in the DOMAINNAME message catalog for the current + CATEGORY locale and, if PLURAL is nonzero, search over string + depending on the plural form determined by N. */ +char * +DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) + const char *domainname; + const char *msgid1; + const char *msgid2; + int plural; + unsigned long int n; + int category; +{ +#ifndef HAVE_ALLOCA + struct block_list *block_list = NULL; +#endif + struct loaded_l10nfile *domain; + struct binding *binding; + const char *categoryname; + const char *categoryvalue; + char *dirname, *xdomainname; + char *single_locale; + char *retval; + size_t retlen; + int saved_errno; +#if defined HAVE_TSEARCH || defined _LIBC + struct known_translation_t *search; + struct known_translation_t **foundp = NULL; + size_t msgid_len; +#endif + size_t domainname_len; + + /* If no real MSGID is given return NULL. */ + if (msgid1 == NULL) + return NULL; + +#ifdef _LIBC + if (category < 0 || category >= __LC_LAST || category == LC_ALL) + /* Bogus. */ + return (plural == 0 + ? (char *) msgid1 + /* Use the Germanic plural rule. */ + : n == 1 ? (char *) msgid1 : (char *) msgid2); +#endif + + __libc_rwlock_rdlock (_nl_state_lock); + + /* If DOMAINNAME is NULL, we are interested in the default domain. If + CATEGORY is not LC_MESSAGES this might not make much sense but the + definition left this undefined. */ + if (domainname == NULL) + domainname = _nl_current_default_domain; + + /* OS/2 specific: backward compatibility with older libintl versions */ +#ifdef LC_MESSAGES_COMPAT + if (category == LC_MESSAGES_COMPAT) + category = LC_MESSAGES; +#endif + +#if defined HAVE_TSEARCH || defined _LIBC + msgid_len = strlen (msgid1) + 1; + + /* Try to find the translation among those which we found at + some time. */ + search = (struct known_translation_t *) + alloca (offsetof (struct known_translation_t, msgid) + msgid_len); + memcpy (search->msgid, msgid1, msgid_len); + search->domainname = (char *) domainname; + search->category = category; + + foundp = (struct known_translation_t **) tfind (search, &root, transcmp); + freea (search); + if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) + { + /* Now deal with plural. */ + if (plural) + retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, + (*foundp)->translation_length); + else + retval = (char *) (*foundp)->translation; + + __libc_rwlock_unlock (_nl_state_lock); + return retval; + } +#endif + + /* Preserve the `errno' value. */ + saved_errno = errno; + + /* See whether this is a SUID binary or not. */ + DETERMINE_SECURE; + + /* First find matching binding. */ + for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) + { + int compare = strcmp (domainname, binding->domainname); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It is not in the list. */ + binding = NULL; + break; + } + } + + if (binding == NULL) + dirname = (char *) INTUSE(_nl_default_dirname); + else if (IS_ABSOLUTE_PATH (binding->dirname)) + dirname = binding->dirname; + else + { + /* We have a relative path. Make it absolute now. */ + size_t dirname_len = strlen (binding->dirname) + 1; + size_t path_max; + char *ret; + + path_max = (unsigned int) PATH_MAX; + path_max += 2; /* The getcwd docs say to do this. */ + + for (;;) + { + dirname = (char *) alloca (path_max + dirname_len); + ADD_BLOCK (block_list, dirname); + + __set_errno (0); + ret = getcwd (dirname, path_max); + if (ret != NULL || errno != ERANGE) + break; + + path_max += path_max / 2; + path_max += PATH_INCR; + } + + if (ret == NULL) + /* We cannot get the current working directory. Don't signal an + error but simply return the default string. */ + goto return_untranslated; + + stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname); + } + + /* Now determine the symbolic name of CATEGORY and its value. */ + categoryname = category_to_name (category); + categoryvalue = guess_category_value (category, categoryname); + + domainname_len = strlen (domainname); + xdomainname = (char *) alloca (strlen (categoryname) + + domainname_len + 5); + ADD_BLOCK (block_list, xdomainname); + + stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), + domainname, domainname_len), + ".mo"); + + /* Creating working area. */ + single_locale = (char *) alloca (strlen (categoryvalue) + 1); + ADD_BLOCK (block_list, single_locale); + + + /* Search for the given string. This is a loop because we perhaps + got an ordered list of languages to consider for the translation. */ + while (1) + { + /* Make CATEGORYVALUE point to the next element of the list. */ + while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') + ++categoryvalue; + if (categoryvalue[0] == '\0') + { + /* The whole contents of CATEGORYVALUE has been searched but + no valid entry has been found. We solve this situation + by implicitly appending a "C" entry, i.e. no translation + will take place. */ + single_locale[0] = 'C'; + single_locale[1] = '\0'; + } + else + { + char *cp = single_locale; + while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') + *cp++ = *categoryvalue++; + *cp = '\0'; + + /* When this is a SUID binary we must not allow accessing files + outside the dedicated directories. */ + if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) + /* Ingore this entry. */ + continue; + } + + /* If the current locale value is C (or POSIX) we don't load a + domain. Return the MSGID. */ + if (strcmp (single_locale, "C") == 0 + || strcmp (single_locale, "POSIX") == 0) + break; + + /* Find structure describing the message catalog matching the + DOMAINNAME and CATEGORY. */ + domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); + + if (domain != NULL) + { + retval = _nl_find_msg (domain, binding, msgid1, &retlen); + + if (retval == NULL) + { + int cnt; + + for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) + { + retval = _nl_find_msg (domain->successor[cnt], binding, + msgid1, &retlen); + + if (retval != NULL) + { + domain = domain->successor[cnt]; + break; + } + } + } + + if (retval != NULL) + { + /* Found the translation of MSGID1 in domain DOMAIN: + starting at RETVAL, RETLEN bytes. */ + FREE_BLOCKS (block_list); +#if defined HAVE_TSEARCH || defined _LIBC + if (foundp == NULL) + { + /* Create a new entry and add it to the search tree. */ + struct known_translation_t *newp; + + newp = (struct known_translation_t *) + malloc (offsetof (struct known_translation_t, msgid) + + msgid_len + domainname_len + 1); + if (newp != NULL) + { + newp->domainname = + mempcpy (newp->msgid, msgid1, msgid_len); + memcpy (newp->domainname, domainname, domainname_len + 1); + newp->category = category; + newp->counter = _nl_msg_cat_cntr; + newp->domain = domain; + newp->translation = retval; + newp->translation_length = retlen; + + /* Insert the entry in the search tree. */ + foundp = (struct known_translation_t **) + tsearch (newp, &root, transcmp); + if (foundp == NULL + || __builtin_expect (*foundp != newp, 0)) + /* The insert failed. */ + free (newp); + } + } + else + { + /* We can update the existing entry. */ + (*foundp)->counter = _nl_msg_cat_cntr; + (*foundp)->domain = domain; + (*foundp)->translation = retval; + (*foundp)->translation_length = retlen; + } +#endif + __set_errno (saved_errno); + + /* Now deal with plural. */ + if (plural) + retval = plural_lookup (domain, n, retval, retlen); + + __libc_rwlock_unlock (_nl_state_lock); + return retval; + } + } + } + + return_untranslated: + /* Return the untranslated MSGID. */ + FREE_BLOCKS (block_list); + __libc_rwlock_unlock (_nl_state_lock); +#ifndef _LIBC + if (!ENABLE_SECURE) + { + extern void _nl_log_untranslated PARAMS ((const char *logfilename, + const char *domainname, + const char *msgid1, + const char *msgid2, + int plural)); + const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED"); + + if (logfilename != NULL && logfilename[0] != '\0') + _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural); + } +#endif + __set_errno (saved_errno); + return (plural == 0 + ? (char *) msgid1 + /* Use the Germanic plural rule. */ + : n == 1 ? (char *) msgid1 : (char *) msgid2); +} + + +char * +internal_function +_nl_find_msg (domain_file, domainbinding, msgid, lengthp) + struct loaded_l10nfile *domain_file; + struct binding *domainbinding; + const char *msgid; + size_t *lengthp; +{ + struct loaded_domain *domain; + nls_uint32 nstrings; + size_t act; + char *result; + size_t resultlen; + + if (domain_file->decided == 0) + _nl_load_domain (domain_file, domainbinding); + + if (domain_file->data == NULL) + return NULL; + + domain = (struct loaded_domain *) domain_file->data; + + nstrings = domain->nstrings; + + /* Locate the MSGID and its translation. */ + if (domain->hash_tab != NULL) + { + /* Use the hashing table. */ + nls_uint32 len = strlen (msgid); + nls_uint32 hash_val = hash_string (msgid); + nls_uint32 idx = hash_val % domain->hash_size; + nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); + + while (1) + { + nls_uint32 nstr = + W (domain->must_swap_hash_tab, domain->hash_tab[idx]); + + if (nstr == 0) + /* Hash table entry is empty. */ + return NULL; + + nstr--; + + /* Compare msgid with the original string at index nstr. + We compare the lengths with >=, not ==, because plural entries + are represented by strings with an embedded NUL. */ + if (nstr < nstrings + ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len + && (strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr].offset)) + == 0) + : domain->orig_sysdep_tab[nstr - nstrings].length > len + && (strcmp (msgid, + domain->orig_sysdep_tab[nstr - nstrings].pointer) + == 0)) + { + act = nstr; + goto found; + } + + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + } + /* NOTREACHED */ + } + else + { + /* Try the default method: binary search in the sorted array of + messages. */ + size_t top, bottom; + + bottom = 0; + top = nstrings; + while (bottom < top) + { + int cmp_val; + + act = (bottom + top) / 2; + cmp_val = strcmp (msgid, (domain->data + + W (domain->must_swap, + domain->orig_tab[act].offset))); + if (cmp_val < 0) + top = act; + else if (cmp_val > 0) + bottom = act + 1; + else + goto found; + } + /* No translation was found. */ + return NULL; + } + + found: + /* The translation was found at index ACT. If we have to convert the + string to use a different character set, this is the time. */ + if (act < nstrings) + { + result = (char *) + (domain->data + W (domain->must_swap, domain->trans_tab[act].offset)); + resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; + } + else + { + result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer; + resultlen = domain->trans_sysdep_tab[act - nstrings].length; + } + +#if defined _LIBC || HAVE_ICONV + if (domain->codeset_cntr + != (domainbinding != NULL ? domainbinding->codeset_cntr : 0)) + { + /* The domain's codeset has changed through bind_textdomain_codeset() + since the message catalog was initialized or last accessed. We + have to reinitialize the converter. */ + _nl_free_domain_conv (domain); + _nl_init_domain_conv (domain_file, domain, domainbinding); + } + + if ( +# ifdef _LIBC + domain->conv != (__gconv_t) -1 +# else +# if HAVE_ICONV + domain->conv != (iconv_t) -1 +# endif +# endif + ) + { + /* We are supposed to do a conversion. First allocate an + appropriate table with the same structure as the table + of translations in the file, where we can put the pointers + to the converted strings in. + There is a slight complication with plural entries. They + are represented by consecutive NUL terminated strings. We + handle this case by converting RESULTLEN bytes, including + NULs. */ + + if (domain->conv_tab == NULL + && ((domain->conv_tab = + (char **) calloc (nstrings + domain->n_sysdep_strings, + sizeof (char *))) + == NULL)) + /* Mark that we didn't succeed allocating a table. */ + domain->conv_tab = (char **) -1; + + if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) + /* Nothing we can do, no more memory. */ + goto converted; + + if (domain->conv_tab[act] == NULL) + { + /* We haven't used this string so far, so it is not + translated yet. Do this now. */ + /* We use a bit more efficient memory handling. + We allocate always larger blocks which get used over + time. This is faster than many small allocations. */ + __libc_lock_define_initialized (static, lock) +# define INITIAL_BLOCK_SIZE 4080 + static unsigned char *freemem; + static size_t freemem_size; + + const unsigned char *inbuf; + unsigned char *outbuf; + int malloc_count; +# ifndef _LIBC + transmem_block_t *transmem_list = NULL; +# endif + + __libc_lock_lock (lock); + + inbuf = (const unsigned char *) result; + outbuf = freemem + sizeof (size_t); + + malloc_count = 0; + while (1) + { + transmem_block_t *newmem; +# ifdef _LIBC + size_t non_reversible; + int res; + + if (freemem_size < sizeof (size_t)) + goto resize_freemem; + + res = __gconv (domain->conv, + &inbuf, inbuf + resultlen, + &outbuf, + outbuf + freemem_size - sizeof (size_t), + &non_reversible); + + if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) + break; + + if (res != __GCONV_FULL_OUTPUT) + { + __libc_lock_unlock (lock); + goto converted; + } + + inbuf = result; +# else +# if HAVE_ICONV + const char *inptr = (const char *) inbuf; + size_t inleft = resultlen; + char *outptr = (char *) outbuf; + size_t outleft; + + if (freemem_size < sizeof (size_t)) + goto resize_freemem; + + outleft = freemem_size - sizeof (size_t); + if (iconv (domain->conv, + (ICONV_CONST char **) &inptr, &inleft, + &outptr, &outleft) + != (size_t) (-1)) + { + outbuf = (unsigned char *) outptr; + break; + } + if (errno != E2BIG) + { + __libc_lock_unlock (lock); + goto converted; + } +# endif +# endif + + resize_freemem: + /* We must allocate a new buffer or resize the old one. */ + if (malloc_count > 0) + { + ++malloc_count; + freemem_size = malloc_count * INITIAL_BLOCK_SIZE; + newmem = (transmem_block_t *) realloc (transmem_list, + freemem_size); +# ifdef _LIBC + if (newmem != NULL) + transmem_list = transmem_list->next; + else + { + struct transmem_list *old = transmem_list; + + transmem_list = transmem_list->next; + free (old); + } +# endif + } + else + { + malloc_count = 1; + freemem_size = INITIAL_BLOCK_SIZE; + newmem = (transmem_block_t *) malloc (freemem_size); + } + if (__builtin_expect (newmem == NULL, 0)) + { + freemem = NULL; + freemem_size = 0; + __libc_lock_unlock (lock); + goto converted; + } + +# ifdef _LIBC + /* Add the block to the list of blocks we have to free + at some point. */ + newmem->next = transmem_list; + transmem_list = newmem; + + freemem = newmem->data; + freemem_size -= offsetof (struct transmem_list, data); +# else + transmem_list = newmem; + freemem = newmem; +# endif + + outbuf = freemem + sizeof (size_t); + } + + /* We have now in our buffer a converted string. Put this + into the table of conversions. */ + *(size_t *) freemem = outbuf - freemem - sizeof (size_t); + domain->conv_tab[act] = (char *) freemem; + /* Shrink freemem, but keep it aligned. */ + freemem_size -= outbuf - freemem; + freemem = outbuf; + freemem += freemem_size & (alignof (size_t) - 1); + freemem_size = freemem_size & ~ (alignof (size_t) - 1); + + __libc_lock_unlock (lock); + } + + /* Now domain->conv_tab[act] contains the translation of all + the plural variants. */ + result = domain->conv_tab[act] + sizeof (size_t); + resultlen = *(size_t *) domain->conv_tab[act]; + } + + converted: + /* The result string is converted. */ + +#endif /* _LIBC || HAVE_ICONV */ + + *lengthp = resultlen; + return result; +} + + +/* Look up a plural variant. */ +static char * +internal_function +plural_lookup (domain, n, translation, translation_len) + struct loaded_l10nfile *domain; + unsigned long int n; + const char *translation; + size_t translation_len; +{ + struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; + unsigned long int index; + const char *p; + + index = plural_eval (domaindata->plural, n); + if (index >= domaindata->nplurals) + /* This should never happen. It means the plural expression and the + given maximum value do not match. */ + index = 0; + + /* Skip INDEX strings at TRANSLATION. */ + p = translation; + while (index-- > 0) + { +#ifdef _LIBC + p = __rawmemchr (p, '\0'); +#else + p = strchr (p, '\0'); +#endif + /* And skip over the NUL byte. */ + p++; + + if (p >= translation + translation_len) + /* This should never happen. It means the plural expression + evaluated to a value larger than the number of variants + available for MSGID1. */ + return (char *) translation; + } + return (char *) p; +} + +#ifndef _LIBC +/* Return string representation of locale CATEGORY. */ +static const char * +internal_function +category_to_name (category) + int category; +{ + const char *retval; + + switch (category) + { +#ifdef LC_COLLATE + case LC_COLLATE: + retval = "LC_COLLATE"; + break; +#endif +#ifdef LC_CTYPE + case LC_CTYPE: + retval = "LC_CTYPE"; + break; +#endif +#ifdef LC_MONETARY + case LC_MONETARY: + retval = "LC_MONETARY"; + break; +#endif +#ifdef LC_NUMERIC + case LC_NUMERIC: + retval = "LC_NUMERIC"; + break; +#endif +#ifdef LC_TIME + case LC_TIME: + retval = "LC_TIME"; + break; +#endif +#ifdef LC_MESSAGES + case LC_MESSAGES: + retval = "LC_MESSAGES"; + break; +#endif +#ifdef LC_RESPONSE + case LC_RESPONSE: + retval = "LC_RESPONSE"; + break; +#endif +#ifdef LC_ALL + case LC_ALL: + /* This might not make sense but is perhaps better than any other + value. */ + retval = "LC_ALL"; + break; +#endif + default: + /* If you have a better idea for a default value let me know. */ + retval = "LC_XXX"; + } + + return retval; +} +#endif + +/* Guess value of current locale from value of the environment variables. */ +static const char * +internal_function +guess_category_value (category, categoryname) + int category; + const char *categoryname; +{ + const char *language; + const char *retval; + + /* The highest priority value is the `LANGUAGE' environment + variable. But we don't use the value if the currently selected + locale is the C locale. This is a GNU extension. */ + language = getenv ("LANGUAGE"); + if (language != NULL && language[0] == '\0') + language = NULL; + + /* We have to proceed with the POSIX methods of looking to `LC_ALL', + `LC_xxx', and `LANG'. On some systems this can be done by the + `setlocale' function itself. */ +#ifdef _LIBC + retval = __current_locale_name (category); +#else + retval = _nl_locale_name (category, categoryname); +#endif + + /* Ignore LANGUAGE if the locale is set to "C" because + 1. "C" locale usually uses the ASCII encoding, and most international + messages use non-ASCII characters. These characters get displayed + as question marks (if using glibc's iconv()) or as invalid 8-bit + characters (because other iconv()s refuse to convert most non-ASCII + characters to ASCII). In any case, the output is ugly. + 2. The precise output of some programs in the "C" locale is specified + by POSIX and should not depend on environment variables like + "LANGUAGE". We allow such programs to use gettext(). */ + return language != NULL && strcmp (retval, "C") != 0 ? language : retval; +} + +/* @@ begin of epilog @@ */ + +/* We don't want libintl.a to depend on any other library. So we + avoid the non-standard function stpcpy. In GNU C Library this + function is available, though. Also allow the symbol HAVE_STPCPY + to be defined. */ +#if !_LIBC && !HAVE_STPCPY +static char * +stpcpy (dest, src) + char *dest; + const char *src; +{ + while ((*dest++ = *src++) != '\0') + /* Do nothing. */ ; + return dest - 1; +} +#endif + +#if !_LIBC && !HAVE_MEMPCPY +static void * +mempcpy (dest, src, n) + void *dest; + const void *src; + size_t n; +{ + return (void *) ((char *) memcpy (dest, src, n) + n); +} +#endif + + +#ifdef _LIBC +/* If we want to free all resources we have to do some work at + program's end. */ +libc_freeres_fn (free_mem) +{ + void *old; + + while (_nl_domain_bindings != NULL) + { + struct binding *oldp = _nl_domain_bindings; + _nl_domain_bindings = _nl_domain_bindings->next; + if (oldp->dirname != INTUSE(_nl_default_dirname)) + /* Yes, this is a pointer comparison. */ + free (oldp->dirname); + free (oldp->codeset); + free (oldp); + } + + if (_nl_current_default_domain != _nl_default_default_domain) + /* Yes, again a pointer comparison. */ + free ((char *) _nl_current_default_domain); + + /* Remove the search tree with the known translations. */ + __tdestroy (root, free); + root = NULL; + + while (transmem_list != NULL) + { + old = transmem_list; + transmem_list = transmem_list->next; + free (old); + } +} +#endif diff --git a/lib/malloc/trace.c b/lib/malloc/trace.c index 9dc34df2..c775ae08 100644 --- a/lib/malloc/trace.c +++ b/lib/malloc/trace.c @@ -29,10 +29,10 @@ extern int malloc_trace; static int _mtrace_verbose = 0; -extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t)); - #ifdef MALLOC_TRACE +extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t)); + FILE *_mtrace_fp = NULL; extern char _malloc_trace_buckets[]; diff --git a/lib/malloc/trace.c~ b/lib/malloc/trace.c~ new file mode 100644 index 00000000..9dc34df2 --- /dev/null +++ b/lib/malloc/trace.c~ @@ -0,0 +1,122 @@ +/* trace.c - tracing functions for malloc */ + +/* Copyright (C) 2001-2003 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. */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#include "imalloc.h" + +extern int malloc_trace; + +static int _mtrace_verbose = 0; + +extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t)); + +#ifdef MALLOC_TRACE + +FILE *_mtrace_fp = NULL; +extern char _malloc_trace_buckets[]; + +void +mtrace_alloc (tag, mem, size, file, line) + const char *tag; + PTR_T mem; + size_t size; + const char *file; + int line; +{ + if (_mtrace_fp == NULL) + _mtrace_fp = stderr; + + if (_mtrace_verbose) + fprintf (_mtrace_fp, "alloc: %s: %p (%d bytes) from '%s:%d'\n", + tag, mem, size, file ? file : "unknown", line); + else + fprintf (_mtrace_fp, "alloc:%p:%d:%s:%d\n", + mem, size, file ? file : "unknown", line); +} + +void +mtrace_free (mem, size, file, line) + PTR_T mem; + int size; + const char *file; + int line; +{ + if (_mtrace_fp == NULL) + _mtrace_fp = stderr; + + if (_mtrace_verbose) + fprintf (_mtrace_fp, "free: %p (%d bytes) from '%s:%d'\n", + mem, size, file ? file : "unknown", line); + else + fprintf (_mtrace_fp, "free:%p:%d:%s:%d\n", + mem, size, file ? file : "unknown", line); +} +#endif /* MALLOC_TRACE */ + +int +malloc_set_trace (n) + int n; +{ + int old; + + old = malloc_trace; + malloc_trace = n; + _mtrace_verbose = (n > 1); + return old; +} + +void +malloc_set_tracefp (fp) + FILE *fp; +{ +#ifdef MALLOC_TRACE + _mtrace_fp = fp ? fp : stderr; +#endif +} + +void +malloc_trace_bin (n) + int n; +{ +#ifdef MALLOC_TRACE + _malloc_trace_buckets[n] = 1; +#endif +} + +#define TRACEROOT "/var/tmp/maltrace/trace." + +void +malloc_set_tracefn (s, fn) + char *s; + char *fn; +{ +#ifdef MALLOC_TRACE + FILE *fp; + char defname[sizeof (TRACEROOT) + 64]; + + fp = _imalloc_fopen (s, fn, TRACEROOT, defname, sizeof (defname)); + if (fp) + malloc_set_tracefp (fp); +#endif +} diff --git a/lib/readline/display.c b/lib/readline/display.c index 4b6e5985..b58b98a9 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -340,7 +340,8 @@ rl_expand_prompt (prompt) FREE (local_prompt_prefix); local_prompt = local_prompt_prefix = (char *)0; - prompt_last_invisible = prompt_visible_length = 0; + prompt_last_invisible = prompt_invis_chars_first_line = 0; + prompt_visible_length = prompt_physical_chars = 0; if (prompt == 0 || *prompt == 0) return (0); diff --git a/lib/readline/display.c~ b/lib/readline/display.c~ index 2627effc..4b6e5985 100644 --- a/lib/readline/display.c~ +++ b/lib/readline/display.c~ @@ -883,12 +883,10 @@ rl_redisplay () (wrap_offset > visible_wrap_offset) && (_rl_last_c_pos < visible_first_line_len)) { -#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) nleft = _rl_screenwidth - _rl_last_c_pos; else -#endif - nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; + nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; if (nleft) _rl_clear_to_eol (nleft); } @@ -966,8 +964,11 @@ rl_redisplay () tx = _rl_col_width (&visible_line[pos], 0, nleft); else tx = nleft; - _rl_backspace (_rl_last_c_pos - tx); /* XXX */ - _rl_last_c_pos = tx; + if (_rl_last_c_pos != tx) + { + _rl_backspace (_rl_last_c_pos - tx); /* XXX */ + _rl_last_c_pos = tx; + } } if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) diff --git a/lib/sh/getenv.c b/lib/sh/getenv.c index a7dfb186..c3fbf75d 100644 --- a/lib/sh/getenv.c +++ b/lib/sh/getenv.c @@ -127,7 +127,7 @@ putenv (str) value = name + offset + 1; /* XXX - should we worry about readonly here? */ - var = bind_variable (name, value); + var = bind_variable (name, value, 0); if (var == 0) { errno = EINVAL; @@ -175,7 +175,7 @@ setenv (name, value, rewrite) var = find_variable (name); if (var == 0) - var = bind_variable (name, v); + var = bind_variable (name, v, 0); if (var == 0) return -1; diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 72ec06a2..3efcf32d 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/bash/bash-current +BUILD_DIR=/usr/local/build/chet/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR |