| (* Copyright (C) 2015-2025 Free Software Foundation, Inc. *) |
| (* 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. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. *) |
| |
| IMPLEMENTATION MODULE mcPrintf ; |
| |
| FROM SFIO IMPORT WriteS ; |
| FROM FIO IMPORT StdOut ; |
| FROM DynamicStrings IMPORT String, string, InitString, KillString, InitStringCharStar, Mark ; |
| FROM StrLib IMPORT StrLen ; |
| FROM FormatStrings IMPORT Sprintf0, Sprintf1, Sprintf2, Sprintf3, Sprintf4 ; |
| FROM nameKey IMPORT Name, keyToCharStar ; |
| |
| |
| (* |
| isDigit - returns TRUE if, ch, is a character 0..9 |
| *) |
| |
| PROCEDURE isDigit (ch: CHAR) : BOOLEAN ; |
| BEGIN |
| RETURN (ch>='0') AND (ch<='9') |
| END isDigit ; |
| |
| |
| (* |
| cast - casts a := b |
| *) |
| |
| PROCEDURE cast (VAR a: ARRAY OF BYTE; b: ARRAY OF BYTE) ; |
| VAR |
| i: CARDINAL ; |
| BEGIN |
| IF HIGH (a) = HIGH (b) |
| THEN |
| FOR i := 0 TO HIGH (a) DO |
| a[i] := b[i] |
| END |
| ELSE |
| HALT |
| END |
| END cast ; |
| |
| |
| (* |
| TranslateNameToCharStar - takes a format specification string, a, and |
| if they consist of of %a then this is translated |
| into a String and %a is replaced by %s. |
| *) |
| |
| PROCEDURE TranslateNameToCharStar (VAR a: ARRAY OF CHAR; |
| n: CARDINAL) : BOOLEAN ; |
| VAR |
| argno, |
| i, h : CARDINAL ; |
| BEGIN |
| argno := 1 ; |
| i := 0 ; |
| h := StrLen (a) ; |
| WHILE i<h DO |
| IF (a[i]='%') AND (i+1<h) |
| THEN |
| IF (a[i+1]='a') AND (argno=n) |
| THEN |
| a[i+1] := 's' ; |
| RETURN TRUE |
| END ; |
| INC (argno) ; |
| IF argno>n |
| THEN |
| (* all done *) |
| RETURN FALSE |
| END |
| END ; |
| INC (i) |
| END ; |
| RETURN FALSE |
| END TranslateNameToCharStar ; |
| |
| |
| (* |
| fprintf0 - writes out an array to, file, after the escape sequences |
| have been translated. |
| *) |
| |
| PROCEDURE fprintf0 (file: File; a: ARRAY OF CHAR) ; |
| BEGIN |
| IF KillString (WriteS (file, Sprintf0 (InitString (a)))) = NIL |
| THEN |
| END |
| END fprintf0 ; |
| |
| |
| PROCEDURE fprintf1 (file: File; a: ARRAY OF CHAR; w: ARRAY OF BYTE) ; |
| VAR |
| s, t: String ; |
| n : Name ; |
| BEGIN |
| IF TranslateNameToCharStar (a, 1) |
| THEN |
| cast (n, w) ; |
| s := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| t := Mark (InitString (a)) ; |
| s := Sprintf1 (t, s) |
| ELSE |
| t := Mark (InitString (a)) ; |
| s := Sprintf1 (t, w) |
| END ; |
| IF KillString (WriteS (file, s)) = NIL |
| THEN |
| END |
| END fprintf1 ; |
| |
| |
| PROCEDURE fprintf2 (file: File; a: ARRAY OF CHAR; w1, w2: ARRAY OF BYTE) ; |
| VAR |
| n : Name ; |
| s, |
| s1, s2: String ; |
| b : BITSET ; |
| BEGIN |
| b := {} ; |
| IF TranslateNameToCharStar (a, 1) |
| THEN |
| cast (n, w1) ; |
| s1 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 1) |
| END ; |
| IF TranslateNameToCharStar (a, 2) |
| THEN |
| cast (n, w2) ; |
| s2 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 2) |
| END ; |
| CASE b OF |
| |
| {} : s := Sprintf2 (Mark (InitString (a)), w1, w2) | |
| {1} : s := Sprintf2 (Mark (InitString (a)), s1, w2) | |
| {2} : s := Sprintf2 (Mark (InitString (a)), w1, s2) | |
| {1,2}: s := Sprintf2 (Mark (InitString (a)), s1, s2) |
| |
| ELSE |
| HALT |
| END ; |
| IF KillString (WriteS (file, s)) = NIL |
| THEN |
| END |
| END fprintf2 ; |
| |
| |
| PROCEDURE fprintf3 (file: File; a: ARRAY OF CHAR; |
| w1, w2, w3: ARRAY OF BYTE) ; |
| VAR |
| n : Name ; |
| s, s1, s2, s3: String ; |
| b : BITSET ; |
| BEGIN |
| b := {} ; |
| IF TranslateNameToCharStar (a, 1) |
| THEN |
| cast (n, w1) ; |
| s1 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 1) |
| END ; |
| IF TranslateNameToCharStar (a, 2) |
| THEN |
| cast (n, w2) ; |
| s2 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 2) |
| END ; |
| IF TranslateNameToCharStar (a, 3) |
| THEN |
| cast (n, w3) ; |
| s3 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 3) |
| END ; |
| CASE b OF |
| |
| {} : s := Sprintf3 (Mark (InitString (a)), w1, w2, w3) | |
| {1} : s := Sprintf3 (Mark (InitString (a)), s1, w2, w3) | |
| {2} : s := Sprintf3 (Mark (InitString (a)), w1, s2, w3) | |
| {1,2} : s := Sprintf3 (Mark (InitString (a)), s1, s2, w3) | |
| {3} : s := Sprintf3 (Mark (InitString (a)), w1, w2, s3) | |
| {1,3} : s := Sprintf3 (Mark (InitString (a)), s1, w2, s3) | |
| {2,3} : s := Sprintf3 (Mark (InitString (a)), w1, s2, s3) | |
| {1,2,3}: s := Sprintf3 (Mark (InitString (a)), s1, s2, s3) |
| |
| ELSE |
| HALT |
| END ; |
| IF KillString(WriteS(file, s))=NIL |
| THEN |
| END |
| END fprintf3 ; |
| |
| |
| PROCEDURE fprintf4 (file: File; a: ARRAY OF CHAR; |
| w1, w2, w3, w4: ARRAY OF BYTE) ; |
| VAR |
| n : Name ; |
| s, s1, s2, s3, s4: String ; |
| b : BITSET ; |
| BEGIN |
| b := {} ; |
| IF TranslateNameToCharStar (a, 1) |
| THEN |
| cast (n, w1) ; |
| s1 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 1) |
| END ; |
| IF TranslateNameToCharStar (a, 2) |
| THEN |
| cast (n, w2) ; |
| s2 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 2) |
| END ; |
| IF TranslateNameToCharStar (a, 3) |
| THEN |
| cast (n, w3) ; |
| s3 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 3) |
| END ; |
| IF TranslateNameToCharStar (a, 4) |
| THEN |
| cast (n, w4) ; |
| s4 := Mark (InitStringCharStar (keyToCharStar (n))) ; |
| INCL (b, 4) |
| END ; |
| CASE b OF |
| |
| {} : s := Sprintf4 (Mark(InitString (a)), w1, w2, w3, w4) | |
| {1} : s := Sprintf4 (Mark(InitString (a)), s1, w2, w3, w4) | |
| {2} : s := Sprintf4 (Mark(InitString (a)), w1, s2, w3, w4) | |
| {1,2} : s := Sprintf4 (Mark(InitString (a)), s1, s2, w3, w4) | |
| {3} : s := Sprintf4 (Mark(InitString (a)), w1, w2, s3, w4) | |
| {1,3} : s := Sprintf4 (Mark(InitString (a)), s1, w2, s3, w4) | |
| {2,3} : s := Sprintf4 (Mark(InitString (a)), w1, s2, s3, w4) | |
| {1,2,3} : s := Sprintf4 (Mark(InitString (a)), s1, s2, s3, w4) | |
| {4} : s := Sprintf4 (Mark(InitString (a)), w1, w2, w3, s4) | |
| {1,4} : s := Sprintf4 (Mark(InitString (a)), s1, w2, w3, s4) | |
| {2,4} : s := Sprintf4 (Mark(InitString (a)), w1, s2, w3, s4) | |
| {1,2,4} : s := Sprintf4 (Mark(InitString (a)), s1, s2, w3, s4) | |
| {3,4} : s := Sprintf4 (Mark(InitString (a)), w1, w2, s3, s4) | |
| {1,3,4} : s := Sprintf4 (Mark(InitString (a)), s1, w2, s3, s4) | |
| {2,3,4} : s := Sprintf4 (Mark(InitString (a)), w1, s2, s3, s4) | |
| {1,2,3,4}: s := Sprintf4 (Mark(InitString (a)), s1, s2, s3, s4) |
| |
| ELSE |
| HALT |
| END ; |
| IF KillString (WriteS (file, s)) = NIL |
| THEN |
| END |
| END fprintf4 ; |
| |
| |
| (* |
| printf0 - writes out an array to, StdOut, after the escape |
| sequences have been translated. |
| *) |
| |
| PROCEDURE printf0 (a: ARRAY OF CHAR) ; |
| BEGIN |
| fprintf0 (StdOut, a) |
| END printf0 ; |
| |
| |
| PROCEDURE printf1 (a: ARRAY OF CHAR; |
| w: ARRAY OF BYTE) ; |
| BEGIN |
| fprintf1 (StdOut, a, w) |
| END printf1 ; |
| |
| |
| PROCEDURE printf2 (a: ARRAY OF CHAR; |
| w1, w2: ARRAY OF BYTE) ; |
| BEGIN |
| fprintf2 (StdOut, a, w1, w2) |
| END printf2 ; |
| |
| |
| PROCEDURE printf3 (a: ARRAY OF CHAR; |
| w1, w2, w3: ARRAY OF BYTE) ; |
| BEGIN |
| fprintf3 (StdOut, a, w1, w2, w3) |
| END printf3 ; |
| |
| |
| PROCEDURE printf4 (a: ARRAY OF CHAR; |
| w1, w2, w3, w4: ARRAY OF BYTE) ; |
| BEGIN |
| fprintf4 (StdOut, a, w1, w2, w3, w4) |
| END printf4 ; |
| |
| |
| END mcPrintf. |