grep.c (1939B)
1 // Simple grep. Only supports ^ . * $ operators. 2 3 #include "types.h" 4 #include "stat.h" 5 #include "user.h" 6 7 char buf[1024]; 8 int match(char*, char*); 9 10 void 11 grep(char *pattern, int fd) 12 { 13 int n, m; 14 char *p, *q; 15 16 m = 0; 17 while((n = read(fd, buf+m, sizeof(buf)-m)) > 0){ 18 m += n; 19 p = buf; 20 while((q = strchr(p, '\n')) != 0){ 21 *q = 0; 22 if(match(pattern, p)){ 23 *q = '\n'; 24 write(1, p, q+1 - p); 25 } 26 p = q+1; 27 } 28 if(p == buf) 29 m = 0; 30 if(m > 0){ 31 m -= p - buf; 32 memmove(buf, p, m); 33 } 34 } 35 } 36 37 int 38 main(int argc, char *argv[]) 39 { 40 int fd, i; 41 char *pattern; 42 43 if(argc <= 1){ 44 printf(2, "usage: grep pattern [file ...]\n"); 45 exit(); 46 } 47 pattern = argv[1]; 48 49 if(argc <= 2){ 50 grep(pattern, 0); 51 exit(); 52 } 53 54 for(i = 2; i < argc; i++){ 55 if((fd = open(argv[i], 0)) < 0){ 56 printf(1, "grep: cannot open %s\n", argv[i]); 57 exit(); 58 } 59 grep(pattern, fd); 60 close(fd); 61 } 62 exit(); 63 } 64 65 // Regexp matcher from Kernighan & Pike, 66 // The Practice of Programming, Chapter 9. 67 68 int matchhere(char*, char*); 69 int matchstar(int, char*, char*); 70 71 int 72 match(char *re, char *text) 73 { 74 if(re[0] == '^') 75 return matchhere(re+1, text); 76 do{ // must look at empty string 77 if(matchhere(re, text)) 78 return 1; 79 }while(*text++ != '\0'); 80 return 0; 81 } 82 83 // matchhere: search for re at beginning of text 84 int matchhere(char *re, char *text) 85 { 86 if(re[0] == '\0') 87 return 1; 88 if(re[1] == '*') 89 return matchstar(re[0], re+2, text); 90 if(re[0] == '$' && re[1] == '\0') 91 return *text == '\0'; 92 if(*text!='\0' && (re[0]=='.' || re[0]==*text)) 93 return matchhere(re+1, text+1); 94 return 0; 95 } 96 97 // matchstar: search for c*re at beginning of text 98 int matchstar(int c, char *re, char *text) 99 { 100 do{ // a * matches zero or more instances 101 if(matchhere(re, text)) 102 return 1; 103 }while(*text!='\0' && (*text++==c || c=='.')); 104 return 0; 105 } 106