// OnceOnly.bcpl -- OnceOnly Initialization Module // Copyright Xerox Corporation 1979, 1983 // last modified January 8, 1983 3:49 PM by Boggs get "AltoDefs.d" get "SysDefs.d" get "Disks.d" get "AltoFileSys.d" get "Streams.d" get "Time.d" get "COMSTRUCT.BCPL" // this code is overwritten after execution external [ // imported from ExecInit ClockWrong DiskInfo DiskName ExecSysErr InCaseOfDemise NetNumber OldUserFinishProc OverlayArea OverlayAreaSize screenColor ShowDiskInfo SpaceAbove SpaceBelow // exported to ExecInit OnceOnlyInitCode ] manifest [ DisplayHead = #420 screenWhite = 0 screenBlack = 1 ] static [ BootFileIllegal FullDspLine screenColor = screenWhite ] let OnceOnlyInitCode(CFA) = valof [ SetKeyboardProc(CatchBlankKeys, Allocate(CZ,10), 10) FixupCursor() // Initialize overlays manifest [ lODV = 60 ] OverlayArea = OnceOnlyInitCode let OverlayDescVec = Allocate(CZ, lODV) OverlayScan(lv CFA>>CFA.fp, OverlayDescVec, lODV, lv CFA>>CFA.fa) OverlayAreaSize = MaxOverlaySize() let BQ = Allocate(CZ, size QS/16) INITQ(BQ) ProcessUserCm(BQ) userParamsVec = Allocate(CZ, lUserParams+1) FullDspLine = dsp>>DS.fdcb>>DCB.height*2*WordsPerScanLine SpaceAbove = NewFakeDisplayStream(10) SpaceBelow = NewFakeDisplayStream(10) TIMESTR1 = NewDisplayStream(1, 0) TIMESTR2 = NewDisplayStream(1, 0) DiskInfo = NewDisplayStream(1, 0) UserLineEnds = Allocate(CZ, UserLines) USERSTR = NewDisplayStream(UserLines, (UserLines-1)*FullDspLine) [ let dcb = @DisplayHead until dcb eq 0 do [ dcb>>DCB.background = screenColor dcb = dcb>>DCB.next ] ] ShowDisplayStream(SpaceAbove) ShowDisplayStream(TIMESTR2, 0, SpaceAbove) ShowDisplayStream(DiskInfo, 0, TIMESTR2) ShowDisplayStream(SpaceBelow, 0, DiskInfo) ShowDisplayStream(USERSTR, 0, SpaceBelow) TIMESTR1>>DS.fdcb>>DCB.next = TIMESTR2>>DS.fdcb>>DCB.next PreTimeDcb = FindPreviousDcb(TIMESTR2) OldSysErr = @lvSysErr @lvSysErr = ExecSysErr OldUserFinishProc = @lvUserFinishProc @lvUserFinishProc = InCaseOfDemise DefaultScroll = USERSTR>>DS.scroll USERSTR>>DS.scroll = UserScroll DIRSTATE = EMPTY SYSTEMDIR = OpenFile("SysDir", ksTypeReadOnly, charItem, 0, fpSysDir) PrintDiskInformation(DiskInfo) RemCm = OpenFile("REM.CM", ksTypeReadWrite, charItem, 0, fpRemCm) STREAMTOQR(RemCm, BQ) Resets(RemCm) TruncateDiskStream(RemCm) CleanupDiskStream(RemCm) ComCm = 0 resultis BQ ] and NewDisplayStream(NLines, BlockSize) = valof [ let AreaSize = BlockSize+FullDspLine+ NLines*lDCB let Area = Allocate(CZ, AreaSize, false, true) // even let DS = CreateDisplayStream(NLines, Area, AreaSize, 0, WordsPerScanLine, DSnone, CZ) for i = 1 to NLines do Puts(DS, $*N) let dcb = DS>>DS.fdcb until dcb eq 0 do [ dcb>>DCB.background = screenColor dcb = dcb>>DCB.next ] resultis DS ] and NewFakeDisplayStream(NScanLines) = valof [ let ds = Allocate(CZ, lDCB+2, false, true) // even let dcb = ds+2 ds!0, ds!1 = dcb, dcb Zero(dcb,lDCB) dcb>>DCB.height = NScanLines/2 dcb>>DCB.background = screenColor resultis ds ] and FindPreviousDcb(ds) = valof [ let prev = DisplayHead let firstDcb = ds>>DS.fdcb while prev>>DCB.next ne firstDcb do prev = prev>>DCB.next resultis prev ] and MaxOverlaySize() = valof [ static [ MaxPages ] let CheckMorePages(od) be [ let CurPages = OverlayNpages(od) if CurPages gr MaxPages then MaxPages = CurPages ] MaxPages = 0 GenerateOverlays(CheckMorePages) resultis MaxPages lshift sysDisk>>DSK.lnPageSize ] and ProcessUserCm(Q) be [ ShouldSetTime = ThisEventExists("eventBooted", false) if ClockIsWrong() then [ // AddEvent(eventClockWrong, 0) ShouldSetTime = true ClockWrong = true ] let UserCm = OpenFile("User.Cm", ksTypeReadOnly, charItem, 0, fpUserCm) if UserCm eq 0 then return let InExec = false let InDisplay = false let InScreen = false let InTimeOut = false let Enabled = false until Endofs(UserCm) do [ let String = vec 129 switchon ReadUserCmItem(UserCm, String) into [ case $E: break case $N: if InExec then break InExec = (CompareStrings( String, "EXECUTIVE") eq 0) Enabled = false endcase case $L: unless InExec do endcase if CompareStrings(String, "DISPLAYLINES") eq 0 then [ InDisplay = true; endcase ] if CompareStrings(String, "SCREEN") eq 0 then [ InScreen = true; endcase ] if CompareStrings(String, "EVENTABOUTTODIE") eq 0 then [ InTimeOut = true; endcase ] Enabled = ThisEventExists(String) endcase case $P: if InDisplay then [ UserLines = GetNumber(String, UserLines) InDisplay = false endcase ] if InScreen then [ if CompareStrings(String, "BLACK") eq 0 then screenColor = screenBlack; InScreen = false endcase ] if InTimeOut then [ if HasCommands(String) then [ let n = String>>STRING.length/2+1 TimeOutCommand = Allocate(CZ,n) MoveBlock(TimeOutCommand,String,n) ] InTimeOut = false endcase ] unless Enabled do endcase if HasCommands(String) then ClockWrong = true STRINGTOQR(String, Q) PUTQR(Q, $*N) default: InDisplay = false; InScreen = false; Enabled = false ] ] Closes(UserCm) ] and HasCommands(s) = valof [ if s>>STRING.length eq 0 then resultis false for i = 1 to s>>STRING.length do switchon s>>STRING.char^i into [ case $*S: case $*T: endcase; case $/: resultis false; default: resultis true ] ] and GetNumber(s, def) = valof [ // convert s to a decimal number let v = 0 let usedefault = true let i = 1 let len = s>>STRING.length while i le len & s>>STRING.char^i ge $0 & s>>STRING.char^i le $9 do [ v = v*10 + s>>STRING.char^i-$0; i = i+1 usedefault = false ] resultis usedefault ? def, v ] //and AddEvent(type, bodyLen, body) be // // [ // if no identical event exists in the event vector // // and there is room, add an event. // // let eve = EventVector // until eve!0 eq 0 do // [ if valof // [ if eve>>EVM.type ne type // then resultis false // // if eve>>EVM.length ne bodyLen+1 // then resultis false // // for i=1 to bodyLen do // if eve!i ne body!(i-1) // then resultis false // resultis true // ] then return // // eve = eve+eve>>EVM.length // ] // // if eve+bodyLen+1 ge EventVector+(EventVector!-1) // then return // // eve>>EVM.type = type // eve>>EVM.length = bodyLen+1 // MoveBlock(eve+1, body, bodyLen) // eve!(bodyLen+1) = 0 // ] and ThisEventExists(String, deletIt; numargs na) = valof [ if na ls 2 then deletIt = true let Result = false let EventPtr = EventVector let CopyPtr = EventPtr let s = vec 20 let unknown = CompareStrings(String, "eventUnknown") eq 0 while EventPtr>>EVM.length gr 0 do [ let Length = EventPtr>>EVM.length let eventName = selecton EventPtr>>EVM.type into [ case eventBooted: "eventBooted" case eventAboutToDie: "eventAboutToDie" case eventInstall: "eventInstall" case eventRFC: "eventRFC" case eventExecuteCode: "eventExecuteCode" default: MakeEventName(s) ] test CompareStrings(String, eventName) eq 0 % unknown ifso Result = true ifnot if deletIt then [ MoveBlock(CopyPtr, EventPtr, EventPtr>>EVM.length) CopyPtr = CopyPtr+Length ] EventPtr = EventPtr+Length ] if deletIt then CopyPtr!0 = 0 resultis Result ] and CompareStrings(S1, S2) = valof [ let lS1 = S1>>STRING.length let lS2 = S2>>STRING.length let lC = (lS1 ls lS2)? lS1, lS2 for i=1 to lC do [ let c1 = Capitalize(S1>>STRING.char^i) let c2 = Capitalize(S2>>STRING.char^i) if c1 ne c2 then resultis (c1 gr c2) ? 1, -1 ] resultis (lS1 eq lS2)? 0, ((lS1 gr lS2)? 1, -1) ] and MakeEventName(s, enum) be [ let event = "event" let append(s,c) be [ let l = s>>STRING.length+1 s>>STRING.char^l = c s>>STRING.length = l ] let appendnumber(s,n) be [ let r = n rem 10 if n/10 ne 0 then appendnumber(s,n/10) append(s,r+$0) ] s>>STRING.length = 0 for i = 1 to event>>STRING.length do append(s,event>>STRING.char^i) appendnumber(s,enum) ] and PrintDiskInformation(Stream) be [ structure JUNTADL: [ next word 1 leaderVirtualDa word 1 stuff word 3 version word serialNumber @SN ] let FP = vec lFP let Disk = vec 256 BfsMakeFpFromLabel(FP, juntaTable) let Da = juntaTable>>JUNTADL.leaderVirtualDa FP>>FP.leaderVirtualDa = Da BootFileIllegal = false let BootFile = OpenFile(0, 0, charItem, 0, FP, BootFileDoesntExist, 0) test BootFileIllegal % (BootFile eq 0) ifso [ FORMAT(Disk, "OS Not Installed") ] ifnot [ SetFilePos(BootFile, 0, 512) let Len = Gets(BootFile) for i=1 to Len do Gets(BootFile) if (Len&1) eq 0 then Gets(BootFile) let Len = Gets(BootFile) Disk>>STRING.length = Len for i=1 to Len do Disk>>STRING.char^i = Gets(BootFile) Closes(BootFile) ] let len = Disk>>STRING.length DiskName = Allocate(CZ, (len+2)/2) MoveBlock(DiskName, Disk, (len+2)/2); if (SerialNumberŹ) eq #377 then NetNumber = 0 ShowDiskInfo(Stream) MAKETIMELINE() ] and BootFileDoesntExist(X, Y, Z) be [ BootFileIllegal = true ] and FixupCursor() be [ MoveBlock(#431, (table [ #100000; #140000; #160000; #170000; #174000; #176000; #177000; #170000; #154000; #114000; #006000; #006000; #003000; #003000; #001400; #001400 ]), 16) ] and ClockIsWrong() = valof [ let TIME = vec lenUTV UNPACKDT(0, TIME) resultis (TIME>>UTV.year ls 1983) % (TIME>>UTV.year gr 1990) ]