summaryrefslogtreecommitdiff
path: root/appl/acme/util.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/acme/util.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/acme/util.b')
-rw-r--r--appl/acme/util.b574
1 files changed, 574 insertions, 0 deletions
diff --git a/appl/acme/util.b b/appl/acme/util.b
new file mode 100644
index 00000000..b2930c35
--- /dev/null
+++ b/appl/acme/util.b
@@ -0,0 +1,574 @@
+implement Utils;
+
+include "common.m";
+include "sh.m";
+include "env.m";
+
+sys : Sys;
+draw : Draw;
+gui : Gui;
+acme : Acme;
+dat : Dat;
+graph : Graph;
+textm : Textm;
+windowm : Windowm;
+columnm : Columnm;
+rowm : Rowm;
+scrl : Scroll;
+look : Look;
+
+RELEASECOPY : import acme;
+Point, Rect : import draw;
+Astring, TRUE, FALSE, Mntdir, Lock : import dat;
+mouse, activecol, seltext, row : import dat;
+cursorset : import graph;
+mainwin : import gui;
+Text : import textm;
+Window : import windowm;
+Column : import columnm;
+Row : import rowm;
+
+init(mods : ref Dat->Mods)
+{
+ sys = mods.sys;
+ draw = mods.draw;
+ gui = mods.gui;
+ acme = mods.acme;
+ dat = mods.dat;
+ graph = mods.graph;
+ textm = mods.textm;
+ windowm = mods.windowm;
+ columnm = mods.columnm;
+ rowm = mods.rowm;
+ scrl = mods.scroll;
+ look = mods.look;
+
+ stderr = sys->fildes(2);
+}
+
+min(x : int, y : int) : int
+{
+ if (x < y)
+ return x;
+ return y;
+}
+
+max(x : int, y : int) : int
+{
+ if (x > y)
+ return x;
+ return y;
+}
+
+abs(x : int) : int
+{
+ if (x < 0)
+ return -x;
+ return x;
+}
+
+isalnum(c : int) : int
+{
+ #
+ # Hard to get absolutely right. Use what we know about ASCII
+ # and assume anything above the Latin control characters is
+ # potentially an alphanumeric.
+ #
+ if(c <= ' ')
+ return FALSE;
+ if(16r7F<=c && c<=16rA0)
+ return FALSE;
+ if(strchr("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c) >= 0)
+ return FALSE;
+ return TRUE;
+ # return ('a' <= c && c <= 'z') ||
+ # ('A' <= c && c <= 'Z') ||
+ # ('0' <= c && c <= '9');
+}
+
+strchr(s : string, c : int) : int
+{
+ for (i := 0; i < len s; i++)
+ if (s[i] == c)
+ return i;
+ return -1;
+}
+
+strrchr(s : string, c : int) : int
+{
+ for (i := len s - 1; i >= 0; i--)
+ if (s[i] == c)
+ return i;
+ return -1;
+}
+
+strncmp(s, t : string, n : int) : int
+{
+ if (len s > n)
+ s = s[0:n];
+ if (len t > n)
+ t = t[0:n];
+ if (s < t)
+ return -1;
+ if (s > t)
+ return 1;
+ return 0;
+}
+
+env : Env;
+
+getenv(s : string) : string
+{
+ if (env == nil)
+ env = load Env Env->PATH;
+ e := env->getenv(s);
+ if(e != nil && e[len e - 1] == '\n') # shell bug
+ return e[0: len e -1];
+ return e;
+}
+
+setenv(s, t : string)
+{
+ if (env == nil)
+ env = load Env Env->PATH;
+ env->setenv(s, t);
+}
+
+stob(s : string, n : int) : array of byte
+{
+ b := array[2*n] of byte;
+ for (i := 0; i < n; i++) {
+ b[2*i] = byte (s[i]&16rff);
+ b[2*i+1] = byte ((s[i]>>8)&16rff);
+ }
+ return b;
+}
+
+btos(b : array of byte, s : ref Astring)
+{
+ n := (len b)/2;
+ for (i := 0; i < n; i++)
+ s.s[i] = int b[2*i] | ((int b[2*i+1])<<8);
+}
+
+reverse(ol : list of string) : list of string
+{
+ nl : list of string;
+
+ nl = nil;
+ while (ol != nil) {
+ nl = hd ol :: nl;
+ ol = tl ol;
+ }
+ return nl;
+}
+
+nextarg(p : ref Arg) : int
+{
+ bp : string;
+
+ if(p.av != nil){
+ bp = hd p.av;
+ if(bp != nil && bp[0] == '-'){
+ p.p = bp[1:];
+ p.av = tl p.av;
+ return 1;
+ }
+ }
+ p.p = nil;
+ return 0;
+}
+
+arginit(av : list of string) : ref Arg
+{
+ p : ref Arg;
+
+ p = ref Arg;
+ p.arg0 = hd av;
+ p.av = tl av;
+ nextarg(p);
+ return p;
+}
+
+argopt(p : ref Arg) : int
+{
+ r : int;
+
+ if(p.p == nil && nextarg(p) == 0)
+ return 0;
+ r = p.p[0];
+ p.p = p.p[1:];
+ return r;
+}
+
+argf(p : ref Arg) : string
+{
+ bp : string;
+
+ if(p.p != nil){
+ bp = p.p;
+ p.p = nil;
+ } else if(p.av != nil){
+ bp = hd p.av;
+ p.av = tl p.av;
+ } else
+ bp = nil;
+ return bp;
+}
+
+exec(cmd : string, argl : list of string)
+{
+ file := cmd;
+ if(len file<4 || file[len file-4:]!=".dis")
+ file += ".dis";
+
+ c := load Command file;
+ if(c == nil) {
+ err := sys->sprint("%r");
+ if(file[0]!='/' && file[0:2]!="./"){
+ c = load Command "/dis/"+file;
+ if(c == nil)
+ err = sys->sprint("%r");
+ }
+ if(c == nil){
+ # debug(sys->sprint("file %s not found\n", file));
+ sys->fprint(stderr, "%s: %s\n", cmd, err);
+ return;
+ }
+ }
+ c->init(acme->acmectxt, argl);
+}
+
+getuser() : string
+{
+ fd := sys->open("/dev/user", sys->OREAD);
+ if(fd == nil)
+ return "";
+
+ buf := array[128] of byte;
+ n := sys->read(fd, buf, len buf);
+ if(n < 0)
+ return "";
+
+ return string buf[0:n];
+}
+
+gethome(usr : string) : string
+{
+ if (usr == nil)
+ usr = "tmp";
+ return "/usr/" + usr;
+}
+
+postnote(t : int, this : int, pid : int, note : string) : int
+{
+ if (pid == this || pid == 0)
+ return 0;
+ # fd := sys->open("/prog/" + string pid + "/ctl", sys->OWRITE);
+ fd := sys->open("#p/" + string pid + "/ctl", sys->OWRITE);
+ if (fd == nil)
+ return -1;
+ if (t == PNGROUP)
+ note += "grp";
+ sys->fprint(fd, "%s", note);
+ fd = nil;
+ return 0;
+}
+
+error(s : string)
+{
+ sys->fprint(stderr, "acme: %s: %r\n", s);
+ debug(sys->sprint("error %s : %r\n", s));
+ # s[-1] = 0; # create broken process for debugging
+ acme->acmeexit("error");
+}
+
+dlock : ref Lock;
+dfd : ref Sys->FD;
+
+debuginit()
+{
+ if (RELEASECOPY)
+ return;
+ dfd = sys->create("./debug", Sys->OWRITE, 8r600);
+ # fd = nil;
+ dlock = Lock.init();
+}
+
+debugpr(s : string)
+{
+ if (RELEASECOPY)
+ return;
+ # fd := sys->open("./debug", Sys->OWRITE);
+ # sys->seek(fd, big 0, Sys->SEEKEND);
+ sys->fprint(dfd, "%s", s);
+ # fd = nil;
+}
+
+debug(s : string)
+{
+ if (RELEASECOPY)
+ return;
+ if (dfd == nil)
+ return;
+ dlock.lock();
+ debugpr(s);
+ dlock.unlock();
+}
+
+memfd : ref Sys->FD;
+memb : array of byte;
+
+memdebug(s : string)
+{
+ if (RELEASECOPY)
+ return;
+ dlock.lock();
+ if (memfd == nil) {
+ sys->bind("#c", "/usr/jrf/mnt", Sys->MBEFORE);
+ memfd = sys->open("/usr/jrf/mnt/memory", Sys->OREAD);
+ memb = array[1024] of byte;
+ }
+ sys->seek(memfd, big 0, 0);
+ n := sys->read(memfd, memb, len memb);
+ if (n <= 0) {
+ dlock.unlock();
+ debug(sys->sprint("bad read %r\n"));
+ return;
+ }
+ s = s + " : " + string memb[0:n] + "\n";
+ dlock.unlock();
+ debug(s);
+ s = nil;
+}
+
+rgetc(s : string, n : int) : int
+{
+ if (n < 0 || n >= len s)
+ return 0;
+ return s[n];
+}
+
+tgetc(t : ref Text, n : int) : int
+{
+ if(n >= t.file.buf.nc)
+ return 0;
+ return t.readc(n);
+}
+
+skipbl(r : string, n : int) : (string, int)
+{
+ i : int = 0;
+
+ while(n>0 && (r[i]==' ' || r[i]=='\t' || r[i]=='\n')){
+ --n;
+ i++;
+ }
+ return (r[i:], n);
+}
+
+findbl(r : string, n : int) : (string, int)
+{
+ i : int = 0;
+
+ while(n>0 && r[i]!=' ' && r[i]!='\t' && r[i]!='\n'){
+ --n;
+ i++;
+ }
+ return (r[i:], n);
+}
+
+prevmouse : Point;
+mousew : ref Window;
+
+savemouse(w : ref Window)
+{
+ prevmouse = mouse.xy;
+ mousew = w;
+}
+
+restoremouse(w : ref Window)
+{
+ if(mousew!=nil && mousew==w)
+ cursorset(prevmouse);
+ mousew = nil;
+}
+
+clearmouse()
+{
+ mousew = nil;
+}
+
+#
+# Heuristic city.
+#
+newwindow(t : ref Text) : ref Window
+{
+ c : ref Column;
+ w, bigw, emptyw : ref Window;
+ emptyb : ref Text;
+ i, y, el : int;
+
+ if(activecol != nil)
+ c = activecol;
+ else if(seltext != nil && seltext.col != nil)
+ c = seltext.col;
+ else if(t != nil && t.col != nil)
+ c = t.col;
+ else{
+ if(row.ncol==0 && row.add(nil, -1)==nil)
+ error("can't make column");
+ c = row.col[row.ncol-1];
+ }
+ activecol = c;
+ if(t==nil || t.w==nil || c.nw==0)
+ return c.add(nil, nil, -1);
+
+ # find biggest window and biggest blank spot
+ emptyw = c.w[0];
+ bigw = emptyw;
+ for(i=1; i<c.nw; i++){
+ w = c.w[i];
+ # use >= to choose one near bottom of screen
+ if(w.body.frame.maxlines >= bigw.body.frame.maxlines)
+ bigw = w;
+ if(w.body.frame.maxlines-w.body.frame.nlines >= emptyw.body.frame.maxlines-emptyw.body.frame.nlines)
+ emptyw = w;
+ }
+ emptyb = emptyw.body;
+ el = emptyb.frame.maxlines-emptyb.frame.nlines;
+ # if empty space is big, use it
+ if(el>15 || (el>3 && el>(bigw.body.frame.maxlines-1)/2))
+ y = emptyb.frame.r.min.y+emptyb.frame.nlines*(graph->font).height;
+ else{
+ # if this window is in column and isn't much smaller, split it
+ if(t.col==c && t.w.r.dy()>2*bigw.r.dy()/3)
+ bigw = t.w;
+ y = (bigw.r.min.y + bigw.r.max.y)/2;
+ }
+ w = c.add(nil, nil, y);
+ if(w.body.frame.maxlines < 2)
+ w.col.grow(w, 1, 1);
+ return w;
+}
+
+stralloc(n : int) : ref Astring
+{
+ r := ref Astring;
+ ab := array[n] of { * => byte 'z' };
+ r.s = string ab;
+ if (len r.s != n)
+ error("bad stralloc");
+ ab = nil;
+ return r;
+}
+
+strfree(s : ref Astring)
+{
+ s.s = nil;
+ s = nil;
+}
+
+access(s : string) : int
+{
+ fd := sys->open(s, 0);
+ if (fd == nil)
+ return -1;
+ fd = nil;
+ return 0;
+}
+
+errorwin(dir : string, ndir : int, incl : array of string, nincl : int) : ref Window
+{
+ w : ref Window;
+ r : string;
+ i, n : int;
+
+ n = ndir;
+ r = dir + "+Errors";
+ n += 7;
+ w = look->lookfile(r, n);
+ if(w == nil){
+ w = row.col[row.ncol-1].add(nil, nil, -1);
+ w.filemenu = FALSE;
+ w.setname(r, n);
+ }
+ r = nil;
+ for(i=nincl; --i>=0; )
+ w.addincl(incl[i], n);
+ return w;
+}
+
+warning(md : ref Mntdir, s : string)
+{
+ n, q0, owner : int;
+ w : ref Window;
+ t : ref Text;
+
+ debug(sys->sprint("warning %s\n", s));
+ if (row == nil) {
+ sys->fprint(sys->fildes(2), "warning: %s\n", s);
+ debug(s);
+ debug("\n");
+ return;
+ }
+ if(row.ncol == 0){ # really early error
+ row.init(mainwin.clipr);
+ row.add(nil, -1);
+ row.add(nil, -1);
+ if(row.ncol == 0)
+ error("initializing columns in warning()");
+ }
+ if(md != nil){
+ for(;;){
+ w = errorwin(md.dir, md.ndir, md.incl, md.nincl);
+ w.lock('E');
+ if (w.col != nil)
+ break;
+ # window was deleted too fast
+ w.unlock();
+ }
+ }else
+ w = errorwin(nil, 0, nil, 0);
+ t = w.body;
+ owner = w.owner;
+ if(owner == 0)
+ w.owner = 'E';
+ w.commit(t);
+ (q0, n) = t.bsinsert(t.file.buf.nc, s, len s, TRUE);
+ t.show(q0, q0+n);
+ t.w.settag();
+ scrl->scrdraw(t);
+ w.owner = owner;
+ w.dirty = FALSE;
+ if(md != nil)
+ w.unlock();
+}
+
+getexc(): string
+{
+ f := "/prog/"+string sys->pctl(0, nil)+"/exception";
+ if((fd := sys->open(f, Sys->OREAD)) == nil)
+ return nil;
+ b := array[8192] of byte;
+ if((n := sys->read(fd, b, len b)) < 0)
+ return nil;
+ return string b[0: n];
+}
+
+# returns pc, module, exception
+readexc(): (int, string, string)
+{
+ s := getexc();
+ if(s == nil)
+ return (0, nil, nil);
+ (m, l) := sys->tokenize(s, " ");
+ if(m < 3)
+ return (0, nil, nil);
+ pc := int hd l; l = tl l;
+ mod := hd l; l = tl l;
+ exc := hd l; l = tl l;
+ for( ; l != nil; l = tl l)
+ exc += " " + hd l;
+ return (pc, mod, exc);
+}