0,0 → 1,296 |
(* |
Copyright 2016 Anton Krotov |
|
This program is free software: you can redistribute it and/or modify |
it under the terms of the GNU Lesser General Public License as published by |
the Free Software Foundation, either version 3 of the License, or |
(at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU Lesser General Public License for more details. |
|
You should have received a copy of the GNU Lesser General Public License |
along with this program. If not, see <http://www.gnu.org/licenses/>. |
*) |
|
MODULE In; |
|
IMPORT sys := SYSTEM, ConsoleLib; |
|
TYPE |
|
STRING = ARRAY 260 OF CHAR; |
|
VAR |
|
Done* : BOOLEAN; |
|
PROCEDURE digit(ch: CHAR): BOOLEAN; |
RETURN (ch >= "0") & (ch <= "9") |
END digit; |
|
PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN; |
VAR i: INTEGER; |
BEGIN |
i := 0; |
neg := FALSE; |
WHILE (s[i] <= 20X) & (s[i] # 0X) DO |
INC(i) |
END; |
IF s[i] = "-" THEN |
neg := TRUE; |
INC(i) |
ELSIF s[i] = "+" THEN |
INC(i) |
END; |
first := i; |
WHILE digit(s[i]) DO |
INC(i) |
END; |
last := i |
RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first]) |
END CheckInt; |
|
PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN; |
VAR i: INTEGER; min: STRING; |
BEGIN |
i := 0; |
min := "2147483648"; |
WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO |
INC(i) |
END |
RETURN i = 10 |
END IsMinInt; |
|
PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER; |
CONST maxINT = 7FFFFFFFH; |
VAR i, n, res: INTEGER; flag, neg: BOOLEAN; |
BEGIN |
res := 0; |
flag := CheckInt(str, i, n, neg, FALSE); |
err := ~flag; |
IF flag & neg & IsMinInt(str, i) THEN |
flag := FALSE; |
neg := FALSE; |
res := 80000000H |
END; |
WHILE flag & digit(str[i]) DO |
IF res > maxINT DIV 10 THEN |
err := TRUE; |
flag := FALSE; |
res := 0 |
ELSE |
res := res * 10; |
IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN |
err := TRUE; |
flag := FALSE; |
res := 0 |
ELSE |
res := res + (ORD(str[i]) - ORD("0")); |
INC(i) |
END |
END |
END; |
IF neg THEN |
res := -res |
END |
RETURN res |
END StrToInt; |
|
PROCEDURE Space(s: STRING): BOOLEAN; |
VAR i: INTEGER; |
BEGIN |
i := 0; |
WHILE (s[i] # 0X) & (s[i] <= 20X) DO |
INC(i) |
END |
RETURN s[i] = 0X |
END Space; |
|
PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN; |
VAR i: INTEGER; Res: BOOLEAN; |
BEGIN |
Res := CheckInt(s, n, i, neg, TRUE); |
IF Res THEN |
IF s[i] = "." THEN |
INC(i); |
WHILE digit(s[i]) DO |
INC(i) |
END; |
IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN |
INC(i); |
IF (s[i] = "+") OR (s[i] = "-") THEN |
INC(i) |
END; |
Res := digit(s[i]); |
WHILE digit(s[i]) DO |
INC(i) |
END |
END |
END |
END |
RETURN Res & (s[i] <= 20X) |
END CheckReal; |
|
PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): LONGREAL; |
CONST maxDBL = 1.69D308; maxINT = 7FFFFFFFH; |
VAR i, scale: INTEGER; res, m, d: LONGREAL; minus, neg: BOOLEAN; |
|
PROCEDURE part1(): BOOLEAN; |
BEGIN |
res := 0.0D0; |
d := 1.0D0; |
WHILE digit(str[i]) DO |
res := res * 10.0D0 + LONG(FLT(ORD(str[i]) - ORD("0"))); |
INC(i) |
END; |
IF str[i] = "." THEN |
INC(i); |
WHILE digit(str[i]) DO |
d := d / 10.0D0; |
res := res + LONG(FLT(ORD(str[i]) - ORD("0"))) * d; |
INC(i) |
END |
END |
RETURN str[i] # 0X |
END part1; |
|
PROCEDURE part2(): BOOLEAN; |
BEGIN |
INC(i); |
m := 10.0D0; |
minus := FALSE; |
IF str[i] = "+" THEN |
INC(i) |
ELSIF str[i] = "-" THEN |
minus := TRUE; |
INC(i); |
m := 0.1D0 |
END; |
scale := 0; |
err := FALSE; |
WHILE ~err & digit(str[i]) DO |
IF scale > maxINT DIV 10 THEN |
err := TRUE; |
res := 0.0D0 |
ELSE |
scale := scale * 10; |
IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN |
err := TRUE; |
res := 0.0D0 |
ELSE |
scale := scale + (ORD(str[i]) - ORD("0")); |
INC(i) |
END |
END |
END |
RETURN ~err |
END part2; |
|
PROCEDURE part3; |
VAR i: INTEGER; |
BEGIN |
err := FALSE; |
IF scale = maxINT THEN |
err := TRUE; |
res := 0.0D0 |
END; |
i := 1; |
WHILE ~err & (i <= scale) DO |
IF ~minus & (res > maxDBL / m) THEN |
err := TRUE; |
res := 0.0D0 |
ELSE |
res := res * m; |
INC(i) |
END |
END |
END part3; |
|
BEGIN |
IF CheckReal(str, i, neg) THEN |
IF part1() & part2() THEN |
part3 |
END; |
IF neg THEN |
res := -res |
END |
ELSE |
res := 0.0D0; |
err := TRUE |
END |
RETURN res |
END StrToFloat; |
|
PROCEDURE String*(VAR s: ARRAY OF CHAR); |
VAR res, length: INTEGER; str: STRING; |
BEGIN |
res := ConsoleLib.gets(sys.ADR(str[0]), LEN(str)); |
length := LENGTH(str); |
IF length > 0 THEN |
str[length - 1] := 0X |
END; |
COPY(str, s); |
Done := TRUE |
END String; |
|
PROCEDURE Char*(VAR x: CHAR); |
VAR str: STRING; |
BEGIN |
String(str); |
x := str[0]; |
Done := TRUE |
END Char; |
|
PROCEDURE Ln*; |
VAR str: STRING; |
BEGIN |
String(str); |
Done := TRUE |
END Ln; |
|
PROCEDURE LongReal*(VAR x: LONGREAL); |
VAR str: STRING; err: BOOLEAN; |
BEGIN |
err := FALSE; |
REPEAT |
String(str) |
UNTIL ~Space(str); |
x := StrToFloat(str, err); |
Done := ~err |
END LongReal; |
|
PROCEDURE Real*(VAR x: REAL); |
CONST maxREAL = 3.39E38; |
VAR y: LONGREAL; |
BEGIN |
LongReal(y); |
IF Done THEN |
IF ABS(y) > LONG(maxREAL) THEN |
x := 0.0; |
Done := FALSE |
ELSE |
x := SHORT(y) |
END |
END |
END Real; |
|
PROCEDURE Int*(VAR x: INTEGER); |
VAR str: STRING; err: BOOLEAN; |
BEGIN |
err := FALSE; |
REPEAT |
String(str) |
UNTIL ~Space(str); |
x := StrToInt(str, err); |
Done := ~err |
END Int; |
|
PROCEDURE Open*; |
BEGIN |
Done := TRUE |
END Open; |
|
END In. |