<> <> <> DIRECTORY CD, CDApplications, CDCallSpecific, CDDirectory, CDEvents, CDInline, CDIO, CDIOExtras, CDOps, CDOrient, CDProperties, CDSequencer, CDValue, FileNames, List, ProcessProps, Rope, TerminalIO, TokenIO; CDReferencesImpl: CEDAR PROGRAM IMPORTS CD, CDApplications, CDDirectory, CDEvents, CDInline, CDIO, CDIOExtras, CDOps, CDOrient, CDSequencer, CDValue, FileNames, List, ProcessProps, Rope, TerminalIO, TokenIO SHARES CDDirectory = BEGIN <<-- Terminology>> <<-- importee: design (like module) which is imported>> <<-- entry: object (like variable or procedure) >> <<-- localName: mostly importeeName.entryName>> <<>> <<-- no design is allowed to make circular imports>> ReferencePtr: TYPE = REF ReferenceRep; ReferenceRep: TYPE = RECORD [ boundApp: CD.ApplicationPtr_NIL, -- NIL means not yet bound entryName: Rope.ROPE, importeeName: Rope.ROPE, localName: Rope.ROPE <<--XXX key business not yet impl>> ]; <<-- all references must be accessible, to allow postboned binding>> ImportList: TYPE = RECORD [list: LIST OF REF Import]; -- describes all the imports of a design Import: TYPE = RECORD[ -- describes imports of one particular importee-design importeeName: Rope.ROPE, importee: CD.Design_NIL, -- NIL means not yet bound referenceList: LIST OF CD.ObPtr_NIL ]; pForReference: REF CD.ObjectProcs = CD.RegisterObjectType[$Reference]; SetName: PROC [me: CD.ObPtr, r: Rope.ROPE] = BEGIN rp: ReferencePtr = NARROW[me.specificRef]; rp.localName _ r END; Name: PROC [me: CD.ObPtr] RETURNS [Rope.ROPE] = BEGIN rp: ReferencePtr = NARROW[me.specificRef]; RETURN [rp.localName] END; Key: PROC [me: CD.ObPtr] RETURNS [Rope.ROPE] = BEGIN rp: ReferencePtr = NARROW[me.specificRef]; <<--XXX key business not yet impl>> RETURN [NIL] END; ComputeBounds: CD.RectProc --PROC [ob: ObPtr] RETURNS [DesignRect]-- = BEGIN rp: ReferencePtr ~ NARROW[ob.specificRef]; sz: CD.DesignPosition ~ IF rp.boundApp#NIL THEN rp.boundApp.ob.size ELSE ob.size; RETURN [CDInline.RectAt[[0, 0], sz]] END; EnumerateItsObjects: PROC [me: CD.ObPtr, p: CDDirectory.EnumerateObjectsProc, x: REF] = {--DON'T, they are not directly accessible--}; AdjustItself: CDDirectory.AdjustItselfProc -- PROC [objToReposition: CD.ObPtr, newBound: CD.DesignRect] -- = BEGIN rp: ReferencePtr ~ NARROW[objToReposition.specificRef]; IF rp.boundApp#NIL THEN{ objToReposition.size _ rp.boundApp.ob.size }; END; RepositionElements: CDDirectory.RepositionElementsProc -- PROC [me: CD.ObPtr, objToReposition: CD.ObPtr, oldSize: CD.DesignPosition, newBound: CD.DesignRect, design: CD.Design] -- = {--there is nothing to do--}; InternalCreateReference: PROC [design: CD.Design, size: CD.DesignPosition, entryName, importeeName, localName: Rope.ROPE_NIL, include: BOOL_TRUE] RETURNS [CD.ObPtr] = BEGIN ob: CD.ObPtr; rp: ReferencePtr; import: REF Import ~ GetImport[design, importeeName]; <<--search first for existing object>> FOR list: LIST OF CD.ObPtr _ import.referenceList, list.rest WHILE list#NIL DO ob _ list.first; rp _ NARROW[ob.specificRef, ReferencePtr]; IF Rope.Equal[rp.entryName, entryName] AND Rope.Equal[rp.importeeName, importeeName] THEN RETURN [ob]; ENDLOOP; <<--object has not been found; create one>> ob _ NEW[CD.ObjectDefinition_[ size: CDInline.MaxPoint[size, [1, 1]], p: pForReference, level: CD.combined, specificRef: NEW[ReferenceRep _ [ entryName: entryName, importeeName: importeeName, localName: Rope.Cat[importeeName, ".", entryName] ]] ]]; import.referenceList _ CONS[ob, import.referenceList]; IF include THEN [] _ CDDirectory.Include[design, ob]; IF import.importee#NIL THEN [] _ BindReference[design, ob, import.importee, FALSE]; RETURN [ob] END; CreateReference: --PUBLIC-- PROC [design: CD.Design, size: CD.DesignPosition, entryName, importeeName, localName: Rope.ROPE_NIL] RETURNS [CD.ObPtr] = BEGIN RETURN [InternalCreateReference[design, size, entryName, importeeName, localName, TRUE]]; END; DescribeReference: PROC[me: CD.ObPtr] RETURNS [Rope.ROPE] = { RETURN [Rope.Concat["reference to ", Name[me]]] }; DrawReference: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN rp: ReferencePtr ~ NARROW[aptr.ob.specificRef]; IF rp.boundApp#NIL THEN pr.drawChild[rp.boundApp, pos, orient, pr] ELSE { pr.drawRect[CDOrient.RectAt[pos, aptr.ob.size, orient], CD.highLightShade, pr]; pr.drawComment[CDOrient.RectAt[pos, aptr.ob.size, orient], IF rp.localName#NIL THEN rp.localName ELSE rp.entryName, pr] } END; QuickDrawReference: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN rp: ReferencePtr ~ NARROW[aptr.ob.specificRef]; IF rp.boundApp#NIL THEN rp.boundApp.ob.p.quickDrawMe[rp.boundApp, pos, orient, pr] ELSE { pr.drawRect[CDOrient.RectAt[pos, aptr.ob.size, orient], CD.highLightShade, pr]; pr.drawComment[CDOrient.RectAt[pos, aptr.ob.size, orient], IF rp.localName#NIL THEN rp.localName ELSE rp.entryName, pr] } END; DrawReferenceSelection: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN rp: ReferencePtr ~ NARROW[aptr.ob.specificRef]; IF rp.boundApp#NIL THEN rp.boundApp.ob.p.showMeSelected[rp.boundApp, pos, orient, pr] ELSE pr.outLineProc[CDOrient.RectAt[pos, aptr.ob.size, orient], pr] END; WriteReference: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN rp: ReferencePtr = NARROW[me.specificRef]; TokenIO.WriteInt[me.size.x]; TokenIO.WriteInt[me.size.y]; TokenIO.WriteRope[rp.entryName]; TokenIO.WriteRope[rp.importeeName]; TokenIO.WriteRope[rp.localName]; END; ReadReference: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- = BEGIN x: INT = TokenIO.ReadInt[]; y: INT = TokenIO.ReadInt[]; entryName: Rope.ROPE = TokenIO.ReadRope[]; importeeName: Rope.ROPE = TokenIO.ReadRope[]; localName: Rope.ROPE = TokenIO.ReadRope[]; -- and is ignored ob: CD.ObPtr = InternalCreateReference[ design: CDIO.DesignInReadOperation[], size: [x, y], entryName: entryName, importeeName: importeeName, include: FALSE ]; RETURN [ob] END; GetImportList: PROC [design: CD.Design] RETURNS [imp: REF ImportList_NIL] = BEGIN x: REF ~ CDValue.Fetch[boundTo: design, key: $ImportedDesigns, propagation: design]; IF x#NIL AND ISTYPE[x, REF ImportList] THEN { imp _ NARROW[x, REF ImportList]; } ELSE { imp _ NEW[ImportList_[list: NIL]]; CDValue.Store[boundTo: design, key: $ImportedDesigns, value: imp]; }; END; GetImport: PROC [design: CD.Design, importeeName: Rope.ROPE_NIL, createIfNotFound: BOOL_TRUE] RETURNS [REF Import] = BEGIN mdata: REF Import _ NIL; impl: REF ImportList ~ GetImportList[design]; IF Rope.IsEmpty[importeeName] THEN ERROR CD.Error[ec: other, explanation: "design has empty name, but shouldn't" ]; IF impl#NIL THEN FOR l: LIST OF REF Import _ impl.list, l.rest WHILE l#NIL DO IF l.first#NIL AND Rope.Equal[l.first.importeeName, importeeName] THEN RETURN [l.first] ENDLOOP; IF createIfNotFound THEN { mdata _ NEW[Import_[importeeName: importeeName, importee: NIL, referenceList: NIL]]; impl.list _ CONS[mdata, impl.list]; --atomic-- }; RETURN [mdata] END; BindImportee: PROC [importer, importee: CD.Design, allowSizeConflicts: BOOL _ TRUE] = BEGIN ENABLE TerminalIO.UserAbort => GOTO UserAborted; done: BOOL_TRUE; mdata: REF Import ~ GetImport[importer, importee.name]; IF mdata=NIL THEN ERROR; IF mdata.importee#NIL THEN { IF NOT TerminalIO.UserSaysYes[ text: "design already loaded; shall overload?\n", label: "overload?"] THEN { TerminalIO.WriteRope["dont overload; not done\n"]; RETURN } }; mdata.importee _ importee; FOR list: LIST OF CD.ObPtr _ mdata.referenceList, list.rest WHILE list#NIL DO done _ done AND BindReference[importer, list.first, mdata.importee, allowSizeConflicts].ok ENDLOOP; IF NOT done THEN TerminalIO.WriteRope["some import not bound\n"]; CDOps.DelayedRedraw[importer]; EXITS UserAborted => {TerminalIO.WriteRope["aborted, design not bound\n"]}; END; BindReference: PROC [design: CD.Design, reference: CD.ObPtr, importee: CD.Design, allowSizeConflicts: BOOL _ TRUE] RETURNS [ok: BOOL_FALSE] = BEGIN ENABLE TerminalIO.UserAbort => GOTO UserAborted; rp: ReferencePtr ~ NARROW[reference.specificRef, ReferencePtr]; found: BOOL; referedOb: CD.ObPtr; [found, referedOb] _ CDDirectory.Fetch[importee, rp.entryName]; IF NOT found THEN { TerminalIO.WriteRope["entry "]; TerminalIO.WriteRope[rp.entryName]; TerminalIO.WriteRope[" in "]; TerminalIO.WriteRope[importee.name]; TerminalIO.WriteRope[" not found\n"]; RETURN }; IF referedOb.size=reference.size THEN rp.boundApp _ CDApplications.NewApplicationI[ob: referedOb] ELSE { TerminalIO.WriteRope["entry "]; TerminalIO.WriteRope[rp.entryName]; TerminalIO.WriteRope[" has different size; "]; IF NOT allowSizeConflicts THEN { TerminalIO.WriteRope["not resolved\n"]; RETURN }; IF NOT TerminalIO.UserSaysYes[ text: "import it anyway? ", label: "import different sized entry?"] THEN { TerminalIO.WriteRope["no\n"]; RETURN }; TerminalIO.WriteRope["yes\n"]; rp.boundApp _ CDApplications.NewApplicationI[ob: referedOb]; CDDirectory.RepositionAnObject[design, reference]; }; ok _ TRUE; EXITS UserAborted => {TerminalIO.WriteRope["aborted, entry not replaced\n"]}; END; DoImportation: PROC [design: CD.Design, importee: CD.Design] RETURNS [done: BOOL_FALSE] = BEGIN indirectImport: REF ImportList ~ GetImportList[importee]; IF indirectImport^.list#NIL THEN TerminalIO.WriteRope["There are indirect imports\n"]; <<-- check for forbidden circular import>> FOR list: LIST OF REF Import _ indirectImport^, list.rest WHILE list#NIL DO IF Rope.Equal[list.first.importeeName, design.name] THEN { TerminalIO.WriteRope["**CREATES CIRCULAR IMPORTS\n"]; RETURN } ENDLOOP; <<-- no circular import>> BindImportee[importer: design, importee: importee]; <<--check already imported designs for importing the new design>> FOR list: LIST OF REF Import _ GetImportList[design]^, list.rest WHILE list#NIL DO IF list.first.importee#NIL THEN BindImportee[importer: list.first.importee, importee: importee, allowSizeConflicts: FALSE]; ENDLOOP; <<--check the new design for importing of already imported designs>> FOR list: LIST OF REF Import _ indirectImport^, list.rest WHILE list#NIL DO IF list.first.importee=NIL THEN { imp: REF Import _ GetImport[design, list.first.importeeName, FALSE]; IF imp#NIL AND imp.importee#NIL THEN BindImportee[importer: importee, importee: imp.importee, allowSizeConflicts: FALSE]; } ENDLOOP; done_TRUE; END; GetImportedEntryCommand: PROC [comm: CDSequencer.Command] = BEGIN importeeName, entryName: Rope.ROPE; referenceOb, referedOb: CD.ObPtr; found: BOOLEAN; import: REF Import; TerminalIO.WriteRope["Include referenced entry; "]; importeeName _ TerminalIO.RequestRope["design > "! TerminalIO.UserAbort => {GOTO aborted}]; IF Rope.IsEmpty[importeeName] THEN { TerminalIO.WriteRope[" empty name; not done\n"]; RETURN }; import _ GetImport[design: comm.design, importeeName: importeeName, createIfNotFound: FALSE]; IF import=NIL OR import.importee=NIL THEN { TerminalIO.WriteRope["design "]; TerminalIO.WriteRope[importeeName]; TerminalIO.WriteRope[" not yet imported; not done\n"]; RETURN }; entryName _ TerminalIO.RequestRope["entry > "! TerminalIO.UserAbort => {GOTO aborted}]; [found, referedOb] _ CDDirectory.Fetch[import.importee, entryName]; IF NOT found THEN { TerminalIO.WriteRope[entryName]; TerminalIO.WriteRope[" not found in design "]; TerminalIO.WriteRope[importeeName]; TerminalIO.WriteRope["; not done\n"]; RETURN }; referenceOb _ CreateReference[design: comm.design, size: referedOb.size, entryName: entryName, importeeName: importeeName]; CDOps.AddAnObject[design: comm.design, ob: referenceOb, location: comm.pos, orientation: 0]; EXITS aborted => NULL; END; DesignHasBeenRenamed: CDEvents.EventProc --PROC [event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL_FALSE]-- = <<-- prevent a renaming which would cause circularity>> BEGIN imp: REF Import ~ GetImport[design: design, importeeName: design.name, createIfNotFound: FALSE]; IF imp#NIL THEN { dont_TRUE; TerminalIO.WriteRope["rename causes circularities; not done\n"] }; END; DisplayImports: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope[comm.design.name]; TerminalIO.WriteRope["'s import list: "]; TerminalIO.WriteRope[comm.design.name]; TerminalIO.WriteRope["\n"]; FOR list: LIST OF REF Import _ GetImportList[comm.design]^, list.rest WHILE list#NIL DO TerminalIO.WriteRope[" "]; TerminalIO.WriteRope[list.first.importeeName]; TerminalIO.WriteRope[IF list.first.importee=NIL THEN " -\n" ELSE " +\n"]; ENDLOOP; TerminalIO.WriteRope["---\n"] END; <> <> <> <> <> <> <> < "! TerminalIO.UserAbort => {GOTO aborted}];>> <> <> <> <> <> <<}>> <> <> <> <<};>> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <<};>> <> <<>> DisplayImportedEntries: PROC [comm: CDSequencer.Command] = BEGIN hasNotBound: BOOL _ FALSE; -- if importee loaded importeeName: Rope.ROPE; mdata: REF Import; TerminalIO.WriteRope["display used entries of imported design\n"]; importeeName _ TerminalIO.RequestRope["design > "! TerminalIO.UserAbort => {GOTO aborted}]; mdata _ GetImport[comm.design, importeeName, FALSE]; TerminalIO.WriteRope[importeeName]; IF mdata=NIL THEN { TerminalIO.WriteRope[" not imported\n"]; RETURN } ELSE { IF mdata.importee#NIL THEN TerminalIO.WriteRope[" already loaded\n"] ELSE TerminalIO.WriteRope[" not yet loaded\n"]; FOR list: LIST OF CD.ObPtr _ mdata.referenceList, list.rest WHILE list#NIL DO rp: ReferencePtr ~ NARROW[list.first.specificRef]; TerminalIO.WriteRope[" "]; TerminalIO.WriteRope[rp.localName]; TerminalIO.WriteRope[" ("]; TerminalIO.WriteRope[rp.entryName]; TerminalIO.WriteRope[")"]; IF rp.boundApp=NIL AND mdata.importee#NIL THEN { hasNotBound_TRUE; TerminalIO.WriteRope[" not bound"]; }; TerminalIO.WriteRope["\n"]; ENDLOOP; TerminalIO.WriteRope["---"]; IF hasNotBound THEN { TerminalIO.WriteRope[" has not bound entries"]; RETURN }; TerminalIO.WriteRope["\n"] }; EXITS aborted => NULL; END; ImportReadCommand: 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.WriteRope["Technology missmatch: includee is "]; TerminalIO.WriteRope[design.technology.name]; TerminalIO.WriteRope["\n"]; RETURN }; ok _ NOT Rope.Equal[comm.design.name, CDIO.DesignInReadOperation[].name]; IF NOT ok THEN { TerminalIO.WriteRope["design can not be imported, it has same name\n"]; }; END; done: BOOL _ FALSE; design: CD.Design; TerminalIO.WriteRope["import the directory of an input design\n"]; [] _ UseDesignsWorkingDirectory[comm.design]; design _ CDIO.ReadDesign[NIL, Check]; IF design#NIL THEN { done _ DoImportation[design: comm.design, importee: design]; }; TerminalIO.WriteRope[IF done THEN "include done\n" ELSE "include not done\n"]; END; <> <> <> <> <> <> < "];>> <> <> <> <> <> <> <<};>> <> <> <> <> <> <<};>> < "];>> <> <> <> <<};>> <> <> <> <> <> <> <> < {>> <> <<};>> < ERROR>> <> <> <<}>> <> <<>> <<}>> <> Init: PROC [] = INLINE BEGIN rp: REF CDDirectory.DirectoryProcs ~ CDDirectory.InstallDirectoryProcs[pForReference]; rp.enumerateChildObjects _ EnumerateItsObjects; rp.adjustItself _ AdjustItself; rp.repositionElements _ RepositionElements; rp.computeBounds _ ComputeBounds; rp.key _ Key; rp.name _ Name; rp.setName _ SetName; pForReference.drawMe _ DrawReference; pForReference.quickDrawMe _ QuickDrawReference; pForReference.showMeSelected _ DrawReferenceSelection; pForReference.internalRead _ ReadReference; pForReference.internalWrite _ WriteReference; pForReference.describe _ DescribeReference; CDValue.EnregisterKey[$ImportedDesigns]; CDEvents.RegisterEventProc[$RenameDesign, DesignHasBeenRenamed]; CDSequencer.ImplementCommand[$DrawImportedCell, GetImportedEntryCommand]; CDSequencer.ImplementCommand[$DisplayImports, DisplayImports]; CDSequencer.ImplementCommand[$DisplayImportedEntries, DisplayImportedEntries]; CDSequencer.ImplementCommand[$ImportADesign, ImportReadCommand]; CDSequencer.ImplementCommand[$SelectADesign, SelectADesign]; CDSequencer.ImplementCommand[$DrawCorrespondingObject, DrawImportedCopy]; END; <<--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>> <<--multi-design-copy feature>> selectedDesign: CD.Design _ NIL; SelectADesign: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["select "]; TerminalIO.WriteRope[comm.design.name]; TerminalIO.WriteRope[" for inter-design source\n"]; selectedDesign _ comm.design; END; GlobalSelection: PROC [expectedTechnology: CD.Technology] RETURNS [foundNamed: BOOL_FALSE, foundWithoutChildren: BOOL_FALSE, moduleName: Rope.ROPE_NIL, objectName: Rope.ROPE_NIL, object: CD.ObPtr_NIL, orient: CD.Orientation_CD.original] = <<--never returns with both foundNamed and foundWithoutChildren set to true>> <<--if not found then message to TerminalIO>> <<--if foundNamed then both, moduleName, objectName # NIL>> BEGIN Out: PROC [t: Rope.ROPE] = {TerminalIO.WriteRope[t]}; from: CD.Design = selectedDesign; -- so it does not change IF from=NIL THEN Out[" no selected design"] ELSE { fromName: Rope.ROPE = from.name; -- so it does not change IF Rope.IsEmpty[fromName] THEN Out[" selected design has no name"] ELSE IF expectedTechnology#from.technology AND expectedTechnology#NIL THEN Out[" different technologies"] ELSE { ap: CD.ApplicationPtr; -- the referred application to support the name multiple: BOOLEAN; [ap, multiple] _ CDOps.SelectedApplication[from]; IF multiple THEN Out[" multiple selection"] ELSE IF ap=NIL THEN Out[" no selection"] ELSE { orient _ ap.orientation; IF NOT ap.ob.p.hasChildren THEN { object _ ap.ob; foundWithoutChildren _ TRUE; } ELSE { entryName: Rope.ROPE = CDDirectory.Name[ap.ob]; IF Rope.IsEmpty[entryName] THEN Out[" object has no name"] ELSE { moduleName _ fromName; objectName _ entryName; foundNamed _ TRUE; } } } } } END; DrawImportedCopy: PROC [comm: CDSequencer.Command] = BEGIN foundNamed: BOOL; foundWithoutChildren: BOOL; moduleName: Rope.ROPE; objectName: Rope.ROPE; referenceOb, referedOb: CD.ObPtr; orient: CD.Orientation; TerminalIO.WriteRope["create corresponding object; "]; [foundNamed: foundNamed, foundWithoutChildren: foundWithoutChildren, moduleName: moduleName, objectName: objectName, object: referedOb, orient: orient] _ GlobalSelection[comm.design.technology]; IF foundNamed THEN { import: REF Import ~ GetImport[design: comm.design, importeeName: moduleName, createIfNotFound: FALSE]; IF Rope.Equal[moduleName, comm.design.name] THEN { TerminalIO.WriteRope[" don't refer itself; not done\n "]; RETURN }; IF import=NIL OR import.importee=NIL THEN { TerminalIO.WriteRope[" design "]; TerminalIO.WriteRope[moduleName]; TerminalIO.WriteRope[" not yet imported; not done\n"]; RETURN }; [foundNamed, referedOb] _ CDDirectory.Fetch[import.importee, objectName]; IF NOT foundNamed THEN { TerminalIO.WriteRope[" "]; TerminalIO.WriteRope[objectName]; TerminalIO.WriteRope[" not found in imported design "]; TerminalIO.WriteRope[moduleName]; TerminalIO.WriteRope["; not done\n"]; RETURN }; referenceOb _ CreateReference[design: comm.design, size: referedOb.size, entryName: objectName, importeeName: moduleName]; IF referenceOb=NIL THEN { TerminalIO.WriteRope[" NIL object; not done\n"]; RETURN }; CDOps.AddAnObject[design: comm.design, ob: referenceOb, location: comm.pos, orientation: orient]; TerminalIO.WriteRope[CDOps.Info[referenceOb]]; TerminalIO.WriteRope[" included\n"]; } ELSE IF foundWithoutChildren THEN { CDOps.AddAnObject[design: comm.design, ob: referedOb, location: comm.pos, orientation: orient]; TerminalIO.WriteRope[CDOps.Info[referedOb]]; TerminalIO.WriteRope[" copied\n"]; } ELSE TerminalIO.WriteRope["; not done\n"]; END; <<>> <<--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>> UseDesignsWorkingDirectory: PROC [design: CD.Design] RETURNS [Rope.ROPE] = <<--set's it for the running process>> <<--return's it>> BEGIN wDir: Rope.ROPE _ CDIOExtras.GetDesignsWorkingDirectory[design]; IF wDir#NIL THEN { [] _ List.PutAssoc[key: $WorkingDirectory, val: wDir, aList: ProcessProps.GetPropList[]]; RETURN [wDir]; }; RETURN [FileNames.CurrentWorkingDirectory[]] END; Init[]; END.