toybox/toys/posix/nl.c
<<
>>
Prefs
   1/* nl.c - print line numbers
   2 *
   3 * Copyright 2013 CE Strake <strake888@gmail.com>
   4 *
   5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/nl.html
   6 *
   7 * Deviations from posix: only one logical page (no -ip), no sections (-dfh),
   8 * add -E, support multiple FILE, -n output is long not int.
   9
  10USE_NL(NEWTOY(nl, "v#=1l#w#<0=6b:n:s:E", TOYFLAG_USR|TOYFLAG_BIN))
  11
  12config NL
  13  bool "nl"
  14  default y
  15  help
  16    usage: nl [-E] [-l #] [-b MODE] [-n STYLE] [-s SEPARATOR] [-v #] [-w WIDTH] [FILE...]
  17
  18    Number lines of input.
  19
  20    -E  Use extended regex syntax (when doing -b pREGEX)
  21    -b  Which lines to number: a (all) t (non-empty, default) pREGEX (pattern)
  22    -l  Only count last of this many consecutive blank lines
  23    -n  Number STYLE: ln (left justified) rn (right justified) rz (zero pad)
  24    -s  Separator to use between number and line (instead of TAB)
  25    -v  Starting line number for each section (default 1)
  26    -w  Width of line numbers (default 6)
  27*/
  28
  29#define FOR_nl
  30#include "toys.h"
  31
  32GLOBALS(
  33  char *s, *n, *b;
  34  long w, l, v;
  35
  36  // Count of consecutive blank lines for -l has to persist between files
  37  long lcount, slen;
  38)
  39
  40static void do_nl(char **pline, long len)
  41{
  42  char *line;
  43  int match = *TT.b != 'n';
  44
  45  if (!pline) return;
  46  line = *pline;
  47
  48  if (*TT.b == 'p') match = !regexec((void *)(toybuf+16), line, 0, 0, 0);
  49  if (TT.l || *TT.b == 't')
  50    if (*line == '\n') match = TT.l && ++TT.lcount >= TT.l;
  51  if (match) {
  52    TT.lcount = 0;
  53    printf(toybuf, TT.w, TT.v++, TT.s);
  54  } else printf("%*c", (int)(TT.w+TT.slen), ' ');
  55  xprintf("%s", line);
  56}
  57
  58void nl_main(void)
  59{
  60  char *clip = "";
  61
  62  if (!TT.s) TT.s = "\t";
  63  TT.slen = strlen(TT.s);
  64
  65  if (!TT.n || !strcmp(TT.n, "rn")); // default
  66  else if (!strcmp(TT.n, "ln")) clip = "-";
  67  else if (!strcmp(TT.n, "rz")) clip = "0";
  68  else error_exit("bad -n '%s'", TT.n);
  69
  70  sprintf(toybuf, "%%%s%s", clip, "*ld%s");
  71
  72  if (!TT.b) TT.b = "t";
  73  if (*TT.b=='p' && TT.b[1])
  74    xregcomp((void *)(toybuf+16), TT.b+1, REG_NOSUB|FLAG(E)*REG_EXTENDED);
  75  else if (!TT.b[0] || TT.b[1] || !strchr("atn", *TT.b))
  76    error_exit("bad -b '%s'", TT.b);
  77
  78  loopfiles_lines(toys.optargs, do_nl);
  79}
  80