fixed grep

This commit is contained in:
Your Name 2025-06-04 10:21:28 +03:00
parent 3be9df7610
commit 4834ffca63

View file

@ -6,13 +6,16 @@
#include <regex.h> #include <regex.h>
#include <sys/types.h> #include <sys/types.h>
static struct pattern { struct pattern {
char *str; char *str;
regex_t reg; regex_t reg;
char reg_set; 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 i_flag;
static char F_flag; static char F_flag;
@ -25,55 +28,39 @@ static char mode_flag;
static int reg_flag; static int reg_flag;
static void free_patterns(void) { static void free_patterns(void) {
if (ptrns == NULL) while (ptrns != NULL) {
return; ptr = ptrns->next;
for (size_t i = 0; i < ptrns_size; i++) { if (ptrns->str != NULL)
if (ptrns[i] == NULL) free(ptrns->str);
continue;
if (ptrns[i]->str != NULL) if (ptrns->reg_set)
free(ptrns[i]->str); regfree(&ptrns->reg);
if (ptrns[i]->reg_set) free(ptrns);
regfree(&ptrns[i]->reg); ptrns = ptr;
free(ptrns[i]);
} }
free(ptrns);
ptrns = NULL;
} }
static int addpattern(const char *str, const size_t size) { static int addpattern(const char *str, const size_t size) {
char reg_error_flag = 0;
ptrns = malloc(sizeof(struct pattern));
if (ptrns == NULL) { if (ptrns == NULL) {
ptrns = malloc(sizeof(struct pattern *)); fprintf(stderr, "grep: malloc: %s\n", strerror(errno));
if (ptrns == NULL) { return 1;
fprintf(stderr, "grep: malloc: %s\n", strerror(errno));
return 1;
}
} }
char reg_error_flag = 0; ptrns->str = strdup(str);
struct pattern **bckp = realloc(ptrns, sizeof(struct pattern *) * (ptrns_size + 1)); if (ptrns->str == NULL)
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)
goto ADDP_ERROR; goto ADDP_ERROR;
if (!F_flag) { if (!F_flag) {
char *reg_str = ptrns[ptrns_size]->str; char *reg_str = ptrns->str;
size_t rs_size = size; size_t rs_size = size;
char bol = (ptrns[ptrns_size]->str[0] == '^'); char bol = (ptrns->str[0] == '^');
char eol = (ptrns[ptrns_size]->str[size - 1] == '^'); char eol = (ptrns->str[size - 1] == '^');
if (x_flag || w_flag) { if (x_flag || w_flag) {
if (w_flag) if (w_flag)
@ -85,28 +72,25 @@ static int addpattern(const char *str, const size_t size) {
} }
if (x_flag) 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) 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; reg_error_flag = 1;
ptrns[ptrns_size]->reg_set = 1; ptrns->reg_set = 1;
if (x_flag || w_flag) if (x_flag || w_flag)
free(reg_str); free(reg_str);
} }
if (reg_error_flag) ptrns->next = ptr;
goto ADDP_ERROR; ptr = ptrns;
ptrns_size++;
return 0; return 0;
ADDP_ERROR: ADDP_ERROR:
ptrns_size++;
free_patterns(); free_patterns();
fprintf(stderr, "grep: %s\n", (reg_error_flag) ? "bad regex" : strerror(errno)); fprintf(stderr, "grep: %s\n", (reg_error_flag) ? "bad regex" : strerror(errno));
return 1; return 1;
@ -173,19 +157,22 @@ static int grep(FILE *fp, const char *file) {
buf[size - 1] = '\0'; buf[size - 1] = '\0';
char match = 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; match = 1;
break; break;
} }
else if (regexec(&bckp->reg, buf, 1, &m, 0) == 0) {
match = 1;
break;
}
bckp = ptr;
} }
if (match != v_flag) { if (match != v_flag) {
@ -195,14 +182,14 @@ static int grep(FILE *fp, const char *file) {
break; break;
case 'o': case 'o':
if (ptrns[i]->reg_set) { if (bckp->reg_set) {
unsigned int start = m.rm_so; unsigned int start = m.rm_so;
unsigned int finish = m.rm_eo; unsigned int finish = m.rm_eo;
printf("%.*s\n", finish - start, buf + start); printf("%.*s\n", finish - start, buf + start);
} }
else else
puts(ptrns[i]->str); puts(bckp->str);
break; break;
@ -290,14 +277,14 @@ int main(int argc, char **argv) {
break; break;
default: 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; return 0;
} }
} }
argv += optind; argv += optind;
argc -= optind; argc -= optind;
if (ptrns_size == 0) { if (ptrns == NULL) {
fprintf(stderr, "grep: no patterns specified\n"); fprintf(stderr, "grep: no patterns specified\n");
return 1; return 1;
} }