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