<> <> DIRECTORY Atom, ConvertUnsafe, Directory, FileIO, Inline, IO, Rope, RoseTranslateTypes, System; MnemonicsTranslation: CEDAR PROGRAM IMPORTS Atom, ConvertUnsafe, Directory, FileIO, Inline, IO, Rope, RoseTranslateTypes, System = BEGIN ROPE: TYPE = Rope.ROPE; Mnemonic: TYPE = REF MnemonicRep; MnemonicRep: TYPE = RECORD [ name: ROPE, mesaTypeDecl, roseType: ROPE _ NIL, analyzeSinceEpoch: LONG CARDINAL, bits: CARDINAL _ 0]; ConstructMnemonic: RoseTranslateTypes.SignalTypeConstructor = TRUSTED BEGIN asAny: REF ANY _ RoseTranslateTypes.GetParm[1, "file", parms]; mnemName, fileName: ROPE; atom: ATOM; need: BOOLEAN _ TRUE; fileString: LONG STRING _ [256]; tempString: LONG STRING _ [256]; fileTime: System.GreenwichMeanTime; fileSinceEpoch: LONG CARDINAL; fileExists: BOOLEAN _ TRUE; WITH asAny SELECT FROM q: RoseTranslateTypes.Quoted => mnemName _ q.rope; ENDCASE => ERROR RoseTranslateTypes.TypeConstructionError["Mnemonic constructor not given a quoted string"]; IF mnemName.Length[] < 1 THEN ERROR RoseTranslateTypes.TypeConstructionError["Mnemonic constructor given an empty string"]; atom _ Atom.MakeAtom[fileName _ mnemName.Concat[".mnemonics"]]; type _ NARROW[Atom.GetProp[atom: atom, prop: $mnemonicRoseType]]; ConvertUnsafe.AppendRope[fileString, fileName]; fileTime _ Directory.GetProps[Directory.Lookup[fileString !Directory.Error => {fileExists _ FALSE; CONTINUE}], tempString].createDate; IF NOT fileExists THEN BEGIN IF type = NIL THEN ERROR RoseTranslateTypes.TypeConstructionError[IO.PutFR["File %g not found", IO.rope[fileName]]]; RETURN; END; fileSinceEpoch _ System.SecondsSinceEpoch[fileTime]; IF type # NIL THEN BEGIN mnem: Mnemonic _ NARROW[type.data]; need _ fileSinceEpoch > mnem.analyzeSinceEpoch; END; IF need THEN BEGIN mnem: Mnemonic _ NEW [MnemonicRep _ [ name: mnemName, roseType: IO.PutFR["Mnemonic[\"%g\"]", IO.rope[mnemName]], mesaTypeDecl: IO.PutFR["%g: TYPE = {", IO.rope[mnemName]], analyzeSinceEpoch: fileSinceEpoch]]; file: IO.STREAM _ FileIO.Open[fileName]; count: CARDINAL _ 0; goingToNextBit: BOOLEAN _ FALSE; file.SkipOver[IO.WhiteSpace]; WHILE NOT file.EndOf[] DO member: ROPE _ file.GetToken[IO.IDProc]; newCount: CARDINAL _ count + 1; overlap: CARDINAL _ Inline.BITAND[count, newCount]; IF count > 0 THEN mnem.mesaTypeDecl _ mnem.mesaTypeDecl.Concat[", "]; mnem.mesaTypeDecl _ mnem.mesaTypeDecl.Concat[member]; IF goingToNextBit THEN mnem.bits _ mnem.bits + 1; goingToNextBit _ overlap = 0; count _ newCount; file.SkipOver[IO.WhiteSpace]; ENDLOOP; file.Close[]; IF count = 0 THEN ERROR RoseTranslateTypes.TypeConstructionError[IO.PutFR["No names in mnemonic file %g", IO.rope[fileName]]]; mnem.mesaTypeDecl _ mnem.mesaTypeDecl.Concat["}"]; IF type # NIL THEN type.data _ mnem ELSE type _ NEW [RoseTranslateTypes.SignalTypeRep _ [mnemProcs, mnem]]; Atom.PutProp[atom: atom, prop: $mnemonicRoseType, val: type]; END; END; mnemProcs: RoseTranslateTypes.SignalTypeProcs _ NEW [RoseTranslateTypes.SignalTypeProcsRep _ [ Info: Info, Describe: Describe, Cannonize: Cannonize, MesaTypeDecl: MesaTypeDecl]]; Info: PROC [data: REF ANY] RETURNS [bitWidth: INT, roseType, mesaType: ROPE] = BEGIN mnem: Mnemonic _ NARROW[data]; bitWidth _ mnem.bits; roseType _ mnem.roseType; mesaType _ mnem.name; END; Describe: PROC [data: REF ANY] RETURNS [description: ROPE] = BEGIN mnem: Mnemonic _ NARROW[data]; description _ IO.PutFR["Mnemonic[\"%g\"]", IO.rope[mnem.name]]; END; Cannonize: PROC [data: REF ANY] RETURNS [cannonized: REF ANY] = {cannonized _ data}; MesaTypeDecl: PROC [data: REF ANY] RETURNS [mesaTypeDecl: ROPE] = BEGIN mnem: Mnemonic _ NARROW[data]; mesaTypeDecl _ mnem.mesaTypeDecl; END; RoseTranslateTypes.RegisterSignalTypeConstructor["Mnemonic", ConstructMnemonic]; END.