<<>> <> <> <> <> <> <> DIRECTORY Properties; PropertiesImpl: CEDAR MONITOR EXPORTS Properties = BEGIN <<>> PropList: TYPE = Properties.PropList; <<>> GetProp: PUBLIC ENTRY PROC [propList: PropList, prop: REF] RETURNS [REF ¬ NIL] = { ENABLE UNWIND => NULL; WHILE propList # NIL DO IF propList.first.key = prop THEN RETURN [propList.first.val]; propList ¬ propList.rest; ENDLOOP; }; PutProp: PUBLIC ENTRY PROC [propList: PropList, prop: REF, val: REF ¬ NIL] RETURNS [PropList] = { ENABLE UNWIND => NULL; IF val=NIL THEN RETURN [RemPropInternal[propList, prop]] ELSE RETURN [PutPropInternal[propList, prop, val]] }; RemPropInternal: INTERNAL PROC [propList: PropList, prop: REF] RETURNS [PropList] = INLINE { lst: PropList ¬ propList; lag: PropList ¬ NIL; UNTIL lst = NIL DO rest: PropList ¬ lst.rest; IF lst.first.key = prop THEN { IF lag = NIL THEN RETURN [rest]; lag.rest ¬ rest; RETURN [propList]; }; lag ¬ lst; lst ¬ rest; ENDLOOP; RETURN [propList]; }; PutPropInternal: INTERNAL PROC [propList: PropList, prop: REF, val: REF] RETURNS [PropList] = INLINE { lst: PropList ¬ propList; lag: PropList ¬ NIL; WHILE lst # NIL DO IF lst.first.key = prop THEN { <<--Update list element in place>> lst.first.val ¬ val; RETURN [propList]; }; lag ¬ lst; lst ¬ lst.rest; ENDLOOP; <<--prop not found on property list>> lst ¬ LIST[[key: prop, val: val]]; IF lag = NIL THEN RETURN [lst]; lag.rest ¬ lst; RETURN [propList]; }; Enumerate: PUBLIC PROC [propList: PropList, proc: Properties.EachProp] RETURNS [quit: BOOL¬FALSE] = { <<--yes, this needs no special monitoring... >> <<--but I don't want each user to have to prove again>> <<--that this module never creates a state where Enumerate would fail>> FOR l: PropList ¬ propList, l.rest WHILE l#NIL AND ~quit DO quit ¬ proc[l.first.key, l.first.val]; ENDLOOP; }; CopyList: PUBLIC ENTRY PROC [propList: PropList] RETURNS [copy: PropList¬NIL] = { ENABLE UNWIND => NULL; IF propList#NIL THEN { lst: PropList; copy ¬ lst ¬ propList ¬ LIST[propList.first]; WHILE (propList¬propList.rest) # NIL DO lst.rest ¬ LIST[propList.first]; lst ¬ lst.rest; ENDLOOP }; }; END.