view toys/posix/paste.c @ 1189:95ae2805622f draft

Add Szabolcs Nagy's deflate/inflate code from git://git.suckless.org/flate Confirmed with him on IRC it's ok to use under toybox license, glued the files together and hammered square peg into round hole, no other changes yet.
author Rob Landley <rob@landley.net>
date Fri, 31 Jan 2014 06:01:30 -0600
parents b4faf2ae39e8
children
line wrap: on
line source

/* paste.c - Replace newlines
 *
 * Copyright 2012 Felix Janda <felix.janda@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, **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";
  for (p = TT.delim; *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);
    }
    while (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');
      }
    }
  }
}