diff --git a/src/grep.c b/src/grep.c index db7407b..c6735af 100644 --- a/src/grep.c +++ b/src/grep.c @@ -6,13 +6,16 @@ #include #include -static struct pattern { +struct pattern { char *str; - regex_t reg; char reg_set; -} **ptrns; -static size_t ptrns_size = 0; + + struct pattern *next; +}; + +static struct pattern *ptr; +static struct pattern *ptrns; static char i_flag; static char F_flag; @@ -25,55 +28,39 @@ static char mode_flag; static int reg_flag; static void free_patterns(void) { - if (ptrns == NULL) - return; + while (ptrns != NULL) { + ptr = ptrns->next; - for (size_t i = 0; i < ptrns_size; i++) { - if (ptrns[i] == NULL) - continue; + if (ptrns->str != NULL) + free(ptrns->str); - if (ptrns[i]->str != NULL) - free(ptrns[i]->str); + if (ptrns->reg_set) + regfree(&ptrns->reg); - if (ptrns[i]->reg_set) - regfree(&ptrns[i]->reg); - - free(ptrns[i]); + free(ptrns); + ptrns = ptr; } - - free(ptrns); - ptrns = NULL; } static int addpattern(const char *str, const size_t size) { + char reg_error_flag = 0; + + ptrns = malloc(sizeof(struct pattern)); if (ptrns == NULL) { - ptrns = malloc(sizeof(struct pattern *)); - if (ptrns == NULL) { - fprintf(stderr, "grep: malloc: %s\n", strerror(errno)); - return 1; - } + fprintf(stderr, "grep: malloc: %s\n", strerror(errno)); + return 1; } - char reg_error_flag = 0; - struct pattern **bckp = realloc(ptrns, sizeof(struct pattern *) * (ptrns_size + 1)); - if (bckp == NULL) - goto ADDP_ERROR; - ptrns = bckp; - - ptrns[ptrns_size] = malloc(sizeof(struct pattern)); - if (ptrns[ptrns_size] == NULL) - goto ADDP_ERROR; - - ptrns[ptrns_size]->str = strdup(str); - if (ptrns[ptrns_size]->str == NULL) + ptrns->str = strdup(str); + if (ptrns->str == NULL) goto ADDP_ERROR; if (!F_flag) { - char *reg_str = ptrns[ptrns_size]->str; + char *reg_str = ptrns->str; size_t rs_size = size; - char bol = (ptrns[ptrns_size]->str[0] == '^'); - char eol = (ptrns[ptrns_size]->str[size - 1] == '^'); + char bol = (ptrns->str[0] == '^'); + char eol = (ptrns->str[size - 1] == '^'); if (x_flag || w_flag) { if (w_flag) @@ -85,28 +72,25 @@ static int addpattern(const char *str, const size_t size) { } if (x_flag) - snprintf(reg_str, rs_size + 4, "%s%s%s", (bol) ? "" : "^", ptrns[ptrns_size]->str, (eol) ? "" : "$"); + snprintf(reg_str, rs_size + 4, "%s%s%s", (bol) ? "" : "^", ptrns->str, (eol) ? "" : "$"); else if (w_flag) - snprintf(reg_str, rs_size + 4, "%s\\<%s%.*s%s\\>%s", (bol) ? "^" : "", (E_flag) ? "(" : "\\(", (int)size - bol - eol, ptrns[ptrns_size]->str + bol, (E_flag) ? ")" : "\\)", (eol) ? "$" : ""); + snprintf(reg_str, rs_size + 4, "%s\\<%s%.*s%s\\>%s", (bol) ? "^" : "", (E_flag) ? "(" : "\\(", (int)size - bol - eol, ptrns->str + bol, (E_flag) ? ")" : "\\)", (eol) ? "$" : ""); - if (regcomp(&ptrns[ptrns_size]->reg, reg_str, reg_flag) != 0) + if (regcomp(&ptrns->reg, reg_str, reg_flag) != 0) reg_error_flag = 1; - ptrns[ptrns_size]->reg_set = 1; + ptrns->reg_set = 1; if (x_flag || w_flag) free(reg_str); } - if (reg_error_flag) - goto ADDP_ERROR; - - ptrns_size++; + ptrns->next = ptr; + ptr = ptrns; return 0; ADDP_ERROR: - ptrns_size++; free_patterns(); fprintf(stderr, "grep: %s\n", (reg_error_flag) ? "bad regex" : strerror(errno)); return 1; @@ -173,19 +157,22 @@ static int grep(FILE *fp, const char *file) { buf[size - 1] = '\0'; char match = 0; - size_t i = 0; - for (; i < ptrns_size; i++) { - if (F_flag) { - if (cmp(buf, ptrns[i]->str)) { - match = 1; - break; - } - } - else if (regexec(&ptrns[i]->reg, buf, 1, &m, 0) == 0) { + struct pattern *bckp = ptrns; + while (bckp != NULL) { + ptr = bckp->next; + + if (F_flag && cmp(buf, bckp->str)) { match = 1; break; } + + else if (regexec(&bckp->reg, buf, 1, &m, 0) == 0) { + match = 1; + break; + } + + bckp = ptr; } if (match != v_flag) { @@ -195,14 +182,14 @@ static int grep(FILE *fp, const char *file) { break; case 'o': - if (ptrns[i]->reg_set) { + if (bckp->reg_set) { unsigned int start = m.rm_so; unsigned int finish = m.rm_eo; printf("%.*s\n", finish - start, buf + start); } else - puts(ptrns[i]->str); + puts(bckp->str); break; @@ -290,14 +277,14 @@ int main(int argc, char **argv) { break; default: - puts("grep [efiFHvxwqoc] [FILE]\n\t-e PTRN Pattern to match\n\t-f FILE Read pattern from file\n\t-i Ignore case\n\t-H Add 'filename:' prefix\n\t-F PATTERN is a literal (not regexp)\n\t-E PATTERN is an extended regexp\n\t-v Select non-matching lines\n\t-x Match whole lines only\n\t-w Match whole words only\n\t-q Quiet\n\t-o Show only the matching part of line\n\t-c Show only count of matching lines"); + puts("grep [efiFHvxwqoc] [FILE]\n\t-e PTRN Pattern to match\n\t-f FILE Read pattern from file\n\t-i Ignore case\n\t-H Add 'filename:' prefix\n\t-F Pattern is a literal (not regexp)\n\t-E Pattern is an extended regexp\n\t-v Select non-matching lines\n\t-x Match whole lines only\n\t-w Match whole words only\n\t-q Quiet\n\t-o Show only the matching part of line\n\t-c Show only count of matching lines"); return 0; } } argv += optind; argc -= optind; - if (ptrns_size == 0) { + if (ptrns == NULL) { fprintf(stderr, "grep: no patterns specified\n"); return 1; }