// Main Program for MICRO
// last edited December 26, 1979 8:33 AM
// Copyright Xerox Corporation 1979
get "micdecl.d"
get "streams.d"
get "altofilesys.d"
get "sysdefs.d"
external
[ // O.S.
CreateDisplayStream; ShowDisplayStream
ReadCalendar
FilePos
OpenFile; Puts; Closes
TruncateDiskStream
CounterJunta
MoveBlock
Noop
sysFont
dsp
// EasyJunta
EasyJunta
// LoadOverlay
LoadOverlay
]
manifest [
StackSize = 5000b
ldspData = 5000b
nKS = 7 // in, out, lst, er, fix, +2 for OpenFile
lSysZone = nKS*(lKS+400b+10)+40 // don't know why the extra is needed, but it is
lvCodeTop = 335b
]
static
[ saveDsp
stime
ttime
nullout
]
let micro(blv, params, cfa) be
[ saveDsp = dsp
EasyJunta(levDisplay, micro1, cfa, lCFA, lSysZone)
]
and micro1(cfa) be
[ let dspData = vec ldspData
let ds = CreateDisplayStream(6, dspData, ldspData, sysFont)
ShowDisplayStream(ds, DSalone)
dsp = ds
let femb = "MB"
let StartTime = vec 1
ReadCalendar(StartTime)
stime = StartTime!1
let mbfile = vec filenamelength
freestoretop(0)
let top = fstop
let sources = micinit(mbfile)
@lvCodeTop = micinit // Flush initialization code
freestoretop(fstop+fsbot) // Expand free area
test inchan eq 0
ifso // Create symtab
[ initsym(131, 200b)
defbi(table[ $B;$U;$I;$L;$T;$I;$N], 7, biBUILTIN)
defbi(table[ $I;$N;$S;$E;$R;$T], 6, biINSERT)
]
ifnot // Restore save file
[ srecover(inchan)
close(inchan)
initsym()
recsym()
]
ofbot = fsbot
@lvCodeTop = top+1 // set stack limit
// Initialize fake outchan
let os = vec lST
os>>ST.par1 = mbfile
os>>ST.puts = firstput
fakeoutchan = os
outchan = os
let no = vec lST
no>>ST.puts = Noop
no>>ST.close = Noop
no>>ST.type = not stTypeDisk // for close
nullout = no
initacc()
initin()
initmac()
initmac1()
initout(femb)
initscan()
lchan = lstchan
while sources ne 0 do
[ initreadstat(ucflag % sources!1)
let arg = sources+(2+lFP)
if not inpush(arg, sources+2) then
errx("SOURCE FILE @L DOES NOT EXIST",true,arg)
while readstat() do
test @stbuf eq $:
ifso [ @stbuf = endc; assem() ] // ignore :, always process
ifnot unless ignore do assem() // don't process if ignoring
sources = sources!0
]
if symchan ne 0 then
[ dumpsym()
sdump(symchan)
close(symchan)
recsym()
]
let limit = fstop+fsbot
fsfix(LoadOverlay(cfa, initin, limit), limit) // release main program, load end code
endout()
endlist(xlistflag)
endmic()
]
and defbi(ap, l, i) be
// Predefine a BUILTIN
[ lookup(ap, l)
putin(bitype)!bsno = i
]
and endmic() be
[ let EndTime = vec 1
ReadCalendar(EndTime)
ttime = EndTime!1-stime
summary(ettchan)
closeall()
ShowDisplayStream(dsp, DSdelete)
CounterJunta(micro2)
]
and micro2() be
[ dsp = saveDsp
summary(dsp)
finish
]
and summary(strm) be
[ lchan = strm
llstr("*NTime: ")
ldec(ttime)
llstr(" seconds; ")
if errcnt ne 0 then
[ ldec(errcnt)
llstr(" error(s), ")
]
if warncnt ne 0 then
[ ldec(warncnt)
llstr(" warning(s), ")
]
ldec(fsgap)
llstr(" words free*N")
]
and firstput(os, wd) be
// Called on first Puts(outchan, --). Really opens outchan.
[ unless binflag do // No output
[ outchan = nullout; return ]
if os eq outchan then // otherwise, old outchan was copied somewhere
[ filext(os>>ST.par1, nil, mbext+fstop)
outchan = OpenFile(os>>ST.par1, ksTypeWriteOnly, wordItem, verLatestCreate)
]
Puts(outchan, wd)
]
and putboth(st, ch) be
// This is Puts for a splitter stream
[ Puts(st>>ST.par1, ch)
Puts(st>>ST.par2, ch)
]
and filext(res,org,ext) = valof
// If res is empty, copy org into res forcing the extension to ext
// If res is not empty, add ext as its extension if it has none
[ let empty = @res eq 0
if empty then copyfile(res, org)
let len = length(res)
let i = 1
while i le len do
[ if res>>BS.char↑i eq $. break
i = i+1
]
if empty % (i gr len) then
[ res>>BS.char↑i = $.
for j = 1 to length(ext) do
res>>BS.char↑(i+j) = ext>>BS.char↑j
res>>BS.length = i+length(ext)
]
resultis res
]
and copyfile(tofile,fromfile) be
// Copies a bcpl string.
MoveBlock(tofile,fromfile,(length(fromfile)+2) rshift 1)
and freestoretop(fst) be
// Set top of free storage
[ if fst eq 0 then fst = (lv fst)-StackSize
fsfix(@lvCodeTop, fst)
fstop = fst
// Initialize allocator variables
fsbot = -1
fstop!-1 = 0
slfl = 0
srover = 0
]
and fsfix(bot, top) be
[ if (top-bot) le 0 then // more than 32K, arithmetic fails
bot = top-77777b
fslim = bot
]
and close(str) be
[ if (str eq 0) % (str>>ST.type ne stTypeDisk) return
let pos = vec 1
FilePos(str,pos)
if (pos!0 eq 0) & (pos!1 eq 0) then TruncateDiskStream(str)
Closes(str)
]
and closeall() be
[ close(lstchan)
close(erlchan)
close(outchan)
]