aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-02-25 02:38:20 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-02-25 02:38:20 +0000
commit385304d449c25948315eb8872879d49bb2c65586 (patch)
tree8c66a2629e229c4e38fc47660f875d8af4f24a7f
parent4222ae440a3c73ce5481b7b0e2db0da229fa76aa (diff)
downloadbusybox-w32-385304d449c25948315eb8872879d49bb2c65586.tar.gz
busybox-w32-385304d449c25948315eb8872879d49bb2c65586.tar.bz2
busybox-w32-385304d449c25948315eb8872879d49bb2c65586.zip
grep: implement -w
-rw-r--r--findutils/grep.c172
1 files changed, 96 insertions, 76 deletions
diff --git a/findutils/grep.c b/findutils/grep.c
index c1cb7dd0c..702a8a531 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -22,49 +22,63 @@
22#include "busybox.h" 22#include "busybox.h"
23#include "xregex.h" 23#include "xregex.h"
24 24
25
26/* options */ 25/* options */
27#define GREP_OPTS "lnqvscFiHhe:f:Lor" 26#define OPTSTR_GREP \
28#define GREP_OPT_l (1<<0) 27 "lnqvscFiHhe:f:Lor" \
29#define PRINT_FILES_WITH_MATCHES (option_mask32 & GREP_OPT_l) 28 USE_FEATURE_GREP_CONTEXT("A:B:C:") \
30#define GREP_OPT_n (1<<1) 29 USE_FEATURE_GREP_EGREP_ALIAS("E") \
31#define PRINT_LINE_NUM (option_mask32 & GREP_OPT_n) 30 USE_DESKTOP("w") \
32#define GREP_OPT_q (1<<2) 31
33#define BE_QUIET (option_mask32 & GREP_OPT_q) 32enum {
34#define GREP_OPT_v (1<<3) 33 OPTBIT_l,
35#define GREP_OPT_s (1<<4) 34 OPTBIT_n,
36#define SUPPRESS_ERR_MSGS (option_mask32 & GREP_OPT_s) 35 OPTBIT_q,
37#define GREP_OPT_c (1<<5) 36 OPTBIT_v,
38#define PRINT_MATCH_COUNTS (option_mask32 & GREP_OPT_c) 37 OPTBIT_s,
39#define GREP_OPT_F (1<<6) 38 OPTBIT_c,
40#define FGREP_FLAG (option_mask32 & GREP_OPT_F) 39 OPTBIT_F,
41#define GREP_OPT_i (1<<7) 40 OPTBIT_i,
42#define GREP_OPT_H (1<<8) 41 OPTBIT_H,
43#define GREP_OPT_h (1<<9) 42 OPTBIT_h,
44#define GREP_OPT_e (1<<10) 43 OPTBIT_e,
45#define GREP_OPT_f (1<<11) 44 OPTBIT_f,
46#define GREP_OPT_L (1<<12) 45 OPTBIT_L,
47#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & GREP_OPT_L) 46 OPTBIT_o,
48#define GREP_OPT_o (1<<13) 47 OPTBIT_r,
49#define GREP_OPT_r (1<<14) 48 USE_FEATURE_GREP_CONTEXT(OPTBIT_A ,)
50#if ENABLE_FEATURE_GREP_CONTEXT 49 USE_FEATURE_GREP_CONTEXT(OPTBIT_B ,)
51# define GREP_OPT_CONTEXT "A:B:C:" 50 USE_FEATURE_GREP_CONTEXT(OPTBIT_C ,)
52# define GREP_OPT_A (1<<15) 51 USE_FEATURE_GREP_CONTEXT(OPTBIT_E ,)
53# define GREP_OPT_B (1<<16) 52 USE_DESKTOP( OPTBIT_w ,)
54# define GREP_OPT_C (1<<17) 53 OPT_l = 1 << OPTBIT_l,
55# define GREP_OPT_E (1<<18) 54 OPT_n = 1 << OPTBIT_n,
56#else 55 OPT_q = 1 << OPTBIT_q,
57# define GREP_OPT_CONTEXT "" 56 OPT_v = 1 << OPTBIT_v,
58# define GREP_OPT_A 0 57 OPT_s = 1 << OPTBIT_s,
59# define GREP_OPT_B 0 58 OPT_c = 1 << OPTBIT_c,
60# define GREP_OPT_C 0 59 OPT_F = 1 << OPTBIT_F,
61# define GREP_OPT_E (1<<15) 60 OPT_i = 1 << OPTBIT_i,
62#endif 61 OPT_H = 1 << OPTBIT_H,
63#if ENABLE_FEATURE_GREP_EGREP_ALIAS 62 OPT_h = 1 << OPTBIT_h,
64# define OPT_EGREP "E" 63 OPT_e = 1 << OPTBIT_e,
65#else 64 OPT_f = 1 << OPTBIT_f,
66# define OPT_EGREP "" 65 OPT_L = 1 << OPTBIT_L,
67#endif 66 OPT_o = 1 << OPTBIT_o,
67 OPT_r = 1 << OPTBIT_r,
68 OPT_A = USE_FEATURE_GREP_CONTEXT((1 << OPTBIT_A)) + 0,
69 OPT_B = USE_FEATURE_GREP_CONTEXT((1 << OPTBIT_B)) + 0,
70 OPT_C = USE_FEATURE_GREP_CONTEXT((1 << OPTBIT_C)) + 0,
71 OPT_E = USE_FEATURE_GREP_CONTEXT((1 << OPTBIT_E)) + 0,
72 OPT_w = USE_DESKTOP( (1 << OPTBIT_w)) + 0,
73};
74
75#define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l)
76#define PRINT_LINE_NUM (option_mask32 & OPT_n)
77#define BE_QUIET (option_mask32 & OPT_q)
78#define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s)
79#define PRINT_MATCH_COUNTS (option_mask32 & OPT_c)
80#define FGREP_FLAG (option_mask32 & OPT_F)
81#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L)
68 82
69typedef unsigned char byte_t; 83typedef unsigned char byte_t;
70 84
@@ -107,11 +121,10 @@ static void print_line(const char *line, int linenum, char decoration)
107 if (PRINT_LINE_NUM) 121 if (PRINT_LINE_NUM)
108 printf("%i%c", linenum, decoration); 122 printf("%i%c", linenum, decoration);
109 /* Emulate weird GNU grep behavior with -ov */ 123 /* Emulate weird GNU grep behavior with -ov */
110 if ((option_mask32 & (GREP_OPT_v+GREP_OPT_o)) != (GREP_OPT_v+GREP_OPT_o)) 124 if ((option_mask32 & (OPT_v+OPT_o)) != (OPT_v+OPT_o))
111 puts(line); 125 puts(line);
112} 126}
113 127
114
115static int grep_file(FILE *file) 128static int grep_file(FILE *file)
116{ 129{
117 char *line; 130 char *line;
@@ -148,13 +161,25 @@ static int grep_file(FILE *file)
148 } 161 }
149 regmatch.rm_so = 0; 162 regmatch.rm_so = 0;
150 regmatch.rm_eo = 0; 163 regmatch.rm_eo = 0;
151 ret |= regexec(&(gl->preg), line, 1, &regmatch, 0) == 0; 164 if (regexec(&(gl->preg), line, 1, &regmatch, 0) == 0) {
165 if (!(option_mask32 & OPT_w))
166 ret = 1;
167 else {
168 char c = ' ';
169 if (regmatch.rm_so)
170 c = line[regmatch.rm_so - 1];
171 if (!isalnum(c) && c != '_') {
172 c = line[regmatch.rm_eo];
173 if (!c || (!isalnum(c) && c != '_'))
174 ret = 1;
175 }
176 }
177 }
152 } 178 }
153 pattern_ptr = pattern_ptr->link; 179 pattern_ptr = pattern_ptr->link;
154 } /* while (pattern_ptr) */ 180 } /* while (pattern_ptr) */
155 181
156 if (ret ^ invert_search) { 182 if (ret ^ invert_search) {
157
158 if (PRINT_FILES_WITH_MATCHES || BE_QUIET) 183 if (PRINT_FILES_WITH_MATCHES || BE_QUIET)
159 free(line); 184 free(line);
160 185
@@ -201,7 +226,7 @@ static int grep_file(FILE *file)
201 /* make a note that we need to print 'after' lines */ 226 /* make a note that we need to print 'after' lines */
202 print_n_lines_after = lines_after; 227 print_n_lines_after = lines_after;
203#endif 228#endif
204 if (option_mask32 & GREP_OPT_o) { 229 if (option_mask32 & OPT_o) {
205 line[regmatch.rm_eo] = '\0'; 230 line[regmatch.rm_eo] = '\0';
206 print_line(line + regmatch.rm_so, linenum, ':'); 231 print_line(line + regmatch.rm_so, linenum, ':');
207 } else { 232 } else {
@@ -289,7 +314,6 @@ static void load_regexes_from_file(llist_t *fopt)
289 } 314 }
290} 315}
291 316
292
293static int file_action_grep(const char *filename, struct stat *statbuf, void* matched, int depth) 317static int file_action_grep(const char *filename, struct stat *statbuf, void* matched, int depth)
294{ 318{
295 FILE *file = fopen(filename, "r"); 319 FILE *file = fopen(filename, "r");
@@ -305,7 +329,6 @@ static int file_action_grep(const char *filename, struct stat *statbuf, void* ma
305 return 1; 329 return 1;
306} 330}
307 331
308
309static int grep_dir(const char *dir) 332static int grep_dir(const char *dir)
310{ 333{
311 int matched = 0; 334 int matched = 0;
@@ -320,7 +343,6 @@ static int grep_dir(const char *dir)
320 return matched; 343 return matched;
321} 344}
322 345
323
324int grep_main(int argc, char **argv); 346int grep_main(int argc, char **argv);
325int grep_main(int argc, char **argv) 347int grep_main(int argc, char **argv)
326{ 348{
@@ -336,28 +358,28 @@ int grep_main(int argc, char **argv)
336 358
337 opt_complementary = "H-h:e::f::C-AB"; 359 opt_complementary = "H-h:e::f::C-AB";
338 getopt32(argc, argv, 360 getopt32(argc, argv,
339 GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP, 361 OPTSTR_GREP,
340 &pattern_head, &fopt, 362 &pattern_head, &fopt,
341 &slines_after, &slines_before, &Copt); 363 &slines_after, &slines_before, &Copt);
342 364
343 if (option_mask32 & GREP_OPT_C) { 365 if (option_mask32 & OPT_C) {
344 /* -C unsets prev -A and -B, but following -A or -B 366 /* -C unsets prev -A and -B, but following -A or -B
345 may override it */ 367 may override it */
346 if (!(option_mask32 & GREP_OPT_A)) /* not overridden */ 368 if (!(option_mask32 & OPT_A)) /* not overridden */
347 slines_after = Copt; 369 slines_after = Copt;
348 if (!(option_mask32 & GREP_OPT_B)) /* not overridden */ 370 if (!(option_mask32 & OPT_B)) /* not overridden */
349 slines_before = Copt; 371 slines_before = Copt;
350 option_mask32 |= GREP_OPT_A|GREP_OPT_B; /* for parser */ 372 option_mask32 |= OPT_A|OPT_B; /* for parser */
351 } 373 }
352 if (option_mask32 & GREP_OPT_A) { 374 if (option_mask32 & OPT_A) {
353 lines_after = xatoi_u(slines_after); 375 lines_after = xatoi_u(slines_after);
354 } 376 }
355 if (option_mask32 & GREP_OPT_B) { 377 if (option_mask32 & OPT_B) {
356 lines_before = xatoi_u(slines_before); 378 lines_before = xatoi_u(slines_before);
357 } 379 }
358 /* sanity checks */ 380 /* sanity checks */
359 if (option_mask32 & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L)) { 381 if (option_mask32 & (OPT_c|OPT_q|OPT_l|OPT_L)) {
360 option_mask32 &= ~GREP_OPT_n; 382 option_mask32 &= ~OPT_n;
361 lines_before = 0; 383 lines_before = 0;
362 lines_after = 0; 384 lines_after = 0;
363 } else if (lines_before > 0) 385 } else if (lines_before > 0)
@@ -365,10 +387,10 @@ int grep_main(int argc, char **argv)
365#else 387#else
366 /* with auto sanity checks */ 388 /* with auto sanity checks */
367 opt_complementary = "H-h:e::f::c-n:q-n:l-n"; 389 opt_complementary = "H-h:e::f::c-n:q-n:l-n";
368 getopt32(argc, argv, GREP_OPTS OPT_EGREP, 390 getopt32(argc, argv, OPTSTR_GREP,
369 &pattern_head, &fopt); 391 &pattern_head, &fopt);
370#endif 392#endif
371 invert_search = ((option_mask32 & GREP_OPT_v) != 0); /* 0 | 1 */ 393 invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */
372 394
373 if (pattern_head != NULL) { 395 if (pattern_head != NULL) {
374 /* convert char *argv[] to grep_list_data_t */ 396 /* convert char *argv[] to grep_list_data_t */
@@ -377,20 +399,20 @@ int grep_main(int argc, char **argv)
377 for (cur = pattern_head; cur; cur = cur->link) 399 for (cur = pattern_head; cur; cur = cur->link)
378 cur->data = new_grep_list_data(cur->data, 0); 400 cur->data = new_grep_list_data(cur->data, 0);
379 } 401 }
380 if (option_mask32 & GREP_OPT_f) 402 if (option_mask32 & OPT_f)
381 load_regexes_from_file(fopt); 403 load_regexes_from_file(fopt);
382 404
383 if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f') 405 if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f')
384 option_mask32 |= GREP_OPT_F; 406 option_mask32 |= OPT_F;
385 407
386 if (!(option_mask32 & GREP_OPT_o)) 408 if (!(option_mask32 & (OPT_o | OPT_w)))
387 reflags = REG_NOSUB; 409 reflags = REG_NOSUB;
388 410
389 if (ENABLE_FEATURE_GREP_EGREP_ALIAS && 411 if (ENABLE_FEATURE_GREP_EGREP_ALIAS &&
390 (applet_name[0] == 'e' || (option_mask32 & GREP_OPT_E))) 412 (applet_name[0] == 'e' || (option_mask32 & OPT_E)))
391 reflags |= REG_EXTENDED; 413 reflags |= REG_EXTENDED;
392 414
393 if (option_mask32 & GREP_OPT_i) 415 if (option_mask32 & OPT_i)
394 reflags |= REG_ICASE; 416 reflags |= REG_ICASE;
395 417
396 argv += optind; 418 argv += optind;
@@ -399,14 +421,12 @@ int grep_main(int argc, char **argv)
399 /* if we didn't get a pattern from a -e and no command file was specified, 421 /* if we didn't get a pattern from a -e and no command file was specified,
400 * argv[optind] should be the pattern. no pattern, no worky */ 422 * argv[optind] should be the pattern. no pattern, no worky */
401 if (pattern_head == NULL) { 423 if (pattern_head == NULL) {
424 char *pattern;
402 if (*argv == NULL) 425 if (*argv == NULL)
403 bb_show_usage(); 426 bb_show_usage();
404 else { 427 pattern = new_grep_list_data(*argv++, 0);
405 char *pattern = new_grep_list_data(*argv++, 0); 428 llist_add_to(&pattern_head, pattern);
406 429 argc--;
407 llist_add_to(&pattern_head, pattern);
408 argc--;
409 }
410 } 430 }
411 431
412 /* argv[(optind)..(argc-1)] should be names of file to grep through. If 432 /* argv[(optind)..(argc-1)] should be names of file to grep through. If
@@ -414,9 +434,9 @@ int grep_main(int argc, char **argv)
414 if (argc > 1) 434 if (argc > 1)
415 print_filename = 1; 435 print_filename = 1;
416 /* -H / -h of course override */ 436 /* -H / -h of course override */
417 if (option_mask32 & GREP_OPT_H) 437 if (option_mask32 & OPT_H)
418 print_filename = 1; 438 print_filename = 1;
419 if (option_mask32 & GREP_OPT_h) 439 if (option_mask32 & OPT_h)
420 print_filename = 0; 440 print_filename = 0;
421 441
422 /* If no files were specified, or '-' was specified, take input from 442 /* If no files were specified, or '-' was specified, take input from
@@ -430,10 +450,10 @@ int grep_main(int argc, char **argv)
430 if (!cur_file || (*cur_file == '-' && !cur_file[1])) { 450 if (!cur_file || (*cur_file == '-' && !cur_file[1])) {
431 cur_file = "(standard input)"; 451 cur_file = "(standard input)";
432 } else { 452 } else {
433 if (option_mask32 & GREP_OPT_r) { 453 if (option_mask32 & OPT_r) {
434 struct stat st; 454 struct stat st;
435 if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { 455 if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) {
436 if (!(option_mask32 & GREP_OPT_h)) 456 if (!(option_mask32 & OPT_h))
437 print_filename = 1; 457 print_filename = 1;
438 matched += grep_dir(cur_file); 458 matched += grep_dir(cur_file);
439 goto grep_done; 459 goto grep_done;