Subversion Repositories Kolibri OS

Rev

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

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