From e7eacc893fbdaddaaf8a7e72595fdffbc526a298 Mon Sep 17 00:00:00 2001 From: Tibor Bizjak Date: Sun, 25 Jun 2023 14:30:48 +0200 Subject: [PATCH] Optimizing grep exapmle --- k&r/04-funcs-and-prog-struct/04-grep-grace.c | 120 +++++++++++++++++++ k&r/04-funcs-and-prog-struct/04-grep-input.c | 15 +++ k&r/04-funcs-and-prog-struct/04-grep-opt.c | 75 ++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 k&r/04-funcs-and-prog-struct/04-grep-grace.c create mode 100644 k&r/04-funcs-and-prog-struct/04-grep-input.c create mode 100644 k&r/04-funcs-and-prog-struct/04-grep-opt.c diff --git a/k&r/04-funcs-and-prog-struct/04-grep-grace.c b/k&r/04-funcs-and-prog-struct/04-grep-grace.c new file mode 100644 index 0000000..4085ace --- /dev/null +++ b/k&r/04-funcs-and-prog-struct/04-grep-grace.c @@ -0,0 +1,120 @@ +#include +#include + +#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; +} diff --git a/k&r/04-funcs-and-prog-struct/04-grep-input.c b/k&r/04-funcs-and-prog-struct/04-grep-input.c new file mode 100644 index 0000000..77f183d --- /dev/null +++ b/k&r/04-funcs-and-prog-struct/04-grep-input.c @@ -0,0 +1,15 @@ +#include + +#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; +} diff --git a/k&r/04-funcs-and-prog-struct/04-grep-opt.c b/k&r/04-funcs-and-prog-struct/04-grep-opt.c new file mode 100644 index 0000000..3cb55a8 --- /dev/null +++ b/k&r/04-funcs-and-prog-struct/04-grep-opt.c @@ -0,0 +1,75 @@ +#include +#include + +#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; +}