CDImportCommands.mesa (part of ChipNDale)
Copyright © 1984, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, March 20, 1984 5:50:51 pm PST
Last edited by: Christian Jacobi, March 11, 1987 5:46:13 pm PST
DIRECTORY
CD,
CDEnvironment,
CDDirectory,
CDGenerate,
CDGenerateImports,
CDImports,
CDImportsBackdoor,
CDInstances,
CDIO,
CDMenuSpecials,
CDOps,
CDProperties,
CDRemote,
CDSequencer,
IO,
Process,
RefTab,
Rope,
SymTab,
TerminalIO,
TokenIO;
CDImportCommands:
CEDAR
PROGRAM
IMPORTS CD, CDDirectory, CDEnvironment, CDGenerate, CDGenerateImports, CDImports, CDImportsBackdoor, CDInstances, CDIO, CDMenuSpecials, CDOps, CDProperties, CDRemote, CDSequencer, IO, Process, RefTab, Rope, SymTab, TerminalIO
SHARES CDRemote =
BEGIN
ROPE: TYPE = Rope.ROPE;
ImportSpecific: TYPE = CDImports.ImportSpecific;
ImportRep: TYPE = CDImports.ImportRep;
ImportListRec: TYPE = CDImports.ImportListRec;
ImportEntry: TYPE = CDImports.ImportEntry;
HasImports:
PROC [into:
CD.Design]
RETURNS [
BOOL] = {
il: CDImports.ImportList ← CDImports.GetImportList[into];
RETURN [il#NIL AND il^#NIL]
};
RequestImporteeName:
PROC [into:
CD.Design, restricted:
BOOL←
TRUE, immediateSingle:
BOOL←
FALSE]
RETURNS [importeeName:
ROPE←
NIL] = {
--requests a design name for imports into "into"
--restricted:
-- FALSE => user may type any name; the name of the selected design is included in list
-- TRUE => only designs in into's import list are allowed
--immediateSingle:
-- FALSE => user sees always a selection
-- TRUE => if only a single option exists it is returned without bothering user
options: SymTab.Ref ← FindAllImports[into];
--deal with selected design
IF ~restricted
THEN {
name: Rope.ROPE ← NIL;
d: CD.Design ← SelectedDesign[];
IF d#NIL THEN name ← d.name;
IF ~Rope.IsEmpty[name]
AND ~Rope.Equal[name, into.name]
THEN
[] ← SymTab.Insert[options, name, name]
};
IF immediateSingle
AND restricted
AND SymTab.GetSize[options]=1
THEN {
Check: SymTab.EachPairAction = {
importeeName ← key; RETURN [TRUE]
};
IF ~Rope.IsEmpty[importeeName] THEN RETURN [importeeName];
};
importeeName ← CDMenuSpecials.SelectOneOf[options, "DESIGN name", ~restricted];
};
OptionalLoad:
PROC [into:
CD.Design, importeeName:
ROPE←
NIL, allways:
BOOL←
FALSE, howOverload: CDImports.BoolOrInteractive ← interactive]
RETURNS [import: ImportEntry←
NIL] = {
checkCalled: BOOL ← FALSE;
Check:
PROC [h: TokenIO.Handle]
RETURNS [ok:
BOOL] = {
design: CD.Design ← CDIO.DesignInReadOperation[h];
n: ROPE;
checkCalled ← TRUE;
IF
NOT design.technology=into.technology
THEN {
TerminalIO.PutRopes["technology missmatch: includee is ", design.technology.name, "\n"];
RETURN [ok←FALSE]
};
IF Rope.IsEmpty[design.name]
THEN {
TerminalIO.PutRope["design has no name\n"];
RETURN [ok←FALSE]
};
IF Rope.Equal[into.name, design.name]
THEN {
TerminalIO.PutRope["can't be imported, it would cause circularity\n"];
RETURN [ok←FALSE]
};
IF ~Rope.Equal[importeeName, design.name]
THEN {
TerminalIO.PutRopes["file has different design: name = ", n, "\n"];
RETURN [ok←FALSE]
};
RETURN [ok←TRUE]
};
r, nameX, name1, name2: ROPE;
design: CD.Design←NIL;
loaded: BOOL←FALSE;
IF Rope.IsEmpty[importeeName]
THEN
importeeName ← RequestImporteeName[into: into, restricted: FALSE, immediateSingle: FALSE];
IF Rope.IsEmpty[importeeName]
THEN {
TerminalIO.PutRopes["no design specified\n"]; RETURN
};
IF Rope.Equal[importeeName, into.name]
THEN {
TerminalIO.PutRopes["a design can't import itself\n"]; RETURN
};
import ← CDImports.GetImportEntry[into: into, importeeName: importeeName];
IF import=
NIL
OR ~import.loaded
OR allways
THEN {
menuHeader: ROPE ← Rope.Cat["FILE name for ", importeeName];
menuChoice: LIST OF ROPE ← LIST[importeeName];
IF import#
NIL
AND import.loaded
THEN
TerminalIO.PutRopes["reload design ", importeeName, "\n"];
nameX ← CDRemote.MakupName[into, importeeName];
IF ~Rope.IsEmpty[nameX] THEN menuChoice ← CONS[nameX, menuChoice];
r ← CDMenuSpecials.SelectOneOf[menuChoice, menuHeader, TRUE];
IF Rope.IsEmpty[r] THEN {TerminalIO.PutRope["discarded\n"]; RETURN};
name1 ← CDIO.MakeName[base: r, wDir: CDIO.GetWorkingDirectory[into]];
design ← CDIO.ReadDesign[name1, Check];
IF design=
NIL
THEN {
name2 ← CDIO.MakeName[base: r, wDir: CDIO.GetWorkingDirectory[NIL]];
IF ~Rope.Equal[name1, name2,
FALSE]
AND ~checkCalled
THEN
design ← CDIO.ReadDesign[name2, Check];
};
IF design=NIL THEN RETURN;
CDRemote.CacheDesign[into, design];
loaded ← CDImportsBackdoor.LoadDesign[into: into, importeeName: importeeName, overload: howOverload, allowConflicts: interactive, useCache: TRUE];
IF loaded
THEN
RETURN [CDImports.GetImportEntry[into: into, importeeName: importeeName]]
};
};
GetImportedEntryCommand:
PROC [comm: CDSequencer.Command] = {
objectName: ROPE;
referenceOb: CD.Object;
import: ImportEntry;
TerminalIO.PutRope["draw object of imported design; "];
import ← OptionalLoad[comm.design];
IF import=NIL OR ~import.loaded THEN RETURN;
objectName ← TerminalIO.RequestRope["object > "];
referenceOb ← CDImports.CreateImport[into: comm.design, objectName: objectName, importeeName: import.importeeName];
IF referenceOb=
NIL
THEN {
TerminalIO.PutRopes[objectName, " not found in design ", import.importeeName];
TerminalIO.PutRope["; not done\n"];
RETURN
};
CDOps.IncludeObjectI[design: comm.design, ob: referenceOb, location: comm.pos];
};
--============================================================
GetHintList:
PROC [for:
CD.Design]
RETURNS [
LIST
OF
ROPE←
NIL] = {
IF for#
NIL
THEN
WITH CDProperties.GetDesignProp[for, $ImportHints]
SELECT
FROM
rL: LIST OF ROPE => RETURN [rL];
ENDCASE => NULL;
};
DisplayFiles:
PROC [for:
CD.Design] = {
rl: LIST OF ROPE ← GetHintList[for];
IF rl#
NIL
THEN {
key, rest: ROPE ← NIL;
TerminalIO.PutRopes["file names to be used on imports:\n"];
FOR list:
LIST
OF
ROPE ← rl, list.rest
WHILE list#
NIL
DO
[key, rest] ← CDEnvironment.SplitLine[list.first];
rest ← CDEnvironment.RemoveSpaces[rest];
TerminalIO.PutRopes[" design: ", key];
TerminalIO.PutRopes[" file: ", rest, "\n"];
ENDLOOP;
TerminalIO.PutRope[" --\n"];
};
};
RemKey:
PROC [rl:
LIST
OF
ROPE, key:
ROPE]
RETURNS [x:
LIST
OF
ROPE←
NIL] = {
FOR list:
LIST
OF
ROPE ← rl, list.rest
WHILE list#
NIL
DO
IF ~Rope.Equal[CDEnvironment.SplitLine[list.first].key, key] THEN x ← CONS[list.first, x]
ENDLOOP;
};
ChangeDefaultFileName:
PROC [for:
CD.Design, imp, file:
ROPE] = {
rl: LIST OF ROPE ← GetHintList[for];
rl ← RemKey[rl, imp];
file ← CDEnvironment.RemoveSpaces[file];
IF file#NIL THEN rl ← CONS[Rope.Cat[imp, ": ", file], rl];
CDProperties.PutDesignProp[for, $ImportHints, rl];
};
ChangeDefaultFileNameComm:
PROC [comm: CDSequencer.Command] = {
importeeName, fileName: ROPE;
TerminalIO.PutRope["set default file for import\n"];
importeeName ← RequestImporteeName[into: comm.design, restricted: FALSE, immediateSingle: FALSE];
IF Rope.IsEmpty[importeeName] THEN TerminalIO.PutRope["no input design\n"]
ELSE {
fileName ← TerminalIO.RequestRope["FILE name > "];
ChangeDefaultFileName[comm.design, importeeName, fileName];
TerminalIO.PutRope[" ok\n"];
}
};
--============================================================
FindAllImports:
PROC [design:
CD.Design]
RETURNS [dList: SymTab.Ref] = {
--returns symtab with names of imported designs as keys
--recursively because of indirect imports
Check:
PROC [d:
CD.Design] = {
IF RefTab.Insert[checked, d, d]
THEN {
FOR l:
LIST
OF CDImports.ImportEntry ← CDImports.GetImportList[d]^, l.rest
WHILE l#
NIL
DO
this: CDImports.ImportEntry ← l.first;
[] ← SymTab.Insert[dList, this.importeeName, $ok];
IF ~this.loaded THEN [] ← SymTab.Store[dList, this.importeeName, $notLoaded]
ELSE {
dd: CD.Design ← CDRemote.FetchDesign[design, this.importeeName];
IF dd=NIL THEN [] ← SymTab.Store[dList, this.importeeName, $notLoaded]
ELSE Check[dd];
};
ENDLOOP;
};
};
checked: RefTab.Ref ← RefTab.Create[];
dList ← SymTab.Create[];
Check[design];
};
DisplayImports:
PROC [comm: CDSequencer.Command] = {
ListEach: SymTab.EachPairAction = {
hasImpDesign ← TRUE;
IF val=$notLoaded THEN hasUnloadedDesign ← TRUE;
TerminalIO.PutRopes[" ", key, (IF val=$notLoaded THEN " -\n" ELSE " +\n")];
RETURN [FALSE]
};
design: CD.Design ← comm.design;
hasUnloadedDesign: BOOL ← FALSE;
hasImpDesign: BOOL ← FALSE;
TerminalIO.PutRopes[design.name, "'s import list: \n"];
[] ← SymTab.Pairs[FindAllImports[design], ListEach];
IF ~hasImpDesign THEN TerminalIO.PutRope[" has no imports\n"];
TerminalIO.PutRope[" --\n"];
DisplayFiles[design];
IF hasImpDesign
AND ~hasUnloadedDesign
AND CDImports.HasUnloadedImports[design]
THEN
TerminalIO.PutRope[" **some imported design has unloaded object(s)\n"];
};
DisplayImportedEntries:
PROC [comm: CDSequencer.Command] = {
totalCount, unboundCount: INT ← 0;
importeeName: ROPE;
mdata: ImportEntry;
TerminalIO.PutRope["display used entries of imported design\n"];
IF ~HasImports[comm.design] THEN CDSequencer.Quit["no design imported"];
importeeName ← RequestImporteeName[into: comm.design, immediateSingle: TRUE];
IF Rope.IsEmpty[importeeName] THEN CDSequencer.Quit["no design selected"];
mdata ← CDImports.GetImportEntry[comm.design, importeeName, false];
TerminalIO.PutRope[importeeName];
IF mdata=NIL THEN CDSequencer.Quit[" not imported"]
ELSE {
EachObject: CDDirectory.EachEntryAction = {
WITH ob.specific
SELECT
FROM
ip: CDImports.ImportSpecific =>
IF Rope.Equal[ip.designName, mdata.importeeName]
THEN {
totalCount ← totalCount+1;
TerminalIO.PutF[" %g (%g)", IO.rope[name], IO.rope[ip.objectName]];
IF ip.boundInstance=
NIL
THEN {
unboundCount ← unboundCount+1;
TerminalIO.PutRope[" not loaded"];
};
TerminalIO.PutRope["\n"];
};
ENDCASE => NULL
};
IF mdata.loaded THEN TerminalIO.PutRope[" loaded\n"]
ELSE TerminalIO.PutRope[" not yet loaded\n"];
[] ← CDDirectory.Enumerate[comm.design, EachObject];
IF totalCount=0 THEN TerminalIO.PutRope["--- \n import not used anymore\n"]
ELSE {
TerminalIO.PutF["--- %g objects imported from %g\n", [integer[totalCount]], [rope[importeeName]]];
IF unboundCount#0 THEN TerminalIO.PutF["=== %g imported objects not loaded\n", [integer[unboundCount]]];
};
};
};
ImportReadCommand:
PROC [comm: CDSequencer.Command] = {
import: ImportEntry;
TerminalIO.PutRope["load (or reload) a design for import\n"];
import ← OptionalLoad[comm.design, NIL, TRUE];
TerminalIO.PutRope[IF import#NIL AND import.loaded THEN "done\n" ELSE "not done\n"];
};
MerginImportCommand:
PROC [comm: CDSequencer.Command] = {
importeeName: ROPE;
mdata: ImportEntry;
TerminalIO.PutRope["merge imports into the design\n"];
IF ~HasImports[comm.design]
THEN {
TerminalIO.PutRope["design has no imports\n"]; RETURN
};
importeeName ← RequestImporteeName[into: comm.design, immediateSingle: TRUE];
IF Rope.IsEmpty[importeeName]
THEN {
TerminalIO.PutRope["no imported design specified\n"]; RETURN
};
mdata ← CDImports.GetImportEntry[comm.design, importeeName, false];
IF mdata=
NIL
THEN {
TerminalIO.PutRopes[importeeName, " not imported; not done\n"]; RETURN
}
ELSE
IF ~mdata.loaded
THEN {
TerminalIO.PutRopes[importeeName, " is not yet loaded\n"];
IF OptionalLoad[comm.design, importeeName]=NIL THEN RETURN;
IF ~mdata.loaded THEN RETURN;
};
CDImports.MergeInImports[into: comm.design, importeeName: importeeName];
TerminalIO.PutRope["end merge\n"];
};
--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--multi-design-copy feature
SelectADesign:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRopes["select ", comm.design.name, " as source-design for the <Z-X-middle> command [drawing imports]\n"];
IF Rope.IsEmpty[comm.design.name]
THEN
TerminalIO.PutRope[" design has no name; not done\n"]
ELSE
CDProperties.PutProp[$SelectedDesign, $SelectedDesign, comm.design];
};
SelectedDesign:
PROC []
RETURNS [
CD.Design] = {
WITH CDProperties.GetProp[$SelectedDesign, $SelectedDesign]
SELECT
FROM
d: CD.Design => RETURN [d];
ENDCASE => RETURN [NIL];
};
InterDesignCopyComm:
PROC [comm: CDSequencer.Command] = {
inst: CD.Instance; --copy of sourceInst
Fail:
PROC [r1, r2, r3: Rope.
ROPE←
NIL] = {
TerminalIO.PutRope[Rope.Cat[" failed: ", r1, r2, r3, "\n"]];
};
ForwardNormalCopy:
PROC [comm: CDSequencer.Command] = {
p: CDSequencer.CommandProc ← CDSequencer.FetchCommand[$CopyS].proc;
comm.data ← NIL;
IF p=NIL THEN Fail["command not available"]
ELSE {
TerminalIO.PutRope[" forward as simple copy\n"];
CDSequencer.ExecuteProc[p, comm.design, dontQueue, comm];
};
};
IncludeOb:
PROC [ob:
CD.Object] = {
IF ob=NIL THEN Fail["NIL object"]
ELSE {
CDOps.IncludeObjectI[design, ob, comm.pos, inst.trans.orient];
TerminalIO.PutRopes[" ", CDOps.ObjectRope[ob], " included\n"];
};
};
multiple, always: BOOL ← FALSE;
design: CD.Design ← comm.design; obName: Rope.ROPE; ob: CD.Object;
sourceDesign: CD.Design ← NIL; sdName: Rope.ROPE; sourceInst: CD.Instance;
import: ImportEntry;
TerminalIO.PutRope["interdesign copy\n"];
WITH comm.data
SELECT
FROM
d: CD.Design => sourceDesign ← d;
ENDCASE => sourceDesign ← NIL;
IF sourceDesign=design THEN {ForwardNormalCopy[comm]; RETURN};
IF sourceDesign=NIL THEN {Fail["source design not found"]; RETURN};
IF sourceDesign.technology#design.technology THEN {Fail["technology missmatch"]; RETURN};
[sourceInst, multiple] ← CDOps.SelectedInstance[sourceDesign]; --asynchronous for source !!
IF multiple THEN {Fail["multiple selection in source design"]; RETURN};
IF sourceInst=NIL THEN {Fail["no selection in source design"]; RETURN};
inst ← CDInstances.Copy[sourceInst]; --because of asynchronity problem
IF inst.ob=NIL THEN {Fail["asynchronity problem"]; RETURN};
--Try atomic objects
IF ~inst.ob.class.inDirectory THEN {IncludeOb[inst.ob]; RETURN};
--Object is in directory
obName ← CDDirectory.Name[inst.ob];
sdName ← sourceDesign.name;
Process.Pause[Process.MsecToTicks[200]];
--wow!, here 2 design viewers, the terminal and pop up menus will be involved...
--this pause might help to prevent some kind of viewer wedges
IF Rope.IsEmpty[obName] THEN {Fail["object not named"]; RETURN};
IF Rope.IsEmpty[sdName] THEN {Fail["can not import from un-named design"]; RETURN};
IF Rope.Equal[sdName, design.name]
THEN {
--Designs have equal names; use matching objects from directory
TerminalIO.PutRope[" design names match; use object with same name\n"];
ob ← CDDirectory.Fetch[design, obName].object;
IF ob=NIL THEN {Fail["object ", obName, " not found in directory"]; RETURN};
IncludeOb[ob]; RETURN
};
--Designs have different names; try imports
import ← CDImports.GetImportEntry[into: design, importeeName: sdName];
SELECT
TRUE
FROM
import#
NIL
AND import.loaded => {
--Source design already loaded
always ← FALSE;
header: Rope.ROPE ← Rope.Cat["imported ", sdName, " is already loaded"];
headerDoc: Rope.ROPE ← "re importing design ?";
IF sourceDesign.edited THEN {
header ← Rope.Concat[header, " but design is EDITED"];
headerDoc ← "cache and design in viewer may differ";
};
SELECT TerminalIO.RequestSelection[header: header, headerDoc: headerDoc,
choice: LIST["use cached design", "reload file", "give up"]
] FROM
1 => always ← FALSE;
2 => always ← TRUE;
ENDCASE => {Fail["gives up"]; RETURN};
};
sourceDesign.edited => {
--Source design not yet loaded but edited
always ← FALSE;
SELECT TerminalIO.RequestSelection[
header: Rope.Cat["importing ", sdName, "; but design is edited"],
headerDoc: "file might differ from current design",
choice: LIST["go ahead and load file", "give up"]
] FROM
1 => always ← TRUE;
ENDCASE => {Fail["gives up"]; RETURN};
};
ENDCASE => {
--source design not yet loaded nor edited
IF ~TerminalIO.Confirm[Rope.Concat["import ", sdName]]
THEN {
Fail["gives up"]; RETURN
};
};
import ← OptionalLoad[design, sdName, always, true];
IF import=NIL OR ~import.loaded THEN {Fail[sdName, " not loaded"]; RETURN};
ob ← CDImports.CreateImport[into: design, objectName: obName, importeeName: sdName];
IF ob=NIL THEN {Fail[obName, " not found"]; RETURN};
IncludeOb[ob];
};
DrawImportedCopy:
PROC [comm: CDSequencer.Command] = {
GlobalSelection:
PROC [expectedTechnology:
CD.Technology]
RETURNS [foundNamed:
BOOL←
FALSE, foundWithoutChildren:
BOOL←
FALSE, moduleName:
ROPE←
NIL, objectName:
ROPE←
NIL, object:
CD.Object←
NIL, orient:
CD.Orientation←
CD.Orientation[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
Out:
PROC [t:
ROPE] = {
TerminalIO.PutRope[t]
};
from: CD.Design = SelectedDesign[]; -- so it does not change
IF from=NIL THEN Out[" no selected design"]
ELSE {
fromName: 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 {
inst: CD.Instance; -- the referred instance to support the name
multiple: BOOL;
[inst, multiple] ← CDOps.SelectedInstance[from];
IF multiple THEN Out[" multiple selection"]
ELSE IF inst=NIL THEN Out[" no selection"]
ELSE {
orient ← inst.trans.orient;
IF
NOT inst.ob.class.inDirectory
THEN {
object ← inst.ob;
foundWithoutChildren ← TRUE;
}
ELSE {
entryName: ROPE = CDDirectory.Name[inst.ob];
IF Rope.IsEmpty[entryName] THEN Out[" object has no name"]
ELSE {
moduleName ← fromName;
objectName ← entryName;
foundNamed ← TRUE;
}
}
}
}
}
};
foundNamed, foundWithoutChildren: BOOL;
moduleName, objectName: ROPE;
referenceOb, referedOb: CD.Object ← NIL;
orient: CD.Orientation;
TerminalIO.PutRope["draw corresponding object (import); "];
[foundNamed: foundNamed, foundWithoutChildren: foundWithoutChildren, moduleName: moduleName, objectName: objectName, object: referedOb, orient: orient] ← GlobalSelection[comm.design.technology];
IF foundWithoutChildren THEN referenceOb ← referedOb
ELSE
IF foundNamed
THEN {
IF Rope.Equal[moduleName, comm.design.name]
THEN {
TerminalIO.PutRopes[moduleName, " is selected design; simply copy object\n"];
referenceOb ← CDDirectory.Fetch[comm.design, objectName].object;
}
ELSE {
import: ImportEntry ← OptionalLoad[comm.design, moduleName];
IF import#
NIL
AND import.loaded
THEN {
referenceOb ← CDImports.CreateImport[into: comm.design, objectName: objectName, importeeName: moduleName];
IF referenceOb=NIL THEN TerminalIO.PutF[" %g not found in imported design %g; ", IO.rope[objectName], IO.rope[moduleName]];
}
}
};
IF referenceOb=NIL THEN TerminalIO.PutRope[" not done\n"]
ELSE {
CDOps.IncludeObjectI[comm.design, referenceOb, comm.pos, orient];
TerminalIO.PutRopes[CDOps.ObjectRope[referenceOb], " included\n"];
}
};
LoadAllImps:
PROC [importerDesign:
CD.Design, allowConflicts: CDImports.BoolOrInteractivelse]
RETURNS [alldone:
BOOL] = {
--Tries to import all designs which are used for importerDesign;
--Does not overload.
--Quite talky on TerminalIO, but not interactive unless parameter specifies
jobList: SymTab.Ref ← SymTab.Create[];
LoadOneImport:
PROC [name:
ROPE] = {
done: BOOL;
CDSequencer.CheckAborted[importerDesign];
done ← CDImportsBackdoor.LoadDesign[into: importerDesign, importeeName: name, overload: false, allowConflicts: allowConflicts, useCache: TRUE];
TerminalIO.PutRopes[" ", name, (IF done THEN " imported\n" ELSE " not imported\n")];
};
SearchDirectImports:
PROC [d:
CD.Design] = {
FOR l:
LIST
OF CDImports.ImportEntry ← CDImports.GetImportList[d]^, l.rest
WHILE l#
NIL
DO
[] ← SymTab.Insert[jobList, l.first.importeeName, $mustLoadAndCheck]
ENDLOOP;
};
Each: SymTab.EachPairAction = {
SELECT val
FROM
$mustLoadAndCheck => {
ie: CDImports.ImportEntry ← CDImports.GetImportEntry[importerDesign, key, true];
IF ~ie.loaded THEN LoadOneImport[key];
[] ← SymTab.Store[jobList, key, $mustCheck];
RETURN [TRUE]
};
$mustCheck => {
d: CD.Design ← CDRemote.FetchDesign[importerDesign, key];
IF d#NIL THEN SearchDirectImports[d];
[] ← SymTab.Store[jobList, key, $ok];
RETURN [TRUE]
};
$ok => RETURN [FALSE];
ENDCASE => ERROR;
};
enumeration of imports and indirect imports
When a design is to be imported it is remembered by storing $mustLoadAndCheck
When the design actually is imported its tagged as $loaded
When all its (indirect) imports are found, the design is tagged $ok
Recursively enumerate imports (SearchDirectImports) until all designs found are tagged $ok
SearchDirectImports[importerDesign];
WHILE SymTab.Pairs[jobList, Each] DO ENDLOOP;
alldone ← ~CDImports.HasUnloadedImports[importerDesign];
};
LoadAllImpsCommand:
PROC [comm: CDSequencer.Command] = {
--Load all imports
--Checks first for an userprofile entry;
--checks then for filename=designname
b: BOOL;
TerminalIO.PutRope["load all imported designs\n"];
b ← LoadAllImps[comm.design, interactive];
IF ~b THEN TerminalIO.PutRope[" **some import not loaded\n"];
TerminalIO.PutRope[" --\n"];
};
UnqueuedLoadAllImps:
PROC [comm: CDSequencer.Command] = {
--hack, called from io commands
IF ~LoadAllImps[comm.design, false] THEN TerminalIO.PutRope["**some import not loaded\n"];
};
ReplaceIncludesByImportsComm:
PROC [comm: CDSequencer.Command] = {
FindObjects: CDDirectory.EachEntryAction = {
--uses global replaceList
WITH CDProperties.GetObjectProp[ob, $CameFrom]
SELECT
FROM
--putting the objectnames in the RefTab keeps them even if replacement is in wrong order
r: ROPE => [] ← RefTab.Insert[x: replaceList, key: ob, val: CDProperties.GetObjectProp[ob, $OriginalName]];
ENDCASE => NULL
};
ReplaceObjects: RefTab.EachPairAction = {
--uses globals context and design
quit ← FALSE;
WITH val
SELECT
FROM
r:
ROPE => {
ob: CD.Object ← NARROW[key];
oldName: ROPE ← CDDirectory.Name[ob];
new: CD.Object ← CDGenerate.FetchNCall[context, design, r];
IF new#
NIL
THEN {
msg: ROPE;
CDDirectory.ReplaceObject[design, ob, new];
IF ~CDDirectory.Remove[design, oldName, ob] THEN [] ← CDDirectory.Rename[design, ob, Rope.Cat["old-", CDDirectory.Name[ob]], TRUE];
msg ←
IF new.bbox=ob.bbox
AND
CD.InterestRect[new]=
CD.InterestRect[ob]
THEN " replaced" ELSE " replaced (size conflict)";
TerminalIO.PutF["%g %g by %g\n",
IO.rope[msg],
IO.rope[oldName],
IO.rope[CDDirectory.Name[new]]
];
};
CDSequencer.CheckAborted[design];
};
ENDCASE => NULL
};
replaceList: RefTab.Ref ← RefTab.Create[];
import: ImportEntry;
context: CDGenerate.Context;
design: CD.Design ← comm.design;
TerminalIO.PutRope["replace included objects by imports\n"];
import ← OptionalLoad[comm.design];
IF import=NIL THEN {TerminalIO.PutRope[" not loded\n"]; RETURN};
context ← CDGenerateImports.GetImportContext[import.importeeName];
[] ← CDDirectory.Enumerate[comm.design, FindObjects];
[] ← RefTab.Pairs[replaceList, ReplaceObjects];
TerminalIO.PutRope[" --\n"];
};
[] ← CDProperties.RegisterProperty[$SelectedDesign, $chj];
[] ← CDProperties.RegisterProperty[$ImportHints, $chj];
CDSequencer.ImplementCommand[$DrawImported, GetImportedEntryCommand];
CDSequencer.ImplementCommand[$DisplayImports, DisplayImports,, doQueue];
CDSequencer.ImplementCommand[$DisplayImportedEntries, DisplayImportedEntries,, doQueue];
CDSequencer.ImplementCommand[$ImportADesign, ImportReadCommand];
CDSequencer.ImplementCommand[$SelectADesign, SelectADesign,, doQueue];
CDSequencer.ImplementCommand[$DrawCorrespondingObject, DrawImportedCopy];
CDSequencer.ImplementCommand[$MerginImport, MerginImportCommand];
CDSequencer.ImplementCommand[$LoadAllImps, LoadAllImpsCommand,, doQueue];
CDSequencer.ImplementCommand[$UnqueuedLoadAllImps, UnqueuedLoadAllImps,, dontQueue];
CDSequencer.ImplementCommand[$ReplaceByImp, ReplaceIncludesByImportsComm];
CDSequencer.ImplementCommand[$ImportDefaultName, ChangeDefaultFileNameComm];
CDSequencer.ImplementCommand[$UnqueuedCopyInterDesign, InterDesignCopyComm];
END.