1implement Grep; 2 3include "sys.m"; 4 sys: Sys; 5 FD: import Sys; 6 stdin, stderr, stdout: ref FD; 7 8include "draw.m"; 9 Context: import Draw; 10 11include "regex.m"; 12 regex: Regex; 13 Re: import regex; 14 15include "bufio.m"; 16 bufio: Bufio; 17 Iobuf: import bufio; 18 19include "arg.m"; 20 21 22Grep: module 23{ 24 init: fn(ctxt: ref Context, argv: list of string); 25}; 26 27multi: int; 28lflag, nflag, vflag, iflag, Lflag, sflag: int = 0; 29 30badmodule(path: string) 31{ 32 sys->fprint(stderr, "grep: cannot load %s: %r\n", path); 33 raise "fail:bad module"; 34} 35 36init(nil: ref Context, argv: list of string) 37{ 38 sys = load Sys Sys->PATH; 39 stdin = sys->fildes(0); 40 stdout = sys->fildes(1); 41 stderr = sys->fildes(2); 42 43 arg := load Arg Arg->PATH; 44 if (arg == nil) 45 badmodule(Arg->PATH); 46 47 regex = load Regex Regex->PATH; 48 if(regex == nil) 49 badmodule(Regex->PATH); 50 51 bufio = load Bufio Bufio->PATH; 52 if(bufio == nil) 53 badmodule(Bufio->PATH); 54 55 arg->init(argv); 56 while ((opt := arg->opt()) != 0) { 57 case opt { 58 'l' => 59 lflag = 1; 60 'n' => 61 nflag = 1; 62 'v' => 63 vflag = 1; 64 'i' => 65 iflag = 1; 66 'L' => 67 Lflag = 1; 68 's' => 69 sflag = 1; 70 * => 71 usage(); 72 } 73 } 74 argv = arg->argv(); 75 arg = nil; 76 77 if(argv == nil) 78 usage(); 79 pattern := hd argv; 80 argv = tl argv; 81 if (iflag) 82 pattern = tolower(pattern); 83 (re, err) := regex->compile(pattern,0); 84 if(re == nil) { 85 sys->fprint(stderr, "grep: %s\n", err); 86 raise "fail:bad regex"; 87 } 88 89 matched := 0; 90 if(argv == nil) 91 matched = grep(re, bufio->fopen(stdin, Bufio->OREAD), "stdin"); 92 else { 93 multi = (tl argv != nil); 94 for (; argv != nil; argv = tl argv) { 95 f := bufio->open(hd argv, Bufio->OREAD); 96 if(f == nil) 97 sys->fprint(stderr, "grep: cannot open %s: %r\n", hd argv); 98 else 99 matched += grep(re, f, hd argv); 100 } 101 } 102 if (!matched) 103 raise "fail:no matches"; 104} 105 106usage() 107{ 108 sys->fprint(stderr, "usage: grep [-lnviLs] pattern [file...]\n"); 109 raise "fail:usage"; 110} 111 112grep(re: Re, f: ref Iobuf, file: string): int 113{ 114 matched := 0; 115 for(line := 1; ; line++) { 116 s := t := f.gets('\n'); 117 if(s == nil) 118 break; 119 if (iflag) 120 s = tolower(s); 121 if((regex->executese(re, s, (0, len s-1), 1, 1) != nil) ^ vflag) { 122 matched = 1; 123 if(lflag || sflag) { 124 if (!sflag) 125 sys->print("%s\n", file); 126 return matched; 127 } 128 if (!Lflag) { 129 if(nflag) 130 if(multi) 131 sys->print("%s:%d: %s", file, line, t); 132 else 133 sys->print("%d:%s", line, t); 134 else 135 if(multi) 136 sys->print("%s: %s", file, t); 137 else 138 sys->print("%s", t); 139 } 140 } 141 } 142 if (Lflag && matched == 0 && !sflag) 143 sys->print("%s\n", file); 144 return matched; 145} 146 147tolower(s: string): string 148{ 149 for (i := 0; i < len s; i++) { 150 c := s[i]; 151 if (c >= 'A' && c <= 'Z') 152 s[i] = c - 'A' + 'a'; 153 } 154 return s; 155} 156