<> <> <> <> DIRECTORY CD, CDEnvironment, CDExtras, CDCommandOpsExtras, CDIO, CDOps, CDDirectory, CDPanel, CDProperties, CDSequencer, CDValue, CDViewer USING [CreateViewer], Commander USING [CommandProc, Register], CommandTool, Rope, TerminalIO; CDIOCommands: CEDAR PROGRAM IMPORTS CDDirectory, CD, CDCommandOpsExtras, CDEnvironment, CDExtras, CDIO, CDOps, CDPanel, CDProperties, CDSequencer, CDValue, CDViewer, Commander, CommandTool, Rope, TerminalIO = BEGIN IncludeCommand: PROC [comm: CDSequencer.Command] = BEGIN Forward: PROC [key: ATOM] = INLINE { CDSequencer.ExecuteCommand[comm: comm, key: key, queue: dontQueue]; }; yes: BOOL; TerminalIO.WriteRope["include an input design\n"]; TerminalIO.WriteRope[" (but usually people want to import other designs)\n"]; yes _ TerminalIO.Confirm[label: "you really want to include?", choice: "yes"]; TerminalIO.WriteRope[IF yes THEN " yes\n" ELSE " no, import\n"]; Forward[IF yes THEN $ReallyIncludeADesign ELSE $Import] END; MergeIn: PROC [design: CD.Design, from: CD.Design, name: Rope.ROPE_NIL] RETURNS [ob: CD.Object_NIL, pos: CD.Position] = <<--DANGEROUS PROC>> <<--"from" is transfered to an object, and is included (transitive) to "design"'s directory>> <<--"from" then may be resetted (preserving the rule: any object is in at most one directory)>> <<--the caller is assumed to have the locks of both designs>> <<--if "from" is pushed in, it's merged copy will be popped out, either by flushing, >> <<--replacing or creating new cells>> <<--"name" replaces "from"'s design name for the new created object, but it is a hint only>> <<--"pos": if "ob" is included at position "pos" in an empty design we would get "from" again>> <<--the "from"'s object's may change name to avoid conflicts with "design"'s directory>> <<--ob gets nil if "from" is empty>> <<--technologies must be compatible>> BEGIN SkipAt: PROC [n: Rope.ROPE] RETURNS [Rope.ROPE] = <<--skip everything after and inclusive first "@">> BEGIN RETURN [Rope.Substr[base: n, len: Rope.SkipTo[s: n, skip: "@"]]] END; IncludeOneEntry: CDDirectory.EachEntryAction = <<--[name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL_FALSE]-->> BEGIN IF NOT CDDirectory.Remove[design: from, name: name, expectObject: ob] THEN ERROR; [] _ CDDirectory.Include[design: design, object: ob, alternateName: SkipAt[name]]; CDProperties.PutObjectProp[ob, $CameFrom, from.name]; CDProperties.PutObjectProp[ob, $OriginalName, SkipAt[name]]; END; IF design=from THEN RETURN; IF design.technology#from.technology THEN RETURN WITH ERROR CD.Error[callingError, "MergIn design has different technology"]; [ob, pos] _ CDExtras.Cellize[from, name]; IF ob#NIL THEN { [] _ CDDirectory.Enumerate[design: from, action: IncludeOneEntry]; CDOps.ResetDesign[from]; } ELSE ob _ NIL END; ReallyIncludeCommand: PROC [comm: CDSequencer.Command] = BEGIN Check: PROC [design: CD.Design] RETURNS [ok: BOOL] = BEGIN ok _ design.technology=comm.design.technology; IF NOT ok THEN TerminalIO.WriteRopes["technology miss-match: includee is ", design.technology.name, "\n"]; END; done: BOOL _ FALSE; design: CD.Design; ob: CD.Object; pos: CD.Position; TerminalIO.WriteRope["include input design\n"]; design _ CDIO.ReadDesign[NIL, Check, CDEnvironment.GetWorkingDirectory[comm.design]]; IF design#NIL THEN { [ob, pos] _ MergeIn[design: comm.design, from: design]; IF ob#NIL THEN { [] _ CDCommandOpsExtras.PlaceInst[comm.design, ob, comm]; done _ TRUE; }; }; IF done THEN TerminalIO.WriteRope["include done\n"] ELSE TerminalIO.WriteRope["include not done\n"]; END; ReadCommand: Commander.CommandProc = BEGIN ENABLE { TerminalIO.UserAbort => GOTO UserAbrt; }; design: CD.Design; list: LIST OF Rope.ROPE; length: NAT; name: Rope.ROPE; result _ $Failure; [list, length] _ CommandTool.ParseToList[cmd]; IF length=0 THEN name_NIL ELSE IF length=1 THEN name _ list.first ELSE { msg _ "unknown arguments"; RETURN }; IF Rope.Length[name]>1 AND Rope.Fetch[name, 0] = '- THEN { tech: CD.Technology _ CDExtras.GetTechnology[Rope.Substr[name, 1, Rope.Length[name]]]; IF tech=NIL THEN {msg _ "technology not loaded"; RETURN}; design _ CDOps.CreateDesign[tech]; } ELSE design _ CDIO.ReadDesign[name]; IF design=NIL THEN msg _ "read not done" ELSE { [] _ CDViewer.CreateViewer[design]; result _ design; msg _ Rope.Concat["design ", IF design.name=NIL THEN "no name" ELSE design.name]; }; TerminalIO.WriteRopes[msg, "\n"]; EXITS UserAbrt => {result _ $Failure; msg _ "aborted"}; END; <<>> WriteCommand: PROC [comm: CDSequencer.Command] = BEGIN done: BOOL; to: REF_NIL; TerminalIO.WriteRope["write design to a file\n"]; IF comm.key=$SaveDesign THEN to _ CDValue.Fetch[comm.design, $CDxLastFile]; done _ CDIO.WriteDesign[design: comm.design, to: to]; IF done THEN TerminalIO.WriteRope["done\n"] ELSE { WITH to SELECT FROM r: Rope.ROPE => TerminalIO.WriteRopes["write to ", r, " "]; ENDCASE => NULL; TerminalIO.WriteRope["not done\n"]; }; IF ~done AND to#NIL AND comm.key=$SaveDesign THEN { comm.key _ $OutputDesign; WriteCommand[comm]; }; END; <<>> <<-- Module Initialization>> Commander.Register[ key: "///commands/CDRead", proc: ReadCommand, doc: "Read a ChipNDale design file" ]; Commander.Register[ key: "///commands/CDOpen", proc: ReadCommand, doc: "Open a ChipNDale design: CDOpen {file|-technology}" ]; CDSequencer.ImplementCommand[$ReallyIncludeADesign, ReallyIncludeCommand,, doQueue]; CDSequencer.ImplementCommand[$IncludeADesign, IncludeCommand,, doQueue]; CDSequencer.ImplementCommand[$OutputDesign, WriteCommand,, doQueue]; CDSequencer.ImplementCommand[$SaveDesign, WriteCommand,, doQueue]; CDPanel.DefineButton[tech: NIL, name: "save", command: $SaveDesign, topLine: TRUE]; END.