DIRECTORY Ascii, Atom, CD, CDEnvironment, CDEvents, CDOps, CDValue, Commander, CommandTool, FileNames, FS, Icons, IO, List, PopUpSelection, ProcessProps, Rope, RuntimeError, SystemNames, TerminalIO, TEditImpl USING [ReloadTable], --crazy, wonderful tiptable load procedure TIPUser, UserProfile; CDEnvironmentImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDEvents, CDOps, CDValue, Commander, CommandTool, FileNames, FS, Icons, IO, List, PopUpSelection, ProcessProps, RuntimeError, Rope, SystemNames, TEditImpl, TerminalIO, TIPUser, UserProfile EXPORTS CDEnvironment = BEGIN cdVersion: PUBLIC NAT _ 25; preRelease: PUBLIC BOOL _ FALSE; date: Rope.ROPE = "April 17, 1987"; profilePrefix: PUBLIC Rope.ROPE _ IO.PutFR["ChipNDale%g.", [integer[cdVersion]]]; commandsPrefix: Rope.ROPE _ FileNames.ConvertToSlashFormat[SystemNames.LocalDir["Commands"]]; systemPrefix: Rope.ROPE _ FileNames.ConvertToSlashFormat[SystemNames.LocalDir["System"]]; Prefixed: PROC [r1, r2: Rope.ROPE_NIL] RETURNS [Rope.ROPE] = { RETURN [Rope.Cat[profilePrefix, r1, r2]] }; copyRight: Rope.ROPE = "Copyright (C) 1984, 1987 by Xerox Corporation. All rights reserved.\n\n"; SetTipTable: PUBLIC PROC [for: REF, tipTable: Rope.ROPE] = { TryExplicitTipTable: PROC [for: REF, name: Rope.ROPE] RETURNS [tipTable: TIPUser.TIPTable] = { name _ MakeName[base: name, ext: "tip", wDir: TechWDir[for]]; tipTable _ TIPUser.InstantiateNewTIPTable[name ! FS.Error => { TerminalIO.PutRopes["Tip-table not installed; ", error.explanation, "\n"]; GOTO oops }; TIPUser.InvalidTable => { TerminalIO.PutRopes["Tip-table not installed; ", errorMsg, "\n"]; GOTO oops }; ]; EXITS oops => NULL }; InstallStandardTip: PROC [for: REF] RETURNS [tipTable: TIPUser.TIPTable _ NIL] = { WITH for SELECT FROM tech: CD.Technology => { techPart: Rope.ROPE _ MakeName[base: "ChipNDale", ext: "tip", modifier: tech.name, wDir: GetWorkingDirectory[tech]]; base: Rope.ROPE _ MakeName[base: "ChipNDale", ext: "tip", wDir: GetWorkingDirectory[NIL]]; default: Rope.ROPE _ Rope.Cat[techPart, " ", base]; tipTable _ TEditImpl.ReloadTable[oldTIP: NIL, profileKey: Prefixed[tech.name, ".TIP"], default: default]; IF tipTable=NIL THEN { TerminalIO.PutRopes["* tip-table for ", tech.name, " not installed\n"]; tipTable _ TryExplicitTipTable[for, "ChipNDale.tip"]; }; }; d: CD.Design => tipTable _ InstallStandardTip[d.technology]; ENDCASE => TerminalIO.PutRope["* tip-table not installed\n"]; }; tipTab: TIPUser.TIPTable _ NIL; IF Rope.IsEmpty[tipTable] THEN tipTable _ "Standard"; CDValue.Store[for, $TipTableName, tipTable]; IF Rope.Equal[tipTable, "Standard"] THEN tipTab _ InstallStandardTip[for] ELSE tipTab _ TryExplicitTipTable[for, tipTable]; IF tipTab#NIL THEN CDValue.Store[for, $TipTable, tipTab]; }; GetTipTable: PUBLIC PROC [for: REF] RETURNS [TIPUser.TIPTable] = { WITH CDValue.Fetch[boundTo: for, key: $TipTable, propagation: global] SELECT FROM tipTable: TIPUser.TIPTable => RETURN [tipTable]; ENDCASE => RETURN [NIL]; }; ReInstallStandardTipTables: Commander.CommandProc = { EachTech: CD.TechnologyEnumerator = { WITH CDValue.Fetch[tech, $TipTableName] SELECT FROM r: Rope.ROPE => IF Rope.Equal[r, "Standard"] THEN SetTipTable[tech, r]; ENDCASE => NULL; }; [] _ CD.EnumerateTechnologies[EachTech]; [] _ CDEvents.ProcessEvent[reInstallTipTables, NIL]; }; FetchIconFromFile: PROC [for: REF, file: Rope.ROPE, n: NAT] RETURNS [icon: REF Icons.IconFlavor] = { if: Icons.IconFlavor; icon _ NEW[Icons.IconFlavor_tool]; file _ MakeName[base: file, ext: "icon", wDir: TechWDir[for]]; if _ Icons.NewIconFromFile[file, n ! RuntimeError.UNCAUGHT => GOTO Oops]; icon^ _ if; EXITS Oops => TerminalIO.PutRope["** icon not loaded\n"]; }; SetIcon: PUBLIC PROC [for: REF, file: Rope.ROPE, n: NAT] = { icon: REF Icons.IconFlavor _ FetchIconFromFile[for, file, n]; CDValue.Store[for, $Icon, icon]; }; GetIcon: PUBLIC PROC [for: REF] RETURNS [Icons.IconFlavor] = { WITH CDValue.Fetch[for, $Icon, global] SELECT FROM ip: REF Icons.IconFlavor => RETURN [ip^]; ENDCASE => RETURN [Icons.IconFlavor[unInit]] }; SetPanelIcon: PUBLIC PROC [for: REF, file: Rope.ROPE, n: NAT] = { icon: REF Icons.IconFlavor _ FetchIconFromFile[for, file, n]; CDValue.Store[for, $PanelIcon, icon]; }; GetPanelIcon: PUBLIC PROC [for: REF] RETURNS [Icons.IconFlavor] = { WITH CDValue.Fetch[for, $PanelIcon, global] SELECT FROM ip: REF Icons.IconFlavor => RETURN [ip^]; ENDCASE => RETURN [Icons.IconFlavor[unInit]] }; CheckWDir: PROC [wDir: Rope.ROPE] RETURNS [slashWDir: Rope.ROPE] = { length: INT; IF FileNames.IsADirectory[wDir] AND ~FileNames.IsAPattern[wDir] THEN { slashWDir _ FileNames.ConvertToSlashFormat[wDir]; length _ Rope.Length[slashWDir]; IF length>0 AND slashWDir.Fetch[length-1]='/ THEN RETURN [slashWDir]; }; RETURN [NIL] }; SetWorkingDirectory: PUBLIC PROC [for: REF, wDir: Rope.ROPE] = { IF wDir=NIL THEN { WITH for SELECT FROM t: CD.Technology => { techName: Rope.ROPE _ t.name; IF techName=NIL THEN techName _ Atom.GetPName[t.key]; wDir _ UserProfile.Token[Prefixed[techName, ".BaseDirectory"]]; }; d: CD.Design => NULL; ENDCASE => IF for=NIL THEN { wDir _ UserProfile.Token[Prefixed["BaseDirectory"]]; }; IF wDir=NIL THEN wDir _ FileNames.CurrentWorkingDirectory[]; }; CDValue.Store[for, $WorkingDirectory, CheckWDir[wDir]]; }; GetWorkingDirectory: PUBLIC PROC [for: REF] RETURNS [wDir: Rope.ROPE_NIL] = { WITH CDValue.Fetch[for, $WorkingDirectory, global] SELECT FROM r: Rope.ROPE => wDir _ CheckWDir[r]; ENDCASE => NULL; }; DoWithWDir: PUBLIC PROC [wDir: Rope.ROPE, proc: PROC] = { ProcessProps.AddPropList[ propList: Atom.PutPropOnList[NIL, $WorkingDirectory, wDir], inner: proc ]; }; RegisterCommander: PUBLIC PROC [key: Rope.ROPE, proc: Commander.CommandProc _ NIL, doc: Rope.ROPE _ NIL, clientData: REF _ NIL, interpreted: BOOL _ TRUE, technology: CD.Technology _ NIL] = { gWDir: Rope.ROPE _ GetWorkingDirectory[NIL]; Commander.Register[key: key, proc: proc, doc: doc, clientData: clientData, interpreted: interpreted]; Commander.Register[key: Rope.Cat[gWDir, key], proc: proc, doc: doc, clientData: clientData, interpreted: interpreted]; IF technology#NIL THEN { tWDir: Rope.ROPE _ GetWorkingDirectory[technology]; IF ~Rope.Equal[gWDir, tWDir] THEN Commander.Register[key: Rope.Cat[tWDir, key], proc: proc, doc: doc, clientData: clientData, interpreted: interpreted] } }; MakeName: PUBLIC PROC [base: Rope.ROPE, ext: Rope.ROPE_NIL, wDir: Rope.ROPE_NIL, modifier: Rope.ROPE_NIL] RETURNS [Rope.ROPE] = { TrailingChar: PROC [base: Rope.ROPE, char: CHAR] RETURNS [INT] = { len: INT _ Rope.Length[base]; pos: INT _ len; WHILE pos > 0 DO SELECT Rope.Fetch[base, pos _ pos - 1] FROM char => RETURN [pos]; '!, '], '>, '/ => EXIT; ENDCASE; ENDLOOP; RETURN [len]; }; bang: INT = TrailingChar[base, '!]; r: Rope.ROPE _ Rope.Substr[base: base, len: bang]; IF ~modifier.IsEmpty[] THEN r _ Rope.Concat[r, modifier]; IF ~ext.IsEmpty[] AND (TrailingChar[r, '.]>=Rope.Length[r]) THEN { dot2: INT _ TrailingChar[ext, '.]; IF dot2>=Rope.Length[ext] THEN r _ Rope.Cat[r, ".", ext] ELSE r _ Rope.Concat[r, ext.Substr[dot2]] }; IF wDir#NIL THEN { IF Rope.IsEmpty[r] OR (Rope.Fetch[r]#'/ AND Rope.Fetch[r]#'[) THEN { dir: Rope.ROPE _ FileNames.Directory[wDir]; IF ~Rope.IsEmpty[dir] THEN r _ Rope.Cat[FileNames.ConvertToSlashFormat[dir], r] } }; IF bang searchPath _ rl; r: Rope.ROPE => searchPath _ LIST[r]; r: REF TEXT => searchPath _ LIST[Rope.FromRefText[r]]; d: CD.Design => { AddToWDir[GetWorkingDirectory[d.technology]]; AddToWDir[GetWorkingDirectory[d]]; }; t: CD.Technology => { AddToWDir[GetWorkingDirectory[t]]; }; ENDCASE => NULL; AddToWDir[FileNames.CurrentWorkingDirectory[]]; IF Rope.Length[ext]>0 AND Rope.Fetch[ext, 0]#'. THEN ext _ Rope.Concat[".", ext]; fn _ FileNames.FileWithSearchRules[root: base, defaultExtension: ext, requireExtension: FALSE, requireExact: TRUE, searchRules: searchPath].fullPath; }; RemoveSpaces: PUBLIC PROC [line: Rope.ROPE] RETURNS [Rope.ROPE_NIL] = { leng: INT _ Rope.Length[line]; start: INT _ 0; WHILE start start _ start+1; ENDCASE => EXIT; ENDLOOP; WHILE leng>start DO SELECT Rope.Fetch[line, leng-1] FROM Ascii.SP, Ascii.TAB => leng _ leng-1; ENDCASE => EXIT; ENDLOOP; IF leng>start THEN RETURN [Rope.Substr[line, start, leng-start]]; }; SplitLine: PUBLIC PROC [line: Rope.ROPE] RETURNS [key, rest: Rope.ROPE_NIL] = { leng: INT _ Rope.Length[line]; nextPos: INT _ 0; startPos: INT _ 0; WHILE startPos startPos _ startPos+1; ENDCASE => EXIT; ENDLOOP; nextPos _ startPos; WHILE nextPos EXIT; ENDCASE => nextPos _ nextPos+1; ENDLOOP; IF startPos nextPos _ nextPos+1; ENDCASE => {rest _ Rope.Substr[line, nextPos, leng-nextPos]; RETURN} ENDLOOP; }; FetchKeyLine: PUBLIC PROC [fileName: Rope.ROPE, key: Rope.ROPE] RETURNS [entry: Rope.ROPE_NIL] = { line, first, rest: Rope.ROPE; file: IO.STREAM; file _ FS.StreamOpen[fileName ! FS.Error => GOTO finish]; DO line _ IO.GetLineRope[file ! IO.EndOfStream => GOTO finish]; IF ~Rope.IsEmpty[line] THEN { [first, rest] _ SplitLine[line]; IF Rope.Equal[first, key] THEN RETURN [rest] } ENDLOOP; EXITS finish => NULL; }; StuffToCommandTool: PUBLIC PROC [r: Rope.ROPE, wDir: Rope.ROPE_NIL, searchPath: LIST OF Rope.ROPE_NIL, catchErrors: BOOL_TRUE, continueErrors: BOOL_TRUE] RETURNS [result: REF_NIL] = { RopeListPath: PROC [rl: LIST OF Rope.ROPE] RETURNS [path: List.LORA _ NIL] = { last: Rope.ROPE_NIL; FOR l: LIST OF Rope.ROPE _ rl, l.rest WHILE l#NIL DO IF ~Rope.IsEmpty[l.first] AND ~Rope.Equal[last, l.first, FALSE] THEN { last _ l.first; path _ CONS[last, path]; } ENDLOOP; RETURN [List.DReverse[path]] }; propertyList: List.AList _ List.PutAssoc[key: $StopOnFailure, val: $TRUE, aList: NIL]; --temporary out: Rope.ROPE; --for the result rope returned by the CommandTool cmd: Commander.Handle _ NEW[Commander.CommandObject _ [ out: TerminalIO.TOS[], err: TerminalIO.TOS[], in: IO.noInputStream, propertyList: List.PutAssoc[key: $SearchRules, val: RopeListPath[searchPath], aList: propertyList] ]]; Exec: PROC [] = { [out, result] _ CommandTool.DoCommandRope[commandLine: r, parent: cmd]; }; IF Rope.IsEmpty[r] THEN TerminalIO.PutRopes["executes empty command\n"] ELSE { TerminalIO.PutRopes["executes: """, r, """\n"]; DoWithWDir[wDir, Exec ! ABORTED => {TerminalIO.PutRope["\n**aborted\n"]; IF continueErrors THEN CONTINUE}; RuntimeError.UNCAUGHT => { IF ~catchErrors THEN REJECT ELSE SELECT PopUpSelection.Request[ header: "ERROR", choice: LIST["continue with ChipNDale", "debug"], headerDoc: "error while executing stuff", choiceDoc: LIST["usually ok", "land in debugger (abort will continue ChipNDale)"], timeOut: 600 --10 minutes ] FROM 1 => CONTINUE; -1 => {TerminalIO.PutRope["\n**Timed out request for debugging: reject will probably open a debugger window\n"]; REJECT}; 2 => REJECT; ENDCASE => CONTINUE; }; ]; TerminalIO.PutRopes["\n{", out, "}\n"]; }; }; ExecFileEntry: PUBLIC PROC [key: Rope.ROPE, technology: CD.Technology_NIL, modifier: Rope.ROPE_NIL, catchErrors: BOOL_TRUE, continueErrors: BOOL_TRUE] = { wDir: Rope.ROPE; --for working directories entry: Rope.ROPE; --for the line which will be stuffed into a command tool Fetch: PROC [mod: Rope.ROPE] = { IF modifier#NIL THEN mod _ Rope.Cat[mod, "-", modifier]; mod _ MakeName["ChipNDale-", "CDLoadList", wDir, mod]; entry _ FetchKeyLine[mod, key]; }; searchPath: LIST OF Rope.ROPE _ LIST[GetWorkingDirectory[NIL], commandsPrefix, systemPrefix]; IF technology#NIL THEN { wDir _ GetWorkingDirectory[technology]; searchPath _ CONS[wDir, searchPath]; Fetch[technology.name]; }; IF entry=NIL THEN { wDir _ GetWorkingDirectory[NIL]; Fetch["CD"]; }; IF entry=NIL THEN TerminalIO.PutRopes["command line for ", key, " not found\n"] ELSE [] _ StuffToCommandTool[entry, wDir, searchPath, catchErrors, continueErrors]; }; LoadTechnology: PUBLIC PROC [key: ATOM, name: Rope.ROPE] RETURNS [tech: CD.Technology_NIL] = { IF key#NIL THEN { tech _ CD.FetchTechnology[key]; IF tech=NIL THEN tech _ GetTechnology[key]; }; IF tech=NIL THEN { IF name#NIL THEN tech _ GetTechnology[name]; IF tech=NIL THEN { autoLoadDefault: BOOL _ UserProfile.Boolean[Prefixed["AutoLoad.Default"], TRUE]; IF Rope.IsEmpty[name] THEN name _ Atom.GetPName[key]; IF UserProfile.Boolean[Prefixed["AutoLoad.", name], autoLoadDefault] THEN { TerminalIO.PutRopes["load technology """, name, """ \n"]; ExecFileEntry[name, NIL, NIL, TRUE, TRUE]; IF key#NIL THEN tech _ GetTechnology[key]; IF tech=NIL THEN tech _ GetTechnology[name]; }; IF tech=NIL THEN TerminalIO.PutRopes["technology '", name, "' not loaded\n"]; }; }; }; AskAndExecute: Commander.CommandProc = { question: Rope.ROPE; cl: Rope.ROPE _ cmd.commandLine; IF Rope.IsEmpty[cl] THEN RETURN; question _ Rope.Cat["execute: ", Rope.Substr[base: cl, len: Rope.Length[cl]-1]]; IF ~TerminalIO.Confirm[text: question, dontLog: TRUE] THEN RETURN [$Failure, "denied"]; result _ CommandTool.DoCommand[commandLine: cl, parent: cmd]; }; GetTechnology: PUBLIC PROC [hint: REF] RETURNS [technology: CD.Technology] = { GetWithRope: PROC [name: Rope.ROPE] RETURNS [t: CD.Technology_NIL] = { EachTechnology: CD.TechnologyEnumerator = { IF Rope.Equal[tech.name, name, FALSE] OR Rope.Equal[Atom.GetPName[tech.key], name, FALSE] THEN {quit _ TRUE; technology _ tech} }; IF Rope.IsEmpty[name] THEN RETURN; [] _ CD.EnumerateTechnologies[EachTechnology]; }; WITH hint SELECT FROM tech: CD.Technology => RETURN [tech]; d: CD.Design => RETURN [d.technology]; a: ATOM => technology _ CD.FetchTechnology[a]; ENDCASE => NULL; IF technology=NIL THEN RETURN [GetWithRope[CDOps.ToRope[hint]]] }; TechWDir: PROC [for: REF] RETURNS [Rope.ROPE] = { WITH for SELECT FROM d: CD.Design => for _ d.technology ENDCASE => NULL; RETURN [GetWorkingDirectory[for]] }; TechnologyHasBeenRegisterd: CDEvents.EventProc = { WITH x SELECT FROM t: CD.Technology => { SetWorkingDirectory[t, NIL]; }; ENDCASE => NULL }; NewDesignHasBeenCreated: CDEvents.EventProc = { IF design#NIL THEN SetWorkingDirectory[design, FileNames.CurrentWorkingDirectory[]]; }; reInstallTipTables: CDEvents.EventRegistration _ CDEvents.RegisterEventType[ $CDReRegisterTipTables]; CDValue.RegisterKey[$TipTable, NIL, $CD]; CDValue.RegisterKey[$TipTableName, NIL, $CD]; CDValue.RegisterKey[$Icon, NIL, $CD]; CDValue.RegisterKey[$WorkingDirectory, NIL, $CD]; SetIcon[NIL, "ChipNDale.icons", 0]; SetPanelIcon[NIL, "ChipNDale.icons", 1]; SetWorkingDirectory[NIL, NIL]; CDEvents.RegisterEventProc[$CreateNewDesign, NewDesignHasBeenCreated]; CDEvents.RegisterEventProc[$RegisterTechnology, TechnologyHasBeenRegisterd]; RegisterCommander["CDReInstallTipTables", ReInstallStandardTipTables, "Reload TIP tables for standard ChipNDale technologies"]; RegisterCommander["AskFirst", AskAndExecute, "Conditionally executes command"]; TerminalIO.PutF["ChipNDale\n %g Version %g.%g for Cedar %g\n %g\n Copyright (C) 1984, 1987 by Xerox Corporation. All rights reserved.\n\n", [rope[IF preRelease THEN "PRE RELEASED" ELSE ""]], [integer[cdVersion/10]], [integer[cdVersion MOD 10]], [rope[SystemNames.ReleaseName[]]], [rope[date]] ]; END. ΊCDEnvironmentImpl.mesa (part of ChipNDale) Copyright c 1983, 1987 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, August 11, 1983 11:32 am Last Edited by: Christian Jacobi, April 17, 1987 10:55:16 am PDT -- versions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- tip tables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Icons ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Working Directories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --if wDir is a directory, return it in slash format --else return NIL -- Commander ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Names ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --position of last "char", only before '!, '], '>, '/ considered --remove version number --include modifier --include extension --include working directory --put version number back -- Loader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --skip leading spaces --find position of separator --skip leading spaces again --Searches for a line starting with key in file --Returns the rest of the line found or NIL if not found --checks whether a particular key is mentioned in a .CDLoadList file --if particular key is found, executes the rest of the line with a command tool --technology and modifier are used to make the name of the used .CDLoadList file --(using modifier .CDLoadList files for particular feature classes can be distinguished) --building of name for the .CDLoadList files: -- ChipNDale-CD.CDLoadList if {technology=NIL, modifier=NIL} -- ChipNDale-CD-modifier.CDLoadList if {technology=NIL, modifier#NIL} -- ChipNDale-technologyName.CDLoadList if {technology#NIL, modifier=NIL} -- ChipNDale-technologyName-modifier.CDLoadList if {technology#NIL, modifier#NIL} --internal procedure --makes up the full path name of the .CDLoadList file --and looks for a particular entry line in it --mod: name for the technology --makes all the necessary messages if not loaded -- internals ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ΚΗ˜codešœ1™1Kšœ Οmœ7™BKšœ7™7K™@K˜—šΟk ˜ Kšœž˜Kšœž˜Kšžœ˜Kšœ˜Kšœ ˜ K˜K˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ žœΟc*˜IKšœ˜Kšœ ˜ —K˜šΟnœžœžœ˜!Kšžœžœ?žœ žœr˜ΞKšžœ˜—Kšž˜K˜Kšœ4™4K™K˜Kšœ žœžœ˜Kšœ žœžœžœ˜ Kšœ žœ˜#K˜Kšœžœžœžœ-˜QKšœžœD˜]KšœžœB˜YK˜š  œžœžœžœžœžœ˜>Kšžœ"˜(K˜—K™KšœžœN˜bK™Kšœ6™6K™š   œžœžœžœžœ˜<š  œžœžœ žœžœ!˜^Kšœ=˜=šœ1˜1šžœ ˜ KšœJ˜JKšžœ˜ Kšœ˜—šœ˜KšœA˜AKšžœ˜ Kšœ˜—Kšœ˜—Kšžœ ž˜Kšœ˜—š  œžœžœžœžœ˜Ršžœžœž˜šœžœ˜Kšœžœa˜tKšœ žœEžœ˜ZKšœžœ"˜4Kšœ)žœ=˜išžœ žœžœ˜KšœG˜GKšœ5˜5K˜—Kšœ˜—Kšœžœ8˜=Kšžœ6˜=—Kšœ˜—Kšœžœ˜Kšžœžœ˜6Kšœ,˜,Kšžœ"žœ!˜IKšžœ-˜1Kšžœžœžœ'˜9Kšœ˜—K˜š   œžœžœžœžœ˜BšžœBžœž˜QKšœžœ ˜0Kšžœžœžœ˜—Kšœ˜—K˜šΠbnœ˜5š‘œžœ˜%šžœ$žœž˜3Kšœžœžœžœ˜GKšžœžœ˜—K˜—Kšœžœ!˜(Kšœ/žœ˜4Kšœ˜—K™K™Kšœ4™4K˜š œžœžœ žœžœžœžœ˜dKšœ˜Kšœžœ˜"Kšœ>˜>Kšœ2žœžœ˜IKšœ ˜ Kšžœ4˜9Kšœ˜—K˜š  œžœžœžœ žœžœ˜šžœ#žœž˜2Kšœžœžœ˜)Kšžœžœ˜-—Kšœ˜—K˜š   œžœžœžœ žœžœ˜AKšœžœ4˜=Kšœ%˜%Kšœ˜K˜—š   œžœžœžœžœ˜Cšžœ(žœž˜7Kšœžœžœ˜)Kšžœžœ˜-—Kšœ˜—K˜Kšœ8™8K™š   œžœ žœžœžœ˜DKšœ3™3Kšœ™Kšœžœ˜ šžœžœžœžœ˜FKšœ1˜1Kšœ ˜ Kšžœ žœžœžœ ˜EK˜—Kšžœžœ˜ Kšœ˜—K˜š  œžœžœžœ žœ˜@šžœžœžœ˜šžœžœž˜šœžœ˜Kšœžœ ˜Kšžœ žœžœ!˜5Kšœ?˜?K˜—Kšœžœ žœ˜šžœžœžœžœ˜Kšœ4˜4K˜——Kšžœžœžœ,˜Kšœžœ˜$Kšžœžœ˜—Kšœ˜—K™š  œž œ žœžœ˜9šœ˜Kšœžœ˜;Kšœ ˜ K˜—K˜—K™Kšœ8™8K˜š œžœžœ žœ žœ žœžœžœžœžœžœžœžœ˜ΎKšœ žœžœ˜,Kšœe˜eKšœv˜všžœ žœžœ˜Kšœ žœ#˜3šžœž˜!Kšœu˜u—K˜—Kšœ˜—K™Kšœ4™4K˜š œžœžœ žœ žœžœ žœžœžœžœžœžœ˜K˜š   œžœ žœžœžœžœ˜BKšœA™AKšœžœ˜Kšœžœ˜šžœ ž˜šžœ!ž˜+Kšœžœ˜Kšœžœ˜Kšžœ˜—Kšžœ˜—Kšžœ˜ K˜K˜—Kšœžœ˜#Kšœ™Kšœžœ&˜2Kšœ™Kšžœžœ˜9Kšœ™šžœžœ'žœ˜BKšœžœ˜"Kšžœžœ˜8Kšžœ%˜)K˜—Kšœ™šžœžœžœ˜šžœžœžœžœ˜DKšœ žœ˜+Kšžœžœ5˜OK˜—K˜—Kšœ™šžœžœ˜ Kšœ+˜+K˜—Kšžœ˜ Kšœ˜—K™š œž œ žœ žœžœžœžœžœ žœ˜eKš œ žœžœžœžœ˜Cš  œžœ žœ˜"šžœžœ"ž˜=Kšœ žœ˜!—Kšœ˜—Kšœžœ˜$šžœžœž˜Kšœžœžœžœ˜)Kšœžœžœ˜%Kšœžœžœ˜6šœžœ ˜Kšœ-˜-Kšœ"˜"Kšœ˜—šœžœ˜Kšœ"˜"Kšœ˜—Kšžœžœ˜—Kšœ/˜/Kšžœžœžœ˜QKšœXžœžœ$˜•Kšœ˜—K™KšœŸœ"™+K˜š   œž œ žœžœžœžœ˜GKšœžœ˜Kšœžœ˜šžœ ž˜šžœž˜#Kšœžœžœ˜'Kšžœžœ˜—Kšžœ˜—šžœ ž˜šžœž˜$Kšœžœžœ˜%Kšžœžœ˜—Kšžœ˜—Kšžœ žœžœ(˜AK˜—K˜š  œžœžœ žœžœžœžœ˜OKšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ™šžœž˜šžœž˜&Kšœžœžœ˜-Kšžœžœ˜—Kšžœ˜—Kšœ™Kšœ˜šžœž˜šžœž˜%Kšœžœ žœžœ˜ Kšžœ˜—Kšžœ˜—Kšžœžœ5˜MKšœ˜Kšœ™šžœž˜šžœž˜%Kšœžœžœ˜+Kšžœ6žœ˜D—Kšžœ˜—Kšœ˜—K˜š‘ œžœžœžœ žœžœžœžœ˜bKšœ/™/Kšœ8™8Kšœžœžœžœ˜.Kšœžœžœ žœ ˜9šž˜Kš œžœΟrΠkr’ œžœ ˜<šžœžœ˜Kšœ!˜!Kšžœžœžœ˜,K˜—Kšžœ˜—Kšžœ žœ˜Kšœ˜—K˜K˜š" œžœžœ žœ žœžœžœžœžœžœžœžœžœžœžœ žœžœ˜·K˜š  œžœžœžœžœžœ žœžœ˜NKšœ žœžœ˜š žœžœžœžœžœžœž˜4šžœžœžœžœ˜FKšœ˜Kšœžœ ˜Kšœ˜—Kšžœ˜—Kšžœ˜Kšœ˜—K˜KšœQžœŸ ˜bKšœ žœŸ2˜Bšœžœ˜7Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœb˜bKšœ˜—K˜š œžœ˜KšœG˜GK˜—K˜Kšžœžœ0˜Gšžœ˜Kšœ/˜/šœ˜Kšžœ*žœžœžœ˜Ršœ žœ˜Kšžœžœžœ˜šž˜šžœ˜Kšœ˜Kšœžœ&˜2Kšœ*˜*Kšœ žœC˜RKšœ Ÿ ˜Kšœž˜Kšœžœ˜Kšœqžœ˜yKšœžœ˜ Kšžœžœ˜——K˜—Kšœ˜—Kšœ'˜'Kšœ˜—Kšœ˜—K™š  œžœžœ žœžœ žœžœžœžœžœžœžœ˜šKšœD™DKšœO™OKšœP™PKšœX™XKšœ-™-Kšœ>™>KšœG™GKšœJ™JKšœS™SKšœ žœŸ˜*Kšœ žœŸ9˜KK˜š œžœ žœ˜ Kšœ™Kšœ5™5Kšœ-™-Kšœ™Kšžœ žœžœ$˜8Kšœ6˜6Kšœ˜K˜—K˜Kš œ žœžœžœžœžœ!˜]šžœ žœžœ˜Kšœ'˜'Kšœ žœ˜$Kšœ˜K˜—šžœžœžœ˜Kšœžœ˜ Kšœ ˜ Kšœ˜—Kšžœžœžœ>˜OKšžœO˜SKšœ˜—K™š œžœžœžœ žœžœžœ žœ˜^K™0šžœžœžœ˜Kšœžœ˜Kšžœžœžœ˜+K˜—šžœžœžœ˜Kšžœžœžœ˜,šžœžœžœ˜Kšœžœ5žœ˜PKšžœžœ˜5šžœCžœ˜KKšœ9˜9Kš œžœžœžœžœ˜*Kšžœžœžœ˜*Kšžœžœžœ˜,K˜—Kšžœžœžœ=˜MK˜—K˜—K˜—K™š  œ˜(Kšœžœ˜Kšœ žœ˜ Kšžœžœžœ˜ KšœP˜Pšžœ.žœžœ˜;Kšžœ˜—Kšœ=˜=K˜—K™š   œžœžœžœžœžœ˜Nš   œžœ žœžœžœ žœ˜Fš‘œžœ˜+šžœžœ˜&Kšžœ+žœ˜4Kšžœ žœ˜%—K˜—Kšžœžœžœ˜"Kšœžœ'˜.K˜—šžœžœž˜Kšœžœžœ˜%Kšœžœ žœ˜&Kšœžœžœ˜/Kšžœžœ˜—Kšžœ žœžœžœ"˜?K˜—K™Kšœ.™.K˜š  œžœžœžœžœ˜1šžœžœž˜Kšœžœ˜"Kšžœžœ˜—Kšžœ˜!Kšœ˜—K˜š œ˜2šžœžœž˜šœžœ˜Kšœžœ˜Kšœ˜—Kšžœž˜—Kšœ˜—K˜š‘œ˜/KšžœžœžœB˜TKšœ˜—K˜Kšœe˜eKšœžœ˜)Kšœ#žœ˜-Kšœžœ˜%Kšœ'žœ˜1Kšœžœ˜#Kšœ žœ˜(Kšœžœžœ˜K˜FK˜LKšœ˜KšœO˜Ošœ’˜’Kšœžœ žœžœ˜2Kšœ˜Kšœžœ˜Kšœ"˜"Kšœ ˜ K˜—Kšžœ˜K˜K˜K˜—…—=β[c