aboutsummaryrefslogtreecommitdiff
path: root/findutils/grep.c
diff options
context:
space:
mode:
authorMark Whitley <markw@lineo.com>2001-05-24 18:36:18 +0000
committerMark Whitley <markw@lineo.com>2001-05-24 18:36:18 +0000
commitfa43e54b6f662cb33043ff9d1d312558a6e54bc3 (patch)
tree90ca0d16a760c8d71afd5610f90c9d69fe46d507 /findutils/grep.c
parent04052f96e1385405787356f0955afadd73d8f029 (diff)
downloadbusybox-w32-fa43e54b6f662cb33043ff9d1d312558a6e54bc3.tar.gz
busybox-w32-fa43e54b6f662cb33043ff9d1d312558a6e54bc3.tar.bz2
busybox-w32-fa43e54b6f662cb33043ff9d1d312558a6e54bc3.zip
Added support for grep -e and grep -f, closes bug #1164. Also added some
testcases for these new features.
Diffstat (limited to 'findutils/grep.c')
-rw-r--r--findutils/grep.c237
1 files changed, 142 insertions, 95 deletions
diff --git a/findutils/grep.c b/findutils/grep.c
index 07646e02a..fb7df24cf 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -34,13 +34,13 @@ extern int errno; /* for use with strerror() */
34extern void xregcomp(regex_t *preg, const char *regex, int cflags); /* in busybox.h */ 34extern void xregcomp(regex_t *preg, const char *regex, int cflags); /* in busybox.h */
35 35
36/* options */ 36/* options */
37static int ignore_case = 0; 37static int reflags = REG_NOSUB;
38static int print_filename = 0; 38static int print_filename = 0;
39static int print_line_num = 0; 39static int print_line_num = 0;
40static int print_match_counts = 0; 40static int print_match_counts = 0;
41static int be_quiet = 0; 41static int be_quiet = 0;
42static int invert_search = 0; 42static int invert_search = 0;
43static int suppress_err_msgs = 0; 43static int suppress_err_msgs = 0;
44static int print_files_with_matches = 0; 44static int print_files_with_matches = 0;
45 45
46#ifdef BB_FEATURE_GREP_CONTEXT 46#ifdef BB_FEATURE_GREP_CONTEXT
@@ -52,10 +52,12 @@ static int last_line_printed = 0;
52#endif /* BB_FEATURE_GREP_CONTEXT */ 52#endif /* BB_FEATURE_GREP_CONTEXT */
53 53
54/* globals used internally */ 54/* globals used internally */
55static regex_t regex; /* storage space for compiled regular expression */ 55static regex_t *regexes = NULL; /* growable array of compiled regular expressions */
56static int nregexes = 0; /* number of elements in above arrary */
56static int matched; /* keeps track of whether we ever matched */ 57static int matched; /* keeps track of whether we ever matched */
57static char *cur_file = NULL; /* the current file we are reading */ 58static char *cur_file = NULL; /* the current file we are reading */
58 59
60
59static void print_line(const char *line, int linenum, char decoration) 61static void print_line(const char *line, int linenum, char decoration)
60{ 62{
61#ifdef BB_FEATURE_GREP_CONTEXT 63#ifdef BB_FEATURE_GREP_CONTEXT
@@ -73,12 +75,14 @@ static void print_line(const char *line, int linenum, char decoration)
73 puts(line); 75 puts(line);
74} 76}
75 77
78
76static void grep_file(FILE *file) 79static void grep_file(FILE *file)
77{ 80{
78 char *line = NULL; 81 char *line = NULL;
79 int ret; 82 int ret;
80 int linenum = 0; 83 int linenum = 0;
81 int nmatches = 0; 84 int nmatches = 0;
85 int i;
82#ifdef BB_FEATURE_GREP_CONTEXT 86#ifdef BB_FEATURE_GREP_CONTEXT
83 int print_n_lines_after = 0; 87 int print_n_lines_after = 0;
84 int curpos = 0; /* track where we are in the circular 'before' buffer */ 88 int curpos = 0; /* track where we are in the circular 'before' buffer */
@@ -89,81 +93,81 @@ static void grep_file(FILE *file)
89 chomp(line); 93 chomp(line);
90 linenum++; 94 linenum++;
91 95
92 /* 96 for (i = 0; i < nregexes; i++) {
93 * test for a postitive-assertion match (regexec returns success (0) 97 /*
94 * and the user did not specify invert search), or a negative-assertion 98 * test for a postitive-assertion match (regexec returns success (0)
95 * match (regexec returns failure (REG_NOMATCH) and the user specified 99 * and the user did not specify invert search), or a negative-assertion
96 * invert search) 100 * match (regexec returns failure (REG_NOMATCH) and the user specified
97 */ 101 * invert search)
98 ret = regexec(&regex, line, 0, NULL, 0); 102 */
99 if ((ret == 0 && !invert_search) || (ret == REG_NOMATCH && invert_search)) { 103 ret = regexec(&regexes[i], line, 0, NULL, 0);
100 104 if ((ret == 0 && !invert_search) || (ret == REG_NOMATCH && invert_search)) {
101 /* if we found a match but were told to be quiet, stop here and 105
102 * return success */ 106 /* if we found a match but were told to be quiet, stop here and
103 if (be_quiet) { 107 * return success */
104 regfree(&regex); 108 if (be_quiet)
105 exit(0); 109 exit(0);
106 } 110
107 111 /* keep track of matches */
108 /* keep track of matches */ 112 nmatches++;
109 nmatches++; 113
110 114 /* if we're just printing filenames, we stop after the first match */
111 /* if we're just printing filenames, we stop after the first match */ 115 if (print_files_with_matches)
112 if (print_files_with_matches) 116 break;
113 break; 117
114 118 /* print the matched line */
115 /* print the matched line */ 119 if (print_match_counts == 0) {
116 if (print_match_counts == 0) {
117#ifdef BB_FEATURE_GREP_CONTEXT 120#ifdef BB_FEATURE_GREP_CONTEXT
118 int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; 121 int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1;
119 122
120 /* if we were told to print 'before' lines and there is at least 123 /* if we were told to print 'before' lines and there is at least
121 * one line in the circular buffer, print them */ 124 * one line in the circular buffer, print them */
122 if (lines_before && before_buf[prevpos] != NULL) { 125 if (lines_before && before_buf[prevpos] != NULL) {
123 int first_buf_entry_line_num = linenum - lines_before; 126 int first_buf_entry_line_num = linenum - lines_before;
124 127
125 /* advance to the first entry in the circular buffer, and 128 /* advance to the first entry in the circular buffer, and
126 * figure out the line number is of the first line in the 129 * figure out the line number is of the first line in the
127 * buffer */ 130 * buffer */
128 idx = curpos; 131 idx = curpos;
129 while (before_buf[idx] == NULL) { 132 while (before_buf[idx] == NULL) {
130 idx = (idx + 1) % lines_before; 133 idx = (idx + 1) % lines_before;
131 first_buf_entry_line_num++; 134 first_buf_entry_line_num++;
135 }
136
137 /* now print each line in the buffer, clearing them as we go */
138 while (before_buf[idx] != NULL) {
139 print_line(before_buf[idx], first_buf_entry_line_num, '-');
140 free(before_buf[idx]);
141 before_buf[idx] = NULL;
142 idx = (idx + 1) % lines_before;
143 first_buf_entry_line_num++;
144 }
132 } 145 }
133 146
134 /* now print each line in the buffer, clearing them as we go */ 147 /* make a note that we need to print 'after' lines */
135 while (before_buf[idx] != NULL) { 148 print_n_lines_after = lines_after;
136 print_line(before_buf[idx], first_buf_entry_line_num, '-');
137 free(before_buf[idx]);
138 before_buf[idx] = NULL;
139 idx = (idx + 1) % lines_before;
140 first_buf_entry_line_num++;
141 }
142 }
143
144 /* make a note that we need to print 'after' lines */
145 print_n_lines_after = lines_after;
146#endif /* BB_FEATURE_GREP_CONTEXT */ 149#endif /* BB_FEATURE_GREP_CONTEXT */
147 print_line(line, linenum, ':'); 150 print_line(line, linenum, ':');
151 }
148 } 152 }
149 }
150#ifdef BB_FEATURE_GREP_CONTEXT 153#ifdef BB_FEATURE_GREP_CONTEXT
151 else { /* no match */ 154 else { /* no match */
152 /* Add the line to the circular 'before' buffer */ 155 /* Add the line to the circular 'before' buffer */
153 if(lines_before) { 156 if(lines_before) {
154 if(before_buf[curpos]) 157 if(before_buf[curpos])
155 free(before_buf[curpos]); 158 free(before_buf[curpos]);
156 before_buf[curpos] = strdup(line); 159 before_buf[curpos] = strdup(line);
157 curpos = (curpos + 1) % lines_before; 160 curpos = (curpos + 1) % lines_before;
161 }
158 } 162 }
159 }
160 163
161 /* if we need to print some context lines after the last match, do so */ 164 /* if we need to print some context lines after the last match, do so */
162 if (print_n_lines_after && (last_line_printed != linenum)) { 165 if (print_n_lines_after && (last_line_printed != linenum)) {
163 print_line(line, linenum, '-'); 166 print_line(line, linenum, '-');
164 print_n_lines_after--; 167 print_n_lines_after--;
165 } 168 }
166#endif /* BB_FEATURE_GREP_CONTEXT */ 169#endif /* BB_FEATURE_GREP_CONTEXT */
170 } /* for */
167 free(line); 171 free(line);
168 } 172 }
169 173
@@ -189,23 +193,63 @@ static void grep_file(FILE *file)
189 matched = 1; 193 matched = 1;
190} 194}
191 195
196
197static void add_regex(const char *restr)
198{
199 regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes));
200 xregcomp(&regexes[nregexes-1], restr, reflags);
201}
202
203
204static void load_regexes_from_file(const char *filename)
205{
206 char *line;
207 FILE *f = xfopen(filename, "r");
208 while ((line = get_line_from_file(f)) != NULL) {
209 chomp(line);
210 add_regex(line);
211 free(line);
212 }
213}
214
215
216#ifdef BB_FEATURE_CLEAN_UP
217static void destroy_regexes()
218{
219 if (regexes == NULL)
220 return;
221
222 /* destroy all the elments in the array */
223 while (--nregexes >= 0) {
224 regfree(regexes[nregexes]);
225 free(regexes[nregexes]);
226 }
227}
228#endif
229
230
192extern int grep_main(int argc, char **argv) 231extern int grep_main(int argc, char **argv)
193{ 232{
194 int opt; 233 int opt;
195 int reflags;
196#ifdef BB_FEATURE_GREP_CONTEXT 234#ifdef BB_FEATURE_GREP_CONTEXT
197 char *junk; 235 char *junk;
198#endif 236#endif
199 237
238#ifdef BB_FEATURE_CLEAN_UP
239 /* destroy command strings on exit */
240 if (atexit(destroy_regexes) == -1)
241 perror_msg_and_die("atexit");
242#endif
243
200 /* do normal option parsing */ 244 /* do normal option parsing */
201 while ((opt = getopt(argc, argv, "iHhlnqvsc" 245 while ((opt = getopt(argc, argv, "iHhlnqvsce:f:"
202#ifdef BB_FEATURE_GREP_CONTEXT 246#ifdef BB_FEATURE_GREP_CONTEXT
203"A:B:C:" 247"A:B:C:"
204#endif 248#endif
205)) > 0) { 249)) > 0) {
206 switch (opt) { 250 switch (opt) {
207 case 'i': 251 case 'i':
208 ignore_case++; 252 reflags |= REG_ICASE;
209 break; 253 break;
210 case 'l': 254 case 'l':
211 print_files_with_matches++; 255 print_files_with_matches++;
@@ -231,6 +275,12 @@ extern int grep_main(int argc, char **argv)
231 case 'c': 275 case 'c':
232 print_match_counts++; 276 print_match_counts++;
233 break; 277 break;
278 case 'e':
279 add_regex(optarg);
280 break;
281 case 'f':
282 load_regexes_from_file(optarg);
283 break;
234#ifdef BB_FEATURE_GREP_CONTEXT 284#ifdef BB_FEATURE_GREP_CONTEXT
235 case 'A': 285 case 'A':
236 lines_after = strtoul(optarg, &junk, 10); 286 lines_after = strtoul(optarg, &junk, 10);
@@ -255,11 +305,18 @@ extern int grep_main(int argc, char **argv)
255 } 305 }
256 } 306 }
257 307
258 /* argv[optind] should be the regex pattern; no pattern, no worky */ 308 /* if we didn't get a pattern from a -e and no command file was specified,
259 if (argv[optind] == NULL) 309 * argv[optind] should be the pattern. no pattern, no worky */
260 show_usage(); 310 if (nregexes == 0) {
311 if (argv[optind] == NULL)
312 show_usage();
313 else {
314 add_regex(argv[optind]);
315 optind++;
316 }
317 }
261 318
262 /* sanity check */ 319 /* sanity checks */
263 if (print_match_counts || be_quiet || print_files_with_matches) { 320 if (print_match_counts || be_quiet || print_files_with_matches) {
264 print_line_num = 0; 321 print_line_num = 0;
265#ifdef BB_FEATURE_GREP_CONTEXT 322#ifdef BB_FEATURE_GREP_CONTEXT
@@ -268,28 +325,20 @@ extern int grep_main(int argc, char **argv)
268#endif 325#endif
269 } 326 }
270 327
271 /* compile the regular expression 328 /* argv[(optind)..(argc-1)] should be names of file to grep through. If
272 * we're not going to mess with sub-expressions, and we need to
273 * treat newlines right. */
274 reflags = REG_NOSUB;
275 if (ignore_case)
276 reflags |= REG_ICASE;
277 xregcomp(&regex, argv[optind], reflags);
278
279 /* argv[(optind+1)..(argc-1)] should be names of file to grep through. If
280 * there is more than one file to grep, we will print the filenames */ 329 * there is more than one file to grep, we will print the filenames */
281 if ((argc-1) - (optind+1) > 0) 330 if ((argc-1) - (optind) > 0)
282 print_filename++; 331 print_filename++;
283 332
284 /* If no files were specified, or '-' was specified, take input from 333 /* If no files were specified, or '-' was specified, take input from
285 * stdin. Otherwise, we grep through all the files specified. */ 334 * stdin. Otherwise, we grep through all the files specified. */
286 if (argv[optind+1] == NULL || (strcmp(argv[optind+1], "-") == 0)) { 335 if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) {
287 grep_file(stdin); 336 grep_file(stdin);
288 } 337 }
289 else { 338 else {
290 int i; 339 int i;
291 FILE *file; 340 FILE *file;
292 for (i = optind + 1; i < argc; i++) { 341 for (i = optind; i < argc; i++) {
293 cur_file = argv[i]; 342 cur_file = argv[i];
294 file = fopen(cur_file, "r"); 343 file = fopen(cur_file, "r");
295 if (file == NULL) { 344 if (file == NULL) {
@@ -303,7 +352,5 @@ extern int grep_main(int argc, char **argv)
303 } 352 }
304 } 353 }
305 354
306 regfree(&regex);
307
308 return !matched; /* invert return value 0 = success, 1 = failed */ 355 return !matched; /* invert return value 0 = success, 1 = failed */
309} 356}