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