Support NUL containing lines in join(1)
while also simplyfing the line-field-parser.
This commit is contained in:
parent
d7741c7725
commit
c25996924b
2
README
2
README
@ -43,7 +43,7 @@ The following tools are implemented:
|
|||||||
0=*|o head .
|
0=*|o head .
|
||||||
0=*|x hostname .
|
0=*|x hostname .
|
||||||
0=*|x install .
|
0=*|x install .
|
||||||
=* o join .
|
0=* o join .
|
||||||
0=*|o kill .
|
0=*|o kill .
|
||||||
0=*|o link .
|
0=*|o link .
|
||||||
0=*|o ln .
|
0=*|o ln .
|
||||||
|
74
join.c
74
join.c
@ -27,7 +27,7 @@ struct field {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct jline {
|
struct jline {
|
||||||
char *text;
|
struct line text;
|
||||||
size_t nf;
|
size_t nf;
|
||||||
size_t maxf;
|
size_t maxf;
|
||||||
struct field *fields;
|
struct field *fields;
|
||||||
@ -144,18 +144,14 @@ prjoin(struct jline *la, struct jline *lb, size_t jfa, size_t jfb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prline(struct jline *lp)
|
prline(struct jline *lp)
|
||||||
{
|
{
|
||||||
size_t len = strlen(lp->text);
|
if (fwrite(lp->text.data, 1, lp->text.len, stdout) != lp->text.len)
|
||||||
|
|
||||||
if (fwrite(lp->text, 1, len, stdout) != len)
|
|
||||||
eprintf("fwrite:");
|
eprintf("fwrite:");
|
||||||
|
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,12 +162,12 @@ jlinecmp(struct jline *la, struct jline *lb, size_t jfa, size_t jfb)
|
|||||||
|
|
||||||
/* return FIELD_ERROR if both lines are short */
|
/* return FIELD_ERROR if both lines are short */
|
||||||
if (jfa >= la->nf) {
|
if (jfa >= la->nf) {
|
||||||
status = jfb >= lb->nf ? FIELD_ERROR : -1;
|
status = (jfb >= lb->nf) ? FIELD_ERROR : -1;
|
||||||
} else if (jfb >= lb->nf) {
|
} else if (jfb >= lb->nf) {
|
||||||
status = 1;
|
status = 1;
|
||||||
} else {
|
} else {
|
||||||
status = memcmp(la->fields[jfa].s, lb->fields[jfb].s,
|
status = memcmp(la->fields[jfa].s, lb->fields[jfb].s,
|
||||||
MAX (la->fields[jfa].len, lb->fields[jfb].len));
|
MAX(la->fields[jfa].len, lb->fields[jfb].len));
|
||||||
LIMIT(status, -1, 1);
|
LIMIT(status, -1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,53 +201,43 @@ static struct jline *
|
|||||||
makeline(char *s, size_t len)
|
makeline(char *s, size_t len)
|
||||||
{
|
{
|
||||||
struct jline *lp;
|
struct jline *lp;
|
||||||
char *sp, *beg, *end;
|
char *tmp;
|
||||||
size_t i;
|
size_t i, end;
|
||||||
int eol = 0;
|
|
||||||
|
|
||||||
if (s[len-1] == '\n')
|
if (s[len - 1] == '\n')
|
||||||
s[len-1] = '\0';
|
s[--len] = '\0';
|
||||||
|
|
||||||
lp = ereallocarray(NULL, INIT, sizeof(struct jline));
|
lp = ereallocarray(NULL, INIT, sizeof(struct jline));
|
||||||
lp->text = s;
|
lp->text.data = s;
|
||||||
|
lp->text.len = len;
|
||||||
lp->fields = ereallocarray(NULL, INIT, sizeof(struct field));
|
lp->fields = ereallocarray(NULL, INIT, sizeof(struct field));
|
||||||
lp->nf = 0;
|
lp->nf = 0;
|
||||||
lp->maxf = INIT;
|
lp->maxf = INIT;
|
||||||
|
|
||||||
for (sp = lp->text; isblank(*sp); sp++)
|
for (i = 0; i < lp->text.len && isblank(lp->text.data[i]); i++)
|
||||||
;
|
;
|
||||||
|
while (i < lp->text.len) {
|
||||||
while (!eol) {
|
|
||||||
beg = sp;
|
|
||||||
|
|
||||||
if (sep) {
|
if (sep) {
|
||||||
if (!(end = utfutf(sp, sep)))
|
if ((lp->text.len - i) < seplen ||
|
||||||
eol = 1;
|
!(tmp = memmem(lp->text.data + i,
|
||||||
|
lp->text.len - i, sep, seplen))) {
|
||||||
if (!eol) {
|
goto eol;
|
||||||
addfield(lp, beg, end - beg);
|
|
||||||
for (i = 0; i < seplen; i++)
|
|
||||||
end++;
|
|
||||||
}
|
}
|
||||||
|
end = tmp - lp->text.data;
|
||||||
|
addfield(lp, lp->text.data + i, end - i);
|
||||||
|
i = end + seplen;
|
||||||
} else {
|
} else {
|
||||||
for (end = sp; !(isblank(*end)); end++) {
|
for (end = i; !(isblank(lp->text.data[end])); end++) {
|
||||||
if (*end == '\0') {
|
if (end + 1 == lp->text.len)
|
||||||
eol = 1;
|
goto eol;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
addfield(lp, lp->text.data + i, end - i);
|
||||||
if (!eol)
|
for (i = end; isblank(lp->text.data[i]); i++)
|
||||||
addfield(lp, beg, end - beg);
|
|
||||||
while (isblank(*++end))
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eol)
|
|
||||||
addfield(lp, beg, strlen(sp));
|
|
||||||
|
|
||||||
sp = end;
|
|
||||||
}
|
}
|
||||||
|
eol:
|
||||||
|
addfield(lp, lp->text.data + i, lp->text.len - i);
|
||||||
|
|
||||||
return lp;
|
return lp;
|
||||||
}
|
}
|
||||||
@ -260,9 +246,10 @@ static int
|
|||||||
addtospan(struct span *sp, FILE *fp, int reset)
|
addtospan(struct span *sp, FILE *fp, int reset)
|
||||||
{
|
{
|
||||||
char *newl = NULL;
|
char *newl = NULL;
|
||||||
size_t len, size = 0;
|
ssize_t len;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
if ((len = getline(&newl, &size, fp)) == (size_t)-1) {
|
if ((len = getline(&newl, &size, fp)) < 0) {
|
||||||
if (ferror(fp))
|
if (ferror(fp))
|
||||||
eprintf("getline:");
|
eprintf("getline:");
|
||||||
else
|
else
|
||||||
@ -298,9 +285,8 @@ freespan(struct span *sp)
|
|||||||
|
|
||||||
for (i = 0; i < sp->nl; i++) {
|
for (i = 0; i < sp->nl; i++) {
|
||||||
free(sp->lines[i]->fields);
|
free(sp->lines[i]->fields);
|
||||||
free(sp->lines[i]->text);
|
free(sp->lines[i]->text.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(sp->lines);
|
free(sp->lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user