Mercurial > hg > toybox
comparison toys/pending/grep.c @ 959:8ad85a95f7c3
grep
author | Strake |
---|---|
date | Tue, 23 Jul 2013 20:19:31 -0500 |
parents | 55e587acefa9 |
children | 55794a3d35c5 |
comparison
equal
deleted
inserted
replaced
958:019f54d50c8b | 959:8ad85a95f7c3 |
---|---|
3 * Copyright 2013 CE Strake <strake888 at gmail.com> | 3 * Copyright 2013 CE Strake <strake888 at gmail.com> |
4 * | 4 * |
5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ | 5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ |
6 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html | 6 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html |
7 | 7 |
8 USE_GREP(NEWTOY(grep, "EFhinovclqe*f*m#", TOYFLAG_BIN)) | 8 USE_GREP(NEWTOY(grep, "EFHahinosvclqe*f*m#", TOYFLAG_BIN)) |
9 | 9 |
10 config GREP | 10 config GREP |
11 bool "grep" | 11 bool "grep" |
12 default n | 12 default n |
13 help | 13 help |
14 usage: grep [-clq] [-EFhinov] (-e RE | -f REfile | RE) [file...] | 14 usage: grep [-clq] [-EFHhinosv] (-e RE | -f REfile | RE) [file...] |
15 | 15 |
16 modes: | 16 modes: |
17 default: print lines from each file what match regular expression RE. | 17 default: print lines from each file what match regular expression RE. |
18 -c: print the number of matching lines in each file. | 18 -c: print the number of matching lines in each file. |
19 -l: print all matching file names. | 19 -l: print all matching file names. |
20 -q: print nil; quit with code 0 when match found. | 20 -q: print nil; quit with code 0 when match found. |
21 | 21 |
22 flags: | 22 flags: |
23 -E: extended RE syntax | 23 -E: extended RE syntax |
24 -F: fixed RE syntax, i.e. all characters literal | 24 -F: fixed RE syntax, i.e. all characters literal |
25 -H: print file name | |
25 -h: not print file name | 26 -h: not print file name |
26 -i: case insensitive | 27 -i: case insensitive |
27 -n: print line numbers | 28 -n: print line numbers |
28 -o: print only matching part | 29 -o: print only matching part |
30 -s: keep silent on error | |
29 -v: invert match | 31 -v: invert match |
30 */ | 32 */ |
31 | 33 |
32 #define FOR_grep | 34 #define FOR_grep |
33 #include "toys.h" | 35 #include "toys.h" |
34 #include <regex.h> | 36 #include <regex.h> |
35 #include <err.h> | |
36 | |
37 /* could be in GLOBALS but so need initialization code */ | |
38 static int c = 1; | |
39 | 37 |
40 static regex_t re; /* fails in GLOBALS */ | 38 static regex_t re; /* fails in GLOBALS */ |
41 | 39 |
42 GLOBALS( | 40 GLOBALS( |
43 long mArgu; | 41 long mArgu; |
44 struct arg_list *fArgu, *eArgu; | 42 struct arg_list *fArgu, *eArgu; |
45 char mode; | 43 char mode, *re_xs; |
46 ) | 44 ) |
47 | 45 |
48 static void do_grep (int fd, char *name) { | 46 static void do_grep (int fd, char *name) { |
49 int n = 0, nMatch = 0; | 47 int n = 0, nMatch = 0; |
50 | 48 |
58 y = x; | 56 y = x; |
59 n++; /* start at 1 */ | 57 n++; /* start at 1 */ |
60 | 58 |
61 while (regexec (&re, y, 1, &match, atBOL ? 0 : REG_NOTBOL) == 0) { | 59 while (regexec (&re, y, 1, &match, atBOL ? 0 : REG_NOTBOL) == 0) { |
62 if (atBOL) nMatch++; | 60 if (atBOL) nMatch++; |
63 c = 0; atBOL = 0; | 61 toys.exitval = 0; |
62 atBOL = 0; | |
64 switch (TT.mode) { | 63 switch (TT.mode) { |
65 case 'q': | 64 case 'q': |
66 exit (0); | 65 xexit (); |
67 case 'l': | 66 case 'l': |
68 if (!(toys.optflags & FLAG_h)) printf ("%s\n", name); | 67 if (!(toys.optflags & FLAG_h)) printf ("%s\n", name); |
69 free (x); | 68 free (x); |
70 return; | 69 return; |
71 case 'c': | 70 case 'c': |
100 } | 99 } |
101 re_ys[jj] = 0; | 100 re_ys[jj] = 0; |
102 return re_ys; | 101 return re_ys; |
103 } | 102 } |
104 | 103 |
104 void addRE (char *x) { | |
105 if (toys.optflags & FLAG_F) x = regfix (x); | |
106 if (TT.re_xs) TT.re_xs = astrcat (TT.re_xs, "|"); | |
107 TT.re_xs = astrcat (TT.re_xs, x); | |
108 if (toys.optflags & FLAG_F) free (x); | |
109 } | |
110 | |
105 void buildRE (void) { | 111 void buildRE (void) { |
106 char *re_xs; | 112 for (; TT.eArgu; TT.eArgu = TT.eArgu -> next) addRE (TT.eArgu -> arg); |
107 | |
108 re_xs = 0; | |
109 for (; TT.eArgu; TT.eArgu = TT.eArgu -> next) { | |
110 if (toys.optflags & FLAG_F) TT.eArgu -> arg = regfix (TT.eArgu -> arg); | |
111 if (re_xs) re_xs = xastrcat (re_xs, "|"); | |
112 re_xs = xastrcat (re_xs, TT.eArgu -> arg); | |
113 } | |
114 for (; TT.fArgu; TT.fArgu = TT.fArgu -> next) { | 113 for (; TT.fArgu; TT.fArgu = TT.fArgu -> next) { |
115 FILE *f; | 114 FILE *f; |
116 char *x, *y; | 115 char *x, *y; |
117 size_t l; | 116 size_t l; |
118 | 117 |
119 f = xfopen (TT.fArgu -> arg, "r"); | 118 f = xfopen (TT.fArgu -> arg, "r"); |
120 x = 0; | 119 x = 0; |
121 for (;;) { | 120 for (;;) { |
122 if (getline (&x, &l, f) < 0) { | 121 if (getline (&x, &l, f) < 0) { |
123 if (feof (f)) break; | 122 if (feof (f)) break; |
124 err (2, "failed to read"); | 123 toys.exitval = 2; |
124 perror_exit ("failed to read"); | |
125 } | 125 } |
126 y = x + strlen (x) - 1; | 126 y = x + strlen (x) - 1; |
127 if (y[0] == '\n') y[0] = 0; | 127 if (y[0] == '\n') y[0] = 0; |
128 | 128 |
129 y = toys.optflags & FLAG_F ? regfix (x) : x; | 129 addRE (x); |
130 if (re_xs) re_xs = xastrcat (re_xs, "|"); | |
131 re_xs = xastrcat (re_xs, y); | |
132 free (y); | |
133 } | 130 } |
134 free (x); | 131 free (x); |
135 fclose (f); | 132 fclose (f); |
136 } | 133 } |
137 | 134 |
138 if (!re_xs) { | 135 if (!TT.re_xs) { |
139 if (toys.optc < 1) errx (2, "no RE"); | 136 if (toys.optc < 1) { |
140 re_xs = toys.optflags & FLAG_F ? regfix (toys.optargs[0]) : toys.optargs[0]; | 137 toys.exitval = 2; |
138 error_exit ("no RE"); | |
139 } | |
140 TT.re_xs = toys.optflags & FLAG_F ? regfix (toys.optargs[0]) : toys.optargs[0]; | |
141 toys.optc--; toys.optargs++; | 141 toys.optc--; toys.optargs++; |
142 } | 142 } |
143 | 143 |
144 if (regcomp (&re, re_xs, | 144 if (regcomp (&re, TT.re_xs, |
145 (toys.optflags & (FLAG_E | FLAG_F) ? REG_EXTENDED : 0) | | 145 (toys.optflags & (FLAG_E | FLAG_F) ? REG_EXTENDED : 0) | |
146 (toys.optflags & FLAG_i ? REG_ICASE : 0)) != 0) { | 146 (toys.optflags & FLAG_i ? REG_ICASE : 0)) != 0) { |
147 errx (2, "bad RE"); | 147 toys.exitval = 2; |
148 error_exit ("bad RE"); | |
148 } | 149 } |
149 } | 150 } |
150 | 151 |
151 void grep_main (void) { | 152 void grep_main (void) { |
152 buildRE (); | 153 buildRE (); |
153 | 154 |
154 if (toys.optflags & FLAG_c) TT.mode = 'c'; | 155 if (toys.optflags & FLAG_c) TT.mode = 'c'; |
155 if (toys.optflags & FLAG_l) TT.mode = 'l'; | 156 if (toys.optflags & FLAG_l) TT.mode = 'l'; |
156 if (toys.optflags & FLAG_q) TT.mode = 'q'; | 157 if (toys.optflags & FLAG_q) TT.mode = 'q'; |
157 | 158 |
158 if (toys.optc > 0) loopfiles (toys.optargs, do_grep); | 159 if (!(toys.optflags & FLAG_H) && (toys.optc < 2)) toys.optflags |= FLAG_h; |
159 else do_grep (0, "-"); | |
160 | 160 |
161 exit (c); | 161 toys.exitval = 1; |
162 loopfiles_rw (toys.optargs, O_RDONLY, 0, toys.optflags & FLAG_s, do_grep); | |
163 xexit (); | |
162 } | 164 } |