fixed grep
This commit is contained in:
parent
3be9df7610
commit
4834ffca63
1 changed files with 47 additions and 60 deletions
107
src/grep.c
107
src/grep.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue