DIRECTORY CDProperties, CDPropertyTools, CD, CDPrivate, Atom, Commander, CommandTool, HashTable, List, PropertyLists, Rope, RopeList, RuntimeError USING [UNCAUGHT], TokenIO, UserProfile USING [Boolean], ViewerTools USING [TiogaContents, TiogaContentsRec]; CDPropertiesImpl: CEDAR MONITOR IMPORTS CD, CDPrivate, CDProperties, Atom, Commander, CommandTool, HashTable, List, PropertyLists, Rope, RopeList, RuntimeError, TokenIO, UserProfile EXPORTS CDProperties, CDPropertyTools = BEGIN PropList: TYPE = CD.PropList; PropertyProcs: TYPE = CDProperties.PropertyProcs; PropertyProcsRec: TYPE = CDProperties.PropertyProcsRec; atomTab: HashTable.Table = HashTable.Create[33]; -- contains atoms [maybe in future ref's] where properties hang propertyNameTab: HashTable.Table = HashTable.Create[33]; -- key: propertynames; value: PropertyProcs registrationTab: HashTable.Table = HashTable.Create[33]; -- contains registrationKeys RegisterProperty: PUBLIC ENTRY PROC [prop: REF, registrationKey: REF_NIL] RETURNS [first: BOOL_TRUE] = BEGIN val: HashTable.Value; found: BOOL; [found, val] _ HashTable.Fetch[registrationTab, prop]; -- returns a registration key IF found THEN { IF registrationKey#NIL AND registrationKey=val THEN RETURN [FALSE]; RETURN WITH ERROR CD.Error[doubleRegistration] } ELSE { pp: PropertyProcs _ NEW[PropertyProcsRec]; pp.key _ prop; [] _ HashTable.Insert[propertyNameTab, prop, pp]; -- procs [] _ HashTable.Insert[registrationTab, prop, registrationKey]; -- registration }; END; Err: ERROR = CODE; PutProp: PUBLIC PROC [onto: REF, prop: REF, val: REF] = BEGIN WITH onto SELECT FROM a: CD.Instance => PutInstanceProp[a, prop, val]; o: CD.Object => PutObjectProp[o, prop, val]; pr: CD.PropRef => PutPRefProp[pr, prop, val]; d: CD.Design => PutDesignProp[d, prop, val]; t: CD.Technology => PutTechnologyProp[t, prop, val]; at: ATOM => PutAtomProp[at, prop, val]; class: CD.ObjectClass => PutObjectClassProp[class, prop, val]; pp: PropertyProcs => PutPropertyClassProp[pp, prop, val]; pl: PropertyLists.PropList => RETURN WITH ERROR Err; --explicitely forbidden ENDCASE => RETURN WITH ERROR Err END; GetProp: PUBLIC ENTRY PROC [from: REF, prop: REF] RETURNS [REF] = BEGIN ENABLE UNWIND => NULL; WITH from SELECT FROM a: CD.Instance => RETURN[PropertyLists.GetProp[a.properties, prop]]; o: CD.Object => RETURN[PropertyLists.GetProp[o.properties, prop]]; pr: CD.PropRef => RETURN[PropertyLists.GetProp[pr^, prop]]; pl: CD.PropList => RETURN[PropertyLists.GetProp[pl, prop]]; at: ATOM => RETURN[GetRefAnyPropf[at, prop]]; d: CD.Design => RETURN[PropertyLists.GetProp[d.properties^, prop]]; t: CD.Technology => RETURN[PropertyLists.GetProp[t.properties^, prop]]; class: CD.ObjectClass => RETURN[PropertyLists.GetProp[class.properties^, prop]]; pp: PropertyProcs => RETURN[PropertyLists.GetProp[pp.properties, prop]]; ENDCASE => RETURN WITH ERROR Err; END; GetListProp: PUBLIC ENTRY PROC [propList: PropList, prop: REF] RETURNS [REF] = { ENABLE UNWIND => NULL; RETURN [PropertyLists.GetProp[propList, prop]] }; PutPRefProp: PUBLIC ENTRY PROC [onto: CD.PropRef, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; IF onto=NIL THEN RETURN WITH ERROR CD.Error[other, "nil property field"]; onto^ _ PropertyLists.PutProp[onto^, prop, val] END; PutObjectProp: PUBLIC ENTRY PROC [onto: CD.Object, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; IF onto=NIL THEN RETURN WITH ERROR CD.Error[other, "NIL Object"]; onto.properties _ PropertyLists.PutProp[onto.properties, prop, val] END; PutInstanceProp: PUBLIC ENTRY PROC[onto: CD.Instance, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; IF onto=NIL THEN RETURN WITH ERROR CD.Error[other, "NIL Instance"]; onto.properties _ PropertyLists.PutProp[onto.properties, prop, val] END; PutDesignProp: PUBLIC ENTRY PROC [onto: CD.Design, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; IF onto=NIL OR onto.properties=NIL THEN RETURN WITH ERROR CD.Error[other, "NIL property field"]; onto.properties^ _ PropertyLists.PutProp[onto.properties^, prop, val] END; PutTechnologyProp: PUBLIC ENTRY PROC[onto: CD.Technology, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; IF onto=NIL OR onto.properties=NIL THEN RETURN WITH ERROR CD.Error[other, "nil property field"]; onto.properties^ _ PropertyLists.PutProp[onto.properties^, prop, val] END; PutObjectClassProp: ENTRY PROC[onto: CD.ObjectClass, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; IF onto=NIL OR onto.properties=NIL THEN RETURN WITH ERROR CD.Error[other, "nil property field"]; onto.properties^ _ PropertyLists.PutProp[onto.properties^, prop, val] END; PutAtomProp: PUBLIC PROC[onto: ATOM, prop: REF, val: REF] = { PutPropOnRef[onto: onto, prop: prop, val: val] }; PutLayerProp: PUBLIC ENTRY PROC[onto: CD.Layer, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; CDPrivate.layers[onto].properties^ _ PropertyLists.PutProp[CDPrivate.layers[onto].properties^, prop, val] END; PutPropertyClassProp: ENTRY PROC[onto: PropertyProcs, prop: REF, val: REF] = BEGIN ENABLE UNWIND => NULL; IF onto=NIL OR onto.properties=NIL THEN RETURN WITH ERROR CD.Error[other, "nil PropertyProcs"]; onto.properties _ PropertyLists.PutProp[onto.properties, prop, val] END; PutPropOnRef: ENTRY PROC[onto: REF, prop: REF, val: REF] = BEGIN x: REF; found: BOOL; pp: REF CD.PropList; [found, x] _ HashTable.Fetch[atomTab, onto]; IF found THEN pp _ NARROW[x, REF CD.PropList] ELSE { IF prop=NIL THEN RETURN; pp _ NEW[CD.PropList_NIL]; [] _ HashTable.Store[atomTab, onto, pp]; }; pp^ _ PropertyLists.PutProp[pp^, prop, val]; IF pp^=NIL THEN [] _ HashTable.Delete[atomTab, onto]; END; GetRefAnyPropf: PROC [from: REF, prop: REF] RETURNS [REF] = INLINE BEGIN x: REF; found: BOOL; pp: REF CD.PropList; [found, x] _ HashTable.Fetch[atomTab, from]; IF NOT found THEN RETURN[NIL]; pp _ NARROW[x, REF CD.PropList]; RETURN [PropertyLists.GetProp[pp^, prop]] END; GetObjectProp: PUBLIC PROC [from: CD.Object, prop: REF] RETURNS [REF] = BEGIN ENABLE UNWIND => NULL; RETURN[PropertyLists.GetProp[from.properties, prop]] END; GetInstanceProp: PUBLIC PROC [from: CD.Instance, prop: REF] RETURNS [REF] = BEGIN ENABLE UNWIND => NULL; RETURN[PropertyLists.GetProp[from.properties, prop]] END; GetDesignProp: PUBLIC PROC [from: CD.Design, prop: REF] RETURNS [REF] = BEGIN ENABLE UNWIND => NULL; RETURN[PropertyLists.GetProp[from.properties^, prop]] END; GetTechnologyProp: PUBLIC PROC [from: CD.Technology, prop: REF] RETURNS [REF] = BEGIN ENABLE UNWIND => NULL; RETURN[PropertyLists.GetProp[from.properties^, prop]] END; GetLayerProp: PUBLIC PROC [from: CD.Layer, prop: REF] RETURNS [REF] = BEGIN ENABLE UNWIND => NULL; RETURN[PropertyLists.GetProp[CDPrivate.layers[from].properties^, prop]] END; GetAtomProp: PUBLIC ENTRY PROC [from: ATOM, prop: REF] RETURNS [REF] = BEGIN ENABLE UNWIND => NULL; RETURN[GetRefAnyPropf[from: from, prop: prop]]; END; RegisterAndInstall: PUBLIC PROC [prop: REF, new: PropertyProcsRec, registrationKey: REF] RETURNS [first: BOOL] = BEGIN first _ RegisterProperty[prop, registrationKey]; InstallProcs[prop, new]; END; InstallProcs: PUBLIC ENTRY PROC [prop: REF, new: PropertyProcsRec] = BEGIN ENABLE UNWIND => NULL; pp: PropertyProcs; IF (pp _ FetchProcs[prop])#NIL THEN { IF new.exclusive THEN pp.exclusive_TRUE; IF new.autoRem THEN pp.autoRem_TRUE; IF new.reserved THEN pp.reserved_TRUE; IF new.makeCopy#NIL THEN pp.makeCopy _ new.makeCopy; IF new.internalWrite#NIL THEN pp.internalWrite _ new.internalWrite; IF new.internalRead#NIL THEN pp.internalRead _ new.internalRead; IF new.properties#NIL THEN FOR l: PropList _ new.properties, l.rest WHILE l#NIL DO pp.properties _ PropertyLists.PutProp[pp.properties, l.first.key, l.first.val]; ENDLOOP; } END; FetchProcs: PUBLIC PROC [prop: REF] RETURNS [pp: PropertyProcs] = BEGIN pp _ NARROW[HashTable.Fetch[propertyNameTab, prop].value]; END; CopyVal: PUBLIC PROC [prop: REF, val: REF, purpose: REF] RETURNS [valCopy: REF] = BEGIN valCopy _ val; END; DontCopy: PUBLIC PROC [prop: REF, val: REF, purpose: REF] RETURNS [nil: REF_NIL] = BEGIN END; PutOn: PROC [putOnto: REF, propList: PropList] = BEGIN WITH putOnto SELECT FROM a: CD.Instance => a.properties _ propList; o: CD.Object => o.properties _ propList; pr: CD.PropRef => pr^ _ propList; d: CD.Design => d.properties^ _ propList; t: CD.Technology => t.properties^ _ propList; class: REF CD.ObjectClass => class.properties^ _ propList; pp: PropertyProcs => pp.properties _ propList; at: ATOM => ERROR; ENDCASE => ERROR Err END; CopyProps: PUBLIC ENTRY PROC [propList: PropList, putOnto: REF, purpose: REF_NIL] = BEGIN ENABLE UNWIND => NULL; PutOn[putOnto, InternalDangerousCopyProps[propList, purpose] ! RuntimeError.UNCAUGHT => GOTO crashed]; EXITS crashed => RETURN WITH ERROR Err END; AppendProps: PUBLIC ENTRY PROC [winner, looser: PropList_NIL, putOnto: REF, purpose: REF_NIL] = BEGIN ENABLE UNWIND => NULL; PutOn[putOnto, InternalDangerousAppendProps[winner, looser, purpose] ! RuntimeError.UNCAUGHT => GOTO crashed] EXITS crashed => RETURN WITH ERROR Err END; DCopyProps: PUBLIC ENTRY PROC [propList: PropList, purpose: REF] RETURNS [copy: PropList_NIL] = BEGIN ENABLE UNWIND => NULL; copy _ InternalDangerousCopyProps[propList, purpose] END; DAppendProps: PUBLIC ENTRY PROC [winner, looser: CDProperties.PropList, purpose: REF] RETURNS [copy: CDProperties.PropList] = BEGIN ENABLE UNWIND => NULL; copy _ InternalDangerousAppendProps[winner, looser, purpose] END; InternalDangerousCopyProps: PROC [propList: PropList, purpose: REF] RETURNS [copy: PropList_NIL] = BEGIN FOR l: PropList _ propList, l.rest WHILE l#NIL DO copy _ InternalCopyItem[copy, l.first, purpose] ENDLOOP; END; InternalDangerousAppendProps: PROC [winner, looser: CDProperties.PropList, purpose: REF] RETURNS [copy: CDProperties.PropList] = BEGIN copy _ InternalDangerousCopyProps[looser, purpose]; FOR l: PropList _ winner, l.rest WHILE l#NIL DO copy _ InternalCopyItem[copy, l.first, purpose] ENDLOOP; END; InternalCopyItem: PROC[list: CDProperties.PropList, item: PropertyLists.KeyVal, purpose: REF] RETURNS [newList: CDProperties.PropList] = BEGIN class: CDProperties.PropertyProcs = FetchProcs[item.key]; IF class#NIL AND class.makeCopy#NIL THEN { newVal: REF = class.makeCopy[prop: item.key, val: item.val, purpose: purpose]; IF newVal=NIL THEN newList _ list ELSE newList _ PropertyLists.PutProp[list, item.key, newVal]; } ELSE IF ISTYPE[item.key, ATOM] AND item.val#NIL THEN WITH item.val SELECT FROM r: Rope.ROPE => newList _ PropertyLists.PutProp[list, item.key, r]; at: ATOM => newList _ PropertyLists.PutProp[list, item.key, at]; ri: REF INT => newList _ PropertyLists.PutProp[list, item.key, NEW[INT_ri^]]; pl: CD.PropList => newList _ PropertyLists.PutProp[list, item.key, InternalDangerousCopyProps[pl, purpose]]; rl: LIST OF Rope.ROPE => newList _ PropertyLists.PutProp[list, item.key, RopeList.CopyTopList[rl]]; ENDCASE => newList _ list ELSE newList _ list; END; DoWithinLock: PUBLIC ENTRY PROC [p: PROC] = BEGIN ENABLE { UNWIND => NULL; RuntimeError.UNCAUGHT => IF UserProfile.Boolean["ChipNDale.CatchLowLevelErrors", TRUE] THEN CONTINUE; }; IF p#NIL THEN p[]; END; RopePWrite: PUBLIC PROC [prop: REF, val: REF] = BEGIN WITH val SELECT FROM r: Rope.ROPE => TokenIO.WriteRope[r]; at: ATOM => TokenIO.WriteRope[Atom.GetPName[at]]; ENDCASE => TokenIO.WriteRope["bad property value"]; END; AtomPWrite: PUBLIC PROC [prop: REF, val: REF] = BEGIN WITH val SELECT FROM at: ATOM => TokenIO.WriteAtom[at]; r: Rope.ROPE => TokenIO.WriteAtom[Atom.MakeAtom[r]]; ENDCASE => TokenIO.WriteAtom[$Bad]; END; IntPWrite: PUBLIC PROC [prop: REF, val: REF] = BEGIN WITH val SELECT FROM ri: REF INT => TokenIO.WriteInt[ri^]; rc: REF CARDINAL => TokenIO.WriteInt[rc^]; rn: REF NAT => TokenIO.WriteInt[rn^]; ENDCASE => TokenIO.WriteInt[0]; END; SomePWrite: PUBLIC PROC [prop: REF, val: REF] = BEGIN WITH val SELECT FROM at: ATOM => TokenIO.WriteAtom[at]; r: Rope.ROPE => TokenIO.WriteRope[r]; ri: REF INT => TokenIO.WriteInt[ri^]; rc: REF CARDINAL => TokenIO.WriteInt[rc^]; rn: REF NAT => TokenIO.WriteInt[rn^]; ENDCASE => TokenIO.WriteAtom[$Unknown]; END; RopePRead: PUBLIC PROC [prop: ATOM] RETURNS [val: REF] = BEGIN val _ TokenIO.ReadRope[] END; AtomPRead: PUBLIC PROC [prop: ATOM] RETURNS [val: REF] = BEGIN val _ TokenIO.ReadAtom[] END; IntPRead: PUBLIC PROC [prop: ATOM] RETURNS [val: REF] = BEGIN val _ NEW[INT_TokenIO.ReadInt[]] END; SomePRead: PUBLIC PROC [prop: ATOM] RETURNS [val: REF] = BEGIN t: TokenIO.Token _ TokenIO.ReadToken[]; SELECT t.kind FROM atom, int, rope => val _ t.ref; ENDCASE => val _ $Error; END; TiogaPCopy: PROC [prop: REF, val: REF, purpose: REF] RETURNS [copy: REF] = BEGIN contents: Rope.ROPE _ NIL; formatting: Rope.ROPE _ NIL; WITH val SELECT FROM t: ViewerTools.TiogaContents => { contents _ t.contents; formatting _ t.formatting}; r: Rope.ROPE => contents _ r; ENDCASE => contents _ "$Error"; copy _ NEW[ViewerTools.TiogaContentsRec_[contents: contents, formatting: formatting]] END; TiogaPWrite: PROC [prop: REF, val: REF] = BEGIN contents, formatting: Rope.ROPE _ NIL; WITH val SELECT FROM t: ViewerTools.TiogaContents => { contents _ t.contents; formatting _ t.formatting}; r: Rope.ROPE => contents _ r; ENDCASE => NULL; TokenIO.WriteRope[contents]; TokenIO.WriteRope[formatting]; END; TiogaPRead: PROC [prop: ATOM] RETURNS [val: REF] = BEGIN contents: Rope.ROPE _ TokenIO.ReadRope[]; formatting: Rope.ROPE _ TokenIO.ReadRope[]; val _ NEW[ViewerTools.TiogaContentsRec_[contents: contents, formatting: formatting]] END; Atomize: PROC [r: Rope.ROPE] RETURNS [ATOM_NIL] = { IF Rope.Length[r]>1 AND Rope.Fetch[r]='$ THEN r _ Rope.Substr[r, 1, Rope.Length[r]-1]; IF ~Rope.IsEmpty[r] THEN RETURN [Atom.MakeAtom[r]] }; IsExclusive: PROC [a: ATOM] RETURNS [BOOL_TRUE] = BEGIN IF a#NIL THEN { pType: CDProperties.PropertyProcs = CDProperties.FetchProcs[a]; RETURN [pType#NIL AND pType.exclusive] } END; RemovePropFromRegistrations: PROC [atom: ATOM] = BEGIN RemProps: PROC [atom: ATOM, lora: LIST OF REF ANY] = { FOR l: LIST OF REF ANY _ lora, l.rest WHILE l#NIL DO WITH l.first SELECT FROM a: ATOM => { IF ~IsExclusive[a] THEN PutAtomProp[onto: atom, prop: a, val: NIL]; PutAtomProp[onto: a, prop: atom, val: NIL]; } ENDCASE => NULL; ENDLOOP; }; IF atom=$RegistrationRoot THEN ERROR; --don't do this WITH GetProp[$RegistrationRoot, atom] SELECT FROM loa: LIST OF ATOM => TRUSTED {RemProps[atom, LOOPHOLE[loa]]}; lora: LIST OF REF ANY => RemProps[atom, lora]; a: ATOM => RemProps[atom, LIST[a]] ENDCASE => NULL; END; RemovePropFromLayers: PROC [atom: ATOM] = BEGIN FOR l: CD.Layer IN CD.Layer DO reg: ATOM _ CD.LayerKey[l]; IF reg#NIL THEN { PutAtomProp[onto: atom, prop: reg, val: NIL]; PutAtomProp[onto: reg, prop: atom, val: NIL]; }; PutLayerProp[onto: l, prop: atom, val: NIL]; ENDLOOP; END; RemoveProperties: PUBLIC PROC[key: ATOM] = BEGIN IF ~IsExclusive[key] THEN { PutAtomProp[onto: key, prop: key, val: NIL]; RemovePropFromRegistrations[key]; RemovePropFromLayers[key]; }; END; RemovePropCommand: Commander.CommandProc = BEGIN FOR rl: LIST OF Rope.ROPE _ CommandTool.ParseToList[cmd].list, rl.rest WHILE rl#NIL DO atom: ATOM _ Atomize[rl.first]; --this atoms registrations should be removed IF IsExclusive[atom] THEN msg _ Rope.Cat[msg, " ", rl.first, " not removed (no or exclusive atom)\n"] ELSE RemoveProperties[atom]; ENDLOOP; END; Associate: PUBLIC PROC [key, a: ATOM] = TRUSTED BEGIN IF ~IsExclusive[a] AND ~IsExclusive[key] THEN { list: LIST OF REF ANY _ WITH GetAtomProp[$RegistrationRoot, key] SELECT FROM lora: LIST OF REF ANY => lora, loa: LIST OF ATOM => LOOPHOLE[loa], a: ATOM => LIST[a], ENDCASE => NIL; IF ~List.Memb[a, list] THEN { n: LIST OF REF ANY _ List.Nconc1[list, a]; IF n#list THEN PutAtomProp[onto: $RegistrationRoot, prop: key, val: n]; }; }; END; AssociatePropCommand: Commander.CommandProc = BEGIN key: ATOM _ NIL; rl: LIST OF Rope.ROPE _ CommandTool.ParseToList[cmd].list; IF rl=NIL OR IsExclusive[key_Atomize[rl.first]] THEN { msg _ "no or exclusive key\n"; result _ $Failure; RETURN }; IF rl.rest=NIL THEN { msg _ "no properties to associate with key\n"; result _ $Failure; RETURN }; FOR l: LIST OF Rope.ROPE _ rl.rest, l.rest WHILE l#NIL DO a: ATOM _ Atomize[l.first]; IF IsExclusive[a] THEN msg _ Rope.Cat[msg, l.first, " not allowed\n"] ELSE Associate[key, a]; ENDLOOP END; [] _ RegisterProperty[$RegistrationRoot]; InstallProcs[$RegistrationRoot, CDProperties.PropertyProcsRec[exclusive: TRUE]]; Commander.Register[ key: "///ChipNDale/CDRemoveRegistration", --used by ChipNDale command files only proc: RemovePropCommand, doc: "removes properties from all ChipNDale layers" ]; Commander.Register[ key: "///ChipNDale/CDAssociateRegistration", --used by ChipNDale command files only proc: AssociatePropCommand, doc: "associate ChipNDale properties for removal" ]; [] _ CDProperties.RegisterProperty[$SignalName]; [] _ CDProperties.RegisterProperty[$InstanceName]; [] _ CDProperties.RegisterProperty[$Tioga]; CDProperties.InstallProcs[prop: $SignalName, new: CDProperties.PropertyProcsRec[ makeCopy: CDProperties.CopyVal, internalWrite: CDProperties.RopePWrite, internalRead: CDProperties.RopePRead ]]; CDProperties.InstallProcs[prop: $InstanceName, new: CDProperties.PropertyProcsRec[ makeCopy: CDProperties.CopyVal, internalWrite: CDProperties.RopePWrite, internalRead: CDProperties.RopePRead ]]; CDProperties.InstallProcs[prop: $Tioga, new: CDProperties.PropertyProcsRec[ makeCopy: TiogaPCopy, internalWrite: TiogaPWrite, internalRead: TiogaPRead ]]; END. ώCDPropertiesImpl.mesa a ChipNDale module Copyright c 1983, 1986 by Xerox Corporation. All rights reserved. by Ch. Jacobi, September 27, 1983 2:06 pm last edited Christian Jacobi, March 25, 1986 2:32:23 pm PST --Registration --Usage --speed ups --a NIL val removes the property --here onto MUST NOT be a ChipNDale ref pointing to a record with properties, --since then the properties must be used, not the hash table --NIL if prop is not found --here from MUST NOT be a ChipNDale ref pointing to a record with properties, --since then the properties must be used, not the hash table --property procedures --dangerous procedure; might crash -------------------------- --now some special properties --removes from this atom all properties hanging on $RegistrationRoot --removes this atom's property from all atoms hanging on $RegistrationRoot --removes atom-property from all layers, all layer's registrationkeys, --and the layers registrationkeys-properties from atom --not entry! --Allows to do un-registration from commandfiles which may run --before the tool they are un-registrating --This command is handy for lots of tools which set op their parameters with atom command file --not entry! --module initialization --does not really belong into this module Κ%˜codešœ*™*Kšœ Οmœ7™BKšœ*™*Kšœ<™Kšœ:˜:Kšœžœ ˜LKšžœžœ˜ —Kšžœ˜K˜—š‘œžœž œžœžœžœžœ˜AKšž˜Kšžœžœžœ˜šžœžœž˜Kšœžœ žœ,˜DKšœžœ žœ,˜BKšœžœ#˜;Kšœžœ"˜;Kšœžœžœ˜-Kšœžœ žœ-˜CKšœžœžœ-˜GKšœžœžœ1˜PKšœžœ-˜HKšžœžœ˜!—Kšžœ˜—K˜š ‘ œž œžœžœžœžœ˜PKšžœžœžœ˜Jšžœ(˜.Jšœ˜K˜—Kšœ ™ K˜š‘ œžœžœžœžœžœžœ˜HKšž˜Kšžœžœžœ˜Kšžœžœžœžœžœžœžœ$˜IKšœ/˜/Kšžœ˜K˜—š‘ œžœžœžœžœžœžœ˜IKšž˜Kšžœžœž˜Kšžœžœžœžœžœžœžœ˜AKšœC˜CKšžœ˜K˜—š‘œžœžœžœžœžœžœ˜LKšž˜Kšžœžœž˜Kšžœžœžœžœžœžœžœ˜CKšœC˜CKšžœ˜K˜—š‘ œžœžœžœžœžœžœ˜IKšž œžœž˜šžœžœžœžœ˜(Kšžœžœžœžœ$˜8—KšœE˜EKšžœ˜K˜—š‘œžœžœžœžœžœžœ˜PKšž œžœž˜šžœžœžœžœ˜(Kšžœžœžœžœ$˜8—KšœE˜EKšžœ˜K˜—š ‘œžœžœžœžœžœ˜KKšž œžœžœ˜š žœžœžœžœžœ˜(Kšžœžœžœžœ$˜8—KšœE˜EKšžœ˜K˜—š ‘ œžœžœžœžœžœ˜=Kšœ.˜.Kšœ˜K˜—š‘ œžœžœžœžœžœžœ˜FKšž œžœž˜Kšœi˜iKšžœ˜K˜—š ‘œžœžœžœžœ˜LKšž˜Kšžœžœžœ˜š žœžœžœžœžœ˜(Kšžœžœžœžœ#˜7—KšœC˜CKšžœ˜K˜—š ‘ œžœžœžœžœžœ˜:Kšœ ™ KšœM™MKšœ<™Jš œžœžœžœžœ˜/Jšœžœžœ˜"Jšžœžœ˜—Kšžœ˜—K˜š‘œžœžœ˜*JšœF™FJšœ6™6Jšž˜š žœžœžœžœž˜Jšœžœžœ ˜šžœžœžœ˜Jšœ(žœ˜-Jšœ(žœ˜-J˜—Jšœ'žœ˜,Jšžœ˜—Kšž˜—K˜š‘œžœžœžœ˜*Kšœ ™ Kšž˜šžœžœ˜Jšœ'žœ˜,Jšœ!˜!Kšœ˜J˜—Kšžœ˜—K˜š’œ˜+Kšœ>™>Kšœ+™+Kšœ_™_Kšž˜š žœžœžœžœ.žœžœž˜VJšœžœ ,˜Lšžœžœ˜KšœK˜K—Kšžœ˜Jšžœ˜—Kšžœ˜K˜—š‘ œž œ žœ˜(Kšœ ™ Kšž ˜ šžœžœžœ˜/šœžœžœžœžœžœ%žœž˜LKš œžœžœžœžœ ˜Kš œžœžœžœžœ˜#Kšœžœžœ˜Kšžœžœ˜—šžœžœ˜Kš œžœžœžœžœ˜*Kšžœžœ9˜GK˜—K˜—Kšžœ˜—K˜š’œ˜.Kšž˜Kšœžœžœ˜Kšœžœžœžœ%˜:šžœžœžœ$žœ˜6Kšœ˜Kšœ˜Kšž˜K˜—šžœ žœžœ˜Kšœ.˜.Kšœ˜Kšž˜K˜—š žœžœžœžœžœžœž˜9Kšœžœ˜Kšžœžœ/˜EKšžœ˜Kšž˜—Kšžœ˜K˜—K™K™K˜Kšœ)˜)KšœIžœ˜Pšœ˜Kšœ* &˜PKšœ˜Kšœ3˜3Kšœ˜—šœ˜Kšœ- &˜SKšœ˜Kšœ1˜1Kšœ˜—K˜K˜Kšœ)™)Kšœ0˜0Kšœ3˜3Kšœ,˜,šœ2˜2šœ˜Kšœ˜Kšœ'˜'Kšœ$˜$Kšœ˜——šœ4˜4šœ˜Kšœ˜Kšœ'˜'Kšœ$˜$Kšœ˜——šœ-˜-šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜——Kšžœ˜K˜K˜—…—Dfd‰