//Compat.Bcpl -- Compatibility with old OS
//Copyright Xerox Corporation 1979
get "AltoFileSys.d"
get "streams.d"
// outgoing procedure
external [
InitializeCompatibility
GetSysDir
]
// statics declared elsewhere
external [
dsp //Display stream for OS
keys //Keyboard stream
sysFont // Default system display font
badStream
sysZone
sysDisk
]
// Incoming procedures
external [
// from Os -- dirs
OpenFile; SetWorkingDir; CreateDiskStream
DeleteFile
// -- streams
Puts; Gets; Resets
Closes
EofError
ReadBlock
WriteBlock
PositionPtr
FilePos
FindFdEntry
SetFilePos
CleanupDiskStream
ReadLeaderPage
GetCompleteFa
RealDiskDA
VirtualDiskDA
DeleteDiskPages
PositionPage
TruncateDiskStream
// Display
CreateDisplayStream
ShowDisplayStream
// -- misc
Noop
Usc
SysErr
DoubleAdd
MoveBlock
RetryCall
SetBlock
DefaultArgs
]
// outgoing procs
external [
OverWrite
MissingSysProc
Creates
LookupEntry
ReadFileStuff
ReadVec
WriteVec
OldPositionPtr
MoveStream
FlushPage
DeleteFileS
OpenAFile
GetAFile
CreateAFile
DeleteAFile
CloseAFile
Display
GetChar
BStore
BMove
AddObj
DelObj
Mem
IncMem
GetFixed; FreeFixed; FixedLeft
RealDA; VirtualDA
]
// error codes
manifest [
ecBadOst=2001
ecCantOpenStream=2002
ecMissingProc=2005
ecNoSysDirStream=2006
ecNotSysDir=2007
]
static gotSysDir
// string streams
structure SS[
@ST
addr word
charPtr word // offset by SS.big
big word // 0 for Bcpl string, 1 for big string
]
manifest lSS=size SS/16
// old stream types
manifest [
ostMin=0
ostDiskRo=0
ostDiskWo=1
ostDiskRw=2
ostDiskRoCh=3
ostDiskWoCh=4
ostDiskRwCh=5
ostString=6
ostBigString=7
ostKeys=9
ostDisplay=10
ostMax=10
]
// Routines for compatibility with the old Os
let Creates(param, ost, errRtn; numargs na)=valof
[
if na ls 3 then errRtn=SysErr
let s=selecton ost into
[
case ostString: CreateStringStream(param, 0)
case ostBigString: CreateStringStream(param, 1)
case ostKeys: keys
case ostDisplay: valof [
if param eq 0 then resultis dsp
let ww=param!3; if ww eq 0 then ww=38
let f=param!2; if f eq 0 then f=sysFont
let ht=((f!-2)+1)&(-2)
let len=param!1-param!0
let nl=len/(ww*ht+4)
let s=CreateDisplayStream(nl, param!0, len, f, ww)
ShowDisplayStream(s)
resultis s
]
case ostDiskRo to ostDiskRwCh:
CreateDiskStream(param, KsTypeOfOst(ost),
ItemSizeOfOst(ost), Noop, errRtn, sysZone, 0)
default: SysErr(ost, ecBadOst)
]
if s eq 0 then SysErr(param, ecCantOpenStream)
s>>ST.error=errRtn
resultis s
]
and KsTypeOfOst(ost)=(table [
ksTypeReadOnly
ksTypeWriteOnly
ksTypeReadWrite
ksTypeReadOnly
ksTypeWriteOnly
ksTypeReadWrite
])!ost
and ItemSizeOfOst(ost)=(table [ 2; 2; 2; 1; 1; 1 ])!ost
and LookupEntry(dir, name) = valof
[
if dir ne badStream then SysErr(dir, ecNotSysDir)
Resets(badStream) //get gotSysDir set up
let p=FindFdEntry(gotSysDir, name)
if p eq -1 then resultis false
SetFilePos(gotSysDir, 0, 2*p)
resultis true
]
and ReadVec(s, addr, countMinus1)= valof
[
if s eq badStream then s=gotSysDir
resultis ReadBlock(s, addr, countMinus1+1)-1
]
and WriteVec(s, addr, countMinus1)=WriteBlock(s, addr, countMinus1+1)
and OldPositionPtr(s, newPosPlus2)=PositionPtr(s, newPosPlus2-2)
and MoveStream(s, deltaWords) be
[
if s eq badStream then s=gotSysDir
let v=vec 2; FilePos(s, v)
let w=vec 2; w!0=(deltaWords ge 0 ? 0, -1); w!1=deltaWords
DoubleAdd(v, w); DoubleAdd(v, w)
SetFilePos(s, v)
]
and FlushPage(s)=CleanupDiskStream(s)
and DeleteFileS(s, pageNo, byteNo; numargs na) be
[
let buf=vec 256
if byteNo eq 512 then [ pageNo=pageNo+1; byteNo=0 ]
test na eq 1 % pageNo eq 0
ifso
[
let cfa=vec lCFA; GetCompleteFa(s, cfa)
DeleteDiskPages(sysDisk, buf, cfa>>CFA.fp.leaderVirtualDa, lv cfa>>CFA.fp, 0)
]
ifnot
[
PositionPage(s, pageNo); PositionPtr(s, byteNo)
TruncateDiskStream(s)
]
]
and GetAFile(name, ost, errRtn; numargs na)=valof
[
DefaultArgs(lv na, 1, ostDiskRw, SysErr)
resultis OpenAFile(name, ost, errRtn, verLatestCreate)
]
and OpenAFile(name, ost, errRtn, version; numargs na)=valof
[
DefaultArgs(lv na, 1, ostDiskRw, SysErr, verLatest)
resultis OpenFile(name, KsTypeOfOst(ost), ItemSizeOfOst(ost),
version, 0, errRtn)
]
and CloseAFile(s) be Closes(s)
and DeleteAFile(nam) be DeleteFile(nam)
and ReadFileStuff(s, v) be ReadLeaderPage(s, v)
and GetSysDir(s, datum) be
[
unless gotSysDir then
[
let s=OpenFile("SysDir.", ksTypeReadOnly)
if s eq 0 then SysErr(s, ecNoSysDirStream)
gotSysDir=s
]
RetryCall(gotSysDir, datum)
]
and RealDA(vda) = valof
[
let a=nil
RealDiskDA(sysDisk, vda, lv a)
resultis a
]
and VirtualDA(rda) = VirtualDiskDA(sysDisk, lv rda)
and Display(c) be Puts(dsp, c)
and GetChar() be Gets(keys)
and BStore(dest, value, countMinus1) be
SetBlock(dest, value, countMinus1+1)
and BMove(source, dest, countMinus1) be
MoveBlock(dest, source, countMinus1+1)
and AddObj(type, ptr)=0
and DelObj(type, ptr)=0
and Mem(v) be [ v!0=0; v!1=0 ]
and MissingSysProc() be SysErr(nil, ecMissingProc)
// the SS structure declaration is global (streams.d), and should be
// retrieved if this code is separated from the rest
and CreateStringStream(str, big)=valof
[
let StringGets(s)=valof
[
let t=s>>SS.charPtr
if t ge StrLn(s) then EofError(s)
t=t+1
s>>SS.charPtr=t
resultis s>>SS.addr>>STRING.char↑t
]
and StringPuts(s, c) be
[
let t=s>>SS.charPtr
if not s>>SS.big & t gr maxStringIndex then EofError(s)
t=t+1; s>>SS.charPtr=t
s>>SS.addr>>STRING.char↑t=c
let olength=StrLn(s)
if t gr olength then
[
let a=s>>SS.addr
test s>>SS.big
then a!0=t-1
or a>>STRING.length=t
]
]
and ResetStringStream(s) be s>>SS.charPtr=s>>SS.big
and EndofStringStream(s)=s>>SS.charPtr ge StrLn(s)
and StrLn(s) =
((s>>SS.big ne 0)?
s>>SS.addr!0+1, s>>SS.addr>>STRING.length)
and StringClose(s) be (sysZone>>ZN.Free)(sysZone, s)
let s=(sysZone>>ZN.Allocate)(sysZone, lSS)
for i=0 to lSS-1 do s!i=SysErr
s>>SS.gets=StringGets; s>>SS.puts=StringPuts
s>>SS.reset=ResetStringStream; s>>SS.endof=EndofStringStream
s>>SS.close=StringClose
s>>SS.addr=str; s>>SS.big=big; s>>SS.charPtr=big
resultis s
]
//Following is called at finish time to reset things
and InitializeCompatibility() be
[
gotSysDir=0
[
// Addresses in ENTVEC
manifest [
evKBOPEN=#1000
evKBINT=#1001
//#1002 -- some kind of signal to COMMAND
evDINIT=#1005
evDPUT=#1006
evCHKRB=#1007
evGCRB=#1010
evFONT=#1011
evOUTLD=#1013
evINLD=#1014
evLINKF=#1015
evINITALTOIOUSES=#1016
evPARTY=#1020
evMYADD=#1021
]
external [
// sysFont
CursorLink
sysStatics
CallSwat
]
//For new OS, patch most of these to CallSwat
SetBlock(#1000,CallSwat,#1021-#1000+1)
rv evFONT=sysFont
rv evLINKF=lv CursorLink
rv evINITALTOIOUSES=sysStatics
]
]