xref: /inferno-os/appl/cmd/grep.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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