<> <> <> <> DIRECTORY CDValue, CD, CDEvents, RefTab; CDValueImpl: CEDAR MONITOR IMPORTS CD, CDEvents, RefTab EXPORTS CD, CDValue = BEGIN Propagation: TYPE = CDValue.Propagation; PrivateValueDRep: PUBLIC TYPE = RECORD [ values: RefTab.Ref ]; PrivateValueTRep: PUBLIC TYPE = RECORD [ registration: RefTab.Ref, values: RefTab.Ref ]; globalTab: RefTab.Ref = RefTab.Create[]; registerTab: RefTab.Ref = RefTab.Create[]; registeredWithTechnology: REF _ NEW[INT]; DesignCreateEvent: CDEvents.EventProc = { design.cdValuePriv _ NEW[PrivateValueDRep _ [values: RefTab.Create[]]] }; TechnologyCreateEvent: CDEvents.EventProc = { tech: CD.Technology = NARROW[x]; tech.cdValuePriv _ NEW[PrivateValueTRep _ [registration: RefTab.Create[], values: RefTab.Create[]]] }; RegisterKey: PUBLIC ENTRY PROC [key: REF, boundTo: CD.Technology, registrationKey: REF] = { ENABLE UNWIND => NULL; Register: PROC [regTab: RefTab.Ref, key: REF, registrationKey: REF] RETURNS [ok: BOOL] = { oldRegistrationKey: REF _ RefTab.Fetch[regTab, key].val; IF oldRegistrationKey=NIL THEN ok _ RefTab.Insert[regTab, key, registrationKey] ELSE IF oldRegistrationKey=$nil OR oldRegistrationKey#registrationKey THEN ok _ FALSE ELSE ok _ TRUE }; done: BOOL _ FALSE; IF registrationKey=NIL THEN registrationKey _ $nil; IF boundTo=NIL THEN done _ Register[registerTab, key, registrationKey] ELSE { done _ Register[registerTab, key, registeredWithTechnology]; IF done THEN { tem: REF PrivateValueTRep = boundTo.cdValuePriv; IF tem=NIL THEN RETURN WITH ERROR CD.Error[ec: calling, explanation: "technology had not been registered"]; done _ Register[tem.registration, key, registrationKey] }; }; IF ~done THEN RETURN WITH ERROR CD.Error[doubleRegistration] }; Fetch: PUBLIC ENTRY PROC [boundTo: REF, key: REF, propagation: Propagation] RETURNS [REF] = { ENABLE UNWIND => NULL; val: RefTab.Val; found: BOOL; DO WITH boundTo SELECT FROM d: CD.Design => { [found: found, val: val] _ RefTab.Fetch[d.cdValuePriv.values, key]; IF found THEN RETURN [val]; IF propagation>design THEN boundTo_d.technology ELSE RETURN [NIL] }; t: CD.Technology => { [found: found, val: val] _ RefTab.Fetch[t.cdValuePriv.values, key]; IF found THEN RETURN [val]; IF propagation>technology THEN boundTo_NIL ELSE RETURN [NIL] }; ENDCASE => { IF boundTo#NIL THEN RETURN WITH ERROR CD.Error[calling, "CDValue.Fetch: bad boundTo type"] ELSE { [found: found, val: val] _ RefTab.Fetch[globalTab, key]; IF found THEN RETURN [val]; RETURN [NIL] }; }; ENDLOOP }; GetTab: PROC [boundTo: REF] RETURNS [ref: RefTab.Ref] = INLINE { WITH boundTo SELECT FROM t: CD.Technology => RETURN [t.cdValuePriv.values]; d: CD.Design => RETURN [d.cdValuePriv.values]; ENDCASE => { IF boundTo#NIL THEN RETURN WITH ERROR CD.Error[calling, "CDValue.Store: bad boundTo type"] ELSE RETURN [globalTab] }; }; Store: PUBLIC PROC [boundTo: REF, key: REF, value: REF] = { ref: RefTab.Ref = GetTab[boundTo]; IF value#NIL THEN [] _ RefTab.Store[ref, key, value] ELSE [] _ RefTab.Delete[ref, key]; }; StoreConditional: PUBLIC PROC [boundTo: REF, key: REF, value: REF] RETURNS [done: BOOL] = { ref: RefTab.Ref = GetTab[boundTo]; IF value#NIL THEN done _ RefTab.Insert[ref, key, value] ELSE done _ RefTab.Delete[ref, key]; }; FetchInt: PUBLIC PROC [boundTo: REF, key: REF, propagation: Propagation, ifNotFound: INT] RETURNS [INT] = { WITH Fetch[boundTo, key, propagation] SELECT FROM r: REF INT => RETURN [r^] ENDCASE => RETURN [ifNotFound] }; StoreInt: PUBLIC PROC [boundTo: REF, key: REF, value: INT] = { Store[boundTo, key, NEW[INT _ value]] }; CDEvents.RegisterEventProc[$CreateNewDesign, DesignCreateEvent]; CDEvents.RegisterEventProc[$RegisterTechnology, TechnologyCreateEvent]; END.