Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. MODULE out;    (* formatted output to stdout *)
  2. (* Wim Niemann, Jan Tuitman 06-OCT-2016 *)
  3.  
  4. IMPORT SYSTEM, _unix;
  5.  
  6. (* example:  IMPORT o:=out;
  7.         o.str("Hello, World!");o.nl;
  8.         o.formatInt("n = %", 3);o.nl;
  9. *)
  10.  
  11. (*
  12. The output functions buffer the characters in buf. This buffer is flushed when out.nl is
  13. called and also when the buffer is full.
  14.  
  15. Calling flush once per line is far more efficient then one system call per
  16. character, but this is noticable only at very long outputs.
  17. *)
  18.  
  19. CONST MAX = 63;         (* last position in buf *)
  20.  
  21. VAR len :INTEGER;       (* string length in buf *)
  22.         buf :ARRAY MAX+1 OF BYTE;
  23.  
  24. PROCEDURE exit* (n :INTEGER);
  25.         (* prevent IMPORT unix for many programs *)
  26. BEGIN _unix._exit(n) END exit;
  27.  
  28. PROCEDURE writeChars;
  29.         (* write buf to the output function and set to empty string *)
  30. VAR ri :INTEGER;
  31. BEGIN
  32.         IF len > 0 THEN
  33.                 (* buf[len] := 0X; *)
  34.                 ri := _unix._write (1, SYSTEM.ADR(buf), len); ASSERT (ri = len);  (* stdout *)
  35.                 len := 0
  36.         END
  37. END writeChars;
  38.  
  39. PROCEDURE nl*;  (* append a newline to buf and flush *)
  40. BEGIN
  41.         IF len = MAX THEN writeChars END;
  42.         buf[len] := 0AH; INC(len);
  43.         (* unix: 0AX; Oberon: 0DX;
  44.        Windows: IF len >= MAX-1 THEN 0DX 0AX; *)
  45.         writeChars;
  46. END nl;
  47.  
  48. PROCEDURE char* (c :CHAR);
  49.         (* append char to the end of buf *)
  50. BEGIN
  51.         IF len = MAX THEN writeChars END;
  52.         buf[len] := ORD(c); INC(len)
  53. END char;
  54.  
  55. PROCEDURE str* (t :ARRAY OF CHAR);
  56.         (* append t to buf *)
  57. VAR j :INTEGER;
  58. BEGIN
  59.         j := 0; WHILE t[j] # 0X DO char(t[j]); INC(j) END
  60. END str;
  61.  
  62. PROCEDURE int* (n :INTEGER);
  63.         (* append integer; append n to d, return TRUE on overflow of d *)
  64. VAR     j :INTEGER;
  65.         sign :BOOLEAN;
  66.         dig :ARRAY 11 OF CHAR;  (* assume 32 bit INTEGER *)
  67. BEGIN
  68.         sign := FALSE; IF n < 0 THEN sign := TRUE; n := -n END;
  69.         IF n < 0 THEN
  70.                 str ("-2147483648");
  71.         ELSE
  72.                 j := 0;
  73.                 REPEAT dig[j] := CHR (n MOD 10 + 30H); n := n DIV 10; INC(j) UNTIL n = 0;
  74.                 IF sign THEN char ("-") END;
  75.                 REPEAT DEC(j); char(dig[j]) UNTIL j = 0;
  76.         END
  77. END int;
  78.  
  79. PROCEDURE formatInt* (t :ARRAY OF CHAR; n :INTEGER);
  80.         (* append formatted string t. Replace the first % by n *)
  81. VAR j :INTEGER;
  82. BEGIN
  83.         j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END;
  84.         IF t[j] = "%" THEN
  85.                 int(n); INC(j);
  86.                 WHILE t[j] # 0X DO char(t[j]); INC(j) END
  87.         END
  88. END formatInt;
  89.  
  90. PROCEDURE formatInt2* (t:ARRAY OF CHAR; n1, n2 :INTEGER);
  91.         (* append formatted string t. Replace the first two % by n1 and n2 *)
  92. VAR j :INTEGER;
  93. BEGIN
  94.         j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END;
  95.         IF t[j] = "%" THEN
  96.                 int(n1); INC(j);
  97.                 WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END;
  98.                 IF t[j] = "%" THEN
  99.                         int(n2); INC(j);
  100.                         WHILE t[j] # 0X DO char(t[j]); INC(j) END
  101.                 END
  102.         END
  103. END formatInt2;
  104.  
  105. PROCEDURE formatStr* (t, u :ARRAY OF CHAR);
  106.         (* append formatted string. Replace the first % in t by u *)
  107. VAR j, k :INTEGER;
  108. BEGIN
  109.         j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END;
  110.         IF t[j] = "%" THEN
  111.                 k := 0; WHILE u[k] # 0X DO char(u[k]); INC(k) END;
  112.                 INC(j); WHILE t[j] # 0X DO char(t[j]); INC(j) END
  113.         END
  114. END formatStr;
  115.  
  116. PROCEDURE hex* (n, width :INTEGER);
  117.         (* print width positions of n as hex string. If necessary, prefix with leading zeroes *)
  118.         (* note: if n needs more positions than width, the first hex digits are not printed *)
  119. VAR j :INTEGER;
  120.         dig :ARRAY 9 OF CHAR;
  121. BEGIN
  122.         ASSERT(width > 0);
  123.         ASSERT (width <= 8);
  124.         dig[width] := 0X;
  125.         REPEAT
  126.                 j := n MOD 16; n := n DIV 16;
  127.                 IF j < 10 THEN j := ORD("0") + j ELSE j := ORD("A") + j - 10 END;
  128.                 DEC(width); dig[width] := CHR(j)
  129.         UNTIL width = 0;
  130.         str (dig);
  131. END hex;
  132.  
  133. PROCEDURE flush*;
  134. (* this routine comes at the end. It won't hardly ever be called
  135.    because nl also flushes. It is present only in case you
  136.    want to write a flushed string which does not end with nl. *)
  137. BEGIN writeChars END flush;
  138.  
  139. (* note: global variable 'len' must be 0 on init. Within the core, bodies of imported modules
  140.    are not executed, so rely on zero initialisation by Modules.Load *)
  141. END out.
  142.  
  143.