======================================================================= 1 ===
Date:    1 Apr 93 09:45:47 GMT
From:    os102@cl.cam.ac.uk (Oliver Stephens)
Subject: Re: thread operation

In article <1993Apr1.030018.616@uxmail.ust.hk>, clfung@cs.ust.hk (Fung Chi Leun
g) writes:
|> Hello,
|>   
|> 1.	When I call Usocket.accept(...) inside a thread, the
|> 	thread scheduler will hang up at the statement until
|> 	the Usocket.accept(...) is reutrn.  In my previous
|> 	testings on the thread opertaions, the scheduler will
|> 	pass the control to the other threads alternatively after
|> 	the time slice of each thread is expired.  However, the
|> 	the thread calling Usocket.accept will not be suspended
|> 	by the scheduler and the other threads do not have their
|> 	turns to run.
|> 
|> 	This problem is solved when I set the Usocket.accept(...) to
|> 	a non-blocking operation and the thread scheduler will work
|> 	properly.  I am curious that does the thread support blocking
|>         operations?  If not, what are the alternatives or necessary 
|> 	procedures can be used?
|> 

The problem with a blocking call like this is that the whole process is
suspended by the UNIX scheduler until the operation completes.  The M3 runtime
thread stuff does not know about this kind of blocking operation - the kind
that is due to the "wait" command.  You could teach it about the Unix "wait"
command, getting it to do a non-blocking wait to determine when the thread can
be re-activated, but the problem is many unix commands have a "wait" inside
them (like "system") - I'm not sure there are non-waiting equivalents of all
of these.

Below, I have included my solution to the problem that the "system" command
halts the process until completion.  I wrote this because I wanted to do
a "system" command at the response of a button press from a user interface,
but I didn't want the interface to hang until it was complete.  It may
give you some pointers.

DISCLAIMER: I only wrote this the other day - I am not convinced it is
            bomb-proof yet.

---+--- FILE Uwait.i3 ---+---

UNSAFE INTERFACE Uwait ;

(* stuff which should be in Uexec but isn't
   + mktemp() because I needed it
 *)

FROM Ctypes IMPORT Int, IntStar, CharStar, CharStarStar ;

<* EXTERNAL *> PROCEDURE waitpid(pid     : Int ;
                                 statusp : IntStar ;
                                 options : Int) : Int ;

<* EXTERNAL *> PROCEDURE mktemp(template : CharStar) : CharStar ;

CONST
  WNOHANG   = 1 ;
  WUNTRACED = 2 ;

END Uwait.

---+--- FILE SystemCmd.i3 ---+---

(* Author : Olly Stephens <os102@cl.cam.ac.uk> *)

INTERFACE SystemCmd ;

(* To use the UNIX "system" command, you usually have to turn off thread
   preemption.  Even if you don't have to do this, the "system" commmand
   does not return your process to its normal state until the command has
   been completed and so pre-emption is effectively turned off.  This
   interface provides a method of executing shell commands without
   forsaking preemption.

   There are two procedures - "Do" will execute the command given in
   "cmd" and returns the status.  "Start" starts off a similar execution
   but returns immediately.  It calls back on the "callback" closure when
   the command is complete - this is especially useful inside button action
   procedures of a user interface for example, because you want to minimise
   your time inside them as the VBT tree is locked on entry.

   The "Start" procedure returns the "Thread.T" which is performing the
   shell commands.  To abort the commands, alert the thread by calling
   "Thread.Alert".  To wait for completion of the commands (or of the
   aborting), call "Thread.Join".  The value returned by "Thread.Join"
   will be a "REF INTEGER" which holds the result of the execution.

   The result will be: -1 if the procedures failed to execute the commands
                       -2 if "wait" returns a negative value (check errno)
                       -3 if the shell was interrupted by a signal
                       -4 if the command was aborted (by Thread.Alert)
                        0 if the shell command succeeded
                        1..LAST(INTEGER) if the shell command failed
*)
         
IMPORT Thread ;

PROCEDURE Do(cmds : TEXT) : INTEGER ;

TYPE
  Callback = OBJECT
             METHODS
               done(result : INTEGER)
             END ;

PROCEDURE Start(cmds     : TEXT ;
                callback : Callback) : Thread.T ;

END SystemCmd.

---+--- FILE SystemCmd.m3 ---+---

UNSAFE MODULE SystemCmd ;

IMPORT Ctypes, Dir, FileStream, M3toC, RTThread, Thread, Time, Uexec, Unix,
       Usignal, Uwait, Word, Wr ;

TYPE
  Closure = Thread.Closure BRANDED OBJECT
              cmd      : TEXT ;
              callback : Callback := NIL
            OVERRIDES
              apply := Apply
            END ;

PROCEDURE Apply(c : Closure) : REFANY =
VAR file : TEXT ;
VAR fileS : Ctypes.CharStar ;
VAR wr : Wr.T ;
VAR argv := ARRAY [0..1] OF Ctypes.CharStar { NIL, NIL } ;
VAR waitstate, status, pid : INTEGER ;
VAR result := NEW(REF INTEGER) ;
BEGIN
  fileS := Uwait.mktemp(M3toC.CopyTtoS("/tmp/scXXXXXX")) ;
  file := M3toC.StoT(fileS) ;
  argv[0] := fileS ;
  TRY
    TRY
      wr := FileStream.OpenWrite(file) ;
      TRY
        Wr.PutText(wr, "#!/bin/sh\n\n") ;
        Wr.PutText(wr, c.cmd) ;
        Wr.PutChar(wr, '\n')
      FINALLY
        Wr.Close(wr) ;
        EVAL Unix.chmod(fileS, 8_700)
      END ;
      pid := Unix.vfork() ;
      CASE pid OF
        -1 => result^ := -1
      |  0 => RTThread.disallow_sigvtalrm() ;
              IF (Uexec.execv(fileS, ADR(argv)) < 0) THEN
                Unix.exit(1)
              ELSE
                <* ASSERT FALSE *>
              END
      ELSE
        REPEAT
          waitstate := Uwait.waitpid(pid, ADR(status), Uwait.WNOHANG) ;
          IF (waitstate = 0) THEN
            IF (Thread.TestAlert()) THEN
              EVAL Usignal.kill(pid, Usignal.SIGKILL) ;
              RAISE Thread.Alerted
            END ;
            Time.LongPause(5)
          END
        UNTIL (waitstate # 0) ;
        IF (waitstate < 0) THEN
          result^ := -2
        ELSE
          IF (Word.And(status, 16_7F) # 0) THEN
            result^ := -3
          ELSE
            result^ := Word.And(status, 16_FF00) DIV 16_80
          END
        END
      END
    FINALLY
      M3toC.FreeS(fileS) ;
      Dir.Delete(file)
    END
  EXCEPT
    Thread.Alerted =>
      result^ := -4
  ELSE
    result^ := -1
  END ;
  IF ((result^ # -4) AND (c.callback # NIL)) THEN
    c.callback.done(result^)
  END ;
  RETURN result
END Apply ;

PROCEDURE Do(cmd : TEXT) : INTEGER =
VAR result : REF INTEGER ;
BEGIN
  result := Thread.Join(Thread.Fork(NEW(Closure, cmd := cmd))) ;
  RETURN result^
END Do ;

PROCEDURE Start(cmd : TEXT ;
                callback : Callback) : Thread.T =
BEGIN
  RETURN Thread.Fork(NEW(Closure, cmd := cmd, callback := callback))
END Start ;

BEGIN
END SystemCmd.

------------------------------------------------------------------------- 
Olly Stephens                                oliver.stephens@cl.cam.ac.uk
Computer Laboratory
University of Cambridge    Loved you there and then, and now like a sheep
United Kingdom                                             - Van Morrison


======================================================================= 2 ===
Date:    1 Apr 1993 09:01:01 GMT
From:    laverman@cs.rug.nl (Bert Laverman)
Subject: SRC-m3 vs -O

If I remember correctly, there have been some problems with using
optimization on the C compiler pass, some versions ago. Is there
anybody using -O with the current version auccessfully? It would
save considerable on size of the libraries...

Bert
-- 
#include <std/disclaimer>

  Bert Laverman,  Dept. of Computing Science, Groningen University
  Friendly mail to: laverman@cs.rug.nl      The rest to: /dev/null


======================================================================= 3 ===
Date:    1 Apr 93 06:34:26 GMT
From:    tas@cs.uq.oz.au (Tasman Hayes)
Subject: new vbtkit and formsvbt docs on gatekeeper.dec.com

I don't seem to be able (to have access) to ftp the new
formsvbt and vbtkit documentation at gatekeeper.doc.com
in pub/DEC/Modula-3/contrib.

Do I have software problems OR are they not meant for
public consumption OR have their file permissions simply
been incorrectly set?

Thanks,
Tasman Hayes





======================================================================= 4 ===
Date:    1 Apr 93 10:20:28 GMT
From:    os102@cl.cam.ac.uk (Oliver Stephens)
Subject: Re: thread operation

In article <1993Apr1.094547.20409@infodev.cam.ac.uk>, os102@cl.cam.ac.uk (Olive
r Stephens) writes:
|> In article <1993Apr1.030018.616@uxmail.ust.hk>, clfung@cs.ust.hk (Fung Chi L
eung) writes:
|> |> Hello,
|> |>   
|> |> 1.	When I call Usocket.accept(...) inside a thread, the
|> |> 	thread scheduler will hang up at the statement until
|> |> 	the Usocket.accept(...) is reutrn.  In my previous
|> |> 	testings on the thread opertaions, the scheduler will
|> |> 	pass the control to the other threads alternatively after
|> |> 	the time slice of each thread is expired.  However, the
|> |> 	the thread calling Usocket.accept will not be suspended
|> |> 	by the scheduler and the other threads do not have their
|> |> 	turns to run.
|> |> 
|> |> 	This problem is solved when I set the Usocket.accept(...) to
|> |> 	a non-blocking operation and the thread scheduler will work
|> |> 	properly.  I am curious that does the thread support blocking
|> |>         operations?  If not, what are the alternatives or necessary 
|> |> 	procedures can be used?
|> |> 
|> 
|> The problem with a blocking call like this is that the whole process is
|> suspended by the UNIX scheduler until the operation completes.  The M3 runti
me
|> thread stuff does not know about this kind of blocking operation - the kind
|> that is due to the "wait" command.

Ooops.  Before I get flamed, I better change what I said.  I've just realised
that Leung is talking about "Usocket.accept" which is not bound by the "wait"
command.  What I said in my last message is correct for commands like
"system" so I don't regret saying it :-)

File and Socket based calls can be handled by the thread package through the
use of the RTScheduler.IOSelect or RTScheduler.IOAlertSelect.  These procedures
are functionally equivalent to the unix "select" command, except they do not
prevent other threads from running.

To quote from the "accept" man page:

       It is possible to select(2) a socket for the  purposes  of
       doing an accept() by selecting it for read.

------------------------------------------------------------------------- 
Olly Stephens                                oliver.stephens@cl.cam.ac.uk
Computer Laboratory
University of Cambridge    Loved you there and then, and now like a sheep
United Kingdom                                             - Van Morrison


======================================================================= 5 ===
Date:    Thu, 1 Apr 1993 03:00:18 GMT
From:    clfung@cs.ust.hk (Fung Chi Leung)
Subject: thread operation

Hello,
  
  Recently, I am developing a distrubuting system using M3 with
a lot of thread operations and I come across several questions about
the thread:  

1.	When I call Usocket.accept(...) inside a thread, the
	thread scheduler will hang up at the statement until
	the Usocket.accept(...) is reutrn.  In my previous
	testings on the thread opertaions, the scheduler will
	pass the control to the other threads alternatively after
	the time slice of each thread is expired.  However, the
	the thread calling Usocket.accept will not be suspended
	by the scheduler and the other threads do not have their
	turns to run.

	This problem is solved when I set the Usocket.accept(...) to
	a non-blocking operation and the thread scheduler will work
	properly.  I am curious that does the thread support blocking
        operations?  If not, what are the alternatives or necessary 
	procedures can be used?


2.	My second question is about the performance of the thread.
	Since I want to give higher priority ( in terms of CPU time )
	to some threads, I will call Thread.Yield( ) to pass the
	control from some lower priority threads to higher priority
	threads, but the performance of overall system does not
	match my expectation. :)
        Is there any comment on that?  Is it a right way to use
	Thread.Yield( ) in doing such priority tasks?  

3.	The last question is:
	Any hint of using thread operations efficiently?
	( other than the stuff covered in the System Programming 
	  book )


Thanks in advance.

Any reply would be highly appreciated.


--
Leung [ Chi-Leung Fung ] 
<< E-Mail: clfung@cs.ust.hk ## Phone: (852) 358 7023 >>


======================================================================= 6 ===
Date:    Thu, 1 Apr 93 18:04:29 GMT
From:    mjordan@src.dec.com (Mick Jordan)
Subject: Re: SRC-m3 vs -O

I can only speak for the DECstations, but I have found gcc v2.2 to be very reli
able
in its -O2 mode. In fact it is now my C compiler of choice, partly because the
Mips cc exhibits buggy behaviour on large programs. You get a factor of 2 speed
up
using -O2, and a noticeable reduction in code size.

Mick Jordan


======================================================================= 7 ===
Date:    Thu, 01 Apr 93 09:12:52 -0800
From:    mhb@src.dec.com
Subject: Re: new vbtkit and formsvbt docs on gatekeeper.dec.com


Yes, there are new versions of the VBTkit and FormsVBT manuals
in gatekeeper.pa.dec.com in pub/DEC/Modula-3/contrib. They 
seem to have the correct permissions:

% ls -l
-r--r--r--  1 root       503965 Mar 25 16:15 formsvbt.25Mar93.ps.Z
-r--r--r--  1 root       109243 Mar 26 14:57 formsvbt.AppC.26Mar93.ps.Z
-r--r--r--  1 root       241681 Mar 25 16:14 vbtkit.25Mar93.ps.Z

I just tried to ftp these files, and had no problems. If you are 
still having problems, send email to m3-request@src.dec.com. 

These files are not part of Modula-3/release; they are meant for 
semi-public consumption. We have made extensive changes to VBTkit 
and a slew of small changes to FormsVBT. We are using the new software 
here at SRC, and it will probably be part of the next release of 
M3 onto gatekeeper. Jim Meehan and I plan to freeze VBTkit and FormsVBT 
for the foreseeable future (of course, we'll make bug fixes and we 
encourage other people to add to both packages!). Part of freezing 
the software is to also freeze the documentation and publish it like 
the Trestle reference manual. Before doing so, we've asked a number 
of VBT-enthusiats to review the manuals. Storing them in Modula-3/contrib 
is the easiest way to make the documents available for non-DEC folks. 

Other people are welcome to look them over too, but, since they do 
not correspond to the released software, non-experienced VBT-hackers 
might have a difficult time with them. 

Marc


======================================================================= 8 ===
Date:    Thu, 1 Apr 1993 15:21:34 GMT
From:    dagenais@alberich.vlsi.polymtl.ca (Michel Dagenais)
Subject: Re: 1Mb Hello World...!? Is this normal?


Following the release of DEC SRC M3 2.07, shared libraries were discussed
on this newsgroup. I then believed that postprocessing libraries to make
them dynamic would reduce the possibilities of sharing memory, when two
or more m3 programs execute, but that the execution time would not be
affected. The recent postings led me to recompile eeeeeeverything from
scratch with real "position independent code" shared libraries.

The results are very interesting. The total elapsed time to compile,
link and run a 100 lines program that uses trestle (a very large library)
goes from 2:46 minutes to 50 seconds, mainly because of reduced i/o
and dynamic linking time. After all, a C++ program using InterViews would
probably take just about as much time even with a native compiler
because of the zillions of nested include files usually involved.

Modula3-2.07 with postprocessed libraries on a lightly loaded Sparc 2:

froh> time m3 -o DrawRect DrawRect.m3 -lm3ui -lm3X11R4 -lX11
26.9user 8.39system 2:00.06elapsed 28%CPU (0text+5405data 5320max)k
428inputs+79outputs (716major+3095minor)pagefaults 0swaps

froh> ls -als DrawRect
  80 -rwxrwxr-x   1 dagenais analyste    81920 Oct 15 17:27 DrawRect*

froh> time ./DrawRect
12.23user 2.23system 0:46.91elapsed 30%CPU (0text+4203data 4232max)k
38inputs+3outputs (385major+1230minor)pagefaults 0swaps


Modula3-2.11 with real shared libraries under pretty much the same conditions:

froh> time m3 -o DrawRect DrawRect.m3 -lm3ui -lm3X11R4 -lX11
24.74user 3.88system 0:40.66elapsed 70%CPU (0text+5904data 5764max)k
247inputs+26outputs (643major+2273minor)pagefaults 0swaps

froh> ls -als DrawRect
  64 -rwxrwxr-x  1 dagenais    65536 Apr  1 10:13 DrawRect*

froh> time ./DrawRect
2.80user 0.85system 0:10.22elapsed 35%CPU (0text+2459data 3744max)k
52inputs+1outputs (364major+454minor)pagefaults 0swaps
--
---------------------------------------------------------------------

Prof. Michel Dagenais			    dagenais@vlsi.polymtl.ca
Dept of Electrical and Computer Eng.
Ecole Polytechnique de Montreal		    tel: (514) 340-4029

---------------------------------------------------------------------


======================================================================= 9 ===
Date:    Thu, 1 Apr 93 17:42:53 GMT
From:    Eric Muller <muller@src.dec.com>
Subject: Modula-3 Frequently Asked Questions (FAQ)

Archive-name: Modula-3-faq
Last-modified: Apr 1 1993


		 Modula-3 Frequently Asked Questions
		 ===================================


1. The language
	1.1. What is Modula-3 ?
	1.2. Is Modula-3 a superset of Modula-2 ?
2. The documentation
	2.1. Where can I get a description of Modula-3 ? 
	2.2. Where can I get other information on Modula-3 ?
3. The implementations
	3.1. Where can I get an implementation ?
	3.2. What is SRC Modula-3 ?
	3.3. What is m3pc ?
	3.4. What is GNU Modula-3 ?
4. FTP
	4.1. What if I don't have ftp access ?
5. Contributing
	5.1. Can I contribute Modula-3 software ?




1.1. What is Modula-3 ?

   The goal of Modula-3 is to be as simple and safe as it can be while
   meeting the needs of modern systems programmers.  Instead of
   exploring new features, we studied the features of the Modula
   family of languages that have proven themselves in practice and
   tried to simplify them into a harmonious language.  We found that
   most of the successful features were aimed at one of two main
   goals: greater robustness, and a simpler, more systematic type
   system.

   Modula-3 descends from Mesa, Modula-2, Cedar, and Modula-2+.  It
   also resembles its cousins Object Pascal, Oberon, and Euclid.

   Modula-3 retains one of Modula-2's most successful features, the
   provision for explicit interfaces between modules.  It adds objects
   and classes, exception handling, garbage collection, lightweight
   processes (or threads), and the isolation of unsafe features.


1.2. Is Modula-3 a superset of Modula-2 ?

   No; valid Modula-2 programs are not valid Modula-3 programs.  However,
   there is a tool to help convert Modula-2 programs to Modula-3.


2.1. Where can I get a description of Modula-3 ? 
   
   The definition of Modula-3 is contained in:

        System Programming with Modula-3
        Edited by Greg Nelson
        Prentice Hall Series in Innovative Technology
        ISBN 0-13-590464-1
        L.C. QA76.66.S87 1991

   also known as SPwM3.  Here is the table of contents:

        1. Introduction
        2. Language Definition
        3. Standard Interfaces
        4. An Introduction to Programming with Threads
        5. Thread Synchronization: A Formal Specification
        6. I/O Streams: Abstract Types, Real Programs
        7. Trestle Window System Tutorial
        8. How the Language Got its Spots

   Chapters 2 and 3 have been reprinted in Sigplan Notices, Volume 27,
   Number 8, August 1992, pp 15-42.

   Sam Harbison has written a more tutorial book about Modula3:

        Modula-3
        Samuel P. Harbison
        Prentice Hall, 1992
        ISBN 0-13-596396-6

   The errata sheet is available via anonymous ftp from gatekeeper.dec.com 
   in pub/DEC/Modula-3/errata.


2.2. Where can I get other information on Modula-3 ?

   There is a Usenet newsgroup, comp.lang.modula3.  The archives of
   that group are available via anonymous ftp from gatekeeper.dec.com
   in pub/DEC/Modula-3/comp.lang.modula3.  If you do not have
   access to Usenet, there is a relay mailing list; send a message to
   m3-request@src.dec.com to be added to it.

   There are a couple high-level overview articles available:

        "Modula-3", Sam Harbison, Byte, Vol. 15, No. 12, November 1990,
        pp 385+.

        "Safe Programming with Modula-3", Sam Harbison, Dr. Dobb's Journal,
        Vol. 17, No. 10, October 1992, pp 88+.

   A description of the Modula-3 type system is in

        "The Modula-3 Type System", Luca Cardelli, Jim Donahue, Mick Jordan,
        Bill Kalsow, Greg Nelson, Conference Record of the Sixteenth Annual
        ACM Symposium on Principles of Programming Languages (POPL), Austin
        Texas, January 11-13 1989, pp 202-212.

   The Trestle window system toolkit and higher-level FormsVBT toolkit,
   available with Modula-3, are documented in the following reports:

        "Trestle Reference Manual", Mark S. Manasse and Greg Nelson,
        SRC Research Report 68, December 1991.

        "Trestle Tutorial", Mark S. Manasse and Greg Nelson, SRC Research
        Report 69, May 1, 1992.

        "The FormsVBT Reference Manual", Marc H. Brown and James R. Meehan,
        (soon to be SRC Research Report ??).

   These reports can be ordered by e-mail; send your request to
   src-reports@src.dec.com.


3.1. Where can I get an implementation ?

   Two implementations are available, SRC Modula-3 and a
   PC version of it (m3pc).  Work is also progressing on GNU Modula-3.


3.2. What is SRC Modula-3 ?

   SRC Modula-3 was built by the DEC Systems Reseach Center
   and is available via anonymous ftp from gatekeeper.dec.com in
   pub/DEC/Modula-3/release.

   The current version, 2.11, implements the language defined in SPwM3.
   There are versions for the following machines:

        AIX386  IBM PC running AIX/PS2,
        AP3000  Apollo DN4500 running Domain/OS
        ARM     Acorn R260 running RISC iX 1.21
        DS3100  DECstation 3100 and 5000 running Ultrix 4.0 and 4.2
        HP300   HP 9000/300 running HP-UX 8.0
	HPPA    HP 700/800 running HP-UX 8.0
        IBMR2   IBM R6000 running AIX 3.1, 
        IBMRT   IBM RT running IBM/4.3, 
        NEXT    NeXT running ?
	OKI     Okidata 7300 (i860) running AT&T SVR4.0
        SPARC   SPARCstation running SunOS 4.1.x
        SUN3    SUN3 running SunOS
	SUN386  Sun 386i  running SunOS 4.0.1
        UMAX    Encore Multimax running UMAX 4.3 (R4.1.1)
        VAX     VAX running Ultrix 3.1

   SRC Modula-3 includes a user manual, compiler, runtime library,
   some libraries and a few other goodies (see below).

   The compiler generates C as an intermediate language and should be
   fairly easy to port.  Except for the very lowest levels of the
   thread implementation, the entire system is written in Modula-3.


3.3. What is m3pc ?

   m3pc is available via anonymous ftp from gatekeeper.dec.com in
   pub/DEC/Modula-3/contrib/m3pc.

   From: laszlo@post.ifi.uni-klu.ac.at (Prof.Dr.Laszlo BOESZOERMENYI)
   Subject: M3 pn PC
   Date: 8 Mar 1993 13:13:52 GMT

   The Modula-3 system ported by us on the PC and available on the
   gatekeeper, runs with MSDOS, gnu c compiler and djgpp memory
   manager (detailed description in the read me file).

   You may compile, link and run Modula-3 programs, without threads.
   From the library modules only those are tested which are used by
   the compiler.  In the course of a student project a
   "student-friendly" environment is in development.  It will be
   available at end of June (hopefully).


3.4. What is GNU Modula-3 ?

   From: moss@cs.cmu.edu (Eliot Moss)
   Subject: GNU Modula-3 alpha release status
   Date: 25 Mar 93 17:53:12 GMT

   We said we'd try to get the initial (alpha) release of GNU
   Modula-3 out some time this month (March), and we're in the
   process of figuring out what to release and how to package it
   up. We expect to have something in roughly two weeks (watch
   this space for a notice).

   What would this be? First, it is a compiler for the VAX (only)
   under Ultrix (only), definitely without threads, and probably
   still failing a small number of the tests in the SRC test
   suite (which implies that not all of libm3 is likely to work
   either). The actual release information will detail more about
   what's working and what's not at that time. We DO currently
   pass all the compiler tests that the SRC compiler did when it
   was first released (i.e., the ones we fail are more obscure
   things that users uncovered over time).

   Second, the release itself will be a compressed tar file
   including sources and executables. The executables will
   probably work only if you put libraries, etc., in the expected
   places (otherwise, you'll need to rebuild from sources).The
   compiler is written in C and should be compiled with a recent
   version of gcc (so you'll need gcc installed). The system also
   uses gld (the GNU linker).

   This release should be most useful to people undertaking ports
   to other machines and operating systems, since it will give
   them a head start on understanding the compiler and getting
   the full system ready. It may be of some use for ordinary
   programming, but it really depends on whether you tend to use
   features that tickle the remaining bugs. We are indeed
   interested in alpha test reports, but only if they tell us
   something new (i.e., we'll provide a list of known
   deficiencies).

   When the release is made, we'll also start email discussions
   with the various parties who have indicated they might
   undertake ports, to help sort out who will do what.

   Regards, and thanks for your continued interest and
   encouragement -- EM


4.1. What if I don't have ftp access ?

   Unfortunately, we cannot deliver Modula-3 other than by 
   anonymous ftp.  

   Fortunately, Prime Time Freeware (PTF) includes Modula-3.  PTF is
   a set of two ISO-9660 CDroms filled with 3GB of freeware, issued
   semi-annually.  The latest issue, Volume 1, Number 2, July 1992,
   contains SRC Modula-3 2.07.  PTF is distributed via bookstores and
   mail.  You can reach PTF using:

	Email:  ptf@cfcl.com
        Fax:    [1] (408) 738 2050
        Voice:  [1] (408) 738 4832
        Mail:   Prime Time Freeware
 	        415-112 N. Mary Ave., Suite 50
		Sunnyvale, CA 94086
	        USA

5.1. Can I contribute Modula-3 software ?

   Certainly.  Send us what you are willing to share, be it programs,
   libraries or other things.  We'll put them in the distribution.

   Right now, the pub/DEC/Modula-3/contrib directory contains:

      m3rpc   an rpc system from Xerox Parc
      M2toM3  a translator from Modula-2 to Modula-3
      m3pc    an implementation of Modula-3 for PCs.
   


-- 
Eric.





======================================================================= 10 ===
Date:    1 Apr 1993 10:07:55 -0500
From:    Christian Schaepper <cschaepp@iiic.ethz.ch>
Subject: RESULT: comp.lang.oberon passes 237:17

                            comp.lang.oberon
                             R E S U L T S

Here are the results of the CFV on the creation of the comp.lang.oberon
newsgroup.

	votes cast:	254
	yes votes:	237 (93.3%)
	no votes:	 17 ( 6.7%)

The requirements for group creation are met and the new newsgroup can be
created after a waiting period of 5 days. During this waiting period the
net has a chance to correct any errors in the voter list appended below.

Thanks to anyone who cast a vote!

YES votes:
"A. Evers" <wbtt001@dutrun2.tudelft.nl>
aburke@BIX.com
adcmail!jasons@uu4.psi.com (Jason Smith)
Adrian Howard <adrianh@cogs.sussex.ac.uk>
aki@bnlux1.bnl.gov
alane@wozzle.linet.org (J. Alan Eldridge)
Alexander Tuninga <tuninga@statistik.tu-muenchen.de>
altmann@swe.uni-linz.ac.at
"(Andreas Garzotto)" <garzotto@swssai.uu.ch>
"(Andreas Margelisch)" <magi@swssai.uu.ch>
andrew%srsuna@srsuna.shlrc.mq.edu.au (Andrew McVeigh)
ATJBF%ASUACAD.BITNET@CEARN.BITNET (John Foster)
Barry Allebone <barry@frost.bain.OZ.AU>
Barry Cornelius <Barry.Cornelius@durham.ac.uk>
bbking!kgs@VFL.Paramax.COM
ben@nj8j.blackwlf.mese.com (Ben Coleman)
Bernhard Leisch <K3096E0@edvz.uni-linz.ac.at>
Bert Bos <bert@let.rug.nl>
biff@biff.jpunix.com (Dwight Everhart)
Bill Wallace <wewallac@watsol.uwaterloo.ca>
borchert@mathematik.uni-ulm.de (Andreas Borchert)
Boris Nordenstroem <boris@vis.inf.ethz.ch>
brent@rcx1.ssd.csd.harris.com (Brent Benson)
Brian Beattie <beattie@SSD.intel.com>
Brian Excarnate <aslakson@cs.umn.edu>
brueni@csgrad.cs.vt.edu (Dennis Brueni)
Cedric Didier Baechler <cbaechle@iiic.ethz.ch>
"Cheryl Lins" <cheryl_lins@quickmail.apple.com>
"(Christoph MALLOTH)" <malloth@lsesun4.epfl.ch>
claudio@amsoft.net.ch (Claudio Nieder)
Clemens Szyperski <szyperski@ICSI.Berkeley.EDU>
clerc@gla.ecoledoc.ibp.fr
cond@hyperion.lsi-j.co.jp (Yoshiyuki KONDO)
Conor O'Neill <conor@inmos.co.uk>
<Crelier@cs.inf.ethz.ch>
cspt@giraffe.ru.ac.za (Pat Terry)
Curlen H. Phipps <phipps@cis.ohio-state.edu>
CZSORO@zcvx00.decnet.ascom.ch
d90-awe@nada.kth.se
David Derbes <derbes@uhuru.uchicago.edu>
"David M. Brumley" <dmb@srl.cacs.usl.edu>
David.Sims@UC.Edu (David Sims)
Denisov  Andrey <andy@isi.itfs.nsk.su>
Dennis Michl <dmichl@iiic.ethz.ch>
Dirk Muysers <muysers@capsogeti.fr>
dm_devaney@pnlg.pnl.gov
Dmitry Sagatelyan <Dima@growth.msk.su>
dnord@cs.gmu.edu (David J. Nordstrom)
Douin Jean Michel <douin@cnam.cnam.fr>
dov@menora.weizmann.ac.il (Dov Grobgeld)
eberhard@vptt.ch
Edin Hodzic <dino@ready.eng.ready.com>
elidriss@enserb.u-bordeaux.fr ((Elho) ELIDRISSI)
epl@world.std.com (Edward P Luwish)
eric blair hanneken <hanneken@cis.ohio-state.edu>
Eric Stechmann - SP <els@puck.zycad.com>
erv@everest.tandem.com (E. Videki)
euzebio@dcc.unicamp.br (Marcos J. C. Euzebio)
ezavada@rucs2.sunlab.cs.runet.edu
"(Fernando D. Mato Mira)" <matomira@ligsg15.epfl.ch>
fld@informatik.uni-bremen.de (Guenter Feldmann)
foulques@email.teaser.com ( dominik  latouche)
<Franz@cs.inf.ethz.ch>
frings@mathematik.uni-ulm.de (Astrid Frings)
frode@toaster.SFSU.EDU (Frode Odegard)
FSSPR@acad3.alaska.edu
geser@ares.informatik.uni-ulm.de
gesswein@pcpool1.informatik.uni-ulm.de
ggw@wolves.Durham.NC.US (Gregory G. Woodbury)
grabert@mathematik.uni-ulm.de (Matthias Grabert)
"Greg (G.T.) Stovall" <gstovall@bnr.ca>
<Griesemer@cs.inf.ethz.ch>
gsc@coombs.anu.edu.au (Sean Case)
Guenter Dotzel <100023.2527@CompuServe.COM>
guenter@prism.gatech.edu (Brian Guenter)
<Gutknecht@cs.inf.ethz.ch>
gwg@salmon.aux.apple.com (Gene Garbutt)
halpin@vsg1.dsg.dec.com (Stephen E. Halpin)
Hans Eberle <eberle@src.dec.com>
Hans J. Froehlich <froehlich@swe.uni-linz.ac.at>
"(Hansjakob Emch)" <hajo@swssai.uu.ch>
hartmut@oberon.nbg.sub.org (hartmut Goebel hartmut Goebel)
Hasse Haitto <haitto@nada.kth.se>
<Hausner@cs.inf.ethz.ch>
hausutzu@chamber.in-berlin.de (Utz-Uwe Haus)
"Heberto Ghezzo" <heberto@christie.Meakins.McGill.CA>
<Heeb@cs.inf.ethz.ch>
<Heuberger@cs.inf.ethz.ch>
<Hiestand@cs.inf.ethz.ch>
holger@lsd.nbg.sub.org (Holger Mitterwald)
HSSEMMIB%CPHKVX.BITNET@CEARN.BITNET
"J. Adrian Zimmer" <jazimmer@cs.UND.NoDak.Edu>
jaime@afs.com
Jarmo Pussinen
jds@cs.UMD.EDU (James da Silva)
jeffo@uiuc.edu (J.B. Nicholson-Owens)
"Jeffrey R. Brown" <jeffrey.r.brown@inst.medtronic.com>
jerry.bujas@itc.univie.ac.at (Jerry Bujas (gst))
jjan@cs.rug.nl (Beeblebrox)
"Joachim Michely" <michely@deliah.nemeter.dinoco.DE>
joel@pa.dec.com (Joel McCormack)
"Jon. Hallett" <J.J.Hallett@ecs.southampton.ac.uk>
Jordan Henderson <jhenders@SEI.CMU.EDU>
jordan@uniblab.aero.org (Larry M. Jordan)
Josef Templ <templ@inf.ethz.ch>
jpg@ee.edinburgh.ac.uk
jpussi@cs.joensuu.fi (Jarmo Pussinen)
Jyrki J Wahlstedt <jwa@vipunen.hut.fi>
kardaras@ecn.purdue.edu (George S Kardaras)
katcher@netcom.com (Jeff Katcher)
"Kevin R. Coombes" <krc@wam.umd.edu>
kluge@avalon.physik.unizh.ch (kluge daniel)
knapp@cs.purdue.edu (Edgar Knapp)
Kristian Butorac <butorac@informatik.tu-muenchen.de>
krumke@cs.albany.edu (Sven Oliver Krumke)
ksackett@cs.uah.edu (Karl R. Sackett)
laffra@watson.ibm.com (C.Laffra)
larry@titan.tsd.arlut.utexas.edu (Larry Maturo)
lchen@ponder.csci.unt.edu (Lee Li-Jen Chen)
lendecke@namu01.gwdg.de (Volker Lendecke EIFFEL)
lima!lima-3!reh@uu5.psi.com (Rich Hoffarth)
longjohn@adnovum.ch (Stefan Wengi)
<Ludwig@cs.inf.ethz.ch>
lvin@vucnit.voronezh.su
lytras@avalon.physik.unizh.ch (Apostolos Lytras)
maartenb@na47sun05.cern.ch (Maarten Ballintijn)
mani@ppvku.ericsson.se (Markus Nikolopoulos)
Manuel Eduardo Correia <mcc@ciup1.ncc.up.pt>
Marc Brandis <brandis@inf.ethz.ch>
Marcel Waldvogel <marcel@nice.usergroup.ethz.ch>
Mark Skipper <mcs@de-montfort.ac.uk>
Markus Geltz <Geltz@informatik.uni-stuttgart.de>
martin@mathematik.uni-ulm.de (Martin Hasch)
martino@alseng.boeing.com
matt@amex-trs.com (The Libertarian Underground)
"Matthew (M.) Holiday" <holiday@bnr.ca>
Matthias Neeracher <neeri@iis.ee.ethz.ch>
matwood@peruvian.cs.utah.edu (Mark Atwood)
Maximilian Spring <sepp@cs.tu-berlin.de>
mcbreen@wg.estec.esa.nl
mcintosh@ccwf.cc.utexas.edu (aubrey mcintosh)
mdt26@cas.org (Ming-Ding Tsao)
Michael John Haertel <mike@skinner.cs.uoregon.edu>
mich@trl.mei.co.jp
mikeg@psg.com (Mike Gallo)
mjl@cs.rit.edu (Michael J Lutz)
<Moessenboeck@cs.inf.ethz.ch>
Nedorya Alexey <ned@isi.itfs.nsk.su>
neurogen@reks.uia.ac.be (Neurogenetica)
norman@bellcore.com (Norman Ramsey)
Paolo Bucci <bucci@cis.ohio-state.edu>
pareto!steffan@wupost.wustl.edu (Mike Steffan)
Patrick Saladin <psaladin@iiic.ethz.ch>
Paul McRae <mcrae@gaul.csd.uwo.ca>
Paul Prescod <papresco@undergrad.math.uwaterloo.ca>
Paul.Tvete@ii.uib.no
pcroom-user@ntucc-pcroom.ntu.edu.tw
Peter Hertel <PHERTEL@dosuni1.rz.Uni-Osnabrueck.DE>
peter@ficc.ferranti.com (Peter da Silva)
<Pfister@cs.inf.ethz.ch>
"pfterry" <pfterry@MSMail.kgs.ukans.edu>
pjc@luke.ATdiv.Lanl.GOV (Paul J. Channell)
ploesch@swe.uni-linz.ac.at
pomberger@swe.uni-linz.ac.at
pshuang@Athena.MIT.EDU
psp@spectrospin.ch (Panagiotis Spiliopoulos)
pwau@alcbel.be (Patrick Wauters)
R James Noble <kjx@comp.vuw.ac.nz>
Ralf Bauer <nathan@cs.tu-berlin.de>
"Ramon E. Pereda" <rpereda@cs.arizona.edu>
randy@psg.com (Randy Bush)
Ray Jackson <raj@halcyon.halcyon.com>
reinhold@swe.uni-linz.ac.at
"Rett Bull, Pomona College" <RBULL@POMONA.CLAREMONT.EDU>
Richard Hable <K3027E7@edvz.uni-linz.ac.at>
Rick Moore <rickm@gethen.com>
Rik Watson <watson@futurs.enet.dec.com>
"R.J.D.Elias" <R.J.D.Elias@fel.tno.nl>
"(Robb Nebbe)" <nebbe@lglsun.epfl.ch>
Robert Cowell <rgc@stats.ucl.ac.uk>
rod@cosc.canterbury.ac.nz (R. Harries)
Roger Vossler <vossler@csn.org>
rohm@mpimfhd.mpimf-heidelberg.mpg.de (Klaus Rohm)
romu@spectrospin.ch (Roger Mueller)
rose@cs.wisc.edu (Scott Rose)
rschnapp@metaflow.com (Russ Schnapp)
rschoen@mathematik.uni-ulm.de (Reinhard Schoen)
ruess@ares.informatik.uni-ulm.de (Harald Ruess)
sametinger@swe.uni-linz.ac.at
schauler@mathematik.uni-ulm.de (Markus Schauler)
schiffer@swe.uni-linz.ac.at
schramm@prosun.first.gmd.de (Andreas Schramm)
sclafani@netcom.com (Michael Sclafani)
sibrahim@cs.usc.edu (Shahril Ibrahim)
stanglow@mathematik.uni-ulm.de (Werner Stanglow)
Stefan Esser <se@ParC02.mi.Uni-Koeln.DE>
Stefan Odendahl <sodendah@iiic.ethz.ch>
stefan@fostam.nbg.sub.org (Stefan Stammler)
"(Stelio Tzonis)" <stelio@lysis.ch>
stephan@stack.urc.tue.nl (Stephan Eggermont)
stewartg@ERE.UMontreal.CA (Stewart Gilles)
stritzinger@swe.uni-linz.ac.at
<Supcik@cs.inf.ethz.ch>
swg@mathematik.uni-ulm.de (Franz Schweiggert)
T0FG000 <T0FG@unb.ca>
thacker@src.dec.com
Thomas F. Reid <reid@vtopus.cs.vt.edu>
Thomas Ingold <tingold@iiic.ethz.ch>
"Thomas J. Herbert" <THERBERT@umiami.IR.Miami.EDU>
Thomas Wainwright <tcwain@u.washington.edu>
thutt <thutt@MAIL.CASI.NASA.GOV>
"Todd A. Proebsting" <todd@cs.arizona.edu>
tomk@ee.edinburgh.ac.uk
Tony Sloane <tony@riker.cs.colorado.edu>
Toshinori.Maeno <tmaeno@cc.titech.ac.jp>
troyer@ips.id.ethz.ch
TSOS@uni-duesseldorf.de (Detlef Lannert)
uli@decum.enet.dec.com (uli@decum.enet.dec.com)
Ulrich Hoffmann <uho@informatik.uni-kiel.dbp.de>
ulrich@mips.complang.tuwien.ac.at (Ulrich Neumerkel)
Urs Blum <ublum@iiic.ethz.ch>
vev@vevdec.cs.murdoch.edu.au (Val Veraart)
vilva@viikki21.helsinki.fi (VEIJO VILVA (KEJAL))
"(Vincent Kohler)" <kohler@di.epfl.ch>
wald@mathematik.uni-ulm.de (Bernd Waldbauer)
wald@theory.lcs.mit.edu (David Wald)
walische@mathematik.uni-ulm.de (Hanno Walischewski)
wbirkhol@mathematik.uni-ulm.de (Detlef Birkholz)
wfugmann@mathematik.uni-ulm.de (Andreas Fugmann)
whitney@christie.Meakins.McGill.CA (Whitney de Vries)
WI00227@wipool.wifo.uni-mannheim.de
<Wirth@cs.inf.ethz.ch>
wnj@indigo.hobby.nl (Willy Jacobs)
Wolfgang Pree <wolfgang@amadeus.wustl.edu>
wrc@cs.rit.edu (Warren R Carithers)
x920031@bus072.rz.ruhr-uni-bochum.de (Jost Krieger)
yeung@cse.ogi.edu (Woodrow Yeung)

NO votes:
claude@trc.mew.mei.co.jp (Claude Huss)
emcguire@intellection.com (Ed McGuire)
"Eric J. Olson" <ejo@kaja.gi.alaska.edu>
Igor Metz <metz@iam.unibe.ch>
Marc Moorcroft <smarry@zooid.guild.org>
mhpower@Athena.MIT.EDU
owens@cookiemonster.cc.buffalo.edu (Bill Owens)
peirce@gumby.cc.wmich.edu (Leonard J. Peirce)
Peter Hermann <ph@ica.uni-stuttgart.dbp.de>
"Phil Scadden, Scadden Research" <mdlcpgs@lhn.gns.cri.nz>
rick@crick.ssctr.bcm.tmc.edu (Richard H. Miller)
Roland Kaltefleiter <kaltef@theo-physik.uni-kiel.dbp.de>
srogers@tad.eds.com (Steve Rogers)
Stephen Lau <lau@ai.sri.com>
tchannon@black.demon.co.uk (Tim Channon)
tkoppel@cassandra.cair.du.edu (Ted Koppel)
trier@slc6.INS.CWRU.Edu (Stephen C. Trier)


======================================================================= 11 ===
Date:    Fri, 2 Apr 93 01:05:20 GMT
From:    steveg@src.dec.com (Steve Glassman)
Subject: Re: Why are exceptions not resumable?

First, there were very few uses of resumable exceptions in Mesa.  
As I recall, most could be recoded by catching the exception and 
retrying or by handling a specific condition with a direct procedure
call.

In large, multi-threaded programs it was hard to resume an exception
because the system was not in a known/clean state while the exception
was being handled before being resumed.  

For instance, the procedure that is prepared to handle the exception, 
makes a call on a procedure that acquires locks, makes more procedure
calls, etc.  Eventually, some descendant of that call raises 
the exception which is to be handled.  Unfortunately, the caller can 
not know (in general) what the state of the system is (for locks, 
resources, invariants, etc) and thus can't safely fix the condition.

If the exception is caught and reraised, then all intervening procedures
(should) have restored the state to a point where the condition can 
be fixed and the operation retried.  Alternatively, when the caller/raiser
is a small predetermined set then the raiser and caller
can cooperate (via a direct call on some procedure that understands
the current stata) to fix the condition and (logically) resume.

In gneral, the Mesa exception model had a lot of complexity that 
has been deemed unnecessary for Modula-3.

Steve


======================================================================= 12 ===
Date:    Thu, 1 Apr 1993 19:42:42 GMT
From:    wunder@hpl.hp.com (Walter Underwood)
Subject: Why are exceptions not resumable?

I've been looking at Modula-3, and I noticed a feature that was in
Mesa, but is not in Modula-3: the ability to for a handler to cause
execution to resume after the RAISE.

I don't have a burning need to do this, but I'm curious whether it was
left out for a particular reason.  I can make guesses: it wasn't used
by Mesa programmers, it increases the coupling between modules, etc.

So, was there a rationale, and if so, what was it?

wunder



======================================================================= 13 ===
Date:    1 Apr 93 11:40:19
From:    vixie@pa.dec.com (Paul A Vixie)
Subject: Re: new vbtkit and formsvbt docs on gatekeeper.dec.com

> Yes, there are new versions of the VBTkit and FormsVBT manuals
> in gatekeeper.pa.dec.com in pub/DEC/Modula-3/contrib. They 
> seem to have the correct permissions:

that's gatekeeper.dec.com.  just fyi.
--
Paul Vixie, DEC Network Systems Lab	
Palo Alto, California, USA         	"Don't be a rebel, or a conformist;
<vixie@pa.dec.com> decwrl!vixie		they're the same thing, anyway.  Find
<paul@vix.com>     vixie!paul		your own path, and stay on it."  -me


======================================================================= 14 ===
Date:    2 Apr 1993 12:44:22 GMT
From:    mead@bucknell.edu (Jerry Mead)
Subject: Modula3 texts


Yesterday I was visited by a rep from one of the large text book publishers.
In the course of our conversation he noticed my copy of Harbison's book.
He hadn't heard of Modula3.  He asked if there were any introductory CS
texts using Modula3 - I told him there were none but that I thought it
wouldn't be difficult to convert one of the many Modula2 texts to a Modula3
version.  Do any of you know whether there are any publishers persuing this
direction?  

---------------------

Jerry Mead
Dept of Computer Science
Bucknell University
Lewisburg, PA 17837
mead@bucknell.edu



======================================================================= 15 ===
Date:    Thu, 1 Apr 1993 20:28:28 GMT
From:    mg@elan (Michael Golan)
Subject: Re: Debuggers

meehan@src.dec.com writes:

>There isn't a specific M3 debugger; since the released compiler generates 
>C code, we use dbx or gdb. Not great, but better than nothing. Here
>are some tips:

[good tips deleted]

If you use gdb, you might want to get and install Duel, a special language
for debugging. Duel is designed specifically for C, but if you use the C
mode for gdb's "print" you are better off with Duel (which links in with gdb
to add a single new command, "dl"). As a simple example, the following
code would print the positive elements of array mymodule.x.

(gdb) dl x__mymodule[1..100] >? 0

Below is some farther information on how to get Duel and what it does.
Duel is about 6000 lines of C code that is gdb-independent and in 
the public domain (not GNUish), so you can port it to other debuggers.
Because Duel is small and self contained, it will probably be easier to
"teach" duel about M3 name demangling, open arrays, etc., then to teach gdb.

If you get/try duel, please (please!) drop me a line with any comments,
good or bad.

-- Michael Golan
   mg@cs.princeton.edu

-----------------------------------------------------------------------------
DUEL -  A high level language for debugging C programs.
-----------------------------------------------------------------------------

Duel is a special purpose language designed for concise state exploration 
of debugged C programs under existing debuggers. It lets you to explore 
the program's state better than either the debugger's commands, a C 
interpreter, or print statements added to your code. The debugger is 
extended with the new 'dl' command for Duel expressions, e.g.,

     gdb> dl x[0..10].level >? 5
     x[3].level = 14
     x[8].level = 6

prints the "level" fields of array elements x[0] to x[10] that are greater 
than 5.  The output includes the values 14 and 6, as well as their 
symbolic representation "x[3].level" and "x[8].level". Linked list and
other complex data structures are just as easy. Most of C (e.g. for, if)
is also supported, e.g., int i; for(i=0; i<11; i++) if(x[i].level>5) x[i].

Duel is debugger-independent, but the current distribution interfaces only
with gdb. You will need the source for gdb-4.6, 4.7 or 4.8. All supported
gdb environments should work with Duel. It was tried at least on dec/mips,
sparc, sgi/iris, sony, hp9000, aix/rs6000, and sysV. Duel is public 
domain code. Do whatever you like with it - add it to commercial debuggers, 
to dbx/sdb or even make it part of the GNU project. No part of this 
distribution contains any copyright or derived code, (i.e. no GPL code, 
either). No disclaimer - free public domain software don't need one!
Even if you don't normally use debuggers, but you are programming in C, give
Duel a try! The man page & help even include a summary of useful gdb commands.

Duel is available for anonymous ftp from ftp.cs.princeton.edu, in 
/duel/duel.tar.Z. A "tar.Z" format means you should use the command
 "zcat duel.tar.Z | tar xf -" to unpack the files.
The Usenix Jan/93 paper about Duel is also available as tech report 399,
in /reports/1992/399.ps.Z on ftp.cs.princeton.edu

DUEL is "Debugging U (might) Even Like" or "Don't Use this Exotic Language"
you should judge which is better!

Michael Golan
mg@cs.princeton.edu
-----------------------------------------------------------------------------
The tutorial part from the manual page follows:

     Duel is based on expressions which return	multiple  values.   The  x..y
     operator  returns	the  integers from x to y; the x,y operator returns x
     and then y, e.g.

     gdb> dl (1,9,12..15,22)

     prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can be  used	wher-
     ever a single value is used, e.g.

     gdb> dl x[0..99]=0 ;

     assigns zero to the first 100 elements of array x. The semantics of x[i]
     are  the  same as in C. They are applied for each of the values returned
     by 0..99, which can be thought of as  an  implied	external  loop.   The
     trailing  semicolon  indicates evaluation for side-effects only, with no
     output. Duel incorporates C operators, casts  C  statements  as  expres-
     sions, and supports limited  variable declaration:

     gdb> dl int i;for(i=0;i<100;i++)
		      if(x[i]<0) printf("x[%d]=%d\n",i,x[i]);
     x[7] = -4

     The semicolon prevents Duel output; only output from printf is  printed.
     Aliases  are  defined  with  x:=y and provide an alternative to variable
     declaration. We could also return x[i] instead of using printf:

     gdb> dl if(x[i:=0..99]<0) x[i]
     x[i] = -4

     The symbolic output "x[i]" can be fixed by surrounding i with {}, i.e.

     gdb> dl if(x[i:=0..99]<0) x[{i}]
     x[7] = -4

     The {} are like (), but force the symbolic evaluation to use i's  value,
     instead  of  "i". You can usually avoid this altogether with direct Duel
     operators:

     gdb> dl x[..100] <? 0
     x[7] = -4

     The ..n operator is a shorthand for 0..n-1, i.e. ..100 is	the  same  as
     0..99.   The x<?y, x==?y, x>=?y, etc., operators compare their left side
     operand to their right side operand as in C, but return  the  left  side
     value  if	the  comparison  result is true. Otherwise, they look for the
     next values to compare, without returning anything.

     Duel's x.y and x->y allow an expression y, evaluated under x's scope:

     gdb> dl emp[..100].(if(code>400) (code,name))
     emp[46].code = 682
     emp[46].name = "Ela"

     The if() expression is evaluated under the  scope	of  each  element  of
     emp[], an array of structures. In C terms, we had to write:

     gdb> dl int i; for(i=0; i<100 ; i++)
	   if(emp[i].code>400) emp[{i}].code,emp[{i}].name

     A useful alternative to loops is the x=>y operator.  It  returns  y  for
     each value of x, setting `_' to reference x's value, e.g.

     gdb> ..100 => if(emp[_].code>400) emp[_].code,emp[_].name

     Using `_' instead of `i' also avoids the  need  for  {i}.	Finally,  the
     x-->y  operator  expands lists and other data structures. If head points
     to a linked list threaded through the next field, then:

     gdb> dl head-->next->data
     head->data = 12
     head->next->data = 14
     head-->next[[2]]->data = 20
     head-->next[[3]]->data = 26

     produce the data field for each node in the list. x-->y returns x, x->y,
     x->y->y,  x->y->y->y,  ...  until	a  NULL is found. The symbolic output
     "x-->y[[n]]" indicates that ->y was applied n times. x[[y]] is also  the
     selection operator:

     gdb> dl head-->next[[50..60]]->data

     return the 50th through the 60th elements in the list. The #/x  operator
     counts the number of values, so

     gdb> dl #/( head-->next->data >? 50 )

     counts the number of data elements over 50 on the list.

[There is a lot more in the full manual. Cyclic lists, strings, arrays like
argv, etc]
---------------------------------------------------------------------------


======================================================================= 16 ===
Date:    2 Apr 93 08:38:56 GMT
From:    os102@cl.cam.ac.uk (Oliver Stephens)
Subject: Re: SRC-m3 vs -O

In article <1peb0d$33p@rug4.cs.rug.nl>, laverman@cs.rug.nl (Bert Laverman) writ
es:
|> If I remember correctly, there have been some problems with using
|> optimization on the C compiler pass, some versions ago. Is there
|> anybody using -O with the current version auccessfully? It would
|> save considerable on size of the libraries...
|> 

With version 2.11, SPARC cc works fine with -O.  DEC cc doesn't (I tried
building the compiler but it crashes straight away complaining about a
very large negative open array size.)  Compiling on the DECs with no
options (ie. neither -g or -O) works fine and seriously reduces the
size of things.  I haven't tried gcc - perhaps I should.  I guess I
presume it to be a slower compiler - people seem to be just as bothered
at speed of compilation as they are at size of output around here - but
then when you've got 100 undergraduates all compiling FormsVBT programs,
there's not much I can do about turnaround time :-)

------------------------------------------------------------------------- 
Olly Stephens                                oliver.stephens@cl.cam.ac.uk
Computer Laboratory
University of Cambridge    Loved you there and then, and now like a sheep
United Kingdom                                             - Van Morrison


======================================================================= 17 ===
Date:    Fri, 02 Apr 93 09:31:02 -0800
From:    mhb@src.dec.com
Subject: Re: Modula3 texts


On a related matter, Bob Sedgewick just completed "ALGORITHMS IN 
MODULA-3", and the camera-ready copy is someplace between Princeton, 
Palo Alto, Mountain View, and Reading as I type. This book is for 
a 2nd or 3rd semester course concentrating on algorithms and data 
structures, not intro programming. It should be available in 6-8 
weeks. 

There's a project here at SRC to prepare a slew of algorithm animations 
corresponding to the key algorithms in that text. A feel for what's 
planned is available on gatekeeper.dec.com in the Modula-3 distribution. 



======================================================================= 18 ===
Date:    2 Apr 93 19:16:32 GMT
From:    mday@jukebox.lcs.mit.edu (Mark Day)
Subject: Re: Why are exceptions not resumable?


   wunder@hpl.hp.com (Walter Underwood) writes:

   I've been looking at Modula-3, and I noticed a feature that was in
   Mesa, but is not in Modula-3: the ability to for a handler to cause
   execution to resume after the RAISE.

   I don't have a burning need to do this, but I'm curious whether it was
   left out for a particular reason.  I can make guesses: it wasn't used
   by Mesa programmers, it increases the coupling between modules, etc.

   So, was there a rationale, and if so, what was it?

Modula-3 exceptions are similar to CLU exceptions, since both
languages have a termination model and neither language allows signals
to propagate through multiple levels of abstraction.  You might
find it interesting to read the rationale for the CLU model:

Barbara Liskov and Alan Snyder, "Exception Handling in CLU." IEEE
Transactions on Software Engineering 5(6): 546-558 (November 1979).

--Mark Day

mday@lcs.mit.edu


======================================================================= 19 ===
Date:    Fri, 2 Apr 1993 21:45:10 GMT
From:    emery@goldfinger.mitre.org (David Emery)
Subject: Re: Why are exceptions not resumable?

There's also a discussion of this in the Ada rationale, as Ada has
similar "abandonment" semantics.  On the other hand, Ada exceptions
*do* propogate through multiple levels of abstractions, and there is
no requirement for an Ada subprogram to explicitly identify the
exceptions that it can raise.
				dave


======================================================================= 20 ===
Date:    Fri, 2 Apr 93 23:23:49 CST
From:    lampman@fullfeed.com (Ray Lampman)
Subject: Re: Modula-3 Frequently Asked Questions (FAQ)

Please also cross-post this FAQ to "comp.answers", thankx much, Ray.
-- 
Ray.Lampman@FullFeed.Com ,^-_  FullFeed provides public access to
FullFeed Communications  L   `; Usenet news and E-mail, plus UUCP
Madison, WI 53704, USA   \ . J    connections to the Madison area
voice +1 608 246 4239     L__]   data +1 608 246 2701 login guest


======================================================================= 21 ===
Date:    Sun, 4 Apr 1993 22:45:12 GMT
From:    moss@cs.cmu.edu (Eliot Moss)
Subject: Re: efficiency of open arrays

There's a reasonably obvious reason this might be happening. In the fixed
array case, since the FOR loop bounds are static and within the array, it is
not too hard to eliminate bounds checks -- I suspect the SRC compiler does it,
and I'm pretty sure the GNU one will in this case, too. In the open array
case, the size information is carried by the specific value (the NEW array),
not in the type of the variable, and requires more sophisticated analysis to
enable the bounds checks to be removed. If you nreally need open arrays,
you'll probbaly have the bounds checks anyway, and will not be able to get the
higher speed loop.

Improving array access performance by eliminating needless checks is something
all the compiler writers have on their agenda, but I can't promise great
solutions soon .....						EM
--

J. Eliot B. Moss, Associate Professor	Visiting Associate Professor
Department of Computer Science		School of Computer Science
Lederle Graduate Research Center	Carnegie Mellon University
University of Massachusetts		5000 Forbes Avenue
Amherst, MA  01003			Pittsburgh, PA  15213-3891
(413) 545-4206, 545-1249 (fax)		(412) 268-6767, 681-5739 (fax)
Moss@cs.umass.edu			Moss@cs.cmu.edu


======================================================================= 22 ===
Date:    5 Apr 1993 22:09:19 GMT
From:    joel@decwrl.dec.com (Joel McCormack)
Subject: Re: efficiency of open arrays

Actually, there is absolutely no reason for bounds checks of open arrays
not to be moved from within a FOR loop to outside the loop.  It is, in
fact, exactly the same code as moving constant bounds checks, but you
load variables instead of constants where the check is moved outside the
loop.  To do this for FOR loops requires none of the more complex 
analysis that code movement out of loops in general requires.

In the examples from Chris Thewalt's message, the version without open
arrays makes it easy to remove the bounds checks completely, as they
can be done at compile time.  A smart compiler might be able to do so
with the open array version as is.  If instead of using ``Num_iter'' or
``Num_size'' as a limit he had used ``HIGH(xxx)'' a less smart compiler
could remove the bounds tests completely without much trouble.  But
even if the compiler didn't bother, it wouldn't matter: the loops
execute 1000 and 10000 times, anyway, so as long as you don't do bounds
checking EACH ITERATION you'd be fine.

I'm sure that the SRC people doing M3 compilers noticed the ``it is now
obvious that the open array overhead makes the use of Modula3 impossible''
in Chris Thewalt's message.  Knowing Bill, they'll probably do something
about it, too, if they haven't already.

This is a compiler problem, not a Modula-3 problem.  The WRL Modula-2
compiler had no trouble moving these types of bounds checks out of
FOR loops.

-- 
- Joel McCormack (decwrl!joel, joel@decwrl.dec.com)


======================================================================= 23 ===
Date:    5 Apr 93 21:04:14 GMT
From:    thewalt@canuck.ce.berkeley.edu (C. Thewalt)
Subject: Re: efficiency of open arrays

In article <MOSS.93Apr4174512@CRAFTY.cs.cmu.edu> moss@cs.cmu.edu
(Eliot Moss) writes:

>There's a reasonably obvious reason this might be happening. In the fixed
>array case, since the FOR loop bounds are static and within the array, it is
>not too hard to eliminate bounds checks -- I suspect the SRC compiler does it,
>and I'm pretty sure the GNU one will in this case, too. In the open array
>case, the size information is carried by the specific value (the NEW array),
>not in the type of the variable, and requires more sophisticated analysis to
>enable the bounds checks to be removed. If you nreally need open arrays,
>you'll probbaly have the bounds checks anyway, and will not be able to get the
>higher speed loop.

>Improving array access performance by eliminating needless checks is something
>all the compiler writers have on their agenda, but I can't promise great
>solutions soon .....						EM
>--

>J. Eliot B. Moss, Associate Professor	Visiting Associate Professor

Thanks for your response, I have looked at the C code and your guess
sounds correct.

I had been considering modula3 for a fairly large analytical package,
and had a couple of students learning it, but the package will do lot
of linear algebra and the matrix/vector sizes vary from problem to
problem.  A basic core of linear algebra functions (like BLAS in
FORTRAN) is required, and it is now obvious that the open array
overhead makes the use of Modula3 impossible.

I just ran a benchmark of a matrix multiply with open and fixed array
sizes and the speed ratio is 4.8:1 and we can't take a hit like that. 

Thanks for the clue,

Chris
--
Christopher Robin Thewalt               (thewalt@ce.berkeley.edu)
Dept. of Civil Engineering              These opinions are not necessarily
University of California, Berkeley      shared by my employer...


======================================================================= 24 ===
Date:    Wed, 7 Apr 1993 01:43:44 GMT
From:    ellis@parc.xerox.com (John Ellis)
Subject: Re: efficiency of open arrays

Joel raised an issue of optimizing bounds checks that I also
encountered in the Vulcan M2+ compiler.  I think Joel's suggested
optimization requires a little more elaboration that may be obvious to
some readers.

Consider the following loop:

    FOR i := m TO n DO
        ...a[ i ]... 

I think Joel was proposing that the bounds checks for a[ i ] would get
moved to the beginning of the loop:

    IF n >= m AND (LOW( a ) < m OR HIGH( a ) > n) THEN ...error... END;
    FOR i := m TO n DO
        ...a[ i ]... 

Before making this transformation, the compiler must ensure that the
loop actually executes for all the values of i = [m..n].  Otherwise,
if the loop terminates prematurely, then the transformation above
could incorrectly signal a subscript error.  Here are two examples of
loops that may exit prematurely:

    FOR i := m TO n DO
        IF i > C THEN EXIT; END;
        ...a[ i ]...

    FOR i := m TO n DO
        P();            /* Raises an exception */
        ...a[ i ]...

So it seems safe to do the transformation if: 

    The loop body contains no EXITs.

    All exceptions raised by the loop body are caught within the body.

Given the pervasive use of exceptions, this second condition makes the
optimization less useful than you might think initially (though it is
still useful).


======================================================================= 25 ===
Date:    Wed, 7 Apr 1993 12:40:59 GMT
From:    dave@kanga.lcs.mit.edu (David Sternlicht)
Subject: seeking trestle/mt experiences

-- 
Good morning.  I have been taking a long hard look at trestle and 
modula-3 from the standpoint of taking its experience in multi-threading
and using it in the X consortiums development of a next generation 
GUI toolkit, aka Fresco.  Admitedley the development language here is c++, 
not m3 (I do like m3 alot however!).  I have been thinking along the lines
of taking trestles locking level system for the procedures and data of
its interfaces and doing the same thing for the various public members of
Fresco's classes.  I guess I'm looking for some war stories here.  Has
anybody written a trestle program that makes extensive use of threads.
Are their any weaknesses in the design decisions taken?  Particular 
strengths that should be mentioned?

				dave sternlicht
				mit X consortium
				dave@expo.lcs.mit.edu


======================================================================= 26 ===
Date:    Wed, 7 Apr 1993 16:09:58 GMT
From:    cfr@tyrolia.Princeton.EDU (Chuck Rose)
Subject: m3 for SGI

Does anyone have information about m3 for SGIs?  Has anyone successfully
ported m3 to the SGI?

Thanks in advance,
chuck.




======================================================================= 27 ===
Date:    Thu, 08 Apr 1993 01:04:37 GMT
From:    urban@CS.ColoState.EDU (david urban)
Subject: Interfaces Cstring & M3toC

A software design class I am in stores strings of text in the cells of
a spreadsheet which need to be parsed for references to other cells. I
noticed in Harbison's book that there are interfaces Cstring and M3toC
which would make the parsing alot easier. 

Are there any references on how these interfaces are used since the book
does not explain them?

Any help with this would be greatly appreciated.

David Urban
-- 
David S. Urban   email : urban@cs.colostate.edu
To be the person, you must know the person. To know the person, you must
understand the person. To understand the person, you must listen. To listen,
you must open your mind and put aside all preconceived ideas and notions.


======================================================================= 28 ===
Date:    8 Apr 93 21:28:10 GMT
From:    sasaki@netop3.harvard.edu (Marty Sasaki)
Subject: Problems getting the compiler working


I'm trying to get the DS3100 version of m3 working on my DS5000
running Ultrix 4.3. The compiler runs fine and generates configuration
information.

	netop3:7> m3 -\?
	pass 0       := /usr2/local/lib/m3/m3compiler
	pass 1       := /bin/cc -G 0 -Wf,-XNp200000 -Wf,-XNd150000
	pass 2       := /bin/cc -G 0
	pass 2 base  := -N
	pass 3       := /bin/ar cru
	pass 4       := /usr/bin/ranlib
	pass 5       := /bin/ld -A
	pass 5 mid   := -G 0 -g2
	pass 5 tail  := -lc_G0
	def path     := . /usr2/local/include/m3
	lib path     := . /usr2/local/lib/m3
	include      := /usr2/local/lib/m3
	server limit := 0 megabytes
	make mode    := FALSE
	bootstrap    := FALSE
	std libs     := TRUE -lm3 -lm
	keep files   := FALSE
	coverage     := FALSE /usr2/local/lib/m3/report_coverage.o
	resolve libs := FALSE
	CC paranoid  := FALSE
	-O           => -O2
	-g           => -g2

When I try to use m3make to create libm3 I get an error:

	netop3:5> m3make -f m3makefile.libm3 all install
	-------------------------------------- libm3/DS3100
	/usr2/local/bin/m3 -w1 -make -why -nostd -times -g    -a libm3.a -F.PGM
_SOURCES 
	new source -> compiling ../C/src/generic/Cerrno.i3

	 seconds  #times  operation
	    0.25       1  flattening search path
	    0.09       5  checking object timestamps
	    0.24       1  compiling Modula-3 -> C
	    0.05       3  removing temporary files
	    0.31       2  garbage collection
	    0.38          other
	---------------------------------------------------
	    1.32          TOTAL


	Fatal Error: program "/usr2/local/lib/m3/m3compiler" got fatal signal 1
1

	*** Error code 255

	Stop.
	*** Error code 1

	Stop.

Anything obviously wrong? How do I begin to look at things?
--
Marty Sasaki            Harvard University           Sasaki Kite Fabrications
sasaki@noc.harvard.edu  Network Operations Division  26 Green Street
617-496-4320            10 Ware Street               Jamaica Plain, MA 02130
                        Cambridge, MA 02138-4002     phone/fax: 617-522-8546


======================================================================= 29 ===
Date:    9 Apr 1993 15:31:57 GMT
From:    mead@bucknell.edu (Jerry Mead)
Subject: Solaris2.1 version of M3?


Has anyone had success bringing modula3 up on Solaris 2.1?  
Suggestions and/or war stories are of interest.
---------------------

Jerry Mead
Dept of Computer Science
Bucknell University
Lewisburg, PA 17837
mead@bucknell.edu



======================================================================= 30 ===
Date:    9 Apr 93 19:14:22 GMT
From:    sasaki@netop3.harvard.edu (Marty Sasaki)
Subject: Re: Problems getting the compiler working


In article <1993Apr8.212810.27881@das.harvard.edu>, sasaki@netop3.harvard.edu (
Marty Sasaki) writes:
>When I try to use m3make to create libm3 I get an error:

Thanks to those who offered suggestions and help. On the hunch of some
one I just rebuilt things form the distribution. The new version seems
to be working fine.
--
Marty Sasaki            Harvard University           Sasaki Kite Fabrications
sasaki@noc.harvard.edu  Network Operations Division  26 Green Street
617-496-4320            10 Ware Street               Jamaica Plain, MA 02130
                        Cambridge, MA 02138-4002     phone/fax: 617-522-8546


======================================================================= 31 ===
Date:    Sat, 10 Apr 1993 17:23:44 GMT
From:    robsch@robkaos.GUN.de (Robert Schien)
Subject: M3 for 386BSD

Does it exist? Or is anybody porting it?
Thanks in advance.
Robert
-- 
Robert Schien    robsch@robkaos.GUN.de
"To err is human, to really foul things up requires a computer"


======================================================================= 32 ===
Date:    Tue, 13 Apr 1993 20:31:53 GMT
From:    woolsey@mri.com (Jeff Woolsey)
Subject: Re: Solaris2.1 version of M3?

In article <1q44td$ifh@coral.bucknell.edu> mead@bucknell.edu writes:

>Has anyone had success bringing modula3 up on Solaris 2.1?  
>Suggestions and/or war stories are of interest.

A-step-in-that-direction story:

I have a fairly monolithic old-mainframe CPU simulator that's my
favorite benchmark these days.  It's compiled by m3-2.11 on SunOS
4.1.1.  Solaris 2.1 is supposed to have a SunOS-4 compatibility mode
for dynamically-linked programs.  We have received a few SPARCstation
LX machines in house recently, and I wanted to "benchmark" these guys,
but they run Solaris 2.1.

I hauled the binary over there, and started it up.  Assertion failed at
line 832 in Thread.m3.   I poked around the various .i3, .m3, and .mc
files that came with the compiler, and eventually found that there was
a variable somewhere called "__M3__stack_grows_down".  The assertion
had to do with stack direction, so on a hunch I decided to nail it.
I changed it from a zero to a one with adb (easiest way, actually) and
tried it out.  This worked well enough for me, but interactive I/O
wasn't working, and I have no idea whether threads would work (my
program doesn't use them).

Incidentally, by my figures an LX is about the same speed as an ELC.

-- 
-- 
Jeff Woolsey			800 950 5554	woolsey@mri.COM
Microtec Research, Inc.	     +1 408 980 1300	woolsey@netcom.COM
Nothing like a three-address mailer....		woolsey@jlw.com


======================================================================= 33 ===
Date:    Wed, 14 Apr 1993 10:07:54 GMT
From:    jbowyer@cis.vutbr.cs (Bowyer Jeff)
Subject: We Want Your Work


We want you to announce your work on our mailing list!

     Do you use a program that has a non-English interface?

     Have you converted any software to support more than one language for
     its interface?

     Will you sponsor a conference that might concern software with a
     non-English interface?

Please tell us!



INSOFT-L on LISTSERV@CIS.VUTBR.CS   Internationalization of Software
                                    Discussion List

   Internationalization of software relates to two subjects:

        1. Software that is written so a user can easily change the
           language of the interface;

        2. Versions of software, such as Czech WordPerfect, whose
           interface language differs from the original product.

   Topics discussed on this list will include:

        -- Techniques for developing new software

        -- Techniques for converting existing software

        -- Internationalization tools

        -- Announcements of internationalized public domain software

        -- Announcements of foreign-language versions of commercial
           software

        -- Calls for papers

	-- Conference announcements

	-- References to documentation related to the
           internationalization of software
	
   This list is moderated.

   To subscribe to this list, send an electronic mail message to
   LISTSERV@CIS.VUTBR.CS with the body containing the command:

      SUB INSOFT-L Yourfirstname Yourlastname

   Owner:

      Center for Computing and Information Services
      Technical University of Brno
      Udolni 19, 602 00 BRNO
      Czech Republic

      INSOFT-L-REQUEST@CIS.VUTBR.CS


======================================================================= 34 ===
Date:    Thu, 15 Apr 93 21:17:38 GMT
From:    mjordan@src.dec.com (Mick Jordan)
Subject: Re: .m3 + .c ?

In article <1qkedi$12m@usenet.INS.CWRU.Edu>, bf148@cleveland.Freenet.Edu (Shad 
Todd) writes:
|> 
|> Hello,
|> I am trying to compile the following simple modula-3 program without
|> success. This is the error I get when I try to compile:
|> 
|>     m3 test.m3 cstuff.c cstuff.i3
|>     
|>     undefined version stamp: cstuff.cprocedure  <f8a45f393fb4b124>
|>          test.m3  cstuff.i3  
|>     
|>     Fatal Error: incomplete program
|> 
|> Can anyone tell me what I am doing wrong here, or point me
|> towards documentation for calling C routines from modula-3?
|> Thanks very much for your time,
|> 
|
|> --cstuff.i3------
|> UNSAFE INTERFACE cstuff;
|> 
|> PROCEDURE cprocedure(x, y: INTEGER): INTEGER;
|> END cstuff.
|> 

Since "cprocedure" is implemented in C, you need to say:

<*EXTERNAL*> PROCEDURE cprocedure(x, y: INTEGER): INTEGER;

The linker is looking for a Modula-3 implementatioin and not finding it.

Mick Jordan


======================================================================= 35 ===
Date:    Thu, 15 Apr 93 23:17:45 GMT
From:    harrison@src.dec.com (Stephen Harrison)
Subject: Re: .m3 + .c ?



Shad Todd described a problem linking Modula-3 and C.

His Modula-3 interface omitted the <*EXTERNAL*> pragma from the declaration of
the C procedure.

It should read:

    INTERFACE cstuff;

    <*EXTERNAL*> PROCEDURE cprocedure(x, y: INTEGER): INTEGER;

    END cstuff.

Cheers,

/Stephen

--
Stephen Harrison              | harrison@pa.dec.com
Systems Research Center       | 
Digital Equipment Corporation | work +1 (415) 853-2140
130 Lytton Avenue             | fax  +1 (415) 853-2104
Palo Alto, CA 94301, USA      | home +1 (408) 739-7734



======================================================================= 36 ===
Date:    15 Apr 1993 19:52:18 GMT
From:    bf148@cleveland.Freenet.Edu (Shad Todd)
Subject: .m3 + .c ?


Hello,
I am trying to compile the following simple modula-3 program without
success. This is the error I get when I try to compile:

    m3 test.m3 cstuff.c cstuff.i3
    
    undefined version stamp: cstuff.cprocedure  <f8a45f393fb4b124>
         test.m3  cstuff.i3  
    
    Fatal Error: incomplete program

Can anyone tell me what I am doing wrong here, or point me
towards documentation for calling C routines from modula-3?
Thanks very much for your time,

Shad
--
Shadrach Todd
shtodd@vassar.edu

--test.m3---------
MODULE test EXPORTS Main;

FROM cstuff IMPORT cprocedure;

VAR
  result: INTEGER;

BEGIN
  result:=cprocedure(1, 2);
END test.

--cstuff.c-------
int cprocedure(x, y)
int x,y;
{
return x+y;
}
--cstuff.i3------
UNSAFE INTERFACE cstuff;

PROCEDURE cprocedure(x, y: INTEGER): INTEGER;
END cstuff.



======================================================================= 37 ===
Date:    Thu, 15 Apr 1993 20:39:12 GMT
From:    jkpchang@laplace.uwaterloo.ca (Jorge 'CS-Geek' Chang)
Subject: Modula-3 for IBM PCs


Anyone know where I can get a Modula-3 compiler for IBM PC. If you know please
either email me or post on this newsgroup exactly where I can get it and how...


					Thanks... Jorge 


======================================================================= 38 ===
Date:    Fri, 16 Apr 1993 13:08:08 GMT
From:    cpshelle@undergrad.math.uwaterloo.ca (cameron shelley)
Subject: Re: Modula-3 for IBM PCs

In article <C5JLDC.C4L@undergrad.math.uwaterloo.ca> you write:
> 
> Anyone know where I can get a Modula-3 compiler for IBM PC. If you know pleas
e
> either email me or post on this newsgroup exactly where I can get it and how.
..

The PC Modula-3 compiler is archived at archive.uwaterloo.ca in
directory micro/m3pc.  Please consult the FAQ file for your course as
was posted in uw.cs.cs246 or in the directory /u/cs246/documents for
more information.

</dev/cam
--
       Cameron Shelley         |"In the beginning, there was nothing.  Then
cpshelle@descartes.uwaterloo.ca| God said `Let there be light', and there
    Math & Computer Rm 1014    | was still nothing, but youse could see it."
  Phone (519) 885-1211 x6827   | --Dave Thomas, SCTV:_Sunrise Semester_


======================================================================= 39 ===
Date:    Tue, 20 Apr 1993 01:27:34 GMT
From:    jeffo@uiuc.edu (J.B. Nicholson-Owens)
Subject: Creating SRC Modula-3 2.11 on a NeXTSTEP 3.0 machine

I'm wondering if anyone has made the SRC M3 compiler v2.11 on a
NeXTSTEP 3.0 machine.  I tried to and the compiler returns some
strange error every time I call it:

$ m3

Fatal Error: improperly formatted argument: -z8@

$

(I didn't give any argument at all)

If you've created this compiler (or a later version of it), please let
me know how or what config file you used so I can make the compiler.

Thanks,
-- 
-- J.B. Nicholson-Owens (jeffo@uiuc.edu)
-- NeXTmail welcome


======================================================================= 40 ===
Date:    19 Apr 1993 23:56:13 GMT
From:    grunwald@foobar.cs.colorado.edu (Dirk Grunwald)
Subject: Demangle?


Is there a symbol table ``demangler'' for Modula-3. E.g., I want to
translate

	FBEPostScript__WriteProlog__WriteFontSetup:f15

Into something more useful. Actually, want I *really* want to know is,
given a symbol name, is this a function name from a Modula-3 object
method?

Any ideas on how to do this? The analoge in the C++ world is the cplus-dem.c
program that comes with the FSF ``liberty'' library.

Thanks,


Dirk Grunwald                          Asst. Prof, Univ. of Colorado at Boulder


======================================================================= 41 ===
Date:    Mon, 19 Apr 93 17:38:13 CST
From:    EM306965@itesmvf1.rzs.itesm.mx (Gustavo Cavazos)
Subject: TCP/IP for M3 ??

Hello...
    How does one uses the TCPIP with Modula-3...
Thanx for any info
 
+Gus


======================================================================= 42 ===
Date:    Mon, 19 Apr 1993 18:41:19 GMT
From:    cope@cbnewsb.cb.att.com (james.o.coplien)
Subject: Call For Papers: OOPSLA Workshop on Objects and Process Standards


            OBJECTS, ITERATION AND DEVELOPMENT PROCESS STANDARDS
                 A one-day workshop to be held at OOPSLA '93
                            Sep 26 - Oct 1 1993
                              Washington, D.C.


PURPOSE AND GOALS FOR WORKSHOP

       At the 1992 OOPSLA in Vancouver, we combined the workshops "OO in the
       Commercial Environment:  The Bottom Line" and "Development Processes for
       Use under the Object Paradigm." The result was an exciting, fruitful day
       of dialogue that covered both state-of-the-art and emerging approaches
       to object-oriented development.  At the 1993 OOPSLA in Washington, D.C.,
       we propose to continue this workshop, refocusing a bit on the issue of
       industry standard development processes and their relationship to
       the object paradigm.

       Last year, we looked at the tension between iterative design methods
       such as prototypical development, and the need for stability (for
       example, of system interfaces) and progress tracking (by upper
       management) that is valued in most development cultures.  Many
       solutions were presented, including hybrid methods, application of
       different method models at different levels of corporate management,
       radical change to incorporate new development models and ways of
       doing business, and the use of formal specifications.  We also
       found surprisingly broad concensus concerning the inability of objects
       to encapsulate change in large, embedded systems, making iterative
       development difficult.

       This year, we will revisit similar considerations, but in the context
       of established and emerging industry standards for software development
       process.  Examples of topics to be considered include the following:

	   - The SEI Capability Maturity Model (CMM) is an emerging defacto
	     standard for development process, aimed at developing high-
	     reliability software.  Can its rigour and structure be reconciled
	     with iterative development?

	   - While the CMM focuses on low fault density, other processes
	     focus on time-to-market (such as concurrent engineering
	     approaches), direct customer engagement (such as prototyping
	     approaches), cost reduction, and other factors.  Which of
	     these models -- if any -- is suitable for the object paradigm?
	     Are the object paradigm, its technologies, and the processes
	     most often associated intrinsically tied to some of these
	     variables at the expense of ignoring others?  Where does
	     the object paradigm work best?  What paradigms should be
	     used to optimize other criteria?

	   - The ISO 9001 standard is attracting an increasing number of
	     adherents from world corporations wishing to market their products
	     in the European Common Market, and elsewhere world-wide.  Its
	     main tenets relate to reproducibility of a process.  Are iterative
	     processes "reproducible"?  How can ISO 9001 be reconciled to
	     iterative development?  Is the ISO 9001 standard an impediment
	     or aid to use of the object paradigm?

	   - STD 2167A is a largely stable and widely embraced standard for
	     software development under military contract.  Can its tenets
	     be reconciled with object-oriented development?  How does it
	     aid or limit object-oriented development?  What does the place
	     of Ada-9X in military standards, and its stature in the world of
	     object orientation, portend for succesful use of the object
	     paradigm under 2167A?
	
	   - IPSE2.5 and other process standards focus on automating process
	     steps by executing prescribed process models.  Sequencing major
	     activities in a traditional waterfall-style development seems to
	     be an intuitive application of the modeling facilities in
	     IPSE2.5.  Does IPSE2.5 extend to iterative development and use
	     of the object paradigm?

       An objective of the workshop is to identify interim measures that
       support coexistence of object-oriented techniques and established
       process standards, if such can be found.  The workshop should also
       increase the level of appreciation and understanding on how current
       process models might be evolved or replaced, with the goal in mind
       of steering both object-oriented techniques and next-generation
       standards to increase the liklihood that the two might coexist.

       In this one day of dialogue, we hope the group can establish
       a framework of development processes and their relationship to iterative
       development and the object paradigm. We also expect to uncover pragmatic
       approaches that deal with the tensions between prescribed methods and
       the object paradigm, or between prescribed methods and iterative
       development.  Individual papers will be selected for presentation on the
       workshop agenda, but all invited participants are expected to
       participate in discussion and are encouraged to bring supporting
       materials.

PARTICIPANTS

       Participation is solicited from those actively engaged in
       research on software methodology, architectural evolution,
       or software process, as well as spokespersons for project
       and corporate management strategies for deployment of software
       products.  Members of the established software development
       process communities are particularly encouraged to participate.

WORKSHOP FORMAT AND LENGTH

       We hope to keep as much of the agenda as possible free for
       moderated discussion.  Specific papers may be selected for short
       (20 minute) presentations, depending on the response received.
       We are open to suggestions for use of other formats.  The workshop
       will be one day long.

POSITION PAPERS

       All participants must submit short (1-3 page) position papers to the
       workshop organizers.  The paper should briefly describe your project
       (application, number of people, language used), and address 3-5 issues
       of interest to you.  You may select issues from the list above,
       or contribute additional issues.  Papers must be submitted by
       August 20, 1993.  Participants will be selected and notified by
       Sept. 15, 1993.  Papers should be sent to Jim Coplien (below);
       electronic media are preferred.

ORGANIZERS

      Jim Coplien
      Software Production Research Department
      AT&T Bell Laboratories
      1000 East Warrenville Road
      Naperville, IL 60566 USA
      Voice: (708) 713 5384   Fax: (708) 713 4982
      Email: cope@research.att.com

      Suzana Hutz
      Motorola Inc. - Corporate Offices
      Software Research and Development
      3701 Algonquin Rd. Suite 601
      Rolling Meadows, IL 60008 USA
      Voice: (708) 576 2815   Fax: (708) 576 2025
      Email: hutz@corp.mot.com

      Russel Winder
      Department of Computer Science
      University College London
      Gower Street, London WC1E 68T
      Voice: +44 (0)71 380 7293   Fax: +44 (0)71 387 1397
      Email:  R.Winder@cs.ucl.ac.uk


======================================================================= 43 ===
Date:    Thu, 22 Apr 1993 21:42:14 GMT
From:    barton@chopin.eche.ualberta.ca (Bob Barton System Administrator (403)4
92 5160)
Subject: Generic for Reading Numerics?

We are contemplating using M3 in introductory computing for engineering
students. We do not plan on teaching all about M3 but more about problem
solving in an engineering environment. For this we would like to have some
easy way to read integer, real and complex numbers from stdin and files.
I realize that I can write the modules myself but I think it is highly
probable that someone else has already done this. If anyone has done this
and if they are willing to pass them on I would appreciate receiving them.

Thank you.
--,,,,
 | D |  R.L. Barton                    Department of Chemical Engineering
 | A |  Tel (403) 492-5160             University of Alberta 
 | C |  Fax (403) 492-2881             Edmonton, Alberta, Canada T6G 2G6
 | S |  Internet barton@chopin.eche.ualberta.ca
--''''


======================================================================= 44 ===
Date:    Thu, 22 Apr 93 22:26:44 GMT
From:    mcjones@src.dec.com
Subject: Re: Generic for Reading Numerics?

Date: Thu, 22 Apr 93 15:26:35 -0700
X-Received: by whitman.pa.dec.com; id AA19055; Thu, 22 Apr 93 15:26:35 -0700
X-Received: by src-news.pa.dec.com; id AA04385; Thu, 22 Apr 93 15:26:40 -0700
X-Mts: smtp

Bob,

As it happens, we're planning to include an interface for simple 
I/O in the standard SRC Modula-3 distribution.  Here's the current 
draft version; we'd be interested in getting your comments.  (This 
version doesn't include the BNF for numbers; in the final version, 
that will be handled by referring to (a new, improved) Lex.)

(* Copyright 1993 by Digital Equipment Corp.                   *)
(* All rights reserved.                                        *)
(* See the file COPYRIGHT for a full description.              *)
(* Last modified on Thu Apr 22 10:01:42 PDT 1993 by mcjones    *)
(*      modified on Sat Jan 26 14:38:00 PST 1993 by gnelson    *)

(* The "IO" interface provides textual input and output for simple
   programs.  For more detailed control, use the interfaces "Rd",
   "Wr", "Stdio", "FileRd", "FileWr", "Fmt", and "Lex".

   The input procedures take arguments of type "Rd.T" that specify
   which input stream to use.  If this argument is defaulted, standard
   input ("Stdio.stdin") is used.  Similarly, if an argument of type
   "Wr.T" to an output procedure is defaulted, "Stdio.stdout" is used.
   *)

INTERFACE IO;

IMPORT Rd, Wr;

PROCEDURE Put(txt: TEXT; wr: Wr.T := NIL);
(* Output "txt" to "wr" and flush "wr". *)

PROCEDURE PutInt(n: INTEGER; wr: Wr.T := NIL);
(* Output "Fmt.Int(n)" to "wr" and flush "wr". *)
   
PROCEDURE PutReal(r: REAL; wr: Wr.T := NIL);
(* Output "Fmt.Real(r)" to "wr" and flush "wr". *)

PROCEDURE EOF(rd: Rd.T := NIL): BOOLEAN;
(* Return "TRUE" iff "rd" is at end-of-file. *)

EXCEPTION Error;

(* The exception "Error" is raised whenever a "Get" procedure
   encounters syntactically invalid input, including unexpected
   end-of-file. *)

PROCEDURE GetLine(rd: Rd.T := NIL): TEXT RAISES {Error};
(* Read a line of text from "rd" and return it. *)

(* A line of text is either zero or more characters terminated by a
   newline, or one or more characters terminated by an end-of-file.
   In the former case, "GetLine" consumes the newline character but
   does not include it in the returned value. *)

PROCEDURE GetChar(rd: Rd.T := NIL): CHAR RAISES {Error};
(* Read the next character from "rd" and return it. *)

PROCEDURE GetInt(rd: Rd.T := NIL): INTEGER RAISES {Error};
(* Read a decimal numeral from "rd" and return its value. *)

PROCEDURE GetReal(rd: Rd.T := NIL): REAL RAISES {Error};
(* Read a real number from "rd" and return its value. *)
  
PROCEDURE OpenRead(f: TEXT): Rd.T;
(* Open the file name "f" for reading and return a reader on 
   its contents. If the file doesn't exist or is not readable,
   return "NIL". *)

PROCEDURE OpenWrite(f: TEXT): Wr.T;
(* Open the file named "f" for writing and return a writer on
   its contents.  If the file does not exist it will be created.
   If the process does not have the authority to modify or create 
   the file, return "NIL". *)

END IO.



======================================================================= 45 ===
Date:    Fri, 23 Apr 93 00:29:03 GMT
From:    Eric Muller <muller@src.dec.com>
Subject: kwic of the comp.lang.modula3 archives

I have created a Key Word In Context index on the subjects of the
messages sent to comp.lang.modula3. It will appear very soon on
gatekeeper.dec.com in pub/DEC/Modula-3/comp.lang.modula3/kwic and I
will maintain it as I add new volumes to this archive.

The following words have been ignored:

  A M3 Modula-3 Modula Modula3 Questions Question Re about an and
  another as at for from help i is again all are be does is it of on

Please, let me know if you think I should modify that list.

Here is a sample, for the keyword "syntax":

90-01:             SRC compiler              syntax accepted by the
90-01:             SRC compiler        Re:   syntax accepted by the
90-01:                       TRY statement   syntax non-problem
90-01:                   Re: TRY statement   syntax non-problem
90-12:                        SRC Modula-3   syntax and semantics
90-12:             constants      Modula-3   syntax and semantics for
90-12:             constants      Modula-3   syntax and semantics for
90-12:             constants      Modula-3   syntax and semantics for
91-01:             method/             new   syntax for overriding
92-09:                                       Syntax of WITH and TRY
92-10:                                       Syntax of Modula-3
92-10:                                 Re:   Syntax of Modula-3


The left-hand side is the name of the file that contains the message,
and conveniently tells you when the message was posted.

The current version is not too big:

% wc kwic
    7523   47010  486556 kwic

For those of you who have more resources, I recommend the ni program
(available on gatekeeper.dec.com in pub/DEC/ni.tar.Z) which builds
full indexes (not just on the subject) of newsgroups and provides a
simple interface to find and read those articles that contain certain
words.  The amount of disk space it takes is not too bad, and well
worth it; here at SRC, we could not do without ni anymore.

-- 
Eric.



======================================================================= 46 ===
Date:    23 Apr 1993 09:54:59 GMT
From:    laszlo@post.ifi.uni-klu.ac.at (Laszlo BOESZOERMENYI)
Subject: Bug In Set.mg

I have found a bug in the Generic-set "Set.mg".
In the procedure "copy" the line
	cur := self.a [b];
must be properly:
	cur := self.a [b]; prevN:= NIL;

I wonder, if anybody has ever used this module??!!

Cheers
Laszlo
------------------------------
Prof. Laszlo Boeszoermenyi
Institut fuer Informatik

Universitaet Klagenfurt
Universitaetsstr. 65-67
A-9022 Klagenfurt / Austria

e-mail:
laszlo@ifi.uni-klu.ac.at
Tel.: 
00-43-463-2700-509 
00-43-463-2700-506 (secr.)
Fax.:
00-43-463-2700-505 


======================================================================= 47 ===
Date:    Fri, 23 Apr 93 22:28:10 GMT
From:    Eric Muller <muller@src.dec.com>
Subject: Re: Problem with RealFloat?


|> I am getting a core dump when I try to use RealFloat.Sqrt. [on AIX386]

Most of the RealFloat implementation is machine specific, and we
haven't tried to guess the proper implementation for the machines we
don't have access to.

In the case of Sqrt, the implementation of the DS3100 version should
work fine on most machines:

	RETURN FLOAT (Math.Sqrt (FLOAT (x, LONGREAL)), T);

I'll include that for the next release.  Of course, if somebody can
provide a full implementation of the machine-specific interfaces and
modules for floating point, it will be even better.  Look in
libm3/float/src.

-- 
Eric.



======================================================================= 48 ===
Date:    23 Apr 93 20:54:23 GMT
From:    barton@chopin.eche.ualberta.ca (Bob Barton System Administrator (403)4
92 5160)
Subject: Problem with RealFloat?

I am getting a core dump when I try to use RealFloat.Sqrt. The problem can
be demonstrated with the following code -

MODULE FloatTst EXPORTS Main;
IMPORT Fmt, RealFloat, Wr, Stdio;
VAR
	testValue : REAL;
BEGIN
	Wr.PutText(Stdio.stdout, "Test of Sqrt from RealFloat\n");
	testValue := RealFloat.Sqrt(4.0);
	Wr.PutText(Stdio.stdout,"\nThe square root of 4.0 is: ");
	Wr.PutText(Stdio.stdout, Fmt.Real(testValue));
	Wr.PutText(Stdio.stdout,"\n");
END FloatTst.

which produces -
***
*** runtime error
***	ASSERT failed
***	file "RealFloat.m3", line 63
***
Test of Sqrt from RealFloat

I am probably doing something incorrectly but I have not identified it. I have
accomplished the square root by using Math.sqrt and multiple FLOATs but
that is pretty kludgey. I am working with m3 version 2.11 on an IBM RS/6000 
with AIX 3.2.3.

--,,,,
 | D |  R.L. Barton                    Department of Chemical Engineering
 | A |  Tel (403) 492-5160             University of Alberta 
 | C |  Fax (403) 492-2881             Edmonton, Alberta, Canada T6G 2G6
 | S |  Internet barton@chopin.eche.ualberta.ca
--''''


======================================================================= 49 ===
Date:    23 Apr 93 17:29:52 GMT
From:    muzok@microsoft.com (Muzaffer Kal)
Subject: Re: Modula-3 for IBM PCs

In article <93Apr16.091142edt.246216-2@undergrad.math.uwaterloo.ca> cpshelle@un
dergrad.math.uwaterloo.ca wrote:
> In article <C5JLDC.C4L@undergrad.math.uwaterloo.ca> you write:
> > 
> > Anyone know where I can get a Modula-3 compiler for IBM PC. If you know ple
ase
> > either email me or post on this newsgroup exactly where I can get it and ho
w...
> 
> The PC Modula-3 compiler is archived at archive.uwaterloo.ca in
> directory micro/m3pc.  Please consult the FAQ file for your course as
> was posted in uw.cs.cs246 or in the directory /u/cs246/documents for
> more information.
> 
> </dev/cam
> --
>        Cameron Shelley         |"In the beginning, there was nothing.  Then
> cpshelle@descartes.uwaterloo.ca| God said `Let there be light', and there
>     Math & Computer Rm 1014    | was still nothing, but youse could see it."
>   Phone (519) 885-1211 x6827   | --Dave Thomas, SCTV:_Sunrise Semester_

is there an ftp source for this compiler ? Also is there an oberon compiler and
/or environment for PCs ?
please give fully resolved addresses.


======================================================================= 50 ===
Date:    Sat, 24 Apr 1993 07:50:44 GMT
From:    stjk100@cl.cam.ac.uk (S.T.J. Kam)
Subject: M3 vs C++

Could anybody give a comparison between M3 and C++?
I am particularly interested in their OOP features.

                                         S.T.J. Kam
Keywords: 



======================================================================= 51 ===
Date:    24 Apr 93 12:22:48
From:    vixie@pa.dec.com (Paul A Vixie)
Subject: Re: M3 vs C++

>Could anybody give a comparison between M3 and C++?
>I am particularly interested in their OOP features.
>
>                                         S.T.J. Kam

C++ has operator overloading and multiple inheritance but no garbage collection
(though it can be added later, there's no standard for it yet).  My article in
";login:" (the USENIX Association Newsletter) a few issues ago provides a light
comparison between M3 and C++.  If you don't get ;login: and can't find it, let
me know and I'll mail you a copy electronically.
--
Paul Vixie, DEC Network Systems Lab	
Palo Alto, California, USA         	"Don't be a rebel, or a conformist;
<vixie@pa.dec.com> decwrl!vixie		they're the same thing, anyway.  Find
<paul@vix.com>     vixie!paul		your own path, and stay on it."  -me


======================================================================= 52 ===
Date:    24 Apr 93 23:07:55
From:    vixie@pa.dec.com (Paul A Vixie)
Subject: Re: M3 vs C++

I wrote:

> [...] My article in ";login:" (the USENIX Association Newsletter) a few
> issues ago provides a light comparison between M3 and C++.  If you don't
> get ;login: and can't find it, let me know and I'll mail you a copy
> electronically.

It turns out that the ;login: people don't mind and I already got publication
approval from my employer, so here it is.  Note that it has a very polemic
style, one I would not normally use on Usenet since it tends to cause flame
wars.  There several actual facts contained herein, though, so give it a read
if you care about this sort of thing.  

by the way, those of you who don't receive ;login: are missing out.  send mail
to office@usenix.org if you want to join; i think the membership rate is $35 a
year for individuals, less for students.  note: i am not a spokesman for or a
representative of Usenix or ;login: -- just a happy contributor and reader.

Copyright (c) 1993: do not separate the following text from the above text,
including enough of the article header to show authorship.  otherwise you may
redistribute at will, with or without fee.

============================ begin ;login: article ============================
Have you seen Modula-3?

Consider:

	MODULE Main;	(* hello1.m3 *)

	IMPORT Stdio, Wr;

	BEGIN
	    Wr.PutText(Stdio.stdout, "Hello, world.\n");
	END Main.

The above program is written in Modula-3, one of the latest languages to
descend from Algol.  As you can see, the source looks a lot like Modula-2
or Pascal (or, if you live on the bleeding edge, you might agree that it
looks a lot like Oberon).

As is true of the "Hello, World" program when written in other languages,
our example does not begin to explicate Modula-3's interesting features;
however, as with C, if you started by looking at a program which used all
or even some of the interesting features, you would probably giggle and
turn the page.

Modula-3 has explicit boundaries between modules.  Types, constants,
variables and procedures declared in a module are only accessable to other
modules if the declaring module explicitly "exports" them.  (Contrast this
to C, where all top-level names in a source file are globally visible at
link time unless they are declared "static".)  A module which depends on
entities from some other module must explicitly "import" the symbols it
needs.

Consider:

	MODULE Main;    (* hello2.m3 *)

	FROM Wr    IMPORT PutText;
	FROM Stdio IMPORT stdout;

	BEGIN
	    PutText(stdout, "Hello, world.\n");
	END Main.

In the first example, we imported the symbol tables from the Wr and Stdio
modules, and then used their PutText and stdout symbols by qualifying those
symbols with the names of the modules that exported them.  In this second
example, we imported only the PutText and stdout symbols -- now we can
refer to them without module qualifiers.  (Note that the current
recommended practice among experienced Modula-3 programmers is to always
import symbol tables and use qualified references; you will rarely or never
see local symbol aliases used in published Modula-3 source.)  

Modula-3 is a strongly typed language whose loopholes are difficult enough
and inconvenient enough to use that one tends to localize them to one or
only a few "modules" (which, for now, you can think of as "source files").
This leads toward that ideal state of affairs where most of the ugly and
nonportable code in a software system is located in one place; modules which
are not declared to the compiler as "able to contain ugly, nonportable code"
are prohibiting from containing such code.  Examples of such code include
most kinds of type casts, pointer arithmetic which could lead to alignment
or byte-order gaffes, and use of dynamic memory in ways that could lead to
memory leaks.  Noone has yet invented a compiler which rejects code that is
_portably_ ugly.

Modula-3 has "objects", which for the OO-impaired are basically "records"
(think "structs") which you can "subclass" (make another object just like
this one but which adds some fields at the end or overrides the default
values of existing fields) and which can contain "methods" (fields which are
procedure ("function") pointers, calls to which are automagically rewritten
by the compiler to pass as the first parameter the object variable whose
method is being referenced).

Modula-3 has "garbage collection" which means that you almost never "free"
dynamic memory when you are done with it; it is reclaimed by the runtime
system at some time after the last reference to it disappears.  In fact the
DISPOSE procedure needed to deallocate dynamic memory is only available in
modules which are declared to the compiler as UNSAFE (meaning that they are
allowed to contain ugly, nonportable code).

Modula-3 has a defined "threads" interface, which means that coprocessing
programs can look like what they do instead of being twisted around a very
busy select(2) or poll(2) system call.  The freely-available uniprocessor
implementation of Modula-3's threads package uses select(2) and setjmp(2)
and longjmp(2), but programmers don't have to think in terms of these
details and the resulting improvement in readability -- and writability --
of coprocessing programs is quite dramatic.  And of course, if you use
threads in your code and someday move it to a multiprocessor with thread
support, you'll get multiprocessing and concurrency for free.

In support of threads, Modula-3 has mutex semaphores and a built-in LOCK
statement to lock and unlock these mutexes around critical sections of code,
as well as a general interface that lets threads share access to "condition
variables", which BSD kernel hackers will recognize as "like sleep() and
wakeup(), only how do they do that in user mode?"

For example, Figure 1 shows short cycle burner that will prove that the
thread scheduler is indeed preemptive:

==================================================================== Figure 1
	MODULE Main;

	IMPORT Stdio, Wr, Fmt, Thread, Text, Time;

	TYPE
	    LockedIndex = MUTEX OBJECT
		index := 0;
	    END;

	VAR
	    Inner := NEW(LockedIndex);
	    Outer := 0;

	PROCEDURE InnerF(self: Thread.Closure): REFANY RAISES {} =
	BEGIN
	    LOOP
		LOCK Inner DO
		    INC(Inner.index);
		END;
	    END;
	END InnerF;

	BEGIN
	    EVAL Thread.Fork(NEW(Thread.Closure, apply := InnerF));
	    LOOP
		Time.LongPause(1);
		LOCK Inner DO
		    Wr.PutText(Stdio.stdout,
			"Inner=" & Fmt.Int(Inner.index) & "; " &
			"Outer=" & Fmt.Int(Outer) & "\n");
		    Wr.Flush(Stdio.stdout);
		    INC(Outer);
		    Inner.index := 0;
		END;
	    END;
	END Main.
================================================================ end Figure 1

This program forks off a thread which increments, with locking, a global
index variable.  We made this variable an "object" which subclasses the
"MUTEX" object type, since this is the usual style for object types with
a single mutex to lock all of its resources.  We could as easily have made
this a "record" type with an explicit mutex field; for that matter we could
have made the index and the mutex separate global variables with no "record"
or "object" type to aggregate them.  Anyway, the main thread forks a thread
that executes the ApplyF function, which loops forever, incrementing the
global index variable which is protected by a mutex.  The main thread then
loops, waiting one second and then printing and clearing the index that the
other thread is furiously incrementing.  On the author's workstation, this
program prints:

	% ./a.out
	Inner=144204; Outer=0
	Inner=126392; Outer=1
	Inner=114215; Outer=2
	Inner=125996; Outer=3
	^C

Exceptions

Last in our brief survey of Modula-3's features, we note "exceptions".  An
experienced C programmer knows that there are two kinds of code: the kind
where you check the return codes of all system and library calls, and then
there's the kind that people actually write.  In the first kind (which has
been characterized as "you're crossing the street to buy an ice cream cone,
so after every step you stop and check yourself all over to see if you have
just been hit by a crashlanding 747 jetliner"), you discover that return
codes breed more return codes, since if your function discovers an unusual
error it would like to propagate this unusualness to its caller, which must
do the same, all the way up the call stack until some caller "handles" it
(or more often in the code we've seen, casts it to "void").  Modula-3 has
as part of every procedure declaration a list of "conditions" which that
procedure is capable of "raising".  Code which calls that procedure has the
option of wrapping the call in a TRY...EXCEPT...END statement if it wants
to have a chance to "handle" certain exceptions; in the absence of any
caller who cares, the program exits with an error.  This leaves the return
value available for a full range of useful things, none of which are reserved
as magic cookies.  It also avoids most occasions where an error encoding must
be mapped from "-1 was an error" to "but NULL is *my* return error code".

A Larger Example

So, why would you care about Modula-3, given that the world seems to be
switching to C++ and Objective-C, or pouring megaspecmarks into Common
Lisp?  Simply put, "it ain't over 'til the fat lady sings."  C++ is an
endlessly flexible language, much worse so than C; measured by the ability
to write code which other programmers cannot understand or to write code
which even the author cannot understand or to write code which does not do
what it looks like it should be doing, C++ is the first language to eclipse
C.  (Sorry, Larry, C++ beat Perl by a couple of years.)  One could (and
has) argued that C++'s design not only permits bad code, it encourages it.
Common Lisp, on the other hand, is a beautiful, elegant language which will
someday join ADA in the museum of beached whales.

Of the languages whose definitions are in the public domain and for which
there are freely-available, portable implementations available for most of
the popular POSIX-like platforms, Modula-3 is the one in which it is
hardest to write code which does not do what it looks like it should be
doing, or which even the author cannot understand, or which other
programmers cannot understand.  You may not see this from the examples
shown so far, but consider the program in Figure 2, which sends an IP/UDP
datagram (think "packet") requesting the network time from all inetd(8)'s
on the local subnet, collects the replies, and prints the average or
"network" time.

================================================================== Figure 2
	UNSAFE MODULE Main;

	IMPORT Datagram, Netdb, Net, MyTime;            (* local hacks *)
	IMPORT Stdio, Wr, Fmt, Thread, Time, Text;      (* standard *)
	IMPORT Word, Ctypes;                            (* nonportable *)

	TYPE
	    T = Ctypes.long;    (* 64-bit machines will in be trouble here *)

	VAR
	    Done := FALSE;
	    Rcvd := 0;
	    Waits := 0;
	    NetTime: T;

	CONST
	    TimeDifferential = -2085978496;     	(* inetd(8)'s offset *)

	PROCEDURE ProtocolF(self: Thread.Closure): REFANY RAISES {} =
	VAR
	    port := Datagram.NewClient(NIL, mayBroadcast := TRUE);
	    server := Netdb.NewRemotePort("255.255.255.255", "time", "udp");
	    timeval := NEW(REF T);
	BEGIN
	    port.send(NIL, 0, server);  (* 0-length datagram is a "request" *)
	    LOOP
	        EVAL port.recv(timeval, BYTESIZE(timeval^), server);
	        timeval^ := Word.Minus(Net.ntohl(timeval^), TimeDifferential);
	        IF Rcvd = 0 THEN
	            NetTime := timeval^;
	        ELSE
	            NetTime := Word.Divide(Word.Plus(NetTime, timeval^), 2);
	        END;
	        INC(Rcvd);
	        Done := FALSE;
	    END;
	END ProtocolF;

	BEGIN
	    EVAL Thread.Fork(NEW(Thread.Closure, apply := ProtocolF));
	    REPEAT
	        Done := TRUE;
	        Time.LongPause(1);
	        INC(Waits);
	    UNTIL Done;
	    IF Rcvd = 0 THEN
	        Wr.PutText(Stdio.stdout, "No Replies.\n");
	    ELSE
	        NetTime := Word.Minus(NetTime, Waits);
	        Wr.PutText(Stdio.stdout,
	            "Network time: " & MyTime.TimeToText(NetTime) &
	            " (" & Fmt.Int(Rcvd) & " replies)\n");
	    END;
	END Main.
=============================================================== end Figure 2

One important note about this code: the Datagram module is a quick and dirty
hack that we cobbled together to test some assumptions about IP/UDP
performance; the actual IP/UDP interface supported in Modula-3 is likely to
be quite different.  Likewise the Netdb, Net, and MyTime modules are all
local hacks that you don't have and wouldn't want anyway.  As is true of any
language which is less than a decade old, Modula-3's standard libraries are
still evolving.

The program makes slightly contrived use of the Thread interface; the goal
is to keep collecting responses until none appear for one second.  A C
programmer would use alarm(2), or select(2) with a timeout.  This program
starts a thread which blocks in port.recv() (which, given the presence of
the Thread interface, was designed without any explicit timeouts of its
own); whenever a datagram comes in, this thread receives it and computes it
into the running average.  The main thread loops, waiting one second and
then exiting the loop only when no datagrams have been received by the other
thread during the last second.  The code is sloppy in that it should protect
its thread-shared variables with mutexes, but as a demonstration it is
already as complicated as would be useful.

The program is also of the "ugly and nonportable" variety; a more robust
implementation would hide all of the details of the Word ("unsigned")
arithmetic in other modules so that this module could do its job as
straighforwardly as possible.  We chose this example because it shows
Modula-3 code trying to deal with the UNIX system call interface.  This, in
other words, is as ugly as system-dependent Modula-3 source ever has to get.
You might wonder why we NEW() the timeval variable and dereference it every-
where rather than creating a normal variable and passing it by ADR() in the
one place we actually need its address.  This has to do with the declaration
of the Datagram object's recv method, which due to dampness behind its
authors' ears, was rather more selective than it could have been.

To get an idea of what is really possible given threads and garbage
collection, consider an IP/DNS name server which needs to concurrently
process multiple incoming and outgoing "zone transfers" over IP/TCP, all
the while receiving, forwarding, and generating DNS requests and replies
over IP/UDP.  The popular BIND name server forks a subprocess for each zone
transfer -- a major performance penalty if you don't have a copy-on-write
fork() and your nameserver core image is tens of megabytes in size.  BIND
also has a very busy select(2) at its core, along with a memory management
scheme that can make grown programmers want to quit their jobs and go drive
tow-trucks.  Given garbage collection and threads, the hardest parts of
this sort of program just obviously slide into place with almost zero
insertion force.  Any C programmer who likes to use the CPP to layer
garbage collection on top of malloc(3) and threads on top of select(2) will
probably not enjoy Modula-3 very much since all that stuff is done for you
and your application's code is mostly goal- rather than mechanism-oriented.

Comparisons

The features highlighted by the last example are: (1) variables can be
given types, or initial values, or both, and if both are specified then the
initial value must be of the given type; (2) this is also true of formal
procedure parameters; (3) actual procedure parameters may be given
positionally or by name; (4) aggregates may be returned by functions, or
assigned to local procedure ("auto") variables; (5) if you want to call a
typed procedure ("function") and throw away the result, you have to
explicitly EVAL it; (6) EVAL in Modula-3 does not do anything like what it
does in Lisp or Perl; (7) expressions of type TEXT, which includes "quoted
strings" and results of functions of type TEXT, can be catenated inline
with the "&" operator; (8) the ever-present newline ("\n") works as you'd
expect; (9) most statements are innately compound, which means that IF and
WHILE need an END, but BEGIN is meaningless for them; (10) dynamic
variables created with NEW can be forgotten about, with no explicit
deallocation; (11) expressions can be contained in parenthesis but need not
be, and the expression used for IF and WHILE and REPEAT can be
parenthesisless.

Features which are not highlighted in this example but which are
interesting: (1) (*comments (*can be*) nested*); (2) NEW can fill in or
override default values of fields in record ("struct") or object ("struct
with magic") types; (3) record and object fields can _have_ default values,
which, as with variables and formal procedure parameters, cause the type
to be imputed if no type is specified.

Differences from C which you will probably find bizarre or irritating: (1)
NEW takes as its argument a pointer type rather than the size or type of
the thing being allocated; (2) there are no (pre,post)-(inc,dec)rement
operators, so you have to use INC(x) for x++ and DEC(x) for x--, and
neither INC() or DEC returns the new value; (3) arith- metic on unsigned
integers is painful and awkward; (4) compilation time and object size are
both very large compared to PCC or GCC if you use the current version of
the freely-available DEC SRC compiler (which is the only one in existence
at this time); (5) case is significant even for built-ins, so you _must_
type a fair amount of your program text in UPPER CASE; (6) printf() is not
impossible but not straightforward, either.

Differences from C++ which will either make you tense or relieved: (1) there
are no enforced constructors or destructors, and though there is a convention
for constructors there is none for destructors; (2) multiple inheritance, long
considered either a botch or a blight (depending on who you ask), isn't here
at all.

The advantages (or disadvantages, depending on who you ask) of strong type
checking have already been argued elsewhere.  To the oft-quoted "strong
type-checking is for weak minds" argument, we counter that "software systems
are getting larger and more complex; programmers' minds are not."

History

Modula-3 was designed in the late 1980's by researchers at Digital's
Systems Research Center ("DEC SRC") in Palo Alto, California, and at the
Olivetti Research Center ("ORC") in Menlo Park, California.  It descends
most recently from Modula-2+, which came from Cedar and Mesa and Pascal;
Modula-3 was lightly cross-pollinated with Oberon, as Niklaus Wirth
(creator of Pascal, Modula-2, Oberon, and more recently Oberon-2) was on
sabbatical at DEC SRC during part of the time that Modula-3 was being
conceived.  Legend has it that Wirth's main contribution to Modula-3 was to
encourage its designers to leave things out; this "smallness" is apparent
in that Modula-3 is smaller by far than Modula-2+, though it is still
larger than Oberon or Oberon-2.

A portable implementation of Modula-3 was written at DEC SRC and has been
made more-or-less freely available by Digital Equipment Corporation.  This
compiler generates C as its intermediate language, which accounts for its
portability but also its moderate speed and largish object code size; on
the bright side it is free, and runs on most of the common POSIX-like
platforms including Ultrix (MIPS and VAX), SunOS (SPARC and 68000), RS6000,
and HP-UX (PA-RISC and 68000).  More ports are under way, as is development
and standardization of the runtime library.  There are restrictions on the
use of this compiler for commercial products, but you should get those details
by reading the release notes that come with the DEC SRC compiler.

Future

To many programmers, C and C++ seem like forgone conclusions.  Modula-3 is
the only serious challenger to C++ as the next massively popular system and
application programming language.  This author believes that there is a good
chance that there will be a market for programmers and CASE tools in Modula-3
in the next year or two, since it is a practical yet elegant software design
and implementation tool which encourages clean, bug-free code and is a true
pleasure to work in no matter how large the project might be (or become).

If you enjoyed Modula-2 or Pascal but found them incomplete and limiting,
it's a safe bet that you will find whatever you were missing...in Modula-3.

If C is driving you nuts but you get cold sweats whenever you think about
C++, you may find a way out of your dilemma...in Modula-3.

Resources

"System Programming with Modula-3", Greg E. Nelson et al, Prentice Hall

"Modula-3", Samual P. Harbison, Prentice Hall

comp.lang.modula3			(usenet newsgroup)

m3@src.dec.com or decwrl!m3		(mailing list, gatewayed
					 to comp.lang.modula3)

gatekeeper.dec.com:~ftp/DEC/Modula-3/*	(a freely available, portable
					 Modula-3 compiler for several
					 UNIX variants including Ultrix,
					 SunOS, HP-UX.)

$Id: m3-art,v 1.4 1992/10/13 16:47:07 vixie Exp $
========================== end ;login: article ================================
--
Paul Vixie, DEC Network Systems Lab	
Palo Alto, California, USA         	"Don't be a rebel, or a conformist;
<vixie@pa.dec.com> decwrl!vixie		they're the same thing, anyway.  Find
<paul@vix.com>     vixie!paul		your own path, and stay on it."  -me


======================================================================= 53 ===
Date:    26 Apr 93 20:29:25 GMT
From:    holt@turing.toronto.edu (Ric Holt)
Subject: Object Oriented Turing Demo on FTP


OBJECT ORIENTED TURING: DEMO AVAILABLE VIA FTP

OOT (Object Oriented Turing) is a programming language that has been 
developed at the University of Toronto.  An OOT demo, which includes the 
fully implemented language, is available for Sun/4's running X windows.  
See below for instructions to copy the demo to your site.

OOT supports the standard OOPL features of information hiding, classes,
polymorphism and generics, as well as the usual features in C and Pascal 
style languages.  It also supports concurrency, exception handling 
and system programming (pointer arithmetic, bit manipulation, etc).  

The OOT environment is designed for teaching Computer Science.
It is being used in introductory programming courses, courses
on OO concepts, compiler courses, OS courses, etc.

The OOT environment is fully integrated, with multi-window editing, turbo 
speed compiler, integrated color graphics, GUI user interface, implicit MAKE, 
on-line manual, integrated demos, etc.  The system includes an experimental
CASE tool with an interface browser and a visual system browser.

HOW TO ACCESS THE OBJECT ORIENTED TURING DEMO

You can get the instructions for accessing the OOT demo as follows.
Start up FTP (File Transfer Protocol) by giving this UNIX command:
		% ftp 128.100.1.192
When you are asked for your "name", you should type:
		anonymous
When you are asked for your "password", you should type your 
email address, eg:
		jsmith@csri.toronto.edu
Once you have successfully "logged in", give the following commands to FTP:
		ftp> cd pub
		ftp> get ootDistrib
Once the transfer is complete, exit FTP with the command:
		ftp> quit
Now read the your file 'ootDistrib', which contains the instructions for 
accessing the OOT demo.

-- 
Ric Holt		University of Toronto		holt@turing.toronto.edu


======================================================================= 54 ===
Date:    27 Apr 93 09:29:11 GMT
From:    clfung@cs.ust.hk (Fung Chi Leung)
Subject: BUG in Moudla3?


Hi folks,

  Here is a set of small programs to demonstrate a tricky bug in 
  M3.  The aim of these set of programs is to copy a file, "test.dat"
  to "result.dat" by two indenpendent threads, play and record.  You
  can compile the program by "m3make -f memakefile.gc" and 
  create a file "test.dat" to test it.  The file "test.dat" should
  be greater than 50k in order to let bug occur before the program
  endedi, you can simple copy the executable GCTEST to test.dat.  
  Here is a short description of each file:

  GenKeyList.ig,mg - The generic module of a simple list.
  CMMRecvQueueElement.i3,m3 - Data type definition for the generic list
			      module.
  DMMRecvQueue.i3,m3 - Instantiation of the generic list using
		       CMMRecvQueueElement.
  PMMO.i3,m3 - The play and record thread.
  ModuleA.i3 - Global defination of the variables.
  GCTEST.m3 - Main program.

  I found that the problem is come from the empty record definition
  in the file, CMMRecvQueueElement.i3.  If you define an empty 
  record there, the garbage collector will have an run-time error 
  after a short while.  However, if you insert a dummy field into 
  the record or simple delete the empty record, everything will be 
  alright.  

  My system is sun sparc station running sunos 4.1.3 and the version
  of m3 is 2.11.  
   
  Pls let me know if you have any idea about this, thanks.
  

#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 04/27/1993 09:00 UTC by clfung@cssu11
# Source directory /staff1/cs/clfung/Project/src/BUG/FINAL
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    276 -rw-r----- CMMRecvQueueElement.i3
#     60 -rw-r----- CMMRecvQueueElement.m3
#     78 -rw-r----- DMMRecvQueue.i3
#     75 -rw-r----- DMMRecvQueue.m3
#    263 -rw-r----- DataMessageManager.i3
#   1576 -rw-r----- DataMessageManager.m3
#    302 -rw-r----- GCTEST.m3
#    643 -rw-r----- GenKeyList.ig
#   2401 -rw-r----- GenKeyList.mg
#    129 -rw-r----- ModuleA.i3
#    225 -rw-r----- PMMO.i3
#   2957 -rw-r----- PMMO.m3
#    175 -rw-r----- m3makefile.gc
#
# ============= CMMRecvQueueElement.i3 ==============
if test -f 'CMMRecvQueueElement.i3' -a X"$1" != X"-c"; then
	echo 'x - skipping CMMRecvQueueElement.i3 (File already exists)'
else
echo 'x - extracting CMMRecvQueueElement.i3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'CMMRecvQueueElement.i3' &&
INTERFACE CMMRecvQueueElement;
X
TYPE
X  BufferType = REF ARRAY OF CHAR;
X
X  Key = RECORD
(* IF you comment the line below, there will be a run-time error *)
(*    i : INTEGER; *)
X  END;
X
X  T = RECORD
X    rKey : Key; 
X    pacBuffer : BufferType;
X  END;
X
END CMMRecvQueueElement.
SHAR_EOF
chmod 0640 CMMRecvQueueElement.i3 ||
echo 'restore of CMMRecvQueueElement.i3 failed'
Wc_c="`wc -c < 'CMMRecvQueueElement.i3'`"
test 276 -eq "$Wc_c" ||
	echo 'CMMRecvQueueElement.i3: original size 276, current size' "$Wc_c"
fi
# ============= CMMRecvQueueElement.m3 ==============
if test -f 'CMMRecvQueueElement.m3' -a X"$1" != X"-c"; then
	echo 'x - skipping CMMRecvQueueElement.m3 (File already exists)'
else
echo 'x - extracting CMMRecvQueueElement.m3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'CMMRecvQueueElement.m3' &&
MODULE CMMRecvQueueElement;
X
BEGIN
END CMMRecvQueueElement.
SHAR_EOF
chmod 0640 CMMRecvQueueElement.m3 ||
echo 'restore of CMMRecvQueueElement.m3 failed'
Wc_c="`wc -c < 'CMMRecvQueueElement.m3'`"
test 60 -eq "$Wc_c" ||
	echo 'CMMRecvQueueElement.m3: original size 60, current size' "$Wc_c"
fi
# ============= DMMRecvQueue.i3 ==============
if test -f 'DMMRecvQueue.i3' -a X"$1" != X"-c"; then
	echo 'x - skipping DMMRecvQueue.i3 (File already exists)'
else
echo 'x - extracting DMMRecvQueue.i3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'DMMRecvQueue.i3' &&
INTERFACE DMMRecvQueue = GenKeyList( CMMRecvQueueElement )
X
END DMMRecvQueue.
SHAR_EOF
chmod 0640 DMMRecvQueue.i3 ||
echo 'restore of DMMRecvQueue.i3 failed'
Wc_c="`wc -c < 'DMMRecvQueue.i3'`"
test 78 -eq "$Wc_c" ||
	echo 'DMMRecvQueue.i3: original size 78, current size' "$Wc_c"
fi
# ============= DMMRecvQueue.m3 ==============
if test -f 'DMMRecvQueue.m3' -a X"$1" != X"-c"; then
	echo 'x - skipping DMMRecvQueue.m3 (File already exists)'
else
echo 'x - extracting DMMRecvQueue.m3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'DMMRecvQueue.m3' &&
MODULE DMMRecvQueue = GenKeyList( CMMRecvQueueElement )
X
END DMMRecvQueue.
SHAR_EOF
chmod 0640 DMMRecvQueue.m3 ||
echo 'restore of DMMRecvQueue.m3 failed'
Wc_c="`wc -c < 'DMMRecvQueue.m3'`"
test 75 -eq "$Wc_c" ||
	echo 'DMMRecvQueue.m3: original size 75, current size' "$Wc_c"
fi
# ============= DataMessageManager.i3 ==============
if test -f 'DataMessageManager.i3' -a X"$1" != X"-c"; then
	echo 'x - skipping DataMessageManager.i3 (File already exists)'
else
echo 'x - extracting DataMessageManager.i3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'DataMessageManager.i3' &&
INTERFACE DataMessageManager;
X
TYPE 
X  BufferType = REF ARRAY OF CHAR;
X
T <: PublicT;
X
PublicT = OBJECT
METHODS
X
X  Enqueue( pacDataMsg : BufferType );
X
X  SendDataMsg( pacDataMsg : BufferType );
X
X  Init( ) : PublicT;
X
X  InitLoop( );
X
END;
X
END DataMessageManager.
SHAR_EOF
chmod 0640 DataMessageManager.i3 ||
echo 'restore of DataMessageManager.i3 failed'
Wc_c="`wc -c < 'DataMessageManager.i3'`"
test 263 -eq "$Wc_c" ||
	echo 'DataMessageManager.i3: original size 263, current size' "$Wc_c"
fi
# ============= DataMessageManager.m3 ==============
if test -f 'DataMessageManager.m3' -a X"$1" != X"-c"; then
	echo 'x - skipping DataMessageManager.m3 (File already exists)'
else
echo 'x - extracting DataMessageManager.m3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'DataMessageManager.m3' &&
UNSAFE MODULE DataMessageManager;
X
IMPORT Wr, Stdio, Text, Thread;
IMPORT CMMRecvQueueElement, DMMRecvQueue;
FROM ModuleA IMPORT oPMMOTest;
X
X
REVEAL T = PublicT BRANDED OBJECT
X  mQueue : Thread.Mutex; 
X  oRecvQueue : DMMRecvQueue.T; 
OVERRIDES
X  Enqueue := Enqueue;
X  InitLoop := InitLoop;
X  Init := Init;
END;
X
X
X
X
(* Init : Initialize all the internal variables and start to scan
X *        through the receiving queue and distribute the data packets
X *        to corresponding object.
X *)
PROCEDURE Init( self : T ) : PublicT =
BEGIN
X  self.mQueue := NEW( Thread.Mutex );
X  self.oRecvQueue := NEW( DMMRecvQueue.T );
X  EVAL Thread.Fork( NEW( InitLoopDaemon, oDataMgr := self ) );
X  RETURN self;
END Init;
X
X
X
X
TYPE
X  InitLoopDaemon = Thread.Closure OBJECT
X    oDataMgr : T;
X  OVERRIDES
X    apply := InitLoopDaemonHandler;
X  END;
X
X
PROCEDURE InitLoopDaemonHandler( self : InitLoopDaemon ) : REFANY =
BEGIN
X  self.oDataMgr.InitLoop( );
X  RETURN NIL;
END InitLoopDaemonHandler;
X
X
X
PROCEDURE InitLoop( self : T ) =
VAR
X  rItem : CMMRecvQueueElement.T;
BEGIN
X  LOOP
X    TRY
X      LOCK self.mQueue DO
X	rItem := self.oRecvQueue.GetQueueHead( );
X        oPMMOTest.Enqueue( rItem.pacBuffer );
X      END; (* LOCK *)
X    EXCEPT
X    | DMMRecvQueue.ListEmpty => 
X	Thread.Yield( );
X    END; (* TRY *)
X  END; (* LOOP *)
END InitLoop;  
X
X
PROCEDURE Enqueue( self : T; pacDataMsg : BufferType ) =
VAR
X  rItem : CMMRecvQueueElement.T; 
BEGIN
X  rItem.pacBuffer := pacDataMsg;
X  LOCK self.mQueue DO
X    self.oRecvQueue.InsertQueueEnd( rItem );
X  END; 
END Enqueue;
X
X
BEGIN
END DataMessageManager.
SHAR_EOF
chmod 0640 DataMessageManager.m3 ||
echo 'restore of DataMessageManager.m3 failed'
Wc_c="`wc -c < 'DataMessageManager.m3'`"
test 1576 -eq "$Wc_c" ||
	echo 'DataMessageManager.m3: original size 1576, current size' "$Wc_c"
fi
# ============= GCTEST.m3 ==============
if test -f 'GCTEST.m3' -a X"$1" != X"-c"; then
	echo 'x - skipping GCTEST.m3 (File already exists)'
else
echo 'x - extracting GCTEST.m3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'GCTEST.m3' &&
MODULE Main;
X
IMPORT RTHeap;
IMPORT PMMO, DataMessageManager;
FROM ModuleA IMPORT oPMMOTest, oDMMTest;
X
BEGIN
X  (*
X  RTHeap.GCOff( );
X  *)
X  oPMMOTest := NEW( PMMO.T );
X  oDMMTest := NEW( DataMessageManager.T );
X  oPMMOTest.Init( );
X  EVAL oDMMTest.Init( );
X  oPMMOTest.Start( );
X  LOOP END;
END Main.
SHAR_EOF
chmod 0640 GCTEST.m3 ||
echo 'restore of GCTEST.m3 failed'
Wc_c="`wc -c < 'GCTEST.m3'`"
test 302 -eq "$Wc_c" ||
	echo 'GCTEST.m3: original size 302, current size' "$Wc_c"
fi
# ============= GenKeyList.ig ==============
if test -f 'GenKeyList.ig' -a X"$1" != X"-c"; then
	echo 'x - skipping GenKeyList.ig (File already exists)'
else
echo 'x - extracting GenKeyList.ig (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'GenKeyList.ig' &&
GENERIC INTERFACE GenKeyList( Element );
X
EXCEPTION 
X  ListFull; (* raise when it is a bounded limit queue and 
X	     * the number of element is greater than the limit 
X	     *)
X  ListEmpty; (* raise when removing a node from a empty list *)
X
TYPE 
X  Status = BOOLEAN;
X  
X  T <: PublicT;
X  PublicT = OBJECT
X  METHODS
X
X    (* Set the upper boundary of the queue *)
X    Init( nLength : CARDINAL := 0 ): PublicT;
X
X    (* Insert a node at the queue end *)
X    InsertQueueEnd( rItem : Element.T ) RAISES { ListFull };
X
X    (* Return the queue head node *)
X    GetQueueHead( ) : Element.T RAISES { ListEmpty };
X
X  END; (* OBJECT *)
X
END GenKeyList.
SHAR_EOF
chmod 0640 GenKeyList.ig ||
echo 'restore of GenKeyList.ig failed'
Wc_c="`wc -c < 'GenKeyList.ig'`"
test 643 -eq "$Wc_c" ||
	echo 'GenKeyList.ig: original size 643, current size' "$Wc_c"
fi
# ============= GenKeyList.mg ==============
if test -f 'GenKeyList.mg' -a X"$1" != X"-c"; then
	echo 'x - skipping GenKeyList.mg (File already exists)'
else
echo 'x - extracting GenKeyList.mg (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'GenKeyList.mg' &&
GENERIC MODULE GenKeyList( Element );
X
TYPE
X  PtrNode = REF RECORD (* Abstract node of type element.T *)
X    rContent : Element.T; (* data type of node element *)
X    rpNext : PtrNode := NIL;  (* Pointer to next node *)
X  END;
X
REVEAL T = PublicT BRANDED OBJECT
X    rpHead, rpTail, rpCurrent : PtrNode; (* head and tail pointer *)
X    (* If nMaxListLength = 0 THEN there is no list queue limiation *)
X    nMaxListLength : CARDINAL; 	(* maximum list length *)
X    nCurListLength : CARDINAL;  (* current list length *)
X  OVERRIDES
X    Init := Init;
X    InsertQueueEnd := InsertQueueEnd;
X    GetQueueHead := GetQueueHead;
X  END;
X
X
(* Init: Initialize all the internal variables 
X * IN: nLength - Maximum list length
X *)
PROCEDURE Init( self : T; nLength : CARDINAL := 0 ) : PublicT =
BEGIN
X  IF self = NIL THEN
X    self := NEW( T ); 
X  END; (* IF *)
X  self.rpHead := NIL; self.rpTail := NIL; self.rpCurrent := NIL;
X  self.nMaxListLength := nLength;
X  self.nCurListLength := 0;
X  RETURN self;
END Init;
X
X
(* InsertQueueEnd: Insert a item to the end of the list
X * IN: rItem - Node item to be added
X * ECP: ListFull - Raise if the list larger than the maximum list length
X *) 
PROCEDURE InsertQueueEnd( self : T; rItem : Element.T ) RAISES { ListFull } =
VAR prTmp : PtrNode;
BEGIN
X  IF self.nCurListLength >= self.nMaxListLength AND self.nMaxListLength # 0 TH
EN
X    RAISE ListFull;
X  ELSE
X    prTmp := NEW( PtrNode );
X    prTmp.rpNext := NIL;
X    prTmp.rContent := rItem;
X    IF self.rpTail = NIL THEN (* Case of none element *)
X      self.rpHead := prTmp;
X      self.rpTail := prTmp;
X    ELSE
X      self.rpTail.rpNext := prTmp;
X      self.rpTail:= prTmp;
X    END; (* IF *)
X    INC( self.nCurListLength );
X  END; (* IF *)
END InsertQueueEnd;
X
X
(* GetQueueHead: Remove and return the first element from the list
X * OUT: The First element
X * ECP: ListEmpty - Raise if the list is empty
X *)
PROCEDURE GetQueueHead( self : T ) : Element.T RAISES { ListEmpty } =
VAR rpTmp : PtrNode;
BEGIN
X  IF self.nCurListLength <= 0 THEN
X    RAISE ListEmpty;
X  ELSE
X    IF self.rpHead = self.rpTail THEN (* Case of one element *)
X      rpTmp := self.rpHead;
X      self.rpHead := NIL;
X      self.rpTail := NIL;
X    ELSE
X      rpTmp := self.rpHead;
X      self.rpHead := self.rpHead.rpNext;
X    END; (* IF *)
X    DEC( self.nCurListLength );
X    RETURN rpTmp.rContent;
X  END; (* IF *)
END GetQueueHead;
X
X
BEGIN
END GenKeyList.
SHAR_EOF
chmod 0640 GenKeyList.mg ||
echo 'restore of GenKeyList.mg failed'
Wc_c="`wc -c < 'GenKeyList.mg'`"
test 2401 -eq "$Wc_c" ||
	echo 'GenKeyList.mg: original size 2401, current size' "$Wc_c"
fi
# ============= ModuleA.i3 ==============
if test -f 'ModuleA.i3' -a X"$1" != X"-c"; then
	echo 'x - skipping ModuleA.i3 (File already exists)'
else
echo 'x - extracting ModuleA.i3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ModuleA.i3' &&
INTERFACE ModuleA;
X
IMPORT PMMO, DataMessageManager;
X
VAR
X  oPMMOTest : PMMO.T;
X  oDMMTest : DataMessageManager.T;
X
END ModuleA.
SHAR_EOF
chmod 0640 ModuleA.i3 ||
echo 'restore of ModuleA.i3 failed'
Wc_c="`wc -c < 'ModuleA.i3'`"
test 129 -eq "$Wc_c" ||
	echo 'ModuleA.i3: original size 129, current size' "$Wc_c"
fi
# ============= PMMO.i3 ==============
if test -f 'PMMO.i3' -a X"$1" != X"-c"; then
	echo 'x - skipping PMMO.i3 (File already exists)'
else
echo 'x - extracting PMMO.i3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'PMMO.i3' &&
INTERFACE PMMO;
X
CONST 
X  BUFFERSIZE = 512;
X
TYPE
BufferType = REF ARRAY OF CHAR;  
X
T <: PublicT;
X
PublicT = OBJECT
METHODS
X  Record( );
X  Play( );
X  Init( );
X  Start( );
X  Enqueue( pacBuffer : BufferType );
END;
X
END PMMO.
SHAR_EOF
chmod 0640 PMMO.i3 ||
echo 'restore of PMMO.i3 failed'
Wc_c="`wc -c < 'PMMO.i3'`"
test 225 -eq "$Wc_c" ||
	echo 'PMMO.i3: original size 225, current size' "$Wc_c"
fi
# ============= PMMO.m3 ==============
if test -f 'PMMO.m3' -a X"$1" != X"-c"; then
	echo 'x - skipping PMMO.m3 (File already exists)'
else
echo 'x - extracting PMMO.m3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'PMMO.m3' &&
MODULE PMMO;
X
IMPORT Wr, Rd, Text, Char, Thread, FileStream, Stdio;
IMPORT DMMRecvQueue, CMMRecvQueueElement;
FROM ModuleA IMPORT oDMMTest;
X
REVEAL T = PublicT BRANDED OBJECT
X  mPMMOQueue : Thread.Mutex;
X  oPMMOQueue : DMMRecvQueue.T;
OVERRIDES
X  Enqueue := Enqueue;
X  Play := Play;
X  Record := Record;
X  Start := Start;
X  Init := Init;
END;
X
X
PROCEDURE Init( self : T ) =
BEGIN
X  self.mPMMOQueue := NEW( Thread.Mutex );
X  self.oPMMOQueue := NEW( DMMRecvQueue.T );
END Init;
X
X
PROCEDURE Enqueue( self : T; pacBuffer : BufferType ) =
VAR
X  rNewItem : CMMRecvQueueElement.T;
BEGIN
X  rNewItem.pacBuffer := pacBuffer;
X  LOCK self.mPMMOQueue DO
X    self.oPMMOQueue.InsertQueueEnd( rNewItem );
X  END; 
END Enqueue;
X
PROCEDURE Record( self : T ) =
VAR
X  pFileId : Rd.T;
X  pacBuffer : BufferType;
X  iCount, iSwitch : INTEGER := 0;
BEGIN
X  pFileId := FileStream.OpenRead( "test.dat" );
X  REPEAT
X    (* The first byte is used to indicate the end of file *)
X    (* When it is the last buffer, the first byte is set to 'e',
X     * otherwise set to 'n' 
X     *)
X    pacBuffer := Char.NewArray( BUFFERSIZE+1, ' ');
X    iCount := 0;
X    WHILE ( NOT Rd.EOF ( pFileId ) AND iCount < BUFFERSIZE ) DO 
X      pacBuffer[iCount+1] := Rd.GetChar( pFileId );
X      iCount := iCount+1;
X    END;
X    Wr.PutText( Stdio.stderr, "Read one buffer\n" );
X    IF NOT Rd.EOF( pFileId ) THEN
X      pacBuffer[0] := 'n';
X    ELSE
X      pacBuffer[0] := 'e';
X    END;
X    oDMMTest.Enqueue( pacBuffer );
X    (*
X    iSwitch := iSwitch + 1;
X    IF iSwitch = 2 THEN
X      iSwitch := 0;
X      Thread.Yield( );
X    END;
X    *)
X  UNTIL Rd.EOF( pFileId );
X  Rd.Close( pFileId );
END Record;
X
X
PROCEDURE Play( self : T ) =
VAR
X  pFileId : Wr.T;
X  pacBuffer : BufferType;
X  rItem : CMMRecvQueueElement.T;
X  bEnd := FALSE;
BEGIN
X  pFileId := FileStream.OpenWrite( "result.dat" );
X  REPEAT
X    TRY  
X      LOCK self.mPMMOQueue DO
X	rItem := self.oPMMOQueue.GetQueueHead( );
X      END;
X      pacBuffer := rItem.pacBuffer;
X      FOR iTmp := 1 TO BUFFERSIZE DO
X	Wr.PutChar( pFileId, pacBuffer[iTmp] );
X      END;
X      Wr.PutText( Stdio.stderr, "Write one buffer\n" );
X      IF pacBuffer[0] = 'e' THEN
X	bEnd := TRUE;
X      END;
X    EXCEPT
X    | DMMRecvQueue.ListEmpty =>
X	(*
X	Thread.Yield( );
X	*)
X    END;
X  UNTIL bEnd;
X  Wr.Close( pFileId );
END Play;
X
X
TYPE
X  PlayThread = Thread.Closure OBJECT
X    oPMMO : T;
X  OVERRIDES
X    apply := PlayThreadHandler;
X  END;
X
X  RecordThread = Thread.Closure OBJECT
X    oPMMO : T;
X  OVERRIDES
X    apply := RecordThreadHandler;
X  END;
X
X
PROCEDURE Start( self : T ) =
BEGIN
X  EVAL Thread.Fork( NEW( RecordThread, oPMMO := self ) );
X  EVAL Thread.Fork( NEW( PlayThread, oPMMO := self ) );
END Start;
X
X
PROCEDURE PlayThreadHandler( self : PlayThread ) : REFANY =
BEGIN
X  self.oPMMO.Play( );
X  RETURN NIL;
END PlayThreadHandler;
X
PROCEDURE RecordThreadHandler( self : RecordThread ) : REFANY =
BEGIN
X  self.oPMMO.Record( );
X  RETURN NIL;
END RecordThreadHandler;
X
BEGIN
END PMMO.
SHAR_EOF
chmod 0640 PMMO.m3 ||
echo 'restore of PMMO.m3 failed'
Wc_c="`wc -c < 'PMMO.m3'`"
test 2957 -eq "$Wc_c" ||
	echo 'PMMO.m3: original size 2957, current size' "$Wc_c"
fi
# ============= m3makefile.gc ==============
if test -f 'm3makefile.gc' -a X"$1" != X"-c"; then
	echo 'x - skipping m3makefile.gc (File already exists)'
else
echo 'x - extracting m3makefile.gc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'm3makefile.gc' &&
module(DMMRecvQueue)
module(CMMRecvQueueElement)
module(PMMO)
module(DataMessageManager)
generic_module(GenKeyList)
interface(ModuleA)
implementation(GCTEST)
program(GCTEST)
X
SHAR_EOF
chmod 0640 m3makefile.gc ||
echo 'restore of m3makefile.gc failed'
Wc_c="`wc -c < 'm3makefile.gc'`"
test 175 -eq "$Wc_c" ||
	echo 'm3makefile.gc: original size 175, current size' "$Wc_c"
fi
exit 0

--
Leung [Chi-Leung Fung] | email: clfung@cs.ust.hk | phone: (852) 358 7023
Smile, it makes people wonder what you are thinking.


======================================================================= 55 ===
Date:    Tue, 27 Apr 93 15:53:10 GMT
From:    kalsow@src.dec.com (Bill Kalsow)
Subject: Re: BUG in Moudla3?

Thanks for the bug report.  I've fixed the problem in my copy of
the compiler.  The fix will be included in the next release.

The problem was that the compiler was generating "struct { int filler; }"
for empty records, but claiming that they occupied zero bytes.
Empty structs cause C compilers to get grumpy.

The workaround is to avoid empty records in structures that are
heap allocated.

If you're desperate, the patch is to add the five marked lines below
at about line 181 of compiler/src/types/RecordType.m3:

     (* assign the final offsets to each field *)
     SizeAndAlignment (p.scope, p.recSize, p.align);
>    IF (p.recSize = 0) THEN
>      (* add the 'filler' field *)
>      p.align   := MAX (Target.INTSIZE, Target.STRUCTURESIZEBOUNDARY);
>      p.recSize := RoundUp (Target.INTSIZE, p.align);
>    END;

    (* compute the hash value for this record *)
    hash := Word.Plus (Word.Times (943, p.recSize), p.align);

Please send bug reports to m3-request@src.dec.com.

Thanks
  - Bill Kalsow



======================================================================= 56 ===
Date:    27 Apr 93 23:59:06 -0600
From:    rustad@mhd.moorhead.msus.edu
Subject: Survey Pros & Cons OOP

Object-Oriented Programming Survey

This survey is a meant to find the current relationship between 
programmers and Object-Oriented Programming.  Please return this survey 
before May 5, 1993.  Return to rustad@mhd.moorhead.msus.edu

Would you like a copy of the published statistics? (yes/no) _______
Your Occupation:
__________________________________________________________________________
Years of Programming Experience:
__________________________________
Programming Languages you're associated with:
__________________________________________________________________________
Years of OOP experience:
__________________________________
Your preferred OOP language:
__________________________________________________________________________
Is there an advantage to OOP (yes/no) _________
Is OOP coding faster than traditional programming (yes/no) _________
Is OOP maintenance quicker and easier than traditional (yes/no or opinion):
__________________________________________________________________________
Comments: (pros & cons with Object-Oriented Programming)





======================================================================= 57 ===
Date:    29 Apr 1993 08:49:45 GMT
From:    laverman@cs.rug.nl (Bert Laverman)
Subject: Small patch to RCS to recognize modula-3 files

After having to edit an RCS maintained file for the umptienth time,
I decided to patch RCS so it will recognize the modula-3 filename
suffixes (i3, ig, m3, mg) and use the currect comment leader for
multiline comments (" * ") in stead of the annoying "# ".

*** rcsfnms.old	Thu Apr 29 10:43:34 1993
--- rcsfnms.c	Thu Apr 29 10:43:53 1993
***************
*** 189,199 ****
--- 189,203 ----
          "h",   " * ",   /* C-header    */
  	"hpp", "// ",	/* C++ header  */
  	"hxx", "// ",
+ 	"i3",  " * ",	/* Modula-3 interface */
+ 	"ig",  " * ",	/* Modula-3 generic interface */
          "l",   " * ",   /* lex      NOTE: conflict between lex and franzlisp 
*/
  	"lisp",";;; ",	/* Lucid Lisp  */
  	"lsp", ";; ",	/* Microsoft Lisp */
+ 	"m3",  " * ",	/* Modula-3 Module */
  	"mac", ";; ",	/* macro (DEC-10, MS-DOS, PDP-11, VMS, etc) */
  	"me",  ".\\\" ",/* me-macros   t/nroff*/
+ 	"mg",  " * ",	/* Modula-3 generic module */
  	"ml",  "; ",    /* mocklisp    */
  	"mm",  ".\\\" ",/* mm-macros   t/nroff*/
  	"ms",  ".\\\" ",/* ms-macros   t/nroff*/

Greetings, Bert
-- 
#include <std/disclaimer>

  Bert Laverman,  Dept. of Computing Science, Groningen University
  Friendly mail to: laverman@cs.rug.nl      The rest to: /dev/null


======================================================================= 58 ===
Date:    Fri, 30 Apr 93 01:15:15 GMT
From:    msm@src.dec.com
Subject: Re: seeking trestle/mt experiences

Date: Thu, 29 Apr 93 18:14:58 -0700
X-Received: by gillie.pa.dec.com; id AA03154; Thu, 29 Apr 93 18:15:08 -0700
X-Received: by src-news.pa.dec.com; id AA05733; Thu, 29 Apr 93 18:15:12 -0700
X-Mts: smtp


A while ago, David Sternlicht asked about experience with locking 
levels, and with the locking strategies used in Trestle.  Here's 
my perspective, after a brief intro: 

For those not familiar with the intricacies of locking in Trestle, 
the main thing to be aware of is that there are some, since we're 
trying to accomodate multi-threaded applications without falling 
into race conditions.

In particular, we want to deliver events to the application in a 
way that's consistent with the window tree at the time we deliver 
the event.  Since VBTs do event propagation for themselves (as opposed 
to having a centralized mechanism containing the entire window tree), 
there are really only three alternatives:

1) while relaying the event down the tree, use the local geometry, 
and don't worry about it being the same at the time the method of 
that split goes on to relay things further.  The problem with this 
is that there's no guarantee that the position of the button click 
(say) will still even be inside the window when we get around to 
processing it.  Thus, it's possible that an event will have to be 
discarded, since we won't know where to send it.  We decided that 
users that clicked while their application was rearranging itself 
shouldn't care which window got the button press, but they ought 
to be able to count on the fact that some window that will, and that 
it should be a window that could have received the button press if 
event delivery was infinitely fast compared to rearranging.

2) as in 1), except that we keep a versioned history of the window 
tree.  When relaying an event, we can use the geometry as of the 
time of the event.  This has many virtues, along with one serious 
drawback: it's really annoying to implement.  Since we wanted split 
writing to be easy (and full consistency would require that leaf 
VBT writers also support historied geometry!) we reluctantly decided 
that this was too much of a burden.

3) as in 1), except that we lock the geometry during event delivery, 
so that everything is consistent with some version of the layout.  
The problem with this is that it means that some lock on the geometry 
will be held even while we're delivering events to normal client 
code.  That means that the procedures they call in such a state must 
support being called with this lock, VBT.mu, held.  Since this is 
supposed to be our geomtry lock, we also need client code that intends 
to modify the window tree to acquire VBT.mu.

In fact, for some actions, we allow a finer-grain of locking, VBT.mu.v, 
which is v's share of VBT.mu.  We use this when it's safe to deliver 
events concurrently to all the subwindows of a window; for example 
when we're asking the application to repair damage.  This makes the 
assumption that it's unreasonable for an application to change its 
overall layout in response to having a small piece fix some damage.

We could have decided to step outside the locks provided by the language, 
and support thread-reentrant locks; that is, a mutex which can be 
repeatedly reacquired by a single thread.  We chose not to, since 
it complicates entry and exit from the lock, it's against SRC religion, 
and it doesn't help an application that wants to do some work synchronously 
in a forked thread.  It would have permitted us to claim that everything 
was a relatively simple monitor, howeve; one where we would hide 
the work of acquiring or reacquiring the mutex as needed.

At any rate, to support multi-threaded programs, we would still have 
had to tell programmers what locks were held when callbacks were 
activated, and what locks they needed to hold (or make sure stayed 
held) to make a call.

The locking level scheme that we adopted is relatively simple: to 
avoid deadlock, we assume that there's a partial order on locks, 
with VBT.mu down near the bottom, and that programs can only acquire 
a lock if every lock they hold is smaller in the partial order.  

Every method declaration, callback procedure parameter, and procedure 
has an annotation that describes what locks may, will, or must be 
held when the procedure is activated; for example, a method may say 
LL.sup = VBT.mu; this means that on entry (and exit) VBT.mu will 
be held, and no greater lock will be.  LL, the locking level, is 
just the set of locks that are stably held in the environment of 
the calling thread (if there's a thread synchronously waiting for 
this thread to do something, and it holds locks, you should count 
those, too).  LL.sup denotes the supremum of LL, so its the tightest 
lock held (or held for) the thread.  Thus, it's safe for this thread 
to call any procedure that expects VBT.mu IN LL, or to acquire 
any mutex greater than VBT.mu in order to call some procedure with 
a more demanding locking level.  It mustn't call a procedure that 
expects LL.sup < VBT.mu.

To keep track of the partial ordering, we annotate declarations of 
mutexes with a description of where they fall in the partial order, 
in comparison with all of the mutexes that we reasonably expect to 
be in the scope of any program that imports the interface where this 
mutex is declared.  Sometimes we'll just say that a mutex is maximal; 
we usually do this for mutexes that are used by implementations that 
don't make any out calls.

Some clients may import essentially disconnected parts of the mutex 
space.  In this case, it's incumbent on the client to discover if 
there's any secret implementation-dependent ordering of the mutexes 
that it ought to respect; in general, it's safest not to try to define 
an ordering between them.

In addition, to solve data race conditions, we annotate the declaration 
of a variable, or a field of a record or object, with the locks that 
protect it.  Our usual policy is that you need to hold any one of 
the locks in order to read the data, and all of them in order to 
write.  This comes in handy when you have some data that has to be 
read under uncontrolled circumstances (like the clipping information 
you need in order to paint), but which you only modify when something 
exciting is happening.

At any rate, Greg and I found this technique invaluable in building 
Trestle.  Before we invented our notation for this, we basically 
had to keep the knowledge of lock ordering and procedure requirements 
in our heads, which proved to be quite fallible over the course of 
time; we had a modest number of deadlocks, and more race conditions 
than I care to recall in the very earliest versions of Trestle (circa 
1986-7; the rewrite in M3 has always been pretty clean in this area).  
Over the years, we've even gained a few converts: when you write 
a large system, it just gets too hard to keep it all in your head, 
and potential race conditions invariably happen; the really good 
ones usually don't happen until several months after you've shipped 
some library to a bunch of new programmers and completely forgotten 
exactly how everything worked.

By not having reentrant mutexes, we gain some advantages; our locking 
levels can almost always just mention the supremum of the locks held.  
With reentrant mutexes, there's probably a bit more of a temptation 
to take advantage of locks that are in your LL but that are fairly 
deep in the ordering below the supremum.  In addition, you would 
need to be careful in specifying which procedures you could safely 
call, by explaining exactly which locks might be needed, so that 
you don't have to worry that it might need some lock higher than 
the one that it first tries to acquire (but which might be lower 
than some other lock you already have--deadlock city!)

Mark





