CDImportCommands.mesa (part of ChipNDale)
Copyright © 1984, 1986 by Xerox Corporation. All rights reserved.
by Christian Jacobi, March 20, 1984 5:50:51 pm PST
last edited Christian Jacobi, February 12, 1986 4:03:19 pm PST
DIRECTORY
CD,
CDDirectory,
CDGenerate,
CDGenerateImports,
CDImports,
CDIO,
CDMenus,
CDOps,
CDProperties,
CDRemote,
CDSequencer,
IO,
RefTab,
Rope,
TerminalIO,
UserProfile;
CDImportCommands:
CEDAR
PROGRAM
IMPORTS CD, CDDirectory, CDGenerate, CDGenerateImports, CDImports, CDIO, CDMenus, CDOps, CDProperties, CDRemote, CDSequencer, IO, RefTab, Rope, TerminalIO, UserProfile
SHARES CDRemote =
BEGIN
ImportPtr: TYPE = CDImports.ImportPtr;
ImportRep: TYPE = CDImports.ImportRep;
ImportList: TYPE = CDImports.ImportList;
ImportDesign: TYPE = CDImports.ImportDesign;
RequestImporteeName:
PROC [into:
CD.Design]
RETURNS [importeeName: Rope.
ROPE] =
BEGIN
cnt: INT ← 0;
i: INT ← 0;
rl: LIST OF Rope.ROPE ← NIL;
il: LIST OF REF ImportDesign ← CDImports.GetImportList[into]^;
FOR list:
LIST
OF
REF ImportDesign ← il, list.rest
WHILE list#
NIL
AND cnt<20
DO
cnt ← cnt+1;
rl ← CONS[list.first.importeeName, rl];
ENDLOOP;
IF rl=NIL THEN i ← 1
ELSE
i ← TerminalIO.RequestSelection[choice: CONS["<type name>", rl], label: "DESIGN name"];
IF i=1 THEN importeeName ← TerminalIO.RequestRope["DESIGN name > "]
ELSE
IF i>1
AND i<=cnt+1
THEN {
FOR cnt IN [3..i] DO rl ← rl.rest ENDLOOP;
importeeName ← rl.first;
TerminalIO.WriteRopes[" select ", importeeName, "\n"];
}
ELSE ERROR TerminalIO.UserAbort
END;
OptionalLoad:
PROC [into:
CD.Design, importeeName: Rope.
ROPE←
NIL, allways:
BOOL←
FALSE]
RETURNS [import:
REF ImportDesign←
NIL] =
BEGIN
Check:
PROC [design:
CD.Design]
RETURNS [ok:
BOOL] =
BEGIN
n: Rope.ROPE;
IF
NOT design.technology=into.technology
THEN {
TerminalIO.WriteRopes["technology missmatch: includee is ", design.technology.name, "\n"];
RETURN [ok←FALSE]
};
n ← CDIO.DesignInReadOperation[].name;
IF Rope.IsEmpty[n]
THEN {
TerminalIO.WriteRope["design has no name\n"];
RETURN [ok←FALSE]
};
IF Rope.Equal[into.name, n]
THEN {
TerminalIO.WriteRope["design can not be imported, it has same name\n"];
RETURN [ok←FALSE]
};
IF ~Rope.Equal[importeeName, n]
THEN {
TerminalIO.WriteRopes["wrong design; has name ", n, "\n"];
RETURN [ok←FALSE]
};
RETURN [ok←TRUE]
END;
n: INT;
loaded: BOOL←FALSE;
wDir: Rope.ROPE ← CDIO.GetWorkingDirectory[into];
IF Rope.IsEmpty[importeeName]
THEN {
importeeName ← RequestImporteeName[into];
};
IF Rope.IsEmpty[importeeName]
THEN {
TerminalIO.WriteRopes["empty name\n"];
RETURN
};
import ← CDImports.GetImportEntry[into: into, importeeName: importeeName];
IF import=
NIL
OR ~import.loaded
OR allways
THEN {
IF Rope.Equal[into.name, importeeName]
AND ~Rope.IsEmpty[importeeName]
THEN {
TerminalIO.WriteRope["design can not be imported, it has same name\n"];
RETURN [NIL]
};
IF allways THEN TerminalIO.WriteRopes["overload design ", importeeName, "\n"];
n ← TerminalIO.RequestSelection[label: Rope.Cat["load design ", importeeName], choice: LIST["default file name", "other file name"]];
SELECT n
FROM
1 => {
IF allways
THEN {
design: CD.Design ← CDIO.ReadDesign[importeeName, Check, wDir];
IF design=NIL THEN RETURN;
CDRemote.CacheDesign[into, design];
};
};
2 => {
design: CD.Design ← CDIO.ReadDesign[NIL, Check, wDir];
IF design=NIL THEN RETURN;
CDRemote.CacheDesign[into, design];
};
ENDCASE => RETURN;
loaded ← CDImports.Load[into: into, importeeName: importeeName, overload: interactive, allowConflicts: interactive];
IF loaded
THEN
RETURN [CDImports.GetImportEntry[into: into, importeeName: importeeName]]
};
END;
GetImportedEntryCommand:
PROC [comm: CDSequencer.Command] =
BEGIN
objectName: Rope.ROPE;
referenceOb: CD.Object;
import: REF ImportDesign;
TerminalIO.WriteRope["draw object of imported design; "];
import ← OptionalLoad[comm.design];
IF import=NIL OR ~import.loaded THEN RETURN;
objectName ← TerminalIO.RequestRope["entry > "];
referenceOb ← CDImports.CreateImport[into: comm.design, objectName: objectName, importeeName: import.importeeName];
IF referenceOb=
NIL
THEN {
TerminalIO.WriteRopes[objectName, " not found in design ", import.importeeName];
TerminalIO.WriteRope["; not done\n"];
RETURN
};
CDOps.AddAnObject[design: comm.design, ob: referenceOb, location: comm.pos];
END;
DisplayImports:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRopes[comm.design.name, "'s import list: ", comm.design.name];
TerminalIO.WriteLn[];
FOR list:
LIST
OF
REF ImportDesign ← CDImports.GetImportList[comm.design]^, list.rest
WHILE list#
NIL
DO
TerminalIO.WriteRopes[" ", list.first.importeeName, (IF list.first.loaded THEN " +\n" ELSE " -\n")];
ENDLOOP;
TerminalIO.WriteRope["---\n"]
END;
DisplayImportedEntries:
PROC [comm: CDSequencer.Command] =
BEGIN
hasNotBound: BOOL ← FALSE; -- if importee loaded
importeeName: Rope.ROPE;
mdata: REF ImportDesign;
TerminalIO.WriteRope["display used entries of imported design\n"];
importeeName ← RequestImporteeName[comm.design];
mdata ← CDImports.GetImportEntry[comm.design, importeeName, false];
TerminalIO.WriteRope[importeeName];
IF mdata=NIL THEN CDSequencer.QuitCommand[" not imported"]
ELSE {
EachObject: CDDirectory.EachEntryAction = {
WITH ob.specificRef
SELECT
FROM
ip: CDImports.ImportPtr =>
IF Rope.Equal[ip.designName, mdata.importeeName]
THEN {
TerminalIO.WriteF[" %g (%g)", IO.rope[name], IO.rope[ip.objectName]];
IF ip.boundInstance=
NIL
THEN {
hasNotBound ← TRUE;
TerminalIO.WriteRope[" not loaded"];
};
TerminalIO.WriteRope["\n"];
};
ENDCASE => NULL
};
IF mdata.loaded THEN TerminalIO.WriteRope[" loaded\n"]
ELSE TerminalIO.WriteRope[" not yet loaded\n"];
[] ← CDDirectory.Enumerate[comm.design, EachObject];
TerminalIO.WriteRope["---"];
IF hasNotBound THEN TerminalIO.WriteRope[" has not-loaded entries"];
TerminalIO.WriteRope["\n"]
};
END;
ImportReadCommand:
PROC [comm: CDSequencer.Command] =
BEGIN
import: REF ImportDesign;
TerminalIO.WriteRope["load (or reload) a design for import\n"];
import ← OptionalLoad[comm.design, NIL, TRUE];
TerminalIO.WriteRope[IF import#NIL AND import.loaded THEN "done\n" ELSE "not done\n"];
END;
MerginImportCommand:
PROC [comm: CDSequencer.Command] =
BEGIN
importeeName: Rope.ROPE;
mdata: REF ImportDesign;
TerminalIO.WriteRope["merge imports into the design\n"];
importeeName ← RequestImporteeName[comm.design];
mdata ← CDImports.GetImportEntry[comm.design, importeeName, false];
IF mdata=
NIL
THEN {
TerminalIO.WriteRopes[importeeName, " not imported; not done\n"];
RETURN
}
ELSE
IF ~mdata.loaded
THEN {
TerminalIO.WriteRopes[importeeName, " is not yet loaded\n"];
[] ← OptionalLoad[comm.design, importeeName];
IF ~mdata.loaded THEN RETURN
};
CDImports.MergeInImports[into: comm.design, importeeName: importeeName];
TerminalIO.WriteRope["end merge\n"];
END;
--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--multi-design-copy feature
SelectADesign:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRopes["select ", comm.design.name, " for inter-design source\n"];
CDProperties.PutProp[$SelectedDesign, $SelectedDesign, comm.design];
END;
SelectedDesign:
PROC []
RETURNS [
CD.Design] =
BEGIN
WITH CDProperties.GetProp[$SelectedDesign, $SelectedDesign]
SELECT
FROM
d: CD.Design => RETURN [d];
ENDCASE => RETURN [NIL];
END;
DrawImportedCopy:
PROC [comm: CDSequencer.Command] =
BEGIN
GlobalSelection:
PROC [expectedTechnology:
CD.Technology]
RETURNS [foundNamed:
BOOL←
FALSE, foundWithoutChildren:
BOOL←
FALSE, moduleName: Rope.
ROPE←
NIL, objectName: Rope.
ROPE←
NIL, object:
CD.Object←
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.Instance; -- the referred application to support the name
multiple: BOOL;
[ap, multiple] ← CDOps.SelectedInstance[from];
IF multiple THEN Out[" multiple selection"]
ELSE IF ap=NIL THEN Out[" no selection"]
ELSE {
orient ← ap.orientation;
IF
NOT ap.ob.class.inDirectory
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;
foundNamed, foundWithoutChildren: BOOL;
moduleName, objectName: Rope.ROPE;
referenceOb, referedOb: CD.Object ← NIL;
orient: CD.Orientation;
TerminalIO.WriteRope["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.WriteRopes[moduleName, " is selected design; simply copy object\n"];
referenceOb ← CDDirectory.Fetch[comm.design, objectName].object;
}
ELSE {
import: REF ImportDesign ← 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.WriteF[" %g not found in imported design %g; ", IO.rope[objectName], IO.rope[moduleName]];
}
}
};
IF referenceOb=NIL THEN TerminalIO.WriteRope[" not done\n"]
ELSE {
CDOps.AddAnObject[comm.design, referenceOb, comm.pos, orient];
TerminalIO.WriteRopes[CDOps.Info[referenceOb], " included\n"];
}
END;
LoadAllImps:
PROC[importerDesign:
CD.Design] =
--Tries to import all designs which are used for importerDesign;
--Does not allow any conflicts, nor overloading.
--Search in the userprofile for filenames corresponding to the design names.
--Quite talky on TerminalIO, but not interactive
BEGIN
TryToImport:
PROC [ri:
REF CDImports.ImportDesign] =
BEGIN
wDir: Rope.ROPE ← CDIO.GetWorkingDirectory[importerDesign];
done: BOOL ← FALSE;
fileName: Rope.ROPE ← UserProfile.Token[Rope.Cat["ChipNDale.ImportFor.", ri.importeeName], NIL];
IF Rope.IsEmpty[fileName] THEN fileName ← ri.importeeName;
fileName ← CDIO.MakeName[base: fileName, ext: ".dale", wDir: wDir];
CDSequencer.CheckAborted[importerDesign];
[] ← CDRemote.GetTableUsingFile[importerDesign, ri.importeeName, fileName];
CDSequencer.CheckAborted[importerDesign];
done ← CDImports.Load[into: importerDesign, importeeName: ri.importeeName, overload: false, allowConflicts: false];
IF done THEN TerminalIO.WriteRope[" imported"]
ELSE TerminalIO.WriteRope[" not imported"]
END;
HandleOneImport:
PROC [ri:
REF CDImports.ImportDesign] =
BEGIN
TerminalIO.WriteRopes[" ", ri.importeeName, " "];
IF ri.loaded THEN TerminalIO.WriteRope[" already imported"] ELSE TryToImport[ri];
TerminalIO.WriteLn[];
END;
--LoadAllImps
FOR list:
LIST
OF
REF CDImports.ImportDesign ← CDImports.GetImportList[importerDesign]^, list.rest
WHILE list#
NIL
DO
HandleOneImport[list.first]
ENDLOOP;
END;
LoadAllImpsCommand:
PROC [comm: CDSequencer.Command] =
--Load all imports
--Checks first for an userprofile entry;
--checks then for filename=designname
BEGIN
TerminalIO.WriteRope["load all imported designs\n"];
LoadAllImps[comm.design];
TerminalIO.WriteRope[" --\n"];
END;
ReplaceIncludesByImportsComm:
PROC [comm: CDSequencer.Command] =
BEGIN
FindObjects: CDDirectory.EachEntryAction = {
--uses global replaceList
WITH CDProperties.GetPropFromObject[ob, $CameFrom]
SELECT
FROM
--putting the objectnames in the RefTab keeps them even if replacement is in wrong order
r: Rope.ROPE => [] ← RefTab.Insert[x: replaceList, key: ob, val: CDProperties.GetPropFromObject[ob, $OriginalName]];
ENDCASE => NULL
};
ReplaceObjects: RefTab.EachPairAction =
--uses globals table and design
BEGIN quit ← FALSE;
WITH val
SELECT
FROM
r: Rope.
ROPE => {
ob: CD.Object ← NARROW[key];
oldName: Rope.ROPE ← CDDirectory.Name[ob];
new: CD.Object ← CDGenerate.FetchNCall[table, design, r];
IF new#
NIL
THEN {
msg: Rope.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.size=ob.size
AND
CD.InterestRect[new]=
CD.InterestRect[ob]
THEN " replaced" ELSE " replaced (size conflict)";
TerminalIO.WriteF["%g %g by %g\n",
IO.rope[msg],
IO.rope[oldName],
IO.rope[CDDirectory.Name[new]]
];
};
CDSequencer.CheckAborted[design];
};
ENDCASE => NULL
END;
replaceList: RefTab.Ref ← RefTab.Create[];
import: REF ImportDesign;
table: CDGenerate.Table;
design: CD.Design ← comm.design;
TerminalIO.WriteRope["replace included objects by imports\n"];
import ← OptionalLoad[comm.design];
IF import=NIL THEN {TerminalIO.WriteRope[" not loded\n"]; RETURN};
table ← CDGenerateImports.GetImportTable[import.importeeName];
[] ← CDDirectory.Enumerate[comm.design, FindObjects];
[] ← RefTab.Pairs[replaceList, ReplaceObjects];
TerminalIO.WriteRope[" --\n"];
END;
[] ← CDProperties.RegisterProperty[$SelectedDesign, $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[$ReplaceByImp, ReplaceIncludesByImportsComm];
CDMenus.CreateEntry[$ImportMenu, "load all imports", $LoadAllImps];
CDMenus.CreateEntry[$IOMenu, "load all imports", $LoadAllImps];
CDMenus.CreateEntry[$ImportMenu, "replace included by imports", $ReplaceByImp];
CDMenus.CreateEntry[$ImportMenu, "select DESIGN", $SelectADesign];
END.