Subversion Repositories Kolibri OS

Rev

Rev 6613 | Rev 7696 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2016, 2018 Anton Krotov
  3.  
  4.     This program is free software: you can redistribute it and/or modify
  5.     it under the terms of the GNU Lesser General Public License as published by
  6.     the Free Software Foundation, either version 3 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU Lesser General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU Lesser General Public License
  15.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16. *)
  17.  
  18. MODULE In;
  19.  
  20. IMPORT sys := SYSTEM, ConsoleLib;
  21.  
  22. TYPE
  23.  
  24.   STRING = ARRAY 260 OF CHAR;
  25.  
  26. VAR
  27.  
  28.   Done* : BOOLEAN;
  29.  
  30. PROCEDURE digit(ch: CHAR): BOOLEAN;
  31.   RETURN (ch >= "0") & (ch <= "9")
  32. END digit;
  33.  
  34. PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN;
  35. VAR i: INTEGER;
  36. BEGIN
  37.   i := 0;
  38.   neg := FALSE;
  39.   WHILE (s[i] <= 20X) & (s[i] # 0X) DO
  40.     INC(i)
  41.   END;
  42.   IF s[i] = "-" THEN
  43.     neg := TRUE;
  44.     INC(i)
  45.   ELSIF s[i] = "+" THEN
  46.     INC(i)
  47.   END;
  48.   first := i;
  49.   WHILE digit(s[i]) DO
  50.     INC(i)
  51.   END;
  52.   last := i
  53.   RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first])
  54. END CheckInt;
  55.  
  56. PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN;
  57. VAR i: INTEGER; min: STRING;
  58. BEGIN
  59.   i := 0;
  60.   min := "2147483648";
  61.   WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO
  62.     INC(i)
  63.   END
  64.   RETURN i = 10
  65. END IsMinInt;
  66.  
  67. PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER;
  68. CONST maxINT = 7FFFFFFFH;
  69. VAR i, n, res: INTEGER; flag, neg: BOOLEAN;
  70. BEGIN
  71.   res := 0;
  72.   flag := CheckInt(str, i, n, neg, FALSE);
  73.   err := ~flag;
  74.   IF flag & neg & IsMinInt(str, i) THEN
  75.     flag := FALSE;
  76.     neg := FALSE;
  77.     res := 80000000H
  78.   END;
  79.   WHILE flag & digit(str[i]) DO
  80.     IF res > maxINT DIV 10 THEN
  81.       err := TRUE;
  82.       flag := FALSE;
  83.       res := 0
  84.     ELSE
  85.       res := res * 10;
  86.       IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN
  87.         err := TRUE;
  88.         flag := FALSE;
  89.         res := 0
  90.       ELSE
  91.         res := res + (ORD(str[i]) - ORD("0"));
  92.         INC(i)
  93.       END
  94.     END
  95.   END;
  96.   IF neg THEN
  97.     res := -res
  98.   END
  99.   RETURN res
  100. END StrToInt;
  101.  
  102. PROCEDURE Space(s: STRING): BOOLEAN;
  103. VAR i: INTEGER;
  104. BEGIN
  105.   i := 0;
  106.   WHILE (s[i] # 0X) & (s[i] <= 20X) DO
  107.     INC(i)
  108.   END
  109.   RETURN s[i] = 0X
  110. END Space;
  111.  
  112. PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN;
  113. VAR i: INTEGER; Res: BOOLEAN;
  114. BEGIN
  115.   Res := CheckInt(s, n, i, neg, TRUE);
  116.   IF Res THEN
  117.     IF s[i] = "." THEN
  118.       INC(i);
  119.       WHILE digit(s[i]) DO
  120.         INC(i)
  121.       END;
  122.       IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN
  123.         INC(i);
  124.         IF (s[i] = "+") OR (s[i] = "-") THEN
  125.           INC(i)
  126.         END;
  127.         Res := digit(s[i]);
  128.         WHILE digit(s[i]) DO
  129.           INC(i)
  130.         END
  131.       END
  132.     END
  133.   END
  134.   RETURN Res & (s[i] <= 20X)
  135. END CheckReal;
  136.  
  137. PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL;
  138. CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH;
  139. VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN;
  140.  
  141.   PROCEDURE part1 (str: STRING; VAR res, d: REAL; VAR i: INTEGER): BOOLEAN;
  142.   BEGIN
  143.     res := 0.0;
  144.     d := 1.0;
  145.     WHILE digit(str[i]) DO
  146.       res := res * 10.0 + FLT(ORD(str[i]) - ORD("0"));
  147.       INC(i)
  148.     END;
  149.     IF str[i] = "." THEN
  150.       INC(i);
  151.       WHILE digit(str[i]) DO
  152.         d := d / 10.0;
  153.         res := res + FLT(ORD(str[i]) - ORD("0")) * d;
  154.         INC(i)
  155.       END
  156.     END
  157.     RETURN str[i] # 0X
  158.   END part1;
  159.  
  160.   PROCEDURE part2 (str: STRING; VAR i, scale: INTEGER; VAR minus, err: BOOLEAN; VAR m, res: REAL): BOOLEAN;
  161.   BEGIN
  162.     INC(i);
  163.     m := 10.0;
  164.     minus := FALSE;
  165.     IF str[i] = "+" THEN
  166.       INC(i)
  167.     ELSIF str[i] = "-" THEN
  168.       minus := TRUE;
  169.       INC(i);
  170.       m := 0.1
  171.     END;
  172.     scale := 0;
  173.     err := FALSE;
  174.     WHILE ~err & digit(str[i]) DO
  175.       IF scale > maxINT DIV 10 THEN
  176.         err := TRUE;
  177.         res := 0.0
  178.       ELSE
  179.         scale := scale * 10;
  180.         IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN
  181.           err := TRUE;
  182.           res := 0.0
  183.         ELSE
  184.           scale := scale + (ORD(str[i]) - ORD("0"));
  185.           INC(i)
  186.         END
  187.       END
  188.     END
  189.     RETURN ~err
  190.   END part2;
  191.  
  192.   PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR res, m: REAL; VAR scale: INTEGER);
  193.   VAR i: INTEGER;
  194.   BEGIN
  195.     err := FALSE;
  196.     IF scale = maxINT THEN
  197.       err := TRUE;
  198.       res := 0.0
  199.     END;
  200.     i := 1;
  201.     WHILE ~err & (i <= scale) DO
  202.       IF ~minus & (res > maxDBL / m) THEN
  203.         err := TRUE;
  204.         res := 0.0
  205.       ELSE
  206.         res := res * m;
  207.         INC(i)
  208.       END
  209.     END
  210.   END part3;
  211.  
  212. BEGIN
  213.   IF CheckReal(str, i, neg) THEN
  214.     IF part1(str, res, d, i) & part2(str, i, scale, minus, err, m, res) THEN
  215.       part3(err, minus, res, m, scale)
  216.     END;
  217.     IF neg THEN
  218.       res := -res
  219.     END
  220.   ELSE
  221.     res := 0.0;
  222.     err := TRUE
  223.   END
  224.   RETURN res
  225. END StrToFloat;
  226.  
  227. PROCEDURE String*(VAR s: ARRAY OF CHAR);
  228. VAR res, length: INTEGER; str: STRING;
  229. BEGIN
  230.   res := ConsoleLib.gets(sys.ADR(str[0]), LEN(str));
  231.   length := LENGTH(str);
  232.   IF length > 0 THEN
  233.     str[length - 1] := 0X
  234.   END;
  235.   COPY(str, s);
  236.   Done := TRUE
  237. END String;
  238.  
  239. PROCEDURE Char*(VAR x: CHAR);
  240. VAR str: STRING;
  241. BEGIN
  242.   String(str);
  243.   x := str[0];
  244.   Done := TRUE
  245. END Char;
  246.  
  247. PROCEDURE Ln*;
  248. VAR str: STRING;
  249. BEGIN
  250.   String(str);
  251.   Done := TRUE
  252. END Ln;
  253.  
  254. PROCEDURE Real* (VAR x: REAL);
  255. VAR str: STRING; err: BOOLEAN;
  256. BEGIN
  257.   err := FALSE;
  258.   REPEAT
  259.     String(str)
  260.   UNTIL ~Space(str);
  261.   x := StrToFloat(str, err);
  262.   Done := ~err
  263. END Real;
  264.  
  265.  
  266. PROCEDURE Int*(VAR x: INTEGER);
  267. VAR str: STRING; err: BOOLEAN;
  268. BEGIN
  269.   err := FALSE;
  270.   REPEAT
  271.     String(str)
  272.   UNTIL ~Space(str);
  273.   x := StrToInt(str, err);
  274.   Done := ~err
  275. END Int;
  276.  
  277. PROCEDURE Open*;
  278. BEGIN
  279.   Done := TRUE
  280. END Open;
  281.  
  282. END In.
  283.