#include #include #include #include #include #include #include #include #include #include "util/debug.h" #include "util/error.h" #include "util/loop_args.h" #include "util/versie.h" #include "io/read_file.h" static char *gpats; static bool fixed = false; static bool extended = false; static bool icase = false; static bool binary = false; static bool list = false; static bool invert = false; static bool quiet = false; static size_t npat = 0; static void **patterns = NULL; // can hold `char*` or `regex_t*` static size_t nfiles; static bool anyMatch = false; static void usage(FILE *f) { fprintf(f, "Gebruik: grijp [-hV] [PATRONEN] [BESTAND]...\n" "\n" "TODO\n" "\n" " -h Toon deze hulptekst\n" " -V Toon versienummer\n"); } // Returns pointer to argument array containing patterns and then the file names static char** parse_options(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "FiEUlLvqhV")) != -1) { switch (opt) { case 'F': fixed = true; break; case 'i': icase = true; break; case 'E': extended = true; break; case 'U': binary = true; break; case 'l': list = true; break; case 'L': invert = true; list = true; break; case 'v': invert = true; break; case 'q': quiet = true; break; case 'h': usage(stdout); exit(0); case 'V': drukkedoos_print_versie(stdout); exit(0); case '?': fprintf(stderr, "grijp: Ongeldige optie: -%c\n", optopt); usage(stderr); exit(2); } } return argv + optind; } static void parse_patterns() { size_t cappat = 1 << 4; patterns = calloc(cappat, sizeof(char*)); char *s = gpats; size_t cursor = 0; while (true) { const size_t lfidx = strchrnul(s + cursor, '\n') - s; const bool last = s[lfidx] == '\0'; s[lfidx] = '\0'; if (npat == cappat) { cappat *= 2; patterns = realloc(patterns, sizeof(char*)*cappat); } patterns[npat] = strdup(s + cursor); npat++; cursor = lfidx + 1; if (last) break; } } static void compile_regexps() { for (size_t i = 0; i < npat; i++) { regex_t *regexp = calloc(1, sizeof(regex_t)); int flags = 0; if (extended) flags |= REG_EXTENDED; if (icase) flags |= REG_ICASE; if (regcomp(regexp, patterns[i], flags) != 0) { fprintf(stderr, "grijp: fout tijdens compileren van reguliere expressie\n"); exit(2); } free(patterns[i]); patterns[i] = regexp; } } static void print_match(char *fname, char *line) { if (quiet) return; if (list) { printf("%s\n", fname); return; } if (nfiles >= 2) { printf("%s:", fname); } printf("%s\n", line); } static int process(char *fname, bool isstdin) { FILE *stream = isstdin ? stdin : fopen(fname, binary ? "rb" : "r"); if (stream == NULL && !isstdin) { fprintf(stderr, "grijp: %s: fout tijdens openen bestand\n", fname); return 2; } else if (stream == NULL && isstdin) { fprintf(stderr, "grijp: fout tijdens lezen standaard invoer\n"); return 2; } char *line = NULL; size_t linecap = 0; ssize_t nread = 0; while ((errno = 0, nread = getline(&line, &linecap, stream)) != -1) { if (nread > 0 && line[nread-1] == '\n') line[--nread] = '\0'; for (size_t i = 0; i < npat; i++) { bool matches = false; if (fixed) { char *pat = patterns[i]; matches = (strstr(line, pat) != NULL); } else { regex_t *regexp = patterns[i]; regmatch_t pmatch; matches = (regexec(regexp, line, 1, &pmatch, 0) == 0); } if (invert) matches = !matches; if (matches) { anyMatch = true; print_match(fname, line); if (list) goto done; break; } } } done: free(line); if (!isstdin) fclose(stream); return 0; } int entry_grijp(int argc, char **argv) { char **args = parse_options(argc, argv); if (*args == NULL) { fprintf(stderr, "grijp: geen patroon gegeven\n"); return 2; } gpats = *args; args++; // count the amount of files provided for (nfiles = 0; args[nfiles] != NULL; nfiles++); parse_patterns(); int res = 0; if (fixed) { res = loop_args(args, process); } else { compile_regexps(); res = loop_args(args, process); for (size_t i = 0; i < npat; i++) regfree(patterns[i]); } for (size_t i = 0; i < npat; i++) free(patterns[i]); free(patterns); if (res == 0 && !anyMatch) res = 1; return res; }