The ModulaTor logo 7KB

The ModulaTor

Oberon-2 and Modula-2 Technical Publication

Erlangen's First Independent Modula_2 Journal! Nr. 7/Aug-1993


Dynamically Loaded Modules in Oberon-2 on VAX/VMS

by Günter Dotzel, ModulaWare

Module dyn_load


___________________________________________________________________
MODULE dyn_load;
(* 
dyn_load is the main program which dynamically loads and activates a independent module using the VMS-call LIB$FIND_IMAGE_SYMBOL.

written by Guenter Dotzel, ModulaWare GmbH, 24-May-1993

Illustrates dynamic module loading in Oberon-2 on VAX/VMS using a VMS run-time library procedure which provides run-time binding of image symbols contained in linked shareable images.

Use the script (command procedure) dyn_base.com to compile (needs H2O V1.28 or later) and link two shareable images.

Oberon-2 source files:

1. dyn_base.mod: base class based on Objects_Types (persistent objects support); linked and installed as shareable image.

2. dyn_load.mod: find an image symbol and activate (load) a module, execute its module body to register its type information in Objects_Types; create an object of dynamic type and call an associated method inherited from the dynamically loaded module; call a procedure (command) which is bound at run-time.

3. dyn_module.mod: dynamically loaded module; extends the base class dyn_base.objExt and overides a method; exports a command procedure; linked as a shareable image to the shareable image base dyn_base.

At compile-time, modules dyn_load and dyn_module independently import the common base class declared in module dyn_base.

At link-time, modules dyn_load and dyn_module are fully independent.

Connection from dyn_load to dyn_module is made at run-time. This mechanism allows to dynamically load any independent module based dyn_base using a module name string.

Dynamic types can be created with procedure Objects_Types.This using the module- and type-name string.

Connections to any procedure exported from a dynamically loaded module can be made at run-time with the same library call LIB$FIND_IMAGE_SYMBOL substituting the module and procedure name separated with a "." (or module_name_separator) in a string; the call results in the relocatable start address of the specified procedure which can be called by means of procedure variables. This works for any procedure type but is shown below for a parameterless procedure only.

Neither the Oberon System nor any Oberon-2 language extensions are necessary to support dynamic loading of modules under VMS. The VMS feature to dynamically load shareable images is available since more than 10 years.

VMS is a multi-process, multi-user operating system; by installing the objects/types base module as a shareable image (as shown in the script file dyn_base.com), other processes could even share the same objects/types data base.


*)

IMPORT CTR, lib:=LIB$,  OT:=Objects_Types, dyn_base, SYSTEM;

CONST Module="DYN_MODULE";
CONST module="dyn_module";
CONST Command="DYN_MODULE.COMMAND";

VAR i: LONGINT;
  adr: CTR.INTEGER;
  mod,typ: ARRAY OT.maxIdentLen OF CHAR;
  obj: dyn_base.objExt;
  o: OT.Object;

TYPE P=PROCEDURE;
VAR dyn_mod_body, command: P;

BEGIN
  i:=lib.LIB$FIND_IMAGE_SYMBOL(Module,Module,adr);
  IF ~ ODD(i) THEN lib.LIB$SIGNAL(i);
    (* file or module entry name not found or not a shareable image*)
  END;
  (* get symbol value and execute the module body to register the 
     types of the new module *)
  dyn_mod_body:=SYSTEM.VAL(P,adr);
  dyn_mod_body;

  (* create an object with module- and type-name is 
     "dyn_module.objExtDesc"
  *)
  OT.NewObj(o, OT.This(module,"myobjExtDesc"));
  obj:=o(dyn_base.objExt);
  (* call associated method from shareable image Module *)
  obj.method(123);

  i:=lib.LIB$FIND_IMAGE_SYMBOL(Module,Command,adr);
  IF ~ ODD(i) THEN lib.LIB$SIGNAL(i); END;
  command:=SYSTEM.VAL(P,adr);
  (* call the parameterless procedure Command of the new module *)
  command;
END dyn_load.
___________________________________________________________________

Module dyn_module

___________________________________________________________________

 MODULE dyn_module;

IMPORT dyn_base;

TYPE
  myobjExt*=POINTER TO myobjExtDesc;

  myobjExtDesc*=RECORD (dyn_base.objExtDesc)
    any: INTEGER
   END;

PROCEDURE (o: myobjExt) method* (any: INTEGER);
BEGIN
  o.any:=any
END method;

PROCEDURE command*;
BEGIN
  HALT(20);
END command;

(* there is always a dummy module body even without an explicit body *)
END dyn_module.
___________________________________________________________________

Module dyn_base

___________________________________________________________________

 MODULE dyn_base;
(* this is the base class for the client modules
   - dyn_load, and 
   - dyn_module 

   written by Guenter Dotzel, ModulaWare GmbH, 25-May-1993
*)

IMPORT OT:=Objects_Types;

TYPE
  objExt*=POINTER TO objExtDesc;

  objExtDesc*=RECORD (OT.ObjectDesc) END;

PROCEDURE (o: objExt) method* (any: INTEGER);
BEGIN
END method;

END dyn_base.
___________________________________________________________________

Command Procedure dyn_base.COM

___________________________________________________________________

$! Guenter Dotzel, ModulaWare GmbH, 25-May-1993
$!
$! compile and link shareable images and execute dyn_load demo
$! to illustrate dynamic module loading in Oberon-2 on VAX/VMS
$! using the VMS run-time library procedure
$!   lib$find_image_symbol.
$!
$! Oberon-2 source files:
$! - ctr  (central basic type definitions)
$! - objects_types (persistent objects support)
$! - dyn_base.mod
$! - dyn_load.mod
$! - dyn_module.mod
$!
$ set verify
$ oberon2 :== h2o/log/debug/nolist! compilation command
$ oberon2 ctr
$ oberon2 ob2:objects_types
$!
$ oberon2 dyn_base
$!
$ libr/create/share dyn_base
$!
$ link/debug/map=dyn_base/share=dyn_base sys$input/options
dyn_base
objects_types
ctr
ob2:h2orts/lib
gsmatch=lequal,1,0
universal=dyn_base.$objects$
universal=objects_types.$data$! data section shared r/w by all images
psect_attr=modula2.$data$,shr! change attributes from noshr to shr
dzro_min=0! initialise shared writeable pages to zero
$!
$ libr/share/repla/log dyn_base dyn_base
$ purge ctr.obj,objects_types.obj,dyn_base.*/noconf
$!
$ define/user mod$library ob2
$ oberon2 dyn_load
$ define/user lnk$library_1 ob2:h2orts
$ link/map/full/debug dyn_load,sys$input/options
dyn_base/share
$!
$ define/user mod$library ob2
$ oberon2 dyn_module
$ define/user lnk$library_1 ob2:h2orts
$ link/share/map/full/debug dyn_module,sys$input/options
dyn_base/share
$!
$! install writeable shareable image dyn_base
$ run sys$system:install
sys$disk:[]dyn_base /open/share/write
$!
$ define/user dyn_base sys$disk:[]dyn_base
$ define/user dyn_module sys$disk:[]dyn_module
$ run dyn_load/nodebug
$!
$! de-install writeable shareable image dyn_base
$run sys$system:install
sys$disk:[]dyn_base /delete
$!
$exit
___________________________________________________________________

Module Objects_Types.DEF

___________________________________________________________________

 DEFINITION MODULE Objects_Types;
(* 
   Run-time type information to support persistent objects.
   Compiler supported object registration and
   and type-name processing.

   A2O|H2O (ModulaWare's AXP|VAX/VMS Oberon-2 Compiler Implementation)
   If preconditions specified are not fulfilled, HALT(20) is called.

   13-Jan-1993/hG/GD: designed based on ETH-Zuerich's module Type.
   05-Apr-1993/pF: procedures DisposeObj, Sizeof added.
   04-Nov-1994/hG/GD: procedure DisposeDynArray added.
*)
CONST maxIdentLen* = 32;

TYPE
  Object* = POINTER TO ObjectDesc;
  ObjectDesc* = RECORD END;

  Type* = POINTER TO TypeDesc;

PROCEDURE TypeOf * (o: Object): Type;
(* returns the dynmaic type of object o.
*)

PROCEDURE TypeName * (typ: Type; VAR module, name: ARRAY OF CHAR);
(* returns the source level module and record name of type t.
  module and name are filled from LENGTH() to LEN()-1 with CHR(0).
  Precondition: typ # NIL.
*)

PROCEDURE This * (module, name: ARRAY OF CHAR): Type;
(* If an object with the name "module.name" was registered,
  it returns the pointer type of "module.name"
  otherwise NIL is returned.
*)

PROCEDURE NewObj * (VAR o: Object; t: Type);
(* creates an object depending on the dynamic type of t.

  A2O|H2O implementation details:
  Allocation is performed by calling SYSTEM.NEW, which in
  H2O calls LIB$GET_VM. In A2O this is a call to Storage.ALLOCATE,
  which usually also calls the OpenVMS system library routine
  LIB$GET_VM.
  Precondition: t # NIL.
*)

PROCEDURE SizeOf * (o: Object) : LONGINT;
(* returns the number of bytes allocated to the dynamic type of the object o,
  not counting the size of the type tag which is equal to SIZE(SYSTEM.PTR).
  Precondition: o # NIL.
*)

PROCEDURE DisposeObj * (VAR o: Object);
(* disposes an object o pointing to any extension of Objects_Types.ObjectDesc
  depending on the dynamic type of o (including the storage occupied by the
  type tag). 
  A2O|H2O implementation detail:
  Deallocation is peformed by calling Storage.DEALLOCATE, which usually
  calls the OpenVMS system library routine LIB$FREE_VM. 
  Precondition: o # NIL, postcondition: o = NIL.
*)

PROCEDURE DisposeDynArray * (VAR o: SYSTEM.PTR;
  numDims, elemSize: LONGINT);
(* dispose a Oberon-2 dynamic array with numDims dimensions and elemSize
  element size. o is a pointer variable to a n-dimensional dymamic array
  such as VAR o: POINTER TO {ARRAY OF}_n T;
  DisposeDynArray(o, n, SIZE(T)); disposes the dynamic array o including
  its array descriptor.
  Precondition: o # NIL, postcondition: o = NIL
  In A2O, this procedure does not have the parameters numDims, elemSize;
  their values are known from the array descriptor. 
*)

PROCEDURE StoreModObjects * (typeDescBase, objects: SYSTEM.PTR);
(*
  A call to StoreModObjects is generated by the Oberon-2 compiler in
  module body of any Oberon-2 program to register the module's record types.
  Run-time type information can be processed with the procedures
  TypeOf, TypeName, This, Sizeof and DisposeObj for all objects which are an
  extension of type Object.

  H2O implementation detail:
  In H2O, the call is actually performed indirectly by the run-time procedure 
  mod$storemodobjects contained in MODRTS.mar (part of H2ORTS.OLB)
*)
END Objects_Types.
___________________________________________________________________

Module CTR

___________________________________________________________________

MODULE CTR;
(* central definition of INTEGER and CARDINAL *)
IMPORT SYSTEM;

TYPE 
  INTEGER * = SYSTEM.SIGNED_32; (* 32 Bit signed whole number type *)
  CARDINAL* = SYSTEM.SIGNED_32;
  ADDRESS * = SYSTEM.SIGNED_32;

(* select your enumeration types carefully: *)
  ENUM8 * = SYSTEM.SIGNED_8;  (* ORD(MAX(corresponding_Modula_2_enum)
 < 256 *)
  ENUM16* = SYSTEM.SIGNED_16; (* ORD(MAX(corresponding_Modula_2_enum)
 < 65536 *)
  ENUM32* = SYSTEM.SIGNED_32; (* ORD(MAX(corresponding_Modula_2_enum)
 < 2^31 *)

(* WORD and QUADWORD are extension of the Oberon-2 module SYSTEM.
   Sorry, there was no other way! *)

  WORD* = SYSTEM.WORD; (* 32 Bit *)
  (* WORD is used in ConvType only (no recursive procedure definitions) *)

  QUADWORD* = SYSTEM.QUADWORD; (* 64 Bit *)
  (* QUADWORD is used in RndFile only (no structured function values) *)

END CTR.
___________________________________________________________________

Foreign Interface Module LIB$

___________________________________________________________________

 MODULE LIB$;
(* Oberon-2 foreign interface module converted from Modula-2 to Oberon-2 
  by Guenter Dotzel, ModulaWare GmbH, 24-May-1993
  using Petra Fabian's ForeignDefToO2 tool, itself written in Oberon-2.

 Parameter suffix $S means: to be passed by string descriptor (%STDESCR)
*)
 
IMPORT SYSTEM,CTR;

TYPE
 CARDINAL * = CTR.CARDINAL;
 INTEGER * = CTR.INTEGER;
                              
PROCEDURE LIB$FIND_IMAGE_SYMBOL* (
     filename$S : ARRAY OF CHAR;
     symbol_desc$S : ARRAY OF CHAR;
 VAR symbol_val: INTEGER
 ): CARDINAL;

END LIB$FIND_IMAGE_SYMBOL;

(* ... other LIB$ procedures deleted ... *)

END LIB$.

Photograph of dyn_load

The following is the log of a terminal session when running dyn_load in debug mode (note, that H2O generates debug information for language VAX-Pascal to be able to use the VMS debugger):



%PHOTO-I-INIT, recording initiated at 25-SEP-1993 16:52:36.03 %PHOTO-I-FILE, log file is _PSLAVE$DKA0:[EDISON.OBERON2.OLI]PHOTO. LOG;2 $ define/user dyn_base sys$disk:[]dyn_base $ define/user dyn_module sys$disk:[]dyn_module $ run dyn_load VAX DEBUG Version V5.4-019 %DEBUG-I-INITIAL, language is PASCAL, module set to DYN_LOAD DBG> Step stepped to DYN_LOAD\%LINE 85 85: IF ~ ODD(i) THEN lib.LIB$SIGNAL(i); DBG> Step stepped to DYN_LOAD\%LINE 90 90: dyn_mod_body:=SYSTEM.VAL(P,adr); DBG> Step stepped to DYN_LOAD\%LINE 91 91: dyn_mod_body; DBG> step/into %DEBUG-I-DYNIMGSET, setting image DYN_MODULE %DEBUG-I-DYNMODSET, setting module DYN_MODULE stepped to routine DYN_MODULE DBG> Step %DEBUG-I-DYNIMGSET, setting image DYN_LOAD stepped to DYN_LOAD\%LINE 96 96: OT.NewObj(o, OT.This(module,"myobjExtDesc")); DBG> Step stepped to DYN_LOAD\%LINE 97 97: obj:=o(dyn_base.objExt); DBG> Step stepped to DYN_LOAD\%LINE 99 99: obj.method(123); DBG> step/into %DEBUG-I-DYNIMGSET, setting image DYN_MODULE stepped to routine DYN_MODULE\MYOBJEXT.METHOD 14: o.any:=any DBG> Step %DEBUG-I-DYNIMGSET, setting image DYN_LOAD stepped to DYN_LOAD\%LINE 99+29 99: obj.method(123); DBG> Step stepped to DYN_LOAD\%LINE 101 101: i:=lib.LIB$FIND_IMAGE_SYMBOL(Module,Command,adr); DBG> Step stepped to DYN_LOAD\%LINE 102 102: IF ~ ODD(i) THEN lib.LIB$SIGNAL(i); END; DBG> Step stepped to DYN_LOAD\%LINE 103 103: command:=SYSTEM.VAL(P,adr); DBG> Step stepped to DYN_LOAD\%LINE 105 105: command; DBG> step/into %DEBUG-I-DYNIMGSET, setting image DYN_MODULE stepped to routine DYN_MODULE.COMMAND DBG> Step stepped to routine DYN_MODULE\COMMAND 19: HALT(20); DBG> Step %OBERON-F-HLTSTMT, HALT statement encountered, value=20 break on unhandled exception preceding DYN_MODULE\COMMAND\%LINE 19 +19 19: HALT(20); DBG> exit $ photo/off %PHOTO-I-FINI, recording finished at 25-SEP-1993 17:00:04.92

Supervisor Series

Credit is due to the creators of the VAX/VMS photo utility. Here is the Product Information

The Supervisor Series is a suite of terminal monitoring and logging utilities that consists of PHOTO and SUPERVISOR.

Originally written by Bob Pasker, Bill Donner, and Terry Way for Precision Business Systems, the Supervisor Series was later acquired by Security Pacific Software Services. After selling and maintaining the software for a number of years, Security Pacific Software's Dan Shoop placed version 5.0D of the Supervisor Series into the public domain in 1992.

The Supervisor Series is currently maintained by Hunter Goatley, VMS Systems Programmer for Western Kentucky University, Bowling Green, KY.

If you have any suggestions for improvements or new features, or would like to report a bug, please contact Hunter Goatley via e-mail at goathunter@WKUVX1.BITNET (preferred) or by phone at 502-745-5251.

You can get the new version via anonymous ftp from ftp.spc.edu; you'll need:

[.MACRO32]UNZIP.EXE

[.MACRO32.SAVESETS]SUPERVISOR.ZIP

To get it via e-mail, send the following commands in the body of a mail message to FILESERV@WKUVX1.BITNET:

SEND SUPERVISOR

SEND FILESERV_TOOLS

There's also a SUPSER-L mailing list that is described in the release notes (and/or the installation manual). I'd suggest you subscribe to it to you get announcements about the Supervisor Series.


The ModulaTor Forum

Five Minutes Poesie for Everyone: What is the Color of a Bit?

[Ed. note] The following article is in German. Too much of poetry would be lost by a translation into English.

Ellen sent the article to Max Sch~onherr in Apr-1992. Max moderates a radio emission call Zuendfunk, Bit Byte Gebissen, broadcasted by Bavarian Radio 2. Ellen tried to answer Max's famous question "What is the color of a bit?". Permission to publish this letter in the ModulaTor was granted. Thanks to Ellen for her contribution.

Die Farbe eines Bits?

Betreffend Ihre wiederholte Anfrage nach der Farbe eines Bits erlaube ich mir im folgenden, Ihnen meinen Versuch zur Beantwortung vorzulegen. Sollte die Frage inzwischen bereits zur allgemeinen Zufriedenheit gekl~art sein, bitte ich das weitere als gegenstandslos zu betrachten.

Zun~achst: Da Bits bekanntlich sehr scheu sind und sich einer direkten Observierung erfahrungsgem~a~s zu entziehen verm~ogen, bleibt nur ein deduktiver L~osungsansatz. Ich versuche also eine Schritt-fuer-Schritt- Ann~aherung.

1. Ein Bit kann zwei Zust~ande annehmen: "Strom" oder "Nicht Strom". Es scheint nun logisch die Anfangsfrage zu modifizieren: Welche zwei Farben kann ein Bit annehmen?

2. Essentiell fuer das Bit als solches ist also der Zustand "Strom" oder "Nicht Strom". Betrachten wir die folgende Tabelle von Wirkungen auf andere Elemente, determiniert durch die o.g. Zust~ande.


Element                "Strom"              "Nicht Strom"
__________________________________________________________________
Kuehlschrank             kalt                    warm
Herd                    warm                    kalt
Gluehbirne               hell                    duster
Radio                   laut                    still
Die Reihe lie~se sich erweitern, was jedoch fuer die zu ziehenden Schlu~sfolgerungen irrelevant ist. Die ~Uberpruefung der ersten beiden Elemente ergibt eine gegenseitige Aufhebung von Wirkungen, fuehrt also substantiell nicht weiter.

Das dritte Element mag eine m~ogliche Richtung weisen: hell und dunkel, oder, fuer Bits mit angeschlossenem SW-Monitor, wei~s und schwarz. Diese allzu offensichtliche L~osung mu~s jedoch deshalb verworfen werden, weil ein- und dasselbe Bit auch an verschiedene Farb-Monitore angeschlossen werden kann und damit die Zuweisung "Wei~s" und "Schwarz" nicht mehr zwingend ist.

Weiter tragend scheint das letzte Element der Tabelle: Hier werden "Strom" und "Nicht Strom" den Auswirkungen "laut" und "still" zugeordnet. Es sei an dieser Stelle ein Exkurs in die Philologie erlaubt, um die Schluessigkeit der Argumentationskette zu gew~ahrleisten.

Exkurs

Die Antagonismen "laut" und "still" lassen sich umformulieren in "Reden" und "Schweigen". Der Volksmund hat hier nun eine treffliche syn~asthetische Formel gefunden: "Reden ist silber, Schweigen ist gold". Es scheint verlockend, dies nun endlich ohne weiters Hinterfragen auf das Bit zu uebertragen - diesen Verlockungen sollte jedoch Widerstand geleistet werden, weitere Verifikationen sind n~otig:

- Kann ein Spruch aus den Tiefen des Volkslebens ueberhaupt Anwendung finden auf einen Gegenstand, der nachweislich erst so viel sp~ater realiter entstand als der Spruch selbst? Man ist versucht, dies zu verneinen, jedoch: Haben nicht Augusta Ada Byron und ihr Mitarbeiter Charles Babbage schon vor 1850 mit der Idee des Bit, mit dem virtuellen Bit also, recht erfolgreichen Umgang gepflegt? Was hindert die ~Uberlegung, da~s ein virtuelles Bit schon immer im Raum stand, nicht schlagend Farben tragend, einer Volksweisheit zug~anglich.

- Suchen wir weiter im reichen Schatz ueberlieferten Wissens, schlagen wir bei den Gebr. Grimm nach. Im M~archen vom klugen Schneiderlein begegnen uns weitere Farbenpaare: wei~s und schwarz (s.o.), braun und rot, und schlie~slich wiederum silbern und golden. In dem im genannten M~archen gestellten R~atsel stellt sich die Paarung "silbern und golden" als die rechte heraus, die hier im Zusammenhang mit den Haaren einer Prinzessin (welcher Zusammenhang hier zun~achst als irrelevant apostrophiert wird).

Auch an anderen Stellen in den von den Gebr. Grimm tradierten Volkserz~ahlungen lassen sich Belege fuer das Farbpaar "Silber und Gold" finden, das sich im Fortgang der Erz~ahlung als das rechte erweist, meist konnotiert von Begriffen wie Reichtum oder ganz einfach "Geld" finden.

Dies fuehrt geradewegs zu einer abschlie~senden Folgerung:

Aus dem oben gesagten ergibt sich eine hohe Wahrscheinlichkeit, da~s ein Bit, wie die kostbaren Haare einer Prinzessin, nur die Farben "silbern" und "golden" annehmen kann: Haben nicht viele Menschen, die einen nahen Umgang mit dem scheuen Bit pflegen, eine stark erh~ohte Affinit~at zu den Edelmetallen Gold und Silber gezeigt? Manche Garage wurde schlie~slich zun~achst zu einer Brutst~atte von Bits und infolgedessen zu einer Produktionsst~atte von Gold und Silber.

Gold und Silber - Geld - dies fuehrt uns zu der modifizierten Ausgangsfrage zurueck: Welche Farbe(n) hat ein Bit? Jede. Immer die Farbe des Geldes.

Immer in der Hoffung, Ihnen mit meinen ~Uberlegungen ein wenig dienlich gewesen zu sein zu k~onnen, bleibe ich

mit freundlichen Grue~sen

Ellen Friedel



IMPRESSUM: The ModulaTor is an unrefereed journal. Technical papers are to be taken as working papers and personal rather than organizational statements. Items are printed at the discretion of the Editor based upon his judgement on the interest and relevancy to the readership. Letters, announcements, and other items of professional interest are selected on the same basis. Office of publication. The Editor of The ModulaTor is Günter Dotzel; he can be reached at mailto:[email deleted due to spam]


Home | Site_index | Legal | OpenVMS_compiler | Alpha_Oberon_System | ModulaTor | Bibliography | Oberon[-2]_links | Modula-2_links |

Amazon.com [3KB] [Any browser]

Books Music Video Enter keywords...


Amazon.com logo

Webdesign by www.otolo.com/webworx, 16-Dec-1998