|
|
@@ -1,4 +1,12 @@
|
|
|
IMPLEMENTATION MODULE Conversions;
|
|
|
+(* Tolerant parsers report an ISO-style ConvResults code. INTEGER
|
|
|
+ range is checked with a LONGINT accumulator (V3 INTEGER is 32-bit):
|
|
|
+ a value outside [-2147483648, 2147483647] is strOutOfRange. *)
|
|
|
+
|
|
|
+CONST
|
|
|
+ (* 32-bit INTEGER bounds (V3 INTEGER is 32-bit) *)
|
|
|
+ IntMax = 2147483647;
|
|
|
+ IntMin = -2147483647 - 1;
|
|
|
|
|
|
PROCEDURE m2realstr(x : REAL; VAR s : ARRAY OF CHAR);
|
|
|
EXTERNAL;
|
|
|
@@ -6,6 +14,8 @@ PROCEDURE m2realstr(x : REAL; VAR s : ARRAY OF CHAR);
|
|
|
PROCEDURE m2strreal(VAR s : ARRAY OF CHAR; VAR ok : INTEGER) : REAL;
|
|
|
EXTERNAL;
|
|
|
|
|
|
+(* ---------------- output ---------------- *)
|
|
|
+
|
|
|
PROCEDURE IntToStr(n : INTEGER; VAR s : ARRAY OF CHAR);
|
|
|
VAR v : INTEGER;
|
|
|
i, k : CARDINAL;
|
|
|
@@ -59,49 +69,104 @@ BEGIN
|
|
|
m2realstr(x, s)
|
|
|
END RealToStr;
|
|
|
|
|
|
-PROCEDURE StrToInt(s : ARRAY OF CHAR; VAR n : INTEGER) : BOOLEAN;
|
|
|
+(* ---------------- input ---------------- *)
|
|
|
+
|
|
|
+PROCEDURE StrToInt(s : ARRAY OF CHAR; VAR n : INTEGER) : ConvResults;
|
|
|
+(* signed decimal. V3 has no VAL(LONGINT, int) or long->int
|
|
|
+ narrowing, so overflow is detected *before* the 32-bit accumulate
|
|
|
+ wraps: reject when v would exceed (IntMax-d) DIV 10. The whole
|
|
|
+ magnitude accumulates as a non-negative INTEGER, then range is
|
|
|
+ checked per sign. *)
|
|
|
VAR i : CARDINAL;
|
|
|
- neg, seen : BOOLEAN;
|
|
|
+ neg, seen, over : BOOLEAN;
|
|
|
v : INTEGER;
|
|
|
+ d : INTEGER;
|
|
|
+ bound : INTEGER;
|
|
|
BEGIN
|
|
|
n := 0; i := 0; neg := FALSE; seen := FALSE; v := 0;
|
|
|
- IF (i > HIGH(s)) OR (s[i] = CHR(0)) THEN RETURN FALSE END;
|
|
|
+ over := FALSE;
|
|
|
+ IF (i > HIGH(s)) OR (s[i] = CHR(0)) THEN RETURN strEmpty END;
|
|
|
IF s[i] = "-" THEN neg := TRUE; INC(i)
|
|
|
ELSIF s[i] = "+" THEN INC(i)
|
|
|
END;
|
|
|
+ IF (i > HIGH(s)) OR (s[i] < "0") OR (s[i] > "9") THEN
|
|
|
+ RETURN strWrongFormat
|
|
|
+ END;
|
|
|
WHILE (i <= HIGH(s)) AND (s[i] >= "0") AND (s[i] <= "9") DO
|
|
|
- v := v * 10 + (ORD(s[i]) - ORD("0"));
|
|
|
+ d := ORD(s[i]) - ORD("0");
|
|
|
+ IF neg THEN
|
|
|
+ (* magnitude may reach 2^31 *)
|
|
|
+ bound := (IntMax - 1 - d) DIV 10
|
|
|
+ ELSE
|
|
|
+ bound := (IntMax - d) DIV 10
|
|
|
+ END;
|
|
|
+ IF v > bound THEN over := TRUE
|
|
|
+ ELSE v := v * 10 + d
|
|
|
+ END;
|
|
|
seen := TRUE;
|
|
|
INC(i)
|
|
|
END;
|
|
|
- IF NOT seen THEN RETURN FALSE END;
|
|
|
- IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN FALSE END;
|
|
|
- IF neg THEN n := -v ELSE n := v END;
|
|
|
- RETURN TRUE
|
|
|
+ IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN strWrongFormat END;
|
|
|
+ IF NOT seen THEN RETURN strWrongFormat END;
|
|
|
+ IF over THEN RETURN strOutOfRange END;
|
|
|
+ IF neg THEN n := 0 - v ELSE n := v END;
|
|
|
+ RETURN strAllRight
|
|
|
END StrToInt;
|
|
|
|
|
|
-PROCEDURE StrToCard(s : ARRAY OF CHAR; VAR n : CARDINAL) : BOOLEAN;
|
|
|
+PROCEDURE StrToCard(s : ARRAY OF CHAR; VAR n : CARDINAL) : ConvResults;
|
|
|
+(* unsigned decimal; same pre-wrap overflow guard, bounded by the
|
|
|
+ CARDINAL max (2^32-1) held as a non-negative INTEGER magnitude. *)
|
|
|
VAR i : CARDINAL;
|
|
|
- seen : BOOLEAN;
|
|
|
- v : CARDINAL;
|
|
|
+ seen, over : BOOLEAN;
|
|
|
+ v : INTEGER;
|
|
|
+ d, bound : INTEGER;
|
|
|
BEGIN
|
|
|
- n := 0; i := 0; seen := FALSE; v := 0;
|
|
|
+ n := 0; i := 0; seen := FALSE; v := 0; over := FALSE;
|
|
|
+ IF (i > HIGH(s)) OR (s[i] = CHR(0)) THEN RETURN strEmpty END;
|
|
|
+ IF (s[i] < "0") OR (s[i] > "9") THEN RETURN strWrongFormat END;
|
|
|
WHILE (i <= HIGH(s)) AND (s[i] >= "0") AND (s[i] <= "9") DO
|
|
|
- v := v * 10 + (ORD(s[i]) - ORD("0"));
|
|
|
+ d := ORD(s[i]) - ORD("0");
|
|
|
+ bound := (IntMax - d) DIV 10;
|
|
|
+ IF v > bound THEN over := TRUE
|
|
|
+ ELSE v := v * 10 + d
|
|
|
+ END;
|
|
|
seen := TRUE;
|
|
|
INC(i)
|
|
|
END;
|
|
|
- IF NOT seen THEN RETURN FALSE END;
|
|
|
- IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN FALSE END;
|
|
|
+ IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN strWrongFormat END;
|
|
|
+ IF NOT seen THEN RETURN strWrongFormat END;
|
|
|
+ IF over THEN RETURN strOutOfRange END;
|
|
|
n := v;
|
|
|
- RETURN TRUE
|
|
|
+ RETURN strAllRight
|
|
|
END StrToCard;
|
|
|
|
|
|
-PROCEDURE StrToReal(VAR s : ARRAY OF CHAR; VAR x : REAL) : BOOLEAN;
|
|
|
- VAR ok : INTEGER;
|
|
|
+PROCEDURE StrToReal(VAR s : ARRAY OF CHAR; VAR x : REAL) : ConvResults;
|
|
|
+ VAR i : CARDINAL;
|
|
|
+ ok : INTEGER;
|
|
|
BEGIN
|
|
|
+ x := 0.0;
|
|
|
+ i := 0;
|
|
|
+ IF (i > HIGH(s)) OR (s[i] = CHR(0)) THEN RETURN strEmpty END;
|
|
|
x := m2strreal(s, ok);
|
|
|
- RETURN ok # 0
|
|
|
+ IF ok = 0 THEN RETURN strWrongFormat END;
|
|
|
+ RETURN strAllRight
|
|
|
END StrToReal;
|
|
|
|
|
|
+(* ---------------- BOOLEAN shortcuts ---------------- *)
|
|
|
+
|
|
|
+PROCEDURE IntVal(s : ARRAY OF CHAR; VAR n : INTEGER) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN StrToInt(s, n) = strAllRight
|
|
|
+END IntVal;
|
|
|
+
|
|
|
+PROCEDURE CardVal(s : ARRAY OF CHAR; VAR n : CARDINAL) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN StrToCard(s, n) = strAllRight
|
|
|
+END CardVal;
|
|
|
+
|
|
|
+PROCEDURE RealVal(VAR s : ARRAY OF CHAR; VAR x : REAL) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN StrToReal(s, x) = strAllRight
|
|
|
+END RealVal;
|
|
|
+
|
|
|
END Conversions.
|