annotate src/usr/grep.c @ 0:53676d1f5817 default tip

firsh commit
author tobaru
date Sun, 04 Feb 2018 17:54:49 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
1 // Simple grep. Only supports ^ . * $ operators.
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
2
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
3 #include "types.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
4 #include "stat.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
5 #include "user.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
6
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
7 char buf[1024];
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
8 int match(char*, char*);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
9
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
10 void
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
11 grep(char *pattern, int fd)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
12 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
13 int n, m;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
14 char *p, *q;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
15
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
16 m = 0;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
17 while((n = read(fd, buf+m, sizeof(buf)-m)) > 0){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
18 m += n;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
19 p = buf;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
20 while((q = strchr(p, '\n')) != 0){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
21 *q = 0;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
22 if(match(pattern, p)){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
23 *q = '\n';
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
24 write(1, p, q+1 - p);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
25 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
26 p = q+1;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
27 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
28 if(p == buf)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
29 m = 0;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
30 if(m > 0){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
31 m -= p - buf;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
32 memmove(buf, p, m);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
33 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
34 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
35 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
36
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
37 int
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
38 main(int argc, char *argv[])
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
39 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
40 int fd, i;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
41 char *pattern;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
42
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
43 if(argc <= 1){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
44 printf(2, "usage: grep pattern [file ...]\n");
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
45 exit();
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
46 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
47 pattern = argv[1];
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
48
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
49 if(argc <= 2){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
50 grep(pattern, 0);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
51 exit();
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
52 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
53
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
54 for(i = 2; i < argc; i++){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
55 if((fd = open(argv[i], 0)) < 0){
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
56 printf(1, "grep: cannot open %s\n", argv[i]);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
57 exit();
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
58 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
59 grep(pattern, fd);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
60 close(fd);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
61 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
62 exit();
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
63 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
64
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
65 // Regexp matcher from Kernighan & Pike,
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
66 // The Practice of Programming, Chapter 9.
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
67
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
68 int matchhere(char*, char*);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
69 int matchstar(int, char*, char*);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
70
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
71 int
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
72 match(char *re, char *text)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
73 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
74 if(re[0] == '^')
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
75 return matchhere(re+1, text);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
76 do{ // must look at empty string
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
77 if(matchhere(re, text))
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
78 return 1;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
79 }while(*text++ != '\0');
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
80 return 0;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
81 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
82
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
83 // matchhere: search for re at beginning of text
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
84 int matchhere(char *re, char *text)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
85 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
86 if(re[0] == '\0')
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
87 return 1;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
88 if(re[1] == '*')
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
89 return matchstar(re[0], re+2, text);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
90 if(re[0] == '$' && re[1] == '\0')
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
91 return *text == '\0';
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
92 if(*text!='\0' && (re[0]=='.' || re[0]==*text))
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
93 return matchhere(re+1, text+1);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
94 return 0;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
95 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
96
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
97 // matchstar: search for c*re at beginning of text
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
98 int matchstar(int c, char *re, char *text)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
99 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
100 do{ // a * matches zero or more instances
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
101 if(matchhere(re, text))
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
102 return 1;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
103 }while(*text!='\0' && (*text++==c || c=='.'));
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
104 return 0;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
105 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
106