286 lines
5.1 KiB
C
286 lines
5.1 KiB
C
/* fgrep - fast grep Author: Jan Christiaan van Winkel */
|
|
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
|
|
int argc;
|
|
char **argv;
|
|
int stringlen, offset, boundary;
|
|
int i, j, k, count, linum;
|
|
char stringarea[1024];
|
|
int strptr;
|
|
int strcount;
|
|
unsigned char tbl[32][256];
|
|
int lengths[32];
|
|
char *tststring[32];
|
|
char string[512];
|
|
char tmpstring[512];
|
|
int vflag, cflag, nofname, hadone, lflag, nflag, sflag, hflag, eflag, fflag;
|
|
int fp;
|
|
|
|
main(oargc, oargv)
|
|
int oargc;
|
|
char *oargv[];
|
|
|
|
{
|
|
int find();
|
|
void exparg();
|
|
void getargs();
|
|
void gotone();
|
|
|
|
argc = oargc;
|
|
argv = oargv;
|
|
getargs();
|
|
|
|
fp = 0;
|
|
if (i >= argc - 2 || hflag) /* stdin, 1 file, hflag */
|
|
nofname = 1;
|
|
|
|
do {
|
|
if (i < argc && (fp = open(argv[i], O_RDONLY)) < 0) {
|
|
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[i]);
|
|
continue;
|
|
}
|
|
count = 0;
|
|
linum = 0;
|
|
|
|
while ((stringlen = getlin(fp, string, 512)) != EOF) {
|
|
linum++;
|
|
for (j = 0; j < strcount; j++) {
|
|
if (find(tststring[j], tbl[j], lengths[j]) != vflag) {
|
|
gotone();
|
|
break;
|
|
}
|
|
}
|
|
if (lflag && count) break;
|
|
}
|
|
close(fp);
|
|
|
|
if (cflag) {
|
|
printf("%s: %d times\n", argv[i], count);
|
|
}
|
|
if (lflag && count > 0) {
|
|
printf("%s\n", argv[i]);
|
|
}
|
|
} while (++i < argc);
|
|
|
|
fflush(stdout);
|
|
if (hadone)
|
|
exit(0);
|
|
else
|
|
exit(1);
|
|
}
|
|
|
|
void getargs()
|
|
{
|
|
int tmp;
|
|
void maktbl();
|
|
for (i = 1; i < argc && argv[i][0] == '-'; i++) {
|
|
switch (argv[i][1]) {
|
|
case 'e':
|
|
eflag = 1;
|
|
if (fflag) {
|
|
fprintf(stderr, "%s: can't have -e and -f at the same time\n", argv[0]);
|
|
exit(2);
|
|
}
|
|
if (i < argc - 1) {
|
|
i++;
|
|
tststring[0] = argv[i];
|
|
strcount = 1;
|
|
} else {
|
|
fprintf(stderr, "%s: not enough arguments\n");
|
|
exit(2);
|
|
}
|
|
break;
|
|
case 'v': vflag = 1; break;
|
|
case 'c': cflag = 1; break;
|
|
case 'l': lflag = 1; break;
|
|
case 's': sflag = 1; break;
|
|
case 'h': hflag = 1; break;
|
|
case 'n': nflag = 1; break;
|
|
case 'f':
|
|
fflag = 1;
|
|
if (eflag) {
|
|
fprintf(stderr,
|
|
"%s: can't have -e and -f at the same time\n", argv[0]);
|
|
exit(2);
|
|
}
|
|
if (i >= argc - 1) {
|
|
fprintf(stderr, "%s: not enough arguments\n");
|
|
exit(2);
|
|
} else {
|
|
i++;
|
|
if ((fp = open(argv[i], O_RDONLY)) < 0) {
|
|
fprintf(stderr,
|
|
"%s: can't open %s\n", argv[0], argv[i]);
|
|
exit(2);
|
|
}
|
|
strcount = 0;
|
|
while ((tmp = getlin(fp, &stringarea[strptr], 128)) != EOF) {
|
|
tststring[strcount++] = &stringarea[strptr];
|
|
strptr = strptr + tmp + 1;
|
|
if (strptr >= 1024 - 128 || strcount == 32) {
|
|
fprintf(stderr, "%s: not enough room\n", argv[0]);
|
|
exit(2);
|
|
}
|
|
}
|
|
close(fp);
|
|
}
|
|
break;
|
|
default:
|
|
fprintf(stderr, "%s: invalid command line option\n", argv[0]);
|
|
exit(2);
|
|
break;
|
|
}
|
|
if (cflag && lflag) {
|
|
fprintf(stderr, "%s: cannot have -l and -c at the same time\n", argv[0]);
|
|
exit(2);
|
|
}
|
|
}
|
|
|
|
if (!eflag && !fflag) {
|
|
if (i < argc) {
|
|
tststring[0] = argv[i++];
|
|
strcount = 1;
|
|
} else {
|
|
fprintf(stderr, "%s: no search string.\n", argv[0]);
|
|
exit(2);
|
|
}
|
|
}
|
|
for (j = 0; j < strcount; j++) {
|
|
if (tststring[j][0] == '"') {
|
|
count = strlen(tststring[j]);
|
|
movmem(&tststring[j][1], tststring[j], count - 2);
|
|
tststring[j][count - 2] = '\0';
|
|
}
|
|
maktbl(tststring[j], tbl[j], &lengths[j]);
|
|
}
|
|
}
|
|
|
|
|
|
movmem(src, dst, len)
|
|
char *src, *dst;
|
|
int len;
|
|
{
|
|
while (len--) *dst++ = *src++;
|
|
}
|
|
|
|
setmem(mem, len, filler)
|
|
char *mem;
|
|
int len;
|
|
char filler;
|
|
{
|
|
while (len--) *mem++ = filler;
|
|
}
|
|
|
|
|
|
int find(findword, table, wordlen)
|
|
unsigned char *findword;
|
|
unsigned char *table;
|
|
int wordlen;
|
|
{
|
|
auto int lastletter, tmp;
|
|
|
|
boundary = stringlen - wordlen;
|
|
lastletter = wordlen - 1;
|
|
offset = 0;
|
|
while (offset <= boundary) {
|
|
tmp = table[string[offset + lastletter]];
|
|
if (tmp) {
|
|
offset += tmp;
|
|
} else {
|
|
for (k = lastletter - 1; k >= 0; k--) {
|
|
if ((string[k + offset]) != findword[k]) {
|
|
offset++;
|
|
break;
|
|
}
|
|
}
|
|
if (k < 0) return(1);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
void maktbl(findword, table, wordlen)
|
|
unsigned char *findword;
|
|
unsigned char *table;
|
|
int *wordlen;
|
|
{
|
|
|
|
auto int i, len;
|
|
|
|
*wordlen = len = strlen(findword);
|
|
setmem(table, 256, len);
|
|
for (i = 0; i < len; i++) table[findword[i]] = len - i - 1;
|
|
}
|
|
|
|
|
|
void gotone()
|
|
{
|
|
hadone = 1;
|
|
|
|
if (cflag || lflag || sflag) {
|
|
count++;
|
|
return;
|
|
}
|
|
if (!nofname) printf("%s:", argv[i]);
|
|
|
|
if (nflag) printf("%d:", linum);
|
|
|
|
printf("%s\n", string);
|
|
}
|
|
|
|
|
|
int getlin(infile, buf, maxlen)
|
|
int infile;
|
|
char *buf;
|
|
int maxlen;
|
|
{
|
|
static char mybuf[2048];
|
|
static char *low;
|
|
static char *high;
|
|
|
|
auto int status;
|
|
auto char *p = buf;
|
|
auto int endline;
|
|
|
|
*p = '\0';
|
|
maxlen--;
|
|
while (1) {
|
|
endline = 0;
|
|
while (low < high && !endline) {
|
|
if (p >= &buf[maxlen]) { /* overflow, skip all
|
|
* until \n */
|
|
while (low < high && *low != '\n') low++;
|
|
endline = (*low == '\n');
|
|
} else
|
|
endline = ((*p++ = *low++) == '\n');
|
|
|
|
} /* exhausted buffer or found \n */
|
|
|
|
/* Don't continue if \n found */
|
|
if (endline) {
|
|
*(p - 1) = '\0';
|
|
return(p - buf - 1);
|
|
}
|
|
status = read(infile, mybuf, 2048);
|
|
if (status <= 0) break;
|
|
|
|
low = mybuf;
|
|
high = &mybuf[status];
|
|
|
|
}
|
|
|
|
/* Empty line or a bit filled ? */
|
|
*p = '\0';
|
|
if (status < 0) {
|
|
perror("read error");
|
|
return(EOF);
|
|
}
|
|
if (p - buf) return(p - buf);
|
|
return(EOF);
|
|
|
|
} /* of getlin() */
|