diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | grep.c | 106 | 
2 files changed, 108 insertions, 0 deletions
| @@ -93,7 +93,9 @@ mkfs: mkfs.c fs.h  UPROGS=\  	_cat\ +	_echo\  	_forktest\ +	_grep\  	_init\  	_kill\  	_ln\ @@ -0,0 +1,106 @@ +// Simple grep.  Only supports ^ . * $ operators. + +#include "types.h" +#include "stat.h" +#include "user.h" + +char buf[1024]; +int match(char*, char*); + +void +grep(char *pattern, int fd) +{ +  int n, m; +  char *p, *q; +   +  m = 0; +  while((n = read(fd, buf+m, sizeof(buf)-m)) > 0){ +    m += n; +    p = buf; +    while((q = strchr(p, '\n')) != 0){ +      *q = 0; +      if(match(pattern, p)){ +        *q = '\n'; +        write(1, p, q+1 - p); +      } +      p = q+1; +    } +    if(p == buf) +      m = 0; +    if(m > 0){ +      m -= p - buf; +      memmove(buf, p, m); +    } +  } +} + +int +main(int argc, char *argv[]) +{ +  int fd, i; +  char *pattern; +   +  if(argc <= 1){ +    printf(2, "usage: grep pattern [file ...]\n"); +    exit(); +  } +  pattern = argv[1]; +   +  if(argc <= 2){ +    grep(pattern, 0); +    exit(); +  } + +  for(i = 2; i < argc; i++){ +    if((fd = open(argv[i], 0)) < 0){ +      printf(1, "grep: cannot open %s\n", argv[i]); +      exit(); +    } +    grep(pattern, fd); +    close(fd); +  } +  exit(); +} + +// Regexp matcher from Kernighan & Pike, +// The Practice of Programming, Chapter 9. + +int matchhere(char*, char*); +int matchstar(int, char*, char*); + +int +match(char *re, char *text) +{ +  if(re[0] == '^') +    return matchhere(re+1, text); +  do{  // must look at empty string +    if(matchhere(re, text)) +      return 1; +  }while(*text++ != '\0'); +  return 0; +} + +// matchhere: search for re at beginning of text +int matchhere(char *re, char *text) +{ +  if(re[0] == '\0') +    return 1; +  if(re[1] == '*') +    return matchstar(re[0], re+2, text); +  if(re[0] == '$' && re[1] == '\0') +    return *text == '\0'; +  if(*text!='\0' && (re[0]=='.' || re[0]==*text)) +    return matchhere(re+1, text+1); +  return 0; +} + +// matchstar: search for c*re at beginning of text +int matchstar(int c, char *re, char *text) +{ +  do{  // a * matches zero or more instances +    if(matchhere(re, text)) +      return 1; +  }while(*text!='\0' && (*text++==c || c=='.')); +  return 0; +} + | 
