mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 15:43:18 +02:00
commit bash-20070405 snapshot
This commit is contained in:
@@ -14458,3 +14458,45 @@ mailcheck.h
|
||||
|
||||
shell.c
|
||||
- call init_mail_dates instead of remember_mail_dates
|
||||
|
||||
4/4
|
||||
---
|
||||
builtins/read.def
|
||||
- changes to print $PS2 when a line is continued with a backslash in
|
||||
an interactive shell. This is as POSIX requires
|
||||
|
||||
4/5
|
||||
---
|
||||
subst.c
|
||||
- make sure quote_escapes is only ever called when the word to be
|
||||
escaped is not marked as double-quoted -- cleaner, and allows us
|
||||
to make certain assumptions
|
||||
|
||||
4/6
|
||||
---
|
||||
subst.c
|
||||
- change all EX_* defines to begin with SX_
|
||||
- new flag, SX_NOCTLESC, obeyed by string_extract_verbatim, tells it
|
||||
to not obey CTLESC quoting
|
||||
- change quote_escapes to not quote CTLESC with CTLESC if one of the
|
||||
chars in $IFS is CTLESC, since the return value from quote_string
|
||||
will be passed to word splitting and filename generation
|
||||
- change read_comsub to do the same thing for unquoted command
|
||||
substitutions
|
||||
- change list_string to pass SX_NOCTLESC if CTLESC is one of the
|
||||
chars in $IFS, so it will split on CTLESC instead of using it as a
|
||||
quote character
|
||||
|
||||
4/7
|
||||
---
|
||||
subst.c
|
||||
- slight change to string_extract_verbatim to allow CTLESC to quote
|
||||
CTLNUL even if SX_NOCTLESC is set in the flags passed, to protect
|
||||
the CTLNULs from future calls to remove_quoted_nulls. Only
|
||||
matters when $IFS contains CTLESC
|
||||
- changes to cope with $IFS containing CTLNUL in the same way as the
|
||||
CTLESC changes
|
||||
|
||||
builtins/read.def
|
||||
- changes to cope with $IFS containing CTLNUL in the same way as the
|
||||
CTLESC changes
|
||||
|
||||
+39
-2
@@ -14444,8 +14444,9 @@ doc/Makefile.in
|
||||
mailcheck.c
|
||||
- new function, init_mail_dates, calls remember_mail_dates only if
|
||||
there are no mailboxes in `mailfiles'
|
||||
- new function, init_mail_file, just calls RESET_MAIL_FILE (placeholder
|
||||
for later expansion)
|
||||
- new function, init_mail_file, initializes a FILEINFO, using the
|
||||
last time mail was checked as the mtime and atime (or the time the
|
||||
shell was started if last_time_mail_checked is uninitialized)
|
||||
- call init_mail_file instead of update_mail_file in add_mail_file,
|
||||
called from remember_mail_dates (which is supposed to initialize
|
||||
the list of mail files)
|
||||
@@ -14457,3 +14458,39 @@ mailcheck.h
|
||||
|
||||
shell.c
|
||||
- call init_mail_dates instead of remember_mail_dates
|
||||
|
||||
4/4
|
||||
---
|
||||
builtins/read.def
|
||||
- changes to print $PS2 when a line is continued with a backslash in
|
||||
an interactive shell. This is as POSIX requires
|
||||
|
||||
4/5
|
||||
---
|
||||
subst.c
|
||||
- make sure quote_escapes is only ever called when the word to be
|
||||
escaped is not marked as double-quoted -- cleaner, and allows us
|
||||
to make certain assumptions
|
||||
|
||||
4/6
|
||||
---
|
||||
subst.c
|
||||
- change all EX_* defines to begin with SX_
|
||||
- new flag, SX_NOCTLESC, obeyed by string_extract_verbatim, tells it
|
||||
to not obey CTLESC quoting
|
||||
- change quote_escapes to not quote CTLESC with CTLESC if one of the
|
||||
chars in $IFS is CTLESC, since the return value from quote_string
|
||||
will be passed to word splitting and filename generation
|
||||
- change read_comsub to do the same thing for unquoted command
|
||||
substitutions
|
||||
- change list_string to pass SX_NOCTLESC if CTLESC is one of the
|
||||
chars in $IFS, so it will split on CTLESC instead of using it as a
|
||||
quote character
|
||||
|
||||
4/7
|
||||
---
|
||||
subst.c
|
||||
- slight change to string_extract_verbatim to allow CTLESC to quote
|
||||
CTLNUL even if SX_NOCTLESC is set in the flags passed, to protect
|
||||
the CTLNULs from future calls to remove_quoted_nulls. Only
|
||||
matters when $IFS contains CTLESC
|
||||
|
||||
@@ -702,6 +702,8 @@ tests/array1.sub f
|
||||
tests/array2.sub f
|
||||
tests/array3.sub f
|
||||
tests/array4.sub f
|
||||
tests/array5.sub f
|
||||
tests/array6.sub f
|
||||
tests/array-at-star f
|
||||
tests/array2.right f
|
||||
tests/braces.tests f
|
||||
@@ -749,8 +751,9 @@ tests/exec4.sub f
|
||||
tests/exec5.sub f
|
||||
tests/exec6.sub f
|
||||
tests/exec7.sub f
|
||||
tests/exp-tests f
|
||||
tests/exp.tests f
|
||||
tests/exp.right f
|
||||
tests/exp1.sub f
|
||||
tests/extglob.tests f
|
||||
tests/extglob.right f
|
||||
tests/extglob1.sub f
|
||||
@@ -823,6 +826,8 @@ tests/nquote3.tests f
|
||||
tests/nquote3.right f
|
||||
tests/nquote4.tests f
|
||||
tests/nquote4.right f
|
||||
tests/nquote5.tests f
|
||||
tests/nquote5.right f
|
||||
tests/posix2.tests f
|
||||
tests/posix2.right f
|
||||
tests/posixpat.tests f
|
||||
@@ -900,6 +905,7 @@ tests/run-nquote1 f
|
||||
tests/run-nquote2 f
|
||||
tests/run-nquote3 f
|
||||
tests/run-nquote4 f
|
||||
tests/run-nquote5 f
|
||||
tests/run-posix2 f
|
||||
tests/run-posixpat f
|
||||
tests/run-precedence f
|
||||
|
||||
+31
-9
@@ -1,7 +1,7 @@
|
||||
This file is read.def, from which is created read.c.
|
||||
It implements the builtin "read" in Bash.
|
||||
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -127,14 +127,14 @@ read_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register char *varname;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
|
||||
int raw, edit, nchars, silent, have_timeout, fd;
|
||||
unsigned int tmout;
|
||||
intmax_t intval;
|
||||
char c;
|
||||
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
|
||||
char *e, *t, *t1;
|
||||
char *e, *t, *t1, *ps2;
|
||||
struct stat tsb;
|
||||
SHELL_VAR *var;
|
||||
#if defined (ARRAY_VARS)
|
||||
@@ -148,6 +148,7 @@ read_builtin (list)
|
||||
USE_VAR(size);
|
||||
USE_VAR(i);
|
||||
USE_VAR(pass_next);
|
||||
USE_VAR(print_ps2);
|
||||
USE_VAR(saw_escape);
|
||||
USE_VAR(input_is_pipe);
|
||||
/* USE_VAR(raw); */
|
||||
@@ -163,6 +164,7 @@ read_builtin (list)
|
||||
USE_VAR(rlind);
|
||||
#endif
|
||||
USE_VAR(list);
|
||||
USE_VAR(ps2);
|
||||
|
||||
i = 0; /* Index into the string that we are reading. */
|
||||
raw = edit = 0; /* Not reading raw input by default. */
|
||||
@@ -261,6 +263,8 @@ read_builtin (list)
|
||||
ifs_chars = getifs ();
|
||||
if (ifs_chars == 0) /* XXX - shouldn't happen */
|
||||
ifs_chars = "";
|
||||
for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
|
||||
skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
|
||||
|
||||
input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
|
||||
|
||||
@@ -386,7 +390,8 @@ read_builtin (list)
|
||||
setmode (0, O_TEXT);
|
||||
#endif
|
||||
|
||||
for (eof = retval = 0;;)
|
||||
ps2 = 0;
|
||||
for (print_ps2 = eof = retval = 0;;)
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
@@ -412,6 +417,15 @@ read_builtin (list)
|
||||
{
|
||||
#endif
|
||||
|
||||
if (print_ps2)
|
||||
{
|
||||
if (ps2 == 0)
|
||||
ps2 = get_string_value ("PS2");
|
||||
fprintf (stderr, "%s", ps2 ? ps2 : "");
|
||||
fflush (stderr);
|
||||
print_ps2 = 0;
|
||||
}
|
||||
|
||||
if (unbuffered_read)
|
||||
retval = zread (fd, &c, 1);
|
||||
else
|
||||
@@ -440,24 +454,32 @@ read_builtin (list)
|
||||
{
|
||||
pass_next = 0;
|
||||
if (c == '\n')
|
||||
i--; /* back up over the CTLESC */
|
||||
{
|
||||
i--; /* back up over the CTLESC */
|
||||
if (interactive && raw == 0)
|
||||
print_ps2 = 1;
|
||||
}
|
||||
else
|
||||
goto add_char;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This may cause problems if IFS contains CTLESC */
|
||||
if (c == '\\' && raw == 0)
|
||||
{
|
||||
pass_next++;
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
if (skip_ctlesc == 0)
|
||||
{
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((unsigned char)c == delim)
|
||||
break;
|
||||
|
||||
if (c == CTLESC || c == CTLNUL)
|
||||
if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
|
||||
{
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
|
||||
@@ -0,0 +1,806 @@
|
||||
This file is read.def, from which is created read.c.
|
||||
It implements the builtin "read" in Bash.
|
||||
|
||||
Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
$PRODUCES read.c
|
||||
|
||||
$BUILTIN read
|
||||
$FUNCTION read_builtin
|
||||
$SHORT_DOC read [-ers] [-a array] [-d delim] [-n nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
|
||||
One line is read from the standard input, or from file descriptor FD if the
|
||||
-u option is supplied, and the first word is assigned to the first NAME,
|
||||
the second word to the second NAME, and so on, with leftover words assigned
|
||||
to the last NAME. Only the characters found in $IFS are recognized as word
|
||||
delimiters. If no NAMEs are supplied, the line read is stored in the REPLY
|
||||
variable. If the -r option is given, this signifies `raw' input, and
|
||||
backslash escaping is disabled. The -d option causes read to continue
|
||||
until the first character of DELIM is read, rather than newline. If the -p
|
||||
option is supplied, the string PROMPT is output without a trailing newline
|
||||
before attempting to read. If -a is supplied, the words read are assigned
|
||||
to sequential indices of ARRAY, starting at zero. If -e is supplied and
|
||||
the shell is interactive, readline is used to obtain the line. If -n is
|
||||
supplied with a non-zero NCHARS argument, read returns after NCHARS
|
||||
characters have been read. The -s option causes input coming from a
|
||||
terminal to not be echoed.
|
||||
|
||||
The -t option causes read to time out and return failure if a complete line
|
||||
of input is not read within TIMEOUT seconds. If the TMOUT variable is set,
|
||||
its value is the default timeout. The return code is zero, unless end-of-file
|
||||
is encountered, read times out, or an invalid file descriptor is supplied as
|
||||
the argument to -u.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include "posixstat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
# include <fcntl.h>
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#include <shtty.h>
|
||||
|
||||
#if defined (READLINE)
|
||||
#include "../bashline.h"
|
||||
#include <readline/readline.h>
|
||||
#endif
|
||||
|
||||
#if defined (BUFFERED_INPUT)
|
||||
# include "input.h"
|
||||
#endif
|
||||
|
||||
#if !defined(errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if defined (READLINE)
|
||||
static void reset_attempted_completion_function __P((char *));
|
||||
static char *edit_line __P((char *));
|
||||
static void set_eol_delim __P((int));
|
||||
static void reset_eol_delim __P((char *));
|
||||
#endif
|
||||
static SHELL_VAR *bind_read_variable __P((char *, char *));
|
||||
|
||||
static sighandler sigalrm __P((int));
|
||||
static void reset_alarm __P((void));
|
||||
|
||||
static procenv_t alrmbuf;
|
||||
static SigHandler *old_alrm;
|
||||
static unsigned char delim;
|
||||
|
||||
static sighandler
|
||||
sigalrm (s)
|
||||
int s;
|
||||
{
|
||||
longjmp (alrmbuf, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_alarm ()
|
||||
{
|
||||
set_signal_handler (SIGALRM, old_alrm);
|
||||
alarm (0);
|
||||
}
|
||||
|
||||
/* Read the value of the shell variables whose names follow.
|
||||
The reading is done from the current input stream, whatever
|
||||
that may be. Successive words of the input line are assigned
|
||||
to the variables mentioned in LIST. The last variable in LIST
|
||||
gets the remainder of the words on the line. If no variables
|
||||
are mentioned in LIST, then the default variable is $REPLY. */
|
||||
int
|
||||
read_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register char *varname;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc;
|
||||
int raw, edit, nchars, silent, have_timeout, fd;
|
||||
unsigned int tmout;
|
||||
intmax_t intval;
|
||||
char c;
|
||||
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
|
||||
char *e, *t, *t1, *ps2;
|
||||
struct stat tsb;
|
||||
SHELL_VAR *var;
|
||||
#if defined (ARRAY_VARS)
|
||||
WORD_LIST *alist;
|
||||
#endif
|
||||
#if defined (READLINE)
|
||||
char *rlbuf;
|
||||
int rlind;
|
||||
#endif
|
||||
|
||||
USE_VAR(size);
|
||||
USE_VAR(i);
|
||||
USE_VAR(pass_next);
|
||||
USE_VAR(print_ps2);
|
||||
USE_VAR(saw_escape);
|
||||
USE_VAR(input_is_pipe);
|
||||
/* USE_VAR(raw); */
|
||||
USE_VAR(edit);
|
||||
USE_VAR(tmout);
|
||||
USE_VAR(nchars);
|
||||
USE_VAR(silent);
|
||||
USE_VAR(ifs_chars);
|
||||
USE_VAR(prompt);
|
||||
USE_VAR(arrayname);
|
||||
#if defined (READLINE)
|
||||
USE_VAR(rlbuf);
|
||||
USE_VAR(rlind);
|
||||
#endif
|
||||
USE_VAR(list);
|
||||
USE_VAR(ps2);
|
||||
|
||||
i = 0; /* Index into the string that we are reading. */
|
||||
raw = edit = 0; /* Not reading raw input by default. */
|
||||
silent = 0;
|
||||
arrayname = prompt = (char *)NULL;
|
||||
fd = 0; /* file descriptor to read from */
|
||||
|
||||
#if defined (READLINE)
|
||||
rlbuf = (char *)0;
|
||||
rlind = 0;
|
||||
#endif
|
||||
|
||||
tmout = 0; /* no timeout */
|
||||
nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
|
||||
delim = '\n'; /* read until newline */
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "ersa:d:n:p:t:u:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'r':
|
||||
raw = 1;
|
||||
break;
|
||||
case 'p':
|
||||
prompt = list_optarg;
|
||||
break;
|
||||
case 's':
|
||||
silent = 1;
|
||||
break;
|
||||
case 'e':
|
||||
#if defined (READLINE)
|
||||
edit = 1;
|
||||
#endif
|
||||
break;
|
||||
#if defined (ARRAY_VARS)
|
||||
case 'a':
|
||||
arrayname = list_optarg;
|
||||
break;
|
||||
#endif
|
||||
case 't':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned int)intval)
|
||||
{
|
||||
builtin_error (_("%s: invalid timeout specification"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
have_timeout = 1;
|
||||
tmout = intval;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (int)intval)
|
||||
{
|
||||
sh_invalidnum (list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
nchars = intval;
|
||||
break;
|
||||
case 'u':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (int)intval)
|
||||
{
|
||||
builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
fd = intval;
|
||||
if (sh_validfd (fd) == 0)
|
||||
{
|
||||
builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
delim = *list_optarg;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
/* `read -t 0 var' returns failure immediately. XXX - should it test
|
||||
whether input is available with select/FIONREAD, and fail if those
|
||||
are unavailable? */
|
||||
if (have_timeout && tmout == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
/* IF IFS is unset, we use the default of " \t\n". */
|
||||
ifs_chars = getifs ();
|
||||
if (ifs_chars == 0) /* XXX - shouldn't happen */
|
||||
ifs_chars = "";
|
||||
for (skip_ctlesc = 0, e = ifs_chars; *e; e++)
|
||||
skip_ctlesc |= *e == CTLESC;
|
||||
|
||||
input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
|
||||
|
||||
/* $TMOUT, if set, is the default timeout for read. */
|
||||
if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
|
||||
{
|
||||
code = legal_number (e, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned int)intval)
|
||||
tmout = 0;
|
||||
else
|
||||
tmout = intval;
|
||||
}
|
||||
|
||||
begin_unwind_frame ("read_builtin");
|
||||
|
||||
#if defined (BUFFERED_INPUT)
|
||||
if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
|
||||
sync_buffered_stream (default_buffered_input);
|
||||
#endif
|
||||
|
||||
input_is_tty = isatty (fd);
|
||||
if (input_is_tty == 0)
|
||||
#ifndef __CYGWIN__
|
||||
input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
|
||||
#else
|
||||
input_is_pipe = 1;
|
||||
#endif
|
||||
|
||||
/* If the -p, -e or -s flags were given, but input is not coming from the
|
||||
terminal, turn them off. */
|
||||
if ((prompt || edit || silent) && input_is_tty == 0)
|
||||
{
|
||||
prompt = (char *)NULL;
|
||||
edit = silent = 0;
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
add_unwind_protect (xfree, rlbuf);
|
||||
#endif
|
||||
|
||||
if (prompt && edit == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", prompt);
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
pass_next = 0; /* Non-zero signifies last char was backslash. */
|
||||
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
|
||||
|
||||
if (tmout > 0)
|
||||
{
|
||||
/* Turn off the timeout if stdin is a regular file (e.g. from
|
||||
input redirection). */
|
||||
if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
|
||||
tmout = 0;
|
||||
}
|
||||
|
||||
if (tmout > 0)
|
||||
{
|
||||
code = setjmp (alrmbuf);
|
||||
if (code)
|
||||
{
|
||||
run_unwind_frame ("read_builtin");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
old_alrm = set_signal_handler (SIGALRM, sigalrm);
|
||||
add_unwind_protect (reset_alarm, (char *)NULL);
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
|
||||
#endif
|
||||
alarm (tmout);
|
||||
}
|
||||
|
||||
/* If we've been asked to read only NCHARS chars, or we're using some
|
||||
character other than newline to terminate the line, do the right
|
||||
thing to readline or the tty. */
|
||||
if (nchars > 0 || delim != '\n')
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
{
|
||||
if (nchars > 0)
|
||||
{
|
||||
unwind_protect_int (rl_num_chars_to_read);
|
||||
rl_num_chars_to_read = nchars;
|
||||
}
|
||||
if (delim != '\n')
|
||||
{
|
||||
set_eol_delim (delim);
|
||||
add_unwind_protect (reset_eol_delim, (char *)NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (input_is_tty)
|
||||
{
|
||||
ttsave ();
|
||||
if (silent)
|
||||
ttcbreak ();
|
||||
else
|
||||
ttonechar ();
|
||||
add_unwind_protect ((Function *)ttrestore, (char *)NULL);
|
||||
}
|
||||
}
|
||||
else if (silent) /* turn off echo but leave term in canonical mode */
|
||||
{
|
||||
ttsave ();
|
||||
ttnoecho ();
|
||||
add_unwind_protect ((Function *)ttrestore, (char *)NULL);
|
||||
}
|
||||
|
||||
/* This *must* be the top unwind-protect on the stack, so the manipulation
|
||||
of the unwind-protect stack after the realloc() works right. */
|
||||
add_unwind_protect (xfree, input_string);
|
||||
interrupt_immediately++;
|
||||
terminate_immediately = 1;
|
||||
|
||||
unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
|
||||
|
||||
#if defined (__CYGWIN__) && defined (O_TEXT)
|
||||
setmode (0, O_TEXT);
|
||||
#endif
|
||||
|
||||
ps2 = 0;
|
||||
for (print_ps2 = eof = retval = 0;;)
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
{
|
||||
if (rlbuf && rlbuf[rlind] == '\0')
|
||||
{
|
||||
xfree (rlbuf);
|
||||
rlbuf = (char *)0;
|
||||
}
|
||||
if (rlbuf == 0)
|
||||
{
|
||||
rlbuf = edit_line (prompt ? prompt : "");
|
||||
rlind = 0;
|
||||
}
|
||||
if (rlbuf == 0)
|
||||
{
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
c = rlbuf[rlind++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
|
||||
if (print_ps2)
|
||||
{
|
||||
if (ps2 == 0)
|
||||
ps2 = get_string_value ("PS2");
|
||||
fprintf (stderr, "%s", ps2 ? ps2 : "");
|
||||
fflush (stderr);
|
||||
print_ps2 = 0;
|
||||
}
|
||||
|
||||
if (unbuffered_read)
|
||||
retval = zread (fd, &c, 1);
|
||||
else
|
||||
retval = zreadc (fd, &c);
|
||||
|
||||
if (retval <= 0)
|
||||
{
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (i + 2 >= size)
|
||||
{
|
||||
input_string = (char *)xrealloc (input_string, size += 128);
|
||||
remove_unwind_protect ();
|
||||
add_unwind_protect (xfree, input_string);
|
||||
}
|
||||
|
||||
/* If the next character is to be accepted verbatim, a backslash
|
||||
newline pair still disappears from the input. */
|
||||
if (pass_next)
|
||||
{
|
||||
pass_next = 0;
|
||||
if (c == '\n')
|
||||
{
|
||||
i--; /* back up over the CTLESC */
|
||||
if (interactive && raw == 0)
|
||||
print_ps2 = 1;
|
||||
}
|
||||
else
|
||||
goto add_char;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This may cause problems if IFS contains CTLESC */
|
||||
if (c == '\\' && raw == 0)
|
||||
{
|
||||
pass_next++;
|
||||
if (skip_ctlesc == 0)
|
||||
{
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((unsigned char)c == delim)
|
||||
break;
|
||||
|
||||
if ((skip_ctlesc == 0 && c == CTLESC) || c == CTLNUL)
|
||||
{
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
}
|
||||
|
||||
add_char:
|
||||
input_string[i++] = c;
|
||||
nr++;
|
||||
|
||||
if (nchars > 0 && nr >= nchars)
|
||||
break;
|
||||
}
|
||||
input_string[i] = '\0';
|
||||
|
||||
#if 1
|
||||
if (retval < 0)
|
||||
{
|
||||
builtin_error (_("read error: %d: %s"), fd, strerror (errno));
|
||||
run_unwind_frame ("read_builtin");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmout > 0)
|
||||
reset_alarm ();
|
||||
|
||||
if (nchars > 0 || delim != '\n')
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
{
|
||||
if (nchars > 0)
|
||||
rl_num_chars_to_read = 0;
|
||||
if (delim != '\n')
|
||||
reset_eol_delim ((char *)NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (input_is_tty)
|
||||
ttrestore ();
|
||||
}
|
||||
else if (silent)
|
||||
ttrestore ();
|
||||
|
||||
if (unbuffered_read == 0)
|
||||
zsyncfd (fd);
|
||||
|
||||
interrupt_immediately--;
|
||||
terminate_immediately = 0;
|
||||
discard_unwind_frame ("read_builtin");
|
||||
|
||||
retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
/* If -a was given, take the string read, break it into a list of words,
|
||||
an assign them to `arrayname' in turn. */
|
||||
if (arrayname)
|
||||
{
|
||||
if (legal_identifier (arrayname) == 0)
|
||||
{
|
||||
sh_invalidid (arrayname);
|
||||
xfree (input_string);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
var = find_or_make_array_variable (arrayname, 1);
|
||||
if (var == 0)
|
||||
{
|
||||
xfree (input_string);
|
||||
return EXECUTION_FAILURE; /* readonly or noassign */
|
||||
}
|
||||
array_flush (array_cell (var));
|
||||
|
||||
alist = list_string (input_string, ifs_chars, 0);
|
||||
if (alist)
|
||||
{
|
||||
if (saw_escape)
|
||||
dequote_list (alist);
|
||||
else
|
||||
word_list_remove_quoted_nulls (alist);
|
||||
assign_array_var_from_word_list (var, alist, 0);
|
||||
dispose_words (alist);
|
||||
}
|
||||
xfree (input_string);
|
||||
return (retval);
|
||||
}
|
||||
#endif /* ARRAY_VARS */
|
||||
|
||||
/* If there are no variables, save the text of the line read to the
|
||||
variable $REPLY. ksh93 strips leading and trailing IFS whitespace,
|
||||
so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
|
||||
same way, but I believe that the difference in behaviors is useful
|
||||
enough to not do it. Without the bash behavior, there is no way
|
||||
to read a line completely without interpretation or modification
|
||||
unless you mess with $IFS (e.g., setting it to the empty string).
|
||||
If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
|
||||
if (list == 0)
|
||||
{
|
||||
#if 0
|
||||
orig_input_string = input_string;
|
||||
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
|
||||
;
|
||||
input_string = t;
|
||||
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
|
||||
#endif
|
||||
|
||||
if (saw_escape)
|
||||
{
|
||||
t = dequote_string (input_string);
|
||||
var = bind_variable ("REPLY", t, 0);
|
||||
free (t);
|
||||
}
|
||||
else
|
||||
var = bind_variable ("REPLY", input_string, 0);
|
||||
VUNSETATTR (var, att_invisible);
|
||||
|
||||
free (input_string);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* This code implements the Posix.2 spec for splitting the words
|
||||
read and assigning them to variables. */
|
||||
orig_input_string = input_string;
|
||||
|
||||
/* Remove IFS white space at the beginning of the input string. If
|
||||
$IFS is null, no field splitting is performed. */
|
||||
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
|
||||
;
|
||||
input_string = t;
|
||||
|
||||
for (; list->next; list = list->next)
|
||||
{
|
||||
varname = list->word->word;
|
||||
#if defined (ARRAY_VARS)
|
||||
if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
|
||||
#else
|
||||
if (legal_identifier (varname) == 0)
|
||||
#endif
|
||||
{
|
||||
sh_invalidid (varname);
|
||||
xfree (orig_input_string);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* If there are more variables than words read from the input,
|
||||
the remaining variables are set to the empty string. */
|
||||
if (*input_string)
|
||||
{
|
||||
/* This call updates INPUT_STRING. */
|
||||
t = get_word_from_string (&input_string, ifs_chars, &e);
|
||||
if (t)
|
||||
*e = '\0';
|
||||
/* Don't bother to remove the CTLESC unless we added one
|
||||
somewhere while reading the string. */
|
||||
if (t && saw_escape)
|
||||
{
|
||||
t1 = dequote_string (t);
|
||||
var = bind_read_variable (varname, t1);
|
||||
xfree (t1);
|
||||
}
|
||||
else
|
||||
var = bind_read_variable (varname, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (char *)0;
|
||||
var = bind_read_variable (varname, "");
|
||||
}
|
||||
|
||||
FREE (t);
|
||||
if (var == 0)
|
||||
{
|
||||
xfree (orig_input_string);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
stupidly_hack_special_variables (varname);
|
||||
VUNSETATTR (var, att_invisible);
|
||||
}
|
||||
|
||||
/* Now assign the rest of the line to the last variable argument. */
|
||||
#if defined (ARRAY_VARS)
|
||||
if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
|
||||
#else
|
||||
if (legal_identifier (list->word->word) == 0)
|
||||
#endif
|
||||
{
|
||||
sh_invalidid (list->word->word);
|
||||
xfree (orig_input_string);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This has to be done this way rather than using string_list
|
||||
and list_string because Posix.2 says that the last variable gets the
|
||||
remaining words and their intervening separators. */
|
||||
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
|
||||
#else
|
||||
/* Check whether or not the number of fields is exactly the same as the
|
||||
number of variables. */
|
||||
if (*input_string)
|
||||
{
|
||||
t1 = input_string;
|
||||
t = get_word_from_string (&input_string, ifs_chars, &e);
|
||||
if (*input_string == 0)
|
||||
input_string = t;
|
||||
else
|
||||
input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (saw_escape)
|
||||
{
|
||||
t = dequote_string (input_string);
|
||||
var = bind_read_variable (list->word->word, t);
|
||||
xfree (t);
|
||||
}
|
||||
else
|
||||
var = bind_read_variable (list->word->word, input_string);
|
||||
stupidly_hack_special_variables (list->word->word);
|
||||
if (var)
|
||||
VUNSETATTR (var, att_invisible);
|
||||
xfree (orig_input_string);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static SHELL_VAR *
|
||||
bind_read_variable (name, value)
|
||||
char *name, *value;
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (name) == 0)
|
||||
return (bind_variable (name, value, 0));
|
||||
else
|
||||
return (assign_array_element (name, value, 0));
|
||||
#else /* !ARRAY_VARS */
|
||||
return bind_variable (name, value, 0);
|
||||
#endif /* !ARRAY_VARS */
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
static rl_completion_func_t *old_attempted_completion_function = 0;
|
||||
|
||||
static void
|
||||
reset_attempted_completion_function (cp)
|
||||
char *cp;
|
||||
{
|
||||
if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
|
||||
rl_attempted_completion_function = old_attempted_completion_function;
|
||||
}
|
||||
|
||||
static char *
|
||||
edit_line (p)
|
||||
char *p;
|
||||
{
|
||||
char *ret;
|
||||
int len;
|
||||
|
||||
if (bash_readline_initialized == 0)
|
||||
initialize_readline ();
|
||||
|
||||
old_attempted_completion_function = rl_attempted_completion_function;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
ret = readline (p);
|
||||
rl_attempted_completion_function = old_attempted_completion_function;
|
||||
old_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
len = strlen (ret);
|
||||
ret = (char *)xrealloc (ret, len + 2);
|
||||
ret[len++] = delim;
|
||||
ret[len] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int old_delim_ctype;
|
||||
static rl_command_func_t *old_delim_func;
|
||||
static int old_newline_ctype;
|
||||
static rl_command_func_t *old_newline_func;
|
||||
|
||||
static unsigned char delim_char;
|
||||
|
||||
static void
|
||||
set_eol_delim (c)
|
||||
int c;
|
||||
{
|
||||
Keymap cmap;
|
||||
|
||||
if (bash_readline_initialized == 0)
|
||||
initialize_readline ();
|
||||
cmap = rl_get_keymap ();
|
||||
|
||||
/* Change newline to self-insert */
|
||||
old_newline_ctype = cmap[RETURN].type;
|
||||
old_newline_func = cmap[RETURN].function;
|
||||
cmap[RETURN].type = ISFUNC;
|
||||
cmap[RETURN].function = rl_insert;
|
||||
|
||||
/* Bind the delimiter character to accept-line. */
|
||||
old_delim_ctype = cmap[c].type;
|
||||
old_delim_func = cmap[c].function;
|
||||
cmap[c].type = ISFUNC;
|
||||
cmap[c].function = rl_newline;
|
||||
|
||||
delim_char = c;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_eol_delim (cp)
|
||||
char *cp;
|
||||
{
|
||||
Keymap cmap;
|
||||
|
||||
cmap = rl_get_keymap ();
|
||||
|
||||
cmap[RETURN].type = old_newline_ctype;
|
||||
cmap[RETURN].function = old_newline_func;
|
||||
|
||||
cmap[delim_char].type = old_delim_ctype;
|
||||
cmap[delim_char].function = old_delim_func;
|
||||
}
|
||||
#endif
|
||||
+32
-10
@@ -1,7 +1,7 @@
|
||||
This file is read.def, from which is created read.c.
|
||||
It implements the builtin "read" in Bash.
|
||||
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -23,7 +23,7 @@ $PRODUCES read.c
|
||||
|
||||
$BUILTIN read
|
||||
$FUNCTION read_builtin
|
||||
$SHORT_DOC read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]
|
||||
$SHORT_DOC read [-ers] [-a array] [-d delim] [-n nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
|
||||
One line is read from the standard input, or from file descriptor FD if the
|
||||
-u option is supplied, and the first word is assigned to the first NAME,
|
||||
the second word to the second NAME, and so on, with leftover words assigned
|
||||
@@ -127,14 +127,14 @@ read_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register char *varname;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc;
|
||||
int raw, edit, nchars, silent, have_timeout, fd;
|
||||
unsigned int tmout;
|
||||
intmax_t intval;
|
||||
char c;
|
||||
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
|
||||
char *e, *t, *t1;
|
||||
char *e, *t, *t1, *ps2;
|
||||
struct stat tsb;
|
||||
SHELL_VAR *var;
|
||||
#if defined (ARRAY_VARS)
|
||||
@@ -148,6 +148,7 @@ read_builtin (list)
|
||||
USE_VAR(size);
|
||||
USE_VAR(i);
|
||||
USE_VAR(pass_next);
|
||||
USE_VAR(print_ps2);
|
||||
USE_VAR(saw_escape);
|
||||
USE_VAR(input_is_pipe);
|
||||
/* USE_VAR(raw); */
|
||||
@@ -163,6 +164,7 @@ read_builtin (list)
|
||||
USE_VAR(rlind);
|
||||
#endif
|
||||
USE_VAR(list);
|
||||
USE_VAR(ps2);
|
||||
|
||||
i = 0; /* Index into the string that we are reading. */
|
||||
raw = edit = 0; /* Not reading raw input by default. */
|
||||
@@ -261,6 +263,8 @@ read_builtin (list)
|
||||
ifs_chars = getifs ();
|
||||
if (ifs_chars == 0) /* XXX - shouldn't happen */
|
||||
ifs_chars = "";
|
||||
for (skip_ctlesc = 0, e = ifs_chars; *e; e++)
|
||||
skip_ctlesc |= *e == CTLESC;
|
||||
|
||||
input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
|
||||
|
||||
@@ -386,7 +390,8 @@ read_builtin (list)
|
||||
setmode (0, O_TEXT);
|
||||
#endif
|
||||
|
||||
for (eof = retval = 0;;)
|
||||
ps2 = 0;
|
||||
for (print_ps2 = eof = retval = 0;;)
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
@@ -412,6 +417,15 @@ read_builtin (list)
|
||||
{
|
||||
#endif
|
||||
|
||||
if (print_ps2)
|
||||
{
|
||||
if (ps2 == 0)
|
||||
ps2 = get_string_value ("PS2");
|
||||
fprintf (stderr, "%s", ps2 ? ps2 : "");
|
||||
fflush (stderr);
|
||||
print_ps2 = 0;
|
||||
}
|
||||
|
||||
if (unbuffered_read)
|
||||
retval = zread (fd, &c, 1);
|
||||
else
|
||||
@@ -440,24 +454,32 @@ read_builtin (list)
|
||||
{
|
||||
pass_next = 0;
|
||||
if (c == '\n')
|
||||
i--; /* back up over the CTLESC */
|
||||
{
|
||||
i--; /* back up over the CTLESC */
|
||||
if (interactive && raw == 0)
|
||||
print_ps2 = 1;
|
||||
}
|
||||
else
|
||||
goto add_char;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This may cause problems if IFS contains CTLESC */
|
||||
if (c == '\\' && raw == 0)
|
||||
{
|
||||
pass_next++;
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
if (skip_ctlesc == 0)
|
||||
{
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((unsigned char)c == delim)
|
||||
break;
|
||||
|
||||
if (c == CTLESC || c == CTLNUL)
|
||||
if ((skip_ctlesc == 0 && c == CTLESC) || c == CTLNUL)
|
||||
{
|
||||
saw_escape++;
|
||||
input_string[i++] = CTLESC;
|
||||
|
||||
+1
-2
@@ -2,7 +2,6 @@
|
||||
.\" MAN PAGE COMMENTS to
|
||||
.\"
|
||||
.\" Chet Ramey
|
||||
.\" Information Network Services
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
@@ -2570,7 +2569,7 @@ The \fIpattern\fP is expanded to produce a pattern just as in
|
||||
pathname expansion.
|
||||
\fIParameter\fP is expanded and the longest match of \fIpattern\fP
|
||||
against its value is replaced with \fIstring\fP.
|
||||
If \Ipattern\fP begins with \fB/\fP, all matches of \fIpattern\fP are
|
||||
If \fIpattern\fP begins with \fB/\fP, all matches of \fIpattern\fP are
|
||||
replaced with \fIstring\fP. Normally only the first match is replaced.
|
||||
If \fIpattern\fP begins with \fB#\fP, it must match at the beginning
|
||||
of the expanded value of \fIparameter\fP.
|
||||
|
||||
+33
-49
@@ -1,66 +1,50 @@
|
||||
BASHBUG(1) BASHBUG(1)
|
||||
|
||||
|
||||
|
||||
BASHBUG(1) BASHBUG(1)
|
||||
|
||||
|
||||
NNAAMMEE
|
||||
bashbug - report a bug in bash
|
||||
|
||||
SSYYNNOOPPSSIISS
|
||||
bbaasshhbbuugg [_a_d_d_r_e_s_s]
|
||||
bbaasshhbbuugg [_-_-_v_e_r_s_i_o_n] [_-_-_h_e_l_p] [_e_m_a_i_l_-_a_d_d_r_e_s_s]
|
||||
|
||||
DDEESSCCRRIIPPTTIIOONN
|
||||
bbaasshhbbuugg is a shell script to help the user compose and
|
||||
mail bug reports concerning bash in a standard format.
|
||||
bbaasshhbbuugg invokes the editor specified by the environment
|
||||
variable EEDDIITTOORR on a temporary copy of the bug report for-
|
||||
mat outline. The user must fill in the appropriate fields
|
||||
and exit the editor. bbaasshhbbuugg then mails the completed
|
||||
report to _b_u_g_-_b_a_s_h_@_g_n_u_._o_r_g, or _a_d_d_r_e_s_s. If the report
|
||||
cannot be mailed, it is saved in the file _d_e_a_d_._b_a_s_h_b_u_g in
|
||||
the invoking user's home directory.
|
||||
bbaasshhbbuugg is a shell script to help the user compose and mail bug reports
|
||||
concerning bash in a standard format. bbaasshhbbuugg invokes the editor spec-
|
||||
ified by the environment variable EEDDIITTOORR on a temporary copy of the bug
|
||||
report format outline. The user must fill in the appropriate fields and
|
||||
exit the editor. bbaasshhbbuugg then mails the completed report to _b_u_g_-
|
||||
_b_a_s_h_@_g_n_u_._o_r_g, or _e_m_a_i_l_-_a_d_d_r_e_s_s. If the report cannot be mailed, it is
|
||||
saved in the file _d_e_a_d_._b_a_s_h_b_u_g in the invoking user's home directory.
|
||||
|
||||
The bug report format outline consists of several sec-
|
||||
tions. The first section provides information about the
|
||||
machine, operating system, the bash version, and the com-
|
||||
pilation environment. The second section should be filled
|
||||
in with a description of the bug. The third section
|
||||
should be a description of how to reproduce the bug. The
|
||||
optional fourth section is for a proposed fix. Fixes are
|
||||
encouraged.
|
||||
The bug report format outline consists of several sections. The first
|
||||
section provides information about the machine, operating system, the
|
||||
bash version, and the compilation environment. The second section
|
||||
should be filled in with a description of the bug. The third section
|
||||
should be a description of how to reproduce the bug. The optional
|
||||
fourth section is for a proposed fix. Fixes are encouraged.
|
||||
|
||||
EENNVVIIRROONNMMEENNTT
|
||||
bbaasshhbbuugg will utilize the following environment variables
|
||||
if they exist:
|
||||
bbaasshhbbuugg will utilize the following environment variables if they exist:
|
||||
|
||||
EEDDIITTOORR Specifies the preferred editor. If EEDDIITTOORR is not
|
||||
set, bbaasshhbbuugg defaults to eemmaaccss.
|
||||
EEDDIITTOORR Specifies the preferred editor. If EEDDIITTOORR is not set, bbaasshhbbuugg
|
||||
defaults to eemmaaccss.
|
||||
|
||||
HHOOMMEE Directory in which the failed bug report is saved
|
||||
if the mail fails.
|
||||
HHOOMMEE Directory in which the failed bug report is saved if the mail
|
||||
fails.
|
||||
|
||||
TTMMPPDDIIRR Directory in which to create temporary files and directories.
|
||||
|
||||
SSEEEE AALLSSOO
|
||||
_b_a_s_h(1)
|
||||
|
||||
AAUUTTHHOORRSS
|
||||
Brian Fox, Free Software Foundation
|
||||
bfox@gnu.org
|
||||
|
||||
Chet Ramey, Case Western Reserve University
|
||||
chet@po.cwru.edu
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
GNU 1998 July 30 1
|
||||
|
||||
|
||||
GNU Bash-3.2 1998 July 30 BASHBUG(1)
|
||||
|
||||
+26
-3
@@ -1,8 +1,17 @@
|
||||
.TH BASHBUG 1 "1998 July 30" GNU
|
||||
.\"
|
||||
.\" MAN PAGE COMMENTS to
|
||||
.\"
|
||||
.\" Chet Ramey
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Tue Apr 3 15:46:30 EDT 2007
|
||||
.\"
|
||||
.TH BASHBUG 1 "1998 July 30" "GNU Bash-3.2"
|
||||
.SH NAME
|
||||
bashbug \- report a bug in bash
|
||||
.SH SYNOPSIS
|
||||
\fBbashbug\fP [\fIaddress\fP]
|
||||
\fBbashbug\fP [\fI--version\fP] [\fI--help\fP] [\fIemail-address\fP]
|
||||
.SH DESCRIPTION
|
||||
.B bashbug
|
||||
is a shell script to help the user compose and mail bug reports
|
||||
@@ -15,7 +24,7 @@ on a temporary copy of the bug report format outline. The user must
|
||||
fill in the appropriate fields and exit the editor.
|
||||
.B bashbug
|
||||
then mails the completed report to \fIbug-bash@gnu.org\fP, or
|
||||
\fIaddress\fP. If the report cannot be mailed, it is saved in the
|
||||
\fIemail-address\fP. If the report cannot be mailed, it is saved in the
|
||||
file \fIdead.bashbug\fP in the invoking user's home directory.
|
||||
.PP
|
||||
The bug report format outline consists of several sections. The first
|
||||
@@ -39,3 +48,17 @@ defaults to
|
||||
.TP
|
||||
.B HOME
|
||||
Directory in which the failed bug report is saved if the mail fails.
|
||||
.TP
|
||||
.B TMPDIR
|
||||
Directory in which to create temporary files and directories.
|
||||
.SH "SEE ALSO"
|
||||
.TP
|
||||
\fIbash\fP(1)
|
||||
.SH AUTHORS
|
||||
Brian Fox, Free Software Foundation
|
||||
.br
|
||||
bfox@gnu.org
|
||||
.PP
|
||||
Chet Ramey, Case Western Reserve University
|
||||
.br
|
||||
chet@po.cwru.edu
|
||||
|
||||
+65
-31
@@ -1,16 +1,21 @@
|
||||
%!PS-Adobe-3.0
|
||||
%%Creator: groff version 1.10
|
||||
%%CreationDate: Wed Sep 30 13:53:50 1998
|
||||
%%Creator: groff version 1.19.1
|
||||
%%CreationDate: Tue Apr 3 15:54:18 2007
|
||||
%%DocumentNeededResources: font Times-Roman
|
||||
%%+ font Times-Bold
|
||||
%%+ font Times-Italic
|
||||
%%DocumentSuppliedResources: procset grops 1.10 0
|
||||
%%DocumentSuppliedResources: procset grops 1.19 1
|
||||
%%Pages: 1
|
||||
%%PageOrder: Ascend
|
||||
%%DocumentMedia: Default 595 842 0 () ()
|
||||
%%Orientation: Portrait
|
||||
%%EndComments
|
||||
%%BeginDefaults
|
||||
%%PageMedia: Default
|
||||
%%EndDefaults
|
||||
%%BeginProlog
|
||||
%%BeginResource: procset grops 1.10 0
|
||||
%%BeginResource: procset grops 1.19 1
|
||||
%!PS-Adobe-3.0 Resource-ProcSet
|
||||
/setpacking where{
|
||||
pop
|
||||
currentpacking
|
||||
@@ -108,11 +113,26 @@ TM setmatrix
|
||||
/ST/stroke load def
|
||||
/MT/moveto load def
|
||||
/CL/closepath load def
|
||||
/FL{
|
||||
currentgray exch setgray fill setgray
|
||||
/Fr{
|
||||
setrgbcolor fill
|
||||
}bind def
|
||||
/BL/fill load def
|
||||
/setcmykcolor where{
|
||||
pop
|
||||
/Fk{
|
||||
setcmykcolor fill
|
||||
}bind def
|
||||
}if
|
||||
/Fg{
|
||||
setgray fill
|
||||
}bind def
|
||||
/FL/fill load def
|
||||
/LW/setlinewidth load def
|
||||
/Cr/setrgbcolor load def
|
||||
/setcmykcolor where{
|
||||
pop
|
||||
/Ck/setcmykcolor load def
|
||||
}if
|
||||
/Cg/setgray load def
|
||||
/RE{
|
||||
findfont
|
||||
dup maxlength 1 index/FontName known not{1 add}if dict begin
|
||||
@@ -154,6 +174,7 @@ newpath
|
||||
/CNT countdictstack def
|
||||
userdict begin
|
||||
/showpage{}def
|
||||
/setpagedevice{}def
|
||||
}bind def
|
||||
/PEND{
|
||||
clear
|
||||
@@ -166,15 +187,20 @@ pop
|
||||
setpacking
|
||||
}if
|
||||
%%EndResource
|
||||
%%EndProlog
|
||||
%%BeginSetup
|
||||
%%BeginFeature: *PageSize Default
|
||||
<< /PageSize [ 595 842 ] /ImagingBBox null >> setpagedevice
|
||||
%%EndFeature
|
||||
%%IncludeResource: font Times-Roman
|
||||
%%IncludeResource: font Times-Bold
|
||||
%%IncludeResource: font Times-Italic
|
||||
grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
|
||||
def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
|
||||
/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
|
||||
def/PL 841.89 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron
|
||||
/Zcaron/scaron/zcaron/Ydieresis/trademark/quotesingle/Euro/.notdef
|
||||
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
|
||||
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
|
||||
/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
|
||||
/.notdef/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
|
||||
/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
|
||||
/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
|
||||
/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
|
||||
@@ -199,32 +225,33 @@ def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
|
||||
/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
|
||||
/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
|
||||
/Times-Roman@0 ENC0/Times-Roman RE
|
||||
%%EndProlog
|
||||
%%EndSetup
|
||||
%%Page: 1 1
|
||||
%%BeginPageSetup
|
||||
BP
|
||||
%%EndPageSetup
|
||||
/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SHB).35 E 347.52(UG\(1\) B)-.1 F
|
||||
(ASHB)-.35 E(UG\(1\))-.1 E/F1 9/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E
|
||||
F0(bashb)108 96 Q(ug \255 report a b)-.2 E(ug in bash)-.2 E F1(SYNOPSIS)
|
||||
72 112.8 Q/F2 10/Times-Bold@0 SF(bashb)108 124.8 Q(ug)-.2 E F0([)2.5 E
|
||||
/F3 10/Times-Italic@0 SF(addr)A(ess)-.37 E F0(])A F1(DESCRIPTION)72
|
||||
141.6 Q F2(bashb)108 153.6 Q(ug)-.2 E F0 .446
|
||||
(ASHB)-.35 E(UG\(1\))-.1 E/F1 10.95/Times-Bold@0 SF -.219(NA)72 84 S(ME)
|
||||
.219 E F0(bashb)108 96 Q(ug \255 report a b)-.2 E(ug in bash)-.2 E F1
|
||||
(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(bashb)108 124.8 Q(ug)-.2 E F0
|
||||
([)2.5 E/F3 10/Times-Italic@0 SF(--ver)A(sion)-.1 E F0 2.5(][)C F3
|
||||
(--help)-2.5 E F0 2.5(][)C F3(email-addr)-2.5 E(ess)-.37 E F0(])A F1
|
||||
(DESCRIPTION)72 141.6 Q F2(bashb)108 153.6 Q(ug)-.2 E F0 .446
|
||||
(is a shell script to help the user compose and mail b)2.947 F .446
|
||||
(ug reports concerning bash in a standard for)-.2 F(-)-.2 E(mat.)108
|
||||
165.6 Q F2(bashb)5.961 E(ug)-.2 E F0(in)3.461 E -.2(vo)-.4 G -.1(ke).2 G
|
||||
3.461(st).1 G .962(he editor speci\214ed by the en)-3.461 F .962
|
||||
(vironment v)-.4 F(ariable)-.25 E F1(EDIT)3.462 E(OR)-.162 E F0 .962
|
||||
(on a temporary cop)3.212 F 3.462(yo)-.1 G(f)-3.462 E .374(the b)108
|
||||
177.6 R .374(ug report format outline. The user must \214ll in the appr\
|
||||
opriate \214elds and e)-.2 F .374(xit the editor)-.15 F(.)-.55 E F2
|
||||
(bashb)5.373 E(ug)-.2 E F0(then)2.873 E .439
|
||||
(mails the completed report to)108 189.6 R F3 -.2(bu)2.939 G
|
||||
(g-bash@gnu.or).2 E(g)-.37 E F0 2.939(,o)C(r)-2.939 E F3(addr)2.939 E
|
||||
(ess)-.37 E F0 5.439(.I)C 2.939(ft)-5.439 G .44
|
||||
(he report cannot be mailed, it is sa)-2.939 F -.15(ve)-.2 G 2.94(di).15
|
||||
G(n)-2.94 E(the \214le)108 201.6 Q F3(dead.bashb)2.5 E(ug)-.2 E F0
|
||||
(in the in)2.5 E -.2(vo)-.4 G(king user').2 E 2.5(sh)-.55 G
|
||||
(vironment v)-.4 F(ariable)-.25 E/F4 9/Times-Bold@0 SF(EDIT)3.462 E(OR)
|
||||
-.162 E F0 .962(on a temporary cop)3.212 F 3.462(yo)-.1 G(f)-3.462 E
|
||||
.374(the b)108 177.6 R .374(ug report format outline. The user must \
|
||||
\214ll in the appropriate \214elds and e)-.2 F .374(xit the editor)-.15
|
||||
F(.)-.55 E F2(bashb)5.373 E(ug)-.2 E F0(then)2.873 E 1.141
|
||||
(mails the completed report to)108 189.6 R F3 -.2(bu)3.641 G
|
||||
(g-bash@gnu.or).2 E(g)-.37 E F0 3.641(,o)C(r)-3.641 E F3(email-addr)
|
||||
3.641 E(ess)-.37 E F0 6.141(.I)C 3.641(ft)-6.141 G 1.142
|
||||
(he report cannot be mailed, it is)-3.641 F(sa)108 201.6 Q -.15(ve)-.2 G
|
||||
2.5(di).15 G 2.5(nt)-2.5 G(he \214le)-2.5 E F3(dead.bashb)2.5 E(ug)-.2 E
|
||||
F0(in the in)2.5 E -.2(vo)-.4 G(king user').2 E 2.5(sh)-.55 G
|
||||
(ome directory)-2.5 E(.)-.65 E .354(The b)108 218.4 R .354
|
||||
(ug report format outline consists of se)-.2 F -.15(ve)-.25 G .353
|
||||
(ral sections.).15 F .353(The \214rst section pro)5.353 F .353
|
||||
@@ -236,16 +263,23 @@ G(n)-2.94 E(the \214le)108 201.6 Q F3(dead.bashb)2.5 E(ug)-.2 E F0
|
||||
-.2 F .208(third section should be a description of ho)2.709 F 2.708(wt)
|
||||
-.25 G 2.708(or)-2.708 G .208(eproduce the)-2.708 F -.2(bu)108 254.4 S
|
||||
2.5(g. The).2 F(optional fourth section is for a proposed \214x.)2.5 E
|
||||
(Fix)5 E(es are encouraged.)-.15 E F1(ENVIR)72 271.2 Q(ONMENT)-.27 E F2
|
||||
(Fix)5 E(es are encouraged.)-.15 E F1(ENVIR)72 271.2 Q(ONMENT)-.329 E F2
|
||||
(bashb)108 283.2 Q(ug)-.2 E F0(will utilize the follo)2.5 E(wing en)-.25
|
||||
E(vironment v)-.4 E(ariables if the)-.25 E 2.5(ye)-.15 G(xist:)-2.65 E
|
||||
F2(EDIT)108 300 Q(OR)-.18 E F0(Speci\214es the preferred editor)144 312
|
||||
Q 2.5(.I)-.55 G(f)-2.5 E F1(EDIT)2.5 E(OR)-.162 E F0(is not set,)2.25 E
|
||||
Q 2.5(.I)-.55 G(f)-2.5 E F4(EDIT)2.5 E(OR)-.162 E F0(is not set,)2.25 E
|
||||
F2(bashb)2.5 E(ug)-.2 E F0(def)2.5 E(aults to)-.1 E F2(emacs)2.5 E F0(.)
|
||||
A F2(HOME)108 328.8 Q F0(Directory in which the f)144 340.8 Q(ailed b)
|
||||
-.1 E(ug report is sa)-.2 E -.15(ve)-.2 G 2.5(di).15 G 2.5(ft)-2.5 G
|
||||
(he mail f)-2.5 E(ails.)-.1 E 184.005(GNU 1998)72 768 R(July 30)2.5 E(1)
|
||||
203.165 E EP
|
||||
(he mail f)-2.5 E(ails.)-.1 E F2(TMPDIR)108 357.6 Q F0
|
||||
(Directory in which to create temporary \214les and directories.)144
|
||||
369.6 Q F1(SEE ALSO)72 386.4 Q F3(bash)108 398.4 Q F0(\(1\))A F1 -.548
|
||||
(AU)72 415.2 S(THORS).548 E F0(Brian F)108 427.2 Q(ox, Free Softw)-.15 E
|
||||
(are F)-.1 E(oundation)-.15 E(bfox@gnu.or)108 439.2 Q(g)-.18 E
|
||||
(Chet Rame)108 456 Q 1.3 -.65(y, C)-.15 H(ase W).65 E(estern Reserv)-.8
|
||||
E 2.5(eU)-.15 G(ni)-2.5 E -.15(ve)-.25 G(rsity).15 E(chet@po.cwru.edu)
|
||||
108 468 Q(GNU Bash-3.2)72 768 Q(1998 July 30)148.175 E(1)203.165 E 0 Cg
|
||||
EP
|
||||
%%Trailer
|
||||
end
|
||||
%%EOF
|
||||
|
||||
@@ -79,10 +79,12 @@ extern int errno;
|
||||
#define ST_DQUOTE 0x08 /* unused yet */
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define EX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define EX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define EX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define EX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
@@ -543,11 +545,11 @@ sub_append_number (number, target, indx, size)
|
||||
/* Extract a substring from STRING, starting at SINDEX and ending with
|
||||
one of the characters in CHARLIST. Don't make the ending character
|
||||
part of the string. Leave SINDEX pointing at the ending character.
|
||||
Understand about backslashes in the string. If (flags & EX_VARNAME)
|
||||
Understand about backslashes in the string. If (flags & SX_VARNAME)
|
||||
is non-zero, and array variables have been compiled into the shell,
|
||||
everything between a `[' and a corresponding `]' is skipped over.
|
||||
If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
|
||||
update SINDEX. If (flags & EX_REQMATCH) is non-zero, the string must
|
||||
If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
|
||||
update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
|
||||
contain a closing character from CHARLIST. */
|
||||
static char *
|
||||
string_extract (string, sindex, charlist, flags)
|
||||
@@ -575,7 +577,7 @@ string_extract (string, sindex, charlist, flags)
|
||||
break;
|
||||
}
|
||||
#if defined (ARRAY_VARS)
|
||||
else if ((flags & EX_VARNAME) && c == '[')
|
||||
else if ((flags & SX_VARNAME) && c == '[')
|
||||
{
|
||||
int ni;
|
||||
/* If this is an array subscript, skip over it and continue. */
|
||||
@@ -595,13 +597,13 @@ string_extract (string, sindex, charlist, flags)
|
||||
|
||||
/* If we had to have a matching delimiter and didn't find one, return an
|
||||
error and let the caller deal with it. */
|
||||
if ((flags & EX_REQMATCH) && found == 0)
|
||||
if ((flags & SX_REQMATCH) && found == 0)
|
||||
{
|
||||
*sindex = i;
|
||||
return (&extract_string_error);
|
||||
}
|
||||
|
||||
temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
*sindex = i;
|
||||
|
||||
return (temp);
|
||||
@@ -712,7 +714,7 @@ add_one_character:
|
||||
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_COMMAND); /*)*/
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 1, 0);
|
||||
|
||||
@@ -814,9 +816,9 @@ skip_double_quoted (string, slen, sind)
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
|
||||
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
|
||||
i = si + 1;
|
||||
continue;
|
||||
@@ -924,12 +926,19 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
size_t mblength;
|
||||
#endif
|
||||
if (c == CTLESC)
|
||||
if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
/* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
|
||||
through, to protect the CTLNULs from later calls to
|
||||
remove_quoted_nulls. */
|
||||
else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mblength = MBLEN (string + i, slen - i);
|
||||
if (mblength > 1)
|
||||
@@ -983,7 +992,7 @@ extract_command_subst (string, sindex)
|
||||
char *string;
|
||||
int *sindex;
|
||||
{
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", EX_COMMAND)); /*)*/
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
|
||||
}
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string. (])
|
||||
@@ -1090,7 +1099,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
|
||||
/* Not exactly right yet; should handle shell metacharacters and
|
||||
multibyte characters, too. */
|
||||
if ((flags & EX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
{
|
||||
in_comment = 1;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -1108,7 +1117,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (STREQN (string + i, opener, len_opener))
|
||||
{
|
||||
si = i + len_opener;
|
||||
t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
|
||||
t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1117,7 +1126,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
|
||||
{
|
||||
si = i + len_alt_opener;
|
||||
t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
|
||||
t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1136,7 +1145,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (c == '`')
|
||||
{
|
||||
si = i + 1;
|
||||
t = string_extract (string, &si, "`", flags|EX_NOALLOC);
|
||||
t = string_extract (string, &si, "`", flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1170,7 +1179,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
}
|
||||
|
||||
si = i - *sindex - len_closer + 1;
|
||||
if (flags & EX_NOALLOC)
|
||||
if (flags & SX_NOALLOC)
|
||||
result = (char *)NULL;
|
||||
else
|
||||
{
|
||||
@@ -1245,7 +1254,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (c == '`')
|
||||
{
|
||||
si = i + 1;
|
||||
t = string_extract (string, &si, "`", flags|EX_NOALLOC);
|
||||
t = string_extract (string, &si, "`", flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1255,7 +1264,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (string[i] == '$' && string[i+1] == LPAREN)
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC|EX_COMMAND); /*)*/
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|SX_NOALLOC|SX_COMMAND); /*)*/
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1290,7 +1299,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
}
|
||||
}
|
||||
|
||||
result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
*sindex = i;
|
||||
|
||||
return (result);
|
||||
@@ -1518,9 +1527,9 @@ skip_to_delim (string, start, delims)
|
||||
CQ_RETURN(si);
|
||||
|
||||
if (string[i+1] == LPAREN)
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
|
||||
temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
i = si;
|
||||
if (string[i] == '\0') /* don't increment i past EOS in loop */
|
||||
break;
|
||||
@@ -1945,7 +1954,7 @@ list_string (string, separators, quoted)
|
||||
WORD_LIST *result;
|
||||
WORD_DESC *t;
|
||||
char *current_word, *s;
|
||||
int sindex, sh_style_split, whitesep;
|
||||
int sindex, sh_style_split, whitesep, xflags;
|
||||
size_t slen;
|
||||
|
||||
if (!string || !*string)
|
||||
@@ -1955,6 +1964,11 @@ list_string (string, separators, quoted)
|
||||
separators[1] == '\t' &&
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
slen = 0;
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -1980,7 +1994,7 @@ list_string (string, separators, quoted)
|
||||
{
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, 0);
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
|
||||
if (current_word == 0)
|
||||
break;
|
||||
|
||||
@@ -2062,19 +2076,23 @@ get_word_from_string (stringp, separators, endptr)
|
||||
{
|
||||
register char *s;
|
||||
char *current_word;
|
||||
int sindex, sh_style_split, whitesep;
|
||||
int sindex, sh_style_split, whitesep, xflags;
|
||||
size_t slen;
|
||||
|
||||
if (!stringp || !*stringp || !**stringp)
|
||||
return ((char *)NULL);
|
||||
|
||||
s = *stringp;
|
||||
|
||||
sh_style_split = separators && separators[0] == ' ' &&
|
||||
separators[1] == '\t' &&
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
s = *stringp;
|
||||
slen = 0;
|
||||
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -2103,7 +2121,7 @@ get_word_from_string (stringp, separators, endptr)
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, 0);
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
|
||||
|
||||
/* Set ENDPTR to the first character after the end of the word. */
|
||||
if (endptr)
|
||||
@@ -2934,12 +2952,14 @@ expand_string (string, quoted)
|
||||
|
||||
/* Quote escape characters in string s, but no other characters. This is
|
||||
used to protect CTLESC and CTLNUL in variable values from the rest of
|
||||
the word expansion process after the variable is expanded. If IFS is
|
||||
null, we quote spaces as well, just in case we split on spaces later
|
||||
(in the case of unquoted $@, we will eventually attempt to split the
|
||||
entire word on spaces). Corresponding code exists in dequote_escapes.
|
||||
Even if we don't end up splitting on spaces, quoting spaces is not a
|
||||
problem. */
|
||||
the word expansion process after the variable is expanded (word splitting
|
||||
and filename generation). If IFS is null, we quote spaces as well, just
|
||||
in case we split on spaces later (in the case of unquoted $@, we will
|
||||
eventually attempt to split the entire word on spaces). Corresponding
|
||||
code exists in dequote_escapes. Even if we don't end up splitting on
|
||||
spaces, quoting spaces is not a problem. This should never be called on
|
||||
a string that is quoted with single or double quotes or part of a here
|
||||
document (effectively double-quoted). */
|
||||
char *
|
||||
quote_escapes (string)
|
||||
char *string;
|
||||
@@ -2947,19 +2967,23 @@ quote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
int quote_spaces, skip_ctlesc, skip_ctlnul;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
|
||||
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
@@ -2998,7 +3022,7 @@ static char *
|
||||
dequote_escapes (string)
|
||||
char *string;
|
||||
{
|
||||
register char *s, *t;
|
||||
register char *s, *t, *s1;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
@@ -3011,12 +3035,13 @@ dequote_escapes (string)
|
||||
send = string + slen;
|
||||
|
||||
t = result = (char *)xmalloc (slen + 1);
|
||||
s = string;
|
||||
|
||||
if (strchr (string, CTLESC) == 0)
|
||||
return (strcpy (result, s));
|
||||
return (strcpy (result, string));
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
s = string;
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
|
||||
@@ -3993,7 +4018,9 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
||||
FREE (val);
|
||||
if (temp1)
|
||||
{
|
||||
val = quote_escapes (temp1);
|
||||
val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
? quote_string (temp1)
|
||||
: quote_escapes (temp1);
|
||||
free (temp1);
|
||||
temp1 = val;
|
||||
}
|
||||
@@ -4460,13 +4487,16 @@ read_comsub (fd, quoted, rflag)
|
||||
int fd, quoted;
|
||||
int *rflag;
|
||||
{
|
||||
char *istring, buf[128], *bufp;
|
||||
int istring_index, istring_size, c, tflag;
|
||||
char *istring, buf[128], *bufp, *s;
|
||||
int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
|
||||
ssize_t bufn;
|
||||
|
||||
istring = (char *)NULL;
|
||||
istring_index = istring_size = bufn = tflag = 0;
|
||||
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
|
||||
#endif
|
||||
@@ -4503,12 +4533,12 @@ read_comsub (fd, quoted, rflag)
|
||||
/* Escape CTLESC and CTLNUL in the output to protect those characters
|
||||
from the rest of the word expansions (word splitting and globbing.)
|
||||
This is essentially quote_escapes inline. */
|
||||
else if (c == CTLESC)
|
||||
else if (skip_ctlesc == 0 && c == CTLESC)
|
||||
{
|
||||
tflag |= W_HASCTLESC;
|
||||
istring[istring_index++] = CTLESC;
|
||||
}
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
@@ -5608,18 +5638,9 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
/* We want E2 to be the number of elements desired (arrays can be sparse,
|
||||
so verify_substring_values just returns the numbers specified and we
|
||||
rely on array_subrange to understand how to deal with them). */
|
||||
tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
#if 0
|
||||
temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
/* array_subrange now calls array_quote_escapes as appropriate, so the
|
||||
caller no longer needs to. */
|
||||
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
|
||||
{
|
||||
temp = tt ? quote_escapes (tt) : (char *)NULL;
|
||||
FREE (tt);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
temp = tt;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -5852,7 +5873,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
FREE (val);
|
||||
if (temp)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
@@ -5869,16 +5890,9 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
temp = array_patsub (array_cell (v), p, rep, mflags);
|
||||
#if 0
|
||||
/* Don't need to do this anymore; array_patsub calls array_quote_escapes
|
||||
as appropriate before adding the space separators. */
|
||||
if (temp && (mflags & MATCH_QUOTED) == 0)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
#endif
|
||||
/* Don't call quote_escapes anymore; array_patsub calls
|
||||
array_quote_escapes as appropriate before adding the
|
||||
space separators. */
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -5968,9 +5982,9 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
t_index = ++sindex;
|
||||
/* ${#var} doesn't have any of the other parameter expansions on it. */
|
||||
if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
|
||||
name = string_extract (string, &t_index, "}", EX_VARNAME);
|
||||
name = string_extract (string, &t_index, "}", SX_VARNAME);
|
||||
else
|
||||
name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
|
||||
name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
|
||||
|
||||
ret = 0;
|
||||
tflag = 0;
|
||||
@@ -7027,7 +7041,7 @@ add_string:
|
||||
{
|
||||
t_index = sindex++;
|
||||
|
||||
temp = string_extract (string, &sindex, "`", EX_REQMATCH);
|
||||
temp = string_extract (string, &sindex, "`", SX_REQMATCH);
|
||||
/* The test of sindex against t_index is to allow bare instances of
|
||||
` to pass through, for backwards compatibility. */
|
||||
if (temp == &extract_string_error || temp == &extract_string_fatal)
|
||||
|
||||
+8207
File diff suppressed because it is too large
Load Diff
+100
-69
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -79,10 +79,11 @@ extern int errno;
|
||||
#define ST_DQUOTE 0x08 /* unused yet */
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define EX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define EX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define EX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define EX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
@@ -543,11 +544,11 @@ sub_append_number (number, target, indx, size)
|
||||
/* Extract a substring from STRING, starting at SINDEX and ending with
|
||||
one of the characters in CHARLIST. Don't make the ending character
|
||||
part of the string. Leave SINDEX pointing at the ending character.
|
||||
Understand about backslashes in the string. If (flags & EX_VARNAME)
|
||||
Understand about backslashes in the string. If (flags & SX_VARNAME)
|
||||
is non-zero, and array variables have been compiled into the shell,
|
||||
everything between a `[' and a corresponding `]' is skipped over.
|
||||
If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
|
||||
update SINDEX. If (flags & EX_REQMATCH) is non-zero, the string must
|
||||
If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
|
||||
update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
|
||||
contain a closing character from CHARLIST. */
|
||||
static char *
|
||||
string_extract (string, sindex, charlist, flags)
|
||||
@@ -575,7 +576,7 @@ string_extract (string, sindex, charlist, flags)
|
||||
break;
|
||||
}
|
||||
#if defined (ARRAY_VARS)
|
||||
else if ((flags & EX_VARNAME) && c == '[')
|
||||
else if ((flags & SX_VARNAME) && c == '[')
|
||||
{
|
||||
int ni;
|
||||
/* If this is an array subscript, skip over it and continue. */
|
||||
@@ -595,13 +596,13 @@ string_extract (string, sindex, charlist, flags)
|
||||
|
||||
/* If we had to have a matching delimiter and didn't find one, return an
|
||||
error and let the caller deal with it. */
|
||||
if ((flags & EX_REQMATCH) && found == 0)
|
||||
if ((flags & SX_REQMATCH) && found == 0)
|
||||
{
|
||||
*sindex = i;
|
||||
return (&extract_string_error);
|
||||
}
|
||||
|
||||
temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
*sindex = i;
|
||||
|
||||
return (temp);
|
||||
@@ -712,7 +713,7 @@ add_one_character:
|
||||
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_COMMAND); /*)*/
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 1, 0);
|
||||
|
||||
@@ -814,9 +815,9 @@ skip_double_quoted (string, slen, sind)
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
|
||||
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
|
||||
i = si + 1;
|
||||
continue;
|
||||
@@ -924,7 +925,7 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
size_t mblength;
|
||||
#endif
|
||||
if (c == CTLESC)
|
||||
if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
@@ -983,7 +984,7 @@ extract_command_subst (string, sindex)
|
||||
char *string;
|
||||
int *sindex;
|
||||
{
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", EX_COMMAND)); /*)*/
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
|
||||
}
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string. (])
|
||||
@@ -1090,7 +1091,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
|
||||
/* Not exactly right yet; should handle shell metacharacters and
|
||||
multibyte characters, too. */
|
||||
if ((flags & EX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
{
|
||||
in_comment = 1;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -1108,7 +1109,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (STREQN (string + i, opener, len_opener))
|
||||
{
|
||||
si = i + len_opener;
|
||||
t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
|
||||
t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1117,7 +1118,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
|
||||
{
|
||||
si = i + len_alt_opener;
|
||||
t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
|
||||
t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1136,7 +1137,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (c == '`')
|
||||
{
|
||||
si = i + 1;
|
||||
t = string_extract (string, &si, "`", flags|EX_NOALLOC);
|
||||
t = string_extract (string, &si, "`", flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1170,7 +1171,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
}
|
||||
|
||||
si = i - *sindex - len_closer + 1;
|
||||
if (flags & EX_NOALLOC)
|
||||
if (flags & SX_NOALLOC)
|
||||
result = (char *)NULL;
|
||||
else
|
||||
{
|
||||
@@ -1245,7 +1246,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (c == '`')
|
||||
{
|
||||
si = i + 1;
|
||||
t = string_extract (string, &si, "`", flags|EX_NOALLOC);
|
||||
t = string_extract (string, &si, "`", flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1255,7 +1256,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (string[i] == '$' && string[i+1] == LPAREN)
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC|EX_COMMAND); /*)*/
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|SX_NOALLOC|SX_COMMAND); /*)*/
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1290,7 +1291,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
}
|
||||
}
|
||||
|
||||
result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
*sindex = i;
|
||||
|
||||
return (result);
|
||||
@@ -1518,9 +1519,9 @@ skip_to_delim (string, start, delims)
|
||||
CQ_RETURN(si);
|
||||
|
||||
if (string[i+1] == LPAREN)
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
|
||||
temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
i = si;
|
||||
if (string[i] == '\0') /* don't increment i past EOS in loop */
|
||||
break;
|
||||
@@ -1888,7 +1889,13 @@ string_list_dollar_at (list, quoted)
|
||||
sep[1] = '\0';
|
||||
#endif
|
||||
|
||||
/* 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))
|
||||
#endif
|
||||
? quote_list (list)
|
||||
: list_quote_escapes (list);
|
||||
|
||||
@@ -1939,7 +1946,7 @@ list_string (string, separators, quoted)
|
||||
WORD_LIST *result;
|
||||
WORD_DESC *t;
|
||||
char *current_word, *s;
|
||||
int sindex, sh_style_split, whitesep;
|
||||
int sindex, sh_style_split, whitesep, xflags;
|
||||
size_t slen;
|
||||
|
||||
if (!string || !*string)
|
||||
@@ -1949,6 +1956,8 @@ list_string (string, separators, quoted)
|
||||
separators[1] == '\t' &&
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
|
||||
slen = 0;
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -1974,7 +1983,7 @@ list_string (string, separators, quoted)
|
||||
{
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, 0);
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
|
||||
if (current_word == 0)
|
||||
break;
|
||||
|
||||
@@ -2056,19 +2065,20 @@ get_word_from_string (stringp, separators, endptr)
|
||||
{
|
||||
register char *s;
|
||||
char *current_word;
|
||||
int sindex, sh_style_split, whitesep;
|
||||
int sindex, sh_style_split, whitesep, xflags;
|
||||
size_t slen;
|
||||
|
||||
if (!stringp || !*stringp || !**stringp)
|
||||
return ((char *)NULL);
|
||||
|
||||
s = *stringp;
|
||||
|
||||
sh_style_split = separators && separators[0] == ' ' &&
|
||||
separators[1] == '\t' &&
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
|
||||
s = *stringp;
|
||||
slen = 0;
|
||||
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -2097,7 +2107,7 @@ get_word_from_string (stringp, separators, endptr)
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, 0);
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
|
||||
|
||||
/* Set ENDPTR to the first character after the end of the word. */
|
||||
if (endptr)
|
||||
@@ -2653,11 +2663,12 @@ remove_backslashes (string)
|
||||
|
||||
/* This needs better error handling. */
|
||||
/* Expand W for use as an argument to a unary or binary operator in a
|
||||
[[...]] expression. If SPECIAL is nonzero, this is the rhs argument
|
||||
[[...]] expression. If SPECIAL is 1, this is the rhs argument
|
||||
to the != or == operator, and should be treated as a pattern. In
|
||||
this case, we quote the string specially for the globbing code. The
|
||||
caller is responsible for removing the backslashes if the unquoted
|
||||
words is needed later. */
|
||||
this case, we quote the string specially for the globbing code. If
|
||||
SPECIAL is 2, this is an rhs argument for the =~ operator, and should
|
||||
be quoted appropriately for regcomp/regexec. The caller is responsible
|
||||
for removing the backslashes if the unquoted word is needed later. */
|
||||
char *
|
||||
cond_expand_word (w, special)
|
||||
WORD_DESC *w;
|
||||
@@ -2665,6 +2676,7 @@ cond_expand_word (w, special)
|
||||
{
|
||||
char *r, *p;
|
||||
WORD_LIST *l;
|
||||
int qflags;
|
||||
|
||||
if (w->word == 0 || w->word[0] == '\0')
|
||||
return ((char *)NULL);
|
||||
@@ -2679,8 +2691,11 @@ cond_expand_word (w, special)
|
||||
}
|
||||
else
|
||||
{
|
||||
qflags = QGLOB_CVTNULL;
|
||||
if (special == 2)
|
||||
qflags |= QGLOB_REGEXP;
|
||||
p = string_list (l);
|
||||
r = quote_string_for_globbing (p, QGLOB_CVTNULL);
|
||||
r = quote_string_for_globbing (p, qflags);
|
||||
free (p);
|
||||
}
|
||||
dispose_words (l);
|
||||
@@ -2923,7 +2938,14 @@ expand_string (string, quoted)
|
||||
|
||||
/* Quote escape characters in string s, but no other characters. This is
|
||||
used to protect CTLESC and CTLNUL in variable values from the rest of
|
||||
the word expansion process after the variable is expanded. */
|
||||
the word expansion process after the variable is expanded (word splitting
|
||||
and filename generation). If IFS is null, we quote spaces as well, just
|
||||
in case we split on spaces later (in the case of unquoted $@, we will
|
||||
eventually attempt to split the entire word on spaces). Corresponding
|
||||
code exists in dequote_escapes. Even if we don't end up splitting on
|
||||
spaces, quoting spaces is not a problem. This should never be called on
|
||||
a string that is quoted with single or double quotes or part of a here
|
||||
document (effectively double-quoted). */
|
||||
char *
|
||||
quote_escapes (string)
|
||||
char *string;
|
||||
@@ -2931,17 +2953,23 @@ quote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces, skip_ctlesc;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC;
|
||||
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC || *s == CTLNUL)
|
||||
if ((skip_ctlesc == 0 && *s == CTLESC) || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
@@ -2980,9 +3008,10 @@ static char *
|
||||
dequote_escapes (string)
|
||||
char *string;
|
||||
{
|
||||
register char *s, *t;
|
||||
register char *s, *t, *s1;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
if (string == 0)
|
||||
@@ -2992,14 +3021,16 @@ dequote_escapes (string)
|
||||
send = string + slen;
|
||||
|
||||
t = result = (char *)xmalloc (slen + 1);
|
||||
s = string;
|
||||
|
||||
if (strchr (string, CTLESC) == 0)
|
||||
return (strcpy (result, s));
|
||||
return (strcpy (result, string));
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
s = string;
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
|
||||
{
|
||||
s++;
|
||||
if (*s == '\0')
|
||||
@@ -3973,7 +4004,9 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
||||
FREE (val);
|
||||
if (temp1)
|
||||
{
|
||||
val = quote_escapes (temp1);
|
||||
val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
? quote_string (temp1)
|
||||
: quote_escapes (temp1);
|
||||
free (temp1);
|
||||
temp1 = val;
|
||||
}
|
||||
@@ -4317,7 +4350,7 @@ process_substitute (string, open_for_read_in_child)
|
||||
/* Cancel traps, in trap.c. */
|
||||
restore_original_signals ();
|
||||
setup_async_signals ();
|
||||
subshell_environment |= SUBSHELL_COMSUB;
|
||||
subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
|
||||
}
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
@@ -4440,18 +4473,22 @@ read_comsub (fd, quoted, rflag)
|
||||
int fd, quoted;
|
||||
int *rflag;
|
||||
{
|
||||
char *istring, buf[128], *bufp;
|
||||
int istring_index, istring_size, c, tflag;
|
||||
char *istring, buf[128], *bufp, *s;
|
||||
int istring_index, istring_size, c, tflag, skip_ctlesc;
|
||||
ssize_t bufn;
|
||||
|
||||
istring = (char *)NULL;
|
||||
istring_index = istring_size = bufn = tflag = 0;
|
||||
|
||||
for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
|
||||
#endif
|
||||
|
||||
/* Read the output of the command through the pipe. */
|
||||
/* Read the output of the command through the pipe. This may need to be
|
||||
changed to understand multibyte characters in the future. */
|
||||
while (1)
|
||||
{
|
||||
if (fd < 0)
|
||||
@@ -4476,16 +4513,18 @@ read_comsub (fd, quoted, rflag)
|
||||
/* Add the character to ISTRING, possibly after resizing it. */
|
||||
RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
|
||||
|
||||
/* This is essentially quote_string inline */
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
|
||||
istring[istring_index++] = CTLESC;
|
||||
/* Escape CTLESC and CTLNUL in the output to protect those characters
|
||||
from the rest of the word expansions (word splitting and globbing.) */
|
||||
else if (c == CTLESC)
|
||||
from the rest of the word expansions (word splitting and globbing.)
|
||||
This is essentially quote_escapes inline. */
|
||||
else if (skip_ctlesc == 0 && c == CTLESC)
|
||||
{
|
||||
tflag |= W_HASCTLESC;
|
||||
istring[istring_index++] = CTLESC;
|
||||
}
|
||||
else if (c == CTLNUL)
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
@@ -5585,14 +5624,9 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
/* We want E2 to be the number of elements desired (arrays can be sparse,
|
||||
so verify_substring_values just returns the numbers specified and we
|
||||
rely on array_subrange to understand how to deal with them). */
|
||||
tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
|
||||
{
|
||||
temp = tt ? quote_escapes (tt) : (char *)NULL;
|
||||
FREE (tt);
|
||||
}
|
||||
else
|
||||
temp = tt;
|
||||
temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
/* array_subrange now calls array_quote_escapes as appropriate, so the
|
||||
caller no longer needs to. */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -5825,7 +5859,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
FREE (val);
|
||||
if (temp)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
@@ -5842,12 +5876,9 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
temp = array_patsub (array_cell (v), p, rep, mflags);
|
||||
if (temp && (mflags & MATCH_QUOTED) == 0)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
/* Don't call quote_escapes anymore; array_patsub calls
|
||||
array_quote_escapes as appropriate before adding the
|
||||
space separators. */
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -5937,9 +5968,9 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
t_index = ++sindex;
|
||||
/* ${#var} doesn't have any of the other parameter expansions on it. */
|
||||
if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
|
||||
name = string_extract (string, &t_index, "}", EX_VARNAME);
|
||||
name = string_extract (string, &t_index, "}", SX_VARNAME);
|
||||
else
|
||||
name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
|
||||
name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
|
||||
|
||||
ret = 0;
|
||||
tflag = 0;
|
||||
@@ -6996,7 +7027,7 @@ add_string:
|
||||
{
|
||||
t_index = sindex++;
|
||||
|
||||
temp = string_extract (string, &sindex, "`", EX_REQMATCH);
|
||||
temp = string_extract (string, &sindex, "`", SX_REQMATCH);
|
||||
/* The test of sindex against t_index is to allow bare instances of
|
||||
` to pass through, for backwards compatibility. */
|
||||
if (temp == &extract_string_error || temp == &extract_string_fatal)
|
||||
|
||||
+8224
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -79,10 +79,12 @@ extern int errno;
|
||||
#define ST_DQUOTE 0x08 /* unused yet */
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define EX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define EX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define EX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define EX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
@@ -543,11 +545,11 @@ sub_append_number (number, target, indx, size)
|
||||
/* Extract a substring from STRING, starting at SINDEX and ending with
|
||||
one of the characters in CHARLIST. Don't make the ending character
|
||||
part of the string. Leave SINDEX pointing at the ending character.
|
||||
Understand about backslashes in the string. If (flags & EX_VARNAME)
|
||||
Understand about backslashes in the string. If (flags & SX_VARNAME)
|
||||
is non-zero, and array variables have been compiled into the shell,
|
||||
everything between a `[' and a corresponding `]' is skipped over.
|
||||
If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
|
||||
update SINDEX. If (flags & EX_REQMATCH) is non-zero, the string must
|
||||
If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
|
||||
update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
|
||||
contain a closing character from CHARLIST. */
|
||||
static char *
|
||||
string_extract (string, sindex, charlist, flags)
|
||||
@@ -575,7 +577,7 @@ string_extract (string, sindex, charlist, flags)
|
||||
break;
|
||||
}
|
||||
#if defined (ARRAY_VARS)
|
||||
else if ((flags & EX_VARNAME) && c == '[')
|
||||
else if ((flags & SX_VARNAME) && c == '[')
|
||||
{
|
||||
int ni;
|
||||
/* If this is an array subscript, skip over it and continue. */
|
||||
@@ -595,13 +597,13 @@ string_extract (string, sindex, charlist, flags)
|
||||
|
||||
/* If we had to have a matching delimiter and didn't find one, return an
|
||||
error and let the caller deal with it. */
|
||||
if ((flags & EX_REQMATCH) && found == 0)
|
||||
if ((flags & SX_REQMATCH) && found == 0)
|
||||
{
|
||||
*sindex = i;
|
||||
return (&extract_string_error);
|
||||
}
|
||||
|
||||
temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
*sindex = i;
|
||||
|
||||
return (temp);
|
||||
@@ -712,7 +714,7 @@ add_one_character:
|
||||
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_COMMAND); /*)*/
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 1, 0);
|
||||
|
||||
@@ -814,9 +816,9 @@ skip_double_quoted (string, slen, sind)
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
|
||||
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
|
||||
i = si + 1;
|
||||
continue;
|
||||
@@ -924,12 +926,19 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
size_t mblength;
|
||||
#endif
|
||||
if (c == CTLESC)
|
||||
if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
/* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
|
||||
through, to protect the CTLNULs from later calls to
|
||||
remove_quoted_nulls. */
|
||||
else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mblength = MBLEN (string + i, slen - i);
|
||||
if (mblength > 1)
|
||||
@@ -983,7 +992,7 @@ extract_command_subst (string, sindex)
|
||||
char *string;
|
||||
int *sindex;
|
||||
{
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", EX_COMMAND)); /*)*/
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
|
||||
}
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string. (])
|
||||
@@ -1090,7 +1099,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
|
||||
/* Not exactly right yet; should handle shell metacharacters and
|
||||
multibyte characters, too. */
|
||||
if ((flags & EX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
{
|
||||
in_comment = 1;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -1108,7 +1117,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (STREQN (string + i, opener, len_opener))
|
||||
{
|
||||
si = i + len_opener;
|
||||
t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
|
||||
t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1117,7 +1126,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
|
||||
{
|
||||
si = i + len_alt_opener;
|
||||
t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
|
||||
t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1136,7 +1145,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
if (c == '`')
|
||||
{
|
||||
si = i + 1;
|
||||
t = string_extract (string, &si, "`", flags|EX_NOALLOC);
|
||||
t = string_extract (string, &si, "`", flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1170,7 +1179,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
}
|
||||
|
||||
si = i - *sindex - len_closer + 1;
|
||||
if (flags & EX_NOALLOC)
|
||||
if (flags & SX_NOALLOC)
|
||||
result = (char *)NULL;
|
||||
else
|
||||
{
|
||||
@@ -1245,7 +1254,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (c == '`')
|
||||
{
|
||||
si = i + 1;
|
||||
t = string_extract (string, &si, "`", flags|EX_NOALLOC);
|
||||
t = string_extract (string, &si, "`", flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1255,7 +1264,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (string[i] == '$' && string[i+1] == LPAREN)
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC|EX_COMMAND); /*)*/
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|SX_NOALLOC|SX_COMMAND); /*)*/
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1290,7 +1299,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
}
|
||||
}
|
||||
|
||||
result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
|
||||
*sindex = i;
|
||||
|
||||
return (result);
|
||||
@@ -1518,9 +1527,9 @@ skip_to_delim (string, start, delims)
|
||||
CQ_RETURN(si);
|
||||
|
||||
if (string[i+1] == LPAREN)
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
|
||||
temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
i = si;
|
||||
if (string[i] == '\0') /* don't increment i past EOS in loop */
|
||||
break;
|
||||
@@ -1945,7 +1954,7 @@ list_string (string, separators, quoted)
|
||||
WORD_LIST *result;
|
||||
WORD_DESC *t;
|
||||
char *current_word, *s;
|
||||
int sindex, sh_style_split, whitesep;
|
||||
int sindex, sh_style_split, whitesep, xflags;
|
||||
size_t slen;
|
||||
|
||||
if (!string || !*string)
|
||||
@@ -1955,6 +1964,11 @@ list_string (string, separators, quoted)
|
||||
separators[1] == '\t' &&
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
slen = 0;
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -1980,7 +1994,7 @@ list_string (string, separators, quoted)
|
||||
{
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, 0);
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
|
||||
if (current_word == 0)
|
||||
break;
|
||||
|
||||
@@ -2062,19 +2076,23 @@ get_word_from_string (stringp, separators, endptr)
|
||||
{
|
||||
register char *s;
|
||||
char *current_word;
|
||||
int sindex, sh_style_split, whitesep;
|
||||
int sindex, sh_style_split, whitesep, xflags;
|
||||
size_t slen;
|
||||
|
||||
if (!stringp || !*stringp || !**stringp)
|
||||
return ((char *)NULL);
|
||||
|
||||
s = *stringp;
|
||||
|
||||
sh_style_split = separators && separators[0] == ' ' &&
|
||||
separators[1] == '\t' &&
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
s = *stringp;
|
||||
slen = 0;
|
||||
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -2103,7 +2121,7 @@ get_word_from_string (stringp, separators, endptr)
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, 0);
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
|
||||
|
||||
/* Set ENDPTR to the first character after the end of the word. */
|
||||
if (endptr)
|
||||
@@ -2659,11 +2677,12 @@ remove_backslashes (string)
|
||||
|
||||
/* This needs better error handling. */
|
||||
/* Expand W for use as an argument to a unary or binary operator in a
|
||||
[[...]] expression. If SPECIAL is nonzero, this is the rhs argument
|
||||
[[...]] expression. If SPECIAL is 1, this is the rhs argument
|
||||
to the != or == operator, and should be treated as a pattern. In
|
||||
this case, we quote the string specially for the globbing code. The
|
||||
caller is responsible for removing the backslashes if the unquoted
|
||||
words is needed later. */
|
||||
this case, we quote the string specially for the globbing code. If
|
||||
SPECIAL is 2, this is an rhs argument for the =~ operator, and should
|
||||
be quoted appropriately for regcomp/regexec. The caller is responsible
|
||||
for removing the backslashes if the unquoted word is needed later. */
|
||||
char *
|
||||
cond_expand_word (w, special)
|
||||
WORD_DESC *w;
|
||||
@@ -2671,6 +2690,7 @@ cond_expand_word (w, special)
|
||||
{
|
||||
char *r, *p;
|
||||
WORD_LIST *l;
|
||||
int qflags;
|
||||
|
||||
if (w->word == 0 || w->word[0] == '\0')
|
||||
return ((char *)NULL);
|
||||
@@ -2685,8 +2705,11 @@ cond_expand_word (w, special)
|
||||
}
|
||||
else
|
||||
{
|
||||
qflags = QGLOB_CVTNULL;
|
||||
if (special == 2)
|
||||
qflags |= QGLOB_REGEXP;
|
||||
p = string_list (l);
|
||||
r = quote_string_for_globbing (p, QGLOB_CVTNULL);
|
||||
r = quote_string_for_globbing (p, qflags);
|
||||
free (p);
|
||||
}
|
||||
dispose_words (l);
|
||||
@@ -2929,12 +2952,14 @@ expand_string (string, quoted)
|
||||
|
||||
/* Quote escape characters in string s, but no other characters. This is
|
||||
used to protect CTLESC and CTLNUL in variable values from the rest of
|
||||
the word expansion process after the variable is expanded. If IFS is
|
||||
null, we quote spaces as well, just in case we split on spaces later
|
||||
(in the case of unquoted $@, we will eventually attempt to split the
|
||||
entire word on spaces). Corresponding code exists in dequote_escapes.
|
||||
Even if we don't end up splitting on spaces, quoting spaces is not a
|
||||
problem. */
|
||||
the word expansion process after the variable is expanded (word splitting
|
||||
and filename generation). If IFS is null, we quote spaces as well, just
|
||||
in case we split on spaces later (in the case of unquoted $@, we will
|
||||
eventually attempt to split the entire word on spaces). Corresponding
|
||||
code exists in dequote_escapes. Even if we don't end up splitting on
|
||||
spaces, quoting spaces is not a problem. This should never be called on
|
||||
a string that is quoted with single or double quotes or part of a here
|
||||
document (effectively double-quoted). */
|
||||
char *
|
||||
quote_escapes (string)
|
||||
char *string;
|
||||
@@ -2942,19 +2967,26 @@ quote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
int quote_spaces, skip_ctlesc, skip_ctlnul;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
{
|
||||
skip_ctlesc |= *s == CTLESC;
|
||||
skip_ctlnul |= *s == CTLNUL;
|
||||
}
|
||||
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
@@ -2993,7 +3025,7 @@ static char *
|
||||
dequote_escapes (string)
|
||||
char *string;
|
||||
{
|
||||
register char *s, *t;
|
||||
register char *s, *t, *s1;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
@@ -3006,12 +3038,13 @@ dequote_escapes (string)
|
||||
send = string + slen;
|
||||
|
||||
t = result = (char *)xmalloc (slen + 1);
|
||||
s = string;
|
||||
|
||||
if (strchr (string, CTLESC) == 0)
|
||||
return (strcpy (result, s));
|
||||
return (strcpy (result, string));
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
s = string;
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
|
||||
@@ -3988,7 +4021,9 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
||||
FREE (val);
|
||||
if (temp1)
|
||||
{
|
||||
val = quote_escapes (temp1);
|
||||
val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
? quote_string (temp1)
|
||||
: quote_escapes (temp1);
|
||||
free (temp1);
|
||||
temp1 = val;
|
||||
}
|
||||
@@ -4332,7 +4367,7 @@ process_substitute (string, open_for_read_in_child)
|
||||
/* Cancel traps, in trap.c. */
|
||||
restore_original_signals ();
|
||||
setup_async_signals ();
|
||||
subshell_environment |= SUBSHELL_COMSUB;
|
||||
subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
|
||||
}
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
@@ -4455,13 +4490,16 @@ read_comsub (fd, quoted, rflag)
|
||||
int fd, quoted;
|
||||
int *rflag;
|
||||
{
|
||||
char *istring, buf[128], *bufp;
|
||||
int istring_index, istring_size, c, tflag;
|
||||
char *istring, buf[128], *bufp, *s;
|
||||
int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
|
||||
ssize_t bufn;
|
||||
|
||||
istring = (char *)NULL;
|
||||
istring_index = istring_size = bufn = tflag = 0;
|
||||
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
|
||||
#endif
|
||||
@@ -4498,12 +4536,12 @@ read_comsub (fd, quoted, rflag)
|
||||
/* Escape CTLESC and CTLNUL in the output to protect those characters
|
||||
from the rest of the word expansions (word splitting and globbing.)
|
||||
This is essentially quote_escapes inline. */
|
||||
else if (c == CTLESC)
|
||||
else if (skip_ctlesc == 0 && c == CTLESC)
|
||||
{
|
||||
tflag |= W_HASCTLESC;
|
||||
istring[istring_index++] = CTLESC;
|
||||
}
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
@@ -5603,14 +5641,9 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
/* We want E2 to be the number of elements desired (arrays can be sparse,
|
||||
so verify_substring_values just returns the numbers specified and we
|
||||
rely on array_subrange to understand how to deal with them). */
|
||||
tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
|
||||
{
|
||||
temp = tt ? quote_escapes (tt) : (char *)NULL;
|
||||
FREE (tt);
|
||||
}
|
||||
else
|
||||
temp = tt;
|
||||
temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
/* array_subrange now calls array_quote_escapes as appropriate, so the
|
||||
caller no longer needs to. */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -5843,7 +5876,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
FREE (val);
|
||||
if (temp)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
@@ -5860,16 +5893,9 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
temp = array_patsub (array_cell (v), p, rep, mflags);
|
||||
#if 0
|
||||
/* Don't need to do this anymore; array_patsub calls array_quote_escapes
|
||||
as appropriate before adding the space separators. */
|
||||
if (temp && (mflags & MATCH_QUOTED) == 0)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
#endif
|
||||
/* Don't call quote_escapes anymore; array_patsub calls
|
||||
array_quote_escapes as appropriate before adding the
|
||||
space separators. */
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -5959,9 +5985,9 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
t_index = ++sindex;
|
||||
/* ${#var} doesn't have any of the other parameter expansions on it. */
|
||||
if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
|
||||
name = string_extract (string, &t_index, "}", EX_VARNAME);
|
||||
name = string_extract (string, &t_index, "}", SX_VARNAME);
|
||||
else
|
||||
name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
|
||||
name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
|
||||
|
||||
ret = 0;
|
||||
tflag = 0;
|
||||
@@ -7018,7 +7044,7 @@ add_string:
|
||||
{
|
||||
t_index = sindex++;
|
||||
|
||||
temp = string_extract (string, &sindex, "`", EX_REQMATCH);
|
||||
temp = string_extract (string, &sindex, "`", SX_REQMATCH);
|
||||
/* The test of sindex against t_index is to allow bare instances of
|
||||
` to pass through, for backwards compatibility. */
|
||||
if (temp == &extract_string_error || temp == &extract_string_fatal)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
+64
-4
@@ -152,10 +152,10 @@ for case if then else
|
||||
12 14 16 18 20
|
||||
4414758999202
|
||||
aaa bbb
|
||||
./array.tests: line 285: syntax error near unexpected token `<>'
|
||||
./array.tests: line 285: `metas=( <> < > ! )'
|
||||
./array.tests: line 286: syntax error near unexpected token `<>'
|
||||
./array.tests: line 286: `metas=( [1]=<> [2]=< [3]=> [4]=! )'
|
||||
./array.tests: line 287: syntax error near unexpected token `<>'
|
||||
./array.tests: line 287: `metas=( <> < > ! )'
|
||||
./array.tests: line 288: syntax error near unexpected token `<>'
|
||||
./array.tests: line 288: `metas=( [1]=<> [2]=< [3]=> [4]=! )'
|
||||
abc 3
|
||||
case 4
|
||||
abc case if then else 5
|
||||
@@ -206,3 +206,63 @@ t
|
||||
e
|
||||
9
|
||||
2
|
||||
a b c
|
||||
argv[1] = <"-iname '"a>
|
||||
argv[2] = <"-iname '"b>
|
||||
argv[3] = <"-iname '"c>
|
||||
'hey'
|
||||
hey
|
||||
''hey
|
||||
'hey'
|
||||
argv[1] = <c>
|
||||
argv[2] = <d>
|
||||
argv[3] = <e>
|
||||
argv[4] = <f>
|
||||
argv[1] = <c d>
|
||||
argv[2] = <e f>
|
||||
argv[1] = <c d>
|
||||
argv[2] = <e f>
|
||||
argv[1] = <c d>
|
||||
argv[2] = <e f>
|
||||
argv[1] = <"-iname '"abc>
|
||||
argv[2] = <"-iname '"def>
|
||||
argv[1] = <-iname 'abc>
|
||||
argv[2] = <-iname 'def>
|
||||
argv[1] = <-iname \'abc>
|
||||
argv[2] = <-iname \'def>
|
||||
argv[1] = <-iname>
|
||||
argv[2] = <'abc>
|
||||
argv[3] = <-iname>
|
||||
argv[4] = <'def>
|
||||
argv[1] = <"-iname '"abc>
|
||||
argv[2] = <"-iname '"def>
|
||||
argv[1] = <-iname 'abc>
|
||||
argv[2] = <-iname 'def>
|
||||
*.* OK
|
||||
1
|
||||
a1 2 3c
|
||||
argv[1] = <var with spaces>
|
||||
argv[1] = <var with spaces>
|
||||
argv[1] = <var with spacesab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <var with spacesab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <var with spacesab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <var with spacesab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <var with spacesab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <var with spacesab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
2
|
||||
argv[1] = <element1 with spaces>
|
||||
argv[2] = <element2 with spaces>
|
||||
argv[1] = <element1 with spaces>
|
||||
argv[2] = <element2 with spaces>
|
||||
|
||||
+6
-30
@@ -253,6 +253,8 @@ foo=([10]="bar")
|
||||
echo ${foo[0]}
|
||||
rm 1=bar
|
||||
|
||||
cd $OLDPWD
|
||||
|
||||
foo=(a b c d e f g)
|
||||
echo ${foo[@]}
|
||||
|
||||
@@ -372,34 +374,8 @@ declare -a x=($0)
|
||||
declare -a x=(\$0)
|
||||
echo "${x[@]}"
|
||||
|
||||
: ${TMPDIR:=/tmp}
|
||||
# tests for bash-3.1 problems
|
||||
${THIS_SH} ./array5.sub
|
||||
|
||||
mkdir $TMPDIR/bash-test-$$
|
||||
cd $TMPDIR/bash-test-$$
|
||||
|
||||
trap "cd / ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15
|
||||
|
||||
touch '[3]=abcde'
|
||||
|
||||
touch r s t u v
|
||||
|
||||
declare -a x=(*)
|
||||
|
||||
echo ${x[3]}
|
||||
echo ${x[@]}
|
||||
|
||||
unset x
|
||||
x=(a b c d e)
|
||||
|
||||
echo ${x[*]: -1}
|
||||
|
||||
unset x[4]
|
||||
unset x[2]
|
||||
|
||||
x[9]='9'
|
||||
|
||||
echo ${x[*]: -1}
|
||||
|
||||
TOOLKIT=(1 2 3 4 5 6 7 8 9 10)
|
||||
ARRAY="1"
|
||||
echo ${TOOLKIT["$ARRAY"]}
|
||||
# tests for post-bash-3.2 problems, most fixed in bash-3.2 patches
|
||||
${THIS_SH} ./array6.sub
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
: ${TMPDIR:=/tmp}
|
||||
|
||||
mkdir $TMPDIR/bash-test-$$
|
||||
cd $TMPDIR/bash-test-$$
|
||||
|
||||
trap "cd / ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15
|
||||
|
||||
touch '[3]=abcde'
|
||||
|
||||
touch r s t u v
|
||||
|
||||
declare -a x=(*)
|
||||
|
||||
echo ${x[3]}
|
||||
echo ${x[@]}
|
||||
|
||||
unset x
|
||||
x=(a b c d e)
|
||||
|
||||
echo ${x[*]: -1}
|
||||
|
||||
unset x[4]
|
||||
unset x[2]
|
||||
|
||||
x[9]='9'
|
||||
|
||||
echo ${x[*]: -1}
|
||||
|
||||
TOOLKIT=(1 2 3 4 5 6 7 8 9 10)
|
||||
ARRAY="1"
|
||||
echo ${TOOLKIT["$ARRAY"]}
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,109 @@
|
||||
# test cases for array quoting and escaping fixed post bash-3.2-release
|
||||
|
||||
oIFS="$IFS"
|
||||
|
||||
a=(a b c)
|
||||
echo ${a[@]}
|
||||
|
||||
a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
echo "${dbg-"'hey'"}"
|
||||
echo "${dbg-"hey"}"
|
||||
echo "${dbg-'"'hey}"
|
||||
echo "${dbg-'"hey'}"
|
||||
|
||||
unset a a2
|
||||
|
||||
IFS=
|
||||
a2=(${a[@]/#/"-iname '"})
|
||||
recho "${a2[@]}"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2
|
||||
|
||||
a=('a b' 'c d' 'e f')
|
||||
|
||||
recho ${a[@]:1:2}
|
||||
recho "${a[@]:1:2}"
|
||||
|
||||
IFS=
|
||||
recho ${a[@]:1:2}
|
||||
recho "${a[@]:1:2}"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2
|
||||
|
||||
a=(abc def)
|
||||
|
||||
# Prevent word splitting
|
||||
#IFS=
|
||||
|
||||
a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
a2=("${a[@]/#/-iname \'}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${a[@]/#/-iname \'}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
set -- abc def
|
||||
|
||||
a2=("${@/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${@/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
unset a a2
|
||||
|
||||
IFS=
|
||||
pat=('*.*')
|
||||
case $(ls ${pat[@]} 2>/dev/null) in
|
||||
'') echo '*.* BAD' ;;
|
||||
*) echo '*.* OK' ;;
|
||||
esac
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2 pat
|
||||
|
||||
IFS=
|
||||
|
||||
s='abc'
|
||||
|
||||
set - ${s/b/1 2 3}
|
||||
echo $#
|
||||
echo "$1"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset s
|
||||
|
||||
set -- ab cd ef
|
||||
foo="var with spaces"
|
||||
|
||||
IFS=
|
||||
recho $foo
|
||||
recho "$foo"
|
||||
|
||||
recho ${foo}"$@"
|
||||
recho ${foo}$@
|
||||
|
||||
array=(ab cd ef)
|
||||
recho ${foo}"${array[@]}"
|
||||
recho ${foo}${array[@]}
|
||||
|
||||
recho $(echo $foo)"$@"
|
||||
recho $(echo $foo)$@
|
||||
|
||||
a=('word1 with spaces' 'word2 with spaces')
|
||||
set - ${a[@]/word/element}
|
||||
echo $#
|
||||
recho "$@"
|
||||
recho $@
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2 array foo
|
||||
@@ -0,0 +1,123 @@
|
||||
# test cases for array quoting and escaping fixed post bash-3.2-release
|
||||
|
||||
oIFS="$IFS"
|
||||
|
||||
a=(a b c)
|
||||
echo ${a[@]}
|
||||
|
||||
a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
echo "${dbg-"'hey'"}"
|
||||
echo "${dbg-"hey"}"
|
||||
echo "${dbg-'"'hey}"
|
||||
echo "${dbg-'"hey'}"
|
||||
|
||||
unset a a2
|
||||
|
||||
IFS=
|
||||
a2=(${a[@]/#/"-iname '"})
|
||||
recho "${a2[@]}"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2
|
||||
|
||||
a=('a b' 'c d' 'e f')
|
||||
|
||||
recho ${a[@]:1:2}
|
||||
recho "${a[@]:1:2}"
|
||||
|
||||
IFS=
|
||||
recho ${a[@]:1:2}
|
||||
recho "${a[@]:1:2}"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2
|
||||
|
||||
a=(abc def)
|
||||
|
||||
# Prevent word splitting
|
||||
#IFS=
|
||||
|
||||
a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
a2=("${a[@]/#/-iname \'}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${a[@]/#/-iname \'}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
set -- abc def
|
||||
|
||||
a2=("${@/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${@/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
unset a a2
|
||||
|
||||
IFS=
|
||||
pat=('*.*')
|
||||
case $(ls ${pat[@]} 2>/dev/null) in
|
||||
'') echo '*.* BAD' ;;
|
||||
*) echo '*.* OK' ;;
|
||||
esac
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2 pat
|
||||
|
||||
IFS=
|
||||
|
||||
s='abc'
|
||||
|
||||
set - ${s/b/1 2 3}
|
||||
echo $#
|
||||
echo "$1"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset s
|
||||
|
||||
set -- ab cd ef
|
||||
foo="var with spaces"
|
||||
|
||||
IFS=
|
||||
recho $foo
|
||||
recho "$foo"
|
||||
|
||||
recho ${foo}"$@"
|
||||
recho ${foo}$@
|
||||
|
||||
array=(ab cd ef)
|
||||
recho ${foo}"${array[@]}"
|
||||
recho ${foo}${array[@]}
|
||||
|
||||
recho $(echo $foo)"$@"
|
||||
recho $(echo $foo)$@
|
||||
|
||||
a=('word1 with spaces' 'word2 with spaces')
|
||||
set - ${a[@]/word/element}
|
||||
echo $#
|
||||
recho "$@"
|
||||
recho $@
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2 array foo
|
||||
|
||||
a=$'ab\001cd\001ef'
|
||||
|
||||
recho $a
|
||||
recho "$a"
|
||||
|
||||
recho $(echo $a)
|
||||
recho $(echo "$a")
|
||||
|
||||
# XXX - this doesn't work right until post-bash-3.2
|
||||
IFS=$'\001'
|
||||
recho $a
|
||||
|
||||
IFS=$'\001' recho "$a"
|
||||
@@ -145,3 +145,14 @@ argv[4] = <d>
|
||||
argv[5] = <e>
|
||||
a?b?c
|
||||
a b c
|
||||
argv[1] = <^?>
|
||||
argv[1] = <^?>
|
||||
argv[1] = <^?>
|
||||
argv[1] = <^?>
|
||||
argv[1] = <^?>
|
||||
argv[1] = <^?>
|
||||
argv[1] = <^A>
|
||||
argv[2] = <^?>
|
||||
argv[1] = <^A^?>
|
||||
argv[1] = <^A^?^A^?>
|
||||
argv[1] = <^A^A^?>
|
||||
|
||||
+382
@@ -0,0 +1,382 @@
|
||||
#
|
||||
# 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
|
||||
@@ -0,0 +1,380 @@
|
||||
#
|
||||
# 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//\?/ }
|
||||
@@ -0,0 +1,21 @@
|
||||
# Test the substitution quoting characters (CTLESC and CTLNUL) in different
|
||||
# combinations
|
||||
|
||||
recho `echo ''`
|
||||
recho `echo ""`
|
||||
recho `echo `
|
||||
|
||||
# Test the unquoted special quoting characters
|
||||
recho
|
||||
recho ""
|
||||
recho ''
|
||||
|
||||
# This should give argv[1] = ^A argv[2] = ^?
|
||||
FOO=`echo ' ' | tr ' ' '\012'`
|
||||
recho $FOO
|
||||
|
||||
# Test patterns that come up when the shell quotes funny character
|
||||
# combinations
|
||||
recho ''
|
||||
recho ''
|
||||
recho ''
|
||||
@@ -0,0 +1,94 @@
|
||||
a=$'a\001b'
|
||||
|
||||
set $a
|
||||
|
||||
b=$a
|
||||
c=$1
|
||||
d="$1"
|
||||
|
||||
e=$'uv\001\001wx'
|
||||
f=$'uv\001w\001xy'
|
||||
|
||||
set $e $e
|
||||
|
||||
recho ${e%%??}
|
||||
recho "${e%%??}"
|
||||
|
||||
recho ${e%%???}
|
||||
recho "${e%%???}"
|
||||
|
||||
recho ${a#?}
|
||||
recho "${a#?}"
|
||||
|
||||
# simple variables
|
||||
|
||||
recho ${f##*$'\001'}
|
||||
recho "${f##*$'\001'}"
|
||||
recho ${f##*''} # literal ^A
|
||||
recho "${f##*'^A'}" # two characters, `^' and `A'
|
||||
|
||||
recho ${e%$'\001'*}
|
||||
recho "${e%$'\001'*}"
|
||||
recho ${e#*$'\001'}
|
||||
recho "${e#*$'\001'}"
|
||||
|
||||
# array members
|
||||
|
||||
arr[0]=$e
|
||||
arr[1]=$f
|
||||
|
||||
recho ${arr[1]##*$'\001'}
|
||||
recho "${arr[1]##*$'\001'}"
|
||||
recho ${arr[1]##*''} # literal ^A
|
||||
recho "${arr[1]##*'^A'}" # two characters, `^' and `A'
|
||||
|
||||
recho ${arr[0]%$'\001'*}
|
||||
recho "${arr[0]%$'\001'*}"
|
||||
recho ${arr[0]#*$'\001'}
|
||||
recho "${arr[0]#*$'\001'}"
|
||||
|
||||
recho ${arr%$'\001'*}
|
||||
recho "${arr%$'\001'*}"
|
||||
recho ${arr#*$'\001'}
|
||||
recho "${arr#*$'\001'}"
|
||||
|
||||
# positional parameters
|
||||
|
||||
set $e $f
|
||||
|
||||
recho ${2##*$'\001'}
|
||||
recho "${2##*$'\001'}"
|
||||
recho ${2##*''} # literal ^A
|
||||
recho "${2##*''}" # literal ^A
|
||||
recho ${2##*'^A'} # two characters, `^' and `A'
|
||||
recho "${2##*'^A'}" # two characters, `^' and `A'
|
||||
|
||||
recho ${1%$'\001'*}
|
||||
recho "${1%$'\001'*}"
|
||||
recho ${1#*$'\001'}
|
||||
recho "${1#*$'\001'}"
|
||||
|
||||
recho ${@%$'\001'*}
|
||||
recho "${@%$'\001'*}"
|
||||
recho ${@#*$'\001'}
|
||||
recho "${@#*$'\001'}"
|
||||
recho ${@##*''} # literal ^A
|
||||
recho "${@##*'^A'}" # two characters, `^' and `A'
|
||||
|
||||
# arrays treated as a whole
|
||||
|
||||
recho ${arr[@]%$'\001'*}
|
||||
recho "${arr[@]%$'\001'*}"
|
||||
recho ${arr[@]#*$'\001'}
|
||||
recho "${arr[@]#*$'\001'}"
|
||||
recho ${arr[@]##*''} # literal ^A
|
||||
recho "${arr[@]##*'^A'}" # two characters, `^' and `A'
|
||||
|
||||
# make sure command substitution works with CTLESC as well
|
||||
a=$'ab\001cd\001ef'
|
||||
|
||||
recho $a
|
||||
recho "$a"
|
||||
|
||||
recho $(echo $a)
|
||||
recho $(echo "$a")
|
||||
@@ -0,0 +1,86 @@
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <xxab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <efyy>
|
||||
argv[1] = <ab^Acd^Aef>
|
||||
argv[1] = <ab cd ef>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[1] = <ab^Acd^A>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <e>
|
||||
argv[1] = <ab^Acd^Ae>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <>
|
||||
argv[2] = <c>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <-->
|
||||
argv[3] = <cd>
|
||||
argv[4] = <-->
|
||||
argv[5] = <ef>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <ef>
|
||||
argv[1] = <ab>
|
||||
argv[2] = <-->
|
||||
argv[3] = <cd>
|
||||
argv[4] = <-->
|
||||
argv[5] = <ef>
|
||||
argv[1] = <uv^?wx^?yz>
|
||||
argv[1] = <abyab^Acd^Aefz>
|
||||
argv[1] = <abyab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <efz>
|
||||
argv[1] = <abuv^?wx^?yzyab^Acd^Aefz>
|
||||
argv[1] = <abuv^?wx^?yzyab>
|
||||
argv[2] = <cd>
|
||||
argv[3] = <efz>
|
||||
argv[1] = <abuv^?wx^?yzyab>
|
||||
argv[2] = <-->
|
||||
argv[3] = <cd>
|
||||
argv[4] = <-->
|
||||
argv[5] = <efz>
|
||||
argv[6] = <-->
|
||||
argv[1] = <ab^Acd^Aef>
|
||||
argv[1] = <uv>
|
||||
argv[2] = <wx>
|
||||
argv[3] = <yz>
|
||||
argv[1] = <abyuv^?wx^?yzz>
|
||||
argv[1] = <abyuv>
|
||||
argv[2] = <wx>
|
||||
argv[3] = <yzz>
|
||||
argv[1] = <abuv^?wx^?yzyab^Acd^Aefz>
|
||||
argv[1] = <abuv>
|
||||
argv[2] = <wx>
|
||||
argv[3] = <yzyab^Acd^Aefz>
|
||||
argv[1] = <abuv^?wx^?yzyab>
|
||||
argv[2] = <-->
|
||||
argv[3] = <cd>
|
||||
argv[4] = <-->
|
||||
argv[5] = <efz>
|
||||
argv[6] = <-->
|
||||
argv[7] = <>
|
||||
argv[1] = <abuv>
|
||||
argv[2] = <-->
|
||||
argv[3] = <wx>
|
||||
argv[4] = <-->
|
||||
argv[5] = <yzyab^Acd^Aefz>
|
||||
argv[6] = <-->
|
||||
argv[7] = <>
|
||||
@@ -0,0 +1,63 @@
|
||||
a=$'ab\001cd\001ef'
|
||||
IFS=$'\001'
|
||||
|
||||
recho $a
|
||||
recho ${a}
|
||||
recho xx${a}yy
|
||||
recho "$a"
|
||||
|
||||
recho $(echo $a)
|
||||
recho $(echo "$a")
|
||||
|
||||
recho ${a%%??}
|
||||
recho "${a%%??}"
|
||||
|
||||
recho ${a/f/}
|
||||
recho "${a/f/}"
|
||||
|
||||
a1=("$a")
|
||||
recho ${a1[0]}
|
||||
recho ${a1}
|
||||
|
||||
recho ${a:2:2}
|
||||
|
||||
set -- $a
|
||||
recho $1 -- $2 -- $3
|
||||
|
||||
set -- "$a"
|
||||
recho $1
|
||||
recho ${1}
|
||||
|
||||
echo "$a" | { IFS=$'\001' read x y z; recho $x -- $y -- $z ; }
|
||||
unset x y z
|
||||
b=$'uv\177wx\177yz'
|
||||
|
||||
recho $b
|
||||
|
||||
recho "ab${x}y${a}z"
|
||||
recho ab${x}y${a}z
|
||||
|
||||
recho "ab${b}y${a}z"
|
||||
recho ab${b}y${a}z
|
||||
|
||||
echo "ab${b}y${a}z" | { IFS=$'\001' read l m n o ; recho $l -- $m -- $n -- $o; }
|
||||
unset l m n o
|
||||
|
||||
a=$'ab\001cd\001ef'
|
||||
b=$'uv\177wx\177yz'
|
||||
|
||||
IFS=$'\177'
|
||||
|
||||
recho $a
|
||||
recho $b
|
||||
|
||||
recho "ab${x}y${b}z"
|
||||
recho ab${x}y${b}z
|
||||
|
||||
recho "ab${b}y${a}z"
|
||||
recho ab${b}y${a}z
|
||||
|
||||
echo "ab${b}y${a}z" | { IFS=$'\001' read l m n o ; recho "$l" -- "$m" -- "$n" -- "$o"; }
|
||||
unset l m n o
|
||||
echo "ab${b}y${a}z" | { IFS=$'\177' read l m n o ; recho "$l" -- "$m" -- "$n" -- "$o"; }
|
||||
unset l m n o
|
||||
@@ -0,0 +1,43 @@
|
||||
a=$'ab\001cd\001ef'
|
||||
IFS=$'\001'
|
||||
|
||||
recho $a
|
||||
recho ${a}
|
||||
recho xx${a}yy
|
||||
recho "$a"
|
||||
|
||||
recho $(echo $a)
|
||||
recho $(echo "$a")
|
||||
|
||||
recho ${a%%??}
|
||||
recho "${a%%??}"
|
||||
|
||||
recho ${a/f/}
|
||||
recho "${a/f/}"
|
||||
|
||||
a1=("$a")
|
||||
recho ${a1[0]}
|
||||
recho ${a1}
|
||||
|
||||
recho ${a:2:2}
|
||||
|
||||
set -- $a
|
||||
recho $1 -- $2 -- $3
|
||||
|
||||
set -- "$a"
|
||||
recho $1
|
||||
recho ${1}
|
||||
|
||||
echo "$a" | { IFS=$'\001' read x y z; recho $x -- $y -- $z ; }
|
||||
unset x y z
|
||||
b=$'uv\177wx\177yz'
|
||||
|
||||
recho $b
|
||||
|
||||
recho "ab${x}y${a}z"
|
||||
recho ab${x}y${a}z
|
||||
|
||||
recho "ab${b}y${a}z"
|
||||
recho ab${b}y${a}z
|
||||
|
||||
echo "ab${b}y${a}z" | { IFS=$'\001' read l m n o ; recho $l -- $m -- $n -- $o; }
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
echo "warning: some of these tests may fail if process substitution has not" >&2
|
||||
echo "warning: been compiled into the shell" >&2
|
||||
echo "warning: been compiled into the shell or if the OS does not provide" >&2
|
||||
echo "warning: /dev/fd." >&2
|
||||
|
||||
${THIS_SH} ./builtins.tests > /tmp/xx 2>&1
|
||||
diff /tmp/xx builtins.right && rm -f /tmp/xx
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
echo "warning: some of these tests may fail if process substitution has not" >&2
|
||||
echo "warning: been compiled into the shell or if the OS does not provide" >&2
|
||||
ecoh "warning: /dev/fd." >&2
|
||||
|
||||
${THIS_SH} ./builtins.tests > /tmp/xx 2>&1
|
||||
diff /tmp/xx builtins.right && rm -f /tmp/xx
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
${THIS_SH} ./exp-tests | grep -v '^expect' > /tmp/xx
|
||||
${THIS_SH} ./exp.tests | grep -v '^expect' > /tmp/xx
|
||||
diff /tmp/xx exp.right && rm -f /tmp/xx
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
${THIS_SH} ./exp-tests | grep -v '^expect' > /tmp/xx
|
||||
diff /tmp/xx exp.right && rm -f /tmp/xx
|
||||
@@ -0,0 +1,2 @@
|
||||
${THIS_SH} ./nquote5.tests 2>&1 | grep -v '^expect' > /tmp/xx
|
||||
diff /tmp/xx nquote5.right && rm -f /tmp/xx
|
||||
@@ -0,0 +1,4 @@
|
||||
echo warning: some of these tests will fail if you do not have UTF-8 >&2
|
||||
echo warning: locales installed on your system
|
||||
${THIS_SH} ./nquote4.tests 2>&1 | grep -v '^expect' > /tmp/xx
|
||||
diff /tmp/xx nquote4.right && rm -f /tmp/xx
|
||||
Reference in New Issue
Block a user