diff options
Diffstat (limited to 'src/commands/grep.c')
-rw-r--r-- | src/commands/grep.c | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/src/commands/grep.c b/src/commands/grep.c deleted file mode 100644 index 4062734..0000000 --- a/src/commands/grep.c +++ /dev/null @@ -1,265 +0,0 @@ -#include "../command.h" -#include <stdio.h> - -static struct { - bool filename_prefix; - bool never_file_prefix; - bool line_number; - bool only_matching_names; - bool only_non_matching_names; - bool only_line_count; - bool only_matching_part; - bool quiet; - bool inverse; - bool ignore_case; - bool is_regex; -} flags; - -static int short_arg(char c, char* next) { - UNUSED(next); - switch (c) { - case 'H': - flags.filename_prefix = true; - break; - case 'h': - flags.never_file_prefix = true; - break; - case 'n': - flags.line_number = true; - break; - case 'l': - flags.only_matching_names = true; - break; - case 'L': - flags.only_non_matching_names = true; - break; - case 'c': - flags.only_line_count = true; - break; - case 'o': - flags.only_matching_part = true; - break; - case 'q': - flags.quiet = true; - break; - case 'v': - flags.inverse = true; - break; - case 'i': - flags.ignore_case = true; - break; - case 'F': - flags.is_regex = false; - break; - case 'E': - flags.is_regex = true; - break; - default: - return ARG_INVALID; - } - return ARG_UNUSED; -} - -static void help(void) { - printf("Usage: grep [-HhlLoqviFE] [-m N] PATTERN [FILE]...\n"); - printf("Search for PATTERN in FILEs (or stdin)\n"); - printf("\t-H\tAdd 'filename:' prefix\n"); - printf("\t-h\tDo not add 'filename:' prefix\n"); - printf("\t-n\tAdd 'line_no:' prefix\n"); - printf("\t-l\tShow only names of files that match\n"); - printf("\t-L\tShow only names of files that don't match\n"); - printf("\t-c\tShow only count of matching lines\n"); - printf("\t-o\tShow only the matching part of line\n"); - printf("\t-q\tQuiet. Return 0 if PATTERN is found, 1 otherwise\n"); - printf("\t-v\tSelect non-matching lines\n"); - printf("\t-i\tIgnore case\n"); - printf("\t-F\tPATTERN is a literal (not regexp)\n"); - printf("\t-E\tPATTERN is an extended regexp\n"); -} - -static bool match_regex(char** string, re_t pattern) { - int len; - int index; - if ((index = re_matchp(pattern, *string, &len)) < 0) return false; - if (flags.only_matching_part) { - (*string) += index; - (*string)[len] = '\0'; - } - return true; -} - -static bool match_literal(char** string, char* pattern) { - char* match = *string; - size_t match_len = strlen(match); - size_t pattern_len = strlen(pattern); - size_t i; - - if (match_len < pattern_len) return false; - - for (i = 0; i < match_len - pattern_len + 1; i++) { - if ( - (!flags.ignore_case && strncmp(match + i, pattern, pattern_len) == 0) || - (flags.ignore_case && strncasecmp(match + i, pattern, pattern_len) == 0) - ) { - if (flags.only_matching_part) { - *string = (*string) + i; - (*string)[pattern_len] = '\0'; - } - return true; - } - } - - return false; -} - -static bool match(char** string, void* pattern) { - bool result; - if (flags.is_regex) { - result = match_regex(string, (re_t) pattern); - } else { - result = match_literal(string, (char*) pattern); - } - return (flags.inverse ? !result : result); -} - -static bool match_any(char* path, void* pattern) { - FILE* file; - char* buf = NULL; - size_t offset; - bool matched = false; - int read; - - file = get_file_s(path, "r"); - if (file == NULL) return false; - - while ((read = getline(&buf, &offset, file)) > 0) { - char* save = buf; - if (buf[read-1] == '\n') buf[read-1] = '\0'; - if (match(&save, pattern)) { - matched = true; - break; - } - } - - if (buf != NULL) free(buf); - - return matched; -} - -static bool match_file(char* path, void* pattern, bool many) { - FILE* file; - char* buf = NULL; - size_t offset; - int num_matched = 0; - int line_num = 0; - int read; - - file = get_file_s(path, "r"); - if (file == NULL) return false; - - while((read = getline(&buf, &offset, file)) > 0) { - char* matched = buf; - - if (buf[read-1] == '\n') buf[read-1] = '\0'; - line_num++; - - if (!match(&matched, pattern)) { - continue; - } - - num_matched++; - - if (flags.only_line_count || flags.quiet) continue; - - if ((many || flags.filename_prefix) && !flags.never_file_prefix) { - print_file_path(path); - putchar(':'); - } - - if (flags.line_number) { - printf("%d:", line_num); - } - - if (flags.only_matching_part) { - printf("%s\n", matched); - } else { - printf("%s\n", buf); - } - } - - if (!flags.quiet && flags.only_line_count) { - if ((many || flags.filename_prefix) && !flags.never_file_prefix) { - print_file_path(path); - putchar(':'); - } - printf("%d\n", num_matched); - } - - if (buf != NULL) free(buf); - - return num_matched != 0; -} - -static void* compile(char* pattern) { - if (flags.is_regex) { - return re_compile(pattern); - } else { - return pattern; - } -} - -static bool run_match(char* path, void* pattern, bool many) { - bool result; - if (flags.only_matching_names || flags.only_non_matching_names) { - result = match_any(path, pattern); - if (flags.only_non_matching_names) result = !result; - if (result && !flags.quiet) { - print_file_path(path); - putchar('\n'); - } - return result; - } else { - return match_file(path, pattern, many); - } -} - -COMMAND(grep) { - - int start, i; - char* pattern; - bool many, ok; - void* compiled; - - flags.only_matching_part = false; - flags.only_non_matching_names = false; - flags.only_matching_names = false; - flags.only_line_count = false; - flags.quiet = false; - flags.is_regex = true; - flags.line_number = false; - flags.never_file_prefix = false; - flags.filename_prefix = false; - flags.inverse = false; - - start = parse_args(argc, argv, help, short_arg, NULL); - - if (argc - start < 1) global_help(help); - - pattern = argv[start++]; - - many = argc - start > 0; - ok = false; - - compiled = compile(pattern); - if (run_match("-", compiled, many)) ok = true; - - for (i = start; i < argc; i++) { - if (run_match(argv[i], compiled, many)) ok = true; - } - - if (flags.quiet) { - return ok ? EXIT_SUCCESS : EXIT_FAILURE; - } else { - return EXIT_SUCCESS; - } -} |