#include #include #include #include #include #include #include #include #include typedef unsigned char UCHAR; typedef unsigned char* UCHARP; typedef enum BOOL { FALSE = 0, TRUE = 1 } BOOL; typedef struct ENV { BOOL print_count; BOOL print_filename; int count; char *filename; jmp_buf *ret; } *ENVP; __code filter(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code predict(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code reject(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code accept(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); void s0(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code _s0(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); #define __REGEX__ "h.c" UCHARP get_line_beg(UCHARP p, UCHARP beg) { while(p > beg) { if ((*--p) == '\n') return p+1; } return beg; } void print_line(UCHARP beg, UCHARP end) { fwrite(beg, sizeof(char), (end - beg + 1), stdout); } void grep(int fd, ENVP env) { caddr_t file_mmap; UCHARP buf, end, beg; off_t size; struct stat sb; if (fstat(fd, &sb)) { fprintf(stderr, "can't fstat %s\n", env->filename); exit(0); } size = sb.st_size; file_mmap = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, (off_t)0); if (file_mmap == (caddr_t)-1) { fprintf(stderr, "can't mmap %s\n", env->filename); exit(0); } beg = buf = (UCHARP) file_mmap; end = beg + size - 1; env->count = 0; s0(beg, beg, end, env); munmap(file_mmap, size); return; } void stdingrep(ENVP env) { char buf_[BUFSIZ]; UCHARP buf, beg, end; buf = beg = (UCHARP) buf_; while (fgets(buf_, BUFSIZ, stdin) != NULL) { env->count = 0; end = buf + strlen(buf_) - 1; s0(beg, buf, end, env); } } int main(int argc, char* argv[]) { int i, fd, opt, with_filename = 0; ENVP env = (ENVP)calloc(sizeof(ENVP), 1); while ((opt=getopt(argc, argv, "chH")) != -1) { switch (opt) { case 'c': env->print_count = 1; break; case 'h': with_filename = -1; break; case 'H': with_filename = 1; break; default: fprintf(stderr, "invalid option."); exit(0); } } if (optind == argc) { if (with_filename) { /* handle -h/-H as help */ printf("grep pattern: %s\n", __REGEX__); exit(1); } else { stdingrep(env); } } else { switch (with_filename) { case 0: //default if (argc == optind + 1) { /* just grep 1 file. */ env->print_filename = FALSE; } else { /* grep 1 more files. */ env->print_filename = TRUE; } break; // option case -1: env->print_filename = FALSE; break; case 1: env->print_filename = TRUE; break; default: break; } for (i = optind; i < argc; i++) { fd = open(argv[i], O_RDONLY, 0666); if (fd == 0) { printf("%d, %s\n", i, argv[i]); fprintf(stderr, "can't open %s:", argv[i]); continue; } env->filename = argv[i]; grep(fd, env); close(fd); } } return 0; } __code s1(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code s2(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code s3(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code s4(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code s5(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); __code s6(UCHARP beg, UCHARP buf, UCHARP end, ENVP env); void s0(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { env->ret = (jmp_buf *)malloc(sizeof(int)*100); // allocate dumy fields. for protect real ret addres. env->ret = (jmp_buf *)malloc(sizeof(jmp_buf)); if (env == NULL) { fprintf(stderr, "can't allocate jmp_buf"); exit(0); } int ret; if ((ret = setjmp(env->ret)) == 0) { goto _s0(beg, buf, end, env); } //free(env->ret); danger! return; } __code _s0(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { goto filter(beg, buf, end, env); } __code filter(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { static const UCHARP const key = (UCHARP)"h"; int i, len = 1; loop: while ((buf = memchr(buf, key[0], end-buf))) { for (i = 1; i < len; i++) { if (buf[i] != key[i]) { buf++; goto loop; } } goto next; } buf = end; goto reject(beg, buf, end, env); next: goto s1(beg, buf, end, env); } __code s1(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { static __code (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s1, /* NL */ [10] = (void*)reject, /* h */ [104] = (void*)s2}; if (buf > end) goto tbl['\n'](beg, buf, end, env); goto tbl[*buf++](beg, buf, end, env); } __code s2(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { static __code (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s3, /* NL */ [10] = (void*)reject, /* h */ [104] = (void*)s4}; if (buf > end) goto tbl['\n'](beg, buf, end, env); goto tbl[*buf++](beg, buf, end, env); } __code s3(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { static __code (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s1, /* NL */ [10] = (void*)reject, /* c */ [99] = (void*)s5, /* h */ [104] = (void*)s2}; if (buf > end) goto tbl['\n'](beg, buf, end, env); goto tbl[*buf++](beg, buf, end, env); } __code s4(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { static __code (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s3, /* NL */ [10] = (void*)reject, /* c */ [99] = (void*)s6, /* h */ [104] = (void*)s4}; if (buf > end) goto tbl['\n'](beg, buf, end, env); goto tbl[*buf++](beg, buf, end, env); } __code s5(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { goto accept(beg, buf - 1, end, env); } __code s6(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { goto accept(beg, buf - 1, end, env); } __code accept(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { UCHARP ret = (buf < end) ? (UCHARP) memchr(buf, '\n', (end - buf)) : NULL; if (env->print_count) { env->count++; if (ret == NULL) { if (env->print_filename) { printf("%s:", env->filename); } printf("%d\n", env->count); longjmp(env->ret, 1); } beg = buf = ret + 1; } else { beg = get_line_beg(buf, beg); if (env->print_filename) { printf("%s:", env->filename); } if (ret == NULL) { print_line(beg, end); longjmp(env->ret, 1); } print_line(beg, ret); beg = buf = ret + 1; } goto _s0(beg, buf, end, env); } __code reject(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) { if (buf >= end) { if (env->print_count) { if (env->print_filename) { printf("%s:", env->filename); } printf("%d\n", env->count); } longjmp(env->ret, 1); } beg = buf; goto _s0(beg, buf, end, env); }