<> <> <> <> DIRECTORY CD, Rope, TokenIO; CDProperties: CEDAR DEFINITIONS = BEGIN <> <<>> <> <<>> <> <> <<>> <> <> <<>> <> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <<>> <<--Types and registration>> PropList: TYPE = CD.PropList; PropRef: TYPE = CD.PropRef; --ABSOLUTELY NEVER NIL <<--Use only CDProperties to modify ChipNDale PropList's; Never Properties directly.>> InitPropRef: PROC [] RETURNS [PropRef] = INLINE { <<--Initialization value for a PropRef>> <<--An object MUST be not accessible for ChipNDale until all its PropRef's are initialized. >> RETURN [NEW[PropList_NIL]] }; RegisterProperty: PROC [prop: REF, registrationKey: REF_NIL] RETURNS [first: BOOL]; <<--Registers "prop" for usage; any program which wants to use an ATOM as a "prop" can >> <<--make sure it is the only user of this "prop". >> <<--If registrationKey#NIL and registrationKey is equal to registrationKey of previous >> <<--registration, a property registered again, otherwise raise CD.Error[doubleRegistration] >> <<--if prop is re-registered.>> <<>> <<--Usage>> PutProp: PROC [onto: REF, prop: REF, val: REF_NIL]; <<-- Puts a prop val pair on a property list>> <<-- onto must not be of type PropList>> <<-- a NIL val removes the property>> <<-- It is the callers responsibility not to change properties of immutable objects>> <<-- unless the property is not considered part of the object itself.>> GetProp: PROC [from: REF, prop: REF] RETURNS [REF]; <<--Fetches a value from a property list; NIL if not found>> GetListProp: PROC [propList: PropList, prop: REF] RETURNS [REF]; <<--Fetches a value from a property list; NIL if not found>> <<--PutProp and GetProp "understand" the following types: CD.Instance CD.Object CD.PropRef (CDProperties.PropRef) some more types which are only of secondary importance.>> <<--Speed-ups and special cases>> <<--Putting a NIL val removes the property in all cases>> <<-- It is the callers responsibility not to change properties of immutable things>> <<-- unless the property is not considered part of the things itself.>> << >> PutInstanceProp: PROC [onto: CD.Instance, prop: REF, val: REF_NIL]; PutDesignProp: PROC [onto: CD.Design, prop: REF, val: REF_NIL]; PutTechnologyProp: PROC [onto: CD.Technology, prop: REF, val: REF_NIL]; PutAtomProp: PROC [onto: ATOM, prop: REF, val: REF_NIL]; <<--this property is NOT fetchable with Atom.GetProp>> <<--The onto Atom need not be registered anywhere, the registration of the>> <<--prop is enough to prevent conflicts.>> PutObjectProp: PROC [onto: CD.Object, prop: REF, val: REF_NIL]; <<--warning: different objects may share bits, property owners loose!>> PutLayerProp: PROC [onto: CD.Layer, prop: REF, val: REF_NIL]; PutPRefProp: PROC [onto: CD.PropRef, prop: REF, val: REF_NIL]; <<>> GetInstanceProp: PROC [from: CD.Instance, prop: REF] RETURNS [REF] = INLINE { RETURN [GetListProp[from.properties, prop]] }; GetDesignProp: PROC [from: CD.Design, prop: REF] RETURNS [REF] = INLINE { RETURN [GetListProp[from.properties^, prop]] }; GetTechnologyProp: PROC [from: CD.Technology, prop: REF] RETURNS [REF] = INLINE { RETURN [GetListProp[from.properties^, prop]] }; GetAtomProp: PROC [from: ATOM, prop: REF] RETURNS [REF]; <<--does NOT fetch properties put on an ATOM with Atom.PutProp>> <<--The from Atom need not be registered anywhere, the registration of the>> <<--prop is enough to prevent conflicts>> GetObjectProp: PROC [from: CD.Object, prop: REF] RETURNS [REF] = INLINE { <<--warning: different objects may share bits, property owners loose!>> RETURN [GetListProp[from.properties, prop]] }; GetLayerProp: PROC [from: CD.Layer, prop: REF] RETURNS [REF]; GetPRefProp: PROC [from: CD.PropRef, prop: REF] RETURNS [REF] = INLINE { RETURN [GetListProp[from^, prop]] }; <<>> <<>> <<--Two dimensional properties>> << >> PutPropProp: PROC [onto: REF, key1, key2: REF_, val: REF_NIL]; <<--Put value as property using the key sequence [key1, key2] >> <<--[of course: onto's key1 property is a property list, with a key2 property]>> <<--For simplicity: implementation might fail on concurrent PutPropProp's >> GetPropProp: PROC [from: REF, key1, key2: REF_] RETURNS [REF]; <<--Get property using key sequence [key1, key2] >> <<--[assumes: onto's key1 property is a property list, with a key2 property]>> <<>> <<--General property procedures>> InstallProcs: PROC [prop: REF, procs: PropertyProcsRec _ [properties: NIL]]; <<--Installs procedures for a property registration.>> <<--Overwrites values for which procs has non NIL entries (except key).>> <<--prop must be registered and owned by caller.>> <<--Exceptional: The actual parameter procs.properties might have been created >> <<--with Properties directly.>> <<>> FetchProcs: PROC [prop: REF] RETURNS [PropertyProcs]; <<--Fetches the property registration>> <<--Don't copy PropertyProcs^; it can be extended by future calls of InstallProcs >> Register: PROC [prop: ATOM, procs: PropertyProcsRec _ [properties: NIL], registrationKey: REF _ NIL] RETURNS [sameProp: ATOM]; <<--Short cut for conveniance>> <<--sameProp returns prop again, to be used in declarations>> <<--Parameters and raised exceptions are the same as in RegisterProperty and InstallProcs>> PropertyProcs: TYPE = REF PropertyProcsRec; PropertyProcsRec: TYPE = RECORD [ makeCopy: MakeCopyProc _ NIL, internalWrite: InternalPWriteProc _ NIL, internalRead: InternalPReadProc _ NIL, prettyPrint: PrettyPrintProc _ NIL, exclusive: BOOL _ FALSE, --the implementation requests others not too fool with autoRem: BOOL _ FALSE, --removed on direct edits supressTruth: BOOL _ FALSE, --dont write for permanent files reserved: BOOL _ FALSE, --for experiments key: REF _ NIL, --the prop field of registration properties: PropList _ NIL ]; <<--The procedure types of PropertyProcs will be called within CDProperties monitor lock.>> <<--They must not call any other procedure from CDProperties (wedges!!); But they may>> <<--call Properties directly.>> MakeCopyProc: TYPE = PROC [prop: REF, val: REF, purpose: REF_NIL] RETURNS [valCopy: REF]; <<--valCopy: may be NIL if property should not be copied>> <<--purpose:>> <<-- copy procs will not recognize most purposes...>> <<-- but a particular property might want a particular handling from some tool>> InternalPWriteProc: TYPE = PROC [h: TokenIO.Handle, prop: REF, val: REF]; InternalPReadProc: TYPE = PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF]; PrettyPrintProc: TYPE = PROC [prop: REF, val: REF] RETURNS [r: Rope.ROPE]; CopyProps: PROC [propList: PropList, putOnto: REF, purpose: REF_NIL]; <<--Copies properties individually using their MakeCopyProc's and defaults for some types >> <<--The resulting propList is put on putOnto >> AppendProps: PROC [winner, looser: PropList_NIL, putOnto: REF, purpose: REF_NIL]; <<--Copies properties individually using their MakeCopyProc's and defaults for some types. >> <<--Works like first copying looser, then copying winner. >> <<--copy is a different list from both, looser and winner>> <<--The resulting propList copy is put on putOnto >> <<>> DCopyProps: PROC [propList: PropList, purpose: REF_NIL] RETURNS [copy: PropList]; <<--Like CopyProps, but returns PropList;>> <<--Consider: if you assign the copy to somewhere, the previous PropList might have been >> <<--changed after making the copy and before the assignment is finished. >> DAppendProps: PROC [winner, looser: PropList_NIL, purpose: REF_NIL] RETURNS [copy: PropList]; <<--Like AppendProps, but returns PropList;>> <<--Consider: if you assign the copy to somewhere, the previous PropList might have been >> <<--changed after making the copy and before the assignment is finished. >> <<>> DoWithinLock: PRIVATE PROC [p: PROC]; <<--Executes arbitrary code within CDProperties monitor lock. Dangerous.>> <<--Must not call any other procedure from CDProperties (wedges!!)>> <<--May call Properties directly>> <<>> <<>> <<--Particular property procedures for clients implementing properties>> DontCopy: PROC [prop: REF, val: REF, purpose: REF_NIL] RETURNS [nil: REF]; <<--to be shure that no copy is made; trivial procedure>> CopyVal: PROC [prop: REF, val: REF, purpose: REF_NIL] RETURNS [valCopy: REF]; <<--copy of val; trivial procedure; is for some types a default anyway>> <<>> DontPWrite: PROC [h: TokenIO.Handle, prop: REF, val: REF]; RopePWrite: PROC [h: TokenIO.Handle, prop: REF, val: REF]; RopePRead: PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF]; IntPWrite: PROC [h: TokenIO.Handle, prop: REF, val: REF]; IntPRead: PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF]; AtomPWrite: PROC [h: TokenIO.Handle, prop: REF, val: REF]; AtomPRead: PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF]; SomePWrite: PROC [h: TokenIO.Handle, prop: REF, val: REF]; SomePRead: PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF]; END. <> <> <> <<>> <<>>