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["", 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.IncludeObjectI[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.Quit[" 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; 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] = 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.IncludeObjectI[comm.design, referenceOb, comm.pos, orient]; TerminalIO.WriteRopes[CDOps.ObjectInfo[referenceOb], " included\n"]; } END; LoadAllImps: PROC[importerDesign: CD.Design] = 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; 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] = BEGIN TerminalIO.WriteRope["load all imported designs\n"]; LoadAllImps[comm.design]; TerminalIO.WriteRope[" --\n"]; END; ReplaceIncludesByImportsComm: PROC [comm: CDSequencer.Command] = BEGIN FindObjects: CDDirectory.EachEntryAction = { WITH CDProperties.GetObjectProp[ob, $CameFrom] SELECT FROM r: Rope.ROPE => [] _ RefTab.Insert[x: replaceList, key: ob, val: CDProperties.GetObjectProp[ob, $OriginalName]]; ENDCASE => NULL }; ReplaceObjects: RefTab.EachPairAction = 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 import", $ImportADesign]; CDMenus.CreateEntry[$ImportMenu, "list imports", $DisplayImports]; CDMenus.CreateEntry[$ImportMenu, "list importee's ob", $DisplayImportedEntries]; CDMenus.CreateEntry[$ImportMenu, "merge in import", $MerginImport]; CDMenus.CreateEntry[$ImportMenu, "include", $IncludeADesign]; CDMenus.CreateEntry[$ImportMenu, "load all imports", $LoadAllImps]; CDMenus.CreateEntry[$ImportMenu, "replace included by imports", $ReplaceByImp]; CDMenus.CreateEntry[$ImportMenu, "select DESIGN", $SelectADesign]; END. ΜCDImportCommands.mesa (part of ChipNDale) Copyright c 1984, 1986 by Xerox Corporation. All rights reserved. by Christian Jacobi, March 20, 1984 5:50:51 pm PST last edited Christian Jacobi, March 26, 1986 3:36:09 pm PST --xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --multi-design-copy feature --never returns with both foundNamed and foundWithoutChildren set to true --if not found then message to TerminalIO --if foundNamed then both, moduleName, objectName # NIL --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 --LoadAllImps --Load all imports --Checks first for an userprofile entry; --checks then for filename=designname --uses global replaceList --putting the objectnames in the RefTab keeps them even if replacement is in wrong order --uses globals table and design Κή˜codešœ+™+Kšœ Οmœ7™BKšœ5™5Kšœ=™=K˜—šΟk ˜ Kšžœ˜K˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜K˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ —K˜šΠblœžœžœ˜ Kšžœ ˜§Kšžœ ˜—Kšž˜K˜Kšœ žœ˜'Kšœ žœ˜&Kšœ žœ˜(Kšœžœ˜,K˜š Οnœžœžœ žœžœ˜OKšž˜Kšœžœ˜ Kšœžœ˜ Kš œžœžœžœžœ˜Kšœžœžœžœ/˜>šžœžœžœžœžœžœžœž˜OKšœ ˜ Kšœžœ˜'Kšžœ˜—Kšžœžœžœ˜šžœ˜Kšœ(žœ+˜W—Kšžœžœ8˜Cšžœžœžœ žœ˜Kšžœžœžœžœ˜*Kšœ˜Kšœ8˜8K˜—Kšžœžœ˜Kšžœ˜—K˜š  œžœžœžœžœ žœžœžœ žœžœ˜Kšž˜K˜š  œžœ žœ žœžœ˜4Kšž˜Kšœžœ˜ šžœžœ#žœ˜0KšœZ˜ZKšžœžœ˜K˜—Kšœžœ˜&šžœžœ˜Kšœ-˜-Kšžœžœ˜K˜—šžœžœ˜$KšœG˜GKšžœžœ˜K˜—šžœžœ˜(Kšœ:˜:Kšžœžœ˜K˜—Kšžœžœ˜Kšžœ˜—K˜Kšœžœ˜Kšœžœžœ˜Kšœ žœžœ˜1šžœžœ˜$Kšœ)˜)Kšœ˜—šžœžœ˜$Kšœ&˜&Kšž˜K˜—KšœJ˜Jš žœžœžœžœ žœ˜1šžœ%žœžœ˜MKšœG˜GKšžœžœ˜ K˜—Kšžœ žœ?˜NKšœXžœ*˜†šžœž˜ ˜šžœ žœ˜Kšœžœ žœ'˜?Kšžœžœžœžœ˜Kšœ#˜#Kšœ˜—Kšœ˜—˜Kšœžœ žœ žœ˜6Kšžœžœžœžœ˜Kšœ#˜#K˜—Kšžœžœ˜—Kšœt˜tšžœžœ˜KšžœC˜I—K˜—Kšžœ˜—K˜šΠbnœžœ˜;Kšž˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜K˜9Kšœ#˜#Kš žœžœžœžœž˜,Kšœ0˜0Kšœs˜sšžœ žœžœ˜KšœQ˜QKšœ%˜%Kšž˜Kšœ˜—KšœO˜OKšžœ˜—K˜K˜š œžœ˜2Kšž˜KšœN˜NK˜š žœžœžœžœAžœžœž˜gKšœ7žœžœžœ ˜fKšžœ˜ —Kšœ˜Kšžœ˜K˜—K™š œžœ˜:Kšž˜Kšœ žœžœΟc˜1Kšœžœ˜Kšœžœ˜KšœB˜BKšœ0˜0KšœC˜CKšœ#˜#Kšžœžœžœ"˜3šžœ˜K˜šΟb œ!˜+šžœžœžœ˜ šœžœ/žœ˜RKšœ!žœ žœ˜Hšžœžœžœ˜Kšœžœ˜Kšœ$˜$K˜—Kšœ˜K˜—Kšžœž˜—Kšœ˜K˜—Kšžœžœ#˜7Kšžœ+˜/Kšœ4˜4Kšœ˜Kšžœ žœ1˜DKšœ˜K˜—Kšžœ˜K˜—š œžœ˜6Kšž˜Kšœžœ˜Kšœ?˜?Kšœ#žœžœ˜.Kš œžœžœžœžœ žœ˜VKšžœ˜—K˜š œžœ˜8Kšž˜Kšœžœ˜Kšœžœ˜Kšœ8˜8Kšœ0˜0KšœC˜Cšžœžœžœ˜KšœA˜AKšž˜K˜—šžœžœžœ˜Kšœ<˜˜>KšœΒ˜ΒKšžœžœ˜4šžœžœ žœ˜šžœ*žœ˜2KšœO˜OKšœ@˜@K˜—šžœ˜Kšœžœ6˜Ašžœžœžœžœ˜'Kšœj˜jKš žœ žœžœ=žœžœ˜~K˜—K˜—Kšœ˜—Kšžœ žœžœ$˜;šžœ˜KšœA˜AKšœD˜DK˜—Kšžœ˜—K™š  œžœžœ ˜.Kšœ@™@Kšœ0™0KšœN™NKšœ0™0Kšž˜K˜š  œžœžœ˜4Kšž˜Kšœ žœžœ%˜;Kšœžœžœ˜KšœžœHžœ˜bKšžœžœ˜:Kšœ žœ4˜CKšœ)˜)KšœK˜KKšœ)˜)Kšœs˜sKšžœžœ#˜/Kšžœ'˜+Kšžœ˜—K˜š œžœžœ˜8Kšž˜Kšœ2˜2Kšžœ žœ*žœ˜QKšœ˜Kšžœ˜—K˜Kšœ ™ š žœžœžœžœNžœžœž˜tKšœ˜Kšžœ˜ —Kšžœ˜—K˜š œžœ˜7Kšœ™Kšœ(™(Kšœ%™%Kšž˜Kšœ4˜4Kšœ˜Kšœ˜Kšžœ˜—K˜š œžœ˜AKšž˜K˜š£ œ!˜,Kšœ™šžœ+žœž˜:KšœX™XKšœžœd˜pKšžœž˜—Kšœ˜K˜—š£œ˜'Kšœ™Kšžœžœ˜šžœžœž˜šœžœ˜Kšœžœ žœ˜Kšœžœ˜*Kšœ:˜:šžœžœžœ˜Kšœ žœ˜Kšœ+˜+Kšžœ*žœMžœ˜ƒš œžœžœžœžœ˜GKšžœžœ˜4—šœ#˜#Kšžœ ˜Kšžœ˜Kšžœ˜Kšœ˜—K˜—Kšœ!˜!Kšœ˜—Kšžœž˜—Kšžœ˜—K˜Kšœ+˜+Kšœžœ˜Kšœ˜Kšœ ˜ Kšœ>˜>Kšœ#˜#Kšžœžœžœ(žœ˜CKšœ>˜>Kšœ5˜5Kšœ/˜/Kšœ˜Kšžœ˜—K˜Kšœ:˜:KšœE˜EKšœH˜HKšœX˜XKšœ@˜@KšœF˜FKšœI˜IKšœA˜AKšœI˜IKšœJ˜JK˜Kšœ@˜@KšœB˜BKšœP˜PKšœC˜CKšœ=˜=KšœC˜CKšœO˜OKšœB˜BKšžœ˜K˜—…—5 HΚ