#include #include #include #include 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 ---------------------- */ #define LNBUFF_LEN 128 /* the line buffer lenght must be a power of two */ static_assert(!(LNBUFF_LEN % 2), "Line buffer length is not a power of two!"); /* line_buffer: global overflowing line buffer */ struct { char self[LNBUFF_LEN]; unsigned len; } lnbuff = {.len= 0}; /* LNBUFF_I: current index in line buffer */ #define LNBUFF_I (lnbuff.len & (LNBUFF_LEN - 1)) /* getch_lnbuff: getchar and add it to buffer */ int getch_lnbuff() { int c = getchar(); if (c == EOF || c == '\n') // new line lnbuff.len = 0; else { lnbuff.self[LNBUFF_I] = c; lnbuff.len++; } return c; } /* flush_lnbuff: print contents of line buffer, return length */ int flush_lnbuff() { int i; /* handle overflowing chars */ if (lnbuff.len > LNBUFF_LEN) { for (i = LNBUFF_LEN; i < lnbuff.len; i++) putchar('.'); for (i = LNBUFF_I; i < LNBUFF_LEN; i++) putchar(lnbuff.self[i]); } /* handle rest of chars */ for (i = 0; i < LNBUFF_I; i++) putchar(lnbuff.self[i]); i = lnbuff.len; lnbuff.len = 0; return i; }