view regen/src/grep/grep_jobs.c_back @ 12:a6f51c76dea8

add grep.c
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 28 Jun 2011 16:25:37 +0900
parents
children
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

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;
} *ENVP;

void filter(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void predict(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void reject(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void accept(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void s0(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
#define __REGEX__ "h.s"

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;
}
void s1(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void s2(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void s3(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void s4(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void s5(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);
void s6(UCHARP beg, UCHARP buf, UCHARP end, ENVP env);

void s0(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  return filter(beg, buf, end, env);
}

void 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;
  }
  return reject(beg, end, end, env);
next:
  return s1(beg, buf, end, env);
}

void s1(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  static void (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s1, /* NL */ [10] = (void*)reject, /* h */ [104] = (void*)s2};
  if (buf > end) return tbl['\n'](beg, buf, end, env);
  return tbl[*buf++](beg, buf, end, env);
}

void s2(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  static void (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s3, /* NL */ [10] = (void*)reject, /* h */ [104] = (void*)s4};
  if (buf > end) return tbl['\n'](beg, buf, end, env);
  return tbl[*buf++](beg, buf, end, env);
}

void s3(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  static void (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s1, /* NL */ [10] = (void*)reject, /* h */ [104] = (void*)s2, /* s */ [115] = (void*)s5};
  if (buf > end) return tbl['\n'](beg, buf, end, env);
  return tbl[*buf++](beg, buf, end, env);
}

void s4(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  static void (*tbl[256])(UCHARP, UCHARP, UCHARP, ENVP) = {[0 ... 255] = (void*)s3, /* NL */ [10] = (void*)reject, /* h */ [104] = (void*)s4, /* s */ [115] = (void*)s6};
  if (buf > end) return tbl['\n'](beg, buf, end, env);
  return tbl[*buf++](beg, buf, end, env);
}

void s5(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  return accept(beg, buf - 1, end, env);}

void s6(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  return accept(beg, buf - 1, end, env);}

void
accept(UCHARP beg, UCHARP buf, UCHARP end, ENVP env)
{
  if (buf < beg) buf = beg;
  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);
      return;
    }
    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);
      return;
    }
    print_line(beg, ret);
    beg = buf = ret + 1;
  }
  return s0(beg, buf, end, env);
}

void
reject(UCHARP beg, UCHARP buf, UCHARP end, ENVP env) {
  UCHARP ret;
  if (buf >= end) {
    ret = NULL;
  } else {
    if (*(buf-1) == '\n') {
      ret = buf-1;
    } else {
      ret = (UCHARP)memchr(buf, '\n', (end - buf));
    }
  }
  if (ret == NULL) {
    if (env->print_count) {
      if (env->print_filename) {
        printf("%s:", env->filename);
      }
      printf("%d\n", env->count);
    }
    return;
  }
  beg = buf = ret + 1;
  return s0(beg, buf, end, env);
}