------------------------------------------------------------------------------ Date: Sat, 1 Sep 90 22:42:57 met From: Piet van Oostrum Subject: Patches for HP version of m3 These patches are to get the Modula-3 compiler working on HP-UX: 1. The toplevel makefile is missing a line SHELL=/bin/sh 2. sed on SYSV systems does print substituted lines only with -n. Besides that the parentheses in the command for imake in the makefile are superfluous, so I changed this to: imake: FRC @cd util; \ cpp=`cat config | sed -n -e 's/^CPP[ \t]*=[ \t]*//p' -e 'd'`; \ cc=`cat config | sed -n -e 's/^CC[ \t]*=[ \t]//p' -e 'd'`; \ sed -e s+M3_CPP+$$cpp+ imake.c > imake.foo.c; \ $$cc -o imake imake.foo.c; \ /bin/rm -f imake.foo.c 3. The file util/install.HP300 should have mode rx. 4. config.dist-HP300 should have CLINKFILES = -lm -lBSD *** M3Runtime.c.~1~ Mon Jul 23 20:53:23 1990 --- M3Runtime.c Thu Jul 26 10:17:57 1990 *************** *** 59,67 **** #if defined (HP300) #include #endif - #include #include #include --- 59,68 ---- #if defined (HP300) #include + #else + #include #endif #include #include The intermediate compiler m3.local (and I guess also m3.cross) do miss the needed -lBSD on the link phase on HP-UX. This can be corrected (valid on all systems by patching system/driver/Imakefile: *** Imakefile.~1~ Mon Jul 23 20:53:18 1990 --- Imakefile Thu Jul 26 11:00:15 1990 *************** *** 16,22 **** -e 's+PASS2+.ROOT/system/loader/m3ld+' \ -e 's+DEFPATH+-D -D.ROOT/system/corelib/Interfaces -D.+' \ -e 's+LIBPATH+-L.ROOT/system/corelib+' \ ! -e 's+LINKFILES+.ROOT/system/runtime/m3run.o -lm3core -lm+' \ -e 's+LINKCOVER+.ROOT/tools/coverage/report_coverage.o+' \ -e 's+INCLDIR+.ROOT/system/runtime+' \ -e 's+LD_WANTS_SPACE_AFTER_L+$(LD_WANTS_SPACE_AFTER_L)+' \ --- 16,22 ---- -e 's+PASS2+.ROOT/system/loader/m3ld+' \ -e 's+DEFPATH+-D -D.ROOT/system/corelib/Interfaces -D.+' \ -e 's+LIBPATH+-L.ROOT/system/corelib+' \ ! -e 's+LINKFILES+.ROOT/system/runtime/m3run.o -lm3core $(CLINKFILES) +' \ -e 's+LINKCOVER+.ROOT/tools/coverage/report_coverage.o+' \ -e 's+INCLDIR+.ROOT/system/runtime+' \ -e 's+LD_WANTS_SPACE_AFTER_L+$(LD_WANTS_SPACE_AFTER_L)+' \ *************** *** 30,36 **** -e 's+PASS2+.ROOT/.cross/loader/m3ld+' \ -e 's+DEFPATH+-D -D.ROOT/.cross/corelib/Interfaces -D.+' \ -e 's+LIBPATH+-L.ROOT/system/corelib+' \ ! -e 's+LINKFILES+.ROOT/.cross/runtime/m3run.o -lm3core -lm+' \ -e 's+LINKCOVER+.ROOT/tools/coverage/report_coverage.o+' \ -e 's+INCLDIR+.ROOT/.cross/runtime+' \ -e 's+LD_WANTS_SPACE_AFTER_L+$(LD_WANTS_SPACE_AFTER_L)+' \ --- 30,36 ---- -e 's+PASS2+.ROOT/.cross/loader/m3ld+' \ -e 's+DEFPATH+-D -D.ROOT/.cross/corelib/Interfaces -D.+' \ -e 's+LIBPATH+-L.ROOT/system/corelib+' \ ! -e 's+LINKFILES+.ROOT/system/runtime/m3run.o -lm3core $(CLINKFILES) +' \ -e 's+LINKCOVER+.ROOT/tools/coverage/report_coverage.o+' \ -e 's+INCLDIR+.ROOT/.cross/runtime+' \ -e 's+LD_WANTS_SPACE_AFTER_L+$(LD_WANTS_SPACE_AFTER_L)+' \ util/clone.c needs a few adaptions: *** clone.c.~1~ Mon Jul 23 20:51:03 1990 --- clone.c Thu Jul 26 11:14:05 1990 *************** *** 12,18 **** #include #include ! #if defined (AIX386) #define gd_name d_name #endif --- 12,18 ---- #include #include ! #if defined (AIX386) | defined (HP300) #define gd_name d_name #endif *************** *** 204,210 **** fn (current_dir->path, file->gd_name, current_dir->depth + 1, &statbuf); }}} ! #if defined(IBMRT) closedir (dir);} /* Doesn't return anything on IBM/4.3 */ #else if (closedir (dir) != NULL) { --- 204,210 ---- fn (current_dir->path, file->gd_name, current_dir->depth + 1, &statbuf); }}} ! #if defined(IBMRT) | defined (HP300) closedir (dir);} /* Doesn't return anything on IBM/4.3 */ #else if (closedir (dir) != NULL) { Analyze_coverage has a slight misspelling. *** analyze_coverage.c.~1~ Mon Jul 23 20:51:39 1990 --- analyze_coverage.c Thu Jul 26 23:15:13 1990 *************** *** 11,17 **** #include #include #if defined (HP300) ! #include #endif #include --- 11,17 ---- #include #include #if defined (HP300) ! #include #endif #include Piet* van Oostrum, Dept of Computer Science, Utrecht University, Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31-30-531806 Uucp: uunet!mcsun!ruuinf!piet Telefax: +31-30-513791 Internet: piet@cs.ruu.nl (*`Pete') ------------------------------------------------------------------------------ Date: Mon, 3 Sep 90 18:08:02 MET DST From: Thomas Roemke Subject: Question about BRANDED I've got a question about brands. The report says: 'All brands in a program must be distinct' Does that mean all brands in a module have to be distinct or does that mean all brands in all modules of a program have to be distinct ? I got a little bit confused, because m3 compiles the following program without warnings and the executable doesn't raise an exception: MODULE a EXPORTS Main; TYPE b = BRANDED "string" REF INTEGER; TYPE d = BRANDED "string" REF INTEGER; VAR a: b; c: d; BEGIN a := c; END a. Is the program correct ? Have 'a' and 'c' the same type ? Thomas -- (* Thomas Roemke, University Paderborn, FRG modula-3@uni-paderborn.de ..!uunet!mcsun!unido!pbinfo!modula-3 *) ------------------------------------------------------------------------------ Date: Mon, 3 Sep 90 23:55:38 -0400 From: lauri@svax.cs.cornell.edu (Georges Lauri) Subject: src modula-3 on the NeXT has anyone brought up src modula-3 (1.5) on a NeXT machine and would you be willing to share the result, or, do you have some estimate on how difficult this would be? (I'm thinking of the threads stuff, in particular). also, if you've used Modula-3 for a course, we'd be interested in handouts/tips for semi-naive users that people may have written and be willing to share. Georges Lauri lauri@svax.cs.cornell.edu ------------------------------------------------------------------------------ Date: Tue, 04 Sep 90 11:38:54 PDT From: Eric Muller Subject: August m3 mailing list archive available The mail archive for the messages sent to the m3 mailing list during the month of August is available via anonymous ftp from gatekeeper.dec.com, in pub/DEC/Modula-3/m3-mail.08-90.Z. Eric Muller. ------------------------------------------------------------------------------ System Research Center - 130 Lytton Av. - Palo Alto, CA 94301 - (415) 853 2193 ------------------------------------------------------------------------------ Date: 6 Sep 1990 0833-PDT (Thursday) From: Subject: Re: Question about BRANDED > I've got a question about brands. The report says: > 'All brands in a program must be distinct' > > Does that mean all brands in a module have to be distinct > or does that mean all brands in all modules of a program > have to be distinct ? All brands in a program must be distinct. Otherwise, it would be possible to "guess" the brand and structure of an opaque type and declare a visible type with the same brand and structure. This new type exposes the structure of the opaque type and hence clients of the new type could violate the invariants of the otherwise opaque type. > MODULE a > EXPORTS Main; > > TYPE b = BRANDED "string" REF INTEGER; > TYPE d = BRANDED "string" REF INTEGER; > > VAR a: b; > c: d; > BEGIN > a := c; > END a. This program is illegal and our compiler is buggy. Thanks for the bug report. - Bill Kalsow ------------------------------------------------------------------------------ Date: Mon, 10 Sep 90 16:45:08 EDT From: harbison@tartan.com (Samuel Harbison) Subject: Language question, stmt sequences A minor language question, from the revised report. In the "Statements" section, a statement can be a "sequence of statements." However, in the collected syntax, "sequence of statements" (Stmts) is not a statement, but rather Stmts is used explicitly in the places a sequence is expected, e.g., IF e THEN Stmts END. As far as I can tell, the only effect of the different description is the interpretation of multiple semicolons: IF e THEN ;;; END Would this be legal or illegal? Sam P.S. RCHING: I got your message, too. ------------------------------------------------------------------------------ Date: 11 Sep 90 09:59:46 +0100 (Tuesday) From: Dick Snow Subject: Re: RCHING's message. Like Eliot Moss, I feel rather irritated at having to plough through (and then immediately delete) a number of messages of the form :I got your message:, especially as this time they were preceded by a :Please remove me from the list: message (about which there was a certain amount of discussion some months ago). E-mail etiquette (if such a thing exists) surely requires users of the system to be more considerate in their generation of messages which cause at best irritation, and at worst offence. In some cases, including my own, such messages also have to cross the Atlantic, which seems a considerable waste of resource. Because of some vagaries of the e-mail delivery systems, the *last* message I received was RCHING's message itself, and, after what had gone before, I was surprised to find that it had no content! Maybe it was the cumulative irritation built up over the previous few messages, but I did feel that it would have been nice to know who RCHING was, and why he(she?) wanted the whole of the 'm3' distribution list to reply to him/her. Surely if his/her purpose is to find out who is on the list, it would be simpler for all concerned if s/he merely asked DEC/SRC to supply a copy. If s/he has some other reason for generating a potentially large quantity of e-mail traffic, I, and possibly others, would be very interested to know what it is. ... Dick Snow. C. R. Snow Computing Laboratory University of Newcastle upon Tyne Newcastle upon Tyne, NE1 7RU, U.K. C.R.Snow@newcastle.ac.uk ------------------------------------------------------------------------------ Date: Wed, 12 Sep 90 10:30:29 EDT From: harbison@tartan.com (Samuel Harbison) Subject: A programming quiz, in Modula-3 Here's a little problem to occupy your spare minutes. Everyone submitting a correct answer by Saturday (9/15) midnight will get their names mentioned in a BBoard message that will also feature the best correct answer. Reply to me, of course, so those other people can't cheat and get a share of the prize. We all know how FOR loops are supposed to work. I used to work for a compiler company that had a lot of bright people in it, and we wrote a Modula-2 compiler that was pretty nice. One day, a user called in to say that our FOR loops were broken. He was iterating up to LAST(INTEGER), and we got it wrong. On page 26 of the Modula-3 Report (revised) is a rewriting of the Modula-3 FOR statement that has the same mistake we had: if delta>0 and last=LAST(INTEGER), INC(i,delta) will overflow after the "last" iteration and the loop will never terminate. (Or, if overflow checking were enabled, an error would occur.) PROBLEM: Rewrite the rewriting to work correctly for all values of first, last, and step. ------------------------------------------------------------------------------ Date: Thu, 13 Sep 90 07:09:31 EDT From: Dave Hanson Subject: A programming quiz, in Modula-3 Date: Wed, 12 Sep 90 10:30:29 EDT From: harbison@tartan.com (Samuel Harbison) Reply-To: harbison@tartan.com Here's a little problem to occupy your spare minutes. Everyone submitting a correct answer by Saturday (9/15) midnight will get their names mentioned in a BBoard message that will also feature the best correct answer. Reply to me, of course, so those other people can't cheat and get a share of the priz e. We all know how FOR loops are supposed to work. I used to work for a compil er company that had a lot of bright people in it, and we wrote a Modula-2 compiler that was pretty nice. One day, a user called in to say that our FO R loops were broken. He was iterating up to LAST(INTEGER), and we got it wron g. On page 26 of the Modula-3 Report (revised) is a rewriting of the Modula-3 F OR statement that has the same mistake we had: if delta>0 and last=LAST(INTEGER ), INC(i,delta) will overflow after the "last" iteration and the loop will neve r terminate. (Or, if overflow checking were enabled, an error would occur.) PROBLEM: Rewrite the rewriting to work correctly for all values of first, last, and step. M. C. Newey and W. M. Waite, The Robust Implementation of Sequence-Controlled Iteration, {\it Software---Practice \& Experience \bf 15}, 7 (July 1985) 655-668. ------------------------------------------------------------------------------ Date: Thu, 13 Sep 90 08:13:39 EDT From: moss%ibis@cs.umass.edu (Eliot Moss) Subject: A programming quiz, in Modula-3 I asked about this some time ago (FOR loops going to the end of the integer range) and the response I got was: o Overflow is *supposed* always to result in an error in Modula-3, though this *may* not be true in the C based compilers (SRC, Olivetti) because it is just too costly to check integer operations for overflow through C. o Therefore, in the rare instances in which people might try to go to LAST(INTEGER), too bad, it will overflow; the designers stand by the rewriting, since other approaches are more complex and (in the general case) slower. The users can rewrite such loops themselves using WHILE or whatever. In the GNU M3 compiler effort we have yet to deal with integer overflow, though we are clearly in a better position to do so than the C output compilers. I am uncertain as to the best course to take, however, since following the language spec precisely will result in some slow down when compared with C/C++, which might impede acceptance of M3. We could always go the compiler switch route, but that goes against the philosophy of the language, too. Actually, the FOR loop case is not too bad for two popular targets, namely the VAX and the MIPS R2000. The VAX has a special loop increment instruction which will detect the overflow, and the MIPS has two flavors of add instruction, one that traps overflow and one that does not, so we can just insure that the overflow trapping instruction is used. However, this may all potentially interfere with other optimizations, such as strength reduction (replacement of FOR i ... DO ... A[i] ... END with a stepping pointer as in the C form *p++), though if folded properly with array bounds detection, it should not be too bad (i.e., we're morelikely to run off the end of the array than out of the range of i, in most cases). We also have a general concern about doing a good job on range/bounds checking. It is too early for us to say what the penalty will be for "typical" code; perhaps the compiler really will be good enough to optimize most of the checks away, and it appears that a soon to be released new version of gcc will have more support for this. The FOR loop as designed for M3 probably represents a reasonable tradeoff between a clean definition and what can be done nicely with existing hardware capabilities. As a side note, if one wants to optimize to byte or 16-bit word operations, then it is not just LAST(INTEGER) that is a problem, but also 255 and 32767, etc. Further thoughts, reactions, etc., on this issue? Advice from the designers on what I should do in my compiler? Clarification of what the SRC and Olivetti compilers do? Eliot J. Eliot B. Moss, Assistant Professor Department of Computer and Information Science Lederle Graduate Research Center University of Massachusetts Amherst, MA 01003 (413) 545-4206; Moss@cs.umass.edu ------------------------------------------------------------------------------ Date: Thu, 13 Sep 1990 09:10:28 -0500 (CDT) From: Dick Orgass Subject: Moving SRC Modula-3 I recently found it necessary to move the source tree for SRC Modula-3 to a different location and to prepare the compiled system for distribution to other sites via streaming tape. This turns out to be quite simple and this note describes the procedure I used in case it's useful to others. I moved the build tree for a RISC 6000 system (IBMR2) but the steps are the same for other systems. (1) Before or after moving the tree, in the target specific directory (IBMR2.obj in my case), execute the following commands: rm .SRC ln -s ../dist-1.5 .SRC (2) In the target specific directory, execute the shell script update-move which appears below. Before executing the shell script, change the occurrence of IBMR2 on the last line to your target. When this shell script is executed, the symbolic links for the interfaces are removed and all of the installation directory specific files are deleted. The make at the end reinstalls the symbolic links for the interfaces. (3) To build the system for new directories, execute the command make -k in the target specific directory. Dick ----------------------- file update-move ------------------ #! /bin/csh -f rm ./libs/io/Interfaces/*.i3 rm ./libs/Xt/Interfaces/*.i3 rm ./libs/math/Interfaces/*.i3 rm ./libs/misc/Interfaces/*.i3 rm ./libs/Xlib/Interfaces/*.i3 rm ./libs/Xaw/Interfaces/*.i3 rm ./libs/ultrix-3.1/Interfaces/*.i3 rm ./libs/data/Interfaces/*.i3 rm ./libs/aix-ps2-1.2/Interfaces/*.i3 rm ./libs/ibm-4.3/Interfaces/*.i3 rm ./libs/aix-3.1/Interfaces/*.i3 rm ./libs/posix/Interfaces/*.i3 rm ./libs/hpux-7.0/Interfaces/*.i3 rm ./system/compiler/Interfaces/*.i3 rm ./system/corelib/Interfaces/*.i3 rm ./system/driver/m3 rm ./system/driver/m3.local rm ./system/driver/m3.1 rm ./system/loader/m3ld rm ./tools/depend/m3imc rm ./tools/depend/m3imc.1 rm ./tools/pp/m3pp rm ./tools/pp/m3pp.1 rm ./tools/coverage/analyze_coverage rm ./tools/coverage/analyze_coverage.1 rm ./tools/coverage/coverage.5 rm ./tools/coverage/coverage.7 make -k IBMR2 ---------------------end------------------------ ------------------------------------------------------------------------------ Date: Fri, 14 Sep 90 09:03:29 EDT From: harbison@tartan.com (Samuel Harbison) Subject: FOR loops (intentional and otherwise) Part 1... I was mildly chastised for suggesting the FOR loop description on p. 26 was in error, when in fact it represented the intent of the designers. The motivation for the design decision was a desire not to penalize the efficiency of all programs just to handle a boundary case that never happens anyway. (You can always rewrite the FOR as a WHILE yourself if this is a problem.) So, it appears that the description of the FOR loop in the report could be "clarified" by adding something like the following to p. 25 (so that people don't mis-implement it): "In Modula-3, it is a checked runtime error to complete the last iteration of a FOR loop in which delta>0 AND ORD(last)+delta > LAST(INTEGER). Similarly, it is a checked runtime error to complete the last iteration if delta<0 AND ORD(last)-delta < FIRST(INTEGER)." I'm not absolutely sure the equation is correct, but you get the idea. If any members of the langauge committee think this is not the current definition, please tell me soon. In particular, do implementations have the option to NOT generate an error? (That is not what the report says, but I know of at least one east coast M3 implementor who seems to think it's OK...) Part 2... Well, I don't much like this, so I called one of the chief code generator gurus at Tartan Laboratories to make sure I wasn't just getting old and cranky. (Well, on this issue, anyway.) TL develops optimizing compilers for a variety of architectures, and they have to handle the boundary cases for their languages (C, Modula-2, and Ada) since it appears that users do occasionaly write such code. (The Ada validation suite checks it, of course. Probably the C ones do also.) The report from TL was: Some architectures handle the boundary cases with no penalty, and some do not. On the VAX, which does not, it takes about one extra cycle to handle it. In any case, they said, it didn't seem like a big enough deal to affect a language definition. I agree. Especially in a language that already checks for arithmetic overflow and encourages garbage collection. OK, 'nuff said. Back to work... Sam Harbison ------------------------------------------------------------------------------ Pine Creek Software, 305 S. Craig St., Suite 300, Pgh, PA 15213. 412-681-9811 ------------------------------------------------------------------------------ Date: Fri, 14 Sep 90 15:49:34 -0400 From: fkz@cs.brown.edu (Kenneth Zadeck) Subject: HALT statement I noticed in the interface for ParseParams that there was a HALT statement. Is this a local extension or is this part of the language? I could not find it in the revised report. kenny ------------------------------------------------------------------------------ Date: Fri, 14 Sep 90 17:59:26 PDT From: Eric Muller Subject: Re: HALT statement > I noticed in the interface for ParseParams that there was a HALT > statement. Is this a local extension or is this part of the language? > I could not find it in the revised report. The HALT statement is in a comment showing an actual use of the ParseParams interface. It turns out that this interface has been translated from a Modula-2+ version, and I have not been very careful. The line should read Cstdlib.exit (-1); You have certainly noticed that the syntax of the TRY EXCEPT statement is also wrong. It should be: TRY ... EXCEPT | Scan.BadFormat => ... END; Sorry for the confusion this may have caused. Eric Muller. ------------------------------------------------------------------------------ System Research Center - 130 Lytton Av. - Palo Alto, CA 94301 - (415) 853 2193 ------------------------------------------------------------------------------ Date: Mon, 17 Sep 90 15:55 +1000 From: Richard Thomas Subject: Re: FOR loops (intentional and otherwise) IN%"harbison@tartan.com" 16-SEP-1990 00:31:17.69 writes: Well, I don't much like this, so I called one of the chief code generator gurus at Tartan Laboratories to make sure I wasn't just getting old and cranky. (Well, on this issue, anyway.) TL develops optimizing compilers for a variety of architectures, and they have to handle the boundary cases for their languages (C, Modula-2, and Ada) since it appears that users do occasionaly write such code. (The Ada validation suite checks it, of course. Probably the C ones do also.) The report from TL was: Some architectures handle the boundary cases with no penalty, and some do not. On the VAX, which does not, it takes about one extra cycle to handle it. In any case, they said, it didn't seem like a big enough deal to affect a language definition. I agree. Especially in a language that already checks for arithmetic overflow and encourages garbage collection. I also agree. Just a couple of weeks ago we looked at this problem in my Compiler Construction class in relation to avoiding this error in an M2 compiler we wrote here. The overhead to do the checks is pretty minimal especially if you have a smart compiler and do a little arithmetic. I think it is a poor design that puts in a cheat like this just to avoid a little extra work for the compiler. The definition for the FOR loop as it stands is unnatural and awkward for intuitively correct code. Au revoir, @~~Richard Thomas aka. The AppleByter -- The Misplaced Canadian~~~~~~~~~~~@ { InterNet: R_Thomas@qut.edu.au ACSNet: richard@earth.qitcs.oz.au } { PSI: PSI%505272223015::R_Thomas } @~~~~~School of Computing Science - Queensland University of Technology~~~~~~@ ------------------------------------------------------------------------------ Date: Mon, 17 Sep 90 16:18:35 EDT From: harbison@tartan.com (Samuel Harbison) Subject: Answers to quiz... Well, NO ONE sent any code for the FOR loop, but here are two references. Jeff Woolsey of Microtec Research, Inc. recommends the code in Wirth's Programming in Modula-2/3e. [I couldn't find a page reference. -sh] Dave Hanson at Princeton cites M. C. Newey and W. M. Waite, The Robust Implementation of Sequence-Controlled Iteration, {\it Software---Practice \& Experience \bf 15}, 7 (July 1985) 655-668. Thanks for the contributions. Did I mention I had planned to give out $1,000 for the best code? No? Oh, well, too late now... Sam ------------------------------------------------------------------------------ Date: Tue, 18 Sep 90 10:43:58 EDT From: eachus@d74sun.mitre.org (Robert I. Eachus) Subject: FOR loops (intentional and otherwise) We just had a discussion of this precise issue in the ARG (the Ada standard maintenance group). The issue will be reconsidered when written in final form, but for now it looks like: A loop with one static or dynamic bound which is INTEGER'FIRST or INTEGER'LAST must work "correctly," but a loop from INTEGER'FIRST to INTEGER'LAST is a pathological case which need not be considered. In other words, since there is an easy way in Ada to write loop forever, there is no need to write the nasty code to loop over all values of the largest useful index type so that it executes exactly 2**32 times. A programmer can "unroll" explicitly one iteration where necessary to avoid getting junk code for all dynamic loops. Keep in mind that this is a very preliminary reading of the recommendation and in may change, particularly for cases where SYSTEM.MAX_INT /= INTEGER'LAST. Robert I. Eachus with STANDARD_DISCLAIMER; use STANDARD_DISCLAIMER; function MESSAGE (TEXT: in CLEVER_IDEAS) return BETTER_IDEAS is... ------------------------------------------------------------------------------ Date: Fri, 14 Sep 90 11:52:41 MET DST From: Thomas Roemke Subject: Question about enum variables Suppose you have a declaration VAR enum: {a,b,c,d,e}; Since there's no visible enum type, how can one assign enum a value ? Thomas P.S.: Of course, it's possible to define a type T = {a,b,c,d,e}, declare VAR enum: T and there's no problem......... -- (* Thomas Roemke, University Paderborn, FRG modula-3@uni-paderborn.de ..!uunet!mcsun!unido!pbinfo!modula-3 *) ------------------------------------------------------------------------------ Date: Tue, 18 Sep 90 12:58:04 EDT From: moss%ibis@cs.umass.edu (Eliot Moss) Subject: Question about enum variables Well, it *is* inconvenient not to give an enum type a name, but with FIRST, LAST, and more generally, VAL, you *can* construct the values of the type without reference to the names. There may be occasions where a construct TYPEOF(exp) would be useful, allowing reference to the type of a variable (for example). If M3 had that, you could write TYPEOF(v).a and stuff. I suspect one cannot make strong arguments for TYPEOF in the absence of a generics / paramaterization facility, though. Eliot J. Eliot B. Moss, Assistant Professor Department of Computer and Information Science Lederle Graduate Research Center University of Massachusetts Amherst, MA 01003 (413) 545-4206; Moss@cs.umass.edu ------------------------------------------------------------------------------ Date: 18 Sep 1990 1040-PDT (Tuesday) From: Subject: Re: Question about enum variables Thomas Roemke asks: Suppose you have a declaration VAR enum: {a,b,c,d,e}; Since there's no visible enum type, how can one assign enum a value ? The answer is that you could say enum := {a,b,c,d,e}.a if you really wanted to leave the type anonymous. But why you would want to do this is beyond me. Greg ------------------------------------------------------------------------------ Date: 18 Sep 1990 1223-PDT (Tuesday) From: Subject: Re: Question about enum variables [Greg:] But why you would want to [leave an enumeration type anonymous] is beyond me. Because inventing names is a nuisance. M3's structural type equivalence thankfully removed this need from many contexts, and naturally made the few remaining ones to stand out like sore thumbs. I stumbled into the same M3 quirk the other day, when I wrote PROCEDURE Sort(VAR a: ARRAY OF T; order: {Increasing, Decreasing}); After the "oops", it took some time to convince myself that anonymous enumeration types are virtually useless in M3. Here are some possible solutions to this "problem" that occurred to me then: Solution 1: If the type of is an enumeration type T, then define . to mean the same as T. Solution 2: Introduce the pseudo-procedure TYPEOF(), which returns the type of the designated expression. Then one could write option := TYPEOF(option).Foo Note that since the type of is known at compile-time, the meaning of TYPEOF() would be similarly known. Which means one could use TYPEOF in any context where a type would be acceptable: TYPE T = TYPEOF(y); VAR x: TYPEOF(y); rx := NEW(TYPEOF(rx)); Reversing Eliot Moss' argument, the TYPEOF construct may be quite handy once M3 generics become available. Solution 3: Let the values of enumerations be *unqualified* global symbols, enclosed in single quotes. That is, one should write TYPE Color = { 'Red', 'Yellow', 'Green', 'Cyan', 'Blue', 'Magenta', 'White', 'Black' }; TrafficLight = { 'Green', 'Yellow', 'Red' }; Maturation = { 'Green', 'Ripe'} Operator = { '+', '*', '%%' }; Note that the 'Green' of Color is the same value as the 'Green' of Maturation. So, for example: VAR color: Color; trfic: TrafficLight; mtion: Maturation; i: INTEGER; color := 'Green'; (* Ok *) color := 'Ripe'; (* Range error (detectd at compile time) *) color := VAL(2, Color); (* Ok, means 'Green' *) color := VAL(0, Maturation); (* Ok, means 'Green' *) i := ORD('Green', Color); (* Ok, means 2 *) i := ORD('Green', TrafficLight); (* Ok, means 0 *) i := ORD('Green'); (* Syntax error, ORD requires 2 args *) color := trfic; (* Ok, uses a translation table *) trfic := color; (* Ok, uses a translation table w/ "invalid" flags *) trfic := mtion; (* Ditto, but also emits a level 2 warning: "source type is neither a subset nor a superset of target type" *) color := VAL(i, Maturation); (* Ditto *) Note that the ' ' notation for CHAR literals would then be a special case of this rule, except for the octal escapes. (As for these, perhaps no one will really miss '\011', given that they can write 'TAB' and VAL(8_011, CHAR). (If they really make a fuss about it, perhaps EnumType[i] can be defined as syntactic sugar for VAL(i, EnumType).).) Additional repercussions of this proposal are left as an exercise to the reader 8-) --jorge ------------------------------------------------------------------------------ Date: 19 Sep 1990 0814-PDT (Wednesday) From: Subject: Re: Method override > >> TYPE > >> T = OBJECT METHODS whoami() := FooT END; > >> A = T OBJECT data: INTEGER METHODS whoami := FooA END; > >> B = T OBJECT data: REAL METHODS whoami := FooB END; > >> prl304 240> Test1 > >> T > >> A > >> B No surprises. > >> TYPE > >> T = OBJECT METHODS whoami() := FooT END; > >> A = T OBJECT METHODS whoami := FooA END; > >> B = T OBJECT METHODS whoami := FooB END; > >> prl304 241> Test2 > >> T > >> B > >> B The compiler identified types A and B, because it ignored the default values of the methods. This is a compiler bug. The compiler then picked B as the representative for the "single" type. (Eric, is this bug fixed in your version?) > >> TYPE > >> T = OBJECT METHODS whoami() := FooT END; > >> A = T OBJECT data: INTEGER METHODS whoami := FooA END; > >> B = T OBJECT data: INTEGER METHODS whoami := FooB END; > > >> prl304 242> Test3 > >> T > >> B > >> B Again, the compiler ignored FooA and FooB and went on to identify the types. > >> TYPE > >> T = OBJECT METHODS whoami() := FooT END; > >> A = T OBJECT dataA: INTEGER METHODS whoami := FooA END; > >> B = T OBJECT dataB: INTEGER METHODS whoami := FooB END; > >> prl304 243> Test4 > >> T > >> A > >> B The field names dataA and dataB are differenct so the compiler kept types A and B distinct. > Finally, I swapped the order of the top level procedures FooA and FooB in > the source file for Test2, the code for Test5.m3 is thus: > which gives: > >> prl304 244> Test5 > >> T > >> A > >> A The compiler bug that identifies types A and B picks one of them more or less randomly. In this case it picked A, previously it was taking B. - Bill ------------------------------------------------------------------------------ Date: Wed, 19 Sep 1990 10:45:54 -0500 (CDT) From: Dick Orgass Subject: AIX 3.1 correction, proposed target specific library additions The purpose of this note is to provide a correction for the AIX 3.1 version of Unix.i3, to propose an addition to Uerror.i3 and to propose the addition of an interface and module to the target specific libraries. libs/aix-3.1/Interfaces/Unix.i3 File released as ../lib/m3/aix-3.1/Unix.i3 AIX 3.1 can be thought of as having three modes: 4.3 BSD, SystemV and AIX. The declaration of struct_stat, etc at lines 929-966 is appropriate for AIX mode and, perhaps, for SystemV mode but it is not appropriate for BSD mode. Modula-3 source is compiled in BSD mode. I did make the correction for BSD mode in CoreOS.i3 but forgot to make it in Unix.i3. The interface Stat.i3, below, is a correct replacement for the declaration of struct_stat, etc in Unix.i3. It can be used until the next release when the change should be installed. Access to directory reading procedures. The BSD directory reading procedures, opendir, readdir, etc are not defined in the operating system interfaces. I propose that the interface and module Dirent, below, be added to the target specific libraries for those targets that support these calls. The interface defines the appropriate types and external procedures. In addition, I added a procedure that converts the d_name field of a struct_dirent into a text. I did this because I found myself writing the code over and over again in clients. Converting Uerror.errno to a TEXT message In a number of places, I found myself writing out code to look up an error message that corresponds to an error code and converting it to text in order to write error messages. I propose that Uerror be extended with a procedure, ErrorText, with the same properties as ErrorText.FromErrno in the attached interface and module ErrorText. Dick (* File Stat.i3, created by Dick Orgass at 15:07:10 on Mon Sep 17 1990. *) (* Copyright (C) by IBM Corporation, 1990. *) INTERFACE Stat; FROM Ctypes IMPORT int, short, unsigned_short, long, unsigned_long, char_star; (* Note that the following assumes that bsdcc is used to compile the C generated by the Modula-3 compiler. *) <*UNUSED*> CONST StatCopyright = "Copyright (C) by IBM Corporation, 1990."; StatRCSHeader = "$Header$"; StatDate = "$Date$"; StatRevision = "$Revision$"; (* For documentation of this interface see Calls and Subroutines Reference: BaseOperatingSystem, Volume 1, IBM Form number SC23-2198-00, pp 1-711 to 1-714. *) TYPE dev_t = unsigned_long; ino_t = unsigned_long; off_t = long; time_t = long; uid_t = unsigned_long; gid_t = unsigned_long; TYPE struct_stat = RECORD st_dev : dev_t; st_ino : ino_t; st_mode_ext: unsigned_short; st_mode : unsigned_short; st_nlink : short; st_pad_to_word: short; st_uid_ext: short; st_uid : unsigned_short; st_gid_ext: unsigned_short; st_gid : unsigned_short; st_rdev : dev_t; st_size : off_t; st_atime : time_t; st_spare1 : int; st_mtime : time_t; st_spare2 : int; st_ctime : time_t; st_spare3 : int; st_blksize: unsigned_long; st_blocks : unsigned_long; st_vfstype: unsigned_long; (* Type of fs *) st_vfs : unsigned_long; (* Vfs number *) st_type : unsigned_long; (* Vnode type *) st_gen : unsigned_long; (* Inode generation number *) st_flag : unsigned_long; (* Flag word *) Reserved1 : uid_t; (* Reserved *) Reserved2 : gid_t; (* Reserved *) st_access : unsigned_short; (* Process' access to file *) st_spare4 : ARRAY [0..4] OF unsigned_long; (*Reserved *) END; CONST SIFMT :unsigned_short = 8_10000; SIFPIPE = 8_0; SIFPORT = 8_1; SIFCHR = 8_2; SIFDIR = 8_4; SIFBLK = 8_6; SIFREG = 8_10; SIFLNK = 8_12; SIFSOCK = 8_14; <*EXTERNAL*> PROCEDURE stat (path: char_star; VAR buf: struct_stat): int; <*EXTERNAL*> PROCEDURE lstat (path: char_star; VAR buf: struct_stat): int; <*EXTERNAL*> PROCEDURE fstat (fd: int; VAR buf: struct_stat): int; END Stat. (* File Dirent.i3, created by Dick Orgass at 11:38:53 on Tue Sep 18 1990. *) (* Copyright (C) by IBM Corporation, 1990. *) INTERFACE Dirent; IMPORT Stat; FROM Ctypes IMPORT char_star, int, long, unsigned_long, unsigned_short; <*UNUSED*> CONST DirentCopyright = "Copyright (C) by IBM Corporation, 1990."; DirentRCSHeader = "$Header$"; DirentDate = "$Date$"; DirentRevision = "$Revision$"; (* For documentation of this interface (except NameToText) see Calls and Subroutines Reference: Base Operating System, Volume 1, IBM Form number SC23-2198-00, pp 1-522 to 1-524. *) TYPE D_name = ARRAY [0..255] OF CHAR; DIR = RECORD dd_fd: int; dd_blksize: int; dd_buf: char_star; dd_size: long; dd_flag: long; dd_loc: long; dd_curoff: long END; DIR_star = UNTRACED REF DIR; struct_dirent = RECORD d_offset: unsigned_long; d_ino: Stat.ino_t; d_reclen: unsigned_short; d_namelen: unsigned_short; d_name: D_name; END; struct_dirent_star = UNTRACED REF struct_dirent; <* EXTERNAL *> PROCEDURE opendir(dir: char_star): DIR_star; <* EXTERNAL *> PROCEDURE readdir(VAR dirPtr: DIR): struct_dirent_star; <* EXTERNAL *> PROCEDURE telldir(VAR dirPtr: DIR): long; <* EXTERNAL *> PROCEDURE seekdir(VAR dirPtr: DIR; location: long); <* EXTERNAL *> PROCEDURE rewinddir(VAR dirPtr: DIR); <* EXTERNAL *> PROCEDURE closedir(VAR dirPtr: DIR); PROCEDURE NameToText(name: D_name): TEXT RAISES {}; (* Converts the d_name field of a struct_dirent to a TEXT and returns it. *) END Dirent. (* File Dirent.m3, created by Dick Orgass at 11:49:05 on Tue Sep 18 1990. *) (* Copyright (C) by IBM Corporation, 1990. *) MODULE Dirent; IMPORT Char, Text; <*UNUSED*> CONST DirentImplCopyright = "Copyright (C) by IBM Corporation, 1990."; DirentImplRCSHeader = "$Header$"; DirentImplDate = "$Date$"; DirentImplRevision = "$Revision$"; PROCEDURE NameToText(name: D_name): TEXT RAISES {} = (* Converts the d_name field of a struct_dirent to a TEXT and returns it. *) VAR nameLength: CARDINAL := 0; charName: REF ARRAY OF CHAR; BEGIN FOR i := 0 TO 255 DO IF name[i] = Char.NUL THEN EXIT ELSE INC(nameLength) END END; charName := NEW(REF ARRAY OF CHAR, nameLength); FOR i := 0 TO nameLength-1 DO charName[i] := name[i] END; RETURN Text.FromChars(charName^) END NameToText; BEGIN END Dirent. (* File ErrorText.i3, created by Dick Orgass at 09:41:48 on Wed Sep 19 1990. *) (* Copyright (C) by IBM Corporation, 1990. *) INTERFACE ErrorText; IMPORT Ctypes; <*UNUSED*> CONST ErrorTextCopyright = "Copyright (C) by IBM Corporation, 1990."; ErrorTextRCSHeader = "$Header$"; ErrorTextDate = "$Date$"; ErrorTextRevision = "$Revision$"; PROCEDURE FromErrno(errno: Ctypes.int): TEXT RAISES {}; (* Returns sys_errlist[errno] as a TEXT. Note that there is no new-line (\n) at the end of the return value. *) END ErrorText. (* File ErrorText.m3, created by Dick Orgass at 09:46:00 on Wed Sep 19 1990. *) (* Copyright (C) by IBM Corporation, 1990. *) MODULE ErrorText; IMPORT Ctypes, Fmt, M3toC; <*UNUSED*> CONST ErrorTextImplCopyright = "Copyright (C) by IBM Corporation, 1990."; ErrorTextImplRCSHeader = "$Header$"; ErrorTextImplDate = "$Date$"; ErrorTextImplRevision = "$Revision$"; (* AIX 3.1 defines errno, sys_errlist and sys_nerr (as well as perror which is omitted here). sys_nerr is the number of messages currently in sys_errlist and the documentation suggests checking the error number against this value because there may be error codes without messages in sys_errlist some of the time. For more details, see p. 1-259 of Calls and Subroutines Reference: Base Operating System, Volume 1, IBM form number SC23-2198-00 for more information. *) <* EXTERNAL *> VAR sys_errlist: ARRAY [0..200] OF Ctypes.char_star; (* The value 200, above, is a guess to be large enough; current value of sys_nerr is 115. *) sys_nerr: Ctypes.int; PROCEDURE FromErrno(errno: Ctypes.int): TEXT RAISES {} = (* Returns sys_errlist[errno] as a TEXT. Note that there is no new-line (\n) at the end of the return value. *) BEGIN IF errno < sys_nerr THEN RETURN M3toC.StoT(sys_errlist[errno]) ELSE RETURN "Unknown error, code = " & Fmt.Int(errno) END END FromErrno; BEGIN END ErrorText. ------------------------------------------------------------------------------ Date: 20 Sep 1990 0808-PDT (Thursday) From: Subject: Questions about TEXT Since TEXT is a subtype of REFANY, and NIL is a member of any REF type, does it follow that NIL is a member of TEXT? Is NIL = "" true? Is "" = "" true? Is "foo" = "foo" true? Is Text.Equal(NIL, "") true? If a variable of type TEXT isn't initialized explicitly, does it have (may it have) the value NIL? The value ""? Some other value? --jorge ------------------------------------------------------------------------------ Date: 20 Sep 1990 0942-PDT (Thursday) From: Subject: Re: Questions about TEXT Jorge, The issue of the NIL TEXT was discussed on this bboard several months ago. Here are the answers to your questions. I should warn you that there are some errors in the SRC compiler in this area; I'm giving you the M3 language definition. Since TEXT is a subtype of REFANY, and NIL is a member of any REF type, does it follow that NIL is a member of TEXT? A variable of type TEXT can assume the value NIL, but this value does not represent any character string, and it is an error to pass it to any of the procedures in the Text interface. Is NIL = "" true? No. Is "" = "" true? Not necessarily; it depends on how the implementation handles text literals. Is "foo" = "foo" true? Not necessarily; it depends on how the implementation handles text literals. Is Text.Equal(NIL, "") true? As explained above (and in the M# report), it is a checked runtime error to pass NIL to any of the procedures in the Text interface. If a variable of type TEXT isn't initialized explicitly, does it have (may it have) the value NIL? The value ""? Some other value? It can be initialized to any value that is a member of the type TEXT, including NIL and "". If you care about the initial value, I recommend using an explicit initializer (e.g., ":= NIL" or ':= ""') for readability. ------------------------------------------------------------------------------ Date: 20 Sep 1990 1802-PDT (Thursday) From: Subject: Re: Questions about TEXT > [Greg:] The issue of the NIL TEXT was discussed on this bboard > several months ago. Oops, right. (How did I managed to forget that? I must be running out of synapses...) Your final message in that exchange (dated 20/Jun/90) says: > I see two reasonable positions: > > (1) The TEXT NIL represents the empty character string. > > (2) The TEXT NIL does not represent any character string. I suppose that any position that calls for changes to the language is /a priori/ unreasonable, right? Otherwise, as a programmer, I would think the following alternative to be even more reasonable: (3) TEXT is a primitive type on its own, like INTEGER or REAL, and not a REF type. I claim that (3) is the way most of us plain programmers think of TEXT. Letting TEXT be an opaque REF may seem to simplify the language, but this simplicity is illusory, since it forces all programmers to be aware of implementation details they should not know about, and do not want to know about. The "Null TEXT" issue is just one example of the actual complications that are introduced by the "simplifying" decision to let TEXT be an opaque REF. Another example is the fact that the "=" operator is virtually useless for TEXT values, except as a source of subtle programming errors. Yet another example is the need to call a procedure in order to fetch characters from a TEXT. These problems could easily be solved if TEXT were a primitive type: NIL would obviously not be a valid TEXT, "=" could be defined to mean Text.Equal, "<" could mean Text.LT, and text[i]" could be used to denote the text's /i/th character. Saying that TEXT is a REF type also places unnecessary constrains on the implementation. If TEXTs were built-in types, an implementor could choose to represent them by 64-bit variant records, containing either the actual text, for strings up to 7 bytes long, or a REF to the same, for longer strings. Depending on the statistics of text lengths and the cost of allocation+collection, this schema could be a lot more efficient overall than the REF-only schema demanded by the Report. Of course, you well know that my definition of a "good" programming language is very unconventional (to say the least) and fundamentally different from yours; which makes it hard for me to come up with suggestions that you will find reasonable, and hard for you to come up with arguments that I will find convincing. So, please forgive me for repeatedly posting "heretical" ramblings like this one, and please don't waste too much time and energy when replying to them. --jorge ------------------------------------------------------------------------------ Date: Fri, 21 Sep 1990 12:17:57 -0500 (CDT) From: Dick Orgass Subject: Compiler Bug for Objects? I was looking at yet another approach to declaring object types so that: (1) Only the methods of the object are in the public interface. (2) It is not possible to create a usable instance of the public object using NEW. Rather, a Create procedure is to be used. I declared an interface A as follows: INTERFACE A; EXCEPTION Error; TYPE T = OBJECT METHODS enumerateFiles(enumProc: EnumProc) RAISES {Error}; enumerateImports(enumProc: EnumProc) RAISES {Error}; enumerateExports(enumProc: EnumProc) RAISES {Error}; getLastError(): TEXT RAISES {} END; EnumProc = PROCEDURE(name: TEXT): BOOLEAN RAISES {}; PROCEDURE Create(name: TEXT; writeError: BOOLEAN := FALSE): T RAISES {Error}; END A. A trivial client looks like this: MODULE ta EXPORTS Main; IMPORT A; VAR a := A.T; PROCEDURE ListEntries(name: TEXT): BOOLEAN RAISES {} = BEGIN RETURN TRUE END ListEntries; BEGIN a := A.Create(name := "libsupport.a", writeError := TRUE); a.enumerateFiles(ListEntries) END ta. The SRC compiler complains about the invocation of a.enumerateFiles(ListEntries) as follows: m3 -c ta.m3 "ta.m3", line 15: unknown qualification '.' (enumerateFiles) "ta.m3", line 15: attempting to call a non-procedure 2 errors encountered This appears to contradict part of the next to last paragraph on page 31 of the revised report which reads: > If o is an object, ... If m is one of o's methods, an invocation of the > form o.m( ... ) denotes an execution of o's m method (Section 3). Such invocations are the only way to access methods. Have I misunderstood the report or is this a bug in the SRC compiler. A stripped down implementation of the interface A is attached. I'd appreciate suggestions about better ways to do the job. Dick MODULE A; TYPE MyT = T OBJECT fileName: TEXT := NIL; lastErrorMessage := "No unreported errors." METHODS END; PROCEDURE Create(name: TEXT; writeError: BOOLEAN := FALSE): T RAISES {Error} = BEGIN RETURN NEW(MyT, fileName := name, enumerateFiles := EnumerateFiles, enumerateImports := EnumerateImports, enumerateExports := EnumerateExports, getLastError := GetLastError) END Create; PROCEDURE EnumerateFiles(t: MyT; enumProc: EnumProc) RAISES {Error} = (* Calls enumProc for each file that is included in t. The enumeration terminates when enumProc returns FALSE or when the names of all files in t have been passed to enumProc. *) BEGIN RAISE Error END EnumerateFiles; PROCEDURE EnumerateImports(t: MyT; enumProc: EnumProc) RAISES {Error} = (* Calls enumProc for each symbol that is exported by a file in t. The enumeration terminates when enumProc returns FALSE or when the names of all imports have been passed to enumProc. *) BEGIN RAISE Error; END EnumerateImports; PROCEDURE EnumerateExports(t: MyT; enumProc: EnumProc) RAISES {Error} = (* Calls enumProc for each symbol that is imported by a file in t. The operation terminates when enumProc returns FALSE or when all of the exports have been passed to enumProc. *) BEGIN RAISE Error END EnumerateExports; PROCEDURE GetLastError(t: MyT): TEXT RAISES {} = (* Returns the most recent error message for the archive file. The message includes the name of the file and is in standard *IX format. *) BEGIN RAISE Error END GetLastError; BEGIN END A. ------------------------------------------------------------------------------ Date: 21 Sep 1990 1142-PDT (Friday) From: Subject: Re: Compiler Bug for Objects? The compiler behaves as you described and there is a compiler bug, but it's not what you thought... Your main program is buggy. It declares a variable named 'a' and initializes it to A.T. But, A.T is a type! The compiler should have complained about the variable declaration and all of its uses. Changing "VAR a := A.T" to "VAR a: A.T" fixes your problem. - Bill Kalsow ------------------------------------------------------------------------------ Date: Fri, 21 Sep 90 21:12:50 MET DST From: Thomas Roemke Subject: Re: Compiler Bug for Objects Hallo Dick, sorry, but first of all your program is buggy ! >MODULE ta EXPORTS Main; >IMPORT A; > >VAR > a := A.T; >[..] > VAR a := A.T is not a legal declaration. (which of course should be detected by the compiler) 'a' has not type A.T and thus the qualifications are not allowed. In fact A.T is a type expression and not assignable to any variable at all. Since type expressions are allowed in some contexts (i.e. TYPECODE(),NA RROW(),..) there may be an internal type for type expressions and 'a' may have tha t type. Try out VAR a: A.T; and your program will probably work. Thomas -- (* Thomas Roemke, University Paderborn, FRG modula-3@uni-paderborn.de ..!uunet!mcsun!unido!pbinfo!modula-3 *) ------------------------------------------------------------------------------ Date: 21 Sep 1990 1427-PDT (Friday) From: Subject: Re: Compiler Bug for Objects? This was apparently lost when I posted it this morning... Many a slip... VAR a := A.T; So what is the type of 'a'? I get an "invalid use of type" error from my (the Olivetti) compiler on this line. Clearly the SRC compiler is missing an error message. No doubt you meant: VAR a: A.T := Create(name := "libsupport.a", writeError := TRUE); On the implementation of 'A'. I would first make A.T opaque and use: TYPE T_public = OBJECT METHODS enumerateFiles(enumProc: EnumProc) RAISES {Error}; enumerateImports(enumProc: EnumProc) RAISES {Error}; enumerateExports(enumProc: EnumProc) RAISES {Error}; getLastError(): TEXT RAISES {} END; T <: T_public; and then in the implementation do REVEAL T = T_public OBJECT fileName: TEXT := NIL; lastErrorMessage := "No unreported errors." METHODS END; One day the clamour for some syntactic sugar for this frequently occurring construct might reach our ears. Mick ------------------------------------------------------------------------------ Date: Tue, 25 Sep 90 17:53:41 -0500 (CDT) From: Paul Gunsch Subject: fixes for RT/IBM 4.3 Forwarding note for Michael Bauers: ---------- Forwarded message begins here ---------- There are a few problems when building SRC Modula-3, Version 1.5 on IBM/4.3. These problems are: dist-1.5/system/runtime/M3machine.h.IBMRT Because '_packed' is a reserved word on the High C compiler we needed to redefine it. dist-1.5/system/runtime/M3Runtime.c 'vfprintf' isn't in our library so I used fprintf instead. dist-1.5/system/loader/m3ld.c I needed to write 'tempnam' for the IBMRT architecture. dist-1.5/util/clone.c Fixed a syntax error in a '#if defined(IBMRT)' clause. dist-1.5/util/merge.c 'vfprintf' isn't in our library so I used fprintf instead. dist-1.5/makefile Defined IBMRT on the CC command line, so that clone will compile correctly. I'm providing corrections of these problems as a small number of files and a shell script. All of the files are in a uuencoded compressed tar file which is attached to this note. Here are the instructions for applying the corrections: (1) Save this message in a file, say changes.uu, in the directory that contains dist-1.5, that is, the directory in which you extracted m3-1.5.tar.Z from gatekeeper. (2) Execute the following commands: uudecode changes.uu zcat 1.5changes.IBMRT.tar.Z | tar xvf - At this point, you are ready to apply the changes. If a file is changed by the update procedure, the original file is saved with the additional suffix .SRC (3) Apply the changes by executing the command applypatches (4) If the build is done using the clone directory setup as specified in the SRC 1.5 build documentation, I have provided a shell script to remove a few uneeded files that the clone process created. Make sure you are in the top level build directory and then type 'rmuneeded'. (5) Once the build is done and working, the files that were untar'd and the 1.5changes.IBMRT.tar file can be removed. Michael J. Bauers, BSI begin 666 1.5changes.IBMRT.tar.Z M'YV08>#`89,'3A@Z8]"4F0.@H<.'$"-*G$BQHL6+%4%HO,$1!`"-,F;,H.%1 MHTD8)4V:C%&CI48:-FS,@%'CADR2(&+(T#GC(PR,0(,*'4I48ITY=,+(T0@` MCYXY,&[4Z%D4XAV%9=A4WO8,-R'0,'!)DT2%O$<%'CQ9P\2,NT>2&G MCALZ:=J4>=%D1I,P"=.X*>,"C8LD0II(H6(6+1VU;-W"I2.7KEV\>OGZ!8Q& M,&'#B!53<3%%RA`%"=N\(0-BQ9W&:=>V?1MW;MV[>??V_1MX<.'#B1S'LB77MHP[\V[.GG^'7@R"!XB%8^2D@4,GA@+49<_&CDR;LNW+N35+0:_7 MQ9CCD&=/KGP;L^X9ZYL3'D/:-&HTJK'F&GS)E4_?E9Y][PQ5'('GSG:>? M>@BZ5]UU_V=EMIJK;WV8GS*F??"B"6>F.**+8[1(`C&_5A@A$/.:*2-25Z(G7;!A M>(X!60=>;+PPQHB^O>=D9%^F$>:8;Y29XW\!]@CB"VFN2>9^2S;997)UBGFG MA=9=N2$-6\[9IUYRG+&?H6"F>**B.):F(X`\#GAF6X<^BB=Q3#*JIJ.)+AIH MAEC244.AEZ88QAIEF*%F&7.VL6JKK[ZYHX`^[AF9K*RZRD89><8ZJZ^PCJHA M=S!JQ((,[@$`DPVP"!2 M2S)PFY,,,,3P$P@_86LOLT>2-_DBI`LL-T-LJF MFRV__'"FH8I\FLTQ?SI&FZZ>X<*/&=<<',,P\TKKKV\F[/334$1ENG&6&`BXH._C]^.>O__X65^YBVOC2ML8W.; MN="EMI'<8`9N>YL,;N`3`![L;OMJRE/V!C"N^$TK%@RA"*OR-AH<;@3PDQ_] M%/"V&9Q0<8SK'*=0L+#,:21U(.">]ZH7OO&53P[G2]_ZVJ<`C9@!#MJYR^)0 M@!0:R0%]9F@#'="GE#/,(04[>!\;Y@"L^HWPBV`,HQC#Z+\.CI$H`N3:M\2F M$00FT`8U05NZ:K"VFIPM)RVT007/*!8,YFV#_^H;5D#(QT*&\&TG3"$,<;@P M]KFO?O)ZX>(XYYG'U5`!.#0/'-P0AC:8Y0T+<<,)F%<&/#@&!&T"`1T4`H+0 MG,L%$.S8]KH'N^_UD'QU,!_ZA*`^1_X';RK0)"?;@(+&/!$$PRQ#YJ"U%!6< MY9@J2&86]U!$DR#E(-T#`3-!P(;8T6$(L%M*#T!P@C"<((LJV:88ZF`&,VQ! M7F7K`CI-LDT5X&X.=6##%-DG*S:,:`PHP.)W5`*])-+!#,5<9SO1)X(2S.$% M#BT!&4HP!A&@[YGH2R;Z%$4'.*3A<2E`7S>1`DZE"%0E*UC!2+\9SGEJY)[Y M9-XX^_G/8B)%#K]R0T+9:884M"8G)[4F'>1`ECP4$Z;Z1)]">^I2$.".#G60 M@TZ=NI"8"K0/6N3B"@TI$?_1@*M#22,!NR8N>I55)320@1P;>),(RDMN]0(K M5_S(+T#RS2L?E*M>[T>#&RA)(P45S$%!@((VS.$,4)0B%1-UQ2QZ<:^0C:QD M)\M'_]6`LA,1*TC(RD:S=G8E4UDK'6=P`WBY-21[Q"Q&Z*I!?]TU8(-4K6P+ MUM=$QD]Q*X2))&-82<)>\H:JTV$M>2@^7.I2B+XT(A(%N\0FGNB84=QG%1N; MU2[:;[;8S:YVH^8_"FI7LV3C[`'/ZC88J/5<::.CV610`[?&@()SVZY1KIE! MO042K[&5KWZY$CS&A')>=$UDYJ4 M]KPMI,%7XQMBUMKWM1[,KXB'3!$2#_AB)>L8Y.1>:;D^J2G M+PK*C