mirror of
https://github.com/vishapoberon/compiler.git
synced 2026-04-06 18:02:25 +00:00
244 lines
5.6 KiB
Modula-2
244 lines
5.6 KiB
Modula-2
MODULE ulmIO;
|
|
|
|
IMPORT SYS := ulmSYSTEM, SYSTEM;
|
|
|
|
CONST nl = 0AX;
|
|
|
|
(* conversions *)
|
|
|
|
CONST
|
|
oct = 0;
|
|
dec = 1;
|
|
hex = 2;
|
|
TYPE
|
|
Basetype = SHORTINT; (* oct..hex *)
|
|
|
|
(* basic IO *)
|
|
|
|
VAR
|
|
Done*: BOOLEAN;
|
|
oldch: CHAR;
|
|
readAgain: BOOLEAN;
|
|
|
|
(* ==================== conversions ================================= *)
|
|
|
|
PROCEDURE ConvertNumber(num, len: LONGINT; btyp: Basetype; neg: BOOLEAN;
|
|
VAR str: ARRAY OF CHAR);
|
|
|
|
(* conversion of a number into a string of characters *)
|
|
(* num must get the absolute value of the number *)
|
|
(* len is the minimal length of the generated string *)
|
|
(* neg means: "the number is negative" for btyp = dec *)
|
|
|
|
(*CONST
|
|
NumberLen = 11;*)
|
|
(* we need it as variable to change the value depending on architecture; -- noch *)
|
|
VAR
|
|
(*digits : ARRAY NumberLen+1 OF CHAR;*)
|
|
digits : POINTER TO ARRAY OF CHAR;
|
|
base : INTEGER;
|
|
cnt, ix : INTEGER;
|
|
maxlen : LONGINT;
|
|
dig : LONGINT;
|
|
NumberLen : SHORTINT;
|
|
BEGIN
|
|
|
|
IF SIZE(LONGINT) = 4 THEN
|
|
NumberLen := 11
|
|
ELSIF SIZE(LONGINT) = 8 THEN
|
|
NumberLen := 21
|
|
ELSE
|
|
NumberLen := 11 (* default value, corresponds to 32 bit *)
|
|
END;
|
|
NEW(digits, NumberLen + 1 );
|
|
ASSERT(num >= 0);
|
|
ix := 1;
|
|
WHILE ix <= NumberLen DO
|
|
digits[ix] := "0";
|
|
INC(ix);
|
|
END; (* initialisation *)
|
|
IF btyp = oct THEN
|
|
base := 8;
|
|
ELSIF btyp = dec THEN
|
|
base := 10;
|
|
ELSIF btyp = hex THEN
|
|
base := 10H;
|
|
END;
|
|
cnt := 0;
|
|
REPEAT
|
|
INC(cnt);
|
|
dig := num MOD base;
|
|
num := num DIV base;
|
|
IF dig < 10 THEN
|
|
dig := dig + ORD("0");
|
|
ELSE
|
|
dig := dig - 10 + ORD("A");
|
|
END;
|
|
digits[cnt] := CHR(dig);
|
|
UNTIL num = 0;
|
|
(* (* i don't like this *)
|
|
IF btyp = oct THEN
|
|
cnt := 11;
|
|
ELSIF btyp = hex THEN
|
|
cnt := 8;
|
|
ELSIF neg THEN
|
|
*)
|
|
IF neg THEN
|
|
INC(cnt);
|
|
digits[cnt] := "-";
|
|
END;
|
|
maxlen := LEN(str); (* get maximal length *)
|
|
IF len > maxlen THEN
|
|
len := SHORT(maxlen);
|
|
END;
|
|
IF cnt > maxlen THEN
|
|
cnt := SHORT(maxlen);
|
|
END;
|
|
ix := 0;
|
|
WHILE len > cnt DO
|
|
str[ix] := " ";
|
|
INC(ix);
|
|
DEC(len);
|
|
END;
|
|
WHILE cnt > 0 DO
|
|
str[ix] := digits[cnt];
|
|
INC(ix);
|
|
DEC(cnt);
|
|
END;
|
|
IF ix < maxlen THEN
|
|
str[ix] := 0X;
|
|
END;
|
|
END ConvertNumber;
|
|
|
|
PROCEDURE ConvertInteger(num: LONGINT; len: INTEGER; VAR str: ARRAY OF
|
|
CHAR);
|
|
(* conversion of an integer decimal number to a string *)
|
|
BEGIN
|
|
ConvertNumber(ABS(num),len,dec,num < 0,str);
|
|
END ConvertInteger;
|
|
|
|
(* ========================= terminal ============================ *)
|
|
|
|
PROCEDURE ReadChar(VAR ch: CHAR) : BOOLEAN;
|
|
CONST read = 3;
|
|
(*VAR r0, r1: INTEGER;*)
|
|
VAR r0, r1: LONGINT; (* in ulm system INTEGER and LONGINT have the same 4 byte size; -- noch *)
|
|
BEGIN
|
|
RETURN SYS.UNIXCALL(read, r0, r1, 0, SYSTEM.ADR(ch), 1) & (r0 > 0)
|
|
END ReadChar;
|
|
|
|
PROCEDURE WriteChar(ch: CHAR) : BOOLEAN;
|
|
CONST write = 4;
|
|
(*VAR r0, r1: INTEGER;*)
|
|
VAR r0, r1: LONGINT; (* same here *)
|
|
BEGIN
|
|
RETURN SYS.UNIXCALL(write, r0, r1, 1, SYSTEM.ADR(ch), 1)
|
|
END WriteChar;
|
|
|
|
PROCEDURE Read*(VAR ch: CHAR);
|
|
BEGIN
|
|
Done := TRUE;
|
|
IF readAgain THEN
|
|
ch := oldch;
|
|
readAgain := FALSE;
|
|
ELSIF ~ReadChar(ch) THEN
|
|
Done := FALSE;
|
|
ch := 0X;
|
|
ELSE
|
|
oldch := ch;
|
|
END;
|
|
END Read;
|
|
|
|
PROCEDURE ReadAgain*;
|
|
BEGIN
|
|
IF readAgain THEN
|
|
Done := FALSE;
|
|
ELSE
|
|
Done := TRUE;
|
|
readAgain := TRUE;
|
|
END;
|
|
END ReadAgain;
|
|
|
|
PROCEDURE Write*(ch: CHAR);
|
|
BEGIN
|
|
Done := WriteChar(ch);
|
|
END Write;
|
|
|
|
PROCEDURE WriteLn*;
|
|
CONST nl = 0AX;
|
|
BEGIN
|
|
Write(nl);
|
|
END WriteLn;
|
|
|
|
PROCEDURE WriteString*(s: ARRAY OF CHAR);
|
|
VAR i: INTEGER;
|
|
BEGIN
|
|
i := 0;
|
|
WHILE (i < LEN(s)) & (s[i] # 0X) DO
|
|
Write(s[i]);
|
|
INC(i);
|
|
END;
|
|
END WriteString;
|
|
|
|
PROCEDURE InitIO;
|
|
BEGIN
|
|
readAgain := FALSE;
|
|
Done := TRUE;
|
|
END InitIO;
|
|
|
|
PROCEDURE WriteInt*(arg: LONGINT);
|
|
VAR field: ARRAY 23 OF CHAR;
|
|
BEGIN (* the field size should be big enough to hold the long number. it was 12 to hold just 32 bit numbers, now it can hold 64 bit numbers; need to be more for 128bit numbers; -- noch *)
|
|
ConvertInteger(arg, 1, field);
|
|
WriteString(field);
|
|
END WriteInt;
|
|
|
|
PROCEDURE ReadInt*(VAR arg: LONGINT);
|
|
VAR ch: CHAR;
|
|
minus: BOOLEAN;
|
|
BEGIN
|
|
minus := FALSE;
|
|
REPEAT
|
|
Read(ch);
|
|
IF ~Done THEN RETURN END;
|
|
IF ch = "-" THEN
|
|
minus := TRUE;
|
|
ELSIF (ch # " ") & (ch # nl) & ((ch < "0") OR (ch > "9")) THEN
|
|
WriteString("--- Integer expected on input"); WriteLn;
|
|
END;
|
|
UNTIL (ch >= "0") & (ch <= "9");
|
|
arg := ORD(ch) - ORD("0");
|
|
REPEAT
|
|
Read(ch);
|
|
IF ~Done THEN RETURN END;
|
|
IF (ch >= "0") & (ch <= "9") THEN
|
|
arg := arg*10 + (ORD(ch) - ORD("0"));
|
|
END;
|
|
UNTIL (ch < "0") OR (ch > "9");
|
|
ReadAgain;
|
|
IF minus THEN arg := -arg; END;
|
|
END ReadInt;
|
|
|
|
PROCEDURE ReadLine*(VAR string: ARRAY OF CHAR);
|
|
VAR
|
|
index: INTEGER;
|
|
ch: CHAR;
|
|
ok: BOOLEAN;
|
|
BEGIN
|
|
index := 0; ok := TRUE;
|
|
LOOP
|
|
IF ~ReadChar(ch) THEN ok := FALSE; EXIT END;
|
|
IF ch = nl THEN EXIT END;
|
|
IF index < LEN(string) THEN
|
|
string[index] := ch; INC(index);
|
|
END;
|
|
END;
|
|
IF index < LEN(string) THEN
|
|
string[index] := 0X;
|
|
END;
|
|
Done := ok OR (index > 0);
|
|
END ReadLine;
|
|
|
|
BEGIN
|
|
InitIO;
|
|
END ulmIO.
|