home *** CD-ROM | disk | FTP | other *** search
- (***************************************************************************
-
- $RCSfile: StdIO.mod $
- Description: Simple formatted I/O using the standard input and output
- handles.
-
- Created by: fjc (Frank Copeland)
- $Revision: 1.9 $
- $Author: fjc $
- $Date: 1994/09/03 16:18:21 $
-
- Copyright © 1994, Frank Copeland.
- This file is part of the Oberon-A Library.
- See Oberon-A.doc for conditions of use and distribution.
-
- ***************************************************************************)
-
- MODULE StdIO;
-
- (*
- ** $C= CaseChk $I= IndexChk $L+ LongAdr $N- NilChk
- ** $P- PortableCode $R= RangeChk $S= StackChk $T= TypeChk
- ** $V= OvflChk $Z= ZeroVars
- *)
-
- IMPORT
- SYS := SYSTEM, Exec, Dos, WB := Workbench, Reals, WbConsole;
-
- VAR
- enableBreak * : BOOLEAN;
-
- CONST
- maxD = 9;
-
- (*------------------------------------*)
- PROCEDURE^ CheckBreak ();
-
- (*------------------------------------*)
- PROCEDURE Write* (ch : CHAR);
-
- BEGIN (* Write *)
- CheckBreak ();
- SYS.PUTREG (0, Dos.base.Write (Dos.base.Output(), ch, 1))
- END Write;
-
- (*------------------------------------*)
- PROCEDURE WriteLn*;
-
- BEGIN (* WriteLn *)
- Write (0AX)
- END WriteLn;
-
- (*------------------------------------*)
- PROCEDURE WriteStr* (s : ARRAY OF CHAR);
-
- (* $D- Disables copying of dynamic array parameters. *)
- BEGIN (* WriteStr *)
- CheckBreak ();
- SYS.PUTREG (0, Dos.base.Write (Dos.base.Output (), s, SYS.STRLEN (s)))
- END WriteStr;
-
- (*
- ** $S- Disable compiler stack checking.
- **
- ** CheckBreak() is always called from within a procedure which has already
- ** done it, and PutCh() won't work with it on.
- *)
-
- (*------------------------------------*)
- PROCEDURE CheckBreak ();
-
- VAR signals : SET;
-
- BEGIN (* CheckBreak *)
- IF enableBreak THEN
- signals := Exec.base.SetSignal ({}, {});
- IF Dos.sigBreakCtrlC IN signals THEN
- enableBreak := FALSE;
- WriteStr ("\n***BREAK -- User aborted\n");
- HALT (Dos.returnWarn)
- END
- END
- END CheckBreak;
-
- (*------------------------------------*)
- PROCEDURE* PutCh ();
-
- BEGIN (* PutCh *)
- SYS.INLINE (16C0H) (* MOVE.B D0,(A3)+ *)
- END PutCh;
- (* $S= Enable compiler stack checking *)
-
- (*------------------------------------*)
- PROCEDURE WriteInt* (i : LONGINT);
-
- VAR
- str : ARRAY 256 OF CHAR;
-
- BEGIN (* WriteInt *)
- Exec.base.OldRawDoFmtL ("%ld", i, PutCh, SYS.ADR (str));
- WriteStr (str)
- END WriteInt;
-
- (*------------------------------------*)
- PROCEDURE WriteHex* (i : LONGINT);
-
- VAR
- str : ARRAY 256 OF CHAR;
-
- BEGIN (* WriteHex *)
- Exec.base.OldRawDoFmtL ("%lx", i, PutCh, SYS.ADR (str));
- WriteStr (str)
- END WriteHex;
-
- (*
- * The following WriteReal* and WriteLongReal* procedures have been pinched
- * from Module Texts and have been somewhat modified from the original code
- * described in "Project Oberon".
- *)
-
- (*------------------------------------*)
- PROCEDURE WriteReal * ( x : REAL; n : INTEGER );
-
- VAR e : INTEGER; x0 : REAL; d : ARRAY maxD OF CHAR;
-
- BEGIN (* WriteReal *)
- (*
- * This implementation uses Motorola FFP format reals instead of IEEE
- * single-precision reals. The Project Oberon code has been modified to
- * remove the special-case handling of unnormal and NaN values and assume
- * 7-bit exponents instead of 8-bit.
- *)
- e := Reals.Expo (x);
- IF n <= 9 THEN n := 3 ELSE DEC (n, 6) END;
- REPEAT Write (" "); DEC (n) UNTIL n <= 8;
- (* there are 2 < n <= 8 digits to be written *)
- IF x < 0.0 THEN Write ("-"); x := -x ELSE Write (" ") END;
- e := (e - 64) * 77 DIV 256;
- IF e >= 0 THEN x := x / Reals.Ten (e) ELSE x := Reals.Ten (-e) * x END;
- IF x >= 10.0 THEN x := 0.1 * x; INC (e) END;
- x0 := Reals.Ten (n - 1); x := x0 * x + 0.5;
- IF x >= 10.0 * x0 THEN x := x * 0.1; INC (e) END;
- Reals.Convert (x, n, d);
- DEC (n); Write (d [n]); Write (".");
- REPEAT DEC (n); Write (d [n]) UNTIL n = 0;
- Write ("E");
- IF e < 0 THEN Write ("-"); e := -e ELSE Write ("+") END;
- Write (CHR (e DIV 10 + 30H)); Write (CHR (e MOD 10 + 30H))
- END WriteReal;
-
- (*------------------------------------*)
- PROCEDURE WriteRealFix * ( x : REAL; n, k : INTEGER );
-
- VAR e, i : INTEGER; sign : CHAR; x0 : REAL; d : ARRAY maxD OF CHAR;
-
- (*------------------------------------*)
- PROCEDURE seq ( ch : CHAR; n : LONGINT );
-
- BEGIN (* seq *)
- WHILE n > 0 DO Write (ch); DEC (n) END
- END seq;
-
- (*------------------------------------*)
- PROCEDURE dig (n : INTEGER);
-
- BEGIN (* dig *)
- WHILE n > 0 DO
- DEC (i); Write (d [i]); DEC (n)
- END;
- END dig;
-
- BEGIN (* WriteRealFix *)
- (*
- * This implementation uses Motorola FFP format reals instead of IEEE
- * single-precision reals. The Project Oberon code has been modified to
- * remove the special-case handling of unnormal and NaN values and assume
- * 7-bit exponents instead of 8-bit.
- *)
- IF k < 0 THEN k := 0 END;
- e := (Reals.Expo (x) - 64) * 77 DIV 256;
- IF x < 0.0 THEN sign := "-"; x := -x ELSE sign := " " END;
- IF e >= 0 THEN (* x >= 1.0, 77/256 = log 2 *) x := x / Reals.Ten (e)
- ELSE (* x < 1.0 *) x := Reals.Ten (-e) * x END;
- IF x >= 10.0 THEN x := 0.1 * x; INC (e) END;
- (* 1 <= x < 10 *)
- IF k + e >= maxD - 1 THEN k := maxD - 1 - e
- ELSIF k + e < 0 THEN k := -e; x := 0.0
- END;
- x0 := Reals.Ten (k + e); x := x0 * x + 0.5;
- IF x >= 10.0 * x0 THEN INC (e) END;
- (* e = no. of digits before decimal point *)
- INC (e); i := k + e; Reals.Convert (x, i, d);
- IF e > 0 THEN
- seq (" ", n - e - k - 2); Write (sign); dig (e); Write (".");
- dig (k)
- ELSE
- seq (" ", n - k - 3); Write (sign); Write ("0"); Write (".");
- seq ("0", -e); dig (k + e)
- END; (* ELSE *)
- END WriteRealFix;
-
- (*------------------------------------*)
- PROCEDURE WriteRealHex * ( x : REAL );
-
- VAR d : ARRAY 9 OF CHAR;
-
- BEGIN (* WriteRealHex *)
- Reals.ConvertH (x, d); d [8] := 0X; WriteStr (d)
- END WriteRealHex;
-
- (*------------------------------------*)
- PROCEDURE WriteLongReal * ( x : LONGREAL; n : INTEGER );
-
- BEGIN (* WriteLongReal *)
- (*
- * In this implementation, LONGREAL and REAL types are the same, so this
- * procedure is implemented as a call to WriteReal ().
- *)
- WriteReal (SHORT (x), n)
- END WriteLongReal;
-
- (*------------------------------------*)
- PROCEDURE WriteLongRealHex * ( x : LONGREAL );
-
- BEGIN (* WriteLongRealHex *)
- (*
- * In this implementation, LONGREAL and REAL types are the same, so this
- * procedure is implemented as a call to WriteRealHex ().
- *)
- WriteRealHex (SHORT (x))
- END WriteLongRealHex;
-
- (*------------------------------------*)
- (* $D- Disables copying of dynamic array parameters. *)
- PROCEDURE WriteF* (
- fs : ARRAY OF CHAR; VAR f : ARRAY OF SYS.LONGWORD);
-
- VAR
- str : ARRAY 256 OF CHAR;
-
- BEGIN (* WriteF *)
- Exec.base.OldRawDoFmtL (fs, f, PutCh, SYS.ADR (str));
- WriteStr (str)
- END WriteF;
-
- (*------------------------------------*)
- (* $D- Disables copying of dynamic array parameters. *)
- PROCEDURE WriteF1*
- ( fs : ARRAY OF CHAR;
- param1 : SYS.LONGWORD);
-
- VAR str : ARRAY 256 OF CHAR;
-
- BEGIN (* WriteF1 *)
- Exec.base.OldRawDoFmtL (fs, param1, PutCh, SYS.ADR (str));
- WriteStr (str)
- END WriteF1;
-
- (*------------------------------------*)
- (* $D- Disables copying of dynamic array parameters. *)
- PROCEDURE WriteF2* (
- fs : ARRAY OF CHAR; param1, param2 : SYS.LONGWORD);
-
- VAR str : ARRAY 256 OF CHAR; t : SYS.LONGWORD;
-
- BEGIN (* WriteF2 *)
- t := param1; param1 := param2; param2 := t;
- Exec.base.OldRawDoFmtL (fs, param2, PutCh, SYS.ADR (str));
- WriteStr (str)
- END WriteF2;
-
- (*------------------------------------*)
- (* $D- Disables copying of dynamic array parameters. *)
- PROCEDURE WriteF3* (
- fs : ARRAY OF CHAR; param1, param2, param3 : SYS.LONGWORD);
-
- VAR str : ARRAY 256 OF CHAR; t : SYS.LONGWORD;
-
- BEGIN (* WriteF3 *)
- t := param1; param1 := param3; param3 := t;
- Exec.base.OldRawDoFmtL (fs, param3, PutCh, SYS.ADR (str));
- WriteStr (str)
- END WriteF3;
-
- (*------------------------------------*)
- PROCEDURE Read* (VAR ch : CHAR);
-
- BEGIN (* Read *)
- CheckBreak ();
- IF Dos.base.Read (Dos.base.Input (), ch, 1) < 1 THEN ch := 0X END;
- END Read;
-
- (*------------------------------------*)
- PROCEDURE ReadStr* (VAR str : ARRAY OF CHAR);
-
- VAR ch : CHAR; index, limit : INTEGER;
-
- BEGIN (* ReadStr *)
- (* Skip white space *)
- REPEAT Read (ch) UNTIL (ch # " ") & (ch # 09X);
- (* Read until control char *)
- index := 0; limit := SHORT (LEN (str));
- WHILE (ch >= " ") & (index < limit) DO
- str [index] := ch; INC (index); Read (ch);
- END; (* WHILE *)
- str [index] := 0X;
- (* Skip rest of line if any *)
- WHILE ch >= " " DO Read (ch) END;
- END ReadStr;
-
- BEGIN
- enableBreak := TRUE;
- END StdIO.
-