xref: /xv6-public/grep.c (revision 1a89baa7)
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