add read with delimiter, like AT&T ksh93 (thanks Dave for the suggestion)
This commit is contained in:
parent
865b267dbf
commit
846fbde3b8
26
check.t
26
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.398 2011/01/09 21:57:22 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.399 2011/01/21 22:00:17 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -3411,6 +3411,30 @@ stdin:
|
||||
expected-stdout:
|
||||
[abc]
|
||||
---
|
||||
name: read-delim-1
|
||||
description:
|
||||
Check read with delimiters
|
||||
stdin:
|
||||
emit() {
|
||||
printf 'foo bar\tbaz\nblah \0blub\tblech\nmyok meck \0'
|
||||
}
|
||||
emit | while IFS= read -d "" foo; do print -r -- "<$foo>"; done
|
||||
emit | while read -d "" foo; do print -r -- "<$foo>"; done
|
||||
emit | while read -d "eh?" foo; do print -r -- "<$foo>"; done
|
||||
expected-stdout:
|
||||
<foo bar baz
|
||||
blah >
|
||||
<blub blech
|
||||
myok meck >
|
||||
<foo bar baz
|
||||
blah>
|
||||
<blub blech
|
||||
myok meck>
|
||||
<foo bar baz
|
||||
blah blub bl>
|
||||
<ch
|
||||
myok m>
|
||||
---
|
||||
name: regression-1
|
||||
description:
|
||||
Lex array code had problems with this.
|
||||
|
38
funcs.c
38
funcs.c
@ -26,7 +26,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.165 2011/01/09 21:57:26 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.166 2011/01/21 22:00:15 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -2020,11 +2020,14 @@ c_read(const char **wp)
|
||||
struct shf *shf;
|
||||
XString cs, xs = { NULL, NULL, 0, NULL};
|
||||
struct tbl *vp;
|
||||
char *ccp, *xp = NULL, *wpalloc = NULL;
|
||||
char *ccp, *xp = NULL, *wpalloc = NULL, delim = '\n';
|
||||
static char REPLY[] = "REPLY";
|
||||
|
||||
while ((optc = ksh_getopt(wp, &builtin_opt, "prsu,")) != -1)
|
||||
while ((optc = ksh_getopt(wp, &builtin_opt, "d:prsu,")) != -1)
|
||||
switch (optc) {
|
||||
case 'd':
|
||||
delim = builtin_opt.optarg[0];
|
||||
break;
|
||||
case 'p':
|
||||
if ((fd = coproc_getfd(R_OK, &emsg)) < 0) {
|
||||
bi_errorf("%s: %s", "-p", emsg);
|
||||
@ -2053,7 +2056,8 @@ c_read(const char **wp)
|
||||
if (*wp == NULL)
|
||||
*--wp = REPLY;
|
||||
|
||||
/* Since we can't necessarily seek backwards on non-regular files,
|
||||
/*
|
||||
* Since we can't necessarily seek backwards on non-regular files,
|
||||
* don't buffer them so we can't read too much.
|
||||
*/
|
||||
shf = shf_reopen(fd, SHF_RD | SHF_INTERRUPT | can_seek(fd), shl_spare);
|
||||
@ -2063,16 +2067,18 @@ c_read(const char **wp)
|
||||
wpalloc[cp - *wp] = '\0';
|
||||
*wp = wpalloc;
|
||||
if (isatty(fd)) {
|
||||
/* AT&T ksh says it prints prompt on fd if it's open
|
||||
/*
|
||||
* AT&T ksh says it prints prompt on fd if it's open
|
||||
* for writing and is a tty, but it doesn't do it
|
||||
* (it also doesn't check the interactive flag,
|
||||
* as is indicated in the Kornshell book).
|
||||
* as is indicated in the Korn Shell book).
|
||||
*/
|
||||
shellf("%s", cp+1);
|
||||
shellf("%s", cp + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we are reading from the co-process for the first time,
|
||||
/*
|
||||
* If we are reading from the co-process for the first time,
|
||||
* make sure the other side of the pipe is closed first. This allows
|
||||
* the detection of eof.
|
||||
*
|
||||
@ -2089,10 +2095,10 @@ c_read(const char **wp)
|
||||
Xinit(cs, ccp, 128, ATEMP);
|
||||
for (; *wp != NULL; wp++) {
|
||||
for (ccp = Xstring(cs, ccp); ; ) {
|
||||
if (c == '\n' || c == EOF)
|
||||
break;
|
||||
while (1) {
|
||||
c = shf_getc(shf);
|
||||
if (c == delim)
|
||||
break;
|
||||
if (c == '\0')
|
||||
continue;
|
||||
if (c == EOF && shf_error(shf) &&
|
||||
@ -2121,7 +2127,8 @@ c_read(const char **wp)
|
||||
if (c == '\n') {
|
||||
c = 0;
|
||||
if (Flag(FTALKING_I) && isatty(fd)) {
|
||||
/* set prompt in case this is
|
||||
/*
|
||||
* set prompt in case this is
|
||||
* called from .profile or $ENV
|
||||
*/
|
||||
set_prompt(PS2, NULL);
|
||||
@ -2135,7 +2142,7 @@ c_read(const char **wp)
|
||||
expanding = true;
|
||||
continue;
|
||||
}
|
||||
if (c == '\n' || c == EOF)
|
||||
if (c == delim || c == EOF)
|
||||
break;
|
||||
if (ctype(c, C_IFS)) {
|
||||
if (Xlength(cs, ccp) == 0 && ctype(c, C_IFSWS))
|
||||
@ -2174,9 +2181,10 @@ c_read(const char **wp)
|
||||
histsave(&source->line, Xstring(xs, xp), true, false);
|
||||
Xfree(xs, xp);
|
||||
}
|
||||
/* if this is the co-process fd, close the file descriptor
|
||||
* (can get eof if and only if all processes are have died, ie,
|
||||
* coproc.njobs is 0 and the pipe is closed).
|
||||
/*
|
||||
* if this is the co-process fd, close the file descriptor
|
||||
* (can get eof if and only if all processes are have died,
|
||||
* i.e. coproc.njobs is 0 and the pipe is closed).
|
||||
*/
|
||||
if (c == EOF && !ecode)
|
||||
coproc_read_close(fd);
|
||||
|
9
mksh.1
9
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.245 2011/01/21 21:04:45 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.246 2011/01/21 22:00:14 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
@ -3568,6 +3568,7 @@ directories to the root directory) is printed.
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic read
|
||||
.Op Fl d Ar delimiter
|
||||
.Op Fl prsu Ns Op Ar n
|
||||
.Op Ar parameter ...
|
||||
.Xc
|
||||
@ -3577,6 +3578,12 @@ using the
|
||||
parameter (see
|
||||
.Sx Substitution
|
||||
above), and assigns each field to the specified parameters.
|
||||
Lines are delimited by the first character of
|
||||
.Ar delimiter ,
|
||||
.Dv NUL
|
||||
if empty, if
|
||||
.Fl d
|
||||
was used, a newline otherwise.
|
||||
If there are more parameters than fields, the extra parameters are set to
|
||||
.Dv NULL ,
|
||||
or alternatively, if there are more fields than parameters, the last parameter
|
||||
|
Loading…
x
Reference in New Issue
Block a user