123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 |
- (** AUTHOR "Michael Szediwy"; PURPOSE "Ports the System.State to an Aos window. There is new an auto-refresh feature."; *)
- MODULE WMModuleState;
- IMPORT
- SYSTEM,
- Streams,
- Modules,
- TextUtilities,
- WMComponents,
- WMEditors,
- WMGraphics,
- WMStandardComponents,
- WMDialogs,
- WMWindowManager,
- Commands,
- WMRectangles,
- Kernel;
- CONST
- MaxString = 64;
- MaxArray = 10;
- RefreshOff = "Refresh is off";
- RefreshOn = "Refresh is on";
- TYPE Bytes = Modules.Bytes;
- TYPE StateWindow= OBJECT(WMComponents.FormWindow)
- VAR
- tw-: TextUtilities.TextWriter;
- panel : WMStandardComponents.Panel;
- out- : WMEditors.Editor;
- open : BOOLEAN;
- refresh: WMStandardComponents.Button;
- refreshOn: BOOLEAN;
- timer : Kernel.Timer;
- module: Modules.Module;
- interval: LONGINT;
- autorefresh: WMStandardComponents.Checkbox;
- PROCEDURE &New*(title : ARRAY OF CHAR; interval: LONGINT; name: Modules.Name);
- VAR toolbar: WMStandardComponents.Panel;
- load, clear : WMStandardComponents.Button;
- font: WMGraphics.Font;
- dx, dy: LONGINT;
- bearing : WMRectangles.Rectangle;
- label: WMStandardComponents.Label;
- BEGIN
- NEW(panel); panel.bounds.SetExtents(640, 420); panel.fillColor.Set(WMGraphics.RGBAToColor(255, 255, 255, 255));
- NEW(toolbar);
- toolbar.bounds.SetHeight(20);
- toolbar.alignment.Set(WMComponents.AlignTop);
- panel.AddContent(toolbar);
- NEW(clear);
- clear.alignment.Set(WMComponents.AlignLeft);
- clear.SetCaption("Clear");
- clear.onClick.Add(ClearText);
- font := clear.GetFont();
- font.GetStringSize(" Clear ", dx, dy);
- clear.bounds.SetWidth(dx);
- toolbar.AddContent(clear);
- NEW(load);
- load.alignment.Set(WMComponents.AlignLeft);
- load.SetCaption("Load module");
- load.onClick.Add(Load);
- font := load.GetFont();
- font.GetStringSize(" Load module ", dx, dy);
- load.bounds.SetWidth(dx);
- toolbar.AddContent(load);
- NEW(refresh);
- refresh.alignment.Set(WMComponents.AlignLeft);
- refresh.SetCaption("Refresh");
- refresh.onClick.Add(Refresh);
- font := refresh.GetFont();
- font.GetStringSize(" Refresh ", dx, dy);
- refresh.bounds.SetWidth(dx);
- refreshOn := FALSE;
- toolbar.AddContent(refresh);
- bearing := WMRectangles.MakeRect(3, 3, 3, 3);
- NEW(autorefresh);
- autorefresh.onClick.Add(RefreshSwitch);
- autorefresh.bearing.Set(bearing);
- autorefresh.bounds.SetWidth(14);
- autorefresh.alignment.Set(WMComponents.AlignRight);
- toolbar.AddContent(autorefresh);
- autorefresh.state.Set(0);
- NEW(label);
- font := label.GetFont();
- font.GetStringSize(" auto-refresh ", dx, dy);
- label.bounds.SetWidth(dx);
- label.SetCaption("auto-refresh");
- label.textColor.Set(0000000FFH);
- label.alignment.Set(WMComponents.AlignRight);
- toolbar.AddContent(label);
- NEW(out); out.alignment.Set(WMComponents.AlignClient); out.tv.showBorder.Set(TRUE); panel.AddContent(out);
- Init(panel.bounds.GetWidth(), panel.bounds.GetHeight(), FALSE);
- SetContent(panel);
- manager := WMWindowManager.GetDefaultManager();
- SetTitle(WMComponents.NewString(title));
- WMWindowManager.DefaultAddWindow(SELF);
- NEW(tw, out.text);
- open := TRUE;
- SELF.interval := interval;
- NEW(timer);
- IF name # "" THEN
- out.text.AcquireWrite();
- OutState(name);
- out.text.ReleaseWrite();
- ELSE
- Load(NIL, NIL);
- END;
- END New;
- PROCEDURE Close*;
- BEGIN
- open := FALSE;
- BEGIN{EXCLUSIVE}
- refreshOn := FALSE;
- END;
- Remove(SELF);
- Close^
- END Close;
- PROCEDURE ClearText(sender, data : ANY);
- BEGIN
- out.text.AcquireWrite();
- out.text.Delete(0, out.text.GetLength());
- out.tv.firstLine.Set(0); out.tv.cursor.SetPosition(0);
- out.text.ReleaseWrite();
- END ClearText;
- PROCEDURE Load(sender, data : ANY);
- VAR
- dr: LONGINT;
- name: Modules.Name;
- temp: BOOLEAN;
- BEGIN
- temp := refreshOn;
- BEGIN {EXCLUSIVE}
- refreshOn := FALSE;
- END;
- dr := WMDialogs.QueryString("Enter module name", name);
- IF dr = WMDialogs.ResOk THEN
- out.text.AcquireWrite();
- OutState(name);
- out.text.ReleaseWrite();
- END;
- BEGIN {EXCLUSIVE}
- refreshOn := temp;
- END;
- END Load;
- (* Should be surrounded by out.text.AcquireWrite(); ... out.text.ReleaseWrite();*)
- PROCEDURE OutState(name: Modules.Name);
- VAR
- i, refpos: LONGINT;
- mod: Modules.Module;
- refs: Bytes;
- ch: CHAR;
- nameDis: Modules.Name;
- BEGIN
- out.text.Delete(0, out.text.GetLength());
- out.tv.firstLine.Set(0); out.tv.cursor.SetPosition(0);
- IF name = "" THEN
- IF SELF.module = NIL THEN
- RETURN;
- ELSE
- nameDis := module.name;
- mod := module;
- tw.SetFontStyle({0});
- tw.String(nameDis);
- tw.SetFontStyle({});
- IF mod # NIL THEN
- SELF.module := mod;
- tw.String(" SB = ");
- tw.Hex(mod.sb, 0); tw.Char("H"); tw.Ln();
- refs := SYSTEM.VAL(Bytes, mod.refs);
- IF (refs # NIL) & (LEN(mod.refs) # 0) THEN
- refpos := FindProc(refs, 0); (* assume module body is at PC = 0 (not true for OMI) *)
- IF refpos # -1 THEN
- REPEAT ch := refs[refpos]; INC(refpos) UNTIL ch = 0X;
- Variables(refs, refpos, mod.sb, tw)
- END
- END
- ELSE
- tw.String(" not loaded"); tw.Ln();
- END;
- tw.Update();
- END;
- ELSE
- (* New module: Have to do some work. *)
- i := 0; WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END; name[i] := 0X;
- mod := Modules.root;
- WHILE (mod # NIL) & (mod.name # name) DO mod := mod.next END;
- nameDis := name;
- tw.SetFontStyle({0});
- tw.String(nameDis);
- tw.SetFontStyle({});
- IF mod # NIL THEN
- SELF.module := mod;
- tw.String(" SB =");
- tw.Hex(mod.sb, 0); tw.Char("H"); tw.Ln();
- refs := SYSTEM.VAL(Bytes, mod.refs);
- IF (refs # NIL) & (LEN(mod.refs) # 0) THEN
- refpos := FindProc(refs, 0); (* assume module body is at PC = 0 (not true for OMI) *)
- IF refpos # -1 THEN
- REPEAT ch := refs[refpos]; INC(refpos) UNTIL ch = 0X;
- Variables(refs, refpos, mod.sb, tw)
- END
- END
- ELSE
- tw.String(" not loaded"); tw.Ln();
- END;
- tw.Update();
- END;
- END OutState;
- PROCEDURE RefreshSwitch(sender, data : ANY);
- BEGIN
- BEGIN {EXCLUSIVE} (* Else the waiting process may not be found *)
- refreshOn := ~ refreshOn;
- END;
- IF refreshOn THEN
- refresh.onClick.Remove(Refresh);
- (*refresh.caption.SetAOC(RefreshOn); *)
- ELSE
- (* refresh.caption.SetAOC(RefreshOff);*)
- refresh.onClick.Add(Refresh);
- END;
- END RefreshSwitch;
- PROCEDURE Refresh(sender, data : ANY);
- BEGIN
- out.text.AcquireWrite();
- OutState("");
- out.text.ReleaseWrite();
- END Refresh;
- PROCEDURE SetInterval*(interval: LONGINT);
- BEGIN
- SELF.interval := interval;
- END SetInterval;
- PROCEDURE Variables(refs: Bytes; i: LONGINT; base: ADDRESS; w:Streams.Writer);
- VAR
- mode, ch: CHAR;
- m, type, n, lval, size, tmp1, tdadr: LONGINT;
- adr, tmp2: ADDRESS;
- etc: BOOLEAN;
- sval: SHORTINT;
- ival: INTEGER;
- tmp: Bytes;
- set: SET;
- rval: REAL;
- lrval: LONGREAL;
- BEGIN
- m := LEN(refs^); mode := refs[i]; INC(i);
- WHILE (i < m) & (mode >= 1X) & (mode <= 3X) DO (* var *)
- type := ORD(refs[i]); INC(i); etc := FALSE;
- IF type > 80H THEN
- IF type = 83H THEN type := 15 ELSE DEC(type, 80H) END;
- GetNum(refs, i, n)
- ELSIF (type = 16H) OR (type = 1DH) THEN
- GetNum(refs, i, tdadr); n := 1
- ELSE
- IF type = 15 THEN n := MaxString (* best guess *) ELSE n := 1 END
- END;
- GetNum(refs, i, tmp1); adr := tmp1;
- tw.SetFontColor(00BF00FFH);
- w.Char(9X); ch := refs[i]; INC(i);
- WHILE ch # 0X DO w.Char(ch); ch := refs[i]; INC(i) END;
- tw.SetFontColor(WMGraphics.Black);
- w.String(" = ");
- tw.SetFontColor(WMGraphics.Blue);
- INC(adr, base);
- IF n = 0 THEN (* open array *)
- SYSTEM.GET(adr+4, n) (* real LEN from stack *)
- END;
- IF type = 15 THEN
- IF n > MaxString THEN etc := TRUE; n := MaxString END
- ELSE
- IF n > MaxArray THEN etc := TRUE; n := MaxArray END
- END;
- IF mode # 1X THEN SYSTEM.GET(adr, adr) END; (* indirect *)
- IF (adr >= -4) & (adr < 4096) THEN
- w.String("NIL reference ("); w.Hex( adr,0); w.String("H )")
- ELSE
- IF type = 15 THEN
- w.Char(22X);
- LOOP
- IF n = 0 THEN EXIT END;
- SYSTEM.GET(adr, ch); INC(adr);
- IF (ch < " ") OR (ch > "~") THEN EXIT END;
- w.Char(ch); DEC(n)
- END;
- w.Char(22X); etc := (ch # 0X)
- ELSE
- CASE type OF
- 1..4: size := 1
- |5: size := 2
- |6..7,9,13,14,29: size := 4
- |8, 16: size := 8
- |22: size := 0; ASSERT(n <= 1)
- ELSE
- w.String("bad type "); w.Int(type, 1); n := 0
- END;
- WHILE n > 0 DO
- CASE type OF
- 1,3: (* BYTE, CHAR *)
- SYSTEM.GET(adr, ch);
- IF (ch > " ") & (ch <= "~") THEN w.Char(ch)
- ELSE w.Hex( ORD(ch), 0); w.Char("X")
- END
- |2: (* BOOLEAN *)
- SYSTEM.GET(adr, ch);
- IF ch = 0X THEN w.String("FALSE")
- ELSIF ch = 1X THEN w.String("TRUE")
- ELSE w.Int(ORD(ch), 1)
- END
- |4: (* SHORTINT *)
- SYSTEM.GET(adr, sval); w.Int( sval, 1)
- |5: (* INTEGER *)
- SYSTEM.GET(adr, ival); w.Int( ival, 1)
- |6: (* LONGINT *)
- SYSTEM.GET(adr, lval); w.Int( lval, 1)
- |7: (* REAL *)
- SYSTEM.GET(adr, rval); w.RawReal(rval)
- |8: (* LONGREAL *)
- SYSTEM.GET(adr, lrval); w.RawLReal(lrval)
- |9: (* SET *)
- SYSTEM.GET(adr, set); w.Set(set)
- |13, 29: (* POINTER *)
- SYSTEM.GET(adr, lval); w.Hex( lval, 0); w.Char("H")
- |14: (* PROC *)
- SYSTEM.GET(adr, lval);
- IF lval = 0 THEN w.String("NIL")
- ELSE WriteProc(Modules.ThisModuleByAdr(lval), lval, -1, tmp, tmp1, tmp2, w)
- END
- |16: (* HUGEINT *)
- w.Hex( SYSTEM.GET32(adr+4), 0);
- w.Hex( SYSTEM.GET32(adr), 0)
- |22: (* RECORD *)
- w.Hex( tdadr, 0); w.Char("H")
- END;
- DEC(n); INC(adr, size);
- IF n > 0 THEN w.String(", ") END
- END
- END
- END;
- IF etc THEN w.String(" ...") END;
- w.Ln();
- IF i < m THEN mode := refs[i]; INC(i) END
- END;
- tw.SetFontColor(WMGraphics.Black);
- END Variables;
- (* FindProc - Find a procedure in the reference block. Return index of name, or -1 if not found. *)
- PROCEDURE FindProc(refs: Bytes; ofs: ADDRESS): LONGINT;
- VAR i, m, t, proc: LONGINT; ch: CHAR;
- BEGIN
- proc := -1; i := 0; m := LEN(refs^);
- ch := refs[i]; INC(i);
- WHILE (i < m) & ((ch = 0F8X) OR (ch = 0F9X)) DO (* proc *)
- GetNum(refs, i, t); (* pofs *)
- IF t > ofs THEN (* previous procedure was the one *)
- ch := 0X (* stop search *)
- ELSE (* ~found *)
- IF ch = 0F9X THEN
- GetNum(refs, i, t); (* nofPars *)
- INC(i, 3) (* RetType, procLev, slFlag *)
- END;
- proc := i; (* remember this position, just before the name *)
- REPEAT ch := refs[i]; INC(i) UNTIL ch = 0X; (* pname *)
- IF i < m THEN
- ch := refs[i]; INC(i); (* 1X | 3X | 0F8X | 0F9X *)
- WHILE (i < m) & (ch >= 1X) & (ch <= 3X) DO (* var *)
- ch := refs[i]; INC(i); (* type *)
- IF (ch >= 81X) OR (ch = 16X) OR (ch = 1DX) THEN
- GetNum(refs, i, t) (* dim/tdadr *)
- END;
- GetNum(refs, i, t); (* vofs *)
- REPEAT ch := refs[i]; INC(i) UNTIL ch = 0X; (* vname *)
- IF i < m THEN ch := refs[i]; INC(i) END (* 1X | 3X | 0F8X | 0F9X *)
- END
- END
- END
- END;
- IF (proc = -1) & (i # 0) THEN proc := i END; (* first procedure *)
- RETURN proc
- END FindProc;
- PROCEDURE WriteProc(mod: Modules.Module; pc, fp: ADDRESS; VAR refs: Bytes; VAR refpos: LONGINT; VAR base: ADDRESS; w: Streams.Writer);
- VAR ch: CHAR;
- BEGIN
- refpos := -1;
- IF mod = NIL THEN
- w.String("Unknown PC ="); w.Hex(pc,0); w.Char("H");
- IF fp # -1 THEN
- w.String(" EBP ="); w.Hex(fp, 0); w.Char("H")
- END
- ELSE
- w.String(mod.name);
- DEC(pc, ADDRESSOF(mod.code[0]));
- refs := SYSTEM.VAL(Bytes, mod.refs);
- IF (refs # NIL) & (LEN(mod.refs) # 0) THEN
- refpos := FindProc(refs, pc);
- IF refpos # -1 THEN
- w.Char(".");
- ch := refs[refpos]; INC(refpos);
- IF ch = "$" THEN base := mod.sb ELSE base := fp END; (* for variables *)
- WHILE ch # 0X DO w.Char(ch); ch := refs[refpos]; INC(refpos) END
- END
- END;
- w.String(" PC = "); w.Address(pc)
- END
- END WriteProc;
- PROCEDURE GetNum(refs: Bytes; VAR i, num: LONGINT);
- VAR n, s: LONGINT; x: CHAR;
- BEGIN
- s := 0; n := 0; x := refs[i]; INC(i);
- WHILE ORD(x) >= 128 DO
- INC(n, ASH(ORD(x) - 128, s)); INC(s, 7); x := refs[i]; INC(i)
- END;
- num := n + ASH(ORD(x) MOD 64 - ORD(x) DIV 64 * 64, s)
- END GetNum;
- BEGIN {ACTIVE}
- LOOP
- BEGIN {EXCLUSIVE}
- AWAIT(refreshOn);
- END;
- Refresh(NIL, NIL);
- timer.Sleep(interval)
- END;
- END StateWindow;
- TYPE WinCollection = POINTER TO ARRAY OF StateWindow;
- VAR
- stateWins: WinCollection;
- nrWins: LONGINT;
- PROCEDURE Remove(stateWin: StateWindow);
- VAR
- i, j: LONGINT;
- wins: WinCollection;
- BEGIN {EXCLUSIVE}
- i := 0;
- WHILE (i < LEN(stateWins)) & (stateWins[i] # stateWin) DO
- INC(i)
- END;
- IF stateWins[i] = stateWin THEN
- NEW(wins, LEN(stateWins) - 1);
- FOR j := 0 TO i - 1 DO
- wins[j] := stateWins[j];
- END;
- FOR j := i + 1 TO LEN(stateWins) - 1 DO
- wins[j-1] := stateWins[j];
- END;
- DEC(nrWins);
- stateWins := wins;
- ELSE
- (* Not found. *)
- END;
- END Remove;
- (* Usage: WMModuleState.Open modulename [ms] ~ *)
- PROCEDURE Open*(context : Commands.Context);
- VAR
- interval, i: LONGINT;
- name: Modules.Name;
- wins: WinCollection;
- stateWin: StateWindow;
- BEGIN
- context.arg.SkipWhitespace; context.arg.String(name);
- context.arg.SkipWhitespace; context.arg.Int(interval, FALSE);
- IF interval < 1 THEN interval := 2000 END; (* default interval *)
- NEW(stateWin, "Module State", interval, name);
- INC(nrWins);
- BEGIN {EXCLUSIVE}
- IF stateWins = NIL THEN
- NEW(stateWins, 1);
- stateWins[0] := stateWin;
- ELSE
- NEW(wins, LEN(stateWins) + 1);
- FOR i := 0 TO LEN(stateWins) - 1 DO
- wins[i] := stateWins[i];
- END;
- wins[LEN(stateWins)] := stateWin;
- stateWins := wins;
- END;
- END;
- END Open;
- END WMModuleState.
- System.Free WMModuleState ~
- WMModuleState.Open ~
|