// RaidPrint.bcpl. Raid printing routines for Lisp objects. // Changed October 8, 1986 by van Melle -- added package printing // Changed October 6, 1986 by van Melle -- added ONEDARRAY // Changed May 21, 1984 3:44 PM by van Melle // Changed November 16, 1982 4:39 PM by van Melle // Changed March 8, 1982 11:38 PM by van Melle // Changed February 2, 1982 6:29 PM by van Melle: listpage headers wrong // Changed January 11, 1982 12:36 PM by Masinter: listpage headers wrong // Changed December 30, 1981 10:50 PM by Bill van Melle // Changed August 26, 1981 by Bill van Melle // Allegro change August 4, 1981 4:27 PM by Beau Sheil // Last change July 20, 1981 8:01 PM by Beau Sheil // Last change May 9, 1981 12:29 AM by Beau Sheil // Last change April 14, 1981 8:07 PM by Beau Sheil // Tone change March 17, 1981 5:21 PM by Beau Sheil get "Raid.decl" get "VMem.decl" external [ // procedures defined SpaceCheck; CRLF; Lprint; PrintName; ReadStrng; PrintPtr; Confirm Wo; Wn; Wb; Type; PrintStr; PrintBytes // statics defined uradix; uprintlevel; ulistlength; defaultPackage; packagesOn // statics used dsp; keys; @lvNIL; @lvVPtr; @VPtr0; @VPtr1 typeDecoding; crMax; crCount rmargBitPos; sysFontCharWidth; stringLimit // procedures used RaidReset; ReadKeys; ReadNum; Wc; Ws; FetchAtomComponent EqNIL; VP; UCase @BGetBasePtr; @XGetBasePtr; @XGetBase32; IGetBase @SGetBase; @XSetReadBR; @RRead; @BGetBase; @XGetBase // OS procs GetLmarg; SetLmarg; GetBitPos; EraseBits; CharWidth Negate; Divide; Usc; Min; Gets; FlashScreen; Resets SetScreenColor ] manifest maxdigits = 32 static [ uradix = 8; uprintlevel = 5; ulistlength = 8 defaultPackage = 1 // default is IL scratchPkg // string for unknown packages packagesOn = false ] structure String: [ length byte; char^1,255 byte ] let Lprint(w, internal; numargs n) be // print lisp object w using current position as left margin. // second arg is supplied on recursive call from PrintList, // to suppress margin adjustment [ let savedLM = GetLmarg(dsp) if n eq 1 then SetLmarg(dsp, GetBitPos(dsp)) let typ = Type(w) switchon typ into [ case ATOMTYPE: PrintName(w>>AtomNumber) endcase case LISTTYPE: PrintList(w, uprintlevel) endcase case SMALLTYPE: PrintNum(w>>VA.vahi eq SMALLPOSspace ? 0, -1, w>>VA.valo, uradix) endcase case INTEGERTYPE: XGetBase32(w) PrintNum(VPtr0, VPtr1, uradix) endcase case FLTPTTYPE: WsX("{FLOATP with bits: ") XGetBase32(w) PrintNum(VPtr0, VPtr1, 8) // always octal WsX("}") endcase case STRINGPTRTYPE: PrintStr(w) endcase case ARRAYPTRTYPE: PrintArray(w) endcase case ONEDARRAYTYPE: if PrintOneDArray(w) then endcase default: //print pointer [ let saved = vec 1 MoveAddr(saved, w) // saves w for later test PrintPtr(w!0, w!1, typ) if typ ne 0 then [ WsX("->") XGetBase32(saved) PrintPtr(VPtr0, VPtr1) ] ] ] //ends switchon if n eq 1 then [ CRLF(); SetLmarg(dsp, savedLM) ] ] and PrintArray(lvAPtr) be [ XSetReadBR(lvAPtr) let w = RRead(offset Styp/16) // Flags and type are stored in the same word of the descriptor WsX("{["); WcX(w<>VA.wordN eq 0 then [ // not really a cons WsX("{list page header @ ") PrintPtr (w>>VA.vahi, w>>VA.valo) WcX($}) return ] ] if (w>>VA.valo & 1) eq 1 then [ // odd pointer?? WsX("{bogus cons @ ") PrintPtr (w>>VA.vahi, w>>VA.valo) WcX($}) return ] WcX($() let len = ulistlength [ test len le 0 ifso [ WsX("--") break ] ifnot test Type(w) eq LISTTYPE ifso [ let saved = vec 1 MoveAddr(saved, w) // saves w for later cdr let car = CAR(w) test Type(car) eq LISTTYPE ifso PrintList(car, depth-1) ifnot Lprint(car, true) w = CDR(saved) len=len-1 test EqNIL(w) ifso break ifnot if SpaceCheck(1) then Wc($*S) ] ifnot [ WsX(". ") Lprint(w, true) break ] ] repeat WcX($)) ] and CAR(lvX) = valof // lvX is known to be LISTP [ XGetBase32(lvX) // 32 bits into VPtr0 and 1 compileif CDRCODING then [ unless lvVPtr>>ConsCell.Qfield // indirect cell. Take 1 level of do XGetBase32(lvVPtr) // indirection, to the correct cell lvVPtr>>ConsCell.Qfield = 0 // Turn off the CDR bits ] resultis lvVPtr ] and CDR(lvX) = valof // lvX is known to be LISTP # lvVPtr [ compiletest CDRCODING ifso [ XGetBase32(lvX) // 32 bits into VPPtr0 and 1 unless lvVPtr>>ConsCell.Qfield // indirect cell. Save its address do [ MoveAddr(lvX, lvVPtr) // for later offset, then indirect XGetBase32(lvVPtr) ] // to it let D = lvVPtr>>ConsCell.dfield unless D then resultis lvNIL let F = lvVPtr>>ConsCell.ibit MoveAddr(lvVPtr, lvX) // address is in same page as lvX lvVPtr>>VA.wordN = D lshift 1 unless F do XGetBasePtr(lvVPtr) // indirection for CDR ] ifnot [ MoveAddr(lvVPtr, lvX) // address is in same page as lvX lvVPtr>>VA.valo = lvVPtr>>VA.valo + 2 XGetBasePtr(lvVPtr) ] resultis lvVPtr ] and PrintName(atomnum) be // print pname of atom [ FetchAtomComponent(PNPspace, atomnum) // pname ptr into VPtr let nchars = XGetBase(lvVPtr)<>String.char^1 = pkgno + $0 resultis scratchPkg ] ] ]] SpaceCheck (nchars + prefix? 0, prefix>>String.length) if prefix then Ws(prefix) PrintChars(lvVPtr, 1, nchars, stringLimit) ] and PrintNum(A,B,radx) be // A and B are hi and lo parts of the same number. // This procedure depends on them being put into AC0 // and AC1 for double word Divide. Hence, 2 args. [ let doQ = (radx eq 8) & (A eq 0? (B gr 7 % B ls 0), A eq -1? (B gr 0 % B ls -7), true) // will add "Q" when radix 8 and |number| > 7 let L, P = vec maxdigits, maxdigits let sgn = 0 if A ls 0 then [ sgn = 1; Negate(lv A) ] [ L!P = Divide(lv A, radx)+$0 P = P-1 ] repeatwhile (A ne 0) % (B ne 0) // fill L backwards SpaceCheck (maxdigits-P+sgn+(doQ? 1, 0)) if sgn then Wc($-) while P ls maxdigits do [ P = P+1; Wc(L!P) ] if doQ then Wc($Q) ] and PrintPtr(hi, lo, typ; numargs na) be // print ptr as {hi,lo} [ let name = (na gr 2) & typ ? TypeName (typ), 0 if name // pointer has an interesting type name then [ FetchAtomComponent(PNPspace, name) // pname ptr into VPtr (see PrintName) name = XGetBase(lvVPtr)<>String.length) Ws (str) ]  and MoveAddr(tgt, src) = valof [ tgt!0 = src!0 tgt!1 = src!1 resultis tgt ]  and Type(ptr) = BGetBase(MDSTYPEspace, MDSTYPEbase + VP(ptr) rshift 1)<>String.length , 0 [ let ch=Gets(keys) if ch eq DEL then resultis 0 test (ch eq 1) % (ch eq #10) // ^A or BS ifso test index gr 0 ifso [ unless noecho do EraseBits(dsp, -CharWidth(dsp, str>>String.char^index)) index = index - 1 ] ifnot FlashScreen() ifnot test ch eq $*s ifso [ if index eq 0 then loop // flush leading space unless noecho do Wc(ch) break ] ifnot [ if ch eq $*N then [ Wc (ch); break ] if inited % (ch eq #27) % (ch eq #21) // ^W or ^Q then [ // overwriting/erasing init string unless noecho do [ let width = 0 for i = 1 to index do width = width + CharWidth(dsp, str>>String.char^i) EraseBits (dsp, -width) ] index = 0 inited = false if (ch eq #27) % (ch eq #21) then loop ] unless noecho do Wc(ch) if index ge maxlen then [ FlashScreen(); loop ] index = index+1 str>>String.char^index = ch ] ] repeat unless (index&1) ne 0 do str>>String.char^(index+1) = 0 // null last byte str>>String.length = index resultis str ] (1792) and Confirm(s ;numargs n) = valof [ Resets(keys) if n gr 0 then Ws(s) Ws(" [Confirm] ") let val = (Gets(keys) eq $*N) unless val do Ws("XXX") Wc($*N) resultis val ]  and CRLF() be [ test crCount gr crMax ifso [ crCount = 1 SetScreenColor(true) // flash screen let c = Gets(keys) // wait for keystroke SetScreenColor(false) // restore screen if c eq DEL then RaidReset() ] ifnot crCount = crCount + 1 Wc($*N) ] and SpaceCheck (n) = valof // see if there is room to print n chars // if so, return true; else do CRLF() and return false [ test (GetBitPos(dsp) + (n*sysFontCharWidth) gr rmargBitPos) & (n*sysFontCharWidth ls rmargBitPos-GetLmarg(dsp)) ifso [ CRLF(); resultis false ] ifnot resultis true ]  and PrintBytes(asCharP) be [ let hi = ReadNum(8); let lo = ReadNum(8) Ws(" showing "); let N = ReadNum(8) Wn(N, 8); Ws(" words, as bytes, starting at ") PrintPtr(hi, lo); CRLF() let end = lo+N-1 for i = 1 to 7 do Wc($*S) // print labeling line for i = 0 to 7 do [ Ws(" "); Wo(i) ] for i = (lo & #177770) to end do [ if (i&7) eq 0 then [ CRLF(); Wo(i); Ws(": ") ] Wc($*S) test i ls lo ifso Ws (" ") // don't print data yet ifnot [ let w = BGetBase(hi, i) Wc($*S); Wbc(w<