Support NUL containing lines in cut(1)
This commit is contained in:
parent
5ad71a466b
commit
cc3aefa488
2
README
2
README
|
@ -25,7 +25,7 @@ The following tools are implemented:
|
||||||
0=*|o comm .
|
0=*|o comm .
|
||||||
0=*|o cp (-i)
|
0=*|o cp (-i)
|
||||||
0=*|x cron .
|
0=*|x cron .
|
||||||
#*|o cut .
|
0#*|o cut .
|
||||||
0=*|o date .
|
0=*|o date .
|
||||||
0=*|o dirname .
|
0=*|o dirname .
|
||||||
0=*|o du .
|
0=*|o du .
|
||||||
|
|
68
cut.c
68
cut.c
|
@ -3,6 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "text.h"
|
||||||
#include "utf.h"
|
#include "utf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -70,71 +71,78 @@ parselist(char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
seek(const char *s, size_t pos, size_t *prev, size_t count)
|
seek(struct line *s, size_t pos, size_t *prev, size_t count)
|
||||||
{
|
{
|
||||||
const char *t;
|
size_t n = pos - *prev, i, j;
|
||||||
size_t n = pos - *prev, i;
|
|
||||||
|
|
||||||
if (mode == 'b') {
|
if (mode == 'b') {
|
||||||
if ((t = memchr(s, '\0', n)))
|
if (n >= s->len)
|
||||||
return t - s;
|
return s->len;
|
||||||
if (nflag)
|
if (nflag)
|
||||||
while (n && !UTF8_POINT(s[n]))
|
while (n && !UTF8_POINT(s->data[n]))
|
||||||
n--;
|
n--;
|
||||||
*prev += n;
|
*prev += n;
|
||||||
return n;
|
return n;
|
||||||
} else if (mode == 'c') {
|
} else if (mode == 'c') {
|
||||||
for (n++, t = s; *t; t++)
|
for (n++, i = 0; i < s->len; i++)
|
||||||
if (UTF8_POINT(*t) && !--n)
|
if (UTF8_POINT(s->data[i]) && !--n)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
for (t = (count < delimlen + 1) ? s : s + delimlen; n && *t; ) {
|
for (i = (count < delimlen + 1) ? 0 : delimlen; n && i < s->len; ) {
|
||||||
if (!strncmp(t, delim, delimlen)) {
|
if ((s->len - i) >= delimlen &&
|
||||||
|
!memcmp(s->data + i, delim, delimlen)) {
|
||||||
if (!--n && count)
|
if (!--n && count)
|
||||||
break;
|
break;
|
||||||
t += delimlen;
|
i += delimlen;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (i = 1; !fullrune(t, i); i++);
|
for (j = 1; j + i <= s->len && !fullrune(s->data + i, j); j++);
|
||||||
t += i;
|
i += j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*prev = pos;
|
*prev = pos;
|
||||||
|
|
||||||
return t - s;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cut(FILE *fp, const char *fname)
|
cut(FILE *fp, const char *fname)
|
||||||
{
|
{
|
||||||
static char *buf = NULL;
|
Range *r;
|
||||||
static size_t size = 0;
|
struct line s;
|
||||||
char *s;
|
static struct line line;
|
||||||
|
static size_t size;
|
||||||
size_t i, n, p;
|
size_t i, n, p;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
Range *r;
|
|
||||||
|
|
||||||
while ((len = getline(&buf, &size, fp)) > 0) {
|
while ((len = getline(&line.data, &size, fp)) > 0) {
|
||||||
if (len && buf[len - 1] == '\n')
|
line.len = len;
|
||||||
buf[len - 1] = '\0';
|
if (line.data[line.len - 1] == '\n')
|
||||||
if (mode == 'f' && !utfutf(buf, delim)) {
|
line.data[--line.len] = '\0';
|
||||||
if (!sflag)
|
if (mode == 'f' && !memmem(line.data, line.len, delim, delimlen)) {
|
||||||
puts(buf);
|
if (!sflag) {
|
||||||
|
fwrite(line.data, 1, line.len, stdout);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (i = 0, p = 1, s = buf, r = list; r; r = r->next, s += n) {
|
for (i = 0, p = 1, s = line, r = list; r; r = r->next) {
|
||||||
s += seek(s, r->min, &p, i);
|
n = seek(&s, r->min, &p, i);
|
||||||
|
s.data += n;
|
||||||
|
s.len -= n;
|
||||||
i += (mode == 'f') ? delimlen : 1;
|
i += (mode == 'f') ? delimlen : 1;
|
||||||
if (!*s)
|
if (!s.len)
|
||||||
break;
|
break;
|
||||||
if (!r->max) {
|
if (!r->max) {
|
||||||
fputs(s, stdout);
|
fwrite(s.data, 1, s.len, stdout);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n = seek(s, r->max + 1, &p, i);
|
n = seek(&s, r->max + 1, &p, i);
|
||||||
i += (mode == 'f') ? delimlen : 1;
|
i += (mode == 'f') ? delimlen : 1;
|
||||||
if (fwrite(s, 1, n, stdout) != n)
|
if (fwrite(s.data, 1, n, stdout) != n)
|
||||||
eprintf("fwrite <stdout>:");
|
eprintf("fwrite <stdout>:");
|
||||||
|
s.data += n;
|
||||||
|
s.len -= n;
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user