X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=findutils%2Fgrep.c;h=a2c07c52371513e07ad41408eb9140f9230edbb3;hb=bf181b9338152759fd56c8009e9a962a84808e7c;hp=52ef6c0fe7a0b5a58c5885127720b648fa2bfd53;hpb=f811e07b072600a3784a92e5a1dc8a93dac477eb;p=oweals%2Fbusybox.git diff --git a/findutils/grep.c b/findutils/grep.c index 52ef6c0fe..a2c07c523 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -1,197 +1,167 @@ /* - * Copyright (c) 1999 by David I. Bell - * Permission is granted to use, distribute, or modify this source, - * provided that this copyright notice remains intact. + * Mini grep implementation for busybox using libc regex. * - * The "grep" command, taken from sash. - * This provides basic file searching. + * Copyright (C) 1999,2000 by Lineo, inc. + * Written by Mark Whitley , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Permission to distribute this code under the GPL has been granted. - * Modified for busybox by Erik Andersen */ -#include "internal.h" -#ifdef BB_GREP - #include -#include +#include +#include +#include +#include /* for strerror() */ #include -#include -#include -#include -#include - - -const char grep_usage[] = - "Search the input file(s) for lines matching the given pattern.\n" - "\tI search stdin if no files are given.\n" - "\tI can't grok full regular expressions.\n" - "usage: grep [in] PATTERN [FILES]...\n" - "\ti=ignore case, n=list line numbers\n"; +#include "internal.h" +extern int optind; /* in unistd.h */ +extern int errno; /* for use with strerror() */ +/* options */ +static int ignore_case = 0; +static int print_filename = 0; +static int print_line_num = 0; +static int be_quiet = 0; +static int invert_search = 0; +static int suppress_err_msgs = 0; -static int search (const char *string, const char *word, int ignoreCase); +/* globals */ +static regex_t regex; /* storage space for compiled regular expression */ +static int nmatches = 0; /* keeps track of the number of matches */ +static char *cur_file = NULL; /* the current file we are reading */ -extern int grep_main (int argc, char **argv) +static void print_matched_line(char *line, int linenum) { - FILE *fp; - const char *word; - const char *name; - const char *cp; - int tellName; - int ignoreCase; - int tellLine; - long line; - char buf[BUF_SIZE]; - - ignoreCase = FALSE; - tellLine = FALSE; - - argc--; - argv++; - if (argc < 1) { - fprintf (stderr, "%s", grep_usage); - return 1; - } - - if (**argv == '-') { - argc--; - cp = *argv++; - - while (*++cp) - switch (*cp) { - case 'i': - ignoreCase = TRUE; - break; - - case 'n': - tellLine = TRUE; - break; - - default: - fprintf (stderr, "Unknown option\n"); - return 1; - } - } - - word = *argv++; - argc--; + if (print_filename) + printf("%s:", cur_file); + if (print_line_num) + printf("%i:", linenum); - tellName = (argc > 1); - - while (argc-- > 0) { - name = *argv++; - - fp = fopen (name, "r"); - - if (fp == NULL) { - perror (name); - - continue; - } + printf("%s", line); +} - line = 0; +static void grep_file(FILE *file) +{ + char *line = NULL; + int ret; + int linenum = 0; - while (fgets (buf, sizeof (buf), fp)) { - line++; + while ((line = get_line_from_file(file)) != NULL) { + linenum++; + ret = regexec(®ex, line, 0, NULL, 0); + if (ret == 0 && !invert_search) { /* match */ - cp = &buf[strlen (buf) - 1]; + /* if we found a match but were told to be quiet, stop here and + * return success */ + if (be_quiet) { + regfree(®ex); + exit(0); + } - if (*cp != '\n') - fprintf (stderr, "%s: Line too long\n", name); + nmatches++; - if (search (buf, word, ignoreCase)) { - if (tellName) - printf ("%s: ", name); + print_matched_line(line, linenum); - if (tellLine) - printf ("%ld: ", line); + } else if (ret == REG_NOMATCH && invert_search) { + print_matched_line(line, linenum); + } - fputs (buf, stdout); - } + free(line); } - - if (ferror (fp)) - perror (name); - - fclose (fp); - } - return 0; } - -/* - * See if the specified word is found in the specified string. - */ -static int search (const char *string, const char *word, int ignoreCase) +extern int grep_main(int argc, char **argv) { - const char *cp1; - const char *cp2; - int len; - int lowFirst; - int ch1; - int ch2; - - len = strlen (word); - - if (!ignoreCase) { - while (TRUE) { - string = strchr (string, word[0]); - - if (string == NULL) - return FALSE; - - if (memcmp (string, word, len) == 0) - return TRUE; - - string++; + int opt; + int reflags; + + /* do special-case option parsing */ + if (argv[1] && (strcmp(argv[1], "--help") == 0)) + usage(grep_usage); + + /* do normal option parsing */ + while ((opt = getopt(argc, argv, "iHhnqvs")) > 0) { + switch (opt) { + case 'i': + ignore_case++; + break; + case 'H': + print_filename++; + break; + case 'h': + print_filename--; + break; + case 'n': + print_line_num++; + break; + case 'q': + be_quiet++; + break; + case 'v': + invert_search++; + break; + case 's': + suppress_err_msgs++; + break; + } } - } - - /* - * Here if we need to check case independence. - * Do the search by lower casing both strings. - */ - lowFirst = *word; - - if (isupper (lowFirst)) - lowFirst = tolower (lowFirst); - while (TRUE) { - while (*string && (*string != lowFirst) && - (!isupper (*string) || (tolower (*string) != lowFirst))) { - string++; + /* argv[optind] should be the regex pattern; no pattern, no worky */ + if (argv[optind] == NULL) + usage(grep_usage); + + /* compile the regular expression + * we're not going to mess with sub-expressions, and we need to + * treat newlines right. */ + reflags = REG_NOSUB | REG_NEWLINE; + if (ignore_case) + reflags |= REG_ICASE; + xregcomp(®ex, argv[optind], reflags); + + /* argv[(optind+1)..(argc-1)] should be names of file to grep through. If + * there is more than one file to grep, we will print the filenames */ + if ((argc-1) - (optind+1) > 0) + print_filename++; + + /* If no files were specified, or '-' was specified, take input from + * stdin. Otherwise, we grep through all the files specified. */ + if (argv[optind+1] == NULL || (strcmp(argv[optind+1], "-") == 0)) { + grep_file(stdin); + } else { + int i; + FILE *file; + for (i = optind + 1; i < argc; i++) { + cur_file = argv[i]; + file = fopen(cur_file, "r"); + if (file == NULL) { + if (!suppress_err_msgs) + errorMsg("%s: %s\n", cur_file, strerror(errno)); + } else { + grep_file(file); + fclose(file); + } + } } - if (*string == '\0') - return FALSE; + regfree(®ex); - cp1 = string; - cp2 = word; - - do { - if (*cp2 == '\0') - return TRUE; - - ch1 = *cp1++; - - if (isupper (ch1)) - ch1 = tolower (ch1); - - ch2 = *cp2++; - - if (isupper (ch2)) - ch2 = tolower (ch2); - - } - while (ch1 == ch2); + if (nmatches == 0) + return 1; - string++; - } - return (TRUE); + return 0; } - -#endif -/* END CODE */