summaryrefslogtreecommitdiff
path: root/appl/cmd/grep.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/grep.b')
-rw-r--r--appl/cmd/grep.b155
1 files changed, 155 insertions, 0 deletions
diff --git a/appl/cmd/grep.b b/appl/cmd/grep.b
new file mode 100644
index 00000000..d534de3b
--- /dev/null
+++ b/appl/cmd/grep.b
@@ -0,0 +1,155 @@
+implement Grep;
+
+include "sys.m";
+ sys: Sys;
+ FD: import Sys;
+ stdin, stderr, stdout: ref FD;
+
+include "draw.m";
+ Context: import Draw;
+
+include "regex.m";
+ regex: Regex;
+ Re: import regex;
+
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+
+include "arg.m";
+
+
+Grep: module
+{
+ init: fn(ctxt: ref Context, argv: list of string);
+};
+
+multi: int;
+lflag, nflag, vflag, iflag, Lflag, sflag: int = 0;
+
+badmodule(path: string)
+{
+ sys->fprint(stderr, "grep: cannot load %s: %r\n", path);
+ raise "fail:bad module";
+}
+
+init(nil: ref Context, argv: list of string)
+{
+ sys = load Sys Sys->PATH;
+ stdin = sys->fildes(0);
+ stdout = sys->fildes(1);
+ stderr = sys->fildes(2);
+
+ arg := load Arg Arg->PATH;
+ if (arg == nil)
+ badmodule(Arg->PATH);
+
+ regex = load Regex Regex->PATH;
+ if(regex == nil)
+ badmodule(Regex->PATH);
+
+ bufio = load Bufio Bufio->PATH;
+ if(bufio == nil)
+ badmodule(Bufio->PATH);
+
+ arg->init(argv);
+ while ((opt := arg->opt()) != 0) {
+ case opt {
+ 'l' =>
+ lflag = 1;
+ 'n' =>
+ nflag = 1;
+ 'v' =>
+ vflag = 1;
+ 'i' =>
+ iflag = 1;
+ 'L' =>
+ Lflag = 1;
+ 's' =>
+ sflag = 1;
+ * =>
+ usage();
+ }
+ }
+ argv = arg->argv();
+ arg = nil;
+
+ if(argv == nil)
+ usage();
+ pattern := hd argv;
+ argv = tl argv;
+ if (iflag)
+ pattern = tolower(pattern);
+ (re, err) := regex->compile(pattern,0);
+ if(re == nil) {
+ sys->fprint(stderr, "grep: %s\n", err);
+ raise "fail:bad regex";
+ }
+
+ matched := 0;
+ if(argv == nil)
+ matched = grep(re, bufio->fopen(stdin, Bufio->OREAD), "stdin");
+ else {
+ multi = (tl argv != nil);
+ for (; argv != nil; argv = tl argv) {
+ f := bufio->open(hd argv, Bufio->OREAD);
+ if(f == nil)
+ sys->fprint(stderr, "grep: cannot open %s: %r\n", hd argv);
+ else
+ matched += grep(re, f, hd argv);
+ }
+ }
+ if (!matched)
+ raise "fail:no matches";
+}
+
+usage()
+{
+ sys->fprint(stderr, "usage: grep [-lnviLs] pattern [file...]\n");
+ raise "fail:usage";
+}
+
+grep(re: Re, f: ref Iobuf, file: string): int
+{
+ matched := 0;
+ for(line := 1; ; line++) {
+ s := t := f.gets('\n');
+ if(s == nil)
+ break;
+ if (iflag)
+ s = tolower(s);
+ if((regex->executese(re, s, (0, len s-1), 1, 1) != nil) ^ vflag) {
+ matched = 1;
+ if(lflag || sflag) {
+ if (!sflag)
+ sys->print("%s\n", file);
+ return matched;
+ }
+ if (!Lflag) {
+ if(nflag)
+ if(multi)
+ sys->print("%s:%d: %s", file, line, t);
+ else
+ sys->print("%d:%s", line, t);
+ else
+ if(multi)
+ sys->print("%s: %s", file, t);
+ else
+ sys->print("%s", t);
+ }
+ }
+ }
+ if (Lflag && matched == 0 && !sflag)
+ sys->print("%s\n", file);
+ return matched;
+}
+
+tolower(s: string): string
+{
+ for (i := 0; i < len s; i++) {
+ c := s[i];
+ if (c >= 'A' && c <= 'Z')
+ s[i] = c - 'A' + 'a';
+ }
+ return s;
+}