diff options
Diffstat (limited to 'grep.c')
| -rw-r--r-- | grep.c | 362 |
1 files changed, 198 insertions, 164 deletions
@@ -1,40 +1,43 @@ /* * UNG's Not GNU - * - * Copyright (c) 2011, Jakob Kaivo <jakob@kaivo.net> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * + * Copyright (c) 2011,2022, Jakob Kaivo <jkk@ung.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ +#define _POSIX_C_SOURCE 200809L + +#include <locale.h> #include <limits.h> +#include <regex.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> -#include <regex.h> -// GNU libc unsets ARG_MAX #ifndef ARG_MAX -# define ARG_MAX _POSIX_ARG_MAX +#define ARG_MAX _POSIX_ARG_MAX #endif - -const char *grep_desc = "search a file for a pattern"; -const char *grep_inv = "grep [-E|-F] [-c|-l|-q] [-insvx] -e pattern_list [-e pattern_list]... [-f pattern_file]... [file...]\ngrep [-E|-F] [-c|-l|-q] [-insvx] [-e pattern_list]... -f pattern_file [-f pattern_file]... [file...]\ngrep [-E|-F] [-c|-l|-q] [-insvx] pattern_list [file...]"; - #define BASIC 0 #define EXTENDED 1 #define FIXED 2 @@ -51,151 +54,182 @@ const char *grep_inv = "grep [-E|-F] [-c|-l|-q] [-insvx] -e pattern_list [-e pa #define WHOLELINE 1 << 4 #define FILENAMES 1 << 5 -static int grep (int patterns, char **p, int type, int display, int flags, char *path) +static int grep(int patterns, char **p, int type, int display, int flags, + char *path) { - FILE *f = stdin; - char *buf = NULL; - int line = 0; - size_t nmatch; - size_t len = 0; - size_t nread; - regmatch_t pmatch[1]; - regex_t re; - int i; - int count = 0; - struct stat st; - - stat (path, &st); - if (S_ISDIR(st.st_mode)) - return 0; - - if (strcmp ("-", path)) - f = fopen (path, "r"); - - if (f == NULL) { - if (! (flags & SUPPRESS)) - perror (path); - return 0; - } - - while (!feof (f)) { - if ((nread = getline (&buf, &len, f)) != -1) { - line++; - for (i = 0; i < patterns; i++) { - // FIXME: fixed pattern - if (regcomp (&re, p[i], (type == BASIC ? 0 : REG_EXTENDED) | (flags & IGNORECASE ? REG_ICASE : 0)) != 0) { - printf ("Bad regex: %s\n", p[i]); - exit(2); - } else if (regexec (&re, buf, 1, pmatch, 0) == (flags & INVERT ? REG_NOMATCH : 0)) { - if (!(flags & WHOLELINE) || (flags & WHOLELINE && pmatch[0].rm_so == 0 && pmatch[0].rm_eo == nread - 1)) { - count++; - if (NORMAL == display) { - if (flags & FILENAMES) printf ("%s:", path); - if (flags & LINENUMBERS) printf ("%d:", line); - fwrite (buf, sizeof(char), nread, stdout); - } - } - } - regfree (&re); - } - if (buf != NULL) { free (buf); buf = NULL; } - len = 0; - } - } - - if (strcmp ("-", path)) - fclose (f); - - if (count > 0 && LIST == display) { - if (strcmp ("-", path)) - printf ("%s\n", path); - else - printf ("(standard input)\n"); - } else if (COUNT == display) { - if (flags & FILENAMES) printf ("%s:", path); - printf ("%d\n", count); - } - - return count; + FILE *f = stdin; + char *buf = NULL; + int line = 0; + size_t len = 0; + ssize_t nread = 0; + regmatch_t pmatch[1]; + regex_t re; + int i; + int count = 0; + struct stat st; + + stat(path, &st); + if (S_ISDIR(st.st_mode)) { + return 0; + } + + if (strcmp("-", path)) { + f = fopen(path, "r"); + } + + if (f == NULL) { + if (!(flags & SUPPRESS)) { + perror(path); + } + return 0; + } + + while ((nread = getline(&buf, &len, f)) != -1) { + line++; + for (i = 0; i < patterns; i++) { + // FIXME: fixed pattern + if (regcomp + (&re, p[i], + (type == + BASIC ? 0 : REG_EXTENDED) | (flags & IGNORECASE ? + REG_ICASE : 0)) != + 0) { + printf("Bad regex: %s\n", p[i]); + exit(2); + } else if (regexec(&re, buf, 1, pmatch, 0) == + (flags & INVERT ? REG_NOMATCH : 0)) { + if (!(flags & WHOLELINE) + || (flags & WHOLELINE + && pmatch[0].rm_so == 0 + && pmatch[0].rm_eo == nread - 1)) { + count++; + if (NORMAL == display) { + if (flags & FILENAMES) + printf("%s:", path); + if (flags & LINENUMBERS) + printf("%d:", line); + fwrite(buf, sizeof(char), nread, + stdout); + } + } + } + regfree(&re); + } + if (buf != NULL) { + free(buf); + buf = NULL; + } + len = 0; + } + + if (strcmp("-", path)) { + fclose(f); + } + + if (count > 0 && LIST == display) { + if (strcmp("-", path)) { + printf("%s\n", path); + } else { + printf("(standard input)\n"); + } + } else if (COUNT == display) { + if (flags & FILENAMES) { + printf("%s:", path); + } + printf("%d\n", count); + } + + return count; } -int -main (int argc, char **argv) +int main(int argc, char *argv[]) { - int c; - int n = 10; - int showname = 0; - char *end; - int type = BASIC; - int display = NORMAL; - int flags = 0; - int patterns = 0; - int pfiles = 0; - char *p[ARG_MAX]; - char *pf[ARG_MAX]; - int found = 0; - - while ((c = getopt (argc, argv, ":EFclqinsvxe:f:")) != -1) { - switch (c) { - case 'E': - type = EXTENDED; - break; - case 'F': - type = FIXED; // FIXME - break; - case 'c': - display = COUNT; - break; - case 'e': - p[patterns++] = optarg; - break; - case 'f': - pf[pfiles++] = optarg; - break; - case 'i': - flags |= IGNORECASE; - break; - case 'l': - display = LIST; - break; - case 'n': - flags |= LINENUMBERS; - break; - case 'q': - display = QUIET; - break; - case 's': - flags |= SUPPRESS; - break; - case 'v': - flags |= INVERT; - break; - case 'x': - flags |= WHOLELINE; - break; - default: - fprintf (stderr, "Usage: %s\n", grep_inv); - return 2; - } - } - - if (pfiles > 0) { - // FIXME: read in the files - } - - if (patterns == 0 && optind >= argc) { - return 2; - } else if (patterns == 0) - p[patterns++] = argv[optind++]; - - if (optind >= argc) - found = grep (patterns, p, type, display, flags, "-"); - else { - if (argc - optind > 1) flags |= FILENAMES; - while (optind < argc) - found += grep (patterns, p, type, display, flags, argv[optind++]); - } - - return (found == 0 ? 1 : 0); + setlocale(LC_ALL, ""); + + int c; + int type = BASIC; + int display = NORMAL; + int flags = 0; + int patterns = 0; + int pfiles = 0; + char *p[ARG_MAX]; + int found = 0; + + while ((c = getopt(argc, argv, "EFclqinsvxe:f:")) != -1) { + switch (c) { + case 'E': + type = EXTENDED; + break; + + case 'F': + type = FIXED; // FIXME + break; + + case 'c': + display = COUNT; + break; + + case 'e': + p[patterns++] = optarg; + break; + + case 'f': + //pf[pfiles++] = optarg; + break; + + case 'i': + flags |= IGNORECASE; + break; + + case 'l': + display = LIST; + break; + + case 'n': + flags |= LINENUMBERS; + break; + + case 'q': + display = QUIET; + break; + + case 's': + flags |= SUPPRESS; + break; + + case 'v': + flags |= INVERT; + break; + + case 'x': + flags |= WHOLELINE; + break; + + default: + return 2; + } + } + + if (pfiles > 0) { + // FIXME: read in the files + } + + if (patterns == 0 && optind >= argc) { + return 2; + } else if (patterns == 0) { + p[patterns++] = argv[optind++]; + } + + if (optind >= argc) { + found = grep(patterns, p, type, display, flags, "-"); + } else { + if (argc - optind > 1) + flags |= FILENAMES; + while (optind < argc) + found += + grep(patterns, p, type, display, flags, + argv[optind++]); + } + + return (found == 0 ? 1 : 0); } - |
