// OsUtils.bcpl - OS Utilities
// Copyright Xerox Corporation 1979
// Last modified October 28, 1978  9:21 PM by Boggs

get "AltoFileSys.d"

external
[
// outgoing procedures
Wss; Ws; Wl; Wns; Wos; Wo
GetFixed; FreeFixed; FixedLeft; SetEndCode; GetFixedInit

// Incoming procedures
Gets; Puts; Closes; Endofs; Resets
Usc; DefaultArgs

// incoming statics
dsp
]

static freeFixedList	//List of free blocks for FreeFixed

manifest
[
// For free storage stuff
fixedSlop = 100
codePtr = #335
stackOffset = 4
]

//----------------------------------------------------------------------------
let Wss(stream, string) be
//----------------------------------------------------------------------------
   for i = 1 to string>>STRING.length do
      Puts(stream, string>>STRING.char↑i)

//----------------------------------------------------------------------------
and Ws(string) be Wss(dsp, string)
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
and Wl(string) be [ Ws(string); Puts(dsp, $*N) ]
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
and Wns(stream, number, width, radix; numargs na) be
//----------------------------------------------------------------------------
// Do numeric output to stream.
// Suppresses leading spaces if you tell it to, even if the radix is 8.
[
DefaultArgs(lv na, -2, 1, -10)  // Default width = 1, wadix = 10, signed
let v = vec 16  // Max space needed for unpacked digits
let negative = false
if radix ls 0 then
   [
   radix = -radix
   if number ls 0 then
      [
      number = -number
      negative = true
      width = width-1  // Space for minus sign
      ]
   ]

let i = 0
   [
   v!i = (table	// Divide num by radix, put quotient back in num,
      [		//  and return remainder.
       #55001	// sta 3 1 2
      #155000	// mov 2 3	// preserve frame pointer
       #31407	// lda 2 7 3	// get Radix from frame
       #25405	// lda 1 5 3	// get Num from frame
      #102460	// mkzero 0 0	// high dividend  =  0
       #61021	// div
       #77400	// Swat		// if divide fails
       #45405	// sta 1 5 3	// store quotient back into Num
      #171000	// mov 3 2	// recover frame
       #35001	// lda 3 1 2
        #1401	// jmp 1 3
      ])()
   i = i+1
   ] repeatwhile number ne 0

while width gr i do [ Puts(stream, $*s); width = width-1]
if negative then Puts(stream, $-)
while i ne 0 do [ i = i-1; Puts(stream, $0+v!i) ]
]

//----------------------------------------------------------------------------
and Wos(stream, number) be Wns(stream, number, 6, 8)
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
and Wo(number) be Wos(dsp, number)
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
and GetFixedInit() be freeFixedList = 0
//----------------------------------------------------------------------------

// Note: If you edit GetFixed to require a larger frame, see comment
// in FixedLeft below.

//----------------------------------------------------------------------------
and GetFixed(nwords) = valof
//----------------------------------------------------------------------------
[
let stackBot = lv nwords - stackOffset
let p = @codePtr
let newCodeTop = p + nwords +1

if Usc(newCodeTop+fixedSlop, stackBot) ge 0 then resultis 0

p!0 = nwords
@codePtr = newCodeTop
resultis p +1
]

//----------------------------------------------------------------------------
and FreeFixed(p) be
//----------------------------------------------------------------------------
[
p = p -1
if p + p!0+1 eq @codePtr then
   [
   @codePtr = p
   let oldFFL = freeFixedList
   freeFixedList = 0

   // The loop scans down the list, and the recursion takes
   // care of looking again at blocks which have already been
   // scanned, to see if they are now eligible
   while oldFFL ne 0 do
      [
      let t = oldFFL
      oldFFL = oldFFL!1
      FreeFixed(t+1)
      ]
   return
   ]
p!1 = freeFixedList; freeFixedList = p
]


//----------------------------------------------------------------------------
and FixedLeft(dummy) = valof
//----------------------------------------------------------------------------
[
let stackBot = lv dummy - stackOffset
// -6 in following line is to compensate for two things:
//	1. Difference in frame sizes of GetFixed and FixedLeft, which
//		causes stackBot to be computed differently.
//	2. The fact that GetFixed requires a block one bigger than the
//		request in order to satisfy it.
resultis stackBot - @codePtr - fixedSlop - 6
]

//----------------------------------------------------------------------------
and SetEndCode(address) be @codePtr = address
//----------------------------------------------------------------------------