home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
new
/
dev
/
obero
/
oberon-a
/
source
/
library
/
in.mod
< prev
next >
Wrap
Text File
|
1995-06-29
|
11KB
|
434 lines
(*************************************************************************
$RCSfile: In.mod $
Description: Formatted input from the standard input stream.
Created by: fjc (Frank Copeland)
$Revision: 1.3 $
$Author: fjc $
$Date: 1995/01/26 00:40:27 $
Copyright © 1994-1995, Frank Copeland.
This file is part of the Oberon-A Library.
See Oberon-A.doc for conditions of use and distribution.
*************************************************************************)
MODULE In;
(**
** Extracts from the Oakwood Report are enclosed in quotes.
**
** "Module In provides a set of basic routines for formatted input of
** characters, character sequences, numbers, and names. It assumes a
** standard input stream with a current position that can be reset to
** the beginning of the stream."
**
** This implementation uses the standard AmigaDOS input stream provided
** through the Input() system function as the source of characters.
*)
IMPORT SYS := SYSTEM, Dos, DosUtil, WbConsole, Reals, Sets;
(**
** "Done indicates the success of an input operation. If Done is TRUE
** after an input operation, the operation was successful and its result
** is valid. An unsuccessful input operation sets Done to FALSE; it
** remains FALSE until the next call to Open(). In particular, Done is set
** to FALSE if an attempt is made to read beyond the end of the input
** stream."
*)
VAR
Done -: BOOLEAN;
(*
** eof is set by Read(), and is TRUE if an attempt to read from the
** standard input fails.
**
** nameChars is used in Scan() to determine which characters are legal in
** AmigaDos filenames.
*)
VAR
eof : BOOLEAN;
nameChars : Sets.CharSet;
CONST
(* symbol classes *)
inval = 0; (* invalid symbol *)
name = 1; (* name s *)
string = 2; (* literal string s *)
int = 3; (* integer i (decimal or hexadecimal) *)
real = 4; (* real number rval *)
lreal = 5; (* long real number lrval *)
char = 6; (* special character c *)
TAB = 9X; CR = 0DX; LF = 0AX; (* Amiga end-of-line character *)
maxStr = 256;
(* Results from Scan *)
VAR
class : INTEGER;
ival : LONGINT;
rval : REAL;
lrval : LONGREAL;
cval : CHAR;
sval : ARRAY maxStr OF CHAR;
PROCEDURE Read ( VAR ch : CHAR );
VAR i : LONGINT;
BEGIN (* Read *)
DosUtil.HaltIfBreak ({Dos.ctrlC});
IF ~eof THEN
i := Dos.FGetC (Dos.Input());
IF i >= 0 THEN ch := CHR (i)
ELSE ch := 0X; eof := TRUE
END
END
END Read;
PROCEDURE ScanName;
VAR
ch : CHAR;
i : SHORTINT;
ignore : LONGINT;
BEGIN (* ScanName *)
Read (ch); i := 0;
LOOP
IF (ch # " ") & (ch # TAB) THEN EXIT END;
Read (ch)
END;
IF (CAP (ch) >= "A") & (CAP (ch) <= "Z") THEN (* name *)
(*
** AmigaDos filenames can include all printable characters. Full path
** names can include ":" and "/", but ":" can only appear once, and
** must come before any "/".
*)
nameChars.Clear;
nameChars.InclChRange (" ", "~"); nameChars.InclChRange (0A1X, 0FFX);
REPEAT
IF (ch = ":") OR (ch = "/") THEN nameChars.ExclCh (":") END;
sval [i] := ch; INC (i); Read (ch)
UNTIL ~nameChars.ContainsCh (ch) OR (i = (maxStr - 1));
sval [i] := 0X; class := name;
IF ~eof & (ch # CR) & (ch # LF) THEN
ignore := Dos.UnGetC (Dos.Input(), -1)
END
ELSIF (ch = CR) OR (ch = LF) THEN
sval := ""; class := name
ELSE
class := inval;
IF ~eof THEN ignore := Dos.UnGetC (Dos.Input(), -1) END
END
END ScanName;
PROCEDURE ScanStr;
VAR ch : CHAR; i : SHORTINT; ignore : LONGINT;
BEGIN (* ScanStr *)
Read (ch); i := 0;
LOOP
IF (ch # " ") & (ch # TAB) THEN EXIT END;
Read (ch)
END;
IF ch = 22X THEN (* literal string *)
Read (ch);
WHILE (ch # 22X) & (ch >= " ") & (i # (maxStr - 1)) DO
sval [i] := ch; INC (i); Read (ch)
END;
sval [i] := 0X; class := string;
IF ch # 22X THEN Done := FALSE END
ELSIF (ch = CR) OR (ch = LF) THEN
sval := ""; class := string
ELSE
class := inval;
IF ~eof THEN ignore := Dos.UnGetC (Dos.Input(), -1) END
END
END ScanStr;
PROCEDURE ScanNum;
CONST
maxD = 32;
(* Limits for exponents *)
MaxExp = 38; (* REAL : IEEE single-precision *)
MaxLExp = 38; (* LONGREAL : IEEE single-precision *)
VAR
ch : CHAR;
neg, negE, hex : BOOLEAN;
i, j, h : SHORTINT;
e : INTEGER; k, ignore : LONGINT;
x, f : REAL; y, g : LONGREAL;
d : ARRAY maxD OF CHAR;
(*------------------------------------*)
PROCEDURE ReadScaleFactor ();
BEGIN (* ReadScaleFactor *)
Read (ch);
IF ch = "-" THEN negE := TRUE; Read (ch)
ELSE negE := FALSE; IF ch = "+" THEN Read (ch) END;
END;
WHILE (ch >= "0") & (ch <= "9") DO
e := e * 10 + ORD (ch) - 30H; Read (ch)
END;
IF ~eof THEN ignore := Dos.UnGetC (Dos.Input(), -1) END
END ReadScaleFactor;
BEGIN (* ScanNum *)
Read (ch); i := 0;
LOOP
IF (ch # CR) & (ch # LF) & (ch # " ") & (ch # TAB) THEN EXIT END;
Read (ch)
END;
IF (CAP (ch) >= "A") & (CAP (ch) <= "Z") THEN (* name *)
IF ~eof THEN ignore := Dos.UnGetC (Dos.Input(), -1) END;
class := inval
ELSIF ch = 22X THEN (* literal string *)
IF ~eof THEN ignore := Dos.UnGetC (Dos.Input(), -1) END;
class := inval
ELSE
IF ch = "-" THEN neg := TRUE; Read (ch) ELSE neg := FALSE END;
IF (ch >= "0") & (ch <= "9") THEN (* number *)
hex := FALSE; j := 0;
LOOP
d [i] := ch; INC (i); Read (ch);
IF ch < "0" THEN EXIT END;
IF "9" < ch THEN
IF ("A" <= ch) & (ch <= "F") THEN
hex := TRUE; ch := CHR (ORD (ch) - 7)
ELSIF ("a" <= ch) & (ch <= "f") THEN
hex := TRUE; ch := CHR (ORD (ch) - 27H)
ELSE
EXIT
END
END
END;
IF ch = "H" THEN (* hex number *)
class := int;
IF i - j > 8 THEN j := i - 8 END;
k := ORD (d [j]) - 30H; INC (j);
IF (i - j = 7) & (k >= 8) THEN DEC (k, 16) END;
WHILE j < i DO k := k * 10H + (ORD (d [j]) - 30H); INC (j) END;
IF neg THEN ival := -k ELSE ival := k END;
ELSIF ch = "." THEN (* read real *)
Read (ch); h := i;
WHILE Done & ("0" <= ch) & (ch <= "9") DO
d [i] := ch; INC (i); Read (ch)
END;
IF ch = "D" THEN
e := 0; y := 0.0; g := 1.0;
REPEAT y := y * 10.0 + (ORD (d [j]) - 30H); INC (j) UNTIL j = h;
WHILE j < i DO
g := g / 10.0; y := (ORD (d [j]) - 30H) * g + y; INC (j)
END;
ReadScaleFactor;
IF negE THEN
IF e <= MaxLExp THEN y := y / Reals.TenL (e) ELSE y := 0.0 END
ELSIF e > 0 THEN
IF e <= MaxLExp THEN y := y * Reals.TenL (e) ELSE HALT (40) END
END;
IF neg THEN y := -y END;
class := lreal; lrval := y
ELSE
e := 0; x := 0.0; f := 1.0;
REPEAT x := x * 10.0 + (ORD (d [j]) - 30H); INC (j) UNTIL j = h;
WHILE j < i DO
f := f / 10.0; x := (ORD (d [j]) - 30H) * f + x; INC (j)
END;
IF ch = "E" THEN ReadScaleFactor
ELSIF ~eof THEN ignore := Dos.UnGetC (Dos.Input(), -1)
END;
IF negE THEN
IF e <= MaxExp THEN x := x / Reals.Ten (e) ELSE x := 0.0 END
ELSIF e > 0 THEN
IF e <= MaxExp THEN x := x * Reals.Ten (e) ELSE HALT (40) END
END;
IF neg THEN x := -x END;
class := real; rval := x
END; (* ELSE *)
IF hex THEN class := inval END
ELSE (* decimal integer *)
IF ~eof THEN ignore := Dos.UnGetC (Dos.Input(), -1) END;
class := int; k := 0;
REPEAT k := k * 10 + (ORD (d [j]) - 30H); INC (j) UNTIL j = i;
IF neg THEN ival := -k ELSE ival := k END;
IF hex THEN class := inval ELSE class := int END
END
ELSE
class := char;
IF neg THEN cval := "-" ELSE cval := ch END
END
END
END ScanNum;
(**
** "Open() (re)sets the current position to the beginning of the input
** stream. Done indicates if the operation was successful."
*)
PROCEDURE Open*;
VAR ignore : LONGINT; in : Dos.FileHandle