conversions.mod 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. IMPLEMENTATION MODULE Conversions;
  2. (* Tolerant parsers report an ISO-style ConvResults code. INTEGER
  3. range is checked with a LONGINT accumulator (V3 INTEGER is 32-bit):
  4. a value outside [-2147483648, 2147483647] is strOutOfRange. *)
  5. CONST
  6. (* 32-bit INTEGER bounds (V3 INTEGER is 32-bit) *)
  7. IntMax = 2147483647;
  8. IntMin = -2147483647 - 1;
  9. PROCEDURE m2realstr(x : REAL; VAR s : ARRAY OF CHAR);
  10. EXTERNAL;
  11. PROCEDURE m2strreal(VAR s : ARRAY OF CHAR; VAR ok : INTEGER) : REAL;
  12. EXTERNAL;
  13. (* ---------------- output ---------------- *)
  14. PROCEDURE IntToStr(n : INTEGER; VAR s : ARRAY OF CHAR);
  15. VAR v : INTEGER;
  16. i, k : CARDINAL;
  17. tmp : ARRAY [0 .. 31] OF CHAR;
  18. BEGIN
  19. IF n = 0 THEN
  20. s[0] := "0"; s[1] := CHR(0)
  21. ELSE
  22. IF n < 0 THEN v := -n ELSE v := n END;
  23. i := 0;
  24. WHILE (v > 0) AND (i <= HIGH(tmp)) DO
  25. tmp[i] := CHR(ORD("0") + (v MOD 10));
  26. v := v DIV 10;
  27. INC(i)
  28. END;
  29. k := 0;
  30. IF n < 0 THEN s[k] := "-"; INC(k) END;
  31. WHILE (i > 0) AND (k <= HIGH(s)) DO
  32. DEC(i);
  33. s[k] := tmp[i]; INC(k)
  34. END;
  35. IF k <= HIGH(s) THEN s[k] := CHR(0) END
  36. END
  37. END IntToStr;
  38. PROCEDURE CardToStr(n : CARDINAL; VAR s : ARRAY OF CHAR);
  39. VAR v : CARDINAL;
  40. i, k : CARDINAL;
  41. tmp : ARRAY [0 .. 31] OF CHAR;
  42. BEGIN
  43. IF n = 0 THEN
  44. s[0] := "0"; s[1] := CHR(0)
  45. ELSE
  46. v := n; i := 0;
  47. WHILE (v > 0) AND (i <= HIGH(tmp)) DO
  48. tmp[i] := CHR(ORD("0") + (v MOD 10));
  49. v := v DIV 10;
  50. INC(i)
  51. END;
  52. k := 0;
  53. WHILE (i > 0) AND (k <= HIGH(s)) DO
  54. DEC(i);
  55. s[k] := tmp[i]; INC(k)
  56. END;
  57. IF k <= HIGH(s) THEN s[k] := CHR(0) END
  58. END
  59. END CardToStr;
  60. PROCEDURE RealToStr(x : REAL; VAR s : ARRAY OF CHAR);
  61. BEGIN
  62. m2realstr(x, s)
  63. END RealToStr;
  64. (* ---------------- input ---------------- *)
  65. PROCEDURE StrToInt(s : ARRAY OF CHAR; VAR n : INTEGER) : ConvResults;
  66. (* signed decimal. V3 has no VAL(LONGINT, int) or long->int
  67. narrowing, so overflow is detected *before* the 32-bit accumulate
  68. wraps: reject when v would exceed (IntMax-d) DIV 10. The whole
  69. magnitude accumulates as a non-negative INTEGER, then range is
  70. checked per sign. *)
  71. VAR i : CARDINAL;
  72. neg, seen, over : BOOLEAN;
  73. v : INTEGER;
  74. d : INTEGER;
  75. bound : INTEGER;
  76. BEGIN
  77. n := 0; i := 0; neg := FALSE; seen := FALSE; v := 0;
  78. over := FALSE;
  79. IF (i > HIGH(s)) OR (s[i] = CHR(0)) THEN RETURN strEmpty END;
  80. IF s[i] = "-" THEN neg := TRUE; INC(i)
  81. ELSIF s[i] = "+" THEN INC(i)
  82. END;
  83. IF (i > HIGH(s)) OR (s[i] < "0") OR (s[i] > "9") THEN
  84. RETURN strWrongFormat
  85. END;
  86. WHILE (i <= HIGH(s)) AND (s[i] >= "0") AND (s[i] <= "9") DO
  87. d := ORD(s[i]) - ORD("0");
  88. IF neg THEN
  89. (* magnitude may reach 2^31 *)
  90. bound := (IntMax - 1 - d) DIV 10
  91. ELSE
  92. bound := (IntMax - d) DIV 10
  93. END;
  94. IF v > bound THEN over := TRUE
  95. ELSE v := v * 10 + d
  96. END;
  97. seen := TRUE;
  98. INC(i)
  99. END;
  100. IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN strWrongFormat END;
  101. IF NOT seen THEN RETURN strWrongFormat END;
  102. IF over THEN RETURN strOutOfRange END;
  103. IF neg THEN n := 0 - v ELSE n := v END;
  104. RETURN strAllRight
  105. END StrToInt;
  106. PROCEDURE StrToCard(s : ARRAY OF CHAR; VAR n : CARDINAL) : ConvResults;
  107. (* unsigned decimal; same pre-wrap overflow guard, bounded by the
  108. CARDINAL max (2^32-1) held as a non-negative INTEGER magnitude. *)
  109. VAR i : CARDINAL;
  110. seen, over : BOOLEAN;
  111. v : INTEGER;
  112. d, bound : INTEGER;
  113. BEGIN
  114. n := 0; i := 0; seen := FALSE; v := 0; over := FALSE;
  115. IF (i > HIGH(s)) OR (s[i] = CHR(0)) THEN RETURN strEmpty END;
  116. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN strWrongFormat END;
  117. WHILE (i <= HIGH(s)) AND (s[i] >= "0") AND (s[i] <= "9") DO
  118. d := ORD(s[i]) - ORD("0");
  119. bound := (IntMax - d) DIV 10;
  120. IF v > bound THEN over := TRUE
  121. ELSE v := v * 10 + d
  122. END;
  123. seen := TRUE;
  124. INC(i)
  125. END;
  126. IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN strWrongFormat END;
  127. IF NOT seen THEN RETURN strWrongFormat END;
  128. IF over THEN RETURN strOutOfRange END;
  129. n := v;
  130. RETURN strAllRight
  131. END StrToCard;
  132. PROCEDURE StrToReal(VAR s : ARRAY OF CHAR; VAR x : REAL) : ConvResults;
  133. VAR i : CARDINAL;
  134. ok : INTEGER;
  135. BEGIN
  136. x := 0.0;
  137. i := 0;
  138. IF (i > HIGH(s)) OR (s[i] = CHR(0)) THEN RETURN strEmpty END;
  139. x := m2strreal(s, ok);
  140. IF ok = 0 THEN RETURN strWrongFormat END;
  141. RETURN strAllRight
  142. END StrToReal;
  143. (* ---------------- BOOLEAN shortcuts ---------------- *)
  144. PROCEDURE IntVal(s : ARRAY OF CHAR; VAR n : INTEGER) : BOOLEAN;
  145. BEGIN
  146. RETURN StrToInt(s, n) = strAllRight
  147. END IntVal;
  148. PROCEDURE CardVal(s : ARRAY OF CHAR; VAR n : CARDINAL) : BOOLEAN;
  149. BEGIN
  150. RETURN StrToCard(s, n) = strAllRight
  151. END CardVal;
  152. PROCEDURE RealVal(VAR s : ARRAY OF CHAR; VAR x : REAL) : BOOLEAN;
  153. BEGIN
  154. RETURN StrToReal(s, x) = strAllRight
  155. END RealVal;
  156. END Conversions.