<> <> <> <> <> <> DIRECTORY Ascii USING [SP], BasicTime USING [minutesPerHour, Unpack, Unpacked], Convert USING [CardFromRope], FS USING [StreamOpen], IO USING [card, char, Close, PutChar, PutF, PutRope, rope, STREAM, time, Value], IOUtils USING [CopyPFProcs, PFCodeProc, PFProcs, SetPFCodeProc, SetPFProcs], MB USING [Handle, MakeBootVersion], Rope USING [Cat, FromChar, Index, Length, Substr, ROPE], RopeFile USING [SimpleCreate], TiogaFileOps USING [AddLooks, CreateRoot, InsertNode, Ref, SetContents, Store]; MBLoadmap: CEDAR PROGRAM IMPORTS BasicTime, Convert, FS, IO, IOUtils, MB, Rope, RopeFile, TiogaFileOps EXPORTS MB = BEGIN ROPE: TYPE = Rope.ROPE; 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 = RopeFile.SimpleCreate[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 = FS.StreamOpen[data.loadmapName, $create]; procs: IOUtils.PFProcs = IOUtils.CopyPFProcs[loadmap]; loadmap.PutF["%g\N\NLoadmap for boot file: %g %t\NBuilt by: %g\N\N", IO.rope[data.loadmapName], IO.rope[data.output], IO.time[data.buildTime], IO.rope[MB.MakeBootVersion[]]]; [] _ IOUtils.SetPFCodeProc[procs, 'f, FileName]; [] _ IOUtils.SetPFCodeProc[procs, 'j, JustifiedRope]; [] _ IOUtils.SetPFCodeProc[procs, 'n, Numeric]; [] _ IOUtils.SetPFCodeProc[procs, 's, Spaces]; [] _ IOUtils.SetPFCodeProc[procs, 't, Time]; [] _ IOUtils.SetPFCodeProc[procs, 'z, Boolean]; [] _ IOUtils.SetPFProcs[loadmap, procs]; data.loadmap _ loadmap; }; FileName: IOUtils.PFCodeProc = TRUSTED { <<%f: Argument is a ROPE.>> WITH val SELECT FROM v: rope IO.Value => { r: ROPE = v.value; stream.PutRope[r.Substr[len: r.Index[pos1: r.Length[]-4, s2: ".bcd", case: FALSE]]]; }; ENDCASE => ERROR; }; Spaces: IOUtils.PFCodeProc = TRUSTED { <<%s: Argument is number of spaces to insert.>> WITH val SELECT FROM v: cardinal IO.Value => THROUGH [0..v.value) DO stream.PutChar[Ascii.SP] ENDLOOP; ENDCASE => ERROR; }; JustifiedRope: IOUtils.PFCodeProc = TRUSTED { <<%nj: Outputs argument rope, then sufficient spaces to total "n".>> WITH val SELECT FROM v: rope IO.Value => { limit: INT = Convert.CardFromRope[format.form.Substr[ start: format.first, len: format.form.Index[pos1: format.first, s2: Rope.FromChar[char], case: FALSE] - format.first ]]; stream.PutRope[v.value]; THROUGH [v.value.Length[]..limit) DO stream.PutChar[Ascii.SP] ENDLOOP; }; ENDCASE => ERROR; }; Numeric: IOUtils.PFCodeProc = TRUSTED { <<%n: Outputs in octal unless data.hexLoadmap, then hex.>> WITH val SELECT FROM v: cardinal IO.Value => { f: 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; }; Time: IOUtils.PFCodeProc = TRUSTED { <<%t: old-style time output.>> WITH val SELECT FROM v: time IO.Value => { up: BasicTime.Unpacked = BasicTime.Unpack[v.value]; months: ROPE = "JanFebMarAprMayJunJulAugSepOctNovDec"; ConvertZone: PROC = TRUSTED { dst: BOOL = up.dst = yes; mph: NAT = BasicTime.minutesPerHour; SELECT up.zone FROM 0 => IF ~dst THEN stream.PutRope["GMT"]; NAT[5*mph] => stream.PutRope[IF dst THEN "EDT" ELSE "EST"]; NAT[6*mph] => stream.PutRope[IF dst THEN "CDT" ELSE "CST"]; NAT[7*mph] => stream.PutRope[IF dst THEN "MDT" ELSE "MST"]; NAT[8*mph] => stream.PutRope[IF dst THEN "PDT" ELSE "PST"]; ENDCASE => stream.PutF["%g%02d%02d", IO.char[IF up.zone < 0 THEN '- ELSE '+], IO.card[up.zone.ABS/mph], IO.card[up.zone.ABS MOD mph] ] }; stream.PutF["%02d-%g-%02d ", IO.card[up.day], IO.rope[months.Substr[start: up.month.ORD*3, len: 3]], IO.card[up.year MOD 100] ]; stream.PutF["%02d:%02d:%02d ", IO.card[up.hour], IO.card[up.minute], IO.card[up.second]]; ConvertZone[]; }; ENDCASE => ERROR; }; Boolean: IOUtils.PFCodeProc = TRUSTED { <<%z: Single character Boolean output (T or F).>> WITH val SELECT FROM v: boolean IO.Value => stream.PutChar[IF v.value THEN 'T ELSE 'F]; ENDCASE => ERROR; }; END.