summaryrefslogtreecommitdiff
path: root/grep.c
diff options
context:
space:
mode:
Diffstat (limited to 'grep.c')
-rw-r--r--grep.c362
1 files changed, 198 insertions, 164 deletions
diff --git a/grep.c b/grep.c
index da70d5e..240727d 100644
--- a/grep.c
+++ b/grep.c
@@ -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);
}
-