commit cc3aefa4883a7c208566de6d117819be7c7083ce
Author:     FRIGN <[email protected]>
AuthorDate: Mon Mar 7 12:34:41 2016 +0100
Commit:     sin <[email protected]>
CommitDate: Thu Mar 10 08:48:09 2016 +0000

    Support NUL containing lines in cut(1)

diff --git a/README b/README
index 6c9863b..b2070e7 100644
--- a/README
+++ b/README
@@ -25,7 +25,7 @@ The following tools are implemented:
 0=*|o comm            .
 0=*|o cp              (-i)
 0=*|x cron            .
- #*|o cut             .
+0#*|o cut             .
 0=*|o date            .
 0=*|o dirname         .
 0=*|o du              .
diff --git a/cut.c b/cut.c
index 0258271..a50bdcb 100644
--- a/cut.c
+++ b/cut.c
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "text.h"
 #include "utf.h"
 #include "util.h"
 
@@ -70,71 +71,78 @@ parselist(char *str)
 }
 
 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;
+       size_t n = pos - *prev, i, j;
 
        if (mode == 'b') {
-               if ((t = memchr(s, '\0', n)))
-                       return t - s;
+               if (n >= s->len)
+                       return s->len;
                if (nflag)
-                       while (n && !UTF8_POINT(s[n]))
+                       while (n && !UTF8_POINT(s->data[n]))
                                n--;
                *prev += n;
                return n;
        } else if (mode == 'c') {
-               for (n++, t = s; *t; t++)
-                       if (UTF8_POINT(*t) && !--n)
+               for (n++, i = 0; i < s->len; i++)
+                       if (UTF8_POINT(s->data[i]) && !--n)
                                break;
        } else {
-               for (t = (count < delimlen + 1) ? s : s + delimlen; n && *t; ) {
-                       if (!strncmp(t, delim, delimlen)) {
+               for (i = (count < delimlen + 1) ? 0 : delimlen; n && i < 
s->len; ) {
+                       if ((s->len - i) >= delimlen &&
+                           !memcmp(s->data + i, delim, delimlen)) {
                                if (!--n && count)
                                        break;
-                               t += delimlen;
+                               i += delimlen;
                                continue;
                        }
-                       for (i = 1; !fullrune(t, i); i++);
-                       t += i;
+                       for (j = 1; j + i <= s->len && !fullrune(s->data + i, 
j); j++);
+                       i += j;
                }
        }
        *prev = pos;
 
-       return t - s;
+       return i;
 }
 
 static void
 cut(FILE *fp, const char *fname)
 {
-       static char *buf = NULL;
-       static size_t size = 0;
-       char *s;
+       Range *r;
+       struct line s;
+       static struct line line;
+       static size_t size;
        size_t i, n, p;
        ssize_t len;
-       Range *r;
 
-       while ((len = getline(&buf, &size, fp)) > 0) {
-               if (len && buf[len - 1] == '\n')
-                       buf[len - 1] = '\0';
-               if (mode == 'f' && !utfutf(buf, delim)) {
-                       if (!sflag)
-                               puts(buf);
+       while ((len = getline(&line.data, &size, fp)) > 0) {
+               line.len = len;
+               if (line.data[line.len - 1] == '\n')
+                       line.data[--line.len] = '\0';
+               if (mode == 'f' && !memmem(line.data, line.len, delim, 
delimlen)) {
+                       if (!sflag) {
+                               fwrite(line.data, 1, line.len, stdout);
+                               fputc('\n', stdout);
+                       }
                        continue;
                }
-               for (i = 0, p = 1, s = buf, r = list; r; r = r->next, s += n) {
-                       s += seek(s, r->min, &p, i);
+               for (i = 0, p = 1, s = line, r = list; r; r = r->next) {
+                       n = seek(&s, r->min, &p, i);
+                       s.data += n;
+                       s.len -= n;
                        i += (mode == 'f') ? delimlen : 1;
-                       if (!*s)
+                       if (!s.len)
                                break;
                        if (!r->max) {
-                               fputs(s, stdout);
+                               fwrite(s.data, 1, s.len, stdout);
                                break;
                        }
-                       n = seek(s, r->max + 1, &p, i);
+                       n = seek(&s, r->max + 1, &p, i);
                        i += (mode == 'f') ? delimlen : 1;
-                       if (fwrite(s, 1, n, stdout) != n)
+                       if (fwrite(s.data, 1, n, stdout) != n)
                                eprintf("fwrite <stdout>:");
+                       s.data += n;
+                       s.len -= n;
                }
                putchar('\n');
        }

Reply via email to