DIRECTORY Atom, Basics, BasicTime, PFS, PFSNames, RefTab, Rope; VersionMap2: CEDAR DEFINITIONS IMPORTS PFSNames = { ROPE: TYPE ~ Rope.ROPE; LOR: TYPE ~ LIST OF ROPE; Error: READONLY ERROR [error: PFS.ErrorDesc]; Name: TYPE ~ PFS.PATH--that is absolute--; NameList: TYPE ~ LIST OF Name; nullName: Name ~ NIL; NameMatch: PROC [x, p: Name] RETURNS [BOOL]; NameEqual: PROC [n1, n2: Name] RETURNS [BOOL] ~ INLINE {RETURN PFSNames.Equal[n1, n2]}; RtNameEqual: RefTab.EqualProc; RtNameHash: RefTab.HashProc; NameCompare: PROC [n1, n2: Name] RETURNS [Basics.Comparison]; NamePatternIsConstant: PROC [Name] RETURNS [BOOL]; Created: TYPE ~ PFS.UniqueID; nullCreated: Created ~ PFS.nullUniqueID; CreatedFromGMT: PROC [gmt: BasicTime.GMT] RETURNS [Created] ~ INLINE {RETURN [[egmt: [gmt, 0] ]]}; GMTFromCreated: PROC [c: Created] RETURNS [GMTPlus] ~ INLINE {RETURN [[c.egmt.gmt, c.egmt.usecs#0 OR c.host#[0, 0] ]]}; GMTPlus: TYPE ~ RECORD [gmt: BasicTime.GMT, other: BOOL]; CreatedMatch: PROC [x, p: Created] RETURNS [BOOL] ~ INLINE {RETURN [p=nullCreated OR x=p]}; CreatedCompare: PROC [c1, c2: Created] RETURNS [Basics.Comparison]; VersionStamp: TYPE ~ ARRAY [0 .. 1] OF CARD --= MobDefs.VersionStamp--; nullStamp: VersionStamp ~ [0, 0]; StampMatch: PROC [x, p: VersionStamp] RETURNS [BOOL] ~ INLINE {RETURN [p=nullStamp OR x=p]}; StampCompare: PROC [s1, s2: VersionStamp] RETURNS [Basics.Comparison]; nullTuple: VersionTuple ~ []; VersionTuple: TYPE ~ RECORD [ name: Name _ nullName, created: Created _ nullCreated, stamp: VersionStamp _ nullStamp]; TMatches: PROC [t, pattern: VersionTuple] RETURNS [BOOL]; TEqual: PROC [t1, t2: VersionTuple] RETURNS [BOOL]; TupleCompare: PROC [t1, t2: VersionTuple] RETURNS [Basics.Comparison]; ShortNameToPattern: PROC [ROPE] RETURNS [VersionTuple]; LastComponentToPattern: PROC [PFSNames.Component] RETURNS [VersionTuple]; PatternIsConstant: PROC [VersionTuple] RETURNS [BOOL]; Map: TYPE ~ RECORD [class: MapClass, data: REF ANY _ NIL]; nullMap: Map ~ [NIL]; MapList: TYPE ~ LIST OF Map; RefMap: TYPE ~ REF Map; Refify: PROC [map: Map] RETURNS [RefMap] ~ INLINE {RETURN [NEW[Map _ map]]}; DeRefify: PROC [arg: REF ANY] RETURNS [RefMap]; cantCode: READONLY ATOM; Functional: PROC [map: Map] RETURNS [BOOL] ~ INLINE {RETURN map.class.Functional[map]}; MMutability: PROC [map: Map] RETURNS [Mutability] ~ INLINE {RETURN map.class.MMutability[map]}; Mutability: TYPE ~ {constant, readonly, writable}; Has: PROC [map: Map, elt: VersionTuple] RETURNS [BOOL] ~ INLINE {RETURN map.class.Has[map, elt]}; Scan: PROC [map: Map, Consume: TupleConsumer, inOrder: BOOL, filters: MapList _ NIL] RETURNS [MaybeTuple] ~ INLINE {RETURN map.class.Scan[map, Consume, inOrder, PatternFactorMapList[filters]]}; TupleConsumer: TYPE ~ PROC [VersionTuple] RETURNS [BOOL]; MaybeTuple: TYPE ~ RECORD [found: BOOL, it: VersionTuple]; noMaybe: MaybeTuple ~ [FALSE, nullTuple]; AlwaysAccept: TupleConsumer; FactoredScan: PROC [map: Map, Consume: TupleConsumer, inOrder: BOOL, pfml: PatternFactoredMapList] RETURNS [MaybeTuple] ~ INLINE {RETURN map.class.Scan[map, Consume, inOrder, pfml]}; AllHave: PROC [maplist: MapList, t: VersionTuple] RETURNS [BOOL]; OneHas: PROC [maplist: MapList, t: VersionTuple] RETURNS [BOOL]; PfmlHas: PROC [pfml: PatternFactoredMapList, t: VersionTuple] RETURNS [BOOL]; CreateGenerator: PROC [map: Map, inOrder: BOOL, filters: MapList _ NIL] RETURNS [Generator] ~ INLINE {RETURN map.class.CreateGenerator[map, inOrder, PatternFactorMapList[filters]]}; FactoredCreateGenerator: PROC [map: Map, inOrder: BOOL, pfml: PatternFactoredMapList] RETURNS [Generator] ~ INLINE {RETURN map.class.CreateGenerator[map, inOrder, pfml]}; ScanMatches: PROC [map: Map, Consume: TupleConsumer, inOrder: BOOL, pattern: VersionTuple] RETURNS [MaybeTuple] ~ INLINE {RETURN map.class.Scan[map, Consume, inOrder, [pattern]]}; GenerateMatches: PROC [map: Map, inOrder: BOOL, pattern: VersionTuple] RETURNS [Generator] ~ INLINE {RETURN map.class.CreateGenerator[map, inOrder, [pattern]]}; TheElt: PROC [map: Map] RETURNS [VersionTuple]; AnElt: PROC [map: Map] RETURNS [MaybeTuple]; LookupStamp: PROC [map: Map, stamp: VersionStamp] RETURNS [MaybeTuple]; LookupCreated: PROC [map: Map, created: Created] RETURNS [MaybeTuple]; LookupShortName: PROC [map: Map, shortName: ROPE] RETURNS [MaybeTuple]; Size: PROC [map: Map, limit: INT _ INT.LAST] RETURNS [INT] ~ INLINE {RETURN map.class.Size[map, limit]}; Empty: PROC [map: Map] RETURNS [BOOL] ~ INLINE {RETURN [Size[map, 1]=0]}; AddTuple: PROC [map: Map, t: VersionTuple, if: IfHads _ always] RETURNS [had: Hads] ~ INLINE {RETURN map.class.AddTuple[map, t, if]}; OldCase: TYPE ~ {same, createdDifferent, stampDifferent, bothDifferent, new}; InterestingOldCase: TYPE ~ OldCase[createdDifferent .. new]; IfHads: TYPE ~ PACKED ARRAY InterestingOldCase OF --add:--BOOL; always: IfHads ~ ALL[TRUE]; ifDifferent: IfHads ~ [TRUE, TRUE, TRUE, FALSE]; ifNew: IfHads ~ [FALSE, FALSE, FALSE, TRUE]; Hads: TYPE ~ PACKED ARRAY DependentField OF Had; DependentField: TYPE ~ {created, stamp}; Had: TYPE ~ {same, different, none}; AddMap: PROC [map, other: Map, if: IfHads _ always] RETURNS [some: HadSets] ~ INLINE {RETURN map.class.AddMap[map, other, if]}; HadSet: TYPE ~ PACKED ARRAY Had OF BOOL; HadSets: TYPE ~ ARRAY DependentField OF HadSet _ ALL[ALL[FALSE]]; RemTuple: PROC [map: Map, t: VersionTuple] RETURNS [had: Hads] ~ INLINE {RETURN map.class.RemTuple[map, t]}; RemMap: PROC [map, other: Map] RETURNS [some: HadSets] ~ INLINE {RETURN map.class.RemMap[map, other]}; RemFilters: PROC [map: Map, filters: MapList]; Negate: PROC [map: Map] RETURNS [Map] ~ INLINE {RETURN map.class.Negate[map]}; IsNegation: PROC [map: Map] RETURNS [MaybeMap] ~ INLINE {RETURN map.class.IsNegation[map]}; MaybeMap: TYPE ~ RECORD [found: BOOL, it: Map]; Intersect: PROC [map, other: Map] RETURNS [Map] ~ INLINE {RETURN map.class.Intersect[map, other]}; IsIntersection: PROC [map: Map] RETURNS [Maybe2Maps] ~ INLINE {RETURN map.class.IsIntersection[map]}; Maybe2Maps: TYPE ~ RECORD [found: BOOL, map, other: Map]; Union: PROC [map, other: Map, test: UnionTest _ other, ordered: BOOL _ FALSE] RETURNS [Map] ~ INLINE {RETURN map.class.Union[map, other, test, ordered]}; UnionTest: TYPE ~ {disjoint, map, other}; IsUnion: PROC [map: Map] RETURNS [Maybe2Maps] ~ INLINE {RETURN map.class.IsUnion[map]}; Difference: PROC [map, other: Map] RETURNS [Map] ~ INLINE {RETURN map.class.Difference[map, other]}; IsDifference: PROC [map: Map] RETURNS [Maybe2Maps] ~ INLINE {RETURN map.class.IsDifference[map]}; SymmetricDifference: PROC [map, other: Map] RETURNS [Map] ~ INLINE {RETURN map.class.SymmetricDifference[map, other]}; IsSymmetricDifference: PROC [map: Map] RETURNS [Maybe2Maps] ~ INLINE {RETURN map.class.IsSymmetricDifference[map]}; anEmpty: READONLY Map; aFull: READONLY Map; CreateSingleton: PROC [VersionTuple] RETURNS [Map]; MapIsSingleton: PROC [Map] RETURNS [MaybeTuple]; CreateVariableMap: PROC RETURNS [Map]; MapFromFile: PROC [fileName: Name, created: Created, assumeImmutable: BOOL] RETURNS [Map]; MapIsFromFile: PROC [Map] RETURNS [MaybeFromFile]; MaybeFromFile: TYPE ~ RECORD [found: BOOL, fileName: Name, created: Created, assumeImmutable: BOOL]; StoreToFile: PROC [map: Map, fileName: Name]; CreateDirectoriesMap: PROC [dirs: Map, cache, hints: Map _ nullMap] RETURNS [Map]; CreateMatcher: PROC [pattern: VersionTuple] RETURNS [Map]; PatternFactoredMap: TYPE ~ RECORD [ pattern: VersionTuple, stampInd, general: Map ]; PatternFactorMap: PROC [map: Map] RETURNS [PatternFactoredMap] ~ INLINE {RETURN map.class.PatternFactorMap[map]}; PatternFactoredMapList: TYPE ~ RECORD [ pattern: VersionTuple _ nullTuple, stampInd, general: MapList _ NIL ]; listOfEmpty: READONLY MapList; --LIST[anEmpty] PatternFactorMapList: PROC [MapList] RETURNS [PatternFactoredMapList]; PatternUnfactorMapList: PROC [PatternFactoredMapList] RETURNS [MapList]; PfmlAddMap: PROC [PatternFactoredMapList, Map] RETURNS [PatternFactoredMapList]; CreateSetMatcher: PROC [prefix: VersionTuple, suffixes: LOR] RETURNS [Map]; Generator: TYPE ~ REF GeneratorRep; GeneratorRep: TYPE ~ RECORD [ Next: PROC [Generator] RETURNS [VersionTuple], Close: PROC [Generator], data: REF ANY _ NIL]; GeneratorUnion: PROC [g1, g2: Generator, sort: BOOL] RETURNS [Generator]; GeneratorSort: PROC [Generator] RETURNS [Generator]; FilterGenerator: PROC [Generator, MapList] RETURNS [Generator]; TheGeneratee: PROC [gen: Generator] RETURNS [VersionTuple]; GeneratorQuaTuple: PROC [gen: Generator] RETURNS [MaybeTuple]; MapClass: TYPE ~ REF MapClassRep; MapClassRep: TYPE ~ RECORD [ Functional: PROC [map: Map] RETURNS [BOOL], MMutability: PROC [map: Map] RETURNS [Mutability], Has: PROC [map: Map, elt: VersionTuple] RETURNS [BOOL] _ NIL, Scan: PROC [map: Map, Consume: TupleConsumer, inOrder: BOOL, pfml: PatternFactoredMapList] RETURNS [MaybeTuple] _ NIL, CreateGenerator: PROC [map: Map, inOrder: BOOL, pfml: PatternFactoredMapList] RETURNS [Generator] _ NIL, Size: PROC [map: Map, limit: INT] RETURNS [INT] _ NIL, PatternFactorMap: PROC [map: Map] RETURNS [PatternFactoredMap] _ NIL, AddTuple: PROC [map: Map, t: VersionTuple, if: IfHads] RETURNS [had: Hads] _ NIL, AddMap: PROC [map, other: Map, if: IfHads] RETURNS [some: HadSets] _ NIL, RemTuple: PROC [map: Map, t: VersionTuple] RETURNS [had: Hads] _ NIL, RemMap: PROC [map, other: Map] RETURNS [some: HadSets] _ NIL, Negate: PROC [map: Map] RETURNS [Map] _ NIL, IsNegation: PROC [map: Map] RETURNS [MaybeMap] _ NIL, Intersect: PROC [map, other: Map] RETURNS [Map] _ NIL, IsIntersection: PROC [map: Map] RETURNS [Maybe2Maps] _ NIL, Union: PROC [map, other: Map, test: UnionTest, ordered: BOOL] RETURNS [Map] _ NIL, IsUnion: PROC [map: Map] RETURNS [Maybe2Maps] _ NIL, Difference: PROC [map, other: Map] RETURNS [Map] _ NIL, IsDifference: PROC [map: Map] RETURNS [Maybe2Maps] _ NIL, SymmetricDifference: PROC [map, other: Map] RETURNS [Map] _ NIL, IsSymmetricDifference: PROC [map: Map] RETURNS [Maybe2Maps] _ NIL, other: Atom.PropList _ NIL, data: REF ANY]; }. $’ VersionMap2.Mesa Copyright Ó 1990 by Xerox Corporation. All rights reserved. Last tweaked by Mike Spreitzer on April 10, 1992 9:27 am PDT Basics Extremely generic stuff. The generic error raised by procedures in this interface. This Error is PFS.Error. Version Tuples This section works up to defining a VersionTuple, which contains: a file name, a create date, and a version stamp. p=nullName => result is TRUE; otherwise, the standard PFS rules apply. A total ordering that is consistent with PFS's ordering. NamePatternIsConstant[p] iff for all x1 and x2: NameMatch[x1, p] AND NameMatch[x2, p] => NameEqual[x1, x2] Returns [c.egmt.gmt, c#CreatedFromGMT[c.egmt.gmt]]. TMatches[t, p] iff NameMatch[t.name, p.name], CreatedMatch[t.created, p.created], and StampMatch[t.stamp, p.stamp]. TEqual[t1, t2] iff (TPCompare[t1, t2] = equal). VersionTuples are totally ordered. Returns one that matches every file having the given short name. Returns one that matches every file having the given last component. PatternIsConstant[p] iff for all x1 and x2: TMatches[x1, p] AND TMatches[x2, p] => TEqual[x1, x2] Version Map Basics A Map represents a relation (a set of tuples). The relation may be functional, which means no two tuples have equal name fields. readonly means the map contents may change, but not due to actions on this Map. Querying Version Maps Does the given map contain the given tuple? Passes to Consume those tuples of map that pass the intersection of the filters. If and when Consume[t] returns TRUE, the enumeration is stopped and [TRUE, t] is returned; otherwise [FALSE, nullTuple] is returned. Tuples are passed in TCompare order if inOrder. Consume may call other procedures on the map; if the map is changed during enumeration, there are no guarantess about whether tuples added or removed are enumerated. (NOT found) => (it = nullTuple). Always returns TRUE. Equivalent to Scan[map, Consume, inOrder, PatternUnfactorMapList[pfml]]. TRUE iff for all m in maplist: Has[m, t]. TRUE iff there exists an m in maplist such that Has[m, t]. Equivalent to AllHave[PatternUnfactorMapList[pfml], t]. The passive form of Scan --- return a closure that can generate the elements under client control. Use of generators is covered in a later section. See CreateMatcher for details about matching. Raises Error[client, $NotUnique] if map.Size[] # 1; otherwise returns the one and only tuple in the map. IF map.Size[]=0 THEN RETURN [[FALSE, nullTuple]] ELSE RETURN [[TRUE, one of the elements of map]]. Returns AnElt[map.Intersection[CreateMatcher[stamp: stamp]]]. Returns AnElt[map.Intersection[CreateMatcher[created: created]]]. Returns AnElt[map.Intersection[CreateMatcher[name: ShortNameToPattern[shortName]]]]. Result is anything in [MIN[size, limit] .. size]. This lets clients that don't care about the difference between 2 and infinity, and implementations whose cost is proportional to the answer, get along without much waste. Modifying Version Maps Possibly adds a tuple t into map, depending on whether it's OK to replace the pre-existing tuple with the same name (if there is one). For functional maps, if controls whether replacement is done and had reveals some information about the state of map before this operation; for non-functional maps if is ignored (the addition is always done) and there are no guarantees about had (it may even be unitialized). The OldCase for possibly adding a tuple t to a map m is: new if no u in m has the same name as t, same if t is in m, createdDifferent if some u in m has t's name and stamp but a different created, stampDifferent if some u in m has t's name and created but a different stamp, bothDifferent if some u in m has t's name and different created and stamp. When t is already in m, there's no question about whether to add t to m. Such an array tells whether to add a tuple to a map, according to the case. Some specific arrays of interest. A Had partially reveals a state of a map m with respect to a tuple t and a dependent field f: none means u.name # t.name for every u in m, same means u.name = t.name and u.f = t.f for some u in m, and different means u.name = t.name and u.f # t.f for some u in m. Adds the tuples of other into map, possibly replacing pre-existing tuples with equal names as necessary. For functional maps, if controls whether replaceent is done and some reveals some information about the state of map before this operation; for non-functional maps, if is ignored and there are no guarantees about some. other must be able to enumerate. A HadSets summarizes a relation between two Maps (map and other). Specifically, hs[f][h] is TRUE iff there exists some tuple t in other such that the Had for map with respect to t and f is h. Removes a tuple from a writable map, if that tuple was in the map. The previous state of the map is partially revealed by had if the map is functional; no guarantees about had for non-functional maps. Removes the tuples of other from map. The previous state of the map is partially revealed by had if the map is functional; no guarantees about had for non-functional maps. other must be able to enumerate. Like RemMap[map, intersection of filters], except that no information is returned, and thus the filters need not be able to enumerate. Boolean Combinations of Version Maps Produces a map that can test membership but may not be able to enumerate. Argument and result cannot both be functional. IsNegation[Negate[Negate[x]]] might return [FALSE, nullMap]. (NOT found) => (it = nullMap). Returns a map that contain exactly those tuples contained in both given maps. Implements enumeration by enumerating map and testing membership in other. IsIntersection[x] does not imply that x was made with Intersect. (NOT found) => (map = other = nullMap). test=disjoint => map.Intersect[other].Emtpy ordered => TBCompare[t, u] <= equal for all t in map, u in other. test=map => enumeration implemented by enumerating map, enumerating other and testing membership in map. test=other => enumeration implemented by enumerating other, enumerating map and testing membership in other. Enumeration implemented by enumerating map and testing membership in other. Result can enumerate iff both args can; quickly only if both args can quickly test membership. Various Interesting Maps A constant map with no elements. A constant map that contains every VersionTuple. If map.Size[]=1, returns [TRUE, the T that map has], otherwise [FALSE, nullTuple]. The result is functional, writable, and initially empty. Reads map contents from a file; assumeImmutable indicates whether MapFromFile can assume the file's contents will not change. MapFromFile always returns a constant map. Thus, if assumeImmutable, the returned map can use a RopeFile on the given file; otherwise, the entire file contents must be copied (into memory or another file). (NOT found) => (it = nullName). A `directories map' contains all the files in a set of directories. The directories are the members of dirs (created and stamp unimportant). If given, hints and cache are consulted before file contents to determine version stamps. If cache is given, stamps read from files are stored there. Pattern Matching Maps. Creates a Map that can test membership, but cannot enumerate (unless the pattern is constant). It contains every tuple t such that TMatches[t, pattern]. A factored representation for the intersection of CreateMatcher[pattern], stampInd, and general. Neither stampInd nor general is NIL; aFull is used to say `no more constraints'. Membership in stampInd (`stamp independent') does not depend on a tuple's stamp; that is, for all n, c, s1, and s2: is in stampInd if and only if is in stampInd. Any map that can yield useful information without doing a lot of work is expected to do so. Represents the intersection of CreateMatcher[pattern], the members of stampInd, and the members of general. The members of stampInd do not care about the version stamps of tuples. Setting stampInd=listOfEmpty is a particularly obvious way to indicate the empty intersection. If empty intersection detected, stampInd=listOfEmpty. The inverse of PatternFactorMapList. Result represents the intersection of the arguments. Returns a constant map that matches every tuple whose name is the concatenation of prefix.name and one of the suffixes. Generators Generators produce VersionTuples one at a time. Returns nullTuple when there are no more. Tells the generator that no more of its values will be needed. Result generates elements of both generators, which must be disjoint. Result does not support concurrent calls. If sort, both generators are assumed to generate in order, and the result alternates between them to preserve order. Closes g1 and g2 when closed. Result generates the same elements as the argument, but in order. Result does not support concurrent calls. Closes arg when closed. Returns a more restricted generator. Result does not support concurrent calls. Closes given generator when closed. If the generator has exactly one more tuple to generate, that one is returned; otherwise, raises Error[client, $NotUnique]. If the generator has exactly one more tuple to generate, returns [TRUE, the tuple]; otherwise, returns [FALSE, nullTuple]. Implementing Maps Only implementors of map classes need to know this. Ê©– "cedar" style•NewlineDelimiter ™code™K™—K˜šžœœ%œœ˜AK™)—K˜šžœœ%œœ˜@K™:—K˜šžœœ1œœ˜MKšœ7™7—K˜š žœœœœœ ˜[K™”KšœœœI˜Y—K˜šžœœœ œ ˜iKšœœœ0˜@—K˜š ž œœ žœœœ ˜oKšœ-™-Kšœœœ3˜C—K˜šžœœœœ ˜ZKšœœœ5˜E—K˜šžœœ œ˜/Kšœh™h—K˜šžœœ œ˜,™K™ K™1——K˜šž œœ!œ˜GKšœ=™=—K˜šž œœœ˜FKšœA™A—K˜šžœœœœ˜GKšœT™T—K˜šžœœœœœœœ˜:K™ÝKšœœœ˜-—K˜šžœœ œœ˜%Kšœœœ˜#——™šžœœ2œ ˜SKšœŸœŸœ}Ÿœ*Ÿœ-Ÿœ0ŸœLŸœ™›Kšœœœ!˜1—K˜šœ œ@˜MšœŸœŸœ Ÿœ™8KšŸœŸœŸœŸœ™(KšŸœŸœŸœ™KšŸœŸœŸœ*™OKšŸœ ŸœŸœŸœ*™MKšŸ œ ŸœŸœŸœ(™J——K˜šœœ$˜——K˜šžœœ(œ˜KKšœŸœŸœ^Ÿœ)Ÿœ-Ÿœ1Ÿœ.ŸœŸœ™æKšœœœ#˜3—K˜Kš œœœœœœ˜(K˜š œ œœœ œœœ˜AKšœ2ŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœ™À—K˜šžœœœ ˜>Kšœ{Ÿœ/Ÿœ™ÉKšœœœ˜-—K˜šžœœœ˜6Kš œŸœŸœ:Ÿœ/ŸœŸœ™ÎKšœœœ˜/—K˜šž œœ˜.Kšœ`Ÿœ™†——™$šžœœ œ˜%K™yKšœœœ˜(—K˜šž œœ œ ˜.K™Kšœ[™[Kšœœœ"˜2—K˜šœœœ˜'Kšœ"˜"Kšœ˜ Kšœ˜Kš œŸœŸœŸœŸœ:ŸœB™”—K˜Kšœ œ  ˜.K˜šžœœ œ˜FKšœ Ÿœ™5—K˜šžœœœ ˜HKšœ$™$—K˜šž œœœ˜PK™4—K˜šžœœ"œœ˜KK™w——šœ ™ K™/K˜Kšœ œœ˜#šœœœ˜šžœœ œ˜.K™)—šžœœ ˜K™>—Kšœœœœ˜—K˜šžœœœœ ˜IK™…—K˜šž œœ œ ˜4K™…—K˜šžœœœ ˜?K™t—K˜šž œœœ˜;Kšœ{™{—K˜šžœœœ˜>Kšœz™z——™K™3K˜Kšœ œœ ˜!šœ œœ˜Kšž œœ œœ˜+Kšž œœ œ˜2Kš žœœœœœ˜=Kš žœœ žœœ œœ˜vKš žœœœ œœ˜hKš žœœœœœœ˜6Kšžœœ œœ˜EKšžœœ)œœ˜QKšžœœœœ˜IKšžœœœœ˜EKšžœœœœ˜=Kšžœœ œ œ˜,Kšž œœ œœ˜5Kšž œœœ œ˜6Kšžœœ œœ˜;Kš žœœ-œœ œ˜RKšžœœ œœ˜4Kšž œœœ œ˜7Kšž œœ œœ˜9Kšžœœœ œ˜@Kšžœœ œœ˜BKšœœ˜Kšœœœ˜——K˜—…—'v^±