// MDinit.bcpl -- process command line
// last edited March 25, 1981 4:01 PM
get "mddecl.d"
get "streams.d"
get "altofilesys.d"
get "altodefs.d"
external [ // defined here
Init // () -> sources
// Switches and parameters from command line
DebugFlag
DebugFirstLoc
DebugLastLoc
IgnoreOnPage
Kludge // see MDSCAN
ListAbs
ListingLevel
MapChart
MapIM
MapRM
MapOccupied
ListSymbols
TraceStorage
Version
Xternal
// Other statics
VersionString
StartDTString
OutputSource
MBSource
ScratchSource
DeleteScratch
]
external [
// OS
CreateDisplayStream; ShowDisplayStream
OpenFile
CreateDiskStream
Closes; Endofs; Gets; Puts; Resets; Wss
Allocate; Free; MoveBlock; Zero
fpComCm; fpSysDir
dsp
sysFont; sysZone
// GP
SetupReadParam; ReadParam; EvalParam
// MDI
LookupEntries
// TimeIO
CONVUDT
// Template
PutTemplate
// MDmain
Err
StoreString
MaxBlock
@OutputS; @MBS
@TempZone; @Zone
]
manifest [
nOutputs = 8
ldspLines = 6
ldspLinesSmall = 3
ldspBits = 5000b
ldspBitsSmall = 2000b
]
static [
// Switches and parameters from command line
DebugFlag = 0
DebugFirstLoc = 0
DebugLastLoc = IMsize-1
IgnoreOnPage = false
Kludge = false
LargeProgram = false
ListAbs = false
ListingLevel = listFull
MapChart = false
MapIM = false
MapRM = false
MapOccupied = false
ListSymbols = false
TraceStorage = false
Version = -1
Xternal = false
// Other statics
VersionString
StartDTString
OutputSource = 0
MBSource = 0
ScratchSource = 0
DeleteScratch = false
]
let Init() = valof
[ AllocateDisplay(ldspLines, ldspBits, TempZone)
VersionString = StoreString("*NMicroD 9.14 (OS 16) of March 25, 1981*N", Zone)
Wss(dsp, VersionString)
StartDTString = Allocate(Zone, 10)
CONVUDT(StartDTString, 0)
//Read and parse command line
let inExt = ".DIB"
// Following must be kept in order, with scratchExt last
let lstExt = ".DLS"
let outExt = ".MB"
let mapExt = ".csmap"
let regsExt = ".regs"
let occExt = "Occupied.mc"
let chartExt = ".cschart"
let absExt = ".absDLS"
let scratchExt = ""
let scratchName = "SWATEE"
let ComCmVec = vec 120
let StrVec,FlagVec = vec 100, vec 16
let OutVec = vec 100
@OutVec = 0
let ScratchVec = vec 100
@ScratchVec = 0
let S = OpenFile("Com.Cm",ksTypeReadOnly,charItem,0,fpComCm,0,TempZone)
let firstSource = 0
let lastSource = lv firstSource-(offset Source.next/16)
let NS = 0
//Read and parse global flags
SetupReadParam(StrVec, FlagVec, S, FlagVec)
GlobalFlags(FlagVec)
//Now handle names with local flags
let lastname = nil
while ReadParam(0, -1, StrVec, FlagVec) ne -1 do
[ if (StrVec!0 eq 1) & (StrVec!1 eq $~) then // additional global flags, not a file
[ GlobalFlags(FlagVec); loop ]
let lflag = ListingLevel
let nf = FlagVec!0
for i = 1 to nf do
switchon FlagVec!i & 137B into
[ case $A: lflag = listAbsOnly; endcase
case $C: lflag = listConcise; endcase
case $D: switchon (i eq nf? $*S, valof [ i = i+1; resultis FlagVec!i & 137B ]) into
[ case $*S: DebugFlag = EvalParam(StrVec, $B, "Debug: "); endcase
case $F: DebugFirstLoc = EvalParam(StrVec, $B, "First loc: "); endcase
case $L: DebugLastLoc = EvalParam(StrVec, $B, "Last loc: "); endcase
default: Err(NonFatal, "Undefined switch: $US/D$C", StrVec, FlagVec!i)
]
goto notsource
case $L: lflag = listFull; endcase
case $N: lflag = listNotIM; endcase
case $O:
if nf ne 1 then Err(Fatal, "/O with another switch")
EvalParam(StrVec, $P, 0, OutVec)
goto notsource
case $V:
if nf ne 1 then Err(Fatal, "/V with another switch")
Version = EvalParam(StrVec, $B, "Version: ")
goto notsource
case $Z:
if nf ne 1 then Err(Fatal, "/Z with another switch")
EvalParam(StrVec, $P, 0, ScratchVec)
goto notsource
default: Err(NonFatal, "Undefined switch: $US/$C", StrVec, FlagVec!i)
]
[ EvalParam(StrVec, $P)
let source = Extend(StrVec, inExt, false)
lastname = source>>Source.pName
source>>Source.lflag = lflag
lastSource>>Source.next = source
lastSource = source
NS = NS+1
]
notsource:
]
if NS eq 0 then Err(Fatal, "No input files")
if @OutVec eq 0 then MoveBlock(OutVec, lastname, 100)
if @ScratchVec eq 0 then MoveBlock(ScratchVec, scratchName, 100)
let nfiles = nOutputs+NS
let ff = firstSource
let names = Allocate(TempZone, nfiles)
let osv = vec nOutputs
for i = nOutputs-1 by -1 to 0 do
[ let s = Extend((i eq nOutputs-1? ScratchVec, OutVec), (lv lstExt)!i, true)
osv!i = s
s>>Source.next = ff
ff = s
]
let prvec = Allocate(Zone, nfiles*(lFP+1))
let i = 0
while ff ne 0 do
[ names!i = ff>>Source.pName
ff>>Source.pFP = prvec+i*(lFP+1)+1
i, ff = i+1, ff>>Source.next
]
OutputSource = osv!0
test ListingLevel eq -2 ifso names!1 = 0 ifnot MBSource = osv!1
test MapIM ifso MapIM = osv!2 ifnot names!2 = 0
test MapRM ifso MapRM = osv!3 ifnot names!3 = 0
test MapOccupied ifso MapOccupied = osv!4 ifnot names!4 = 0
test MapChart ifso MapChart = osv!5 ifnot names!5 = 0
test ListAbs ifso ListAbs = osv!6 ifnot names!6 = 0
test ListingLevel eq -2 ifso names!7 = 0 ifnot ScratchSource = osv!7
let DirS = CreateDiskStream(fpSysDir, ksTypeReadOnly, wordItem, 0, 0, TempZone)
let bufsize = MaxBlock(TempZone)
let buf = Allocate(TempZone, bufsize)
LookupEntries(DirS, names, prvec, nfiles, true, buf, bufsize)
Free(TempZone, buf, bufsize)
Closes(DirS)
let s = firstSource
while s ne 0 do
[ let pDE = s>>Source.pFP-1
if @pDE eq 0 then Err(PassFatal, "Can't open input file $S", s>>Source.pName)
s = s>>Source.next
]
OutputS = CheckOutput(osv!0, charItem, Zone)
MBS = (names!1 eq 0? 0, CheckOutput(osv!1, wordItem, Zone))
for i = 2 to nOutputs-1 do
if names!i ne 0 then
CheckOutput(osv!i, (i eq nOutputs-1? wordItem, charItem), 0)
ShowDisplayStream(dsp, DSdelete)
Free(sysZone, dsp) // Free the temporary display stream
test LargeProgram
ifso AllocateDisplay(ldspLinesSmall, ldspBitsSmall, Zone)
ifnot AllocateDisplay(ldspLines, ldspBits, Zone)
Wss(dsp, VersionString)
PutTemplate(OutputS, "$S at $S*N*N", VersionString, StartDTString)
Resets(S)
until Endofs(S) do Puts(OutputS, Gets(S))
Wss(OutputS, "*N*N")
resultis firstSource
]
and GlobalFlags(flagVec) be
// A subroutine so that one can add ~/f onto a command line
[ for i = 1 to flagVec!0 do
switchon flagVec!i & 137B into
[ case $A: ListingLevel = listAbsOnly; endcase // Absolute only
case $C: ListingLevel = listConcise; endcase // Concise, no octal
case $D: DebugFlag = -1; endcase // Debug MicroD
case $E: MapChart = true; endcase // chart Every location
case $H: ListAbs = true; endcase // abs listing for Hardware debugging
case $I: IgnoreOnPage = true; endcase // Ignore OnPage directives
case $K: Kludge = true; endcase
case $L: LargeProgram = true; endcase // large program, small display
case $M: MapIM = true; endcase // Map of IM by page
case $N: ListingLevel = listNotIM; endcase // No IM listing
case $O: MapOccupied = true; endcase // write Occupied location map
case $P: ListingLevel = listPrintMB; endcase // just Print the .MBs
case $R: MapRM = true; endcase // RM map
case $S: ListSymbols = true; endcase // Symbols for all memories
case $T: TraceStorage = true; endcase // Trace calls on allocator
case $X: Xternal = true; endcase // allow eXternal references
default: Err(NonFatal, "Undefined global switch /$C", flagVec!i)
]
]
and AllocateDisplay(nl, lbits, zone) be
[ let bits = Allocate(zone, lbits)
let ds = CreateDisplayStream(nl, bits, lbits, sysFont)
ShowDisplayStream(ds, DSalone)
dsp = ds
]
and Extend(name, ext, force) = valof
[ let v = vec 100
test ext>>BS.length eq 0
ifso v = name // scratch name
ifnot
[ MoveBlock(v, name, 100)
SetExt(v, ext, force)
]
let s = Allocate(Zone, lSource)
s>>Source.pName = StoreString(v, Zone)
resultis s
]
and SetExt(Str, Ext, force) be
[ let I = Str>>STRING.length
for J = 1 to I do
if Str>>STRING.char↑J eq $. then
[ unless force return
I = J-1; break
]
for J = 1 to Ext>>STRING.length do
[ I = I+1; Str>>STRING.char↑I = Ext>>STRING.char↑J
]
Str>>STRING.length = I
]
and CheckOutput(s, item, zone) = valof
[ let name, dv = s>>Source.pName, s>>Source.pFP-1
if @dv eq 0 then Closes(OpenFile(name, ksTypeWriteOnly, item, verLatestCreate, dv+1, 0, TempZone))
if zone eq 0 resultis 0
let st = CreateDiskStream(dv+1, ksTypeWriteOnly, item, 0, 0, zone)
if st eq 0 then Err(Fatal, "Can't open output file $S", name)
resultis st
]