view toys/posix/nl.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 b50e00c9df4b
children 63db77909fc8
line wrap: on
line source

/* nl.c - print line numbers
 *
 * Copyright 2013 CE Strake <strake888@gmail.com>
 *
 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/nl.html
 *
 * This implements a subset: only one logical page (-ip), no sections (-dfh).
 * todo: -lv

USE_NL(NEWTOY(nl, "v#<1=1l#b:n:s:w#<0=6E", TOYFLAG_BIN))

config NL
  bool "nl"
  default y
  help
    usage: nl [-E] [-l #] [-b MODE] [-n STYLE] [-s SEPARATOR] [-w WIDTH] [FILE...]

    Number lines of input.

    -E	Use extended regex syntax (when doing -b pREGEX)
    -b	which lines to number: a (all) t (non-empty, default) pREGEX (pattern)
    -l	Only count last of this many consecutive blank lines
    -n	number STYLE: ln (left justified) rn (right justified) rz (zero pad)
    -s	Separator to use between number and line (instead of TAB)
    -w	Width of line numbers (default 6)
*/

#define FOR_nl
#include "toys.h"
#include "lib/xregcomp.h"

GLOBALS(
  long w;
  char *s;
  char *n;
  char *b;
  long l;
  long v;

  // Count of consecutive blank lines for -l has to persist between files
  long lcount;
)

void do_nl(int fd, char *name)
{
  FILE *f = xfdopen(fd, "r");
  int w = TT.w, slen = strlen(TT.s);

  for (;;) {
    char *line = 0;
    size_t temp;
    int match = *TT.b != 'n';

    if (getline(&line, &temp, f) < 1) {
      if (ferror(f)) perror_msg("%s", name);
      break;
    }

    if (*TT.b == 'p') match = !regexec((void *)(toybuf+16), line, 0, 0, 0);
    if (TT.l || *TT.b == 't')
      if (*line == '\n') match = TT.l && ++TT.lcount >= TT.l;
    if (match) {
      TT.lcount = 0;
      printf(toybuf, w, TT.v++, TT.s);
    } else printf("%*c", (int)w+slen, ' ');
    xprintf("%s", line);

    free(line);
  }

  fclose(f);
}

void nl_main(void)
{
  char *clip = "";

  if (!TT.s) TT.s = "\t";

  if (!TT.n || !strcmp(TT.n, "rn")); // default
  else if (!strcmp(TT.n, "ln")) clip = "-";
  else if (!strcmp(TT.n, "rz")) clip = "0";
  else error_exit("bad -n '%s'", TT.n);

  sprintf(toybuf, "%%%s%s", clip, "*ld%s");

  if (!TT.b) TT.b = "t";
  if (*TT.b == 'p' && TT.b[1])
    xregcomp((void *)(toybuf+16), TT.b+1,
      REG_NOSUB | (toys.optflags&FLAG_E)*REG_EXTENDED);
  else if (!strchr("atn", *TT.b)) error_exit("bad -b '%s'", TT.b);

  loopfiles (toys.optargs, do_nl);
}