Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2013, 2017, 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, WINAPI;
  21.  
  22. TYPE
  23.  
  24.   STRING = ARRAY 260 OF CHAR;
  25.  
  26. VAR
  27.  
  28.   Done*: BOOLEAN;
  29.   hConsoleInput: INTEGER;
  30.  
  31. PROCEDURE digit(ch: CHAR): BOOLEAN;
  32.   RETURN (ch >= "0") & (ch <= "9")
  33. END digit;
  34.  
  35. PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN;
  36. VAR i: INTEGER;
  37. BEGIN
  38.   i := 0;
  39.   neg := FALSE;
  40.   WHILE (s[i] <= 20X) & (s[i] # 0X) DO
  41.     INC(i)
  42.   END;
  43.   IF s[i] = "-" THEN
  44.     neg := TRUE;
  45.     INC(i)
  46.   ELSIF s[i] = "+" THEN
  47.     INC(i)
  48.   END;
  49.   first := i;
  50.   WHILE digit(s[i]) DO
  51.     INC(i)
  52.   END;
  53.   last := i
  54.   RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first])
  55. END CheckInt;
  56.  
  57. PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN;
  58. VAR i: INTEGER; min: STRING;
  59. BEGIN
  60.   i := 0;
  61.   min := "2147483648";
  62.   WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO
  63.     INC(i)
  64.   END
  65.   RETURN i = 10
  66. END IsMinInt;
  67.  
  68. PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER;
  69. CONST maxINT = 7FFFFFFFH;
  70. VAR i, n, res: INTEGER; flag, neg: BOOLEAN;
  71. BEGIN
  72.   res := 0;
  73.   flag := CheckInt(str, i, n, neg, FALSE);
  74.   err := ~flag;
  75.   IF flag & neg & IsMinInt(str, i) THEN
  76.     flag := FALSE;
  77.     neg := FALSE;
  78.     res := 80000000H
  79.   END;
  80.   WHILE flag & digit(str[i]) DO
  81.     IF res > maxINT DIV 10 THEN
  82.       err := TRUE;
  83.       flag := FALSE;
  84.       res := 0
  85.     ELSE
  86.       res := res * 10;
  87.       IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN
  88.         err := TRUE;
  89.         flag := FALSE;
  90.         res := 0
  91.       ELSE
  92.         res := res + (ORD(str[i]) - ORD("0"));
  93.         INC(i)
  94.       END
  95.     END
  96.   END;
  97.   IF neg THEN
  98.     res := -res
  99.   END
  100.   RETURN res
  101. END StrToInt;
  102.  
  103. PROCEDURE Space(s: STRING): BOOLEAN;
  104. VAR i: INTEGER;
  105. BEGIN
  106.   i := 0;
  107.   WHILE (s[i] # 0X) & (s[i] <= 20X) DO
  108.     INC(i)
  109.   END
  110.   RETURN s[i] = 0X
  111. END Space;
  112.  
  113. PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN;
  114. VAR i: INTEGER; Res: BOOLEAN;
  115. BEGIN
  116.   Res := CheckInt(s, n, i, neg, TRUE);
  117.   IF Res THEN
  118.     IF s[i] = "." THEN
  119.       INC(i);
  120.       WHILE digit(s[i]) DO
  121.         INC(i)
  122.       END;
  123.       IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN
  124.         INC(i);
  125.         IF (s[i] = "+") OR (s[i] = "-") THEN
  126.           INC(i)
  127.         END;
  128.         Res := digit(s[i]);
  129.         WHILE digit(s[i]) DO
  130.           INC(i)
  131.         END
  132.       END
  133.     END
  134.   END
  135.   RETURN Res & (s[i] <= 20X)
  136. END CheckReal;
  137.  
  138. PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL;
  139. CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH;
  140. VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN;
  141.  
  142.   PROCEDURE part1(VAR res, d: REAL; VAR i: INTEGER; str: STRING): BOOLEAN;
  143.   BEGIN
  144.     res := 0.0;
  145.     d := 1.0;
  146.     WHILE digit(str[i]) DO
  147.       res := res * 10.0 + FLT(ORD(str[i]) - ORD("0"));
  148.       INC(i)
  149.     END;
  150.     IF str[i] = "." THEN
  151.       INC(i);
  152.       WHILE digit(str[i]) DO
  153.         d := d / 10.0;
  154.         res := res + FLT(ORD(str[i]) - ORD("0")) * d;
  155.         INC(i)
  156.       END
  157.     END
  158.     RETURN str[i] # 0X
  159.   END part1;
  160.  
  161.   PROCEDURE part2(VAR i, scale: INTEGER; VAR m, res: REAL; VAR minus, err: BOOLEAN; str: STRING): BOOLEAN;
  162.   BEGIN
  163.     INC(i);
  164.     m := 10.0;
  165.     minus := FALSE;
  166.     IF str[i] = "+" THEN
  167.       INC(i)
  168.     ELSIF str[i] = "-" THEN
  169.       minus := TRUE;
  170.       INC(i);
  171.       m := 0.1
  172.     END;
  173.     scale := 0;
  174.     err := FALSE;
  175.     WHILE ~err & digit(str[i]) DO
  176.       IF scale > maxINT DIV 10 THEN
  177.         err := TRUE;
  178.         res := 0.0
  179.       ELSE
  180.         scale := scale * 10;
  181.         IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN
  182.           err := TRUE;
  183.           res := 0.0
  184.         ELSE
  185.           scale := scale + (ORD(str[i]) - ORD("0"));
  186.           INC(i)
  187.         END
  188.       END
  189.     END
  190.     RETURN ~err
  191.   END part2;
  192.  
  193.   PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR scale: INTEGER; VAR res, m: REAL);
  194.   VAR i: INTEGER;
  195.   BEGIN
  196.     err := FALSE;
  197.     IF scale = maxINT THEN
  198.       err := TRUE;
  199.       res := 0.0
  200.     END;
  201.     i := 1;
  202.     WHILE ~err & (i <= scale) DO
  203.       IF ~minus & (res > maxDBL / m) THEN
  204.         err := TRUE;
  205.         res := 0.0
  206.       ELSE
  207.         res := res * m;
  208.         INC(i)
  209.       END
  210.     END
  211.   END part3;
  212.  
  213. BEGIN
  214.   IF CheckReal(str, i, neg) THEN
  215.     IF part1(res, d, i, str) & part2(i, scale, m, res, minus, err, str) THEN
  216.       part3(err, minus, scale, res, m)
  217.     END;
  218.     IF neg THEN
  219.       res := -res
  220.     END
  221.   ELSE
  222.     res := 0.0;
  223.     err := TRUE
  224.   END
  225.   RETURN res
  226. END StrToFloat;
  227.  
  228. PROCEDURE String*(VAR s: ARRAY OF CHAR);
  229. VAR count, i: INTEGER; str: STRING;
  230. BEGIN
  231.   WINAPI.ReadConsole(hConsoleInput, sys.ADR(str[0]), 256, sys.ADR(count), 0);
  232.   IF (str[count - 1] = 0AX) & (str[count - 2] = 0DX) THEN
  233.     DEC(count, 2)
  234.   END;
  235.   str[256] := 0X;
  236.   str[count] := 0X;
  237.   i := 0;
  238.   WHILE (i < LEN(s) - 1) & (i < LEN(str)) & (str[i] # 0X) DO
  239.       s[i] := str[i];
  240.       INC(i)
  241.   END;
  242.   s[i] := 0X;
  243.   Done := TRUE
  244. END String;
  245.  
  246. PROCEDURE Char*(VAR x: CHAR);
  247. VAR str: STRING;
  248. BEGIN
  249.   String(str);
  250.   x := str[0];
  251.   Done := TRUE
  252. END Char;
  253.  
  254. PROCEDURE Ln*;
  255. VAR str: STRING;
  256. BEGIN
  257.   String(str);
  258.   Done := TRUE
  259. END Ln;
  260.  
  261. PROCEDURE Real*(VAR x: REAL);
  262. VAR str: STRING; err: BOOLEAN;
  263. BEGIN
  264.   err := FALSE;
  265.   REPEAT
  266.     String(str)
  267.   UNTIL ~Space(str);
  268.   x := StrToFloat(str, err);
  269.   Done := ~err
  270. END Real;
  271.  
  272. PROCEDURE Int*(VAR x: INTEGER);
  273. VAR str: STRING; err: BOOLEAN;
  274. BEGIN
  275.   err := FALSE;
  276.   REPEAT
  277.     String(str)
  278.   UNTIL ~Space(str);
  279.   x := StrToInt(str, err);
  280.   Done := ~err
  281. END Int;
  282.  
  283. PROCEDURE Open*;
  284. BEGIN
  285.   hConsoleInput := WINAPI.GetStdHandle(-10);
  286.   Done := TRUE
  287. END Open;
  288.  
  289. END In.