<> <> <> DIRECTORY CDEvents, CD, RefTab; CDEventsImpl: CEDAR MONITOR IMPORTS CD, RefTab EXPORTS CDEvents = BEGIN EventProc: TYPE = CDEvents.EventProc; EventRegistration: TYPE = REF EventRegistrationRep; EventRegistrationRep: PUBLIC TYPE = RECORD [ event: REF, eventProcs: EventProcs_NIL ]; EventProcs: TYPE = LIST OF RECORD [proc: EventProc, filter: CD.Technology]; eventNameTable: RefTab.Ref ~ RefTab.Create[]; RegisterEventType: PUBLIC PROC [eventName: REF] RETURNS [EventRegistration] = <<--returns EventRegistration=NIL if eventName is already used.>> <<--the EventRegistration is the key to call ProcessEvent>> <<--if ATOM are used for eventName, include them manual in the list>> <<--on file [ivy]chipndale>CDEvents-registration.txt>> BEGIN ev: EventRegistration_NEW[EventRegistrationRep_[event: eventName]]; IF ~RefTab.Insert[eventNameTable, eventName, ev] THEN ev_NIL; IF ev=NIL THEN ERROR CD.Error[doubleRegistration]; RETURN [ev] END; RegisterEventProc: PUBLIC PROC [event: REF, proc: EventProc, filter: CD.Technology_NIL] = <<--registers a procedure which is called each time a specific event occurs>> <<--the procedure might stop certain events with the dont result>> <<--if filter#NIL, proc is only called if event occurs on design of technology=filter>> <<--event must have been previously registered with RegisterEventType>> BEGIN ev: EventRegistration; x: REF; found: BOOL; [found, x] _ RefTab.Fetch[eventNameTable, event]; IF NOT found THEN ERROR CD.Error[missingRegistration]; ev _ NARROW[x]; <<--insert new proc at end! >> <<--(then first registered procedures are called first)>> <<--application procedures are called after chipndale kernel procedures>> IF ev.eventProcs=NIL THEN ev.eventProcs_LIST[[proc, filter]] ELSE FOR l: EventProcs _ ev.eventProcs, l.rest DO IF l.rest=NIL THEN {l.rest_LIST[[proc, filter]]; RETURN} ENDLOOP END; ProcessEvent: PUBLIC PROC [ev: EventRegistration, design: CD.Design, x: REF_NIL, listenToDont: BOOL_FALSE] RETURNS [dont: BOOL_FALSE] = <<--called on certain events>> <<--can be called only if the EventRegistration is known>> BEGIN IF ev#NIL THEN FOR l: EventProcs _ ev.eventProcs, l.rest WHILE l#NIL DO IF l.first.filter#NIL AND (design=NIL OR l.first.filter#design.technology) THEN LOOP; dont _ l.first.proc[ev.event, design, x ! ABORTED => CONTINUE].dont; IF dont AND listenToDont THEN RETURN; ENDLOOP END; END.