Optimizing grep exapmle

master
Tibor Bizjak 2023-06-25 14:30:48 +02:00
parent b81504f2ee
commit e7eacc893f
3 changed files with 210 additions and 0 deletions

View File

@ -0,0 +1,120 @@
#include <stdio.h>
#include <string.h>
#define LNBUFF_LEN 10
int grep(char pattern[]);
/* grep with graceful buffer overflow */
/* parse and verify arg pattern, pass it to grep */
int main(int argc, char *argv[])
{
/* verify arg is given */
if (argc < 2) {
printf("error: excpected pattern\n");
return -1;
}
char *pattern = argv[1];
/* verify pattern */
char c;
int i;
for (i = 0; (c = pattern[i]) != '\0'; i++)
if (c == '\n') {
printf("error: newline in pattern\n");
return -2;
}
int found = grep(pattern);
printf("found = %d\n", found);
return found;
}
void println(void);
int flush_lnbuff(void);
int getch_lnbuff(void);
/* grep: prints lines containing pattern, returns number of matching lines */
int grep(char *pattern)
{
int found, i, c;
const int plen = strlen(pattern);
i = found = 0;
while ((c = getch_lnbuff()) != EOF)
if (c != pattern[i])
i = 0;
else if (++i == plen) { // found match
i = 0;
found++;
flush_lnbuff();
println();
}
return found;
}
/* println: prints next line from stdin
* prints newline on EOF */
void println()
{
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
putchar(c);
}
/* ------------------------ line buffer ---------------------- */
/* line_buffer: global overflowing line buffer */
struct {
char self[LNBUFF_LEN];
unsigned i;
unsigned trunc;
} lnbuff = {.i = 0, .trunc = 0};
/* reset_lnbuff: reset buffer */
#define reset_lnbuff() lnbuff.i = lnbuff.trunc = 0
/* getch_lnbuff: getchar and add it to buffer */
int getch_lnbuff()
{
int c = getchar();
if (c == EOF || c == '\n') { // new line
reset_lnbuff();
return c;
}
if (lnbuff.trunc)
lnbuff.trunc++;
if (lnbuff.i == LNBUFF_LEN) {
lnbuff.i = 0;
if (!lnbuff.trunc)
lnbuff.trunc = 1;
}
lnbuff.self[lnbuff.i++] = c;
return c;
}
/* flush_lnbuff: print contents of line buffer, return length */
int flush_lnbuff()
{
int i, len = lnbuff.i;
if (lnbuff.trunc) {
len = LNBUFF_LEN + lnbuff.trunc;
for (i = 0; i < lnbuff.trunc; i++)
putchar('.');
for (i = lnbuff.i; i < LNBUFF_LEN; i++)
putchar(lnbuff.self[i]);
}
for (i = 0; i < lnbuff.i; i++)
putchar(lnbuff.self[i]);
reset_lnbuff();
return len;
}

View File

@ -0,0 +1,15 @@
#include <stdio.h>
#define W 80
#define REPEAT 4000000
int main()
{
int i, j;
for (i = 0; i < REPEAT; i++) {
for (j = 0; j < W; j++)
putchar('y');
putchar('\n');
}
return 0;
}

View File

@ -0,0 +1,75 @@
#include <stdio.h>
#include <string.h>
#define MAXLINE 1000 /* maximum input line length */
int grep(char *pattern);
/* somewhat optimized book version of grep */
/* find all lines matching pattern */
int main(int argc, char *argv[])
{
/* verify arg is given */
if (argc < 2) {
printf("error: excpected pattern\n");
return -1;
}
char *pattern = argv[1];
/* verify pattern */
char c;
int i;
for (i = 0; (c = pattern[i]) != '\0'; i++)
if (c == '\n') {
printf("error: newline in pattern\n");
return -2;
}
int found = grep(pattern);
printf("found = %d\n", found);
return found;
}
int getln(char line[], int lim);
int strindex(char source[], char searchfor[], int slen);
/* grep: prints lines containing pattern, returns number of matching lines */
int grep(char *pattern)
{
char line[MAXLINE];
int found = 0;
int slen = strlen(pattern);
while (getln(line, MAXLINE) > 0)
if (strindex(line, pattern, slen) >= 0) {
printf("%s", line);
found++;
}
return found;
}
/* getline: get line (including \n) into s, return length */
int getln(char *s, int lim)
{
int c, i = 0;
while (--lim > 0 && (c = getchar()) != EOF && (s[i++] = c) != '\n')
;
s[i] = '\0';
return i;
}
/* strindex: return index of t in s, -1 if none */
int strindex(char s[], char t[], int slen)
{
int i, j;
for (i = j = 0; s[i]; i++)
if (s[i] != t[j])
j = 0;
else if (++j == slen) { // found match
return i - slen + 1;
}
return -1;
}