paste: Support -d '\0'
POSIX specifies that -d '\0' sets the delimiter to an empty string.
This commit is contained in:
parent
28063c02f4
commit
2f0b15201d
13
libutf/utf.c
13
libutf/utf.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
27
paste.c
|
@ -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
2
utf.h
|
@ -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 *);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user