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