diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-25 02:38:20 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-25 02:38:20 +0000 |
commit | 385304d449c25948315eb8872879d49bb2c65586 (patch) | |
tree | 8c66a2629e229c4e38fc47660f875d8af4f24a7f | |
parent | 4222ae440a3c73ce5481b7b0e2db0da229fa76aa (diff) | |
download | busybox-w32-385304d449c25948315eb8872879d49bb2c65586.tar.gz busybox-w32-385304d449c25948315eb8872879d49bb2c65586.tar.bz2 busybox-w32-385304d449c25948315eb8872879d49bb2c65586.zip |
grep: implement -w
-rw-r--r-- | findutils/grep.c | 172 |
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) | 32 | enum { |
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 | ||
69 | typedef unsigned char byte_t; | 83 | typedef 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 | |||
115 | static int grep_file(FILE *file) | 128 | static 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, ®match, 0) == 0; | 164 | if (regexec(&(gl->preg), line, 1, ®match, 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 | |||
293 | static int file_action_grep(const char *filename, struct stat *statbuf, void* matched, int depth) | 317 | static 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 | |||
309 | static int grep_dir(const char *dir) | 332 | static 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 | |||
324 | int grep_main(int argc, char **argv); | 346 | int grep_main(int argc, char **argv); |
325 | int grep_main(int argc, char **argv) | 347 | int 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; |