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 * This implements a subset: only one logical page (-ip), no sections (-dfh). 8 * todo: -l 9 10USE_NL(NEWTOY(nl, "v#=1l#w#<0=6Eb:n:s:", 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; 38 long slen; 39) 40 41static void do_nl(char **pline, long len) 42{ 43 char *line; 44 int match = *TT.b != 'n'; 45 46 if (!pline) return; 47 line = *pline; 48 49 if (*TT.b == 'p') match = !regexec((void *)(toybuf+16), line, 0, 0, 0); 50 if (TT.l || *TT.b == 't') 51 if (*line == '\n') match = TT.l && ++TT.lcount >= TT.l; 52 if (match) { 53 TT.lcount = 0; 54 printf(toybuf, TT.w, TT.v++, TT.s); 55 } else printf("%*c", (int)(TT.w+TT.slen), ' '); 56 xprintf("%s", line); 57} 58 59void nl_main(void) 60{ 61 char *clip = ""; 62 63 if (!TT.s) TT.s = "\t"; 64 TT.slen = strlen(TT.s); 65 66 if (!TT.n || !strcmp(TT.n, "rn")); // default 67 else if (!strcmp(TT.n, "ln")) clip = "-"; 68 else if (!strcmp(TT.n, "rz")) clip = "0"; 69 else error_exit("bad -n '%s'", TT.n); 70 71 sprintf(toybuf, "%%%s%s", clip, "*ld%s"); 72 73 if (!TT.b) TT.b = "t"; 74 if (*TT.b == 'p' && TT.b[1]) 75 xregcomp((void *)(toybuf+16), TT.b+1, 76 REG_NOSUB | (toys.optflags&FLAG_E)*REG_EXTENDED); 77 else if (!strchr("atn", *TT.b)) error_exit("bad -b '%s'", TT.b); 78 79 loopfiles_lines(toys.optargs, do_nl); 80} 81