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]<jacobi>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;