In.ob07 6.1 KB

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