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