commit c25996924b60288533f05a8223842c9272211476
Author:     FRIGN <[email protected]>
AuthorDate: Wed Mar 9 15:56:59 2016 +0100
Commit:     sin <[email protected]>
CommitDate: Thu Mar 10 08:48:09 2016 +0000

    Support NUL containing lines in join(1)
    
    while also simplyfing the line-field-parser.

diff --git a/README b/README
index 55b4918..46f1f96 100644
--- a/README
+++ b/README
@@ -43,7 +43,7 @@ The following tools are implemented:
 0=*|o head            .
 0=*|x hostname        .
 0=*|x install         .
- =* o join            .
+0=* o join            .
 0=*|o kill            .
 0=*|o link            .
 0=*|o ln              .
diff --git a/join.c b/join.c
index 93d4b38..d3e2343 100644
--- a/join.c
+++ b/join.c
@@ -27,7 +27,7 @@ struct field {
 };
 
 struct jline {
-       char *text;
+       struct line text;
        size_t nf;
        size_t maxf;
        struct field *fields;
@@ -144,18 +144,14 @@ prjoin(struct jline *la, struct jline *lb, size_t jfa, 
size_t jfb)
                        }
                }
        }
-
        putchar('\n');
 }
 
 static void
 prline(struct jline *lp)
 {
-       size_t len = strlen(lp->text);
-
-       if (fwrite(lp->text, 1, len, stdout) != len)
+       if (fwrite(lp->text.data, 1, lp->text.len, stdout) != lp->text.len)
                eprintf("fwrite:");
-
        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 */
        if (jfa >= la->nf) {
-               status = jfb >= lb->nf ? FIELD_ERROR : -1;
+               status = (jfb >= lb->nf) ? FIELD_ERROR : -1;
        } else if (jfb >= lb->nf) {
                status = 1;
        } else {
                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);
        }
 
@@ -205,53 +201,43 @@ static struct jline *
 makeline(char *s, size_t len)
 {
        struct jline *lp;
-       char *sp, *beg, *end;
-       size_t i;
-       int eol = 0;
+       char *tmp;
+       size_t i, end;
 
-       if (s[len-1] == '\n')
-               s[len-1] = '\0';
+       if (s[len - 1] == '\n')
+               s[--len] = '\0';
 
        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->nf = 0;
        lp->maxf = INIT;
 
-       for (sp = lp->text; isblank(*sp); sp++)
+       for (i = 0; i < lp->text.len && isblank(lp->text.data[i]); i++)
                ;
-
-       while (!eol) {
-               beg = sp;
-
+       while (i < lp->text.len) {
                if (sep) {
-                       if (!(end = utfutf(sp, sep)))
-                               eol = 1;
-
-                       if (!eol) {
-                               addfield(lp, beg, end - beg);
-                               for (i = 0; i < seplen; i++)
-                                       end++;
+                       if ((lp->text.len - i) < seplen ||
+                           !(tmp = memmem(lp->text.data + i,
+                                          lp->text.len - i, sep, seplen))) {
+                               goto eol;
                        }
+                       end = tmp - lp->text.data;
+                       addfield(lp, lp->text.data + i, end - i);
+                       i = end + seplen;
                } else {
-                       for (end = sp; !(isblank(*end)); end++) {
-                               if (*end == '\0') {
-                                       eol = 1;
-                                       break;
-                               }
+                       for (end = i; !(isblank(lp->text.data[end])); end++) {
+                               if (end + 1 == lp->text.len)
+                                       goto eol;
                        }
-
-                       if (!eol)
-                               addfield(lp, beg, end - beg);
-                       while (isblank(*++end))
+                       addfield(lp, lp->text.data + i, end - i);
+                       for (i = end; isblank(lp->text.data[i]); i++)
                                ;
                }
-
-               if (eol)
-                       addfield(lp, beg, strlen(sp));
-
-               sp = end;
        }
+eol:
+       addfield(lp, lp->text.data + i, lp->text.len - i);
 
        return lp;
 }
@@ -260,9 +246,10 @@ static int
 addtospan(struct span *sp, FILE *fp, int reset)
 {
        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))
                        eprintf("getline:");
                else
@@ -298,9 +285,8 @@ freespan(struct span *sp)
 
        for (i = 0; i < sp->nl; i++) {
                free(sp->lines[i]->fields);
-               free(sp->lines[i]->text);
+               free(sp->lines[i]->text.data);
        }
-
        free(sp->lines);
 }
 

Reply via email to