2019-03-11 11:59:55 +03:00
|
|
|
(*
|
|
|
|
Copyright 2016, 2018 Anton Krotov
|
2016-10-24 02:30:27 +03:00
|
|
|
|
|
|
|
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
|
2019-03-11 11:59:55 +03:00
|
|
|
err := TRUE;
|
|
|
|
flag := FALSE;
|
|
|
|
res := 0
|
2016-10-24 02:30:27 +03:00
|
|
|
ELSE
|
2019-03-11 11:59:55 +03:00
|
|
|
res := res + (ORD(str[i]) - ORD("0"));
|
|
|
|
INC(i)
|
2016-10-24 02:30:27 +03:00
|
|
|
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
|
2019-03-11 11:59:55 +03:00
|
|
|
INC(i)
|
2016-10-24 02:30:27 +03:00
|
|
|
END;
|
|
|
|
IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN
|
2019-03-11 11:59:55 +03:00
|
|
|
INC(i);
|
|
|
|
IF (s[i] = "+") OR (s[i] = "-") THEN
|
|
|
|
INC(i)
|
|
|
|
END;
|
|
|
|
Res := digit(s[i]);
|
|
|
|
WHILE digit(s[i]) DO
|
|
|
|
INC(i)
|
|
|
|
END
|
2016-10-24 02:30:27 +03:00
|
|
|
END
|
|
|
|
END
|
|
|
|
END
|
|
|
|
RETURN Res & (s[i] <= 20X)
|
|
|
|
END CheckReal;
|
|
|
|
|
2019-03-11 11:59:55 +03:00
|
|
|
PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL;
|
|
|
|
CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH;
|
|
|
|
VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN;
|
2016-10-24 02:30:27 +03:00
|
|
|
|
2019-03-11 11:59:55 +03:00
|
|
|
PROCEDURE part1 (str: STRING; VAR res, d: REAL; VAR i: INTEGER): BOOLEAN;
|
2016-10-24 02:30:27 +03:00
|
|
|
BEGIN
|
2019-03-11 11:59:55 +03:00
|
|
|
res := 0.0;
|
|
|
|
d := 1.0;
|
2016-10-24 02:30:27 +03:00
|
|
|
WHILE digit(str[i]) DO
|
2019-03-11 11:59:55 +03:00
|
|
|
res := res * 10.0 + FLT(ORD(str[i]) - ORD("0"));
|
2016-10-24 02:30:27 +03:00
|
|
|
INC(i)
|
|
|
|
END;
|
|
|
|
IF str[i] = "." THEN
|
|
|
|
INC(i);
|
|
|
|
WHILE digit(str[i]) DO
|
2019-03-11 11:59:55 +03:00
|
|
|
d := d / 10.0;
|
|
|
|
res := res + FLT(ORD(str[i]) - ORD("0")) * d;
|
|
|
|
INC(i)
|
2016-10-24 02:30:27 +03:00
|
|
|
END
|
|
|
|
END
|
|
|
|
RETURN str[i] # 0X
|
|
|
|
END part1;
|
|
|
|
|
2019-03-11 11:59:55 +03:00
|
|
|
PROCEDURE part2 (str: STRING; VAR i, scale: INTEGER; VAR minus, err: BOOLEAN; VAR m, res: REAL): BOOLEAN;
|
2016-10-24 02:30:27 +03:00
|
|
|
BEGIN
|
|
|
|
INC(i);
|
2019-03-11 11:59:55 +03:00
|
|
|
m := 10.0;
|
2016-10-24 02:30:27 +03:00
|
|
|
minus := FALSE;
|
|
|
|
IF str[i] = "+" THEN
|
|
|
|
INC(i)
|
|
|
|
ELSIF str[i] = "-" THEN
|
|
|
|
minus := TRUE;
|
|
|
|
INC(i);
|
2019-03-11 11:59:55 +03:00
|
|
|
m := 0.1
|
2016-10-24 02:30:27 +03:00
|
|
|
END;
|
|
|
|
scale := 0;
|
|
|
|
err := FALSE;
|
|
|
|
WHILE ~err & digit(str[i]) DO
|
|
|
|
IF scale > maxINT DIV 10 THEN
|
2019-03-11 11:59:55 +03:00
|
|
|
err := TRUE;
|
|
|
|
res := 0.0
|
2016-10-24 02:30:27 +03:00
|
|
|
ELSE
|
2019-03-11 11:59:55 +03:00
|
|
|
scale := scale * 10;
|
|
|
|
IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN
|
|
|
|
err := TRUE;
|
|
|
|
res := 0.0
|
|
|
|
ELSE
|
|
|
|
scale := scale + (ORD(str[i]) - ORD("0"));
|
|
|
|
INC(i)
|
|
|
|
END
|
2016-10-24 02:30:27 +03:00
|
|
|
END
|
|
|
|
END
|
|
|
|
RETURN ~err
|
|
|
|
END part2;
|
|
|
|
|
2019-03-11 11:59:55 +03:00
|
|
|
PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR res, m: REAL; VAR scale: INTEGER);
|
2016-10-24 02:30:27 +03:00
|
|
|
VAR i: INTEGER;
|
|
|
|
BEGIN
|
|
|
|
err := FALSE;
|
|
|
|
IF scale = maxINT THEN
|
|
|
|
err := TRUE;
|
2019-03-11 11:59:55 +03:00
|
|
|
res := 0.0
|
2016-10-24 02:30:27 +03:00
|
|
|
END;
|
|
|
|
i := 1;
|
|
|
|
WHILE ~err & (i <= scale) DO
|
|
|
|
IF ~minus & (res > maxDBL / m) THEN
|
2019-03-11 11:59:55 +03:00
|
|
|
err := TRUE;
|
|
|
|
res := 0.0
|
2016-10-24 02:30:27 +03:00
|
|
|
ELSE
|
2019-03-11 11:59:55 +03:00
|
|
|
res := res * m;
|
|
|
|
INC(i)
|
2016-10-24 02:30:27 +03:00
|
|
|
END
|
|
|
|
END
|
|
|
|
END part3;
|
|
|
|
|
|
|
|
BEGIN
|
|
|
|
IF CheckReal(str, i, neg) THEN
|
2019-03-11 11:59:55 +03:00
|
|
|
IF part1(str, res, d, i) & part2(str, i, scale, minus, err, m, res) THEN
|
|
|
|
part3(err, minus, res, m, scale)
|
2016-10-24 02:30:27 +03:00
|
|
|
END;
|
|
|
|
IF neg THEN
|
|
|
|
res := -res
|
|
|
|
END
|
|
|
|
ELSE
|
2019-03-11 11:59:55 +03:00
|
|
|
res := 0.0;
|
2016-10-24 02:30:27 +03:00
|
|
|
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;
|
|
|
|
|
2019-03-11 11:59:55 +03:00
|
|
|
PROCEDURE Real* (VAR x: REAL);
|
2016-10-24 02:30:27 +03:00
|
|
|
VAR str: STRING; err: BOOLEAN;
|
|
|
|
BEGIN
|
|
|
|
err := FALSE;
|
|
|
|
REPEAT
|
|
|
|
String(str)
|
|
|
|
UNTIL ~Space(str);
|
|
|
|
x := StrToFloat(str, err);
|
|
|
|
Done := ~err
|
|
|
|
END Real;
|
|
|
|
|
2019-03-11 11:59:55 +03:00
|
|
|
|
2016-10-24 02:30:27 +03:00
|
|
|
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.
|