[Toybox] Implement paste

Felix Janda felix.janda at posteo.de
Sat Jun 29 06:17:03 PDT 2013


Hello,

here's a version of paste. It doesn't deal with wide characters yet and
likely behaves very badly when given too many files or delimiters.

--Felix

# HG changeset patch
# User Felix Janda <felix.janda at posteo.de>
# Date 1372511034 -7200
# Node ID a31b59b82edf66fcbb7efe94a1eeede28cee7e70
# Parent  859a93658467653643417e9fffabd3cef6106ef4
Implement paste

diff -r 859a93658467 -r a31b59b82edf toys/posix/paste.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/paste.c	Sat Jun 29 15:03:54 2013 +0200
@@ -0,0 +1,100 @@
+/* paste.c - Replace newlines
+ *
+ * Copyright 2012 Felix Janda <felix.janda at posteo.de>
+ *
+ * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/paste.html 
+ *
+USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_BIN))
+
+config PASTE
+  bool "paste"
+  default y
+  help
+    usage: paste [-s] [-d list] [file...]
+
+    Replace newlines in files.
+
+    -d list    list of delimiters to separate lines
+    -s         process files sequentially instead of in parallel
+
+    By default print corresponding lines separated by <tab>.
+*/
+#define FOR_paste
+#include "toys.h"
+
+GLOBALS(
+  char *delim;
+)
+
+void paste_main(void)
+{
+  char *p, *buf = toybuf;
+  char **args = toys.optargs;
+  size_t ndelim = 0;
+  int i, j, c;
+
+  // Process delimiter list
+  // TODO: Handle multibyte characters
+  if (!(toys.optflags & FLAG_d)) TT.delim = "\t";
+  p = TT.delim;
+  for (; *p; p++, buf++, ndelim++) {
+    if (*p == '\\') {
+      p++;
+      if (-1 == (i = stridx("nt\\0", *p)))
+        error_exit("bad delimiter: \\%c", *p);
+      *buf = "\n\t\\\0"[i];
+    }
+    else *buf = *p;
+  }
+  *buf = 0;
+
+  if (toys.optflags & FLAG_s) { // Sequential
+    FILE *f;
+    for (; *args; args++) {
+      if ((*args)[0] == '-' && !(*args)[1]) f = stdin;
+      else if (!(f = fopen(*args, "r"))) perror_exit("%s", *args);
+      for (i = 0, c = 0; c != EOF;) {
+        switch(c = getc(f)) {
+        case '\n':
+          putchar(toybuf[i++ % ndelim]);
+        case EOF:
+          break;
+        default:
+          putchar(c);
+        }
+      }
+      if (f != stdin) fclose(f);
+      putchar('\n');
+    }
+  }
+  else { // Parallel
+    // Need to be careful not to print an extra line at the end
+    FILE **files;
+    int anyopen = 1;
+    files = (FILE**)(buf + 1);
+    for (; *args; args++, files++) {
+      if ((*args)[0] == '-' && !(*args)[1]) *files = stdin;
+      else if (!(*files = fopen(*args, "r"))) perror_exit("%s", *args);
+    }
+    for (; anyopen;) {
+      anyopen = 0;
+      for (i = 0; i < toys.optc; i++) {
+        FILE **f = (FILE**)(buf + 1) + i;
+        if (*f) for (;;) {
+          c = getc(*f);
+          if (c != EOF) {
+            if (!anyopen++) for (j = 0; j < i; j++) putchar(toybuf[j % ndelim]);
+            if (c != '\n') putchar(c);
+            else break;
+          }
+          else {
+            if (*f != stdin) fclose(*f);
+            *f = 0;
+            break;
+          }
+        }
+        if (anyopen) putchar((i + 1 == toys.optc) ? toybuf[i % ndelim] : '\n');
+      }
+    }
+  }
+}



More information about the Toybox mailing list