summaryrefslogtreecommitdiff
path: root/src/commands/grep.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands/grep.c')
-rw-r--r--src/commands/grep.c265
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;
- }
-}