<> <> <> <> <<>> DIRECTORY BridgeFTPOps USING [StoreFile, RetrieveFile], BridgeSubmit USING [TransferProc, Register], Commander, CommandTool, EcadOps, FS, FSExtras, IO, Rope, SymTab, TerminalIO; EcadOpsImpl: CEDAR MONITOR IMPORTS BridgeFTPOps, BridgeSubmit, Commander, CommandTool, FS, FSExtras, IO, Rope, SymTab, TerminalIO EXPORTS EcadOps ~ BEGIN ROPE: TYPE = Rope.ROPE; Key: TYPE = REF KeyRec; KeyRec: TYPE = RECORD [ msg: ROPE _ NIL, locked: BOOL _ TRUE, unlocked: CONDITION ]; cmdDoc: ROPE _ " TopLevelCellName rulesFileName \nSends CIF to Dracula"; host: ROPE _ "Velantia"; userName: ROPE _ NIL; passWord: ROPE _ NIL; remoteDir: ROPE _ "/palain/guest/ecad/spool/"; ecadCmd: ROPE _ "/usr/ecad/bin/dracula "; defaultRulesName: ROPE _ "VTI"; cifExt: ROPE _ ".cif"; logExt: ROPE _ ".drc.log"; errorsExt: ROPE _ ".errors.cif"; logFile: ROPE _ "DRCLOG.SUM"; --highly flexible name startText: ROPE _ "(LINE SEGMENTS)"; stopText: ROPE _ "PRIMARY CELL :"; noError: PUBLIC ROPE _ "No Errors !!!"; lock: BOOLEAN _ FALSE; keyTable: SymTab.Ref _ SymTab.Create[]; msgStream: IO.STREAM _ TerminalIO.TOS[]; <> ECADCmd: Commander.CommandProc ~ { <> topCellName, rulesFName: ROPE; args: CommandTool.ArgumentVector = CommandTool.Parse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO fail}; ]; nArgs: NAT = args.argc; IF nArgs<2 THEN GO TO fail; topCellName _ args[1]; rulesFName _ IF nArgs>2 THEN args[2] ELSE defaultRulesName; IF lock THEN { msg _ "\nWait for the previous DRC to finish !\nJob not sent.\n"; GO TO fail; }; <> msg _ ExecuteRemoteECAD[topCellName, rulesFName]; IF msg#NIL AND msg#noError THEN GO TO fail; EXITS fail => result _ $Failed; }; ExecuteRemoteECAD: PUBLIC PROC [topCellName, rules: ROPE] RETURNS [errmsg: ROPE] ~ { cmd: ROPE; wDir: ROPE _ FSExtras.GetWDir[]; [] _ SymTab.Store[keyTable, topCellName, NEW[KeyRec]]; lock _ TRUE; cmd _ Rope.Cat[ecadCmd, topCellName, " ", rules]; errmsg _ BridgeSubmit.Register[host, topCellName, cmd, wDir, Store, Retrieve, userName, passWord, remoteDir]; IF errmsg#NIL THEN lock _ FALSE; }; <> Store: BridgeSubmit.TransferProc ~ { <> localName : ROPE _ Rope.Cat[wDir, id, cifExt]; remoteName: ROPE _ Rope.Cat[remoteDir, id, cifExt]; msg _ BridgeFTPOps.StoreFile[s, remoteName, localName, msgStream]; IF msg # NIL THEN { Ok[id, msg]; RETURN[msg]}; }; <<>> Retrieve: BridgeSubmit.TransferProc ~ { <> localName : ROPE _ Rope.Cat[wDir, id, logExt]; remoteName: ROPE _ Rope.Cat[remoteDir, logFile]; msg _ BridgeFTPOps.RetrieveFile[s, remoteName, localName, msgStream]; lock _ FALSE; IF msg # NIL THEN { Ok[id, msg]; RETURN[msg]}; IF CheckForErrors[localName, msgStream] THEN { localName _ Rope.Cat[wDir, id, errorsExt]; remoteName _ Rope.Cat[remoteDir, id, errorsExt]; msg _ BridgeFTPOps.RetrieveFile[s, remoteName, localName, msgStream]; } ELSE msg _ noError; Ok[id, msg] }; <<>> CheckForErrors: PROC [logName: Rope.ROPE, outStream: IO.STREAM] RETURNS [hasErrors: BOOLEAN _ FALSE] ~ { l: Rope.ROPE _ NIL; logFile: IO.STREAM; logFile _ FS.StreamOpen[logName, read]; UNTIL Rope.Find[s1: l, s2: startText]#-1 DO l _ IO.GetLineRope[logFile]; ENDLOOP; [] _ IO.SkipWhitespace[logFile]; l _ IO.GetLineRope[logFile]; UNTIL Rope.Find[s1: l, s2: stopText]#-1 DO hasErrors _ TRUE; IO.PutRope[outStream, Rope.Cat[l, "\n"]]; [] _ IO.SkipWhitespace[logFile]; l _ IO.GetLineRope[logFile]; ENDLOOP; }; <> WaitForOk: PUBLIC ENTRY PROC[id: ROPE] RETURNS[msg: ROPE]~ { ENABLE UNWIND => NULL; key: Key _ NARROW[SymTab.Fetch[keyTable, id].val]; WHILE key.locked DO WAIT key.unlocked ENDLOOP; RETURN [key.msg]; }; Unlock: ENTRY PROC [key: Key] ~ { ENABLE UNWIND => NULL; key.locked _ FALSE; BROADCAST key.unlocked; }; Ok: PROC [id, msg: ROPE] ~ { key: Key _ NARROW[SymTab.Fetch[keyTable, id].val]; IF key = NIL THEN RETURN; [] _ SymTab.Delete[keyTable, id]; key.msg _ msg; Unlock[key]; }; <> Commander.Register[key: "EcadOps", proc: ECADCmd, doc: cmdDoc]; TerminalIO.PutRope["EcadOps loaded\n"]; END.