xref: /xv6-public/grep.c (revision 7894fcd2)
11a89baa7Srsc // Simple grep.  Only supports ^ . * $ operators.
21a89baa7Srsc 
31a89baa7Srsc #include "types.h"
41a89baa7Srsc #include "stat.h"
51a89baa7Srsc #include "user.h"
61a89baa7Srsc 
71a89baa7Srsc char buf[1024];
81a89baa7Srsc int match(char*, char*);
91a89baa7Srsc 
101a89baa7Srsc void
grep(char * pattern,int fd)111a89baa7Srsc grep(char *pattern, int fd)
121a89baa7Srsc {
131a89baa7Srsc   int n, m;
141a89baa7Srsc   char *p, *q;
151a89baa7Srsc 
161a89baa7Srsc   m = 0;
17*7443b964SAustin Clements   while((n = read(fd, buf+m, sizeof(buf)-m-1)) > 0){
181a89baa7Srsc     m += n;
19*7443b964SAustin Clements     buf[m] = '\0';
201a89baa7Srsc     p = buf;
211a89baa7Srsc     while((q = strchr(p, '\n')) != 0){
221a89baa7Srsc       *q = 0;
231a89baa7Srsc       if(match(pattern, p)){
241a89baa7Srsc         *q = '\n';
251a89baa7Srsc         write(1, p, q+1 - p);
261a89baa7Srsc       }
271a89baa7Srsc       p = q+1;
281a89baa7Srsc     }
291a89baa7Srsc     if(p == buf)
301a89baa7Srsc       m = 0;
311a89baa7Srsc     if(m > 0){
321a89baa7Srsc       m -= p - buf;
331a89baa7Srsc       memmove(buf, p, m);
341a89baa7Srsc     }
351a89baa7Srsc   }
361a89baa7Srsc }
371a89baa7Srsc 
381a89baa7Srsc int
main(int argc,char * argv[])391a89baa7Srsc main(int argc, char *argv[])
401a89baa7Srsc {
411a89baa7Srsc   int fd, i;
421a89baa7Srsc   char *pattern;
431a89baa7Srsc 
441a89baa7Srsc   if(argc <= 1){
451a89baa7Srsc     printf(2, "usage: grep pattern [file ...]\n");
461a89baa7Srsc     exit();
471a89baa7Srsc   }
481a89baa7Srsc   pattern = argv[1];
491a89baa7Srsc 
501a89baa7Srsc   if(argc <= 2){
511a89baa7Srsc     grep(pattern, 0);
521a89baa7Srsc     exit();
531a89baa7Srsc   }
541a89baa7Srsc 
551a89baa7Srsc   for(i = 2; i < argc; i++){
561a89baa7Srsc     if((fd = open(argv[i], 0)) < 0){
571a89baa7Srsc       printf(1, "grep: cannot open %s\n", argv[i]);
581a89baa7Srsc       exit();
591a89baa7Srsc     }
601a89baa7Srsc     grep(pattern, fd);
611a89baa7Srsc     close(fd);
621a89baa7Srsc   }
631a89baa7Srsc   exit();
641a89baa7Srsc }
651a89baa7Srsc 
661a89baa7Srsc // Regexp matcher from Kernighan & Pike,
671a89baa7Srsc // The Practice of Programming, Chapter 9.
681a89baa7Srsc 
691a89baa7Srsc int matchhere(char*, char*);
701a89baa7Srsc int matchstar(int, char*, char*);
711a89baa7Srsc 
721a89baa7Srsc int
match(char * re,char * text)731a89baa7Srsc match(char *re, char *text)
741a89baa7Srsc {
751a89baa7Srsc   if(re[0] == '^')
761a89baa7Srsc     return matchhere(re+1, text);
771a89baa7Srsc   do{  // must look at empty string
781a89baa7Srsc     if(matchhere(re, text))
791a89baa7Srsc       return 1;
801a89baa7Srsc   }while(*text++ != '\0');
811a89baa7Srsc   return 0;
821a89baa7Srsc }
831a89baa7Srsc 
841a89baa7Srsc // matchhere: search for re at beginning of text
matchhere(char * re,char * text)851a89baa7Srsc int matchhere(char *re, char *text)
861a89baa7Srsc {
871a89baa7Srsc   if(re[0] == '\0')
881a89baa7Srsc     return 1;
891a89baa7Srsc   if(re[1] == '*')
901a89baa7Srsc     return matchstar(re[0], re+2, text);
911a89baa7Srsc   if(re[0] == '$' && re[1] == '\0')
921a89baa7Srsc     return *text == '\0';
931a89baa7Srsc   if(*text!='\0' && (re[0]=='.' || re[0]==*text))
941a89baa7Srsc     return matchhere(re+1, text+1);
951a89baa7Srsc   return 0;
961a89baa7Srsc }
971a89baa7Srsc 
981a89baa7Srsc // matchstar: search for c*re at beginning of text
matchstar(int c,char * re,char * text)991a89baa7Srsc int matchstar(int c, char *re, char *text)
1001a89baa7Srsc {
1011a89baa7Srsc   do{  // a * matches zero or more instances
1021a89baa7Srsc     if(matchhere(re, text))
1031a89baa7Srsc       return 1;
1041a89baa7Srsc   }while(*text!='\0' && (*text++==c || c=='.'));
1051a89baa7Srsc   return 0;
1061a89baa7Srsc }
1071a89baa7Srsc 
108