blob: bfb239c39a230f473e8f6e953f91e71a4942e321 [file] [log] [blame]
(* NumberIO.mod provides conversion of ordinal numbers.
Copyright (C) 2001-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. *)
IMPLEMENTATION MODULE NumberIO ;
FROM ASCII IMPORT nul ;
FROM StrIO IMPORT ReadString, WriteString, WriteLn ;
FROM StrLib IMPORT StrLen, StrRemoveWhitePrefix ;
CONST
MaxLineLength = 79 ;
MaxDigits = 20 ;
MaxHexDigits = 20 ;
MaxOctDigits = 40 ;
MaxBits = 64 ;
PROCEDURE CardToStr (x, n: CARDINAL ; VAR a: ARRAY OF CHAR) ;
VAR
i, j,
Higha : CARDINAL ;
buf : ARRAY [1..MaxDigits] OF CARDINAL ;
BEGIN
i := 0 ;
REPEAT
INC(i) ;
IF i>MaxDigits
THEN
WriteString('NumberIO - increase MaxDigits') ; WriteLn ;
HALT
END ;
buf[i] := x MOD 10 ;
x := x DIV 10 ;
UNTIL x=0 ;
j := 0 ;
Higha := HIGH(a) ;
WHILE (n>i) AND (j<=Higha) DO
a[j] := ' ' ;
INC(j) ;
DEC(n)
END ;
WHILE (i>0) AND (j<=Higha) DO
a[j] := CHR( buf[i] + ORD('0') ) ;
INC(j) ;
DEC(i)
END ;
IF j<=Higha
THEN
a[j] := nul
END
END CardToStr ;
PROCEDURE StrToCard (a: ARRAY OF CHAR ; VAR x: CARDINAL) ;
VAR
i : CARDINAL ;
ok : BOOLEAN ;
higha : CARDINAL ;
BEGIN
StrRemoveWhitePrefix(a, a) ;
higha := StrLen(a) ;
i := 0 ;
ok := TRUE ;
WHILE ok DO
IF i<higha
THEN
IF (a[i]<'0') OR (a[i]>'9')
THEN
INC(i)
ELSE
ok := FALSE
END
ELSE
ok := FALSE
END
END ;
x := 0 ;
IF i<higha
THEN
ok := TRUE ;
REPEAT
x := 10*x + (ORD(a[i])-ORD('0')) ;
IF i<higha
THEN
INC(i) ;
IF (a[i]<'0') OR (a[i]>'9')
THEN
ok := FALSE
END
ELSE
ok := FALSE
END
UNTIL NOT ok ;
END
END StrToCard ;
PROCEDURE IntToStr (x: INTEGER; n: CARDINAL ; VAR a: ARRAY OF CHAR) ;
VAR
i, j, c,
Higha : CARDINAL ;
buf : ARRAY [1..MaxDigits] OF CARDINAL ;
Negative: BOOLEAN ;
BEGIN
IF x<0
THEN
Negative := TRUE ;
c := VAL(CARDINAL, ABS(x+1))+1 ;
IF n>0
THEN
DEC(n)
END
ELSE
c := x ;
Negative := FALSE
END ;
i := 0 ;
REPEAT
INC(i) ;
IF i>MaxDigits
THEN
WriteString('NumberIO - increase MaxDigits') ; WriteLn ;
HALT
END ;
buf[i] := c MOD 10 ;
c := c DIV 10 ;
UNTIL c=0 ;
j := 0 ;
Higha := HIGH(a) ;
WHILE (n>i) AND (j<=Higha) DO
a[j] := ' ' ;
INC(j) ;
DEC(n)
END ;
IF Negative
THEN
a[j] := '-' ;
INC(j)
END ;
WHILE (i#0) AND (j<=Higha) DO
a[j] := CHR( buf[i] + ORD('0') ) ;
INC(j) ;
DEC(i)
END ;
IF j<=Higha
THEN
a[j] := nul
END
END IntToStr ;
PROCEDURE StrToInt (a: ARRAY OF CHAR ; VAR x: INTEGER) ;
VAR
i : CARDINAL ;
ok,
Negative : BOOLEAN ;
higha : CARDINAL ;
BEGIN
StrRemoveWhitePrefix(a, a) ;
higha := StrLen(a) ;
i := 0 ;
Negative := FALSE ;
ok := TRUE ;
WHILE ok DO
IF i<higha
THEN
IF a[i]='-'
THEN
INC(i) ;
Negative := NOT Negative
ELSIF (a[i]<'0') OR (a[i]>'9')
THEN
INC(i)
ELSE
ok := FALSE
END
ELSE
ok := FALSE
END
END ;
x := 0 ;
IF i<higha
THEN
ok := TRUE ;
REPEAT
IF Negative
THEN
x := 10*x - INTEGER(ORD(a[i])-ORD('0'))
ELSE
x := 10*x + INTEGER(ORD(a[i])-ORD('0'))
END ;
IF i<higha
THEN
INC(i) ;
IF (a[i]<'0') OR (a[i]>'9')
THEN
ok := FALSE
END
ELSE
ok := FALSE
END
UNTIL NOT ok ;
END
END StrToInt ;
PROCEDURE HexToStr (x, n: CARDINAL ; VAR a: ARRAY OF CHAR) ;
VAR
i, j,
Higha : CARDINAL ;
buf : ARRAY [1..MaxHexDigits] OF CARDINAL ;
BEGIN
i := 0 ;
REPEAT
INC(i) ;
IF i>MaxHexDigits
THEN
WriteString('NumberIO - increase MaxDigits') ; WriteLn ;
HALT
END ;
buf[i] := x MOD 010H ;
x := x DIV 010H ;
UNTIL x=0 ;
j := 0 ;
Higha := HIGH(a) ;
WHILE (n>i) AND (j<=Higha) DO
a[j] := '0' ;
INC(j) ;
DEC(n)
END ;
WHILE (i#0) AND (j<=Higha) DO
IF buf[i]<10
THEN
a[j] := CHR( buf[i] + ORD('0') )
ELSE
a[j] := CHR( buf[i] + ORD('A')-10 )
END ;
INC(j) ;
DEC(i)
END ;
IF j<=Higha
THEN
a[j] := nul
END
END HexToStr ;
PROCEDURE StrToHex (a: ARRAY OF CHAR ; VAR x: CARDINAL) ;
VAR
i: INTEGER ;
BEGIN
StrToHexInt(a, i) ;
x := VAL(CARDINAL, i)
END StrToHex ;
PROCEDURE StrToHexInt (a: ARRAY OF CHAR ; VAR x: INTEGER) ;
VAR
i : CARDINAL ;
ok : BOOLEAN ;
higha : CARDINAL ;
BEGIN
StrRemoveWhitePrefix(a, a) ;
higha := StrLen(a) ;
i := 0 ;
ok := TRUE ;
WHILE ok DO
IF i<higha
THEN
IF ((a[i]>='0') AND (a[i]<='9')) OR ((a[i]>='A') AND (a[i]<='F'))
THEN
ok := FALSE
ELSE
INC(i)
END
ELSE
ok := FALSE
END
END ;
x := 0 ;
IF i<higha
THEN
ok := TRUE ;
REPEAT
IF (a[i]>='0') AND (a[i]<='9')
THEN
x := 010H*x + VAL(INTEGER, (ORD(a[i])-ORD('0')))
ELSIF (a[i]>='A') AND (a[i]<='F')
THEN
x := 010H*x + VAL(INTEGER, (ORD(a[i])-ORD('A')+10))
END ;
IF i<higha
THEN
INC(i) ;
IF ((a[i]<'0') OR (a[i]>'9')) AND ((a[i]<'A') OR (a[i]>'F'))
THEN
ok := FALSE
END
ELSE
ok := FALSE
END
UNTIL NOT ok ;
END
END StrToHexInt ;
PROCEDURE OctToStr (x, n: CARDINAL ; VAR a: ARRAY OF CHAR) ;
VAR
i, j,
Higha : CARDINAL ;
buf : ARRAY [1..MaxOctDigits] OF CARDINAL ;
BEGIN
i := 0 ;
REPEAT
INC(i) ;
IF i>MaxOctDigits
THEN
WriteString('NumberIO - increase MaxDigits') ; WriteLn ;
HALT
END ;
buf[i] := x MOD 8 ;
x := x DIV 8 ;
UNTIL x=0 ;
j := 0 ;
Higha := HIGH(a) ;
WHILE (n>i) AND (j<=Higha) DO
a[j] := ' ' ;
INC(j) ;
DEC(n)
END ;
WHILE (i>0) AND (j<=Higha) DO
a[j] := CHR( buf[i] + ORD('0') ) ;
INC(j) ;
DEC(i)
END ;
IF j<=Higha
THEN
a[j] := nul
END
END OctToStr ;
PROCEDURE StrToOct (a: ARRAY OF CHAR ; VAR x: CARDINAL) ;
VAR
i: INTEGER ;
BEGIN
StrToOctInt(a, i) ;
x := VAL(CARDINAL, i)
END StrToOct ;
PROCEDURE StrToOctInt (a: ARRAY OF CHAR ; VAR x: INTEGER) ;
VAR
i : CARDINAL ;
ok : BOOLEAN ;
higha : CARDINAL ;
BEGIN
StrRemoveWhitePrefix(a, a) ;
higha := StrLen(a) ;
i := 0 ;
ok := TRUE ;
WHILE ok DO
IF i<higha
THEN
IF (a[i]<'0') OR (a[i]>'7')
THEN
INC(i)
ELSE
ok := FALSE
END
ELSE
ok := FALSE
END
END ;
x := 0 ;
IF i<higha
THEN
ok := TRUE ;
REPEAT
x := 8*x + VAL(INTEGER, (ORD(a[i])-ORD('0'))) ;
IF i<higha
THEN
INC(i) ;
IF (a[i]<'0') OR (a[i]>'7')
THEN
ok := FALSE
END
ELSE
ok := FALSE
END
UNTIL NOT ok ;
END
END StrToOctInt ;
PROCEDURE BinToStr (x, n: CARDINAL ; VAR a: ARRAY OF CHAR) ;
VAR
i, j,
Higha : CARDINAL ;
buf : ARRAY [1..MaxBits] OF CARDINAL ;
BEGIN
i := 0 ;
REPEAT
INC(i) ;
IF i>MaxBits
THEN
WriteString('NumberIO - increase MaxBits') ; WriteLn ;
HALT
END ;
buf[i] := x MOD 2 ;
x := x DIV 2 ;
UNTIL x=0 ;
j := 0 ;
Higha := HIGH(a) ;
WHILE (n>i) AND (j<=Higha) DO
a[j] := ' ' ;
INC(j) ;
DEC(n)
END ;
WHILE (i>0) AND (j<=Higha) DO
a[j] := CHR( buf[i] + ORD('0') ) ;
INC(j) ;
DEC(i)
END ;
IF j<=Higha
THEN
a[j] := nul
END
END BinToStr ;
PROCEDURE StrToBin (a: ARRAY OF CHAR ; VAR x: CARDINAL) ;
VAR
i: INTEGER ;
BEGIN
StrToBinInt(a, i) ;
x := VAL(CARDINAL, i)
END StrToBin ;
PROCEDURE StrToBinInt (a: ARRAY OF CHAR ; VAR x: INTEGER) ;
VAR
i : CARDINAL ;
ok : BOOLEAN ;
higha : CARDINAL ;
BEGIN
StrRemoveWhitePrefix(a, a) ;
higha := StrLen(a) ;
i := 0 ;
ok := TRUE ;
WHILE ok DO
IF i<higha
THEN
IF (a[i]<'0') OR (a[i]>'1')
THEN
INC(i)
ELSE
ok := FALSE
END
ELSE
ok := FALSE
END
END ;
x := 0 ;
IF i<higha
THEN
ok := TRUE ;
REPEAT
x := 2*x + VAL(INTEGER, (ORD(a[i])-ORD('0'))) ;
IF i<higha
THEN
INC(i) ;
IF (a[i]<'0') OR (a[i]>'1')
THEN
ok := FALSE
END
ELSE
ok := FALSE
END
UNTIL NOT ok ;
END
END StrToBinInt ;
PROCEDURE ReadOct (VAR x: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
ReadString( a ) ;
StrToOct( a, x )
END ReadOct ;
PROCEDURE WriteOct (x, n: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
OctToStr( x, n, a ) ;
WriteString( a )
END WriteOct ;
PROCEDURE ReadBin (VAR x: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
ReadString(a) ;
StrToBin(a, x)
END ReadBin ;
PROCEDURE WriteBin (x, n: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
BinToStr( x, n, a ) ;
WriteString( a )
END WriteBin ;
PROCEDURE ReadCard (VAR x: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
ReadString( a ) ;
StrToCard( a, x )
END ReadCard ;
PROCEDURE WriteCard (x, n: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
CardToStr( x, n, a ) ;
WriteString( a )
END WriteCard ;
PROCEDURE ReadInt (VAR x: INTEGER) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
ReadString( a ) ;
StrToInt( a, x )
END ReadInt ;
PROCEDURE WriteInt (x: INTEGER; n: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
IntToStr( x, n, a ) ;
WriteString( a )
END WriteInt ;
PROCEDURE ReadHex (VAR x: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
ReadString( a ) ;
StrToHex( a, x )
END ReadHex ;
PROCEDURE WriteHex (x, n: CARDINAL) ;
VAR
a : ARRAY [0..MaxLineLength] OF CHAR ;
BEGIN
HexToStr( x, n, a ) ;
WriteString( a )
END WriteHex ;
END NumberIO.