From 2a242ae9608385ed77b0c6be9ece1728d7b74f6d Mon Sep 17 00:00:00 2001 From: David Brown Date: Sun, 30 Oct 2016 14:22:10 +0000 Subject: [PATCH] Add Oakwood 'In' module and a test for it. --- .gitignore | 1 + src/runtime/In.Mod | 175 +++++++++++++++++------------- src/runtime/Out.Mod | 2 +- src/test/confidence/in/expected | 14 +++ src/test/confidence/in/intest.mod | 16 +++ src/test/confidence/in/test.sh | 16 +++ src/tools/make/oberon.mk | 6 +- 7 files changed, 151 insertions(+), 79 deletions(-) create mode 100644 src/test/confidence/in/expected create mode 100644 src/test/confidence/in/intest.mod create mode 100644 src/test/confidence/in/test.sh diff --git a/.gitignore b/.gitignore index db4032e0..a8e5ff00 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ /src/test/**/*.obj /src/test/**/*.sym **/*.stackdump +/src/test/confidence/**/input /src/test/confidence/**/result /src/test/confidence/**/result-* /src/test/confidence/**/*.asm diff --git a/src/runtime/In.Mod b/src/runtime/In.Mod index aa67e4e7..873a00d9 100644 --- a/src/runtime/In.Mod +++ b/src/runtime/In.Mod @@ -3,113 +3,136 @@ MODULE In; IMPORT Platform, SYSTEM, Out; VAR - nextch: CHAR; - ready: BOOLEAN; - initialized: BOOLEAN; + Done-: BOOLEAN; + nextch: CHAR; (* Maintains 1 character read ahaead except at end of line. *) + readstate: INTEGER; - Done-: BOOLEAN; - -PROCEDURE ReadChar; -VAR error: Platform.ErrorCode; n: LONGINT; ch: CHAR; -BEGIN - error := Platform.ReadBuf(Platform.StdIn, ch, n); - ready := (error = 0) & (n = 1); - IF ready & (nextch = 0DX) & (ch = 0AX) THEN - ready := (error = 0) & (n = 1) - END; - IF ready THEN nextch := ch ELSE nextch := 0X END -END ReadChar; - -PROCEDURE Flush; -BEGIN Out.Flush; IF ~initialized THEN ReadChar END; initialized := TRUE -END Flush; +CONST + pending = 0; (* readstate when at start of input or end of line. Implies nextch undefined. *) + ready = 1; (* readstate when nextch is defined and contains next character on current line. *) + eof = 2; (* readstate when at end of file. *) PROCEDURE Open*; - VAR error: Platform.ErrorCode; +VAR error: Platform.ErrorCode; BEGIN - error := Platform.Seek(Platform.StdIn, 0, Platform.SeekSet); (* Rewind STDIN to beginning of file. *) - ready := TRUE; initialized := FALSE; + error := Platform.Seek(Platform.StdIn, 0, Platform.SeekSet); (* Rewind STDIN to beginning of file. *) + readstate := pending; + Done := TRUE; END Open; -PROCEDURE Char*(VAR ch: CHAR); -BEGIN Flush; - Done := ready; - IF ready THEN ch := nextch; ReadChar ELSE ch := 0X END -END Char; - -PROCEDURE Skip; +PROCEDURE ReadChar; +VAR error: Platform.ErrorCode; n: LONGINT; BEGIN - WHILE ready & (nextch <= " ") DO ReadChar END; (* Skip leading blanks, CR, LF, tab etc. *) -END Skip; + error := Platform.ReadBuf(Platform.StdIn, nextch, n); + IF (error = 0) & (n = 1) THEN readstate := ready ELSE readstate := eof END +END ReadChar; + +PROCEDURE StartRead; (* Ensure either nextch is valid or we're at EOF. *) +BEGIN Out.Flush; IF readstate = pending THEN ReadChar END; +END StartRead; + +PROCEDURE StartAndSkip; (* Like StartRead, but also skip over blanks, CR, LF, tab. *) +BEGIN StartRead; + WHILE (readstate = ready) & (nextch <= " ") DO ReadChar END +END StartAndSkip; + +PROCEDURE Char*(VAR ch: CHAR); +BEGIN + StartRead; + Done := readstate = ready; + IF Done THEN + ch := nextch; + IF ch = 0AX THEN readstate := pending ELSE ReadChar END + ELSE + ch := 0X + END +END Char; PROCEDURE HugeInt*(VAR h: HUGEINT); VAR - neg, hex, decdigit, hexdigit: BOOLEAN; + neg, hex, endofnum: BOOLEAN; decacc, hexacc, digit: HUGEINT; BEGIN - Flush; Skip; - - neg := nextch = '-'; IF neg THEN ReadChar END; - hex := FALSE; - endofnum := FALSE; - decacc := 0; - hexacc := 0; - Done := FALSE; - - WHILE ready & ~endofnum DO - decdigit := (nextch >= "0") & (nextch <= "9"); - IF decdigit THEN digit := ORD(nextch) MOD 16 END; - - hexdigit := (nextch >= "f") & (nextch <= "f") OR (nextch >= "A") & (nextch <= "F"); - IF hexdigit THEN ORD(nextch) MOD 16 + 9; hex := TRUE END; - - IF decdigit OR hexdigit THEN - Done := TRUE; - decacc := decacc * 10 + digit; - hexacc := hexacc * 16 + digit; - ReadChar - ELSIF nextch = "H" THEN - hex := TRUE; endofnum := TRUE; ReadChar + StartAndSkip; + Done := FALSE; + IF readstate = ready THEN + neg := nextch = '-'; IF neg THEN ReadChar END; + hex := FALSE; + endofnum := FALSE; + decacc := 0; + hexacc := 0; + WHILE (readstate = ready) & ~endofnum DO + digit := -1; + IF (nextch >= "0") & (nextch <= "9") THEN + digit := ORD(nextch) MOD 16 + ELSIF (nextch >= "a") & (nextch <= "f") + OR (nextch >= "A") & (nextch <= "F") THEN + digit := ORD(nextch) MOD 16 + 9; hex := TRUE + END; + IF digit >= 0 THEN + Done := TRUE; + decacc := decacc * 10 + digit; + hexacc := hexacc * 16 + digit; + ReadChar + ELSIF nextch = "H" THEN + hex := TRUE; endofnum := TRUE; ReadChar + ELSE + endofnum := TRUE + END + END; + IF Done THEN + IF hex THEN h := hexacc ELSE h := decacc END; + IF neg THEN h := -h END ELSE - endofnum := TRUE + h := 0 END - END; - IF Done THEN - IF hex THEN h := hexacc ELSE h := decacc END; - IF neg THEN h := -h END - ELSE - h := 0 END END HugeInt; PROCEDURE Int*(VAR i: INTEGER); - VAR h: HUGEINT; +VAR h: HUGEINT; BEGIN HugeInt(h); i := SYSTEM.VAL(INTEGER, h) END Int; PROCEDURE LongInt*(VAR i: LONGINT); - VAR h: HUGEINT; +VAR h: HUGEINT; BEGIN HugeInt(h); i := SYSTEM.VAL(LONGINT, h) END LongInt; PROCEDURE Real*(VAR x: REAL); -BEGIN ASSERT(FALSE) (* Not implemented *) +BEGIN HALT(99) (* Not implemented *) END Real; PROCEDURE LongReal*(VAR y: LONGREAL); -BEGIN ASSERT(FALSE) (* Not implemented *) +BEGIN HALT(99) (* Not implemented *) END LongReal; +PROCEDURE Line*(VAR line: ARRAY OF CHAR); +VAR i: INTEGER; +BEGIN StartRead; i := 0; Done := readstate = ready; + WHILE (readstate = ready) & (nextch # 0DX) & (nextch # 0AX) & (i < LEN(line)-1) DO + line[i] := nextch; INC(i); ReadChar + END; + line[i] := 0X; + IF (readstate = ready) & (nextch = 0DX) THEN ReadChar END; + IF (readstate = ready) & (nextch = 0AX) THEN readstate := pending END; +END Line; + PROCEDURE String*(VAR str: ARRAY OF CHAR); - VAR i: INTEGER; -BEGIN Flush; Skip; i := 0; - IF ready AND nextch = '"' THEN (* " *) +VAR i: INTEGER; +BEGIN StartAndSkip; i := 0; + IF (readstate = ready) & (nextch = '"') THEN (* " *) ReadChar; - WHILE ready & (i < LEN(str)-1) & (nextch >= " ") & (nextch # '"') DO (* " *) - str[i] := nextch; INC(i) + WHILE (readstate = ready) + & (i < LEN(str)-1) + & (nextch >= " ") + & (nextch # '"') DO (* " *) + str[i] := nextch; ReadChar; INC(i) END END; - Done := ready & (i < LEN(str)-1) & (nextch = '"'); (* " *) + Done := (readstate = ready) + & (i < LEN(str)-1) + & (nextch = '"'); (* " *) IF Done THEN ReadChar; str[i] := 0X ELSE @@ -118,11 +141,11 @@ BEGIN Flush; Skip; i := 0; END String; PROCEDURE Name*(VAR name: ARRAY OF CHAR); (* Read filename. Presumably using shell semantics. *) -BEGIN ASSERT(FALSE) (* Not implemented *) +BEGIN HALT(99) (* Not implemented *) END Name; BEGIN - nextch := 0X; - ready := FALSE; - initialized := FALSE; + nextch := 0X; + readstate := pending; + Done := TRUE; END In. diff --git a/src/runtime/Out.Mod b/src/runtime/Out.Mod index 52157484..c6429527 100644 --- a/src/runtime/Out.Mod +++ b/src/runtime/Out.Mod @@ -97,7 +97,7 @@ PROCEDURE -Entier64(x: LONGREAL): SYSTEM.INT64 "(int64)(x)"; PROCEDURE RealP(x: LONGREAL; n: INTEGER; long: BOOLEAN); -(* LongReal(x, n) writes the long real number x to the end of the output stream using an +(* RealP(x, n) writes the long real number x to the end of the output stream using an exponential form. If the textual representation of x requires m characters (including a three-digit signed exponent), x is right adjusted in a field of Max(n, m) characters padded with blanks at the left end. A plus sign of the mantissa is not written. diff --git a/src/test/confidence/in/expected b/src/test/confidence/in/expected new file mode 100644 index 00000000..df0db21e --- /dev/null +++ b/src/test/confidence/in/expected @@ -0,0 +1,14 @@ +--- Testing with Oberon 2 variable model --- +chars: Splurdle +integer: 37 +string: "Bert" +line: rest of line +line: another line + + +--- Testing with Component Pascal variable model --- +chars: Splurdle +integer: 37 +string: "Bert" +line: rest of line +line: another line diff --git a/src/test/confidence/in/intest.mod b/src/test/confidence/in/intest.mod new file mode 100644 index 00000000..cb8d2963 --- /dev/null +++ b/src/test/confidence/in/intest.mod @@ -0,0 +1,16 @@ +MODULE intest; +IMPORT Out, In; + +VAR ch: CHAR; i: INTEGER; s: ARRAY 100 OF CHAR; + +BEGIN + In.Char(ch); Out.String("chars: "); + WHILE In.Done & (ch # ".") DO Out.Char(ch); In.Char(ch) END; + Out.Ln; + In.Int(i); IF In.Done THEN Out.String("integer: "); Out.Int(i,1); Out.Ln END; + In.String(s); IF In.Done THEN Out.String('string: "'); Out.String(s); Out.String('"'); Out.Ln END; + In.Line(s); + WHILE In.Done DO + Out.String("line: "); Out.String(s); Out.Ln; In.Line(s) + END +END intest. diff --git a/src/test/confidence/in/test.sh b/src/test/confidence/in/test.sh new file mode 100644 index 00000000..ee738ab4 --- /dev/null +++ b/src/test/confidence/in/test.sh @@ -0,0 +1,16 @@ +#!/bin/sh +. ../testenv.sh +rm -f intest # Remove LSW binary so it doesn't hide Cygwin binary. +echo 'Splurdle.25H "Bert"rest of line'>input +echo another line>>input +$OBECOMP intest.mod -m -O2 +./intest result-O2 +$OBECOMP intest.mod -m -OC +./intest result-OC +echo --- Testing with Oberon 2 variable model --- >result +cat result-O2 >>result +echo "" >>result +echo "" >>result +echo --- Testing with Component Pascal variable model --- >>result +cat result-OC >>result +. ../testresult.sh diff --git a/src/tools/make/oberon.mk b/src/tools/make/oberon.mk index ffdbded1..c67dfe10 100644 --- a/src/tools/make/oberon.mk +++ b/src/tools/make/oberon.mk @@ -197,6 +197,7 @@ runtime: cd $(BUILDDIR)/$(MODEL); $(ROOTDIR)/$(OBECOMP) -Ffs -O$(MODEL) ../../../src/runtime/Modules.Mod cd $(BUILDDIR)/$(MODEL); $(ROOTDIR)/$(OBECOMP) -Ffs -O$(MODEL) ../../../src/runtime/Strings.Mod cd $(BUILDDIR)/$(MODEL); $(ROOTDIR)/$(OBECOMP) -Ffs -O$(MODEL) ../../../src/runtime/Out.Mod + cd $(BUILDDIR)/$(MODEL); $(ROOTDIR)/$(OBECOMP) -Ffs -O$(MODEL) ../../../src/runtime/In.Mod cd $(BUILDDIR)/$(MODEL); $(ROOTDIR)/$(OBECOMP) -Ffs -O$(MODEL) ../../../src/runtime/VT100.Mod cd $(BUILDDIR)/$(MODEL); $(ROOTDIR)/$(OBECOMP) -Ffs -O$(MODEL) ../../../src/runtime/Files.Mod cd $(BUILDDIR)/$(MODEL); $(ROOTDIR)/$(OBECOMP) -Ffs -O$(MODEL) ../../../src/runtime/Math.Mod @@ -382,14 +383,15 @@ RUNTEST = COMPILER=$(COMPILER) OBECOMP="$(OBECOMP) -O$(MODEL)" FLAVOUR=$(FLAVOUR confidence: @printf "\n\n--- Confidence tests ---\n\n" cd src/test/confidence/hello; $(RUNTEST) - cd src/test/confidence/isptest; $(RUNTEST) cd src/test/confidence/out; $(RUNTEST) + cd src/test/confidence/in; $(RUNTEST) cd src/test/confidence/math; $(RUNTEST) cd src/test/confidence/intsyntax; $(RUNTEST) cd src/test/confidence/language; $(RUNTEST) + cd src/test/confidence/arrayassignment; $(RUNTEST) cd src/test/confidence/texts; $(RUNTEST) cd src/test/confidence/library; $(RUNTEST) + cd src/test/confidence/isptest; $(RUNTEST) cd src/test/confidence/lola; $(RUNTEST) - cd src/test/confidence/arrayassignment; $(RUNTEST) if [ "$(PLATFORM)" != "windows" ] ; then cd src/test/confidence/signal; $(RUNTEST); fi @printf "\n\n--- Confidence tests passed ---\n\n"