<> <> <> <> DIRECTORY Ascii USING [SP], Basics USING [LongNumber], Convert USING [DefaultUnsigned, Parse, Value], ConvertUnsafe USING [ToRope], FileIO USING [Open], IO USING [card, Close, PFCodeProc, PutChar, PutF, PutRope, rope, SetPFCodeProc, STREAM], MB USING [Handle, MakeBootVersion], Rope USING [Cat, Fetch, Index, Length, Substr, ROPE], RopeIO USING [FromFile], Segments USING [FHandle, NameForFile], TiogaFileOps USING [AddLooks, CreateRoot, InsertNode, Ref, SetContents, Store]; MBLoadmap: PROGRAM IMPORTS Convert, ConvertUnsafe, FileIO, IO, MB, Rope, RopeIO, Segments, TiogaFileOps EXPORTS MB = BEGIN data: MB.Handle _ NIL; InitLoadmap: PUBLIC PROC [h: MB.Handle] = {data _ h}; FinishLoadmap: PUBLIC PROC = { IF data.loadmap ~= NIL THEN { SetFixedPitchOnLoadmap: PROC = { OPEN TiogaFileOps; root: Ref = CreateRoot[]; node: Ref = InsertNode[root, TRUE]; wholeMap: Rope.ROPE = RopeIO.FromFile[data.loadmapName]; SetContents[node, wholeMap]; AddLooks[x: node, start: 0, len: wholeMap.Length[], look: 'f, root: root]; Store[root, data.loadmapName]; }; data.loadmap.Close[]; data.loadmap _ NIL; SetFixedPitchOnLoadmap[]; }; data _ NIL; }; OpenLoadmap: PUBLIC PROC = { loadmap: IO.STREAM = FileIO.Open[data.loadmapName, overwrite]; loadmap.PutF["%g\N\NLoadmap for boot file: %g %t\NBuilt by: %g\N\N", IO.rope[data.loadmapName], IO.rope[data.output], IO.card[data.buildTime], IO.rope[MB.MakeBootVersion[]]]; loadmap.SetPFCodeProc['f, FileName]; loadmap.SetPFCodeProc['j, JustifiedRope]; loadmap.SetPFCodeProc['n, Numeric]; loadmap.SetPFCodeProc['s, Spaces]; loadmap.SetPFCodeProc['z, Boolean]; data.loadmap _ loadmap; }; FileName: IO.PFCodeProc = TRUSTED { <<%f: Argument is a Segment.FHandle LOOPHOLEd into a LONG CARDINAL.>> WITH v: val SELECT FROM cardinal => { ln: Basics.LongNumber = [lc[v.value]]; f: Segments.FHandle = LOOPHOLE[ln.lowbits]; name: STRING _ [40]; r: Rope.ROPE; at: INT; Segments.NameForFile[name, f]; r _ ConvertUnsafe.ToRope[name]; at _ r.Index[s2: ".bcd", case: FALSE]; IF at = r.Length[]-4 OR (at = r.Length[]-5 AND r.Fetch[at+4] = '.) THEN r _ r.Substr[len: at]; stream.PutRope[r]; }; ENDCASE => ERROR; }; Spaces: IO.PFCodeProc = TRUSTED { <<%s: Argument is number of spaces to insert.>> WITH v: val SELECT FROM cardinal => THROUGH [0..v.value) DO stream.PutChar[Ascii.SP] ENDLOOP; ENDCASE => ERROR; }; JustifiedRope: IO.PFCodeProc = TRUSTED { <<%nj: Outputs argument rope, then sufficient spaces to total "n".>> WITH v: val SELECT FROM rope => { value: Convert.Value = Convert.Parse[text: [rope[format.form]], template: Convert.DefaultUnsigned, pos: format.first].value; limit: INT = WITH v: value SELECT FROM unsigned => v.unsigned, ENDCASE => ERROR; stream.PutRope[v.value]; THROUGH [v.value.Length[]..limit) DO stream.PutChar[Ascii.SP] ENDLOOP; }; ENDCASE => ERROR; }; Numeric: IO.PFCodeProc = TRUSTED { <<%n: Outputs in octal unless data.hexLoadmap, then hex.>> WITH v: val SELECT FROM cardinal => { f: Rope.ROPE = format.form.Substr[ start: format.first, len: format.form.Index[pos1: format.first, s2: "n", case: FALSE]-format.first ]; stream.PutF[Rope.Cat["%", f, IF data.hexLoadmap THEN "x" ELSE "b"], IO.card[v.value]]; }; ENDCASE => ERROR; }; Boolean: IO.PFCodeProc = TRUSTED { <<%z: Single character Boolean output (T or F).>> WITH v: val SELECT FROM boolean => stream.PutChar[IF v.value THEN 'T ELSE 'F]; ENDCASE => ERROR; }; END.