mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
read: add -r to read runes instead of bytes (thanks umbraticus)
This commit is contained in:
parent
1b02c81c18
commit
744475a503
2 changed files with 58 additions and 22 deletions
|
@ -10,12 +10,15 @@ cat, read \- catenate files
|
|||
.B read
|
||||
[
|
||||
.B -m
|
||||
] [
|
||||
|
|
||||
.B -n
|
||||
.I nlines
|
||||
] [
|
||||
|
|
||||
.B -c
|
||||
.I nbytes
|
||||
|
|
||||
.B -r
|
||||
.I nrunes
|
||||
] [
|
||||
.I file ...
|
||||
]
|
||||
|
@ -59,20 +62,14 @@ flag causes it to continue reading and writing multiple lines until end of file;
|
|||
causes it to read no more than
|
||||
.I nlines
|
||||
lines.
|
||||
.PP
|
||||
With the
|
||||
The
|
||||
.B -c
|
||||
flag,
|
||||
.I read
|
||||
copies exactly
|
||||
.I nbytes
|
||||
of characters instead of lines. It is mutually exclusive with
|
||||
.B -n
|
||||
and
|
||||
.B -m
|
||||
flag.
|
||||
.B -r
|
||||
flags specify a number of bytes or runes to read instead of lines.
|
||||
.PP
|
||||
.I Read
|
||||
When reading lines,
|
||||
.I read
|
||||
always executes a single
|
||||
.B write
|
||||
for each line of input, which can be helpful when
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
#include <libc.h>
|
||||
|
||||
int multi;
|
||||
int nlines;
|
||||
vlong nchars;
|
||||
vlong count;
|
||||
char *status = nil;
|
||||
|
||||
int
|
||||
|
@ -50,7 +49,7 @@ lines(int fd, char *file)
|
|||
do{
|
||||
if(line(fd, file) == 0)
|
||||
break;
|
||||
}while(multi || --nlines>0);
|
||||
}while(multi || --count > 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -60,10 +59,10 @@ chars(int fd, char *file)
|
|||
vlong m;
|
||||
int n;
|
||||
|
||||
for(m = 0; m < nchars; m += n){
|
||||
for(m = 0; m < count; m += n){
|
||||
n = sizeof(buf);
|
||||
if(n > (nchars - m))
|
||||
n = nchars - m;
|
||||
if(n > (count - m))
|
||||
n = count - m;
|
||||
if((n = read(fd, buf, n)) < 0){
|
||||
fprint(2, "read: error reading %s: %r\n", file);
|
||||
exits("read error");
|
||||
|
@ -77,10 +76,46 @@ chars(int fd, char *file)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
runes(int fd, char *file)
|
||||
{
|
||||
char buf[8*1024], *s, *e;
|
||||
Rune r;
|
||||
|
||||
while(count > 0){
|
||||
e = buf + read(fd, buf, count + UTFmax < sizeof buf ? count : sizeof buf - UTFmax);
|
||||
if(e < buf){
|
||||
fprint(2, "read: error reading %s: %r\n", file);
|
||||
exits("read error");
|
||||
}
|
||||
if(e == buf)
|
||||
break;
|
||||
for(s = buf; s < e && fullrune(s, e - s); s += chartorune(&r, s))
|
||||
count--;
|
||||
if(s < e){
|
||||
while(!fullrune(s, e - s))
|
||||
switch(read(fd, e, 1)){
|
||||
case -1:
|
||||
fprint(2, "read: error reading %s: %r\n", file);
|
||||
exits("read error");
|
||||
case 0:
|
||||
fprint(2, "warning: partial rune at end of %s: %r\n", file);
|
||||
write(1, buf, e - buf);
|
||||
return;
|
||||
case 1:
|
||||
e++;
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
write(1, buf, e - buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: read [-m] [-n nlines] [-c nbytes] [files...]\n");
|
||||
fprint(2, "usage: read [ -m | -n nlines | -c nbytes | -r nrunes ] [ file ... ]\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
|
@ -93,11 +128,15 @@ main(int argc, char *argv[])
|
|||
proc = lines;
|
||||
ARGBEGIN{
|
||||
case 'c':
|
||||
nchars = atoll(EARGF(usage()));
|
||||
count = atoll(EARGF(usage()));
|
||||
proc = chars;
|
||||
break;
|
||||
case 'r':
|
||||
count = atoll(EARGF(usage()));
|
||||
proc = runes;
|
||||
break;
|
||||
case 'n':
|
||||
nlines = atoi(EARGF(usage()));
|
||||
count = atoi(EARGF(usage()));
|
||||
break;
|
||||
case 'm':
|
||||
multi = 1;
|
||||
|
|
Loading…
Reference in a new issue