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