1// Simple grep. Only supports ^ . * $ operators.
2
3#include "types.h"
4#include "stat.h"
5#include "user.h"
6
7char buf[1024];
8int match(char*, char*);
9
10void
11grep(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
38int
39main(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
69int matchhere(char*, char*);
70int matchstar(int, char*, char*);
71
72int
73match(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
85int 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
99int 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