// FileIOSubrs.bcpl
// Last change May 25, 1983  10:44 AM by Bill van Melle
// Last change April 5, 1983  4:48 PM by Bill van Melle
// Major pruning December 14, 1982  2:47 PM by Bill van Melle
// Last change October 25, 1982  12:43 PM by Bill van Melle
// Last change July 21, 1982  9:50 PM by Bill van Melle
// Last change March 29, 1982  3:53 PM by Bill van Melle
// Last change August 2, 1981  12:43 AM by Beau Sheil
// Tone change March 17, 1981  4:49 PM by Beau Sheil
// Chord change November 20, 1980  2:52 PM by Beau Sheil
// Previous last change August 18, 1980  12:31 PM by Beau Sheil

	get "AltoFileSys.d"
	get "Disks.d"
	get "LispBcpl.decl"
	get "Stats.decl"
	get "Streams.d"

external [	// defined here
	COPYSYS0SUBR

	OutputStream		// used by stats to access log file

		// statics used
	@lvNIL; @TopLevelFrame
	sysDisk; LispFmap; @MiscSTATSbase

		// O.S. procedures used
	Resets; Closes; WriteBlock; Zero; CallSwat; Min; MyFrame
	TruncateDiskStream; CreateDiskStream; ActOnDiskPages; WriteDiskPages 
	FlushDD

		// procedures used
	@BGetBase; @BSetBR; @XSetReadBR; @RRead
	@XGetBase; IGetBase; IPutBase
	EqNIL; RAIDCode; EmUnbox; EmAddr
	SmallUnbox; MkSmallPos; MkSmallNeg
	SysErr; IndexedPageIO
	]

manifest [
	lenCB = #25
	IFPcbstart = #200
	]

let GetFptrArg(lvFptr, f) be
   [
   XSetReadBR(lvFptr)
   for i = 0 to lFP-1 do f!i = RRead(i)
   ]

and HintError(s, cb, code) = valof	// BFS errors - diff args from SysErr
   [
   MyFrame()!0 = TopLevelFrame		// set return addr to return from SUBR
   resultis selecton code into		// error code switch
               [ case 1102: MkSmallNeg(-22)	// error 22 if disk full
                 case 1105: MkSmallNeg(-41)	// error 41 if protected
                 default:   SysErr(0, code) ]
  ] 

and OutputStream(lvFid) = valof
   [
   let fp = vec lFP; GetFptrArg(lvFid, fp)
   let st = CreateDiskStream(fp, ksTypeWriteOnly, wordItem, 0, StreamError)
   unless st do RAIDCode("Cant create stream", lvFid)
   resultis st
   ]

and COPYSYS0SUBR(lvFid) = valof
   [
   let st = OutputStream(lvFid)
   let pvec = vec 4*WordsPerPage
   Zero(pvec, WordsPerPage)
   WriteBlock(st, pvec, WordsPerPage)	// page 1 <- isf index page

   let Last = IGetBase(IFPNActivePages) + FirstVmemBlock - 1
   let i = FirstVmemBlock
   [ let np = Min(Last - i,  4)
     IndexedPageIO(LispFmap, i, pvec, np, 1)
     WriteBlock(st, pvec, np*WordsPerPage)
     i = i + np
   ] repeatuntil i ge Last

   TruncateDiskStream(st)			// in case using old file
   Resets(st); Closes(st)
   resultis lvNIL
   ]

and StreamError(s, code) = HintError(s, 0, code)	// adjust args for HintError