18e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda/* paste.c - Replace newlines
28e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda *
38e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda * Copyright 2012 Felix Janda <felix.janda@posteo.de>
48e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda *
58e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/paste.html
68e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda *
78e9ec867e5753e63778d67c3cb1cce68792f7b24Felix JandaUSE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_BIN))
88e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
98e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Jandaconfig PASTE
108e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  bool "paste"
118e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  default y
128e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  help
138e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    usage: paste [-s] [-d list] [file...]
148e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
158e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    Replace newlines in files.
168e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
178e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    -d list    list of delimiters to separate lines
188e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    -s         process files sequentially instead of in parallel
198e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
208e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    By default print corresponding lines separated by <tab>.
218e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda*/
228e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda#define FOR_paste
238e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda#include "toys.h"
248e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
258e9ec867e5753e63778d67c3cb1cce68792f7b24Felix JandaGLOBALS(
268e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  char *delim;
278e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda)
288e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
298e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Jandavoid paste_main(void)
308e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda{
31c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham  char *p, *buf = toybuf, **args = toys.optargs;
328e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  size_t ndelim = 0;
338e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  int i, j, c;
348e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
358e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  // Process delimiter list
368e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  // TODO: Handle multibyte characters
378e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  if (!(toys.optflags & FLAG_d)) TT.delim = "\t";
38c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham  for (p = TT.delim; *p; p++, buf++, ndelim++) {
398e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    if (*p == '\\') {
408e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      p++;
418e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      if (-1 == (i = stridx("nt\\0", *p)))
428e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        error_exit("bad delimiter: \\%c", *p);
438e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      *buf = "\n\t\\\0"[i];
44c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham    } else *buf = *p;
458e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  }
468e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  *buf = 0;
478e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda
488e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  if (toys.optflags & FLAG_s) { // Sequential
498e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    FILE *f;
50c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham
518e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    for (; *args; args++) {
528e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      if ((*args)[0] == '-' && !(*args)[1]) f = stdin;
53d3a435e53c94ec25b4ae5fa2614f49ef8884e08aRob Landley      else if (!(f = fopen(*args, "r"))) perror_exit_raw(*args);
548e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      for (i = 0, c = 0; c != EOF;) {
558e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        switch(c = getc(f)) {
568e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        case '\n':
578e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          putchar(toybuf[i++ % ndelim]);
588e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        case EOF:
598e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          break;
608e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        default:
618e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          putchar(c);
628e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        }
638e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      }
648e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      if (f != stdin) fclose(f);
658e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      putchar('\n');
668e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    }
67c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham  } else { // Parallel
688e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    // Need to be careful not to print an extra line at the end
698e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    FILE **files;
708e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    int anyopen = 1;
71c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham
728e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    files = (FILE**)(buf + 1);
738e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    for (; *args; args++, files++) {
748e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      if ((*args)[0] == '-' && !(*args)[1]) *files = stdin;
75d3a435e53c94ec25b4ae5fa2614f49ef8884e08aRob Landley      else if (!(*files = fopen(*args, "r"))) perror_exit_raw(*args);
768e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    }
77c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham    while (anyopen) {
788e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      anyopen = 0;
798e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      for (i = 0; i < toys.optc; i++) {
808e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        FILE **f = (FILE**)(buf + 1) + i;
81c810f9f80b9db62de09b6cf4c6ca770eed72ce53Isaac Dunham
828e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        if (*f) for (;;) {
838e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          c = getc(*f);
848e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          if (c != EOF) {
858e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda            if (!anyopen++) for (j = 0; j < i; j++) putchar(toybuf[j % ndelim]);
868e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda            if (c != '\n') putchar(c);
878e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda            else break;
888e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          }
898e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          else {
908e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda            if (*f != stdin) fclose(*f);
918e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda            *f = 0;
928e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda            break;
938e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda          }
948e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        }
958e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda        if (anyopen) putchar((i + 1 == toys.optc) ? toybuf[i % ndelim] : '\n');
968e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda      }
978e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda    }
988e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda  }
998e9ec867e5753e63778d67c3cb1cce68792f7b24Felix Janda}
100