Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site decwrl.UUCP Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!mhuxl!ulysses!allegra!mit-eddie!genrad!decvax!decwrl!powell From: powell@decwrl.UUCP (Mike Powell) Newsgroups: net.lang.mod2 Subject: Modula-2 I/O Message-ID: <3528@decwrl.UUCP> Date: Thu, 6-Sep-84 03:11:21 EDT Article-I.D.: decwrl.3528 Posted: Thu Sep 6 03:11:21 1984 Date-Received: Wed, 12-Sep-84 01:09:37 EDT Sender: powell@decwrl.UUCP Organization: DEC Western Research Lab, Los Altos, CA Lines: 117 I would like to provoke a little discussion about the I/O facilities present in (or absent from) Modula-2. There seem to be 3 + N possible alternatives: 1) Pascal-like I/O 2) What Wirth has proposed (module InOut) 3) No defined I/O N) Pick your favorite I/O mechanism 1) Pascal I/O (especially the "I") has been widely discussed and criticized, so I won't rehash it. Using it would at least make Modula-2 more compatible with Pascal, and would have guaranteed a facility no worse than Pascal's. 2) What Wirth has proposed is not adequate even for many simple programs. There is only one input stream and one output stream for formatted operations. Although it is possible for people to define their own I/O modules as needed, this degenerates into the next alternative. 3) Not defining I/O even in the easy cases will make it impossible to write portable Modula-2 programs. No interesting textbooks will be written and the language will not be taught on a large scale. N) It seems to me that 2 and 3 are both worse than 1. The question is, is some N better than 1? How about this: Define a builtin I/O module patterned after Unix/C printf and scanf. I believe this same (or similar) I/O interface has been used in a variety of languages on a variety of machines and systems, so it seems pretty portable. Formatted input and output are accomplished with procedures that accept a variable number of parameters. The first two parameters are always the file variable and a format string. Additional parameters may be specified, and they are matched against the format string to see how to read or write the variables. Although in C the parameters are not checked (of course, C never checks parameters) and are blindly used by the library at runtime, Modula-2 could check the parameters against the format, and even generate calls to implementation-dependent library routines to perform the I/O. I liked this idea so much I implemented it in my compiler, and I include the pseudo-definition module (since it must be built into the compiler to handle the variable-length parameters lists) below. I'm interested in reactions or suggestions for other alternatives. I would also like to know what other operations you think are essential for a "standard" Modula-2 I/O library. Michael L. Powell Digital Equipment Corporation Western Research Laboratory Los Altos, CA 94022 {decvax,ucbvax}!decwrl!powell powell@decwrl Appendix: io.def This module should not be compiled, but is supplied for documentation purposes. definition module io; export qualified File, Open, Close, Readf, Writef, SReadf, SWritef, Readc, Writec, Readb, Writeb; type File = pointer to FileRec; (* Open file variable type *) var (* Standard files connected to Unix standard input, output, and error *) input, output, terminal : File; procedure Open(name : array of Char; mode : array of Char) : File; (* open a file *) (* name : file name; mode = "r" for input, "w" for output *) (* return value : opened file or nil *) procedure Close(f : File); (* close a file *) procedure Readf(f : File; (* constant *) format : array of Char; var arg1 : ArgType1; var arg2 : ArgType2; ...) : integer; (* read a list of values from a file according to a format string *) (* f : an open file; format : constant string format (like Unix scanf) *) (* argn : variable for corresponding format item, type must match *) (* return value : number of values read, < 0 for end of file *) procedure Writef(f : File; (* constant *) format : array of Char; arg1 : ArgType1; arg2 : ArgType2; ...); (* write a list of values to a file according to a format string *) (* f : an open file; format : constant string format (like Unix printf) *) (* argn : value for corresponding format item, type must match *) procedure Readc(f : File; var c : Char) : integer; (* read the next character from the file *) (* f : an open file; c : variable to read next char into *) (* return value : >= 0 if read OK, < 0 if end of file *) procedure Writec(f : File; c : Char); (* write a character to a file *) (* f : an open file; c : value for next char to write *) procedure SReadf(s : array of Char; format : (* constant *) array of Char; var arg1 : ArgType1; var arg2 : ArgType2; ...) : integer; (* read a list of values from a string according to a format string *) (* s : a string; format : constant string format (like Unix scanf) *) (* argn : variable for corresponding format item, type must match *) (* return value : number of values read *) procedure SWritef(var s : array of Char; format : (* constant *) array of Char; arg1 : ArgType1; arg2 : ArgType2; ...); (* write a list of values to a string according to a format string *) (* s : a string; format : constant string format (like Unix printf) *) (* argn : value for corresponding format item, type must match *) procedure Readb(f : File; var buff : array of byte; size : cardinal) : integer; (* read binary data from a file *) (* f : an open file; buff : variable to read into *) (* size : number of bytes to read *) (* return value : if read OK, = number of bytes read, < 0 if end of file *) procedure Writeb(f : File; buff : array of byte; size : integer); (* write binary data to a file *) (* f : an open file; buff : variable to write *) (* size : number of bytes to write *) end io.