shell/read: fix "'read' without parameters" bash compat thingy

previous change:

function                                             old     new   delta
builtin_read                                          82    1074    +992
popstring                                            134     140      +6
readcmd                                             1034     148    -886
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 998/-886)          Total: 112 bytes

this change:

builtin_read                                        1074    1096     +22
static.arg_REPLY                                       8       -      -8
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/0 up/down: 22/-8)              Total: 14 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-01-12 22:12:10 +01:00
parent 7306727d1b
commit 045f4ad92c

View File

@ -31,8 +31,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
const char *opt_u
)
{
static const char *const arg_REPLY[] = { "REPLY", NULL };
unsigned end_ms; /* -t TIMEOUT */
int fd; /* -u FD */
int nchars; /* -n NUM */
@ -94,8 +92,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
fflush_all();
}
if (argv[0] == NULL)
argv = (char**)arg_REPLY;
if (ifs == NULL)
ifs = defifs;
@ -125,7 +121,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
bufpos = 0;
do {
char c;
const char *is_ifs;
if (end_ms) {
int timeout;
@ -163,40 +158,53 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
}
if (c == '\n')
break;
/* $IFS splitting */
/* $IFS splitting. NOT done if we run "read"
* without variable names (bash compat).
* Thus, "read" and "read REPLY" are not the same.
*/
if (argv[0]) {
/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */
is_ifs = strchr(ifs, c);
if (startword && is_ifs) {
if (isspace(c))
const char *is_ifs = strchr(ifs, c);
if (startword && is_ifs) {
if (isspace(c))
continue;
/* it is a non-space ifs char */
startword--;
if (startword == 1) /* first one? */
continue; /* yes, it is not next word yet */
}
startword = 0;
if (argv[1] != NULL && is_ifs) {
buffer[bufpos] = '\0';
bufpos = 0;
setvar(*argv, buffer, 0);
argv++;
/* can we skip one non-space ifs char? (2: yes) */
startword = isspace(c) ? 2 : 1;
continue;
/* it is a non-space ifs char */
startword--;
if (startword == 1) /* first one? */
continue; /* yes, it is not next word yet */
}
startword = 0;
if (argv[1] != NULL && is_ifs) {
buffer[bufpos] = '\0';
bufpos = 0;
setvar(*argv, buffer, 0);
argv++;
/* can we skip one non-space ifs char? (2: yes) */
startword = isspace(c) ? 2 : 1;
continue;
}
}
put:
bufpos++;
} while (--nchars);
/* Remove trailing space ifs chars */
while (--bufpos >= 0 && isspace(buffer[bufpos]) && strchr(ifs, buffer[bufpos]) != NULL)
continue;
buffer[bufpos + 1] = '\0';
if (argv[0]) {
/* Remove trailing space $IFS chars */
while (--bufpos >= 0 && isspace(buffer[bufpos]) && strchr(ifs, buffer[bufpos]) != NULL)
continue;
buffer[bufpos + 1] = '\0';
/* Use the remainder as a value for the next variable */
setvar(*argv, buffer, 0);
/* Set the rest to "" */
while (*++argv)
setvar(*argv, "", 0);
} else {
/* Note: no $IFS removal */
buffer[bufpos] = '\0';
setvar("REPLY", buffer, 0);
}
setvar(*argv, buffer, 0);
while (*++argv != NULL)
setvar(*argv, "", 0);
ret:
free(buffer);
if (read_flags & BUILTIN_READ_SILENT)