commit bash-20101124 snapshot

This commit is contained in:
Chet Ramey
2011-12-12 22:10:33 -05:00
parent 18d2df9102
commit adc6cff53c
69 changed files with 14151 additions and 780 deletions
+1 -1
View File
@@ -260,7 +260,7 @@ u. History expansion no longer expands the `$!' variable expansion.
v. Posix mode shells no longer exit if a variable assignment error occurs
with an assignment preceding a command that is not a special builtin.
w. Non-interactive mode shells exit if -u is enabled an an attempt is made
w. Non-interactive mode shells exit if -u is enabled and an attempt is made
to use an unset variable with the % or # expansions, the `//', `^', or
`,' expansions, or the parameter length expansion.
+1 -1
View File
@@ -260,7 +260,7 @@ u. History expansion no longer expands the `$!' variable expansion.
v. Posix mode shells no longer exit if a variable assignment error occurs
with an assignment preceding a command that is not a special builtin.
w. Non-interactive mode shells exit if -u is enabled an an attempt is made
w. Non-interactive mode shells exit if -u is enabled and an attempt is made
to use an unset variable with the % or # expansions, the `//', `^', or
`,' expansions, or the parameter length expansion.
+138
View File
@@ -10640,3 +10640,141 @@ lib/readline/complete.c
users_dirname gets tacked back onto the beginning of the possible
completions and then requoted. Bug reported by Andreas Schwab
<schwab@linux-m68k.org>
11/22
-----
lib/readline/parens.c
- the `blink-matching-paren' variable should default to off
11/23
-----
subst.h
- add extern declaration for close_new_fifos()
lib/sh/fnxform.c
- fix curencoding to return the character past the `.', not a string
beginning with `.'
lib/sh/unicode.c
- fix stub_charset to do the same cut-off at `@' as curencoding().
These two functions should be combined
builtins/printf.def
- document new %(datefmt)T modifier in help text
11/24
-----
parse.y
- fix `W' case in decode_prompt_string: memmove was copying one too
few bytes and missed the closing NUL. Bug report from Tim Mooney
<Tim.Mooney@ndsu.edu>
11/26
-----
subst.c
- in expand_word_internal, don't add quoted nulls to partially-
quoted strings if the word will not be subjected to word splitting
later (which will remove the quoted null). Fixes bug reported by
Rocky Bernstein <rocky.bernstein@gmail.com>
11/28
-----
subst.c
- change multibyte case of match_pattern to revert to match_upattern
if neither the pattern nor the string has any multibyte characters
alias.c
- fix tests of backslash-escaped characters in skipquotes, skipws,
rd_token to check for backslash at EOS and not go past the end.
Fixes debian bug 603696 reported by Tim Small <tim@buttersideup.com>
include/shmbchar.h
- new file, mbchar.h from gnulib minus the <stdbool.h> include
lib/sh/shmbchar.c
- new file, mbchar.c from gnulib with additions
- moved mbstrlen from subst.c to here, changed initialization of mbs
- change mbstrlen to use is_basic to avoid calls to mbrlen for ASCII
chars; code hints from gnulib
- don't copy mbs and mbsbak if we're not calling mbrlen
11/29
-----
lib/glob/smatch.c
- change xstrmatch to use internal_strmatch() if the pattern and
string don't have any multibyte characters
11/30
-----
include/shmbutil.h
- change ADVANCE_CHAR and ADVANCE_CHAR_P macros to use is_basic and
only call mbrlen and copy state and state_bak if is_basic returns
false (non-ASCII). Called all over the place.
- change rest of macros except BACKUP_CHAR and BACKUP_CHAR_P in the
same way
12/2
----
subst.c
- audit all calls to string_list and make sure caller can handle a
NULL return value. Fixes bug reported by David Rochberg
<rochberg@google.com>
general.h
- change sh_wassign_func_t to take an additional argument: an int
flags word
subst.c
- change do_word_assignment to take an additional argument to match
wassign_func_t; change callers
- change call to (*assign_func) in expand_word_list_internal to match
new wassign_func_t prototype
- (*assign_func) passes 1 as additional arg if the simple command is
a builtin or function, in which case the assignment to the
temporary env should take effect
variables.c
- change assign_in_env to take an additional argument to match
wassign_func_t; change callers
- move call to sv_ifs from dispose_temporary_env to
dispose_used_env_vars; we don't need to do it if called from
merge_temporary_env
12/3
----
variables.c
- change dispose_temporary_env to maintain a list (tempvar_list) of
variables that need to be handled specially. If a variable that
gets freed by push_temp_var or propagate_temp_var is one of the
variables that the shell handles specially (IFS, LANG, etc.), it's
stored on the list. For each variable in this list,
dispose_temp_var calls stupidly_hack_special_variables.
- assign_in_env calls stupidly_hack_special_variables if flags arg
is non-zero, so variable assignments affect current shell
execution environment if a builtin or function is being executed.
Fixes bug reported by Bruno Haible <bruno@clisp.org>
12/5
----
subst.c
- use mbsmbchar on both string and pattern in match_pattern instead
of strlen and mbstrlen; only go through the strings once
12/6
----
lib/readline/kill.c
- in rl_yank_last_arg, only switch directions if the `count'
argument is < 0, not < 1. This makes explicit count arguments of
0 work as expected. Fixes bug reported by Dennis Williamson
<dennistwilliamson@gmail.com>
doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
- fix documentation for yank-last-arg to make it clear how the count
argument is set and how second and subsequent calls treat any
numeric argument
doc/{bash.1,bashref.texi}
- slight changes to the description of test
- change \(bv to `|'; it seems that many `internationalized' versions
of groff don't render that as a vertical bar. Fixes Debian bug
603805
+139
View File
@@ -10633,3 +10633,142 @@ lib/glob/gmisc.c
fix from Andreas Schwab <schwab@linux-m68k.org>
- use WLPAREN and WRPAREN in multibyte character environments
- fixed typos using L'cc' in a non-wide-char environment
lib/readline/complete.c
- fix rl_filename_completion_function to dequote users_dirname if
there is a filename dequoting function (as well as dirname), since
users_dirname gets tacked back onto the beginning of the possible
completions and then requoted. Bug reported by Andreas Schwab
<schwab@linux-m68k.org>
11/22
-----
lib/readline/parens.c
- the `blink-matching-paren' variable should default to off
11/23
-----
subst.h
- add extern declaration for close_new_fifos()
lib/sh/fnxform.c
- fix curencoding to return the character past the `.', not a string
beginning with `.'
lib/sh/unicode.c
- fix stub_charset to do the same cut-off at `@' as curencoding().
These two functions should be combined
builtins/printf.def
- document new %(datefmt)T modifier in help text
11/24
-----
parse.y
- fix `W' case in decode_prompt_string: memmove was copying one too
few bytes and missed the closing NUL. Bug report from Tim Mooney
<Tim.Mooney@ndsu.edu>
11/26
-----
subst.c
- in expand_word_internal, don't add quoted nulls to partially-
quoted strings if the word will not be subjected to word splitting
later (which will remove the quoted null). Fixes bug reported by
Rocky Bernstein <rocky.bernstein@gmail.com>
11/28
-----
subst.c
- change multibyte case of match_pattern to revert to match_upattern
if neither the pattern nor the string has any multibyte characters
alias.c
- fix tests of backslash-escaped characters in skipquotes, skipws,
rd_token to check for backslash at EOS and not go past the end.
Fixes debian bug 603696 reported by Tim Small <tim@buttersideup.com>
include/shmbchar.h
- new file, mbchar.h from gnulib minus the <stdbool.h> include
lib/sh/shmbchar.c
- new file, mbchar.c from gnulib with additions
- moved mbstrlen from subst.c to here, changed initialization of mbs
- change mbstrlen to use is_basic to avoid calls to mbrlen for ASCII
chars; code hints from gnulib
- don't copy mbs and mbsbak if we're not calling mbrlen
11/29
-----
lib/glob/smatch.c
- change xstrmatch to use internal_strmatch() if the pattern and
string don't have any multibyte characters
11/30
-----
include/shmbutil.h
- change ADVANCE_CHAR and ADVANCE_CHAR_P macros to use is_basic and
only call mbrlen and copy state and state_bak if is_basic returns
false (non-ASCII). Called all over the place.
- change rest of macros except BACKUP_CHAR and BACKUP_CHAR_P in the
same way
12/2
----
subst.c
- audit all calls to string_list and make sure caller can handle a
NULL return value. Fixes bug reported by David Rochberg
<rochberg@google.com>
general.h
- change sh_wassign_func_t to take an additional argument: an int
flags word
subst.c
- change do_word_assignment to take an additional argument to match
wassign_func_t; change callers
- change call to (*assign_func) in expand_word_list_internal to match
new wassign_func_t prototype
- (*assign_func) passes 1 as additional arg if the simple command is
a builtin or function, in which case the assignment to the
temporary env should take effect
variables.c
- change assign_in_env to take an additional argument to match
wassign_func_t; change callers
- move call to sv_ifs from dispose_temporary_env to
dispose_used_env_vars; we don't need to do it if called from
merge_temporary_env
12/3
----
variables.c
- change dispose_temporary_env to maintain a list (tempvar_list) of
variables that need to be handled specially. If a variable that
gets freed by push_temp_var or propagate_temp_var is one of the
variables that the shell handles specially (IFS, LANG, etc.), it's
stored on the list. For each variable in this list,
dispose_temp_var calls stupidly_hack_special_variables.
- assign_in_env calls stupidly_hack_special_variables if flags arg
is non-zero, so variable assignments affect current shell
execution environment if a builtin or function is being executed.
Fixes bug reported by Bruno Haible <bruno@clisp.org>
12/5
----
subst.c
- use mbsmbchar on both string and pattern in match_pattern instead
of strlen and mbstrlen; only go through the strings once
12/6
----
lib/readline/kill.c
- in rl_yank_last_arg, only switch directions if the `count'
argument is < 0, not < 1. This makes explicit count arguments of
0 work as expected. Fixes bug reported by Dennis Williamson
<dennistwilliamson@gmail.com>
doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
- fix documentation for yank-last-arg to make it clear how the count
argument is set and how second and subsequent calls treat any
numeric argument
+4
View File
@@ -220,6 +220,7 @@ include/posixselect.h f
include/posixstat.h f
include/posixtime.h f
include/posixwait.h f
include/shmbchar.h f
include/shmbutil.h f
include/shtty.h f
include/stdc.h f
@@ -411,6 +412,7 @@ lib/sh/pathphys.c f
lib/sh/rename.c f
lib/sh/setlinebuf.c f
lib/sh/shmatch.c f
lib/sh/shmbchar.c f
lib/sh/shquote.c f
lib/sh/shtty.c f
lib/sh/snprintf.c f
@@ -852,6 +854,7 @@ tests/exp.right f
tests/exp1.sub f
tests/exp2.sub f
tests/exp3.sub f
tests/exp4.sub f
tests/extglob.tests f
tests/extglob.right f
tests/extglob1.sub f
@@ -901,6 +904,7 @@ tests/input-line.sub f
tests/input.right f
tests/intl.tests f
tests/intl1.sub f
tests/intl2.sub f
tests/intl.right f
tests/iquote.tests f
tests/iquote.right f
+6
View File
@@ -220,6 +220,7 @@ include/posixselect.h f
include/posixstat.h f
include/posixtime.h f
include/posixwait.h f
include/shmbchar.h f
include/shmbutil.h f
include/shtty.h f
include/stdc.h f
@@ -411,6 +412,7 @@ lib/sh/pathphys.c f
lib/sh/rename.c f
lib/sh/setlinebuf.c f
lib/sh/shmatch.c f
lib/sh/shmbchar.c f
lib/sh/shquote.c f
lib/sh/shtty.c f
lib/sh/snprintf.c f
@@ -852,6 +854,7 @@ tests/exp.right f
tests/exp1.sub f
tests/exp2.sub f
tests/exp3.sub f
tests/exp4.sub f
tests/extglob.tests f
tests/extglob.right f
tests/extglob1.sub f
@@ -950,6 +953,8 @@ tests/posixexp.tests f
tests/posixexp.right f
tests/posixexp1.sub f
tests/posixexp2.sub f
tests/posixexp2.tests f
tests/posixexp2.right f
tests/posixpat.tests f
tests/posixpat.right f
tests/posixpipe.tests f
@@ -1045,6 +1050,7 @@ tests/run-nquote4 f
tests/run-nquote5 f
tests/run-posix2 f
tests/run-posixexp f
tests/run-posixexp2 f
tests/run-posixpat f
tests/run-posixpipe f
tests/run-precedence f
+6 -6
View File
@@ -215,7 +215,7 @@ SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
${SH_LIBSRC}/ufuncs.c ${SH_LIBSRC}/dprintf.c \
${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \
${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \
${SH_LIBSRC}/wcswidth.c
${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/shmbchar.c
SHLIB_LIB = -lsh
SHLIB_LIBNAME = libsh.a
@@ -973,7 +973,7 @@ make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h parser.h
make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/ocache.h
make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h ${BASHINCDIR}/ocache.h
y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
y.tab.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -988,7 +988,7 @@ pathexp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
pathexp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
pathexp.o: pathexp.h flags.h
pathexp.o: $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
pathexp.o: ${BASHINCDIR}/shmbutil.h
pathexp.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
print_cmd.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
print_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
print_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1030,7 +1030,7 @@ subst.o: flags.h jobs.h siglist.h execute_cmd.h ${BASHINCDIR}/filecntl.h trap.h
subst.o: mailcheck.h input.h $(DEFSRC)/getopt.h $(DEFSRC)/common.h
subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
subst.o: ${BASHINCDIR}/chartypes.h
subst.o: ${BASHINCDIR}/shmbutil.h
subst.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
subst.o: ${DEFDIR}/builtext.h
test.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
test.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
@@ -1089,7 +1089,7 @@ arrayfunc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
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 pathexp.h
arrayfunc.o: $(DEFSRC)/common.h
arrayfunc.o: ${BASHINCDIR}/shmbutil.h
arrayfunc.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.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
@@ -1103,7 +1103,7 @@ braces.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h
braces.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
braces.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
braces.o: make_cmd.h subst.h sig.h pathnames.h externs.h
braces.o: ${BASHINCDIR}/shmbutil.h
braces.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
alias.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
alias.o: general.h xmalloc.h bashtypes.h externs.h alias.h
alias.o: pcomplete.h
+2 -2
View File
@@ -215,7 +215,7 @@ SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
${SH_LIBSRC}/ufuncs.c ${SH_LIBSRC}/dprintf.c \
${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \
${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \
${SH_LIBSRC}/wcswidth.c
${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/shmbchar.c
SHLIB_LIB = -lsh
SHLIB_LIBNAME = libsh.a
@@ -522,7 +522,7 @@ CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \
mksyntax${EXEEXT} syntax.c $(VERSPROG) $(VERSOBJ) \
buildversion.o mksignames.o signames.o buildsignames.o
CREATED_CONFIGURE = config.h config.cache config.status config.log \
stamp-h po/POTFILES
stamp-h po/POTFILES config.status.lineno
CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
lib/readline/Makefile lib/glob/Makefile \
lib/sh/Makefile lib/tilde/Makefile lib/malloc/Makefile \
+1 -1
View File
@@ -67,7 +67,7 @@ u. History expansion no longer expands the `$!' variable expansion.
v. Posix mode shells no longer exit if a variable assignment error occurs
with an assignment preceding a command that is not a special builtin.
w. Non-interactive mode shells exit if -u is enabled an an attempt is made
w. Non-interactive mode shells exit if -u is enabled and an attempt is made
to use an unset variable with the % or # expansions, the `//', `^', or
`,' expansions, or the parameter length expansion.
+1 -1
View File
@@ -64,7 +64,7 @@ u. History expansion no longer expands the `$!' variable expansion.
v. Posix mode shells no longer exit if a variable assignment error occurs
with an assignment preceding a command that is not a special builtin.
w. Non-interactive mode shells exit if -u is enabled an an attempt is made
w. Non-interactive mode shells exit if -u is enabled and an attempt is made
to use an unset variable with the % or # expansions, the `//', `^', or
`,' expansions, or the parameter length expansion.
+6
View File
@@ -319,6 +319,8 @@ skipquotes (string, start)
if (string[i] == '\\')
{
i++; /* skip backslash-quoted quote characters, too */
if (string[i] == 0)
break;
continue;
}
@@ -364,6 +366,8 @@ skipws (string, start)
if (string[i] == '\\')
{
peekc = string[i+1];
if (peekc == 0)
break;
if (ISLETTER (peekc))
backslash_quoted_word++; /* this is a backslash-quoted word */
else
@@ -429,6 +433,8 @@ rd_token (string, start)
if (string[i] == '\\')
{
i++; /* skip backslash-escaped character */
if (string[i] == 0)
break;
continue;
}
+576
View File
@@ -0,0 +1,576 @@
/* alias.c -- Not a full alias, but just the kind that we use in the
shell. Csh style alias is somewhere else (`over there, in a box'). */
/* Copyright (C) 1987-2009 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#if defined (ALIAS)
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "chartypes.h"
#include "bashansi.h"
#include "command.h"
#include "general.h"
#include "externs.h"
#include "alias.h"
#if defined (PROGRAMMABLE_COMPLETION)
# include "pcomplete.h"
#endif
#define ALIAS_HASH_BUCKETS 16 /* must be power of two */
typedef int sh_alias_map_func_t __P((alias_t *));
static void free_alias_data __P((PTR_T));
static alias_t **map_over_aliases __P((sh_alias_map_func_t *));
static void sort_aliases __P((alias_t **));
static int qsort_alias_compare __P((alias_t **, alias_t **));
#if defined (READLINE)
static int skipquotes __P((char *, int));
static int skipws __P((char *, int));
static int rd_token __P((char *, int));
#endif
/* Non-zero means expand all words on the line. Otherwise, expand
after first expansion if the expansion ends in a space. */
int alias_expand_all = 0;
/* The list of aliases that we have. */
HASH_TABLE *aliases = (HASH_TABLE *)NULL;
void
initialize_aliases ()
{
if (aliases == 0)
aliases = hash_create (ALIAS_HASH_BUCKETS);
}
/* Scan the list of aliases looking for one with NAME. Return NULL
if the alias doesn't exist, else a pointer to the alias_t. */
alias_t *
find_alias (name)
char *name;
{
BUCKET_CONTENTS *al;
if (aliases == 0)
return ((alias_t *)NULL);
al = hash_search (name, aliases, 0);
return (al ? (alias_t *)al->data : (alias_t *)NULL);
}
/* Return the value of the alias for NAME, or NULL if there is none. */
char *
get_alias_value (name)
char *name;
{
alias_t *alias;
if (aliases == 0)
return ((char *)NULL);
alias = find_alias (name);
return (alias ? alias->value : (char *)NULL);
}
/* Make a new alias from NAME and VALUE. If NAME can be found,
then replace its value. */
void
add_alias (name, value)
char *name, *value;
{
BUCKET_CONTENTS *elt;
alias_t *temp;
int n;
if (!aliases)
{
initialize_aliases ();
temp = (alias_t *)NULL;
}
else
temp = find_alias (name);
if (temp)
{
free (temp->value);
temp->value = savestring (value);
temp->flags &= ~AL_EXPANDNEXT;
n = value[strlen (value) - 1];
if (n == ' ' || n == '\t')
temp->flags |= AL_EXPANDNEXT;
}
else
{
temp = (alias_t *)xmalloc (sizeof (alias_t));
temp->name = savestring (name);
temp->value = savestring (value);
temp->flags = 0;
n = value[strlen (value) - 1];
if (n == ' ' || n == '\t')
temp->flags |= AL_EXPANDNEXT;
elt = hash_insert (savestring (name), aliases, HASH_NOSRCH);
elt->data = temp;
#if defined (PROGRAMMABLE_COMPLETION)
set_itemlist_dirty (&it_aliases);
#endif
}
}
/* Delete a single alias structure. */
static void
free_alias_data (data)
PTR_T data;
{
register alias_t *a;
a = (alias_t *)data;
free (a->value);
free (a->name);
free (data);
}
/* Remove the alias with name NAME from the alias table. Returns
the number of aliases left in the table, or -1 if the alias didn't
exist. */
int
remove_alias (name)
char *name;
{
BUCKET_CONTENTS *elt;
if (aliases == 0)
return (-1);
elt = hash_remove (name, aliases, 0);
if (elt)
{
free_alias_data (elt->data);
free (elt->key); /* alias name */
free (elt); /* XXX */
#if defined (PROGRAMMABLE_COMPLETION)
set_itemlist_dirty (&it_aliases);
#endif
return (aliases->nentries);
}
return (-1);
}
/* Delete all aliases. */
void
delete_all_aliases ()
{
if (aliases == 0)
return;
hash_flush (aliases, free_alias_data);
hash_dispose (aliases);
aliases = (HASH_TABLE *)NULL;
#if defined (PROGRAMMABLE_COMPLETION)
set_itemlist_dirty (&it_aliases);
#endif
}
/* Return an array of aliases that satisfy the conditions tested by FUNCTION.
If FUNCTION is NULL, return all aliases. */
static alias_t **
map_over_aliases (function)
sh_alias_map_func_t *function;
{
register int i;
register BUCKET_CONTENTS *tlist;
alias_t *alias, **list;
int list_index;
i = HASH_ENTRIES (aliases);
if (i == 0)
return ((alias_t **)NULL);
list = (alias_t **)xmalloc ((i + 1) * sizeof (alias_t *));
for (i = list_index = 0; i < aliases->nbuckets; i++)
{
for (tlist = hash_items (i, aliases); tlist; tlist = tlist->next)
{
alias = (alias_t *)tlist->data;
if (!function || (*function) (alias))
{
list[list_index++] = alias;
list[list_index] = (alias_t *)NULL;
}
}
}
return (list);
}
static void
sort_aliases (array)
alias_t **array;
{
qsort (array, strvec_len ((char **)array), sizeof (alias_t *), (QSFUNC *)qsort_alias_compare);
}
static int
qsort_alias_compare (as1, as2)
alias_t **as1, **as2;
{
int result;
if ((result = (*as1)->name[0] - (*as2)->name[0]) == 0)
result = strcmp ((*as1)->name, (*as2)->name);
return (result);
}
/* Return a sorted list of all defined aliases */
alias_t **
all_aliases ()
{
alias_t **list;
if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
return ((alias_t **)NULL);
list = map_over_aliases ((sh_alias_map_func_t *)NULL);
if (list)
sort_aliases (list);
return (list);
}
char *
alias_expand_word (s)
char *s;
{
alias_t *r;
r = find_alias (s);
return (r ? savestring (r->value) : (char *)NULL);
}
/* Readline support functions -- expand all aliases in a line. */
#if defined (READLINE)
/* Return non-zero if CHARACTER is a member of the class of characters
that are self-delimiting in the shell (this really means that these
characters delimit tokens). */
#define self_delimiting(character) (member ((character), " \t\n\r;|&()"))
/* Return non-zero if CHARACTER is a member of the class of characters
that delimit commands in the shell. */
#define command_separator(character) (member ((character), "\r\n;|&("))
/* If this is 1, we are checking the next token read for alias expansion
because it is the first word in a command. */
static int command_word;
/* This is for skipping quoted strings in alias expansions. */
#define quote_char(c) (((c) == '\'') || ((c) == '"'))
/* Consume a quoted string from STRING, starting at string[START] (so
string[START] is the opening quote character), and return the index
of the closing quote character matching the opening quote character.
This handles single matching pairs of unquoted quotes; it could afford
to be a little smarter... This skips words between balanced pairs of
quotes, words where the first character is quoted with a `\', and other
backslash-escaped characters. */
static int
skipquotes (string, start)
char *string;
int start;
{
register int i;
int delimiter = string[start];
/* i starts at START + 1 because string[START] is the opening quote
character. */
for (i = start + 1 ; string[i] ; i++)
{
if (string[i] == '\\')
{
i++; /* skip backslash-quoted quote characters, too */
continue;
}
if (string[i] == delimiter)
return i;
}
return (i);
}
/* Skip the white space and any quoted characters in STRING, starting at
START. Return the new index into STRING, after zero or more characters
have been skipped. */
static int
skipws (string, start)
char *string;
int start;
{
register int i;
int pass_next, backslash_quoted_word;
unsigned char peekc;
/* skip quoted strings, in ' or ", and words in which a character is quoted
with a `\'. */
i = backslash_quoted_word = pass_next = 0;
/* Skip leading whitespace (or separator characters), and quoted words.
But save it in the output. */
for (i = start; string[i]; i++)
{
if (pass_next)
{
pass_next = 0;
continue;
}
if (whitespace (string[i]))
{
backslash_quoted_word = 0; /* we are no longer in a backslash-quoted word */
continue;
}
if (string[i] == '\\')
{
peekc = string[i+1];
if (peekc == 0)
break;
if (ISLETTER (peekc))
backslash_quoted_word++; /* this is a backslash-quoted word */
else
pass_next++;
continue;
}
/* This only handles single pairs of non-escaped quotes. This
overloads backslash_quoted_word to also mean that a word like
""f is being scanned, so that the quotes will inhibit any expansion
of the word. */
if (quote_char(string[i]))
{
i = skipquotes (string, i);
/* This could be a line that contains a single quote character,
in which case skipquotes () terminates with string[i] == '\0'
(the end of the string). Check for that here. */
if (string[i] == '\0')
break;
peekc = string[i + 1];
if (ISLETTER (peekc))
backslash_quoted_word++;
continue;
}
/* If we're in the middle of some kind of quoted word, let it
pass through. */
if (backslash_quoted_word)
continue;
/* If this character is a shell command separator, then set a hint for
alias_expand that the next token is the first word in a command. */
if (command_separator (string[i]))
{
command_word++;
continue;
}
break;
}
return (i);
}
/* Characters that may appear in a token. Basically, anything except white
space and a token separator. */
#define token_char(c) (!((whitespace (string[i]) || self_delimiting (string[i]))))
/* Read from START in STRING until the next separator character, and return
the index of that separator. Skip backslash-quoted characters. Call
skipquotes () for quoted strings in the middle or at the end of tokens,
so all characters show up (e.g. foo'' and foo""bar) */
static int
rd_token (string, start)
char *string;
int start;
{
register int i;
/* From here to next separator character is a token. */
for (i = start; string[i] && token_char (string[i]); i++)
{
if (string[i] == '\\')
{
i++; /* skip backslash-escaped character */
continue;
}
/* If this character is a quote character, we want to call skipquotes
to get the whole quoted portion as part of this word. That word
will not generally match an alias, even if te unquoted word would
have. The presence of the quotes in the token serves then to
inhibit expansion. */
if (quote_char (string[i]))
{
i = skipquotes (string, i);
/* This could be a line that contains a single quote character,
in which case skipquotes () terminates with string[i] == '\0'
(the end of the string). Check for that here. */
if (string[i] == '\0')
break;
/* Now string[i] is the matching quote character, and the
quoted portion of the token has been scanned. */
continue;
}
}
return (i);
}
/* Return a new line, with any aliases substituted. */
char *
alias_expand (string)
char *string;
{
register int i, j, start;
char *line, *token;
int line_len, tl, real_start, expand_next, expand_this_token;
alias_t *alias;
line_len = strlen (string) + 1;
line = (char *)xmalloc (line_len);
token = (char *)xmalloc (line_len);
line[0] = i = 0;
expand_next = 0;
command_word = 1; /* initialized to expand the first word on the line */
/* Each time through the loop we find the next word in line. If it
has an alias, substitute the alias value. If the value ends in ` ',
then try again with the next word. Else, if there is no value, or if
the value does not end in space, we are done. */
for (;;)
{
token[0] = 0;
start = i;
/* Skip white space and quoted characters */
i = skipws (string, start);
if (start == i && string[i] == '\0')
{
free (token);
return (line);
}
/* copy the just-skipped characters into the output string,
expanding it if there is not enough room. */
j = strlen (line);
tl = i - start; /* number of characters just skipped */
RESIZE_MALLOCED_BUFFER (line, j, (tl + 1), line_len, (tl + 50));
strncpy (line + j, string + start, tl);
line[j + tl] = '\0';
real_start = i;
command_word = command_word || (command_separator (string[i]));
expand_this_token = (command_word || expand_next);
expand_next = 0;
/* Read the next token, and copy it into TOKEN. */
start = i;
i = rd_token (string, start);
tl = i - start; /* token length */
/* If tl == 0, but we're not at the end of the string, then we have a
single-character token, probably a delimiter */
if (tl == 0 && string[i] != '\0')
{
tl = 1;
i++; /* move past it */
}
strncpy (token, string + start, tl);
token [tl] = '\0';
/* If there is a backslash-escaped character quoted in TOKEN,
then we don't do alias expansion. This should check for all
other quoting characters, too. */
if (mbschr (token, '\\'))
expand_this_token = 0;
/* If we should be expanding here, if we are expanding all words, or if
we are in a location in the string where an expansion is supposed to
take place, see if this word has a substitution. If it does, then do
the expansion. Note that we defer the alias value lookup until we
are sure we are expanding this token. */
if ((token[0]) &&
(expand_this_token || alias_expand_all) &&
(alias = find_alias (token)))
{
char *v;
int vlen, llen;
v = alias->value;
vlen = strlen (v);
llen = strlen (line);
/* +3 because we possibly add one more character below. */
RESIZE_MALLOCED_BUFFER (line, llen, (vlen + 3), line_len, (vlen + 50));
strcpy (line + llen, v);
if ((expand_this_token && vlen && whitespace (v[vlen - 1])) ||
alias_expand_all)
expand_next = 1;
}
else
{
int llen, tlen;
llen = strlen (line);
tlen = i - real_start; /* tlen == strlen(token) */
RESIZE_MALLOCED_BUFFER (line, llen, (tlen + 1), line_len, (llen + tlen + 50));
strncpy (line + llen, string + real_start, tlen);
line[llen + tlen] = '\0';
}
command_word = 0;
}
}
#endif /* READLINE */
#endif /* ALIAS */
+1 -1
View File
@@ -1,4 +1,4 @@
/* evalstring.c - evaluate a string as one or more shell commands.
/* evalstring.c - evaluate a string as one or more shell commands. */
/* Copyright (C) 1996-2010 Free Software Foundation, Inc.
+2
View File
@@ -40,6 +40,8 @@ and printf(3), printf interprets:
%b expand backslash escape sequences in the corresponding argument
%q quote the argument in a way that can be reused as shell input
%(fmt)T output the date-time string resulting from using FMT as a format
string for strftime(3)
Exit Status:
Returns success unless an invalid option is given or a write or assignment
+4 -1
View File
@@ -28,7 +28,10 @@ Evaluate conditional expression.
Exits with a status of 0 (true) or 1 (false) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators as well, and numeric comparison operators.
are string operators and numeric comparison operators as well.
The behavior of test depends on the number of arguments. Read the
bash manual page for the complete specification.
File operators:
+1 -1
View File
@@ -1,7 +1,7 @@
This file is test.def, from which is created test.c.
It implements the builtin "test" in Bash.
Copyright (C) 1987-2009 Free Software Foundation, Inc.
Copyright (C) 1987-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
+20 -18
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
.\" Last Change: Mon Sep 6 22:07:38 EDT 2010
.\" Last Change: Mon Dec 6 22:25:10 EST 2010
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2010 September 6" "GNU Bash-4.2"
.TH BASH 1 "2010 December 6" "GNU Bash-4.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -476,7 +476,7 @@ A \fItoken\fP that performs a control function. It is one of the following
symbols:
.RS
.PP
.if t \fB\(bv\(bv & && ; ;; ( ) | |& <newline>\fP
.if t \fB|| & && ; ;; ( ) | |& <newline>\fP
.if n \fB|| & && ; ;; ( ) | |& <newline>\fP
.RE
.PD
@@ -586,7 +586,7 @@ of the operators
.BR & ,
.BR && ,
or
.BR \(bv\(bv ,
.BR || ,
and optionally terminated by one of
.BR ; ,
.BR & ,
@@ -596,7 +596,7 @@ or
Of these list operators,
.B &&
and
.B \(bv\(bv
.B ||
have equal precedence, followed by
.B ;
and
@@ -617,7 +617,7 @@ command to terminate in turn. The return status is the
exit status of the last command executed.
.PP
AND and OR lists are sequences of one of more pipelines separated by the
\fB&&\fP and \fB\(bv\(bv\fP control operators, respectively.
\fB&&\fP and \fB||\fP control operators, respectively.
AND and OR lists are executed with left associativity.
An AND list has the form
.RS
@@ -633,7 +633,7 @@ returns an exit status of zero.
An OR list has the form
.RS
.PP
\fIcommand1\fP \fB\(bv\(bv\fP \fIcommand2\fP
\fIcommand1\fP \fB||\fP \fIcommand2\fP
.PP
.RE
.PP
@@ -763,8 +763,7 @@ and
.I expression2
are true.
.TP
.if t \fIexpression1\fP \fB\(bv\(bv\fP \fIexpression2\fP
.if n \fIexpression1\fP \fB||\fP \fIexpression2\fP
\fIexpression1\fP \fB||\fP \fIexpression2\fP
True if either
.I expression1
or
@@ -772,9 +771,7 @@ or
is true.
.PD
.LP
The \fB&&\fP and
.if t \fB\(bv\(bv\fP
.if n \fB||\fP
The \fB&&\fP and \fB||\fP
operators do not evaluate \fIexpression2\fP if the value of
\fIexpression1\fP is sufficient to determine the return value of
the entire conditional expression.
@@ -5508,10 +5505,14 @@ as if the "!\fIn\fP" history expansion had been specified.
.B
yank\-last\-arg (M\-.\^, M\-_\^)
Insert the last argument to the previous command (the last word of
the previous history entry). With an argument,
behave exactly like \fByank\-nth\-arg\fP.
the previous history entry).
With a numeric argument, behave exactly like \fByank\-nth\-arg\fP.
Successive calls to \fByank\-last\-arg\fP move back through the history
list, inserting the last argument of each line in turn.
list, inserting the last word (or the word specified by the argument to
the first call) of each line in turn.
Any numeric argument supplied to these successive calls determines
the direction to move through the history. A negative argument switches
the direction through the history (back or forward).
The history expansion facilities are used to extract the last argument,
as if the "!$" history expansion had been specified.
.TP
@@ -8476,8 +8477,8 @@ or
reserved words, part of any command executed in a
.B &&
or
.B \(bv\(bv
list except the command following the final \fB&&\fP or \fB\(bv\(bv\fP,
.B ||
list except the command following the final \fB&&\fP or \fB||\fP,
any command in a pipeline but the last,
or if the command's return value is
being inverted with
@@ -9262,6 +9263,7 @@ If the first argument is not a valid unary conditional operator, the expression
is false.
.TP
3 arguments
The following conditions are applied in the order listed.
If the second argument is one of the binary conditional operators listed above
under
.SM
@@ -9394,7 +9396,7 @@ part of the test in an
statement, part of a command executed in a
.B &&
or
.B \(bv\(bv
.B ||
list, or if the command's return value is
being inverted via
.BR ! .
+10 -5
View File
@@ -5508,10 +5508,14 @@ as if the "!\fIn\fP" history expansion had been specified.
.B
yank\-last\-arg (M\-.\^, M\-_\^)
Insert the last argument to the previous command (the last word of
the previous history entry). With an argument,
behave exactly like \fByank\-nth\-arg\fP.
the previous history entry).
With a numeric argument, behave exactly like \fByank\-nth\-arg\fP.
Successive calls to \fByank\-last\-arg\fP move back through the history
list, inserting the last argument of each line in turn.
list, inserting the last word (or the word specified by the argument to
the first call) of each line in turn.
Any numeric argument supplied to these successive calls determines
the direction to move through the history. A negative argument switches
the direction through the history (back or forward).
The history expansion facilities are used to extract the last argument,
as if the "!$" history expansion had been specified.
.TP
@@ -9210,6 +9214,7 @@ an argument of \fB\-\-\fP as signifying the end of options.
Expressions may be combined using the following operators, listed
in decreasing order of precedence.
The evaluation depends on the number of arguments; see below.
Operator precedence is used when there are five or more arguments.
.RS
.PD 0
.TP
@@ -9366,8 +9371,8 @@ is
.BR RETURN ,
the command
.I arg
is executed each time a shell function or a script executed with the
\fB.\fP or \fBsource\fP builtins finishes executing.
is executed each time a shell function or a script executed with
the \fB.\fP or \fBsource\fP builtins finishes executing.
.if t .sp 0.5
.if n .sp 1
If a
+1
View File
@@ -3239,6 +3239,7 @@ If the first argument is not a valid unary operator, the expression is
false.
@item 3 arguments
The following conditions are applied in the order listed.
If the second argument is one of the binary conditional
operators (@pxref{Bash Conditional Expressions}), the
result of the expression is the result of the binary test using the
+7 -13
View File
@@ -1717,7 +1717,7 @@ Bash uses the value of the variable formed from the rest of
expanded and that value is used in the rest of the substitution, rather
than the value of @var{parameter} itself.
This is known as @code{indirect expansion}.
The exceptions to this are the expansions of $@{!@var{prefix}@*}
The exceptions to this are the expansions of $@{!@var{prefix}@*@}
and $@{!@var{name}[@@]@}
described below.
The exclamation point must immediately follow the left brace in order to
@@ -3202,6 +3202,7 @@ be a @code{]}.
Expressions may be combined using the following operators, listed in
decreasing order of precedence.
The evaluation depends on the number of arguments; see below.
Operator precedence is used when there are five or more arguments.
@table @code
@item ! @var{expr}
@@ -6694,14 +6695,6 @@ the @sc{posix} standard, and include things like passing incorrect options,
redirection errors, variable assignment errors for assignments preceding
the command name, and so on.
@item
If @env{CDPATH} is set, the @code{cd} builtin will not implicitly
append the current directory to it. This means that @code{cd} will
fail if no valid directory name can be constructed from
any of the entries in @env{$CDPATH}, even if the a directory with
the same name as the name given as an argument to @code{cd} exists
in the current directory.
@item
A non-interactive shell exits with an error status if a variable
assignment error occurs when no command name follows the assignment
@@ -6709,6 +6702,11 @@ statements.
A variable assignment error occurs, for example, when trying to assign
a value to a readonly variable.
@item
A non-interactive shell exists with an error status if a variable
assignment error occurs in an assignment statement preceding a special
builtin, but not with any other simple command.
@item
A non-interactive shell exits with an error status if the iteration
variable in a @code{for} statement or the selection variable in a
@@ -6774,10 +6772,6 @@ constructed from @code{$PWD} and the directory name supplied as an argument
does not refer to an existing directory, @code{cd} will fail instead of
falling back to @var{physical} mode.
@item
When the @code{pwd} builtin is supplied the @option{-P} option, it resets
@code{$PWD} to a pathname containing no symlinks.
@item
The @code{pwd} builtin verifies that the value it prints is the same as the
current directory, even if it is not asked to check the file system with the
+4
View File
@@ -303,6 +303,10 @@ extern int sh_regmatch __P((const char *, const char *, int));
#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */
#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */
/* declarations for functions defined in lib/sh/shmbchar.c */
extern size_t mbstrlen __P((const char *));
extern char *mbsmbchar __P((const char *));
/* declarations for functions defined in lib/sh/shquote.c */
extern char *sh_single_quote __P((const char *));
extern char *sh_double_quote __P((const char *));
+5 -2
View File
@@ -303,9 +303,12 @@ extern int sh_regmatch __P((const char *, const char *, int));
#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */
#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */
/* declarations for functions defined in lib/sh/shmbchar.c */
extern size_t mbstrlen __P((const char *));
/* declarations for functions defined in lib/sh/shquote.c */
extern char *sh_single_quote __P((char *));
extern char *sh_double_quote __P((char *));
extern char *sh_single_quote __P((const char *));
extern char *sh_double_quote __P((const char *));
extern char *sh_mkdoublequoted __P((const char *, int, int));
extern char *sh_un_double_quote __P((char *));
extern char *sh_backslash_quote __P((char *));
+2 -2
View File
@@ -216,8 +216,8 @@ typedef void sh_resetsig_func_t __P((int)); /* sh_vintfunc_t */
typedef int sh_ignore_func_t __P((const char *)); /* sh_icpfunc_t */
typedef int sh_assign_func_t __P((const char *)); /* sh_icpfunc_t */
typedef int sh_wassign_func_t __P((WORD_DESC *));
typedef int sh_assign_func_t __P((const char *));
typedef int sh_wassign_func_t __P((WORD_DESC *, int));
typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */
+325
View File
@@ -0,0 +1,325 @@
/* general.h -- defines that everybody likes to use. */
/* Copyright (C) 1993-2009 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (_GENERAL_H_)
#define _GENERAL_H_
#include "stdc.h"
#include "bashtypes.h"
#include "chartypes.h"
#if defined (HAVE_SYS_RESOURCE_H) && defined (RLIMTYPE)
# if defined (HAVE_SYS_TIME_H)
# include <sys/time.h>
# endif
# include <sys/resource.h>
#endif
#if defined (HAVE_STRING_H)
# include <string.h>
#else
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
#include "xmalloc.h"
/* NULL pointer type. */
#if !defined (NULL)
# if defined (__STDC__)
# define NULL ((void *) 0)
# else
# define NULL 0x0
# endif /* !__STDC__ */
#endif /* !NULL */
/* Hardly used anymore */
#define pointer_to_int(x) (int)((char *)x - (char *)0)
#if defined (alpha) && defined (__GNUC__) && !defined (strchr) && !defined (__STDC__)
extern char *strchr (), *strrchr ();
#endif
#if !defined (strcpy) && (defined (HAVE_DECL_STRCPY) && !HAVE_DECL_STRCPY)
extern char *strcpy __P((char *, const char *));
#endif
#if !defined (savestring)
# define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
#endif
#ifndef member
# define member(c, s) ((c) ? ((char *)mbschr ((s), (c)) != (char *)NULL) : 0)
#endif
#ifndef whitespace
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif
#ifndef CHAR_MAX
# ifdef __CHAR_UNSIGNED__
# define CHAR_MAX 0xff
# else
# define CHAR_MAX 0x7f
# endif
#endif
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
/* Nonzero if the integer type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* Bound on length of the string representing an integer value of type T.
Subtract one for the sign bit if T is signed;
302 / 1000 is log10 (2) rounded up;
add one for integer division truncation;
add one more for a minus sign if t is signed. */
#define INT_STRLEN_BOUND(t) \
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
+ 1 + TYPE_SIGNED (t))
/* Define exactly what a legal shell identifier consists of. */
#define legal_variable_starter(c) (ISALPHA(c) || (c == '_'))
#define legal_variable_char(c) (ISALNUM(c) || c == '_')
/* Definitions used in subst.c and by the `read' builtin for field
splitting. */
#define spctabnl(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
/* All structs which contain a `next' field should have that field
as the first field in the struct. This means that functions
can be written to handle the general case for linked lists. */
typedef struct g_list {
struct g_list *next;
} GENERIC_LIST;
/* Here is a generic structure for associating character strings
with integers. It is used in the parser for shell tokenization. */
typedef struct {
char *word;
int token;
} STRING_INT_ALIST;
/* A macro to avoid making an uneccessary function call. */
#define REVERSE_LIST(list, type) \
((list && list->next) ? (type)list_reverse ((GENERIC_LIST *)list) \
: (type)(list))
#if __GNUC__ > 1
# define FASTCOPY(s, d, n) __builtin_memcpy ((d), (s), (n))
#else /* !__GNUC__ */
# if !defined (HAVE_BCOPY)
# if !defined (HAVE_MEMMOVE)
# define FASTCOPY(s, d, n) memcpy ((d), (s), (n))
# else
# define FASTCOPY(s, d, n) memmove ((d), (s), (n))
# endif /* !HAVE_MEMMOVE */
# else /* HAVE_BCOPY */
# define FASTCOPY(s, d, n) bcopy ((s), (d), (n))
# endif /* HAVE_BCOPY */
#endif /* !__GNUC__ */
/* String comparisons that possibly save a function call each. */
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
#define STREQN(a, b, n) ((n == 0) ? (1) \
: ((a)[0] == (b)[0] && strncmp(a, b, n) == 0))
/* More convenience definitions that possibly save system or libc calls. */
#define STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
#define FREE(s) do { if (s) free (s); } while (0)
#define MEMBER(c, s) (((c) && c == (s)[0] && !(s)[1]) || (member(c, s)))
/* A fairly hairy macro to check whether an allocated string has more room,
and to resize it using xrealloc if it does not.
STR is the string (char *)
CIND is the current index into the string (int)
ROOM is the amount of additional room we need in the string (int)
CSIZE is the currently-allocated size of STR (int)
SINCR is how much to increment CSIZE before calling xrealloc (int) */
#define RESIZE_MALLOCED_BUFFER(str, cind, room, csize, sincr) \
do { \
if ((cind) + (room) >= csize) \
{ \
while ((cind) + (room) >= csize) \
csize += (sincr); \
str = xrealloc (str, csize); \
} \
} while (0)
/* Function pointers can be declared as (Function *)foo. */
#if !defined (_FUNCTION_DEF)
# define _FUNCTION_DEF
typedef int Function ();
typedef void VFunction ();
typedef char *CPFunction (); /* no longer used */
typedef char **CPPFunction (); /* no longer used */
#endif /* _FUNCTION_DEF */
#ifndef SH_FUNCTION_TYPEDEF
# define SH_FUNCTION_TYPEDEF
/* Shell function typedefs with prototypes */
/* `Generic' function pointer typedefs */
typedef int sh_intfunc_t __P((int));
typedef int sh_ivoidfunc_t __P((void));
typedef int sh_icpfunc_t __P((char *));
typedef int sh_icppfunc_t __P((char **));
typedef int sh_iptrfunc_t __P((PTR_T));
typedef void sh_voidfunc_t __P((void));
typedef void sh_vintfunc_t __P((int));
typedef void sh_vcpfunc_t __P((char *));
typedef void sh_vcppfunc_t __P((char **));
typedef void sh_vptrfunc_t __P((PTR_T));
typedef int sh_wdesc_func_t __P((WORD_DESC *));
typedef int sh_wlist_func_t __P((WORD_LIST *));
typedef int sh_glist_func_t __P((GENERIC_LIST *));
typedef char *sh_string_func_t __P((char *)); /* like savestring, et al. */
typedef int sh_msg_func_t __P((const char *, ...)); /* printf(3)-like */
typedef void sh_vmsg_func_t __P((const char *, ...)); /* printf(3)-like */
/* Specific function pointer typedefs. Most of these could be done
with #defines. */
typedef void sh_sv_func_t __P((char *)); /* sh_vcpfunc_t */
typedef void sh_free_func_t __P((PTR_T)); /* sh_vptrfunc_t */
typedef void sh_resetsig_func_t __P((int)); /* sh_vintfunc_t */
typedef int sh_ignore_func_t __P((const char *)); /* sh_icpfunc_t */
typedef int sh_assign_func_t __P((const char *, int));
typedef int sh_wassign_func_t __P((WORD_DESC *));
typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */
#endif /* SH_FUNCTION_TYPEDEF */
#define NOW ((time_t) time ((time_t *) 0))
/* Some defines for calling file status functions. */
#define FS_EXISTS 0x1
#define FS_EXECABLE 0x2
#define FS_EXEC_PREFERRED 0x4
#define FS_EXEC_ONLY 0x8
#define FS_DIRECTORY 0x10
#define FS_NODIRS 0x20
#define FS_READABLE 0x40
/* Default maximum for move_to_high_fd */
#define HIGH_FD_MAX 256
/* The type of function passed as the fourth argument to qsort(3). */
#ifdef __STDC__
typedef int QSFUNC (const void *, const void *);
#else
typedef int QSFUNC ();
#endif
/* Some useful definitions for Unix pathnames. Argument convention:
x == string, c == character */
#if !defined (__CYGWIN__)
# define ABSPATH(x) ((x)[0] == '/')
# define RELPATH(x) ((x)[0] != '/')
#else /* __CYGWIN__ */
# define ABSPATH(x) (((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':') || ISDIRSEP((x)[0]))
# define RELPATH(x) (ABSPATH(x) == 0)
#endif /* __CYGWIN__ */
#define ROOTEDPATH(x) (ABSPATH(x))
#define DIRSEP '/'
#if !defined (__CYGWIN__)
# define ISDIRSEP(c) ((c) == '/')
#else
# define ISDIRSEP(c) ((c) == '/' || (c) == '\\')
#endif /* __CYGWIN__ */
#define PATHSEP(c) (ISDIRSEP(c) || (c) == 0)
#if 0
/* Declarations for functions defined in xmalloc.c */
extern PTR_T xmalloc __P((size_t));
extern PTR_T xrealloc __P((void *, size_t));
extern void xfree __P((void *));
#endif
/* Declarations for functions defined in general.c */
extern void posix_initialize __P((int));
#if defined (RLIMTYPE)
extern RLIMTYPE string_to_rlimtype __P((char *));
extern void print_rlimtype __P((RLIMTYPE, int));
#endif
extern int all_digits __P((char *));
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));
extern int assignment __P((const char *, int));
extern int sh_unset_nodelay_mode __P((int));
extern int sh_validfd __P((int));
extern void check_dev_tty __P((void));
extern int move_to_high_fd __P((int, int, int));
extern int check_binary_file __P((char *, int));
#ifdef _POSIXSTAT_H_
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_exists __P((char *));
extern int file_isdir __P((char *));
extern int file_iswdir __P((char *));
extern int absolute_pathname __P((const char *));
extern int absolute_program __P((const char *));
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 *));
extern void tilde_initialize __P((void));
extern char *bash_tilde_find_word __P((const char *, int, int *));
extern char *bash_tilde_expand __P((const char *, int));
extern int group_member __P((gid_t));
extern char **get_group_list __P((int *));
extern int *get_group_array __P((int *));
#endif /* _GENERAL_H_ */
+350
View File
@@ -0,0 +1,350 @@
/* Multibyte character data type.
Copyright (C) 2001, 2005-2007, 2009-2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>. */
/* A multibyte character is a short subsequence of a char* string,
representing a single wide character.
We use multibyte characters instead of wide characters because of
the following goals:
1) correct multibyte handling, i.e. operate according to the LC_CTYPE
locale,
2) ease of maintenance, i.e. the maintainer needs not know all details
of the ISO C 99 standard,
3) don't fail grossly if the input is not in the encoding set by the
locale, because often different encodings are in use in the same
countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...),
4) fast in the case of ASCII characters,
5) portability, i.e. don't make unportable assumptions about wchar_t.
Multibyte characters are only accessed through the mb* macros.
mb_ptr (mbc)
return a pointer to the beginning of the multibyte sequence.
mb_len (mbc)
returns the number of bytes occupied by the multibyte sequence.
Always > 0.
mb_iseq (mbc, sc)
returns true if mbc is the standard ASCII character sc.
mb_isnul (mbc)
returns true if mbc is the nul character.
mb_cmp (mbc1, mbc2)
returns a positive, zero, or negative value depending on whether mbc1
sorts after, same or before mbc2.
mb_casecmp (mbc1, mbc2)
returns a positive, zero, or negative value depending on whether mbc1
sorts after, same or before mbc2, modulo upper/lowercase conversion.
mb_equal (mbc1, mbc2)
returns true if mbc1 and mbc2 are equal.
mb_caseequal (mbc1, mbc2)
returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion.
mb_isalnum (mbc)
returns true if mbc is alphanumeric.
mb_isalpha (mbc)
returns true if mbc is alphabetic.
mb_isascii(mbc)
returns true if mbc is plain ASCII.
mb_isblank (mbc)
returns true if mbc is a blank.
mb_iscntrl (mbc)
returns true if mbc is a control character.
mb_isdigit (mbc)
returns true if mbc is a decimal digit.
mb_isgraph (mbc)
returns true if mbc is a graphic character.
mb_islower (mbc)
returns true if mbc is lowercase.
mb_isprint (mbc)
returns true if mbc is a printable character.
mb_ispunct (mbc)
returns true if mbc is a punctuation character.
mb_isspace (mbc)
returns true if mbc is a space character.
mb_isupper (mbc)
returns true if mbc is uppercase.
mb_isxdigit (mbc)
returns true if mbc is a hexadecimal digit.
mb_width (mbc)
returns the number of columns on the output device occupied by mbc.
Always >= 0.
mb_putc (mbc, stream)
outputs mbc on stream, a byte oriented FILE stream opened for output.
mb_setascii (&mbc, sc)
assigns the standard ASCII character sc to mbc.
mb_copy (&destmbc, &srcmbc)
copies srcmbc to destmbc.
Here are the function prototypes of the macros.
typedef int bool;
extern const char * mb_ptr (const mbchar_t mbc);
extern size_t mb_len (const mbchar_t mbc);
extern bool mb_iseq (const mbchar_t mbc, char sc);
extern bool mb_isnul (const mbchar_t mbc);
extern int mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2);
extern int mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2);
extern bool mb_equal (const mbchar_t mbc1, const mbchar_t mbc2);
extern bool mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2);
extern bool mb_isalnum (const mbchar_t mbc);
extern bool mb_isalpha (const mbchar_t mbc);
extern bool mb_isascii (const mbchar_t mbc);
extern bool mb_isblank (const mbchar_t mbc);
extern bool mb_iscntrl (const mbchar_t mbc);
extern bool mb_isdigit (const mbchar_t mbc);
extern bool mb_isgraph (const mbchar_t mbc);
extern bool mb_islower (const mbchar_t mbc);
extern bool mb_isprint (const mbchar_t mbc);
extern bool mb_ispunct (const mbchar_t mbc);
extern bool mb_isspace (const mbchar_t mbc);
extern bool mb_isupper (const mbchar_t mbc);
extern bool mb_isxdigit (const mbchar_t mbc);
extern int mb_width (const mbchar_t mbc);
extern void mb_putc (const mbchar_t mbc, FILE *stream);
extern void mb_setascii (mbchar_t *new, char sc);
extern void mb_copy (mbchar_t *new, const mbchar_t *old);
*/
#ifndef _SHMBCHAR_H
#define _SHMBCHAR_H 1
#include <string.h>
/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
<wchar.h>.
BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
<wchar.h>. */
#include <stdio.h>
#include <time.h>
#include <wchar.h>
#include <wctype.h>
#define MBCHAR_BUF_SIZE 24
struct mbchar
{
const char *ptr; /* pointer to current character */
size_t bytes; /* number of bytes of current character, > 0 */
int wc_valid; /* true if wc is a valid wide character */
wchar_t wc; /* if wc_valid: the current character */
char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */
};
/* EOF (not a real character) is represented with bytes = 0 and
wc_valid = false. */
typedef struct mbchar mbchar_t;
/* Access the current character. */
#define mb_ptr(mbc) ((mbc).ptr)
#define mb_len(mbc) ((mbc).bytes)
/* Comparison of characters. */
#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc))
#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0)
#define mb_cmp(mbc1, mbc2) \
((mbc1).wc_valid \
? ((mbc2).wc_valid \
? (int) (mbc1).wc - (int) (mbc2).wc \
: -1) \
: ((mbc2).wc_valid \
? 1 \
: (mbc1).bytes == (mbc2).bytes \
? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
: (mbc1).bytes < (mbc2).bytes \
? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
: (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
#define mb_casecmp(mbc1, mbc2) \
((mbc1).wc_valid \
? ((mbc2).wc_valid \
? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc) \
: -1) \
: ((mbc2).wc_valid \
? 1 \
: (mbc1).bytes == (mbc2).bytes \
? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
: (mbc1).bytes < (mbc2).bytes \
? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
: (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
#define mb_equal(mbc1, mbc2) \
((mbc1).wc_valid && (mbc2).wc_valid \
? (mbc1).wc == (mbc2).wc \
: (mbc1).bytes == (mbc2).bytes \
&& memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
#define mb_caseequal(mbc1, mbc2) \
((mbc1).wc_valid && (mbc2).wc_valid \
? towlower ((mbc1).wc) == towlower ((mbc2).wc) \
: (mbc1).bytes == (mbc2).bytes \
&& memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
/* <ctype.h>, <wctype.h> classification. */
#define mb_isascii(mbc) \
((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127)
#define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc))
#define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc))
#define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc))
#define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc))
#define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc))
#define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc))
#define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc))
#define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc))
#define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc))
#define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc))
#define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc))
#define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc))
/* Extra <wchar.h> function. */
/* Unprintable characters appear as a small box of width 1. */
#define MB_UNPRINTABLE_WIDTH 1
static inline int
mb_width_aux (wint_t wc)
{
int w = wcwidth (wc);
/* For unprintable characters, arbitrarily return 0 for control characters
and MB_UNPRINTABLE_WIDTH otherwise. */
return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH);
}
#define mb_width(mbc) \
((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH)
/* Output. */
#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream))
/* Assignment. */
#define mb_setascii(mbc, sc) \
((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \
(mbc)->wc = (mbc)->buf[0] = (sc))
/* Copying a character. */
static inline void
mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc)
{
if (old_mbc->ptr == &old_mbc->buf[0])
{
memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes);
new_mbc->ptr = &new_mbc->buf[0];
}
else
new_mbc->ptr = old_mbc->ptr;
new_mbc->bytes = old_mbc->bytes;
if ((new_mbc->wc_valid = old_mbc->wc_valid))
new_mbc->wc = old_mbc->wc;
}
/* is_basic(c) tests whether the single-byte character c is in the
ISO C "basic character set".
This is a convenience function, and is in this file only to share code
between mbiter_multi.h and mbfile_multi.h. */
#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
/* The character set is ISO-646, not EBCDIC. */
# define IS_BASIC_ASCII 1
extern const unsigned int is_basic_table[];
static inline int
is_basic (char c)
{
return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31))
& 1;
}
#else
static inline int
is_basic (char c)
{
switch (c)
{
case '\t': case '\v': case '\f':
case ' ': case '!': case '"': case '#': case '%':
case '&': case '\'': case '(': case ')': case '*':
case '+': case ',': case '-': case '.': case '/':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case ':': case ';': case '<': case '=': case '>':
case '?':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z':
case '[': case '\\': case ']': case '^': case '_':
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z': case '{': case '|': case '}': case '~':
return 1;
default:
return 0;
}
}
#endif
#endif /* _SHMBCHAR_H */
+350
View File
@@ -0,0 +1,350 @@
/* Multibyte character data type.
Copyright (C) 2001, 2005-2007, 2009-2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>. */
/* A multibyte character is a short subsequence of a char* string,
representing a single wide character.
We use multibyte characters instead of wide characters because of
the following goals:
1) correct multibyte handling, i.e. operate according to the LC_CTYPE
locale,
2) ease of maintenance, i.e. the maintainer needs not know all details
of the ISO C 99 standard,
3) don't fail grossly if the input is not in the encoding set by the
locale, because often different encodings are in use in the same
countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...),
4) fast in the case of ASCII characters,
5) portability, i.e. don't make unportable assumptions about wchar_t.
Multibyte characters are only accessed through the mb* macros.
mb_ptr (mbc)
return a pointer to the beginning of the multibyte sequence.
mb_len (mbc)
returns the number of bytes occupied by the multibyte sequence.
Always > 0.
mb_iseq (mbc, sc)
returns true if mbc is the standard ASCII character sc.
mb_isnul (mbc)
returns true if mbc is the nul character.
mb_cmp (mbc1, mbc2)
returns a positive, zero, or negative value depending on whether mbc1
sorts after, same or before mbc2.
mb_casecmp (mbc1, mbc2)
returns a positive, zero, or negative value depending on whether mbc1
sorts after, same or before mbc2, modulo upper/lowercase conversion.
mb_equal (mbc1, mbc2)
returns true if mbc1 and mbc2 are equal.
mb_caseequal (mbc1, mbc2)
returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion.
mb_isalnum (mbc)
returns true if mbc is alphanumeric.
mb_isalpha (mbc)
returns true if mbc is alphabetic.
mb_isascii(mbc)
returns true if mbc is plain ASCII.
mb_isblank (mbc)
returns true if mbc is a blank.
mb_iscntrl (mbc)
returns true if mbc is a control character.
mb_isdigit (mbc)
returns true if mbc is a decimal digit.
mb_isgraph (mbc)
returns true if mbc is a graphic character.
mb_islower (mbc)
returns true if mbc is lowercase.
mb_isprint (mbc)
returns true if mbc is a printable character.
mb_ispunct (mbc)
returns true if mbc is a punctuation character.
mb_isspace (mbc)
returns true if mbc is a space character.
mb_isupper (mbc)
returns true if mbc is uppercase.
mb_isxdigit (mbc)
returns true if mbc is a hexadecimal digit.
mb_width (mbc)
returns the number of columns on the output device occupied by mbc.
Always >= 0.
mb_putc (mbc, stream)
outputs mbc on stream, a byte oriented FILE stream opened for output.
mb_setascii (&mbc, sc)
assigns the standard ASCII character sc to mbc.
mb_copy (&destmbc, &srcmbc)
copies srcmbc to destmbc.
Here are the function prototypes of the macros.
extern const char * mb_ptr (const mbchar_t mbc);
extern size_t mb_len (const mbchar_t mbc);
extern bool mb_iseq (const mbchar_t mbc, char sc);
extern bool mb_isnul (const mbchar_t mbc);
extern int mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2);
extern int mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2);
extern bool mb_equal (const mbchar_t mbc1, const mbchar_t mbc2);
extern bool mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2);
extern bool mb_isalnum (const mbchar_t mbc);
extern bool mb_isalpha (const mbchar_t mbc);
extern bool mb_isascii (const mbchar_t mbc);
extern bool mb_isblank (const mbchar_t mbc);
extern bool mb_iscntrl (const mbchar_t mbc);
extern bool mb_isdigit (const mbchar_t mbc);
extern bool mb_isgraph (const mbchar_t mbc);
extern bool mb_islower (const mbchar_t mbc);
extern bool mb_isprint (const mbchar_t mbc);
extern bool mb_ispunct (const mbchar_t mbc);
extern bool mb_isspace (const mbchar_t mbc);
extern bool mb_isupper (const mbchar_t mbc);
extern bool mb_isxdigit (const mbchar_t mbc);
extern int mb_width (const mbchar_t mbc);
extern void mb_putc (const mbchar_t mbc, FILE *stream);
extern void mb_setascii (mbchar_t *new, char sc);
extern void mb_copy (mbchar_t *new, const mbchar_t *old);
*/
#ifndef _MBCHAR_H
#define _MBCHAR_H 1
#include <stdbool.h>
#include <string.h>
/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
<wchar.h>.
BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
<wchar.h>. */
#include <stdio.h>
#include <time.h>
#include <wchar.h>
#include <wctype.h>
#define MBCHAR_BUF_SIZE 24
struct mbchar
{
const char *ptr; /* pointer to current character */
size_t bytes; /* number of bytes of current character, > 0 */
bool wc_valid; /* true if wc is a valid wide character */
wchar_t wc; /* if wc_valid: the current character */
char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */
};
/* EOF (not a real character) is represented with bytes = 0 and
wc_valid = false. */
typedef struct mbchar mbchar_t;
/* Access the current character. */
#define mb_ptr(mbc) ((mbc).ptr)
#define mb_len(mbc) ((mbc).bytes)
/* Comparison of characters. */
#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc))
#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0)
#define mb_cmp(mbc1, mbc2) \
((mbc1).wc_valid \
? ((mbc2).wc_valid \
? (int) (mbc1).wc - (int) (mbc2).wc \
: -1) \
: ((mbc2).wc_valid \
? 1 \
: (mbc1).bytes == (mbc2).bytes \
? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
: (mbc1).bytes < (mbc2).bytes \
? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
: (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
#define mb_casecmp(mbc1, mbc2) \
((mbc1).wc_valid \
? ((mbc2).wc_valid \
? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc) \
: -1) \
: ((mbc2).wc_valid \
? 1 \
: (mbc1).bytes == (mbc2).bytes \
? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
: (mbc1).bytes < (mbc2).bytes \
? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
: (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
#define mb_equal(mbc1, mbc2) \
((mbc1).wc_valid && (mbc2).wc_valid \
? (mbc1).wc == (mbc2).wc \
: (mbc1).bytes == (mbc2).bytes \
&& memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
#define mb_caseequal(mbc1, mbc2) \
((mbc1).wc_valid && (mbc2).wc_valid \
? towlower ((mbc1).wc) == towlower ((mbc2).wc) \
: (mbc1).bytes == (mbc2).bytes \
&& memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
/* <ctype.h>, <wctype.h> classification. */
#define mb_isascii(mbc) \
((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127)
#define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc))
#define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc))
#define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc))
#define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc))
#define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc))
#define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc))
#define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc))
#define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc))
#define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc))
#define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc))
#define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc))
#define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc))
/* Extra <wchar.h> function. */
/* Unprintable characters appear as a small box of width 1. */
#define MB_UNPRINTABLE_WIDTH 1
static inline int
mb_width_aux (wint_t wc)
{
int w = wcwidth (wc);
/* For unprintable characters, arbitrarily return 0 for control characters
and MB_UNPRINTABLE_WIDTH otherwise. */
return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH);
}
#define mb_width(mbc) \
((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH)
/* Output. */
#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream))
/* Assignment. */
#define mb_setascii(mbc, sc) \
((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \
(mbc)->wc = (mbc)->buf[0] = (sc))
/* Copying a character. */
static inline void
mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc)
{
if (old_mbc->ptr == &old_mbc->buf[0])
{
memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes);
new_mbc->ptr = &new_mbc->buf[0];
}
else
new_mbc->ptr = old_mbc->ptr;
new_mbc->bytes = old_mbc->bytes;
if ((new_mbc->wc_valid = old_mbc->wc_valid))
new_mbc->wc = old_mbc->wc;
}
/* is_basic(c) tests whether the single-byte character c is in the
ISO C "basic character set".
This is a convenience function, and is in this file only to share code
between mbiter_multi.h and mbfile_multi.h. */
#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
/* The character set is ISO-646, not EBCDIC. */
# define IS_BASIC_ASCII 1
extern const unsigned int is_basic_table[];
static inline bool
is_basic (char c)
{
return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31))
& 1;
}
#else
static inline bool
is_basic (char c)
{
switch (c)
{
case '\t': case '\v': case '\f':
case ' ': case '!': case '"': case '#': case '%':
case '&': case '\'': case '(': case ')': case '*':
case '+': case ',': case '-': case '.': case '/':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case ':': case ';': case '<': case '=': case '>':
case '?':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z':
case '[': case '\\': case ']': case '^': case '_':
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z': case '{': case '|': case '}': case '~':
return 1;
default:
return 0;
}
}
#endif
#endif /* _MBCHAR_H */
+68 -16
View File
@@ -25,6 +25,7 @@
/* Include config.h for HANDLE_MULTIBYTE */
#include <config.h>
#include "shmbchar.h"
#if defined (HANDLE_MULTIBYTE)
@@ -101,9 +102,16 @@ extern char *xstrchr __P((const char *, int));
{ \
mbstate_t state_bak; \
size_t mblength; \
int _f; \
\
state_bak = state; \
mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
_f = is_basic ((_str)[_i]); \
if (_f) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
} \
\
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
@@ -134,9 +142,16 @@ extern char *xstrchr __P((const char *, int));
{ \
mbstate_t state_bak; \
size_t mblength; \
int _f; \
\
state_bak = state; \
mblength = mbrlen ((_str), (_strsize), &state); \
_f = is_basic (*(_str)); \
if (_f) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_str), (_strsize), &state); \
} \
\
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
@@ -247,8 +262,14 @@ extern char *xstrchr __P((const char *, int));
size_t mblength; \
int _k; \
\
state_bak = state; \
mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
_k = is_basic (*(_src)); \
if (_k) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
} \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
@@ -280,8 +301,14 @@ extern char *xstrchr __P((const char *, int));
size_t mblength; \
int _k; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
_k = is_basic (*((_src) + (_si))); \
if (_k) \
mblength = 1; \
else \
{\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
} \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
@@ -317,8 +344,14 @@ extern char *xstrchr __P((const char *, int));
size_t mblength; \
int _i; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
_i = is_basic (*((_src) + (_si))); \
if (_i) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
} \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
@@ -356,9 +389,16 @@ extern char *xstrchr __P((const char *, int));
{ \
mbstate_t state_bak; \
size_t mblength; \
int _i; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
_i = is_basic (*((_src) + (_si))); \
if (_i) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
} \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
@@ -395,8 +435,14 @@ extern char *xstrchr __P((const char *, int));
mbstate_t state_bak; \
size_t mblength; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
i = is_basic (*((_src) + (_si))); \
if (i) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
} \
if (mblength == (size_t)-1 || mblength == (size_t)-2) \
{ \
state = state_bak; \
@@ -427,8 +473,14 @@ extern char *xstrchr __P((const char *, int));
mbstate_t state_bak; \
size_t mblength; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
i = is_basic (*((_src) + (_si))); \
if (i) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
} \
if (mblength == (size_t)-1 || mblength == (size_t)-2) \
{ \
state = state_bak; \
+470
View File
@@ -0,0 +1,470 @@
/* shmbutil.h -- utility functions for multibyte characters. */
/* Copyright (C) 2002-2004 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (_SH_MBUTIL_H_)
#define _SH_MBUTIL_H_
#include "stdc.h"
/* Include config.h for HANDLE_MULTIBYTE */
#include <config.h>
#include "shmbchar.h"
#if defined (HANDLE_MULTIBYTE)
extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *));
extern size_t mbstrlen __P((const char *));
extern char *xstrchr __P((const char *, int));
#ifndef MB_INVALIDCH
#define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
#define MB_NULLWCH(x) ((x) == 0)
#endif
#define MBSLEN(s) (((s) && (s)[0]) ? ((s)[1] ? mbstrlen (s) : 1) : 0)
#define MB_STRLEN(s) ((MB_CUR_MAX > 1) ? MBSLEN (s) : STRLEN (s))
#define MBLEN(s, n) ((MB_CUR_MAX > 1) ? mblen ((s), (n)) : 1)
#define MBRLEN(s, n, p) ((MB_CUR_MAX > 1) ? mbrlen ((s), (n), (p)) : 1)
#else /* !HANDLE_MULTIBYTE */
#undef MB_LEN_MAX
#undef MB_CUR_MAX
#define MB_LEN_MAX 1
#define MB_CUR_MAX 1
#undef xstrchr
#define xstrchr(s, c) strchr(s, c)
#ifndef MB_INVALIDCH
#define MB_INVALIDCH(x) (0)
#define MB_NULLWCH(x) (0)
#endif
#define MB_STRLEN(s) (STRLEN(s))
#define MBLEN(s, n) 1
#define MBRLEN(s, n, p) 1
#ifndef wchar_t
# define wchar_t int
#endif
#endif /* !HANDLE_MULTIBYTE */
/* Declare and initialize a multibyte state. Call must be terminated
with `;'. */
#if defined (HANDLE_MULTIBYTE)
# define DECLARE_MBSTATE \
mbstate_t state; \
memset (&state, '\0', sizeof (mbstate_t))
#else
# define DECLARE_MBSTATE
#endif /* !HANDLE_MULTIBYTE */
/* Initialize or reinitialize a multibyte state named `state'. Call must be
terminated with `;'. */
#if defined (HANDLE_MULTIBYTE)
# define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
#else
# define INITIALIZE_MBSTATE
#endif /* !HANDLE_MULTIBYTE */
/* Advance one (possibly multi-byte) character in string _STR of length
_STRSIZE, starting at index _I. STATE must have already been declared. */
#if defined (HANDLE_MULTIBYTE)
# define ADVANCE_CHAR(_str, _strsize, _i) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
int _f; \
\
_f = is_basic ((_str)[_i]); \
if (_f) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
} \
\
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
(_i)++; \
} \
else if (mblength == 0) \
(_i)++; \
else \
(_i) += mblength; \
} \
else \
(_i)++; \
} \
while (0)
#else
# define ADVANCE_CHAR(_str, _strsize, _i) (_i)++
#endif /* !HANDLE_MULTIBYTE */
/* Advance one (possibly multibyte) character in the string _STR of length
_STRSIZE.
SPECIAL: assume that _STR will be incremented by 1 after this call. */
#if defined (HANDLE_MULTIBYTE)
# define ADVANCE_CHAR_P(_str, _strsize) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
int _f; \
\
_f = is_basic (*(_str)); \
if (_f) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_str), (_strsize), &state); \
} \
\
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
mblength = 1; \
} \
else \
(_str) += (mblength < 1) ? 0 : (mblength - 1); \
} \
} \
while (0)
#else
# define ADVANCE_CHAR_P(_str, _strsize)
#endif /* !HANDLE_MULTIBYTE */
/* Back up one (possibly multi-byte) character in string _STR of length
_STRSIZE, starting at index _I. STATE must have already been declared. */
#if defined (HANDLE_MULTIBYTE)
# define BACKUP_CHAR(_str, _strsize, _i) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
int _x, _p; /* _x == temp index into string, _p == prev index */ \
\
_x = _p = 0; \
while (_x < (_i)) \
{ \
state_bak = state; \
mblength = mbrlen ((_str) + (_x), (_strsize) - (_x), &state); \
\
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
_x++; \
} \
else if (mblength == 0) \
_x++; \
else \
{ \
_p = _x; /* _p == start of prev mbchar */ \
_x += mblength; \
} \
} \
(_i) = _p; \
} \
else \
(_i)--; \
} \
while (0)
#else
# define BACKUP_CHAR(_str, _strsize, _i) (_i)--
#endif /* !HANDLE_MULTIBYTE */
/* Back up one (possibly multibyte) character in the string _BASE of length
_STRSIZE starting at _STR (_BASE <= _STR <= (_BASE + _STRSIZE) ).
SPECIAL: DO NOT assume that _STR will be decremented by 1 after this call. */
#if defined (HANDLE_MULTIBYTE)
# define BACKUP_CHAR_P(_base, _strsize, _str) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
char *_x, _p; /* _x == temp pointer into string, _p == prev pointer */ \
\
_x = _p = _base; \
while (_x < (_str)) \
{ \
state_bak = state; \
mblength = mbrlen (_x, (_strsize) - _x, &state); \
\
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
_x++; \
} \
else if (mblength == 0) \
_x++; \
else \
{ \
_p = _x; /* _p == start of prev mbchar */ \
_x += mblength; \
} \
} \
(_str) = _p; \
} \
else \
(_str)--; \
} \
while (0)
#else
# define BACKUP_CHAR_P(_base, _strsize, _str) (_str)--
#endif /* !HANDLE_MULTIBYTE */
/* Copy a single character from the string _SRC to the string _DST.
_SRCEND is a pointer to the end of _SRC. */
#if defined (HANDLE_MULTIBYTE)
# define COPY_CHAR_P(_dst, _src, _srcend) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
int _k; \
\
_k = is_basic (*(_src)); \
if (_k) \
mblength = 1; \
else \
{ \
state_bak = state; \
mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
} \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
mblength = 1; \
} \
else \
mblength = (mblength < 1) ? 1 : mblength; \
\
for (_k = 0; _k < mblength; _k++) \
*(_dst)++ = *(_src)++; \
} \
else \
*(_dst)++ = *(_src)++; \
} \
while (0)
#else
# define COPY_CHAR_P(_dst, _src, _srcend) *(_dst)++ = *(_src)++
#endif /* !HANDLE_MULTIBYTE */
/* Copy a single character from the string _SRC at index _SI to the string
_DST at index _DI. _SRCEND is a pointer to the end of _SRC. */
#if defined (HANDLE_MULTIBYTE)
# define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
int _k; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
mblength = 1; \
} \
else \
mblength = (mblength < 1) ? 1 : mblength; \
\
for (_k = 0; _k < mblength; _k++) \
_dst[_di++] = _src[_si++]; \
} \
else \
_dst[_di++] = _src[_si++]; \
} \
while (0)
#else
# define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
#endif /* !HANDLE_MULTIBYTE */
/****************************************************************
* *
* The following are only guaranteed to work in subst.c *
* *
****************************************************************/
#if defined (HANDLE_MULTIBYTE)
# define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
int _i; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
mblength = 1; \
} \
else \
mblength = (mblength < 1) ? 1 : mblength; \
\
temp = xmalloc (mblength + 2); \
temp[0] = _escchar; \
for (_i = 0; _i < mblength; _i++) \
temp[_i + 1] = _src[_si++]; \
temp[mblength + 1] = '\0'; \
\
goto add_string; \
} \
else \
{ \
_dst[0] = _escchar; \
_dst[1] = _sc; \
} \
} \
while (0)
#else
# define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
_dst[0] = _escchar; \
_dst[1] = _sc
#endif /* !HANDLE_MULTIBYTE */
#if defined (HANDLE_MULTIBYTE)
# define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
mbstate_t state_bak; \
size_t mblength; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
{ \
state = state_bak; \
mblength = 1; \
} \
else \
mblength = (mblength < 1) ? 1 : mblength; \
\
FASTCOPY(((_src) + (_si)), (_dst), mblength); \
\
(_dst) += mblength; \
(_si) += mblength; \
} \
else \
{ \
*(_dst)++ = _src[(_si)]; \
(_si)++; \
} \
} \
while (0)
#else
# define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
*(_dst)++ = _src[(_si)]; \
(_si)++
#endif /* !HANDLE_MULTIBYTE */
#if HANDLE_MULTIBYTE
# define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
do \
{ \
if (MB_CUR_MAX > 1) \
{ \
int i; \
mbstate_t state_bak; \
size_t mblength; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
if (mblength == (size_t)-1 || mblength == (size_t)-2) \
{ \
state = state_bak; \
mblength = 1; \
} \
if (mblength < 1) \
mblength = 1; \
\
_dst = (char *)xmalloc (mblength + 1); \
for (i = 0; i < mblength; i++) \
(_dst)[i] = (_src)[(_si)++]; \
(_dst)[mblength] = '\0'; \
\
goto add_string; \
} \
} \
while (0)
#else
# define SADD_MBCHAR(_dst, _src, _si, _srcsize)
#endif
/* Watch out when using this -- it's just straight textual subsitution */
#if defined (HANDLE_MULTIBYTE)
# define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
\
int i; \
mbstate_t state_bak; \
size_t mblength; \
\
state_bak = state; \
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
if (mblength == (size_t)-1 || mblength == (size_t)-2) \
{ \
state = state_bak; \
mblength = 1; \
} \
if (mblength < 1) \
mblength = 1; \
\
(_dst) = (char *)xmalloc (mblength + 2); \
(_dst)[0] = CTLESC; \
for (i = 0; i < mblength; i++) \
(_dst)[i+1] = (_src)[(_si)++]; \
(_dst)[mblength+1] = '\0'; \
\
goto add_string
#endif /* HANDLE_MULTIBYTE */
#endif /* _SH_MBUTIL_H_ */
+10
View File
@@ -365,6 +365,16 @@ xstrmatch (pattern, string, flags)
int ret;
size_t n;
wchar_t *wpattern, *wstring;
size_t plen, slen, mplen, mslen;
#if 0
plen = strlen (pattern);
mplen = mbstrlen (pattern);
if (plen == mplen && strlen (string) == mbstrlen (string))
#else
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
#endif
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
if (MB_CUR_MAX == 1)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
+398
View File
@@ -0,0 +1,398 @@
/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
globbing. */
/* Copyright (C) 1991-2005 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h> /* for debugging */
#include "strmatch.h"
#include <chartypes.h>
#include "bashansi.h"
#include "shmbutil.h"
#include "xmalloc.h"
/* First, compile `sm_loop.c' for single-byte characters. */
#define CHAR unsigned char
#define U_CHAR unsigned char
#define XCHAR char
#define INT int
#define L(CS) CS
#define INVALID -1
#undef STREQ
#undef STREQN
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
/* We use strcoll(3) for range comparisons in bracket expressions,
even though it can have unwanted side effects in locales
other than POSIX or US. For instance, in the de locale, [A-Z] matches
all characters. */
#if defined (HAVE_STRCOLL)
/* Helper function for collating symbol equivalence. */
static int rangecmp (c1, c2)
int c1, c2;
{
static char s1[2] = { ' ', '\0' };
static char s2[2] = { ' ', '\0' };
int ret;
/* Eight bits only. Period. */
c1 &= 0xFF;
c2 &= 0xFF;
if (c1 == c2)
return (0);
s1[0] = c1;
s2[0] = c2;
if ((ret = strcoll (s1, s2)) != 0)
return ret;
return (c1 - c2);
}
#else /* !HAVE_STRCOLL */
# define rangecmp(c1, c2) ((int)(c1) - (int)(c2))
#endif /* !HAVE_STRCOLL */
#if defined (HAVE_STRCOLL)
static int
collequiv (c1, c2)
int c1, c2;
{
return (rangecmp (c1, c2) == 0);
}
#else
# define collequiv(c1, c2) ((c1) == (c2))
#endif
#define _COLLSYM _collsym
#define __COLLSYM __collsym
#define POSIXCOLL posix_collsyms
#include "collsyms.h"
static int
collsym (s, len)
CHAR *s;
int len;
{
register struct _collsym *csp;
char *x;
x = (char *)s;
for (csp = posix_collsyms; csp->name; csp++)
{
if (STREQN(csp->name, x, len) && csp->name[len] == '\0')
return (csp->code);
}
if (len == 1)
return s[0];
return INVALID;
}
/* unibyte character classification */
#if !defined (isascii) && !defined (HAVE_ISASCII)
# define isascii(c) ((unsigned int)(c) <= 0177)
#endif
enum char_class
{
CC_NO_CLASS = 0,
CC_ASCII, CC_ALNUM, CC_ALPHA, CC_BLANK, CC_CNTRL, CC_DIGIT, CC_GRAPH,
CC_LOWER, CC_PRINT, CC_PUNCT, CC_SPACE, CC_UPPER, CC_WORD, CC_XDIGIT
};
static char const *const cclass_name[] =
{
"",
"ascii", "alnum", "alpha", "blank", "cntrl", "digit", "graph",
"lower", "print", "punct", "space", "upper", "word", "xdigit"
};
#define N_CHAR_CLASS (sizeof(cclass_name) / sizeof (cclass_name[0]))
static int
is_cclass (c, name)
int c;
const char *name;
{
enum char_class char_class = CC_NO_CLASS;
int i, result;
for (i = 1; i < N_CHAR_CLASS; i++)
{
if (STREQ (name, cclass_name[i]))
{
char_class = (enum char_class)i;
break;
}
}
if (char_class == 0)
return -1;
switch (char_class)
{
case CC_ASCII:
result = isascii (c);
break;
case CC_ALNUM:
result = ISALNUM (c);
break;
case CC_ALPHA:
result = ISALPHA (c);
break;
case CC_BLANK:
result = ISBLANK (c);
break;
case CC_CNTRL:
result = ISCNTRL (c);
break;
case CC_DIGIT:
result = ISDIGIT (c);
break;
case CC_GRAPH:
result = ISGRAPH (c);
break;
case CC_LOWER:
result = ISLOWER (c);
break;
case CC_PRINT:
result = ISPRINT (c);
break;
case CC_PUNCT:
result = ISPUNCT (c);
break;
case CC_SPACE:
result = ISSPACE (c);
break;
case CC_UPPER:
result = ISUPPER (c);
break;
case CC_WORD:
result = (ISALNUM (c) || c == '_');
break;
case CC_XDIGIT:
result = ISXDIGIT (c);
break;
default:
result = -1;
break;
}
return result;
}
/* Now include `sm_loop.c' for single-byte characters. */
/* The result of FOLD is an `unsigned char' */
# define FOLD(c) ((flags & FNM_CASEFOLD) \
? TOLOWER ((unsigned char)c) \
: ((unsigned char)c))
#define FCT internal_strmatch
#define GMATCH gmatch
#define COLLSYM collsym
#define PARSE_COLLSYM parse_collsym
#define BRACKMATCH brackmatch
#define PATSCAN patscan
#define STRCOMPARE strcompare
#define EXTMATCH extmatch
#define STRCHR(S, C) strchr((S), (C))
#define STRCOLL(S1, S2) strcoll((S1), (S2))
#define STRLEN(S) strlen(S)
#define STRCMP(S1, S2) strcmp((S1), (S2))
#define RANGECMP(C1, C2) rangecmp((C1), (C2))
#define COLLEQUIV(C1, C2) collequiv((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_cclass((C), (S))
#include "sm_loop.c"
#if HANDLE_MULTIBYTE
# define CHAR wchar_t
# define U_CHAR wint_t
# define XCHAR wchar_t
# define INT wint_t
# define L(CS) L##CS
# define INVALID WEOF
# undef STREQ
# undef STREQN
# define STREQ(s1, s2) ((wcscmp (s1, s2) == 0))
# define STREQN(a, b, n) ((a)[0] == (b)[0] && wcsncmp(a, b, n) == 0)
static int
rangecmp_wc (c1, c2)
wint_t c1, c2;
{
static wchar_t s1[2] = { L' ', L'\0' };
static wchar_t s2[2] = { L' ', L'\0' };
if (c1 == c2)
return 0;
s1[0] = c1;
s2[0] = c2;
return (wcscoll (s1, s2));
}
static int
collequiv_wc (c, equiv)
wint_t c, equiv;
{
return (!(c - equiv));
}
/* Helper function for collating symbol. */
# define _COLLSYM _collwcsym
# define __COLLSYM __collwcsym
# define POSIXCOLL posix_collwcsyms
# include "collsyms.h"
static wint_t
collwcsym (s, len)
wchar_t *s;
int len;
{
register struct _collwcsym *csp;
for (csp = posix_collwcsyms; csp->name; csp++)
{
if (STREQN(csp->name, s, len) && csp->name[len] == L'\0')
return (csp->code);
}
if (len == 1)
return s[0];
return INVALID;
}
static int
is_wcclass (wc, name)
wint_t wc;
wchar_t *name;
{
char *mbs;
mbstate_t state;
size_t mbslength;
wctype_t desc;
int want_word;
if ((wctype ("ascii") == (wctype_t)0) && (wcscmp (name, L"ascii") == 0))
{
int c;
if ((c = wctob (wc)) == EOF)
return 0;
else
return (c <= 0x7F);
}
want_word = (wcscmp (name, L"word") == 0);
if (want_word)
name = L"alnum";
memset (&state, '\0', sizeof (mbstate_t));
mbs = (char *) malloc (wcslen(name) * MB_CUR_MAX + 1);
mbslength = wcsrtombs(mbs, (const wchar_t **)&name, (wcslen(name) * MB_CUR_MAX + 1), &state);
if (mbslength == (size_t)-1 || mbslength == (size_t)-2)
{
free (mbs);
return -1;
}
desc = wctype (mbs);
free (mbs);
if (desc == (wctype_t)0)
return -1;
if (want_word)
return (iswctype (wc, desc) || wc == L'_');
else
return (iswctype (wc, desc));
}
/* Now include `sm_loop.c' for multibyte characters. */
#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c))
#define FCT internal_wstrmatch
#define GMATCH gmatch_wc
#define COLLSYM collwcsym
#define PARSE_COLLSYM parse_collwcsym
#define BRACKMATCH brackmatch_wc
#define PATSCAN patscan_wc
#define STRCOMPARE wscompare
#define EXTMATCH extmatch_wc
#define STRCHR(S, C) wcschr((S), (C))
#define STRCOLL(S1, S2) wcscoll((S1), (S2))
#define STRLEN(S) wcslen(S)
#define STRCMP(S1, S2) wcscmp((S1), (S2))
#define RANGECMP(C1, C2) rangecmp_wc((C1), (C2))
#define COLLEQUIV(C1, C2) collequiv_wc((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_wcclass((C), (S))
#include "sm_loop.c"
#endif /* HAVE_MULTIBYTE */
int
xstrmatch (pattern, string, flags)
char *pattern;
char *string;
int flags;
{
#if HANDLE_MULTIBYTE
int ret;
size_t n;
wchar_t *wpattern, *wstring;
size_t plen, slen, mplen, mslen;
plen = strlen (pattern);
mplen = mbstrlen (pattern);
if (plen == mplen && strlen (string) == mbstrlen (string))
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
if (MB_CUR_MAX == 1)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
n = xdupmbstowcs (&wpattern, NULL, pattern);
if (n == (size_t)-1 || n == (size_t)-2)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
n = xdupmbstowcs (&wstring, NULL, string);
if (n == (size_t)-1 || n == (size_t)-2)
{
free (wpattern);
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
}
ret = internal_wstrmatch (wpattern, wstring, flags);
free (wpattern);
free (wstring);
return ret;
#else
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
#endif /* !HANDLE_MULTIBYTE */
}
+7 -3
View File
@@ -763,10 +763,14 @@ as if the "!\fIn\fP" history expansion had been specified.
.B
yank\-last\-arg (M\-.\^, M\-_\^)
Insert the last argument to the previous command (the last word of
the previous history entry). With an argument,
behave exactly like \fByank\-nth\-arg\fP.
the previous history entry).
With a numeric argument, behave exactly like \fByank\-nth\-arg\fP.
Successive calls to \fByank\-last\-arg\fP move back through the history
list, inserting the last argument of each line in turn.
list, inserting the last word (or the word specified by the argument to
the first call) of each line in turn.
Any numeric argument supplied to these successive calls determines
the direction to move through the history. A negative argument switches
the direction through the history (back or forward).
The history expansion facilities are used to extract the last argument,
as if the "!$" history expansion had been specified.
.PD
+5
View File
@@ -492,6 +492,11 @@ completion.
If set to \fBOff\fP, the leading `.' must be
supplied by the user in the filename to be completed.
.TP
.B menu\-complete\-display\-prefix (Off)
If set to \fBOn\fP, menu completion displays the common prefix of the
list of possible completions (which may be empty) before cycling through
the list.
.TP
.B output\-meta (Off)
If set to \fBOn\fP, readline will display characters with the
eighth bit set directly rather than as a meta-prefixed escape
+7 -3
View File
@@ -1120,10 +1120,14 @@ as if the @samp{!@var{n}} history expansion had been specified.
@item yank-last-arg (M-. or M-_)
Insert last argument to the previous command (the last word of the
previous history entry). With an
argument, behave exactly like @code{yank-nth-arg}.
previous history entry).
With a numeric argument, behave exactly like @code{yank-nth-arg}.
Successive calls to @code{yank-last-arg} move back through the history
list, inserting the last argument of each line in turn.
list, inserting the last word (or the word specified by the argument to
the first call) of each line in turn.
Any numeric argument supplied to these successive calls determines
the direction to move through the history. A negative argument switches
the direction through the history (back or forward).
The history expansion facilities are used to extract the last argument,
as if the @samp{!$} history expansion had been specified.
+14 -4
View File
@@ -591,6 +591,12 @@ If set to @samp{off}, the leading @samp{.} must be
supplied by the user in the filename to be completed.
This variable is @samp{on} by default.
@item menu-complete-display-prefix
@vindex menu-complete-display-prefix
If set to @samp{on}, menu completion displays the common prefix of the
list of possible completions (which may be empty) before cycling through
the list. The default is @samp{off}.
@item output-meta
@vindex output-meta
If set to @samp{on}, Readline will display characters with the
@@ -1114,10 +1120,14 @@ as if the @samp{!@var{n}} history expansion had been specified.
@item yank-last-arg (M-. or M-_)
Insert last argument to the previous command (the last word of the
previous history entry). With an
argument, behave exactly like @code{yank-nth-arg}.
previous history entry).
With a numeric argument, behave exactly like @code{yank-nth-arg}.
Successive calls to @code{yank-last-arg} move back through the history
list, inserting the last argument of each line in turn.
list, inserting the last word (or the word specified by the argument to
the first call) of each line in turn.
Any numeric argument supplied to these successive calls determines
the direction to move through the history. A negative argument switches
the direction through the history (back or forward).
The history expansion facilities are used to extract the last argument,
as if the @samp{!$} history expansion had been specified.
@@ -1229,7 +1239,7 @@ Kill from point to the end of the current word, or if between
words, to the end of the next word.
Word boundaries are the same as @code{shell-forward-word}.
@item backward-kill-word ()
@item shell-backward-kill-word ()
Kill the word behind point.
Word boundaries are the same as @code{shell-backward-word}.
@end ifset
+1 -1
View File
@@ -640,7 +640,7 @@ rl_yank_last_arg (count, key)
{
if (undo_needed)
rl_do_undo ();
if (count < 1)
if (count < 0) /* XXX - was < 1 */
direction = -direction;
history_skip += direction;
if (history_skip < 0)
+2 -2
View File
@@ -147,7 +147,7 @@ _rl_copy_to_kill_ring (text, append)
strcat (new, old);
}
xfree (old);
free (text);
xfree (text);
rl_kill_ring[slot] = new;
}
else
@@ -601,7 +601,7 @@ rl_yank_nth_arg_internal (count, ignore, history_skip)
#endif /* VI_MODE */
rl_insert_text (arg);
free (arg);
xfree (arg);
rl_end_undo_group ();
return 0;
+8 -4
View File
@@ -92,7 +92,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \
strchrnul.c unicode.c wcswidth.c
strchrnul.c unicode.c wcswidth.c shmbchar.c
# The header files for this library.
HSOURCES =
@@ -106,7 +106,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
strtrans.o snprintf.o mailstat.o fmtulong.o \
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
input_avail.o mbscasecmp.o fnxform.o unicode.o ${LIBOBJS}
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o ${LIBOBJS}
SUPPORT = Makefile
@@ -169,6 +169,7 @@ pathcanon.o: pathcanon.c
pathphys.o: pathphys.c
rename.o: rename.c
setlinebuf.o: setlinebuf.c
shmbchar.o: shmbchar.c
shquote.o: shquote.c
shtty.o: shtty.c
snprintf.o: snprintf.c
@@ -240,6 +241,7 @@ pathcanon.o: ${BUILD_DIR}/config.h
pathphys.o: ${BUILD_DIR}/config.h
rename.o: ${BUILD_DIR}/config.h
setlinebuf.o: ${BUILD_DIR}/config.h
shmbchare.o: ${BUILD_DIR}/config.h
shquote.o: ${BUILD_DIR}/config.h
shtty.o: ${BUILD_DIR}/config.h
snprintf.o: ${BUILD_DIR}/config.h
@@ -513,7 +515,7 @@ wcswidth.o: ${BASHINCDIR}/stdc.h
mbschr.o: ${topdir}/bashansi.h
mbschr.o: ${BASHINCDIR}/ansi_stdlib.h
mbschr.o: ${BASHINCDIR}/shmbutil.h
mbschr.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
zgetline.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
zgetline.o: ${BASHINCDIR}/stdc.h
@@ -532,7 +534,7 @@ casemod.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
casemod.o: ${BASHINCDIR}/stdc.h
casemod.o: ${topdir}/xmalloc.h
casemod.o: ${topdir}/bashtypes.h
casemod.o: ${BASHINCDIR}/shmbutil.h
casemod.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
dprintf.o: ${BASHINCDIR}/stdc.h
@@ -548,3 +550,5 @@ fnxform.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
fnxform.o: ${BASHINCDIR}/stdc.h
fnxform.o: ${topdir}/bashtypes.h
fnxform.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
shmbchar.o: ${BASHINCDIR}/shmbchar.h
+13 -4
View File
@@ -92,7 +92,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \
strchrnul.c unicode.c
strchrnul.c unicode.c wcswidth.c shmbchar.c
# The header files for this library.
HSOURCES =
@@ -106,7 +106,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
strtrans.o snprintf.o mailstat.o fmtulong.o \
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
input_avail.o mbscasecmp.o fnxform.o unicode.o ${LIBOBJS}
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o ${LIBOBJS}
SUPPORT = Makefile
@@ -169,6 +169,7 @@ pathcanon.o: pathcanon.c
pathphys.o: pathphys.c
rename.o: rename.c
setlinebuf.o: setlinebuf.c
shmbchar.o: shmbchar.c
shquote.o: shquote.c
shtty.o: shtty.c
snprintf.o: snprintf.c
@@ -196,6 +197,7 @@ uconvert.o: uconvert.c
ufuncs.o: ufuncs.c
vprint.o: vprint.c
wcsdup.o: wcsdup.c
wcswidth.o: wcswidth.c
mbschr.o: mbschr.c
zcatfd.o: zcatfd.c
zmapfd.o: zmapfd.c
@@ -239,6 +241,7 @@ pathcanon.o: ${BUILD_DIR}/config.h
pathphys.o: ${BUILD_DIR}/config.h
rename.o: ${BUILD_DIR}/config.h
setlinebuf.o: ${BUILD_DIR}/config.h
shmbchare.o: ${BUILD_DIR}/config.h
shquote.o: ${BUILD_DIR}/config.h
shtty.o: ${BUILD_DIR}/config.h
snprintf.o: ${BUILD_DIR}/config.h
@@ -266,6 +269,7 @@ uconvert.o: ${BUILD_DIR}/config.h
ufuncs.o: ${BUILD_DIR}/config.h
vprint.o: ${BUILD_DIR}/config.h
wcsdup.o: ${BUILD_DIR}/config.h
wcswidth.o: ${BUILD_DIR}/config.h
mbschr.o: ${BUILD_DIR}/config.h
zcatfd.o: ${BUILD_DIR}/config.h
zgetline.o: ${BUILD_DIR}/config.h
@@ -506,9 +510,12 @@ wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsdup.o: ${BASHINCDIR}/stdc.h
wcsdup.o: ${topdir}/xmalloc.h
wcswidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcswidth.o: ${BASHINCDIR}/stdc.h
mbschr.o: ${topdir}/bashansi.h
mbschr.o: ${BASHINCDIR}/ansi_stdlib.h
mbschr.o: ${BASHINCDIR}/shmbutil.h
mbschr.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmchar.h
zgetline.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
zgetline.o: ${BASHINCDIR}/stdc.h
@@ -527,7 +534,7 @@ casemod.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
casemod.o: ${BASHINCDIR}/stdc.h
casemod.o: ${topdir}/xmalloc.h
casemod.o: ${topdir}/bashtypes.h
casemod.o: ${BASHINCDIR}/shmbutil.h
casemod.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmchar.h
casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
dprintf.o: ${BASHINCDIR}/stdc.h
@@ -543,3 +550,5 @@ fnxform.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
fnxform.o: ${BASHINCDIR}/stdc.h
fnxform.o: ${topdir}/bashtypes.h
fnxform.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
shmbchar.o: ${BASHINCDIR}/shmbchar.h
+1 -1
View File
@@ -72,7 +72,7 @@ curencoding ()
mod = strchr (dot, '@');
if (mod)
*mod = '\0';
return dot;
return ++dot;
#endif
}
+92
View File
@@ -0,0 +1,92 @@
/* Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <limits.h>
#include <shmbutil.h>
#include <shmbchar.h>
#if IS_BASIC_ASCII
/* Bit table of characters in the ISO C "basic character set". */
const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] =
{
0x00001a00, /* '\t' '\v' '\f' */
0xffffffef, /* ' '...'#' '%'...'?' */
0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */
0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */
/* The remaining bits are 0. */
};
#endif /* IS_BASIC_ASCII */
size_t
mbstrlen (s)
const char *s;
{
size_t clen, nc;
mbstate_t mbs = { 0 }, mbsbak = { 0 };
int f;
nc = 0;
while (*s && (clen = (f = is_basic (*s)) ? 1 : mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
{
if (MB_INVALIDCH(clen))
{
clen = 1; /* assume single byte */
mbs = mbsbak;
}
if (f == 0)
mbsbak = mbs;
s += clen;
nc++;
}
return nc;
}
/* Return pointer to first multibyte char in S, or NULL if none. */
char *
mbsmbchar (s)
const char *s;
{
char *t;
size_t clen;
mbstate_t mbs = { 0 };
for (t = (char *)s; *t; t++)
{
if (is_basic (*t))
continue;
clen = mbrlen (t, MB_CUR_MAX, &mbs);
if (clen == 0)
return 0;
if (MB_INVALIDCH(clen))
continue;
if (clen > 1)
return t;
}
return 0;
}
#endif
+64
View File
@@ -0,0 +1,64 @@
/* Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <limits.h>
#include <shmbutil.h>
#include <shmbchar.h>
#if IS_BASIC_ASCII
/* Bit table of characters in the ISO C "basic character set". */
const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] =
{
0x00001a00, /* '\t' '\v' '\f' */
0xffffffef, /* ' '...'#' '%'...'?' */
0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */
0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */
/* The remaining bits are 0. */
};
#endif /* IS_BASIC_ASCII */
size_t
mbstrlen (s)
const char *s;
{
size_t clen, nc;
mbstate_t mbs = { 0 }, mbsbak = { 0 };
nc = 0;
while (*s && (clen = is_basic (*s) ? 1 : mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
{
if (MB_INVALIDCH(clen))
{
clen = 1; /* assume single byte */
mbs = mbsbak;
}
if (is_basic (*s) == 0)
mbsbak = mbs;
s += clen;
nc++;
}
return nc;
}
#endif
+91
View File
@@ -0,0 +1,91 @@
/* Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <limits.h>
#include <shmbutil.h>
#include <shmbchar.h>
#if IS_BASIC_ASCII
/* Bit table of characters in the ISO C "basic character set". */
const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] =
{
0x00001a00, /* '\t' '\v' '\f' */
0xffffffef, /* ' '...'#' '%'...'?' */
0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */
0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */
/* The remaining bits are 0. */
};
#endif /* IS_BASIC_ASCII */
size_t
mbstrlen (s)
const char *s;
{
size_t clen, nc;
mbstate_t mbs = { 0 }, mbsbak = { 0 };
nc = 0;
while (*s && (clen = is_basic (*s) ? 1 : mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
{
if (MB_INVALIDCH(clen))
{
clen = 1; /* assume single byte */
mbs = mbsbak;
}
if (is_basic (*s) == 0)
mbsbak = mbs;
s += clen;
nc++;
}
return nc;
}
/* Return pointer to first multibyte char in S, or NULL if none. */
char *
mbsmbchar (s)
const char *s;
{
char *t;
size_t clen;
mbstate_t mbs = { 0 };
for (t = (char *)s; *t; t++)
{
if (is_basic (*t))
continue;
clen = mbrlen (t, MB_CUR_MAX, &mbs);
if (clen == 0)
return 0;
if (MB_INVALIDCH(clen))
continue;
if (clen > 1)
return t;
}
return 0;
}
#endif
+8 -3
View File
@@ -64,14 +64,19 @@ static iconv_t localconv;
static char *
stub_charset ()
{
char *locale, *s;
char *locale, *s, *t;
locale = get_locale_var ("LC_CTYPE");
if (locale == 0)
if (locale == 0 || *locale == 0)
return "ASCII";
s = strrchr (locale, '.');
if (s)
return ++s;
{
t = strchr (s, '@');
if (t)
*t = 0;
return ++s;
}
else if (STREQ (locale, "UTF-8"))
return "UTF-8";
else
+33 -3
View File
@@ -1,6 +1,6 @@
/* unicode.c - functions to convert unicode characters */
/* Copyright (C) 2006 Free Software Foundation, Inc.
/* Copyright (C) 2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -56,7 +56,33 @@ extern char *get_locale_var __P((char *));
static int u32init = 0;
static int utf8locale = 0;
#if defined (HAVE_ICONV)
static iconv_t localconv;
#endif
#ifndef HAVE_LOCALE_CHARSET
static char *
stub_charset ()
{
char *locale, *s;
locale = get_locale_var ("LC_CTYPE");
if (locale == 0 || *locale == 0)
return "ASCII";
s = strrchr (locale, '.');
if (s)
{
t = strchr (s, '@');
if (t)
*t = 0;
return ++s;
}
else if (STREQ (locale, "UTF-8"))
return "UTF-8";
else
return "ASCII";
}
#endif
/* u32toascii ? */
int
@@ -127,7 +153,7 @@ u32cconv (c, s)
const char *charset;
char obuf[25], *optr;
size_t obytesleft;
char *iptr;
const char *iptr;
size_t sn;
#endif
@@ -154,7 +180,11 @@ u32cconv (c, s)
/* this is mostly from coreutils-8.5/lib/unicodeio.c */
if (u32init == 0)
{
# if HAVE_LOCALE_CHARSET
charset = locale_charset (); /* XXX - fix later */
# else
charset = stub_charset ();
# endif
if (STREQ (charset, "UTF-8"))
utf8locale = 1;
else
@@ -187,7 +217,7 @@ u32cconv (c, s)
iconv (localconv, NULL, NULL, NULL, NULL);
if (iconv (localconv, &iptr, &sn, &optr, &obytesleft) == (size_t)-1)
if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1)
return n; /* You get utf-8 if iconv fails */
*optr = '\0';
+1 -1
View File
@@ -297,7 +297,7 @@ get_locale_var (var)
locale = lc_all;
if (locale == 0 || *locale == 0)
locale = get_string_value (var);
locale = get_string_value (var); /* XXX - mem leak? */
if (locale == 0 || *locale == 0)
locale = lang;
if (locale == 0 || *locale == 0)
+1 -1
View File
@@ -5255,7 +5255,7 @@ decode_prompt_string (string)
{
t = strrchr (t_string, '/');
if (t)
memmove (t_string, t + 1, strlen (t) - 1);
memmove (t_string, t + 1, strlen (t)); /* strlen(t) to copy NULL */
}
}
#undef ROOT_PATH
+2 -2
View File
@@ -3434,7 +3434,7 @@ parse_comsub (qc, open, close, lenp, flags)
while (count)
{
comsub_readchar:
ch = shell_getc (qc != '\'' && (tflags & LEX_PASSNEXT) == 0);
ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT)) == 0);
if (ch == EOF)
{
@@ -5255,7 +5255,7 @@ decode_prompt_string (string)
{
t = strrchr (t_string, '/');
if (t)
memmove (t_string, t + 1, strlen (t) - 1);
memmove (t_string, t + 1, strlen (t)); /* tlen to copy NULL */
}
}
#undef ROOT_PATH
+1 -1
View File
@@ -63,7 +63,7 @@ extern int parse_and_execute_level, shell_initialized;
extern int history_lines_this_session;
#endif
extern void intialize_siglist ();
extern void initialize_siglist ();
/* Non-zero after SIGINT. */
volatile int interrupt_state = 0;
+45 -50
View File
@@ -2297,11 +2297,7 @@ string_list_dollar_at (list, quoted)
/* XXX -- why call quote_list if ifs == 0? we can get away without doing
it now that quote_escapes quotes spaces */
#if 0
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
#else
tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
#endif
? quote_list (list)
: list_quote_escapes (list);
@@ -2856,8 +2852,9 @@ do_assignment (string)
}
int
do_word_assignment (word)
do_word_assignment (word, flags)
WORD_DESC *word;
int flags;
{
return do_assignment_internal (word, 1);
}
@@ -4154,7 +4151,13 @@ match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
wchar_t wc, *wp, *nwpat, *wp1;
size_t len;
int mlen;
int n, n1;
int n, n1, n2, simple;
simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'[');
#if defined (EXTENDED_GLOB)
if (extended_glob)
simple |= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
#endif
/* If the pattern doesn't match anywhere in the string, go ahead and
short-circuit right away. A minor optimization, saves a bunch of
@@ -4184,13 +4187,19 @@ match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
return (0);
mlen = wmatchlen (wpat, wstrlen);
/* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
switch (mtype)
{
case MATCH_ANY:
for (n = 0; n <= wstrlen; n++)
{
if (match_pattern_wchar (wpat, wstring + n))
#if 1
n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n);
#else
n2 = match_pattern_wchar (wpat, wstring + n);
#endif
if (n2)
{
#if 0
for (n1 = wstrlen; n1 >= n; n1--)
@@ -4288,6 +4297,7 @@ match_pattern (string, pat, mtype, sp, ep)
size_t n;
wchar_t *wstring, *wpat;
char **indices;
size_t slen, plen, mslen, mplen;
#endif
if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
@@ -4296,6 +4306,17 @@ match_pattern (string, pat, mtype, sp, ep)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1)
{
#if 0
slen = STRLEN (string);
mslen = MBSLEN (string);
plen = STRLEN (pat);
mplen = MBSLEN (pat);
if (slen == mslen && plen == mplen)
#else
if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0)
#endif
return (match_upattern (string, pat, mtype, sp, ep));
n = xdupmbstowcs (&wpat, NULL, pat);
if (n == (size_t)-1)
return (match_upattern (string, pat, mtype, sp, ep));
@@ -5855,34 +5876,6 @@ valid_length_expression (name)
legal_identifier (name + 1)); /* ${#PS1} */
}
#if defined (HANDLE_MULTIBYTE)
size_t
mbstrlen (s)
const char *s;
{
size_t clen, nc;
mbstate_t mbs, mbsbak;
nc = 0;
memset (&mbs, 0, sizeof (mbs));
mbsbak = mbs;
while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
{
if (MB_INVALIDCH(clen))
{
clen = 1; /* assume single byte */
mbs = mbsbak;
}
s += clen;
nc++;
mbsbak = mbs;
}
return nc;
}
#endif
/* Handle the parameter brace expansion that requires us to return the
length of a parameter. */
static intmax_t
@@ -5965,7 +5958,7 @@ parameter_brace_expand_length (name)
if (list)
dispose_words (list);
number = MB_STRLEN (t);
number = t ? MB_STRLEN (t) : 0;
FREE (t);
}
}
@@ -7536,11 +7529,14 @@ param_expand (string, sindex, quoted, expanded_something,
is unset, the parameters are separated by ' '; if $IFS is
null, the parameters are concatenated. */
temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
temp1 = quote_string (temp);
if (*temp == 0)
tflag |= W_HASQUOTEDNULL;
free (temp);
temp = temp1;
if (temp)
{
temp1 = quote_string (temp);
if (*temp == 0)
tflag |= W_HASQUOTEDNULL;
free (temp);
temp = temp1;
}
}
else
{
@@ -8314,7 +8310,7 @@ add_twochars:
if (list->next)
{
#if 0
if (quoted_dollar_at && word->flags & W_NOSPLIT2)
if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
temp = string_list_internal (quote_list (list), " ");
else
#endif
@@ -8352,12 +8348,10 @@ add_twochars:
else
temp = (char *)NULL;
#if 0
/* We do not want to add quoted nulls to strings that are only
partially quoted; we can throw them away. */
if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
continue;
#endif
add_quoted_string:
@@ -9194,7 +9188,7 @@ shell_expand_word_list (tlist, eflags)
if (tlist->word->flags & W_ASSIGNASSOC)
make_internal_declare (tlist->word->word, "-A");
t = do_word_assignment (tlist->word);
t = do_word_assignment (tlist->word, 0);
if (t == 0)
{
last_command_exit_value = EXECUTION_FAILURE;
@@ -9294,7 +9288,7 @@ expand_word_list_internal (list, eflags)
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL; /* no arithmetic errors */
tint = do_word_assignment (temp_list->word);
tint = do_word_assignment (temp_list->word, 0);
/* Variable assignment errors in non-interactive shells
running in Posix.2 mode cause the shell to exit. */
if (tint == 0)
@@ -9343,7 +9337,7 @@ expand_word_list_internal (list, eflags)
if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
{
sh_wassign_func_t *assign_func;
int is_special_builtin;
int is_special_builtin, is_builtin_or_func;
/* If the remainder of the words expand to nothing, Posix.2 requires
that the variable and environment assignments affect the shell's
@@ -9351,15 +9345,16 @@ expand_word_list_internal (list, eflags)
assign_func = new_list ? assign_in_env : do_word_assignment;
tempenv_assign_error = 0;
is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
/* Posix says that special builtins exit if a variable assignment error
occurs in an assignment preceding it. */
is_special_builtin = (posixly_correct && new_list && find_special_builtin (new_list->word->word));
is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL;
assigning_in_environment = (assign_func == assign_in_env);
tint = (*assign_func) (temp_list->word);
tint = (*assign_func) (temp_list->word, is_builtin_or_func);
assigning_in_environment = 0;
/* Variable assignment errors in non-interactive shells running
in Posix.2 mode cause the shell to exit. */
+9392
View File
File diff suppressed because it is too large Load Diff
+53 -53
View File
@@ -52,6 +52,7 @@
#include "mailcheck.h"
#include "shmbutil.h"
#include "typemax.h"
#include "builtins/getopt.h"
#include "builtins/common.h"
@@ -2296,11 +2297,7 @@ string_list_dollar_at (list, quoted)
/* XXX -- why call quote_list if ifs == 0? we can get away without doing
it now that quote_escapes quotes spaces */
#if 0
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
#else
tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
#endif
? quote_list (list)
: list_quote_escapes (list);
@@ -2855,8 +2852,9 @@ do_assignment (string)
}
int
do_word_assignment (word)
do_word_assignment (word, flags)
WORD_DESC *word;
int flags;
{
return do_assignment_internal (word, 1);
}
@@ -4003,6 +4001,7 @@ match_upattern (string, pat, mtype, sp, ep)
int c, len, mlen;
register char *p, *p1, *npat;
char *end;
int n1;
/* If the pattern doesn't match anywhere in the string, go ahead and
short-circuit right away. A minor optimization, saves a bunch of
@@ -4049,8 +4048,15 @@ match_upattern (string, pat, mtype, sp, ep)
for (p1 = end; p1 >= p; p1--)
#else
p1 = (mlen == -1) ? end : p + mlen;
/* extra -1 to handle case of p1 == end */
if (p1 - p + mlen - 1 > len)
/* p1 - p = length of portion of string to be considered
p = current position in string
mlen = number of characters consumed by match (-1 for entire string)
end = end of string
we want to break immediately if the potential match len
is greater than the number of characters remaining in the
string
*/
if (p1 > end)
break;
for ( ; p1 >= p; p1--)
#endif
@@ -4145,7 +4151,13 @@ match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
wchar_t wc, *wp, *nwpat, *wp1;
size_t len;
int mlen;
int n, n1;
int n, n1, n2, simple;
simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'[');
#if defined (EXTENDED_GLOB)
if (extended_glob)
simple |= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
#endif
/* If the pattern doesn't match anywhere in the string, go ahead and
short-circuit right away. A minor optimization, saves a bunch of
@@ -4175,13 +4187,19 @@ match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
return (0);
mlen = wmatchlen (wpat, wstrlen);
/* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
switch (mtype)
{
case MATCH_ANY:
for (n = 0; n <= wstrlen; n++)
{
if (match_pattern_wchar (wpat, wstring + n))
#if 1
n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n);
#else
n2 = match_pattern_wchar (wpat, wstring + n);
#endif
if (n2)
{
#if 0
for (n1 = wstrlen; n1 >= n; n1--)
@@ -4279,6 +4297,7 @@ match_pattern (string, pat, mtype, sp, ep)
size_t n;
wchar_t *wstring, *wpat;
char **indices;
size_t slen, plen, mslen, mplen;
#endif
if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
@@ -4287,6 +4306,13 @@ match_pattern (string, pat, mtype, sp, ep)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1)
{
slen = STRLEN (string);
mslen = MBSLEN (string);
plen = STRLEN (pat);
mplen = MBSLEN (pat);
if (slen == mslen && plen == mplen)
return (match_upattern (string, pat, mtype, sp, ep));
n = xdupmbstowcs (&wpat, NULL, pat);
if (n == (size_t)-1)
return (match_upattern (string, pat, mtype, sp, ep));
@@ -5846,34 +5872,6 @@ valid_length_expression (name)
legal_identifier (name + 1)); /* ${#PS1} */
}
#if defined (HANDLE_MULTIBYTE)
size_t
mbstrlen (s)
const char *s;
{
size_t clen, nc;
mbstate_t mbs, mbsbak;
nc = 0;
memset (&mbs, 0, sizeof (mbs));
mbsbak = mbs;
while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
{
if (MB_INVALIDCH(clen))
{
clen = 1; /* assume single byte */
mbs = mbsbak;
}
s += clen;
nc++;
mbsbak = mbs;
}
return nc;
}
#endif
/* Handle the parameter brace expansion that requires us to return the
length of a parameter. */
static intmax_t
@@ -5907,7 +5905,7 @@ parameter_brace_expand_length (name)
break;
case '!':
if (last_asynchronous_pid == NO_PID)
t = (char *)NULL;
t = (char *)NULL; /* XXX - error if set -u set? */
else
t = itos (last_asynchronous_pid);
break;
@@ -5956,7 +5954,7 @@ parameter_brace_expand_length (name)
if (list)
dispose_words (list);
number = MB_STRLEN (t);
number = t ? MB_STRLEN (t) : 0;
FREE (t);
}
}
@@ -7527,11 +7525,14 @@ param_expand (string, sindex, quoted, expanded_something,
is unset, the parameters are separated by ' '; if $IFS is
null, the parameters are concatenated. */
temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
temp1 = quote_string (temp);
if (*temp == 0)
tflag |= W_HASQUOTEDNULL;
free (temp);
temp = temp1;
if (temp)
{
temp1 = quote_string (temp);
if (*temp == 0)
tflag |= W_HASQUOTEDNULL;
free (temp);
temp = temp1;
}
}
else
{
@@ -8305,7 +8306,7 @@ add_twochars:
if (list->next)
{
#if 0
if (quoted_dollar_at && word->flags & W_NOSPLIT2)
if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
temp = string_list_internal (quote_list (list), " ");
else
#endif
@@ -8343,12 +8344,10 @@ add_twochars:
else
temp = (char *)NULL;
#if 0
/* We do not want to add quoted nulls to strings that are only
partially quoted; we can throw them away. */
if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
continue;
#endif
add_quoted_string:
@@ -9185,7 +9184,7 @@ shell_expand_word_list (tlist, eflags)
if (tlist->word->flags & W_ASSIGNASSOC)
make_internal_declare (tlist->word->word, "-A");
t = do_word_assignment (tlist->word);
t = do_word_assignment (tlist->word, 0);
if (t == 0)
{
last_command_exit_value = EXECUTION_FAILURE;
@@ -9285,7 +9284,7 @@ expand_word_list_internal (list, eflags)
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL; /* no arithmetic errors */
tint = do_word_assignment (temp_list->word);
tint = do_word_assignment (temp_list->word, 0);
/* Variable assignment errors in non-interactive shells
running in Posix.2 mode cause the shell to exit. */
if (tint == 0)
@@ -9334,7 +9333,7 @@ expand_word_list_internal (list, eflags)
if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
{
sh_wassign_func_t *assign_func;
int is_special_builtin;
int is_special_builtin, is_builtin_or_func;
/* If the remainder of the words expand to nothing, Posix.2 requires
that the variable and environment assignments affect the shell's
@@ -9342,15 +9341,16 @@ expand_word_list_internal (list, eflags)
assign_func = new_list ? assign_in_env : do_word_assignment;
tempenv_assign_error = 0;
is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
/* Posix says that special builtins exit if a variable assignment error
occurs in an assignment preceding it. */
is_special_builtin = (posixly_correct && new_list && find_special_builtin (new_list->word->word));
is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL;
assigning_in_environment = (assign_func == assign_in_env);
tint = (*assign_func) (temp_list->word);
tint = (*assign_func) (temp_list->word, is_builtin_or_func);
assigning_in_environment = 0;
/* Variable assignment errors in non-interactive shells running
in Posix.2 mode cause the shell to exit. */
+2 -1
View File
@@ -124,7 +124,7 @@ extern char *strip_trailing_ifs_whitespace __P((char *, char *, int));
splitting on the result of expansion. */
extern int do_assignment __P((char *));
extern int do_assignment_no_expand __P((char *));
extern int do_word_assignment __P((WORD_DESC *));
extern int do_word_assignment __P((WORD_DESC *, int));
/* Append SOURCE to TARGET at INDEX. SIZE is the current amount
of space allocated to TARGET. SOURCE can be NULL, in which
@@ -260,6 +260,7 @@ extern void unlink_fifo __P((int));
extern char *copy_fifo_list __P((int *));
extern void unlink_new_fifos __P((char *, int));
extern void close_new_fifos __P((char *, int));
extern WORD_LIST *list_string_with_quotes __P((char *));
+2
View File
@@ -260,6 +260,7 @@ extern void unlink_fifo __P((int));
extern char *copy_fifo_list __P((int *));
extern void unlink_new_fifos __P((char *, int));
extern void close_new_fifos __P((char *, int));
extern WORD_LIST *list_string_with_quotes __P((char *));
@@ -277,6 +278,7 @@ extern char *cond_expand_word __P((WORD_DESC *, int));
#define SD_INVERT 0x02 /* look for chars NOT in passed set */
#define SD_NOQUOTEDELIM 0x04 /* don't let single or double quotes act as delimiters */
#define SD_NOSKIPCMD 0x08 /* don't skip over $(, <(, or >( command/process substitution */
#define SD_EXTGLOB 0x10 /* skip over extended globbing patterns if appropriate */
extern int skip_to_delim __P((char *, int, char *, int));
+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
+4
View File
@@ -166,3 +166,7 @@ graph
yes
a
a
val
val
val
no arg passed
+2
View File
@@ -384,3 +384,5 @@ ${THIS_SH} ./exp1.sub
${THIS_SH} ./exp2.sub
${THIS_SH} ./exp3.sub
${THIS_SH} ./exp4.sub
+386
View File
@@ -0,0 +1,386 @@
#
# A suite of tests for bash word expansions
#
# This tests parameter and variable expansion, with an empahsis on
# proper quoting behavior.
#
# Chet Ramey
#
# If you comment out the body of this function, you can do a diff against
# `expansion-tests.right' to see if the shell is behaving correctly
#
expect()
{
echo expect "$@"
}
# Test the substitution quoting characters (CTLESC and CTLNUL) in different
# combinations
expect "<^A>"
recho `echo ''`
expect "<^A>"
recho `echo ""`
expect "<^B>"
recho `echo ''`
expect "<^B>"
recho `echo ""`
expect "<^A>"
recho `echo `
expect "<^B>"
recho `echo `
# Test null strings without variable expansion
expect "<abcdefgh>"
recho abcd""efgh
expect "<abcdefgh>"
recho abcd''efgh
expect "<abcdefgh>"
recho ""abcdefgh
expect "<abcdefgh>"
recho ''abcdefgh
expect "<abcd>"
recho abcd""
expect "<abcd>"
recho abcd''
# Test the quirky behavior of $@ in ""
expect nothing
recho "$@"
expect "< >"
recho " $@"
expect "<-->"
recho "-${@}-"
# Test null strings with variable expansion that fails
expect '<>'
recho $xxx""
expect '<>'
recho ""$xxx
expect '<>'
recho $xxx''
expect '<>'
recho ''$xxx
expect '<>'
recho $xxx""$yyy
expect '<>'
recho $xxx''$yyy
# Test null strings with variable expansion that succeeds
xxx=abc
yyy=def
expect '<abc>'
recho $xxx""
expect '<abc>'
recho ""$xxx
expect '<abc>'
recho $xxx''
expect '<abc>'
recho ''$xxx
expect '<abcdef>'
recho $xxx""$yyy
expect '<abcdef>'
recho $xxx''$yyy
unset xxx yyy
# Test the unquoted special quoting characters
expect "<^A>"
recho 
expect "<^B>"
recho 
expect "<^A>"
recho ""
expect "<^B>"
recho ""
expect "<^A>"
recho ''
expect "<^B>"
recho ''
# Test expansion of a variable that is unset
expect nothing
recho $xxx
expect '<>'
recho "$xxx"
expect nothing
recho "$xxx${@}"
# Test empty string expansion
expect '<>'
recho ""
expect '<>'
recho ''
# Test command substitution with (disabled) history substitution
expect '<Hello World!>'
# set +H
recho "`echo \"Hello world!\"`"
# Test some shell special characters
expect '<`>'
recho "\`"
expect '<">'
recho "\""
expect '<\^A>'
recho "\"
expect '<\$>'
recho "\\$"
expect '<\\>'
recho "\\\\"
# This should give argv[1] = a argv[2] = b
expect '<a> <b>'
FOO=`echo 'a b' | tr ' ' '\012'`
recho $FOO
# This should give argv[1] = ^A argv[2] = ^B
expect '<^A> <^B>'
FOO=`echo ' ' | tr ' ' '\012'`
recho $FOO
# Test quoted and unquoted globbing characters
expect '<**>'
recho "*"*
expect '<\.\./*/>'
recho "\.\./*/"
# Test patterns that come up when the shell quotes funny character
# combinations
expect '<^A^B^A^B>'
recho ''
expect '<^A^A>'
recho ''
expect '<^A^B>'
recho ''
expect '<^A^A^B>'
recho ''
# More tests of "$@"
set abc def ghi jkl
expect '< abc> <def> <ghi> <jkl >'
recho " $@ "
expect '< abc> <def> <ghi> <jkl >'
recho "${1+ $@ }"
set abc def ghi jkl
expect '<--abc> <def> <ghi> <jkl-->'
recho "--$@--"
set "a b" cd ef gh
expect '<a b> <cd> <ef> <gh>'
recho ${1+"$@"}
expect '<a b> <cd> <ef> <gh>'
recho ${foo:-"$@"}
expect '<a b> <cd> <ef> <gh>'
recho "${@}"
expect '< >'
recho " "
expect '< - >'
recho " - "
# Test combinations of different types of quoting in a fully-quoted string
# (so the WHOLLY_QUOTED tests fail and it doesn't get set)
expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>'
recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/"
# Test the various Posix parameter expansions
expect '<foo bar>'
recho "${x:-$(echo "foo bar")}"
expect '<foo> <bar>'
recho ${x:-$(echo "foo bar")}
unset X
expect '<abc>'
recho ${X:=abc}
expect '<abc>'
recho $X
set a b c
expect '<posix>'
recho ${3:+posix}
POSIX=/usr/posix
expect '<10>'
recho ${#POSIX}
# remove shortest trailing match
x=file.c
expect '<file.o>'
recho ${x%.c}.o
# remove longest trailing match
x=posix/src/std
expect '<posix>'
recho ${x%%/*}
# remove shortest leading pattern
x=$HOME/src/cmd
expect '</src/cmd>'
recho ${x#$HOME}
# remove longest leading pattern
x=/one/two/three
expect '<three>'
recho ${x##*/}
# pattern removal of patterns that don't match
z=abcdef
expect '<abcdef>'
recho ${z#xyz}
expect '<abcdef>'
recho ${z##xyz}
expect '<abcdef>'
recho ${z%xyz}
expect '<abcdef>'
recho ${z%%xyz}
# Command substitution and the quirky differences between `` and $()
expect '<\$x>'
recho '\$x'
expect '<$x>'
recho `echo '\$x'`
expect '<\$x>'
recho $(echo '\$x')
# The difference between $* "$*" and "$@"
set "abc" "def ghi" "jkl"
expect '<abc> <def> <ghi> <jkl>'
recho $*
expect '<abc def ghi jkl>'
recho "$*"
OIFS="$IFS"
IFS=":$IFS"
# The special behavior of "$*", using the first character of $IFS as separator
expect '<abc:def ghi:jkl>'
recho "$*"
IFS="$OIFS"
expect '<abc> <def ghi> <jkl>'
recho "$@"
expect '<xxabc> <def ghi> <jklyy>'
recho "xx$@yy"
expect '<abc> <def ghi> <jklabc> <def ghi> <jkl>'
recho "$@$@"
foo=abc
bar=def
expect '<abcdef>'
recho "$foo""$bar"
unset foo
set $foo bar '' xyz "$foo" abc
expect '<bar> <> <xyz> <> <abc>'
recho "$@"
# More tests of quoting and deferred evaluation
foo=10 x=foo
y='$'$x
expect '<$foo>'
recho $y
eval y='$'$x
expect '<10>'
recho $y
# case statements
NL='
'
x='ab
cd'
expect '<newline expected>'
case "$x" in
*$NL*) recho "newline expected" ;;
esac
expect '<got it>'
case \? in
*"?"*) recho "got it" ;;
esac
expect '<got it>'
case \? in
*\?*) recho "got it" ;;
esac
set one two three four five
expect '<one> <three> <five>'
recho $1 $3 ${5} $8 ${9}
# length tests on positional parameters and some special parameters
expect '<5> <5>'
recho $# ${#}
expect '<3>'
recho ${#1}
expect '<1>'
recho ${##}
expect '<1>'
recho ${#?}
expect '<5>'
recho ${#@}
expect '<5>'
recho ${#*}
expect '<5>'
recho "${#@}"
expect '<5>'
recho "${#*}"
expect '<42>'
recho $((28 + 14))
expect '<26>'
recho $[ 13 * 2 ]
expect '<\>'
recho `echo \\\\`
expect '<~>'
recho '~'
expect nothing
recho $!
expect nothing
recho ${!}
# test word splitting of assignment statements not preceding a command
a="a b c d e"
declare b=$a
expect '<a> <b> <c> <d> <e>'
recho $b
a="a?b?c"
echo ${a//\\?/ }
echo ${a//\?/ }
${THIS_SH} ./exp1.sub
${THIS_SH} ./exp2.sub
${THIS_SH} ./exp3.sub
+10
View File
@@ -0,0 +1,10 @@
f=" val" e=
echo "$e"$f
echo $e$f
echo "$e""$f"
if [[ "$1"x == x ]] ; then
echo "no arg passed"
exit 1
fi
echo "$1"x | cat -v
+6
View File
@@ -11,3 +11,9 @@ aéb
-абвгдежзиклмноп - 16
-абвгдежзиклмноп- 15
-абвгд- 5
1,0000
1.0000
1.0000
1.0000
1.0000
1,0000
+3
View File
@@ -39,3 +39,6 @@ printf '%s' "$*" | od -b
# display differences make this problematic
${THIS_SH} ./intl1.sub
# this tests both international handling in printf and temporary environments
${THIS_SH} ./intl2.sub
+41
View File
@@ -0,0 +1,41 @@
export LC_ALL=en_US.UTF-8
a=$'\303\251'
echo "$a"
echo ${#a}
b=$'A\303\251B'
echo "$b"
echo ${b: -1}
c=AeB
echo ${c: -1}
unset a
a=$(printf '%b' 'A\303\251B')
IFS=$(printf '%b' '\303\251')
case "$a" in
"A${IFS}B") echo ok 1 ;;
*) echo bad 1 ;;
esac
set $a
case $1 in
A) echo ok 2 ;;
*) echo bad 2 ;;
esac
set a b
printf '%s\n' "$*"
printf '%s' "$*" | od -b
# display differences make this problematic
${THIS_SH} ./intl1.sub
+11
View File
@@ -0,0 +1,11 @@
unset LC_ALL LC_NUMERIC
export LANG=de_DE.UTF-8
printf '%.4f\n' 1
LANG=C printf '%.4f\n' 1
LANG=C /usr/bin/printf '%.4f\n' 1
env LANG=C printf '%.4f\n' 1
(LANG=C; printf '%.4f\n' 1)
printf '%.4f\n' 1
+1
View File
@@ -48,6 +48,7 @@
#include "unwind_prot.h"
#include "quit.h"
#include "sig.h"
#include "error.h" /* for internal_warning */
/* Structure describing a saved variable and the value to restore it to. */
typedef struct {
+38 -9
View File
@@ -1235,10 +1235,6 @@ static int seeded_subshell = 0;
static int
brand ()
{
#if 0
rseed = rseed * 1103515245 + 12345;
return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */
#else
/* From "Random number generators: good ones are hard to find",
Park and Miller, Communications of the ACM, vol. 31, no. 10,
October 1988, p. 1195. filtered through FreeBSD */
@@ -1254,7 +1250,6 @@ brand ()
rseed += 0x7fffffff;
#endif
return ((unsigned int)(rseed & 32767)); /* was % 32768 */
#endif
}
/* Set the random number generator seed to SEED. */
@@ -2491,8 +2486,9 @@ bind_function_def (name, value)
responsible for moving the main temporary env to one of the other
temporary environments. The expansion code in subst.c calls this. */
int
assign_in_env (word)
assign_in_env (word, flags)
WORD_DESC *word;
int flags;
{
int offset;
char *name, *temp, *value;
@@ -2550,8 +2546,13 @@ assign_in_env (word)
array_needs_making = 1;
#if 0
if (ifsname (name))
setifs (var);
else
#endif
if (flags)
stupidly_hack_special_variables (name);
if (echo_command_at_execute)
/* The Korn shell prints the `+ ' in front of assignment statements,
@@ -3271,6 +3272,9 @@ find_tempenv_variable (name)
return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
}
char **tempvar_list;
int tvlist_ind;
/* Push the variable described by (SHELL_VAR *)DATA down to the next
variable context from the temporary environment. */
static void
@@ -3306,6 +3310,9 @@ push_temp_var (data)
}
v->attributes |= var->attributes;
if (find_special_var (var->name) >= 0)
tempvar_list[tvlist_ind++] = savestring (var->name);
dispose_variable (var);
}
@@ -3319,24 +3326,46 @@ propagate_temp_var (data)
if (tempvar_p (var) && (var->attributes & att_propagate))
push_temp_var (data);
else
dispose_variable (var);
{
if (find_special_var (var->name) >= 0)
tempvar_list[tvlist_ind++] = savestring (var->name);
dispose_variable (var);
}
}
/* Free the storage used in the hash table for temporary
environment variables. PUSHF is a function to be called
to free each hash table entry. It takes care of pushing variables
to previous scopes if appropriate. */
to previous scopes if appropriate. PUSHF stores names of variables
that require special handling (e.g., IFS) on tempvar_list, so this
function can call stupidly_hack_special_variables on all the
variables in the list when the temporary hash table is destroyed. */
static void
dispose_temporary_env (pushf)
sh_free_func_t *pushf;
{
int i;
tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
tempvar_list[tvlist_ind = 0] = 0;
hash_flush (temporary_env, pushf);
hash_dispose (temporary_env);
temporary_env = (HASH_TABLE *)NULL;
tempvar_list[tvlist_ind] = 0;
array_needs_making = 1;
sv_ifs ("IFS"); /* XXX here for now */
#if 0
sv_ifs ("IFS"); /* XXX here for now -- check setifs in assign_in_env */
#endif
for (i = 0; i < tvlist_ind; i++)
stupidly_hack_special_variables (tempvar_list[i]);
strvec_dispose (tempvar_list);
tempvar_list = 0;
tvlist_ind = 0;
}
void
+40 -11
View File
@@ -83,7 +83,7 @@ extern char **environ;
/* Variables used here and defined in other files. */
extern int posixly_correct;
extern int line_number;
extern int line_number, line_number_base;
extern int subshell_environment, indirection_level, subshell_level;
extern int build_version, patch_level;
extern int expanding_redir;
@@ -1235,10 +1235,6 @@ static int seeded_subshell = 0;
static int
brand ()
{
#if 0
rseed = rseed * 1103515245 + 12345;
return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */
#else
/* From "Random number generators: good ones are hard to find",
Park and Miller, Communications of the ACM, vol. 31, no. 10,
October 1988, p. 1195. filtered through FreeBSD */
@@ -1254,7 +1250,6 @@ brand ()
rseed += 0x7fffffff;
#endif
return ((unsigned int)(rseed & 32767)); /* was % 32768 */
#endif
}
/* Set the random number generator seed to SEED. */
@@ -1336,7 +1331,7 @@ assign_lineno (var, value, unused, key)
if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
new_value = 0;
line_number = new_value;
line_number = line_number_base = new_value;
return var;
}
@@ -2491,8 +2486,9 @@ bind_function_def (name, value)
responsible for moving the main temporary env to one of the other
temporary environments. The expansion code in subst.c calls this. */
int
assign_in_env (word)
assign_in_env (word, flags)
WORD_DESC *word;
int flags;
{
int offset;
char *name, *temp, *value;
@@ -2550,8 +2546,13 @@ assign_in_env (word)
array_needs_making = 1;
#if 0
if (ifsname (name))
setifs (var);
else
#endif
if (flags)
stupidly_hack_special_variables (name);
if (echo_command_at_execute)
/* The Korn shell prints the `+ ' in front of assignment statements,
@@ -3271,6 +3272,9 @@ find_tempenv_variable (name)
return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
}
char **tempvar_list;
int tvlist_ind;
/* Push the variable described by (SHELL_VAR *)DATA down to the next
variable context from the temporary environment. */
static void
@@ -3306,6 +3310,9 @@ push_temp_var (data)
}
v->attributes |= var->attributes;
if (find_special_var (var->name))
tempvar_list[tvlist_ind++] = savestring (var->name);
dispose_variable (var);
}
@@ -3319,24 +3326,46 @@ propagate_temp_var (data)
if (tempvar_p (var) && (var->attributes & att_propagate))
push_temp_var (data);
else
dispose_variable (var);
{
if (find_special_var (var->name))
tempvar_list[tvlist_ind++] = savestring (var->name);
dispose_variable (var);
}
}
/* Free the storage used in the hash table for temporary
environment variables. PUSHF is a function to be called
to free each hash table entry. It takes care of pushing variables
to previous scopes if appropriate. */
to previous scopes if appropriate. PUSHF stores names of variables
that require special handling (e.g., IFS) on tempvar_list, so this
function can call stupidly_hack_special_variables on all the
variables in the list when the temporary hash table is destroyed. */
static void
dispose_temporary_env (pushf)
sh_free_func_t *pushf;
{
int i;
tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
tempvar_list[tvlist_ind = 0] = 0;
hash_flush (temporary_env, pushf);
hash_dispose (temporary_env);
temporary_env = (HASH_TABLE *)NULL;
tempvar_list[tvlist_ind] = 0;
array_needs_making = 1;
sv_ifs ("IFS"); /* XXX here for now */
#if 0
sv_ifs ("IFS"); /* XXX here for now -- check setifs in assign_in_env */
#endif
for (i = 0; i < tvlist_ind; i++)
stupidly_hack_special_variables (tempvar_list[i]);
strvec_dispose (tempvar_list);
tempvar_list = 0;
tvlist_ind = 0;
}
void
+1 -1
View File
@@ -270,7 +270,7 @@ extern SHELL_VAR *bind_variable_value __P((SHELL_VAR *, char *, int));
extern SHELL_VAR *bind_int_variable __P((char *, char *));
extern SHELL_VAR *bind_var_to_int __P((char *, intmax_t));
extern int assign_in_env __P((WORD_DESC *));
extern int assign_in_env __P((WORD_DESC *, int));
extern int unbind_variable __P((const char *));
extern int unbind_func __P((const char *));
+1 -1
View File
@@ -1,6 +1,6 @@
/* variables.h -- data structures for shell variables. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
+825 -533
View File
File diff suppressed because it is too large Load Diff
+27 -16
View File
@@ -1,7 +1,9 @@
/* A Bison parser, made by GNU Bison 2.0. */
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
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
@@ -15,13 +17,21 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
@@ -78,6 +88,7 @@
yacc_EOF = 304
};
#endif
/* Tokens. */
#define IF 258
#define THEN 259
#define ELSE 260
@@ -129,9 +140,10 @@
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 323 "parse.y"
typedef union YYSTYPE {
{
WORD_DESC *word; /* the word that we read. */
int number; /* the number that we read. */
WORD_LIST *word_list;
@@ -139,9 +151,10 @@ typedef union YYSTYPE {
REDIRECT *redirect;
ELEMENT element;
PATTERN_LIST *pattern;
} YYSTYPE;
/* Line 1274 of yacc.c. */
#line 145 "y.tab.h"
}
/* Line 1489 of yacc.c. */
#line 157 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
@@ -149,5 +162,3 @@ typedef union YYSTYPE {
extern YYSTYPE yylval;