remove minix greps.
This commit is contained in:
parent
d78494cd6e
commit
5b40436aaf
7 changed files with 3 additions and 1129 deletions
|
@ -5,14 +5,14 @@
|
||||||
SUBDIR= aal add_route adduser advent arp ash at autil awk \
|
SUBDIR= aal add_route adduser advent arp ash at autil awk \
|
||||||
backup badblocks banner basename bigmake binpackage \
|
backup badblocks banner basename bigmake binpackage \
|
||||||
binpackages binsizes bzip2 bzip2recover cal calendar \
|
binpackages binsizes bzip2 bzip2recover cal calendar \
|
||||||
cat cawf cd cdiff cdprobe cgrep checkhier chmem \
|
cat cawf cd cdiff cdprobe checkhier chmem \
|
||||||
chmod chown chroot ci cksum cleantmp clear cmp co \
|
chmod chown chroot ci cksum cleantmp clear cmp co \
|
||||||
comm compress cp crc cron crontab cut datasizes date \
|
comm compress cp crc cron crontab cut datasizes date \
|
||||||
dd de decomp16 DESCRIBE dev2name devsize df dhcpd \
|
dd de decomp16 DESCRIBE dev2name devsize df dhcpd \
|
||||||
dhrystone diff dirname dis88 du dumpcore easypack \
|
dhrystone diff dirname dis88 du dumpcore easypack \
|
||||||
ed eject elle elvis env expand factor fgrep file \
|
ed eject elle elvis env expand factor file \
|
||||||
find finger fingerd fix fold format fortune fsck \
|
find finger fingerd fix fold format fortune fsck \
|
||||||
fsck1 ftp101 ftpd200 getty gomoku grep head host \
|
fsck1 ftp101 ftpd200 getty gomoku head host \
|
||||||
hostaddr id ifconfig ifdef indent install \
|
hostaddr id ifconfig ifdef indent install \
|
||||||
intr ipcrm ipcs irdpd isoread join kill last leave \
|
intr ipcrm ipcs irdpd isoread join kill last leave \
|
||||||
lex life loadkeys loadramdisk logger login look lp \
|
lex life loadkeys loadramdisk logger login look lp \
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
PROG= cgrep
|
|
||||||
MAN=
|
|
||||||
|
|
||||||
.include <minix.prog.mk>
|
|
|
@ -1,379 +0,0 @@
|
||||||
/* cgrep - grep and display context Author: Mark Mallet */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Nov 19 1984 Mark Mallett (mem@zinn.MV.COM)
|
|
||||||
|
|
||||||
mem 860224 Modified to do r/e (regular expression) parsing on unix
|
|
||||||
mem 860324 Added -f, -n; added code to number lines correctly on output.
|
|
||||||
mem 870325 Added support for regcmp()/regex() style regular expression
|
|
||||||
library; redid some conditionals to provide better mix'n'match.
|
|
||||||
mem 870326 Don't try to print the filename if reading from stdin.
|
|
||||||
Add -w option. Fix a small problem which occasionally allowed
|
|
||||||
the separator to come out between adjacent lines of the file.
|
|
||||||
mem 871119 Fix semantics of call to regcmp(): the NULL terminating the
|
|
||||||
argument list was missing. It worked, but probably only
|
|
||||||
due to some bizarre coincidence.
|
|
||||||
dro 890109 Minor mods to compile under Minix
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define OS_UNIX /* Define this for unix systems */
|
|
||||||
/* #define REGEX *//* Define this for re_comp/re_exec library */
|
|
||||||
#define REGCMP /* Define this to use regcmp/regex */
|
|
||||||
/* #define OS_CPM *//* Define this for CP/M-80 */
|
|
||||||
|
|
||||||
|
|
||||||
/* Don't touch these */
|
|
||||||
#define NOREGEXP /* Set this for no regular expression */
|
|
||||||
#ifdef REGEX
|
|
||||||
#undef NOREGEXP
|
|
||||||
#endif /* REGEX */
|
|
||||||
|
|
||||||
#ifdef REGCMP
|
|
||||||
#undef NOREGEXP
|
|
||||||
#endif /* REGCMP */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef OS_CPM
|
|
||||||
#include "stdio.h"
|
|
||||||
#include "ctype.h"
|
|
||||||
#endif /* OS_CPM */
|
|
||||||
|
|
||||||
#ifdef OS_UNIX
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/dir.h> /* Either here or in sys directory - dro */
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <limits.h> /* should have this - dro */
|
|
||||||
#include <regexp.h> /* should have this - dro */
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif /* OS_UNIX */
|
|
||||||
|
|
||||||
|
|
||||||
/* Local definitions */
|
|
||||||
|
|
||||||
#ifndef NULL
|
|
||||||
#define NULL ((char *)0)
|
|
||||||
#endif /* NULL */
|
|
||||||
|
|
||||||
#ifndef NUL
|
|
||||||
#define NUL '\000'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE 1
|
|
||||||
#define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal data declared global */
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal routines */
|
|
||||||
|
|
||||||
_PROTOTYPE(int main, (int argc, char **argv));
|
|
||||||
_PROTOTYPE(void dosrch, (char *ifnm));
|
|
||||||
_PROTOTYPE(void shwlin, (char *fnm, int linnum, char *line));
|
|
||||||
_PROTOTYPE(int matlin, (char *line));
|
|
||||||
_PROTOTYPE(void regerror, (const char *s));
|
|
||||||
|
|
||||||
/* External data */
|
|
||||||
|
|
||||||
|
|
||||||
/* Local data */
|
|
||||||
|
|
||||||
static int Debug = {FALSE}; /* Debug enabled flag */
|
|
||||||
static int Lcur = {0}; /* Current line (in Lines array) */
|
|
||||||
static char **Lines = {NULL}; /* Lines pointer array */
|
|
||||||
static int Linlen = {100}; /* Line length */
|
|
||||||
static int Lone = {0}; /* Line one (in Lines array) */
|
|
||||||
static int Nmr = {0}; /* Number of matched regions */
|
|
||||||
static char *Pat = {NULL}; /* Pattern */
|
|
||||||
static char Shwfile = {TRUE}; /* Show file name... */
|
|
||||||
static char Shwline = {TRUE}; /* Show line number */
|
|
||||||
static int Waft = {0}; /* Window after */
|
|
||||||
static int Wbef = {0}; /* Window before */
|
|
||||||
static int Wsiz = {0}; /* Window size */
|
|
||||||
|
|
||||||
regexp *Re; /* Result from reg compilation */
|
|
||||||
|
|
||||||
int main(argc, argv)
|
|
||||||
int argc; /* Argument count */
|
|
||||||
char **argv; /* Argument values */
|
|
||||||
|
|
||||||
{
|
|
||||||
int i; /* Scratch */
|
|
||||||
int n; /* Scratch again */
|
|
||||||
int c; /* A character */
|
|
||||||
char *aptr; /* Argument pointer */
|
|
||||||
int nf; /* number of files on command line */
|
|
||||||
|
|
||||||
nf = 0; /* No files on line */
|
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) { /* Look at args */
|
|
||||||
if (argv[i][0] != '-') {/* If option */
|
|
||||||
if (Pat == NULL) { /* If no pattern yet given */
|
|
||||||
Pat = argv[i]; /* point here */
|
|
||||||
#ifdef REGEX
|
|
||||||
if ((Re = re_comp(Pat)) != NULL) {
|
|
||||||
fprintf(stderr, "cgrep: %s\n", re);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#endif /* REGEX */
|
|
||||||
|
|
||||||
#ifdef REGCMP
|
|
||||||
if ((Re = regcomp(Pat)) == NULL) {
|
|
||||||
fprintf(stderr, "cgrep: error in regular expression.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#endif /* REGCMP */
|
|
||||||
|
|
||||||
} else { /* This must be a file to search */
|
|
||||||
nf++; /* Count it */
|
|
||||||
dosrch(argv[i]); /* Search */
|
|
||||||
}
|
|
||||||
} else { /* Option char */
|
|
||||||
c = argv[i][1]; /* Get option char */
|
|
||||||
if (isupper(c)) /* Trap idiot definition of tolower */
|
|
||||||
c = tolower(c); /* Don't care about case */
|
|
||||||
n = i;
|
|
||||||
aptr = NULL; /* Find arg, if any */
|
|
||||||
if (argv[i][2] != NUL) {
|
|
||||||
aptr = &argv[i][2];
|
|
||||||
n = i; /* Where to set i if we use this arg */
|
|
||||||
} else if (i < argc - 1) { /* use next.. */
|
|
||||||
n = i + 1;
|
|
||||||
aptr = argv[n];
|
|
||||||
}
|
|
||||||
switch (c) { /* Process the option */
|
|
||||||
case 'a': /* Lines after */
|
|
||||||
Waft = atoi(aptr);
|
|
||||||
Lines = NULL;
|
|
||||||
i = n;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b': /* Lines before */
|
|
||||||
Wbef = atoi(aptr);
|
|
||||||
Lines = NULL;
|
|
||||||
i = n;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Disable debug output
|
|
||||||
case 'd': Debug = TRUE; break;
|
|
||||||
*/
|
|
||||||
|
|
||||||
case 'f': /* Suppress filename on output */
|
|
||||||
Shwfile = FALSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l': /* Line length */
|
|
||||||
Linlen = atoi(aptr);
|
|
||||||
Lines = NULL;
|
|
||||||
i = n;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n': /* Suppress line number on output */
|
|
||||||
Shwline = FALSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w': /* Window: lines before and after */
|
|
||||||
Waft = Wbef = atoi(aptr);
|
|
||||||
Lines = NULL;
|
|
||||||
i = n;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Invalid option %s\n", argv[i]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Pat == NULL) { /* If no pattern given */
|
|
||||||
fprintf(stderr,
|
|
||||||
"Usage: cgrep [-a n] [-b n] [-f] [-l n] [-n] [-w n] pattern [filename... ]\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (nf == 0) /* No files processed ? */
|
|
||||||
dosrch((char *)NULL); /* Do standard input */
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dosrch (ifnm) Perform the search
|
|
||||||
* Accepts :
|
|
||||||
*
|
|
||||||
* ifn Input file name
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Returns :
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void dosrch(ifnm)
|
|
||||||
char *ifnm; /* Input filelname */
|
|
||||||
|
|
||||||
{
|
|
||||||
FILE *ifp; /* Input fp */
|
|
||||||
char *lptr; /* Line pointer */
|
|
||||||
int i; /* Scratch */
|
|
||||||
int prtaft; /* Print-after count */
|
|
||||||
int linnum; /* Line number */
|
|
||||||
int nlb; /* Number of lines buffered */
|
|
||||||
|
|
||||||
if (ifnm != NULL) { /* If file name given */
|
|
||||||
ifp = fopen(ifnm, "r"); /* Open it for read access */
|
|
||||||
if (ifp == NULL) {
|
|
||||||
fprintf(stderr, "Can not open file %s\n", ifnm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
ifp = stdin;
|
|
||||||
|
|
||||||
if (Lines == NULL) { /* If no line table allocated.. */
|
|
||||||
Wsiz = Wbef + 2; /* Determine total window size */
|
|
||||||
Lines = (char **) calloc((size_t)Wsiz, sizeof(char *));
|
|
||||||
/* Allocate pointer table */
|
|
||||||
for (i = 0; i < Wsiz; i++) /* Allocate line buffers */
|
|
||||||
Lines[i] = (char *) calloc((size_t)Linlen, sizeof(char));
|
|
||||||
}
|
|
||||||
Lcur = Lone = 0; /* Setup line pointers */
|
|
||||||
nlb = 0; /* No lines buffered */
|
|
||||||
linnum = 0; /* Line number is zero */
|
|
||||||
prtaft = -(Wbef + 1); /* Make sure separator given first time */
|
|
||||||
|
|
||||||
for (;;) { /* Loop through the file */
|
|
||||||
lptr = Lines[Lcur]; /* Get pointer to current line */
|
|
||||||
if (++Lcur == Wsiz) /* Bump curr pointer and wrap */
|
|
||||||
Lcur = 0; /* if hit end */
|
|
||||||
if (Lone == Lcur) /* If wrapped to beginning of window */
|
|
||||||
if (++Lone == Wsiz) /* Bump beginning */
|
|
||||||
Lone = 0; /* and wrap if hit end */
|
|
||||||
|
|
||||||
if (fgets(lptr, Linlen, ifp) != lptr) break; /* if end of file */
|
|
||||||
|
|
||||||
linnum++; /* Count line number */
|
|
||||||
if (matlin(lptr)) { /* If matching line */
|
|
||||||
if (prtaft < (-Wbef)) /* Check for separator needed */
|
|
||||||
if ((Nmr++ > 0) && ((Wbef > 0) || (Waft > 0)))
|
|
||||||
printf("----------------------------------------------------------------------------\n");
|
|
||||||
while (Lone != Lcur) { /* Until we close the window */
|
|
||||||
shwlin(ifnm, linnum - nlb, Lines[Lone]);
|
|
||||||
/* Show the line */
|
|
||||||
if (++Lone == Wsiz) Lone = 0;
|
|
||||||
nlb--;
|
|
||||||
}
|
|
||||||
nlb = 0; /* No lines buffered */
|
|
||||||
prtaft = Waft; /* Print n lines after */
|
|
||||||
} else { /* Didn't match */
|
|
||||||
if (prtaft-- > 0) { /* If must print lines after */
|
|
||||||
shwlin(ifnm, linnum, lptr);
|
|
||||||
/* Show the line */
|
|
||||||
Lone = Lcur; /* Match pointers */
|
|
||||||
} else if (nlb < Wbef) /* Count lines buffered */
|
|
||||||
nlb++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifnm != NULL) fclose(ifp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shwlin (fnm, linnum, line) Show a matching line
|
|
||||||
*
|
|
||||||
* Accepts :
|
|
||||||
*
|
|
||||||
* fnm File name
|
|
||||||
*
|
|
||||||
* linnum Line number
|
|
||||||
*
|
|
||||||
* line Line to show
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Returns :
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void shwlin(fnm, linnum, line)
|
|
||||||
char *fnm; /* File name */
|
|
||||||
int linnum; /* Line number */
|
|
||||||
char *line; /* Line (with newline at end) to print */
|
|
||||||
|
|
||||||
{
|
|
||||||
if (Shwfile && (fnm != NULL)) printf("%s%s", fnm, Shwline ? " " : ":");
|
|
||||||
if (Shwline) printf("@%05d:", linnum);
|
|
||||||
printf("%s", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Matlin (line) Perform match against pattern and line
|
|
||||||
*
|
|
||||||
* Accepts :
|
|
||||||
*
|
|
||||||
* line Address of line to match
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Returns :
|
|
||||||
*
|
|
||||||
* <value> TRUE if match FALSE if not
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
int matlin(line)
|
|
||||||
char *line; /* Line to match */
|
|
||||||
|
|
||||||
{
|
|
||||||
int rtncode; /* Return value from this routine */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef NOREGEXP
|
|
||||||
char *pptr, *lptr, *tlptr;
|
|
||||||
int c1, c2;
|
|
||||||
#endif /* NOREGEXP */
|
|
||||||
|
|
||||||
if (Debug) printf("Matching %s against %s", Pat, line);
|
|
||||||
|
|
||||||
#ifdef REGEX
|
|
||||||
rtncode = re_exec(line); /* Hand off to r/e evaluator */
|
|
||||||
#endif /* REGEX */
|
|
||||||
|
|
||||||
#ifdef REGCMP
|
|
||||||
rtncode = (regexec(Re, line, TRUE) != 0);
|
|
||||||
#endif /* REGCMP */
|
|
||||||
|
|
||||||
#ifdef NOREGEX /* Have to do menial comparison.. */
|
|
||||||
lptr = line; /* Init line pointer */
|
|
||||||
|
|
||||||
for (rtncode = -1; rtncode < 0;) {
|
|
||||||
tlptr = lptr++; /* Get temp ptr to line */
|
|
||||||
pptr = Pat; /* Get ptr to pattern */
|
|
||||||
while (TRUE) {
|
|
||||||
if ((c1 = *pptr++) == NUL) {
|
|
||||||
rtncode = 1; /* GOOD return value */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((c2 = *tlptr++) == NUL) {
|
|
||||||
rtncode = 0; /* BAD return value */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (isupper(c1)) c1 = tolower(c1);
|
|
||||||
if (isupper(c2)) c2 = tolower(c2);
|
|
||||||
if (c1 != c2) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* NOREGEX */
|
|
||||||
|
|
||||||
|
|
||||||
if (Debug) printf("matlin returned %s\n", rtncode ? "TRUE" : "FALSE");
|
|
||||||
return(rtncode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void regerror(s)
|
|
||||||
const char *s;
|
|
||||||
{
|
|
||||||
printf("%s\n", (char *) s);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
PROG= fgrep
|
|
||||||
MAN=
|
|
||||||
|
|
||||||
.include <minix.prog.mk>
|
|
|
@ -1,354 +0,0 @@
|
||||||
/* fgrep - fast grep Author: Bert Gijsbers */
|
|
||||||
|
|
||||||
/* Copyright (c) 1991 by Bert Gijsbers. All rights reserved.
|
|
||||||
* Permission to use and redistribute this software is hereby granted provided
|
|
||||||
* that this copyright notice remains intact and that any modifications are
|
|
||||||
* clearly marked as such.
|
|
||||||
*
|
|
||||||
* syntax:
|
|
||||||
* fgrep -chlnsv <[-e string] ... [-f file] ... | string> [file] ...
|
|
||||||
* options:
|
|
||||||
* -c : print the number of matching lines
|
|
||||||
* -h : don't print file name headers if more than one file
|
|
||||||
* -l : print only the file names of the files containing a match
|
|
||||||
* -n : print line numbers
|
|
||||||
* -s : don't print, return status only
|
|
||||||
* -v : reverse, lines not containing one of the strings match
|
|
||||||
* -e string : search for this string
|
|
||||||
* -f file : file contains strings to search for
|
|
||||||
* notes:
|
|
||||||
* Options are processed by getopt(3).
|
|
||||||
* Multiple strings per command line are supported, eg.
|
|
||||||
* fgrep -e str1 -e str2 *.c
|
|
||||||
* Instead of a filename - is allowed, meaning standard input.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* #include <ansi.h> */
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define MAX_STR_LEN 256 /* maximum length of strings to search for */
|
|
||||||
#define BYTE 0xFF /* convert from char to int */
|
|
||||||
#define READ_SIZE 4096 /* read() request size */
|
|
||||||
#define BUF_SIZE (2*READ_SIZE) /* size of buffer */
|
|
||||||
|
|
||||||
typedef struct test_str {
|
|
||||||
struct test_str *next; /* linked list */
|
|
||||||
char *str; /* string to be found */
|
|
||||||
char *str_end; /* points to last character */
|
|
||||||
int len; /* string length */
|
|
||||||
char *bufp; /* pointer into input buffer */
|
|
||||||
unsigned char table[256]; /* table for Boyer-Moore algorithm */
|
|
||||||
} test_str;
|
|
||||||
|
|
||||||
test_str *strings;
|
|
||||||
char *prog_name;
|
|
||||||
int cflag, hflag, lflag, nflag, sflag, vflag;
|
|
||||||
unsigned line_num; /* line number in current file */
|
|
||||||
|
|
||||||
int fd_in, eof_seen; /* file descriptor for input and eof status */
|
|
||||||
char input_buffer[BUF_SIZE + 2];/* buffer + sentinel margin */
|
|
||||||
#define buffer (&input_buffer[2])
|
|
||||||
|
|
||||||
/* Pointers into the input buffer */
|
|
||||||
char *input; /* points to current input char */
|
|
||||||
char *max_input; /* points to first invalid char */
|
|
||||||
char *buf_end; /* points to first char not read */
|
|
||||||
|
|
||||||
/* Error messages */
|
|
||||||
char no_mem[] = "not enough memory";
|
|
||||||
char no_arg[] = "argument missing";
|
|
||||||
|
|
||||||
extern char *optarg;
|
|
||||||
extern int optind;
|
|
||||||
|
|
||||||
_PROTOTYPE(int main, (int argc, char **argv));
|
|
||||||
_PROTOTYPE(char *search_str, (test_str * ts));
|
|
||||||
_PROTOTYPE(int fill_buffer, (void));
|
|
||||||
_PROTOTYPE(void failure, (char *mesg));
|
|
||||||
_PROTOTYPE(void file_open, (void));
|
|
||||||
_PROTOTYPE(void usage, (void));
|
|
||||||
_PROTOTYPE(char *get_line, (void));
|
|
||||||
_PROTOTYPE(void string_file, (void));
|
|
||||||
_PROTOTYPE(void add_string, (char *str));
|
|
||||||
|
|
||||||
int main(argc, argv)
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
char *line;
|
|
||||||
int c;
|
|
||||||
unsigned count; /* number of matching lines in current file */
|
|
||||||
unsigned found_one = 0; /* was there any match in any file at all ? */
|
|
||||||
|
|
||||||
#ifdef noperprintf
|
|
||||||
noperprintf(stdout);
|
|
||||||
#else
|
|
||||||
static char outbuf[BUFSIZ];
|
|
||||||
|
|
||||||
setvbuf(stdout, outbuf, _IOFBF, sizeof outbuf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
prog_name = argv[0];
|
|
||||||
if (argc == 1) usage();
|
|
||||||
while ((c = getopt(argc, argv, "ce:f:hlnsv")) != EOF) {
|
|
||||||
switch (c) {
|
|
||||||
case 'c': cflag++; break;
|
|
||||||
case 'e': add_string(optarg); break;
|
|
||||||
case 'f': string_file(); break;
|
|
||||||
case 'h': hflag++; break;
|
|
||||||
case 'l': lflag++; break;
|
|
||||||
case 'n': nflag++; break;
|
|
||||||
case 's': sflag++; break;
|
|
||||||
case 'v': vflag++; break;
|
|
||||||
default: usage(); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If no -e or -f option is used take a string from the command line. */
|
|
||||||
if (strings == (test_str *) NULL) {
|
|
||||||
if (optind == argc) failure(no_arg);
|
|
||||||
add_string(argv[optind++]);
|
|
||||||
}
|
|
||||||
if (argc - optind < 2)
|
|
||||||
hflag++; /* don't print filenames if less than two
|
|
||||||
* files */
|
|
||||||
|
|
||||||
/* Handle every matching line according to the flags. */
|
|
||||||
do {
|
|
||||||
optarg = argv[optind];
|
|
||||||
file_open();
|
|
||||||
count = 0;
|
|
||||||
while ((line = get_line()) != (char *) NULL) {
|
|
||||||
count++;
|
|
||||||
if (sflag) return 0;
|
|
||||||
if (lflag) {
|
|
||||||
printf("%s\n", optarg);
|
|
||||||
fflush(stdout);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (cflag) continue;
|
|
||||||
if (hflag == 0) printf("%s:", optarg);
|
|
||||||
if (nflag) printf("%u:", line_num);
|
|
||||||
do {
|
|
||||||
putchar(*line);
|
|
||||||
} while (++line < input);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
found_one |= count;
|
|
||||||
if (cflag) {
|
|
||||||
if (hflag == 0) printf("%s: ", optarg);
|
|
||||||
printf("%u\n", count);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
close(fd_in);
|
|
||||||
} while (++optind < argc);
|
|
||||||
|
|
||||||
/* Exit nonzero if no match is found. */
|
|
||||||
return found_one ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usage()
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"Usage: %s -chlnsv <[-e string] ... [-f file] ... | string> [file] ...\n",
|
|
||||||
prog_name);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void failure(mesg)
|
|
||||||
char *mesg;
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: %s\n", prog_name, mesg);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a string to search for to the global linked list `strings'. */
|
|
||||||
void add_string(str)
|
|
||||||
char *str;
|
|
||||||
{
|
|
||||||
test_str *ts;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (str == (char *) NULL || (len = strlen(str)) == 0) return;
|
|
||||||
if (len > MAX_STR_LEN) failure("string too long");
|
|
||||||
if ((ts = (test_str *) malloc(sizeof(*ts))) == (test_str *) NULL)
|
|
||||||
failure(no_mem);
|
|
||||||
|
|
||||||
/* Initialize Boyer-Moore table. */
|
|
||||||
memset(ts->table, len, sizeof(ts->table));
|
|
||||||
ts->len = len;
|
|
||||||
ts->str = str;
|
|
||||||
ts->str_end = str + len - 1;
|
|
||||||
for (; --len >= 0; str++) ts->table[*str & BYTE] = len;
|
|
||||||
|
|
||||||
/* Put it on the list */
|
|
||||||
ts->next = strings;
|
|
||||||
strings = ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open a file for reading. Initialize input buffer pointers. */
|
|
||||||
void file_open()
|
|
||||||
{
|
|
||||||
/* Use stdin if no file arguments are given on the command line. */
|
|
||||||
if (optarg == (char *) NULL || strcmp(optarg, "-") == 0) {
|
|
||||||
fd_in = 0;
|
|
||||||
optarg = "stdin";
|
|
||||||
} else if ((fd_in = open(optarg, O_RDONLY)) == -1) {
|
|
||||||
fprintf(stderr, "%s: can't open %s\n", prog_name, optarg);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
input = max_input = buf_end = buffer;
|
|
||||||
buffer[-1] = '\n'; /* sentinel */
|
|
||||||
eof_seen = 0;
|
|
||||||
line_num = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move any leftover characters to the head of the buffer.
|
|
||||||
* Read characters into the rest of the buffer.
|
|
||||||
* Round off the available input to whole lines.
|
|
||||||
* Return the number of valid input characters.
|
|
||||||
*/
|
|
||||||
int fill_buffer()
|
|
||||||
{
|
|
||||||
char *bufp;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
if (eof_seen) return 0;
|
|
||||||
|
|
||||||
size = buf_end - max_input;
|
|
||||||
memmove(buffer, max_input, size);
|
|
||||||
bufp = &buffer[size];
|
|
||||||
|
|
||||||
do {
|
|
||||||
if ((size = read(fd_in, bufp, READ_SIZE)) <= 0) {
|
|
||||||
if (size != 0) failure("read error");
|
|
||||||
eof_seen++;
|
|
||||||
if (bufp == buffer) /* no input left */
|
|
||||||
return 0;
|
|
||||||
/* Make sure the last char of a file is '\n'. */
|
|
||||||
*bufp++ = '\n';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bufp += size;
|
|
||||||
} while (bufp - buffer < READ_SIZE && bufp[-1] != '\n');
|
|
||||||
|
|
||||||
buf_end = bufp;
|
|
||||||
while (*--bufp != '\n');
|
|
||||||
if (++bufp == buffer) {
|
|
||||||
/* Line too long. */
|
|
||||||
*buf_end++ = '\n';
|
|
||||||
bufp = buf_end;
|
|
||||||
}
|
|
||||||
max_input = bufp;
|
|
||||||
input = buffer;
|
|
||||||
|
|
||||||
return max_input - buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read strings from a file. Give duplicates to add_string(). */
|
|
||||||
void string_file()
|
|
||||||
{
|
|
||||||
char *str, *p;
|
|
||||||
|
|
||||||
file_open();
|
|
||||||
while (input < max_input || fill_buffer() > 0) {
|
|
||||||
p = (char *) memchr(input, '\n', BUF_SIZE);
|
|
||||||
*p++ = '\0';
|
|
||||||
if ((str = (char *) malloc(p - input)) == (char *) NULL)
|
|
||||||
failure(no_mem);
|
|
||||||
memcpy(str, input, p - input);
|
|
||||||
add_string(str);
|
|
||||||
input = p;
|
|
||||||
}
|
|
||||||
close(fd_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scan the rest of the available input for a string using Boyer-Moore.
|
|
||||||
* Return a pointer to the match or a pointer beyond end of input if no match.
|
|
||||||
* Record how far the input is scanned.
|
|
||||||
*/
|
|
||||||
char *search_str(ts)
|
|
||||||
test_str *ts;
|
|
||||||
{
|
|
||||||
char *bufp, *prevbufp, *s;
|
|
||||||
|
|
||||||
bufp = input + ts->len - 1;
|
|
||||||
while (bufp < max_input) {
|
|
||||||
prevbufp = bufp;
|
|
||||||
bufp += ts->table[*bufp & BYTE];
|
|
||||||
if (bufp > prevbufp) continue;
|
|
||||||
s = ts->str_end;
|
|
||||||
do {
|
|
||||||
if (s == ts->str) { /* match found */
|
|
||||||
ts->bufp = bufp;
|
|
||||||
return bufp;
|
|
||||||
}
|
|
||||||
} while (*--bufp == *--s);
|
|
||||||
bufp = prevbufp + 1;
|
|
||||||
}
|
|
||||||
ts->bufp = bufp;
|
|
||||||
|
|
||||||
return bufp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the next line in which one of the strings occurs.
|
|
||||||
* Or, if the -v option is used, the next line without a match.
|
|
||||||
* Or NULL on EOF.
|
|
||||||
*/
|
|
||||||
char *get_line()
|
|
||||||
{
|
|
||||||
test_str *ts;
|
|
||||||
char *match, *line;
|
|
||||||
|
|
||||||
/* Loop until a line is found. */
|
|
||||||
while (1) {
|
|
||||||
if (input >= max_input && fill_buffer() == 0) { /* EOF */
|
|
||||||
line = (char *) NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If match is still equal to max_input after the next loop
|
|
||||||
* then no match is found. */
|
|
||||||
match = max_input;
|
|
||||||
ts = strings;
|
|
||||||
do {
|
|
||||||
if (input == buffer) {
|
|
||||||
if (search_str(ts) < match) match = ts->bufp;
|
|
||||||
} else if (ts->bufp < match) {
|
|
||||||
if (ts->bufp >= input || search_str(ts) < match)
|
|
||||||
match = ts->bufp;
|
|
||||||
}
|
|
||||||
} while ((ts = ts->next) != (test_str *) NULL);
|
|
||||||
|
|
||||||
/* Determine if and in what line a match is found. Only do
|
|
||||||
* line number counting if it is necessary or very easy. */
|
|
||||||
if (vflag) {
|
|
||||||
line_num++;
|
|
||||||
line = input;
|
|
||||||
input = 1 + (char *) memchr(line, '\n', BUF_SIZE);
|
|
||||||
if (input <= match) break; /* no match in current line */
|
|
||||||
} else if (nflag) {
|
|
||||||
do {
|
|
||||||
line_num++;
|
|
||||||
line = input;
|
|
||||||
input = 1 + (char *) memchr(line, '\n', BUF_SIZE);
|
|
||||||
} while (input < match ||
|
|
||||||
(input == match && match < max_input));
|
|
||||||
if (match < max_input) break; /* match found */
|
|
||||||
} else if (match < max_input) {
|
|
||||||
/* Match found. */
|
|
||||||
for (line = match; *--line != '\n';);
|
|
||||||
line++;
|
|
||||||
input = 1 + (char *) memchr(match, '\n', BUF_SIZE);
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
input = max_input;
|
|
||||||
}
|
|
||||||
|
|
||||||
return line;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
PROG= grep
|
|
||||||
MAN=
|
|
||||||
|
|
||||||
LINKS+= ${BINDIR}/grep ${BINDIR}/egrep
|
|
||||||
|
|
||||||
.include <minix.prog.mk>
|
|
|
@ -1,379 +0,0 @@
|
||||||
/* grep - search a file for a pattern Author: Norbert Schlenker */
|
|
||||||
|
|
||||||
/* Norbert Schlenker (nfs@princeton.edu) 1990-02-08
|
|
||||||
* Released into the public domain.
|
|
||||||
*
|
|
||||||
* Grep searches files for lines containing a pattern, as specified by
|
|
||||||
* a regular expression, and prints those lines. It is invoked by:
|
|
||||||
* grep [flags] [pattern] [file ...]
|
|
||||||
*
|
|
||||||
* Flags:
|
|
||||||
* -e pattern useful when pattern begins with '-'
|
|
||||||
* -c print a count of lines matched
|
|
||||||
* -i ignore case
|
|
||||||
* -l prints just file names, no lines (quietly overrides -n)
|
|
||||||
* -n printed lines are preceded by relative line numbers
|
|
||||||
* -s prints errors only (quietly overrides -l and -n)
|
|
||||||
* -v prints lines which don't contain the pattern
|
|
||||||
*
|
|
||||||
* Semantic note:
|
|
||||||
* If both -l and -v are specified, grep prints the names of those
|
|
||||||
* files which do not contain the pattern *anywhere*.
|
|
||||||
*
|
|
||||||
* Exit:
|
|
||||||
* Grep sets an exit status which can be tested by the caller.
|
|
||||||
* Note that these settings are not necessarily compatible with
|
|
||||||
* any other version of grep, especially when -v is specified.
|
|
||||||
* Possible status values are:
|
|
||||||
* 0 if any matches are found
|
|
||||||
* 1 if no matches are found
|
|
||||||
* 2 if syntax errors are detected or any file cannot be opened
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* External interfaces */
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <regexp.h> /* Thanks to Henry Spencer */
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/* Internal constants */
|
|
||||||
#define MATCH 0 /* exit code: some match somewhere */
|
|
||||||
#define NO_MATCH 1 /* exit code: no match on any line */
|
|
||||||
#define FAILURE 2 /* exit code: syntax error or bad file name */
|
|
||||||
|
|
||||||
/* Macros */
|
|
||||||
#define SET_FLAG(c) (flags[(c)-'a'] = 1)
|
|
||||||
#define FLAG(c) (flags[(c)-'a'] != 0)
|
|
||||||
|
|
||||||
#define uppercase(c) (((unsigned) ((c) - 'A')) <= ('Z' - 'A'))
|
|
||||||
#define downcase(c) ((c) - 'A' + 'a')
|
|
||||||
|
|
||||||
/* Private storage */
|
|
||||||
static char *program; /* program name */
|
|
||||||
static char flags[26]; /* invocation flags */
|
|
||||||
static regexp *expression; /* compiled search pattern */
|
|
||||||
static const char *rerr; /* error message */
|
|
||||||
|
|
||||||
/* External variables. */
|
|
||||||
extern int optind;
|
|
||||||
extern char *optarg;
|
|
||||||
|
|
||||||
/* Internal interfaces */
|
|
||||||
_PROTOTYPE(int main, (int argc, char **argv));
|
|
||||||
_PROTOTYPE(static int match, (FILE *input, char *label, char *filename));
|
|
||||||
_PROTOTYPE(static char *get_line, (FILE *input));
|
|
||||||
_PROTOTYPE(static char *map_nocase, (char *line));
|
|
||||||
_PROTOTYPE(void regerror , (const char *s ) );
|
|
||||||
_PROTOTYPE(static void tov8, (char *v8pattern, char *pattern));
|
|
||||||
|
|
||||||
int main(argc, argv)
|
|
||||||
int argc;
|
|
||||||
char *argv[];
|
|
||||||
{
|
|
||||||
int opt; /* option letter from getopt() */
|
|
||||||
int egrep=0; /* using extended regexp operators */
|
|
||||||
char *pattern; /* search pattern */
|
|
||||||
char *v8pattern; /* v8 regexp search pattern */
|
|
||||||
int exit_status = NO_MATCH; /* exit status for our caller */
|
|
||||||
int file_status; /* status of search in one file */
|
|
||||||
FILE *input; /* input file (if not stdin) */
|
|
||||||
|
|
||||||
program = argv[0];
|
|
||||||
if (strlen(program)>=5 && strcmp(program+strlen(program)-5,"egrep")==0) egrep=1;
|
|
||||||
memset(flags, 0, sizeof(flags));
|
|
||||||
pattern = NULL;
|
|
||||||
|
|
||||||
/* Process any command line flags. */
|
|
||||||
while ((opt = getopt(argc, argv, "e:cilnsv")) != EOF) {
|
|
||||||
if (opt == '?')
|
|
||||||
exit_status = FAILURE;
|
|
||||||
else
|
|
||||||
if (opt == 'e')
|
|
||||||
pattern = optarg;
|
|
||||||
else
|
|
||||||
SET_FLAG(opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Detect a few problems. */
|
|
||||||
if ((exit_status == FAILURE) || (optind == argc && pattern == NULL)) {
|
|
||||||
fprintf(stderr,"Usage: %s [-cilnsv] [-e] expression [file ...]\n",program);
|
|
||||||
exit(FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure we have a usable pattern. */
|
|
||||||
if (pattern == NULL)
|
|
||||||
pattern = argv[optind++];
|
|
||||||
|
|
||||||
/* Map pattern to lowercase if -i given. */
|
|
||||||
if (FLAG('i')) {
|
|
||||||
char *p;
|
|
||||||
for (p = pattern; *p != '\0'; p++) {
|
|
||||||
if (uppercase(*p))
|
|
||||||
*p = downcase(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!egrep) {
|
|
||||||
if ((v8pattern=malloc(2*strlen(pattern)))==(char*)0) {
|
|
||||||
fprintf(stderr,"%s: out of memory\n");
|
|
||||||
exit(FAILURE);
|
|
||||||
}
|
|
||||||
tov8(v8pattern,pattern);
|
|
||||||
} else v8pattern=pattern;
|
|
||||||
|
|
||||||
rerr=(char*)0;
|
|
||||||
if ((expression = regcomp(v8pattern)) == NULL) {
|
|
||||||
fprintf(stderr,"%s: bad regular expression",program);
|
|
||||||
if (rerr) fprintf(stderr," (%s)",rerr);
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
exit(FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process the files appropriately. */
|
|
||||||
if (optind == argc) { /* no file names - find pattern in stdin */
|
|
||||||
exit_status = match(stdin, (char *) NULL, "<stdin>");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (optind + 1 == argc) { /* one file name - find pattern in it */
|
|
||||||
if (strcmp(argv[optind], "-") == 0) {
|
|
||||||
exit_status = match(stdin, (char *) NULL, "-");
|
|
||||||
} else {
|
|
||||||
if ((input = fopen(argv[optind], "r")) == NULL) {
|
|
||||||
fprintf(stderr, "%s: couldn't open %s\n",
|
|
||||||
program, argv[optind]);
|
|
||||||
exit_status = FAILURE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
exit_status = match(input, (char *) NULL, argv[optind]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
while (optind < argc) { /* lots of file names - find pattern in all */
|
|
||||||
if (strcmp(argv[optind], "-") == 0) {
|
|
||||||
file_status = match(stdin, "-", "-");
|
|
||||||
} else {
|
|
||||||
if ((input = fopen(argv[optind], "r")) == NULL) {
|
|
||||||
fprintf(stderr, "%s: couldn't open %s\n",
|
|
||||||
program, argv[optind]);
|
|
||||||
exit_status = FAILURE;
|
|
||||||
} else {
|
|
||||||
file_status = match(input, argv[optind], argv[optind]);
|
|
||||||
fclose(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exit_status != FAILURE)
|
|
||||||
exit_status &= file_status;
|
|
||||||
++optind;
|
|
||||||
}
|
|
||||||
return(exit_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* match - matches the lines of a file with the regular expression.
|
|
||||||
* To improve performance when either -s or -l is specified, this
|
|
||||||
* function handles those cases specially.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int match(input, label, filename)
|
|
||||||
FILE *input;
|
|
||||||
char *label;
|
|
||||||
char *filename;
|
|
||||||
{
|
|
||||||
char *line, *testline; /* pointers to input line */
|
|
||||||
long int lineno = 0; /* line number */
|
|
||||||
long int matchcount = 0; /* lines matched */
|
|
||||||
int status = NO_MATCH; /* summary of what was found in this file */
|
|
||||||
|
|
||||||
if (FLAG('s') || FLAG('l')) {
|
|
||||||
while ((line = get_line(input)) != NULL) {
|
|
||||||
testline = FLAG('i') ? map_nocase(line) : line;
|
|
||||||
if (regexec(expression, testline, 1)) {
|
|
||||||
status = MATCH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (FLAG('l'))
|
|
||||||
if ((!FLAG('v') && status == MATCH) ||
|
|
||||||
( FLAG('v') && status == NO_MATCH))
|
|
||||||
puts(filename);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((line = get_line(input)) != NULL) {
|
|
||||||
++lineno;
|
|
||||||
testline = FLAG('i') ? map_nocase(line) : line;
|
|
||||||
if (regexec(expression, testline, 1)) {
|
|
||||||
status = MATCH;
|
|
||||||
if (!FLAG('v')) {
|
|
||||||
if (label != NULL)
|
|
||||||
printf("%s:", label);
|
|
||||||
if (FLAG('n'))
|
|
||||||
printf("%ld:", lineno);
|
|
||||||
if (!FLAG('c')) puts(line);
|
|
||||||
matchcount++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (FLAG('v')) {
|
|
||||||
if (label != NULL)
|
|
||||||
printf("%s:", label);
|
|
||||||
if (FLAG('n'))
|
|
||||||
printf("%ld:", lineno);
|
|
||||||
if (!FLAG('c')) puts(line);
|
|
||||||
matchcount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (FLAG('c')) printf("%ld\n", matchcount);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* get_line - fetch a line from the input file
|
|
||||||
* This function reads a line from the input file into a dynamically
|
|
||||||
* allocated buffer. If the line is too long for the current buffer,
|
|
||||||
* attempts will be made to increase its size to accomodate the line.
|
|
||||||
* The trailing newline is stripped before returning to the caller.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FIRST_BUFFER (size_t)256 /* first buffer size */
|
|
||||||
|
|
||||||
static char *buf = NULL; /* input buffer */
|
|
||||||
static size_t buf_size = 0; /* input buffer size */
|
|
||||||
|
|
||||||
static char *get_line(input)
|
|
||||||
FILE *input;
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
register char *bp;
|
|
||||||
register int c;
|
|
||||||
char *new_buf;
|
|
||||||
size_t new_size;
|
|
||||||
|
|
||||||
if (buf_size == 0) {
|
|
||||||
if ((buf = (char *) malloc(FIRST_BUFFER)) == NULL) {
|
|
||||||
fprintf(stderr,"%s: not enough memory\n",program);
|
|
||||||
exit(FAILURE);
|
|
||||||
}
|
|
||||||
buf_size = FIRST_BUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
bp = buf;
|
|
||||||
n = buf_size;
|
|
||||||
while (1) {
|
|
||||||
while (--n > 0 && (c = getc(input)) != EOF) {
|
|
||||||
if (c == '\n') {
|
|
||||||
*bp = '\0';
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
*bp++ = c;
|
|
||||||
}
|
|
||||||
if (c == EOF)
|
|
||||||
return (ferror(input) || bp == buf) ? NULL : buf;
|
|
||||||
new_size = buf_size << 1;
|
|
||||||
if ((new_buf = (char *) realloc(buf, new_size)) == NULL) {
|
|
||||||
fprintf(stderr, "%s: line too long - truncated\n", program);
|
|
||||||
while ((c = getc(input)) != EOF && c != '\n') ;
|
|
||||||
*bp = '\0';
|
|
||||||
return buf;
|
|
||||||
} else {
|
|
||||||
bp = new_buf + (buf_size - 1);
|
|
||||||
n = buf_size + 1;
|
|
||||||
buf = new_buf;
|
|
||||||
buf_size = new_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* map_nocase - map a line down to lowercase letters only.
|
|
||||||
* bad points: assumes line gotten from get_line.
|
|
||||||
* there is more than A-Z you say?
|
|
||||||
*/
|
|
||||||
|
|
||||||
static char *map_nocase(line)
|
|
||||||
char *line;
|
|
||||||
{
|
|
||||||
static char *mapped=(char*)0;
|
|
||||||
static size_t map_size = 0;
|
|
||||||
char *mp;
|
|
||||||
|
|
||||||
if (map_size < buf_size) {
|
|
||||||
if ((mapped=realloc(mapped,map_size=buf_size)) == NULL) {
|
|
||||||
fprintf(stderr,"%s: not enough memory\n",program);
|
|
||||||
exit(FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mp = mapped;
|
|
||||||
do {
|
|
||||||
*mp++ = uppercase(*line) ? downcase(*line) : *line;
|
|
||||||
} while (*line++ != '\0');
|
|
||||||
|
|
||||||
return mapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In basic regular expressions, the characters ?, +, |, (, and )
|
|
||||||
are taken literally; use the backslashed versions for RE operators.
|
|
||||||
In v8 regular expressions, things are the other way round, so
|
|
||||||
we have to swap those characters and their backslashed versions.
|
|
||||||
*/
|
|
||||||
static void tov8(char *v8, char *basic)
|
|
||||||
{
|
|
||||||
while (*basic) switch (*basic)
|
|
||||||
{
|
|
||||||
case '?':
|
|
||||||
case '+':
|
|
||||||
case '|':
|
|
||||||
case '(':
|
|
||||||
case ')':
|
|
||||||
{
|
|
||||||
*v8++='\\';
|
|
||||||
*v8++=*basic++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '\\':
|
|
||||||
{
|
|
||||||
switch (*(basic+1))
|
|
||||||
{
|
|
||||||
case '?':
|
|
||||||
case '+':
|
|
||||||
case '|':
|
|
||||||
case '(':
|
|
||||||
case ')':
|
|
||||||
{
|
|
||||||
*v8++=*++basic;
|
|
||||||
++basic;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '\0':
|
|
||||||
{
|
|
||||||
*v8++=*basic++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
*v8++=*basic++;
|
|
||||||
*v8++=*basic++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
*v8++=*basic++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*v8++='\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Regular expression code calls this routine to print errors. */
|
|
||||||
|
|
||||||
void regerror(s)
|
|
||||||
const char *s;
|
|
||||||
{
|
|
||||||
rerr=s;
|
|
||||||
}
|
|
Loading…
Reference in a new issue