/* z.c * * Usage: see help ;) */ #include #include #include #include #include #include #include /* Warning: Won't be able to search correctly if a line contains over 2048 bytes */ #define BUFFER_SIZE 2048 /* class ;p */ typedef struct _0_strs{ char **strs; regex_t **regs; int count; int regflag; int (*func_find) (struct _0_strs *, char *, int); int (*func_ignore)(struct _0_strs *, char *, int); } strs; /* functions */ void help(char *); int zcat(char *, strs *, strs *); /* sub functions */ strs *append_str(strs *, char *); void reg_init (strs *); void reg_finish(strs *); void str_finish(strs *); strs *constructor(strs *); strs *set_val (strs *); void destructor (strs *); /* methods ;p */ int regex_search_find (strs *, char *, int); int string_search_find (strs *, char *, int); int regex_search_ignore (strs *, char *, int); int string_search_ignore(strs *, char *, int); /* main */ int main(int argc, char **argv){ int c, i = 0, result = 0; strs *find = NULL, *ignore = NULL; find = constructor(find); ignore = constructor(ignore); /* analyze options */ while((c = getopt(argc, argv, "f:i:rh")) != -1){ switch(c){ case 'f': find = append_str(find, optarg); break; case 'i': ignore = append_str(ignore, optarg); break; case 'r': find->regflag = ignore->regflag = 1; break; case 'h': default: help(argv[0]); result = 1; break; } } find = set_val(find); ignore = set_val(ignore); /* reading and searching start each files those are given by command line */ if(result == 0){ for(i = optind; i < argc; i++){ if((result = zcat(argv[i], find, ignore)) != 0){ fprintf(stderr, "!!! Some errors have occured: in %s\n - break.\n", argv[i]); break; } } } destructor(find); destructor(ignore); return result; } int zcat(char *filepath, strs *find, strs *ignore){ gzFile in = NULL; char buf[BUFFER_SIZE]; int i; in = gzopen(filepath, "r"); if(!in){ fprintf(stderr, "Error: couldn't open %s\n", filepath); return 1; } MAINLOOP: while(gzgets(in, buf, BUFFER_SIZE)){ for(i = 0; i < find->count; i++){ if(!find->func_find(find, buf, i)){ goto MAINLOOP; /* continue */ } } for(i = 0; i < ignore->count; i++){ if(ignore->func_ignore(ignore, buf, i)){ goto MAINLOOP; /* continue */ } } printf("%s", buf); } if(in){ gzclose(in); } return 0; } int regex_search_find(strs *find, char *buf, int index){ return !regexec(find->regs[index], buf, 0, NULL, 0); } int regex_search_ignore(strs *ignore, char *buf, int index){ return !regexec(ignore->regs[index], buf, 0, NULL, 0); } int string_search_find(strs *find, char *buf, int index){ return (int)strstr(buf, find->strs[index]); } int string_search_ignore(strs *ignore, char *buf, int index){ return (int)strstr(buf, ignore->strs[index]); } strs *append_str(strs *area, char *string){ int length = strlen(string) + 1; /* counts \0 */ area->strs = (char **)realloc(area->strs, sizeof(char *) * (area->count + 1)); area->strs[area->count] = (char *)malloc(sizeof(char) * length); strncpy(area->strs[area->count++], string, length); return area; } /* constructor ;p */ strs *constructor(strs *self){ self = (strs *)malloc(sizeof(strs)); self->count = 0; return self; } strs *set_val(strs *self){ if(self->regflag == 1){ reg_init(self); str_finish(self); self->func_find = regex_search_find; self->func_ignore = regex_search_ignore; } else{ self->func_find = string_search_find; self->func_ignore = string_search_ignore; } return self; } /* destructor ;p */ void destructor(strs *self){ if(self->regflag == 1){ reg_finish(self); } else{ str_finish(self); } free(self); } /* initialization for regex search */ void reg_init(strs *self){ int i; self->regs = (regex_t **)malloc(sizeof(regex_t *) * self->count); for(i = 0; i < self->count; i++){ self->regs[i] = (regex_t *)malloc(sizeof(regex_t)); regcomp(self->regs[i], self->strs[i], REG_EXTENDED); } } /* after care for regex search :) */ void reg_finish(strs *self){ int i; for(i = 0; i < self->count; i++){ regfree(self->regs[i]); } free(self->regs); } /* after care for string search */ void str_finish(strs *self){ int i; for(i = 0; i < self->count; i++){ free(self->strs[i]); } free(self->strs); } void help(char* command){ fprintf(stderr, "\ Syntax:\n\ %s (-r)* (-f STRING)* (-i STRING)* (FILE)+\n\ \n\ Options:\n\ -r\n\ use regular expression when -f or -i setted.\n\ \n\ -f STRING\n\ print lines only contain STRING.\n\ \n\ -i STRING\n\ ignoring lines contained STRING.\n\ \n\ Warnings:\n\ * Won't be able to search correctly if a line contains over %d bytes.\n\ ", command, BUFFER_SIZE*sizeof(char)); }