mirror of
https://github.com/vishapoberon/compiler.git
synced 2026-04-07 03:22:24 +00:00
voc compiler first commit
This commit is contained in:
parent
4a7dc4b549
commit
760d826948
119 changed files with 30394 additions and 0 deletions
565
src/lib/ulm/gnuc/ulmEvents.Mod
Normal file
565
src/lib/ulm/gnuc/ulmEvents.Mod
Normal file
|
|
@ -0,0 +1,565 @@
|
|||
(* Ulm's Oberon Library
|
||||
Copyright (C) 1989-1994 by University of Ulm, SAI, D-89069 Ulm, Germany
|
||||
----------------------------------------------------------------------------
|
||||
Ulm's Oberon Library is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either version
|
||||
2 of the License, or (at your option) any later version.
|
||||
|
||||
Ulm's Oberon Library is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
----------------------------------------------------------------------------
|
||||
E-mail contact: oberon@mathematik.uni-ulm.de
|
||||
----------------------------------------------------------------------------
|
||||
$Id: Events.om,v 1.4 2004/03/30 17:48:14 borchert Exp $
|
||||
----------------------------------------------------------------------------
|
||||
$Log: Events.om,v $
|
||||
Revision 1.4 2004/03/30 17:48:14 borchert
|
||||
support of external queue handling added
|
||||
|
||||
Revision 1.3 1996/01/04 17:07:20 borchert
|
||||
event types are now an extension of Services.Object
|
||||
|
||||
Revision 1.2 1994/07/18 14:17:17 borchert
|
||||
unused variables of Raise (oldevent + newevent) removed
|
||||
|
||||
Revision 1.1 1994/02/22 20:07:41 borchert
|
||||
Initial revision
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
AFB 8/89
|
||||
----------------------------------------------------------------------------
|
||||
*)
|
||||
|
||||
MODULE ulmEvents;
|
||||
|
||||
IMPORT Objects := ulmObjects, Priorities := ulmPriorities, Services := ulmServices, SYS := ulmSYSTEM, SYSTEM;
|
||||
|
||||
TYPE
|
||||
EventType* = POINTER TO EventTypeRec;
|
||||
|
||||
CONST
|
||||
(* possibilities on receipt of an event: *)
|
||||
default* = 0; (* causes abortion *)
|
||||
ignore* = 1; (* ignore event *)
|
||||
funcs* = 2; (* call associated event handlers *)
|
||||
|
||||
TYPE
|
||||
Reaction* = INTEGER; (* one of default, ignore, or funcs *)
|
||||
Message* = ARRAY 80 OF CHAR;
|
||||
Event* = POINTER TO EventRec;
|
||||
EventRec* =
|
||||
RECORD
|
||||
(Objects.ObjectRec)
|
||||
type*: EventType;
|
||||
message*: Message;
|
||||
(* private part *)
|
||||
next: Event; (* queue *)
|
||||
END;
|
||||
EventHandler = PROCEDURE (event: Event);
|
||||
|
||||
(* event managers are needed if there is any action necessary
|
||||
on changing the kind of reaction
|
||||
*)
|
||||
EventManager = PROCEDURE (type: EventType; reaction: Reaction);
|
||||
|
||||
Priority = INTEGER; (* must be non-negative *)
|
||||
|
||||
(* every event with reaction `funcs' has a handler list;
|
||||
the list is in calling order which is reverse to
|
||||
the order of `Handler'-calls
|
||||
*)
|
||||
HandlerList = POINTER TO HandlerRec;
|
||||
HandlerRec* =
|
||||
RECORD
|
||||
(Objects.ObjectRec)
|
||||
handler*: EventHandler;
|
||||
next*: HandlerList;
|
||||
END;
|
||||
SaveList = POINTER TO SaveRec;
|
||||
SaveRec =
|
||||
RECORD
|
||||
reaction: Reaction;
|
||||
handlers: HandlerList;
|
||||
next: SaveList;
|
||||
END;
|
||||
|
||||
EventTypeRec* =
|
||||
RECORD
|
||||
(Services.ObjectRec)
|
||||
(* private components *)
|
||||
handlers: HandlerList;
|
||||
priority: Priority;
|
||||
reaction: Reaction;
|
||||
manager: EventManager;
|
||||
savelist: SaveList;
|
||||
END;
|
||||
|
||||
Queue = POINTER TO QueueRec;
|
||||
QueueRec =
|
||||
RECORD
|
||||
priority: INTEGER; (* queue for this priority *)
|
||||
head, tail: Event;
|
||||
next: Queue; (* queue with lower priority *)
|
||||
END;
|
||||
|
||||
VAR
|
||||
eventTypeType: Services.Type;
|
||||
|
||||
CONST
|
||||
priotabsize = 256; (* size of a priority table *)
|
||||
maxnestlevel = 1024; (* of Raise-calls (avoids endless recursion) *)
|
||||
|
||||
TYPE
|
||||
(* in some cases coroutines uses local priority systems *)
|
||||
PrioritySystem* = POINTER TO PrioritySystemRec;
|
||||
PrioritySystemRec* =
|
||||
RECORD
|
||||
(Objects.ObjectRec)
|
||||
(* private part *)
|
||||
currentPriority: Priority;
|
||||
priotab: ARRAY priotabsize OF Priority;
|
||||
priotop: INTEGER;
|
||||
overflow: INTEGER; (* of priority table *)
|
||||
END;
|
||||
|
||||
CONST
|
||||
priorityViolation* = 0; (* priority violation (EnterPriority *)
|
||||
unbalancedExitPriority* = 1; (* unbalanced call of ExitPriority *)
|
||||
unbalancedRestoreReaction* = 2; (* unbalanced call of RestoreReaction *)
|
||||
negPriority* = 3; (* negative priority given to SetPriority *)
|
||||
errorcodes* = 4;
|
||||
|
||||
TYPE
|
||||
ErrorEvent* = POINTER TO ErrorEventRec;
|
||||
ErrorEventRec* =
|
||||
RECORD
|
||||
(EventRec)
|
||||
errorcode*: SHORTINT;
|
||||
END;
|
||||
|
||||
VAR
|
||||
errormsg*: ARRAY errorcodes OF Message;
|
||||
error*: EventType;
|
||||
|
||||
VAR
|
||||
(* private part *)
|
||||
abort, log, queueHandler: EventHandler;
|
||||
nestlevel: INTEGER; (* of Raise calls *)
|
||||
queue: Queue;
|
||||
lock: BOOLEAN; (* lock critical operations *)
|
||||
psys: PrioritySystem; (* current priority system *)
|
||||
|
||||
PROCEDURE ^ Define*(VAR type: EventType);
|
||||
PROCEDURE ^ SetPriority*(type: EventType; priority: Priority);
|
||||
PROCEDURE ^ Raise*(event: Event);
|
||||
|
||||
PROCEDURE InitErrorHandling;
|
||||
BEGIN
|
||||
Define(error); SetPriority(error, Priorities.liberrors);
|
||||
errormsg[priorityViolation] :=
|
||||
"priority violation (Events.EnterPriority)";
|
||||
errormsg[unbalancedExitPriority] :=
|
||||
"unbalanced call of Events.ExitPriority";
|
||||
errormsg[unbalancedRestoreReaction] :=
|
||||
"unbalanced call of Events.RestoreReaction";
|
||||
errormsg[negPriority] :=
|
||||
"negative priority given to Events.SetPriority";
|
||||
END InitErrorHandling;
|
||||
|
||||
PROCEDURE Error(code: SHORTINT);
|
||||
VAR event: ErrorEvent;
|
||||
BEGIN
|
||||
NEW(event); event.type := error;
|
||||
event.message := errormsg[code];
|
||||
event.errorcode := code;
|
||||
Raise(event);
|
||||
END Error;
|
||||
|
||||
PROCEDURE NilEventManager(type: EventType; reaction: Reaction);
|
||||
END NilEventManager;
|
||||
|
||||
PROCEDURE Init*(type: EventType);
|
||||
VAR
|
||||
stype: Services.Type;
|
||||
BEGIN
|
||||
Services.GetType(type, stype); ASSERT(stype # NIL);
|
||||
type.handlers := NIL;
|
||||
type.priority := Priorities.default;
|
||||
type.reaction := default;
|
||||
type.manager := NilEventManager;
|
||||
type.savelist := NIL;
|
||||
END Init;
|
||||
|
||||
PROCEDURE Define*(VAR type: EventType);
|
||||
(* definition of a new event;
|
||||
an unique event number is returned;
|
||||
the reaction on receipt of `type' is defined to be `default'
|
||||
*)
|
||||
BEGIN
|
||||
NEW(type);
|
||||
Services.Init(type, eventTypeType);
|
||||
Init(type);
|
||||
END Define;
|
||||
|
||||
PROCEDURE GetReaction*(type: EventType) : Reaction;
|
||||
(* returns either `default', `ignore', or `funcs' *)
|
||||
BEGIN
|
||||
RETURN type.reaction
|
||||
END GetReaction;
|
||||
|
||||
PROCEDURE SetPriority*(type: EventType; priority: Priority);
|
||||
(* (re-)defines the priority of an event *)
|
||||
BEGIN
|
||||
IF priority <= 0 THEN
|
||||
Error(negPriority);
|
||||
ELSE
|
||||
type.priority := priority;
|
||||
END;
|
||||
END SetPriority;
|
||||
|
||||
PROCEDURE GetEventPriority*(type: EventType) : Priority;
|
||||
(* return the priority of the given event *)
|
||||
BEGIN
|
||||
RETURN type.priority
|
||||
END GetEventPriority;
|
||||
|
||||
PROCEDURE Manager*(type: EventType; manager: EventManager);
|
||||
BEGIN
|
||||
type.manager := manager;
|
||||
END Manager;
|
||||
|
||||
PROCEDURE Handler*(type: EventType; handler: EventHandler);
|
||||
(* add `handler' to the list of handlers for event `type' *)
|
||||
VAR
|
||||
newhandler: HandlerList;
|
||||
BEGIN
|
||||
NEW(newhandler);
|
||||
newhandler.handler := handler; newhandler.next := type.handlers;
|
||||
type.handlers := newhandler;
|
||||
IF type.reaction # funcs THEN
|
||||
type.reaction := funcs; type.manager(type, funcs);
|
||||
END;
|
||||
END Handler;
|
||||
|
||||
PROCEDURE RemoveHandlers*(type: EventType);
|
||||
(* remove list of handlers for event `type';
|
||||
implies default reaction (abortion) on
|
||||
receipt of `type'
|
||||
*)
|
||||
BEGIN
|
||||
type.handlers := NIL;
|
||||
IF type.reaction # default THEN
|
||||
type.reaction := default; type.manager(type, default);
|
||||
END;
|
||||
END RemoveHandlers;
|
||||
|
||||
PROCEDURE Ignore*(type: EventType);
|
||||
(* implies RemoveHandlers(type) and causes receipt
|
||||
of `type' to be ignored
|
||||
*)
|
||||
BEGIN
|
||||
type.handlers := NIL;
|
||||
IF type.reaction # ignore THEN
|
||||
type.reaction := ignore; type.manager(type, ignore);
|
||||
END;
|
||||
END Ignore;
|
||||
|
||||
PROCEDURE GetHandlers*(type: EventType; handlers: HandlerList);
|
||||
(* returns the list of handlers in `handlers';
|
||||
the reaction of `type' must be `funcs'
|
||||
*)
|
||||
BEGIN
|
||||
handlers := type.handlers;
|
||||
END GetHandlers;
|
||||
|
||||
PROCEDURE Log*(loghandler: EventHandler);
|
||||
(* call `loghandler' for every event;
|
||||
subsequent calls of `Log' replace the loghandler;
|
||||
the loghandler is not called on default and ignore
|
||||
*)
|
||||
BEGIN
|
||||
log := loghandler;
|
||||
END Log;
|
||||
|
||||
PROCEDURE GetLog*(VAR loghandler: EventHandler);
|
||||
(* returns the loghandler set by `Log' *)
|
||||
BEGIN
|
||||
loghandler := log;
|
||||
END GetLog;
|
||||
|
||||
(* noch *)
|
||||
PROCEDURE -getaddr(handler: EventHandler): LONGINT
|
||||
"(LONGINT)&handler";
|
||||
|
||||
PROCEDURE NilHandler*(event: Event);
|
||||
(* an empty event handler *)
|
||||
END NilHandler;
|
||||
|
||||
(* now QueueHandler will translate partly like
|
||||
i = (long)&handler;
|
||||
j = (long)&ulmEvents_NilHandler;
|
||||
b = i != j;
|
||||
if (!(b)) {SYSTEM_assert = 0; SYSTEM_HALT(-1);};
|
||||
|
||||
; noch
|
||||
*)
|
||||
|
||||
PROCEDURE QueueHandler*(handler: EventHandler);
|
||||
(* setup an alternative handler of events
|
||||
that cannot be processed now because
|
||||
of their unsufficient priority
|
||||
*)
|
||||
VAR b : BOOLEAN; (* noch *)
|
||||
i,j : LONGINT;
|
||||
BEGIN
|
||||
i := getaddr(handler);
|
||||
j := getaddr(NilHandler);
|
||||
b := i # j;
|
||||
(*ASSERT (handler # NilHandler);*)
|
||||
ASSERT(b);
|
||||
queueHandler := handler;
|
||||
END QueueHandler;
|
||||
|
||||
PROCEDURE AbortHandler*(handler: EventHandler);
|
||||
(* defines the handler to be called on abortion *)
|
||||
BEGIN
|
||||
abort := handler;
|
||||
END AbortHandler;
|
||||
|
||||
PROCEDURE GetAbortHandler*(VAR handler: EventHandler);
|
||||
(* returns the handler set by `AbortHandler' *)
|
||||
BEGIN
|
||||
handler := abort;
|
||||
END GetAbortHandler;
|
||||
|
||||
PROCEDURE ^ CallHandlers(event: Event);
|
||||
|
||||
PROCEDURE WorkupQueue;
|
||||
VAR
|
||||
ptr: Event;
|
||||
BEGIN
|
||||
WHILE (queue # NIL) & (queue.priority > psys.currentPriority) DO
|
||||
IF SYS.TAS(lock) THEN RETURN END;
|
||||
ptr := queue.head; queue := queue.next;
|
||||
lock := FALSE;
|
||||
WHILE ptr # NIL DO
|
||||
CallHandlers(ptr);
|
||||
ptr := ptr.next;
|
||||
END;
|
||||
END;
|
||||
END WorkupQueue;
|
||||
|
||||
PROCEDURE CallHandlers(event: Event);
|
||||
VAR
|
||||
ptr: HandlerList;
|
||||
oldPriority: Priority;
|
||||
BEGIN
|
||||
CASE event.type.reaction OF
|
||||
| default: abort(event);
|
||||
| ignore:
|
||||
| funcs: oldPriority := psys.currentPriority;
|
||||
psys.currentPriority := event.type.priority;
|
||||
log(event);
|
||||
ptr := event.type.handlers;
|
||||
WHILE ptr # NIL DO
|
||||
ptr.handler(event);
|
||||
ptr := ptr.next;
|
||||
END;
|
||||
psys.currentPriority := oldPriority;
|
||||
END;
|
||||
END CallHandlers;
|
||||
|
||||
PROCEDURE Raise*(event: Event);
|
||||
(* call all event handlers (in reverse order)
|
||||
associated with event.type;
|
||||
abort if there are none;
|
||||
some system events may abort in another way
|
||||
(i.e. they do not cause the abortion handler to be called)
|
||||
*)
|
||||
VAR
|
||||
priority: Priority;
|
||||
|
||||
PROCEDURE AddToQueue(event: Event);
|
||||
VAR
|
||||
prev, ptr: Queue;
|
||||
BEGIN
|
||||
event.next := NIL;
|
||||
ptr := queue; prev := NIL;
|
||||
WHILE (ptr # NIL) & (ptr.priority > priority) DO
|
||||
prev := ptr;
|
||||
ptr := ptr.next;
|
||||
END;
|
||||
IF (ptr # NIL) & (ptr.priority = priority) THEN
|
||||
ptr.tail.next := event;
|
||||
ptr.tail := event;
|
||||
ELSE
|
||||
NEW(ptr);
|
||||
ptr.priority := priority;
|
||||
ptr.head := event; ptr.tail := event;
|
||||
IF prev = NIL THEN
|
||||
ptr.next := queue;
|
||||
queue := ptr;
|
||||
ELSE
|
||||
ptr.next := prev.next;
|
||||
prev.next := ptr;
|
||||
END;
|
||||
END;
|
||||
END AddToQueue;
|
||||
|
||||
BEGIN (* Raise *)
|
||||
INC(nestlevel);
|
||||
IF nestlevel >= maxnestlevel THEN
|
||||
abort(event);
|
||||
ELSE
|
||||
IF event.type.reaction # ignore THEN
|
||||
priority := event.type.priority;
|
||||
IF psys.currentPriority < priority THEN
|
||||
CallHandlers(event); WorkupQueue;
|
||||
ELSIF queueHandler # NIL THEN
|
||||
queueHandler(event);
|
||||
ELSIF ~SYS.TAS(lock) THEN
|
||||
AddToQueue(event);
|
||||
lock := FALSE;
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
DEC(nestlevel);
|
||||
END Raise;
|
||||
|
||||
PROCEDURE CreatePrioritySystem*(VAR prioritySystem: PrioritySystem);
|
||||
(* create and initialize a new priority system *)
|
||||
BEGIN
|
||||
NEW(prioritySystem);
|
||||
prioritySystem.currentPriority := Priorities.base;
|
||||
prioritySystem.priotop := 0;
|
||||
END CreatePrioritySystem;
|
||||
|
||||
PROCEDURE CurrentPrioritySystem*() : PrioritySystem;
|
||||
(* return the priority system currently active *)
|
||||
BEGIN
|
||||
RETURN psys
|
||||
END CurrentPrioritySystem;
|
||||
|
||||
PROCEDURE SwitchPrioritySystem*(prioritySystem: PrioritySystem);
|
||||
(* switch to another priority system; this is typically
|
||||
done in case of task switches
|
||||
*)
|
||||
BEGIN
|
||||
psys := prioritySystem;
|
||||
END SwitchPrioritySystem;
|
||||
|
||||
PROCEDURE EnterPriority*(priority: Priority);
|
||||
(* sets the current priority to `priority';
|
||||
it is an error to give a priority less than
|
||||
the current priority (event `badpriority')
|
||||
*)
|
||||
BEGIN
|
||||
IF psys.currentPriority <= priority THEN
|
||||
IF (psys.overflow = 0) & (psys.priotop < priotabsize) THEN
|
||||
psys.priotab[psys.priotop] := psys.currentPriority;
|
||||
INC(psys.priotop);
|
||||
psys.currentPriority := priority;
|
||||
ELSE
|
||||
INC(psys.overflow);
|
||||
END;
|
||||
ELSE
|
||||
Error(priorityViolation);
|
||||
INC(psys.overflow);
|
||||
END;
|
||||
END EnterPriority;
|
||||
|
||||
PROCEDURE AssertPriority*(priority: Priority);
|
||||
(* current priority
|
||||
< priority: set the current priority to `priority'
|
||||
>= priority: the current priority remains unchanged
|
||||
*)
|
||||
BEGIN
|
||||
IF (psys.overflow = 0) & (psys.priotop < priotabsize) THEN
|
||||
psys.priotab[psys.priotop] := psys.currentPriority; INC(psys.priotop);
|
||||
IF psys.currentPriority < priority THEN
|
||||
psys.currentPriority := priority;
|
||||
END;
|
||||
ELSE
|
||||
INC(psys.overflow);
|
||||
END;
|
||||
END AssertPriority;
|
||||
|
||||
PROCEDURE ExitPriority*;
|
||||
(* causes the priority before the last effective call
|
||||
of SetPriority or AssertPriority to be restored
|
||||
*)
|
||||
BEGIN
|
||||
IF psys.overflow > 0 THEN
|
||||
DEC(psys.overflow);
|
||||
ELSIF psys.priotop = 0 THEN
|
||||
Error(unbalancedExitPriority);
|
||||
ELSE
|
||||
DEC(psys.priotop); psys.currentPriority := psys.priotab[psys.priotop];
|
||||
WorkupQueue;
|
||||
END;
|
||||
END ExitPriority;
|
||||
|
||||
PROCEDURE GetPriority*() : Priority;
|
||||
(* returns the current priority *)
|
||||
BEGIN
|
||||
RETURN psys.currentPriority
|
||||
END GetPriority;
|
||||
|
||||
PROCEDURE SaveReaction*(type: EventType);
|
||||
(* saves current reaction until call of RestoreReaction;
|
||||
the new reaction of `type' is defined to be `ignore'
|
||||
but can be changed by Events.Handler or Events.RemoveHandlers
|
||||
*)
|
||||
VAR
|
||||
savelist: SaveList;
|
||||
BEGIN
|
||||
NEW(savelist);
|
||||
savelist.reaction := type.reaction;
|
||||
savelist.handlers := type.handlers;
|
||||
savelist.next := type.savelist;
|
||||
type.savelist := savelist;
|
||||
type.handlers := NIL;
|
||||
IF type.reaction # ignore THEN
|
||||
type.reaction := ignore; type.manager(type, ignore);
|
||||
END;
|
||||
END SaveReaction;
|
||||
|
||||
PROCEDURE RestoreReaction*(type: EventType);
|
||||
(* restores old reaction;
|
||||
must be properly nested
|
||||
*)
|
||||
VAR
|
||||
savelist: SaveList;
|
||||
BEGIN
|
||||
IF type.savelist = NIL THEN
|
||||
Error(unbalancedRestoreReaction);
|
||||
ELSE
|
||||
savelist := type.savelist;
|
||||
type.savelist := savelist.next;
|
||||
type.handlers := savelist.handlers;
|
||||
IF type.reaction # savelist.reaction THEN
|
||||
type.reaction := savelist.reaction;
|
||||
type.manager(type, savelist.reaction);
|
||||
END;
|
||||
END;
|
||||
END RestoreReaction;
|
||||
|
||||
BEGIN
|
||||
CreatePrioritySystem(psys);
|
||||
|
||||
Services.CreateType(eventTypeType, "Events.EventType", "");
|
||||
|
||||
abort := NilHandler; log := NilHandler; queueHandler := NIL;
|
||||
nestlevel := 0;
|
||||
queue := NIL;
|
||||
lock := FALSE;
|
||||
|
||||
InitErrorHandling;
|
||||
END ulmEvents.
|
||||
Loading…
Add table
Add a link
Reference in a new issue