aboutsummaryrefslogtreecommitdiff
path: root/toys/pending
diff options
context:
space:
mode:
Diffstat (limited to 'toys/pending')
-rw-r--r--toys/pending/nl.c131
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);
}