ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/test.b/
implement Test;
#
# venerable
# test expression
#
include "sys.m";
sys: Sys;
stderr: ref Sys->FD;
include "draw.m";
include "daytime.m";
daytime: Daytime;
Test: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
gargs: list of string;
init(nil: ref Draw->Context, args: list of string)
{
if(args == nil)
return;
gargs = tl args;
sys = load Sys Sys->PATH;
stderr = sys->fildes(2);
if(gargs == nil)
raise "fail:usage";
if(!e())
raise "fail:false";
}
nextarg(mt: int): string
{
if(gargs == nil){
if(mt)
return nil;
synbad("argument expected");
}
s := hd gargs;
gargs = tl gargs;
return s;
}
nextintarg(): (int, int)
{
if(gargs != nil && isint(hd gargs))
return (1, int nextarg(0));
return (0, 0);
}
isnextarg(s: string): int
{
if(gargs != nil && hd gargs == s){
gargs = tl gargs;
return 1;
}
return 0;
}
e(): int
{
p1 := e1();
if(isnextarg("-o"))
return p1 || e();
return p1;
}
e1(): int
{
p1 := e2();
if(isnextarg("-a"))
return p1 && e1();
return p1;
}
e2(): int
{
if(isnextarg("!"))
return !e2();
return e3();
}
e3(): int
{
a := nextarg(0);
case a {
"(" =>
p1 := e();
if(nextarg(0) != ")")
synbad(") expected");
return p1;
"-A" =>
return hasmode(nextarg(0), Sys->DMAPPEND);
"-L" =>
return hasmode(nextarg(0), Sys->DMEXCL);
"-T" =>
return hasmode(nextarg(0), Sys->DMTMP);
"-f" =>
f := nextarg(0);
return exists(f) && !hasmode(f, Sys->DMDIR);
"-d" =>
return hasmode(nextarg(0), Sys->DMDIR);
"-r" =>
return sys->open(nextarg(0), Sys->OREAD) != nil;
"-w" =>
return sys->open(nextarg(0), Sys->OWRITE) != nil;
"-x" =>
fd := sys->open(nextarg(0), Sys->OREAD);
if(fd == nil)
return 0;
(ok, d) := sys->fstat(fd);
if(ok < 0)
return 0;
return (d.mode & 8r111) != 0;
"-e" =>
return exists(nextarg(0));
"-s" =>
(ok, d) := sys->stat(nextarg(0));
if(ok < 0)
return 0;
return d.length > big 0;
"-t" =>
(ok, fd) := nextintarg();
if(!ok)
return iscons(1);
return iscons(fd);
"-n" =>
return nextarg(0) != "";
"-z" =>
return nextarg(0) == "";
* =>
p2 := nextarg(1);
if(p2 == nil)
return a != nil;
case p2 {
"=" =>
return nextarg(0) == a;
"!=" =>
return nextarg(0) != a;
"-older" =>
return isolder(nextarg(0), a);
"-ot" =>
return isolderthan(a, nextarg(0));
"-nt" =>
return isnewerthan(a, nextarg(0));
}
if(!isint(a))
return a != nil;
int1 := int a;
(ok, int2) := nextintarg();
if(ok){
case p2 {
"-eq" =>
return int1 == int2;
"-ne" =>
return int1 != int2;
"-gt" =>
return int1 > int2;
"-lt" =>
return int1 < int2;
"-ge" =>
return int1 >= int2;
"-le" =>
return int1 <= int2;
}
}
synbad("unknown operator " + p2);
return 0;
}
}
synbad(s: string)
{
sys->fprint(stderr, "test: bad syntax: %s\n", s);
raise "fail:bad syntax";
}
isint(s: string): int
{
if(s == nil)
return 0;
for(i := 0; i < len s; i++)
if(s[i] < '0' || s[i] > '9')
return 0;
return 1;
}
exists(f: string): int
{
return sys->stat(f).t0 >= 0;
}
hasmode(f: string, m: int): int
{
(ok, d) := sys->stat(f);
if(ok < 0)
return 0;
return (d.mode & m) != 0;
}
iscons(fno: int): int
{
fd := sys->fildes(fno);
if(fd == nil)
return 0;
s := sys->fd2path(fd);
n := len "/dev/cons";
return s == "#c/cons" || len s >= n && s[len s-n:] == "/dev/cons";
}
isolder(t: string, f: string): int
{
(ok, dir) := sys->stat(f);
if(ok < 0)
return 0;
n := 0;
for(i := 0; i < len t;){
for(j := i; j < len t; j++)
if(!(t[j] >= '0' && t[j] <= '9'))
break;
if(i == j)
synbad("bad time syntax, "+t);
m := int t[i:j];
i = j;
if(i == len t){
n = m;
break;
}
case t[i++] {
'y' => n += m*12*30*24*3600;
'M' => n += m*30*24*3600;
'd' => n += m*24*3600;
'h' => n += m*3600;
'm' => n += m*60;
's' => n += m;
* => synbad("bad time syntax, "+t);
}
}
return dir.mtime+n < now();
}
isolderthan(a: string, b: string): int
{
(aok, ad) := sys->stat(a);
if(aok < 0)
return 0;
(bok, bd) := sys->stat(b);
if(bok < 0)
return 0;
return ad.mtime < bd.mtime;
}
isnewerthan(a: string, b: string): int
{
(aok, ad) := sys->stat(a);
if(aok < 0)
return 0;
(bok, bd) := sys->stat(b);
if(bok < 0)
return 0;
return ad.mtime > bd.mtime;
}
now(): int
{
if(daytime == nil){
daytime = load Daytime Daytime->PATH;
if(daytime == nil)
synbad(sys->sprint("can't load %s: %r", Daytime->PATH));
}
return daytime->now();
}