paste: Support -d '\0'

POSIX specifies that -d '\0' sets the delimiter to an empty string.
This commit is contained in:
Richard Ipsum 2020-04-15 17:46:39 +01:00 committed by Michael Forney
parent 28063c02f4
commit 2f0b15201d
4 changed files with 46 additions and 14 deletions

View File

@ -62,6 +62,19 @@ utfnlen(const char *s, size_t len)
return i; return i;
} }
size_t
utfmemlen(const char *s, size_t len)
{
const char *p = s;
size_t i;
Rune r;
int n;
for(i = 0; (n = charntorune(&r, p, len-(p-s))); i++)
p += n;
return i;
}
char * char *
utfrune(const char *s, Rune r) utfrune(const char *s, Rune r)
{ {

View File

@ -4,10 +4,24 @@
size_t size_t
utftorunestr(const char *str, Rune *r) utftorunestr(const char *str, Rune *r)
{ {
size_t i, n; size_t i;
int n;
for (i = 0; (n = chartorune(&r[i], str)) && r[i]; i++) for (i = 0; (n = chartorune(&r[i], str)) && r[i]; i++)
str += n; str += n;
return i; return i;
} }
size_t
utfntorunestr(const char *str, size_t len, Rune *r)
{
size_t i;
int n;
const char *end = str + len;
for (i = 0; (n = charntorune(&r[i], str, end - str)); i++)
str += n;
return i;
}

27
paste.c
View File

@ -52,8 +52,10 @@ nextline:
c = 0; c = 0;
for (; efgetrune(&c, dsc[i].fp, dsc[i].name) ;) { for (; efgetrune(&c, dsc[i].fp, dsc[i].name) ;) {
for (m = last + 1; m < i; m++) for (m = last + 1; m < i; m++) {
if (delim[m % delimlen] != '\0')
efputrune(&(delim[m % delimlen]), stdout, "<stdout>"); efputrune(&(delim[m % delimlen]), stdout, "<stdout>");
}
last = i; last = i;
if (c == '\n') { if (c == '\n') {
if (i != fdescrlen - 1) if (i != fdescrlen - 1)
@ -67,7 +69,7 @@ nextline:
if (c == 0 && last != -1) { if (c == 0 && last != -1) {
if (i == fdescrlen - 1) if (i == fdescrlen - 1)
putchar('\n'); putchar('\n');
else else if (d != '\0')
efputrune(&d, stdout, "<stdout>"); efputrune(&d, stdout, "<stdout>");
last++; last++;
} }
@ -86,18 +88,18 @@ int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct fdescr *dsc; struct fdescr *dsc;
Rune *delim; Rune *delim_rune = NULL;
size_t delimlen, i; size_t delim_runelen, i, delim_bytelen = 1;
int seq = 0, ret = 0; int seq = 0, ret = 0;
char *adelim = "\t"; char *delim = "\t";
ARGBEGIN { ARGBEGIN {
case 's': case 's':
seq = 1; seq = 1;
break; break;
case 'd': case 'd':
adelim = EARGF(usage()); delim = EARGF(usage());
unescape(adelim); delim_bytelen = unescape(delim);
break; break;
default: default:
usage(); usage();
@ -107,10 +109,11 @@ main(int argc, char *argv[])
usage(); usage();
/* populate delimiters */ /* populate delimiters */
/* TODO: fix libutf to accept sizes */ delim_rune = ereallocarray(NULL,
delim = ereallocarray(NULL, utflen(adelim) + 1, sizeof(*delim)); utfmemlen(delim, delim_bytelen) + 1, sizeof(*delim_rune));
if (!(delimlen = utftorunestr(adelim, delim))) if (!(delim_runelen = utfntorunestr(delim, delim_bytelen, delim_rune))) {
usage(); usage();
}
/* populate file list */ /* populate file list */
dsc = ereallocarray(NULL, argc, sizeof(*dsc)); dsc = ereallocarray(NULL, argc, sizeof(*dsc));
@ -126,9 +129,9 @@ main(int argc, char *argv[])
} }
if (seq) { if (seq) {
sequential(dsc, argc, delim, delimlen); sequential(dsc, argc, delim_rune, delim_runelen);
} else { } else {
parallel(dsc, argc, delim, delimlen); parallel(dsc, argc, delim_rune, delim_runelen);
} }
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)

2
utf.h
View File

@ -38,6 +38,7 @@ int fullrune(const char *, size_t);
char *utfecpy(char *, char *, const char *); char *utfecpy(char *, char *, const char *);
size_t utflen(const char *); size_t utflen(const char *);
size_t utfnlen(const char *, size_t); size_t utfnlen(const char *, size_t);
size_t utfmemlen(const char *, size_t);
char *utfrune(const char *, Rune); char *utfrune(const char *, Rune);
char *utfrrune(const char *, Rune); char *utfrrune(const char *, Rune);
char *utfutf(const char *, const char *); char *utfutf(const char *, const char *);
@ -60,6 +61,7 @@ Rune tolowerrune(Rune);
Rune toupperrune(Rune); Rune toupperrune(Rune);
size_t utftorunestr(const char *, Rune *); size_t utftorunestr(const char *, Rune *);
size_t utfntorunestr(const char *, size_t, Rune *);
int fgetrune(Rune *, FILE *); int fgetrune(Rune *, FILE *);
int efgetrune(Rune *, FILE *, const char *); int efgetrune(Rune *, FILE *, const char *);