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; 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; tmp : ARRAY [0 .. 31] OF CHAR; BEGIN IF n = 0 THEN s[0] := "0"; s[1] := CHR(0) ELSE IF n < 0 THEN v := -n ELSE v := n END; i := 0; WHILE (v > 0) AND (i <= HIGH(tmp)) DO tmp[i] := CHR(ORD("0") + (v MOD 10)); v := v DIV 10; INC(i) END; k := 0; IF n < 0 THEN s[k] := "-"; INC(k) END; WHILE (i > 0) AND (k <= HIGH(s)) DO DEC(i); s[k] := tmp[i]; INC(k) END; IF k <= HIGH(s) THEN s[k] := CHR(0) END END END IntToStr; PROCEDURE CardToStr(n : CARDINAL; VAR s : ARRAY OF CHAR); VAR v : CARDINAL; i, k : CARDINAL; tmp : ARRAY [0 .. 31] OF CHAR; BEGIN IF n = 0 THEN s[0] := "0"; s[1] := CHR(0) ELSE v := n; i := 0; WHILE (v > 0) AND (i <= HIGH(tmp)) DO tmp[i] := CHR(ORD("0") + (v MOD 10)); v := v DIV 10; INC(i) END; k := 0; WHILE (i > 0) AND (k <= HIGH(s)) DO DEC(i); s[k] := tmp[i]; INC(k) END; IF k <= HIGH(s) THEN s[k] := CHR(0) END END END CardToStr; PROCEDURE RealToStr(x : REAL; VAR s : ARRAY OF CHAR); BEGIN m2realstr(x, s) END RealToStr; (* ---------------- input ---------------- *) PROCEDURE StrToInt(s : ARRAY OF CHAR; VAR n : INTEGER) : ConvResults; (* signed decimal. Accumulates in LONGINT (so overflow is simply a range check) then narrows with VAL(INTEGER, v). *) VAR i : CARDINAL; neg, seen : BOOLEAN; v : LONGINT; d : INTEGER; BEGIN n := 0; i := 0; neg := FALSE; seen := FALSE; v := 0; 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 d := ORD(s[i]) - ORD("0"); v := v * 10 + d; seen := TRUE; INC(i) END; IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN strWrongFormat END; IF NOT seen THEN RETURN strWrongFormat END; IF neg THEN v := 0 - v END; IF (v > IntMax) OR (v < IntMin) THEN RETURN strOutOfRange END; n := VAL(INTEGER, v); RETURN strAllRight END StrToInt; PROCEDURE StrToCard(s : ARRAY OF CHAR; VAR n : CARDINAL) : ConvResults; (* unsigned decimal; LONGINT accumulation, bounded by CARDINAL max. *) VAR i : CARDINAL; seen : BOOLEAN; v : LONGINT; d : INTEGER; BEGIN n := 0; i := 0; seen := FALSE; v := 0; 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 d := ORD(s[i]) - ORD("0"); v := v * 10 + d; seen := TRUE; INC(i) END; IF (i <= HIGH(s)) AND (s[i] # CHR(0)) THEN RETURN strWrongFormat END; IF NOT seen THEN RETURN strWrongFormat END; IF v > IntMax THEN RETURN strOutOfRange END; n := VAL(CARDINAL, v); RETURN strAllRight END StrToCard; 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); 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.