add read with delimiter, like AT&T ksh93 (thanks Dave for the suggestion)

This commit is contained in:
tg 2011-01-21 22:00:17 +00:00
parent 865b267dbf
commit 846fbde3b8
3 changed files with 56 additions and 17 deletions

26
check.t
View File

@ -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
View File

@ -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
View File

@ -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