<> <> DIRECTORY Atom, FileIO, Inline, IO, Mnemonics, Rope, Rosemary, VFonts; MnemonicsImpl: CEDAR PROGRAM IMPORTS Atom, FileIO, Inline, IO, Rope, VFonts EXPORTS Mnemonics = BEGIN ROPE: TYPE = Rope.ROPE; WordPtr: TYPE = Rosemary.WordPtr; SignalType: TYPE = Rosemary.SignalType; SignalTypeRep: TYPE = Rosemary.SignalTypeRep; MnemData: TYPE = REF MnemDataRep; MnemDataRep: TYPE = RECORD [ bits: CARDINAL, members: SEQUENCE length: CARDINAL OF ROPE ]; Mnemonic: PUBLIC PROC [mnemName: ROPE] RETURNS [st: SignalType] = BEGIN fileName: ROPE; atom: ATOM; memList: LIST OF ROPE _ NIL; count, newCount, bits: CARDINAL _ 0; file: IO.STREAM; md: MnemData; saturated: BOOLEAN _ FALSE; atom _ Atom.MakeAtom[fileName _ mnemName.Concat[".mnemonics"]]; st _ NARROW[Atom.GetProp[atom: atom, prop: $mnemonicRoseImpl]]; IF st # NIL THEN RETURN; file _ FileIO.Open[fileName]; file.SkipOver[IO.WhiteSpace]; WHILE NOT file.EndOf[] DO mem: ROPE _ file.GetToken[IO.IDProc]; newCount: CARDINAL _ count + 1; overlap: CARDINAL _ Inline.BITAND[count, newCount]; IF saturated THEN bits _ bits + 1; saturated _ overlap = 0; count _ newCount; memList _ CONS[mem, memList]; file.SkipOver[IO.WhiteSpace]; ENDLOOP; file.Close[]; md _ NEW [MnemDataRep[count]]; md.bits _ bits; FOR i: CARDINAL DECREASING IN [0 .. md.length) DO md[i] _ memList.first; memList _ memList.rest; ENDLOOP; st _ NEW [Rosemary.SignalTypeRep _ [ toRope: ToRope, fromRope: FromRope, init: NIL, maxWidth: MaxWidth, parseTest: TestParse, unParseTest: TestUnParse, typeData: md]]; Atom.PutProp[atom: atom, prop: $mnemonicRoseImpl, val: st]; END; ToRope: PROC [where: WordPtr, typeData: REF ANY] RETURNS [rope: ROPE] = TRUSTED BEGIN md: MnemData _ NARROW[typeData]; index: CARDINAL _ Inline.BITAND[where^, masks[md.bits]]; RETURN [IF index >= md.length THEN "??" ELSE md[index]]; END; masks: ARRAY [0..16] OF CARDINAL = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535]; FromRope: PROC [rope: ROPE, where: WordPtr, typeData: REF ANY] RETURNS [success: BOOLEAN] = TRUSTED BEGIN md: MnemData _ NARROW[typeData]; i: CARDINAL; [i, success] _ Lookup[md, rope]; IF success THEN where^ _ i; END; Lookup: PROC [md: MnemData, rope: ROPE] RETURNS [index: CARDINAL, success: BOOLEAN] = BEGIN FOR i: CARDINAL IN [0 .. md.length) DO IF rope.Equal[md[i]] THEN RETURN [i, TRUE]; ENDLOOP; success _ FALSE; index _ 0; END; MaxWidth: PROC [typeData: REF ANY, font: VFonts.Font] RETURNS [INTEGER] = TRUSTED BEGIN md: MnemData _ NARROW[typeData]; mw: INTEGER _ 0; FOR i: CARDINAL IN [0 .. md.length) DO mw _ MAX[mw, VFonts.StringWidth[md[i], font]]; ENDLOOP; RETURN [mw]; END; TestParse: Rosemary.TestParseProc = BEGIN md: MnemData _ NARROW[typeData]; i: CARDINAL; [i, success] _ Lookup[md, rope]; IF success THEN testData _ NEW [CARDINAL _ i] ELSE testData _ NIL; testProc _ TestMnemonic; END; TestUnParse: Rosemary.TestUnParseProc = BEGIN md: MnemData _ NARROW[typeData]; rc: REF CARDINAL _ NARROW[testData]; rope _ IF rc = NIL THEN "??" ELSE md[rc^]; IF subject # NIL THEN rope _ subject.Cat["=", rope]; END; TestMnemonic: Rosemary.TestProc = TRUSTED BEGIN rc: REF CARDINAL _ NARROW[testData]; passes _ rc^ = where^; END; END.