diff options
| -rw-r--r-- | toys/pending/nl.c | 131 | 
1 files changed, 62 insertions, 69 deletions
| diff --git a/toys/pending/nl.c b/toys/pending/nl.c index a698c863..2adac246 100644 --- a/toys/pending/nl.c +++ b/toys/pending/nl.c @@ -2,100 +2,93 @@   *   * Copyright 2013 CE Strake <strake888@gmail.com>   * - * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ - * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html + * 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, "Eb:n:s:w#", TOYFLAG_BIN)) +USE_NL(NEWTOY(nl, "v#<1=1l#b:n:s:w#<0=6E", TOYFLAG_BIN))  config NL    bool "nl"    default n    help -    usage: nl [-E] [-b mode] [-n (r|l)(n|z)] [-s separator] [-w width] +    usage: nl [-E] [-l #] [-b MODE] [-n STYLE] [-s SEPARATOR] [-w WIDTH] [FILE...] -    modes: give numbers to -      a:   all lines -      t:   non-empty lines -      n:   no lines -      pRE: lines what match regex RE +    Number lines of input. -    flags: -      E:   extended RE syntax +    -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 <regex.h> +#include "lib/xregcomp.h"  GLOBALS( -  long wArgu; -  char *sArgu, *nArgu, *bArgu, *re_xs; -  char fmt[5]; +  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;  ) -char s = '\t'; -long width = 6; -regex_t re; /* fails in GLOBALS */ - -void do_nl (int fd, char *name) { -  char *x; -  FILE *f; -  long n = 0; - -  f = fdopen (fd, "r"); -  if (!f) perror_exit ("failed to open %s", name); +void do_nl(int fd, char *name) +{ +  FILE *f = xfdopen(fd, "r"); +  int w = TT.w, slen = strlen(TT.s); -  x = 0;    for (;;) { -    size_t l; -    if (getline (&x, &l, f) < 0) { -      if (feof (f)) break; -      perror_exit ("failed to read"); +    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.re_xs && regexec (&re, x, 0, 0, 0) == 0) printf (TT.fmt, width, ++n); -    printf ("%c%s", s, x); + +    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);    } -  free (x); -  fclose (f); +  fclose(f);  } -void nl_main (void) { -  if (toys.optflags & FLAG_w) width = TT.wArgu; - -  if (TT.sArgu) s = TT.sArgu[0]; - -  if (!TT.nArgu) TT.nArgu = "rn"; - -  if (TT.bArgu) switch (TT.bArgu[0]) { -  case 'a': -    TT.re_xs = ""; -    break; -  case 't': -    TT.re_xs = ".\n"; -    break; -  case 'n': -    TT.re_xs = 0; -    break; -  case 'p': -    TT.re_xs = TT.bArgu + 1; -    break; -  default: -    error_exit ("bad mode: %c", TT.bArgu[0]); -  } -  else TT.re_xs = ".\n"; +void nl_main(void) +{ +  char *clip = ""; -  if (TT.re_xs && -      regcomp (&re, TT.re_xs, -               REG_NOSUB | -               (toys.optflags & FLAG_E ? REG_EXTENDED : 0)) != 0) { -    error_exit ("bad RE"); -  } +  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"); -  strcpy (TT.fmt, "%"); -  if (TT.nArgu[0] == 'l') strcat (TT.fmt, "-"); -  if (TT.nArgu[1] == 'z') strcat (TT.fmt, "0"); -  strcat (TT.fmt, "*d"); +  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);  } | 
