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-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 |
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 |
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 |
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 |
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 | |