printf.red 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. %
  2. % PRINTF.RED - Formatted print routine
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 27 August 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % <PSL.KERNEL>PRINTF.RED.2, 17-Sep-82 16:01:01, Edit by BENSON
  12. % Added ChannelPrintF
  13. % <PSL.INTERP>PRINTF.RED.6, 3-May-82 10:45:11, Edit by BENSON
  14. % %L prints nothing for NIL
  15. % <PSL.INTERP>PRINTF.RED.9, 23-Feb-82 21:40:31, Edit by BENSON
  16. % Added %x for hex
  17. % <PSL.INTERP>PRINTF.RED.7, 1-Dec-81 16:11:11, Edit by BENSON
  18. % Changed to cause error for unknown character
  19. CompileTime flag('(PrintF1 PrintF2), 'InternalFunction);
  20. fluid '(FormatForPrintF!*);
  21. % First, lambda-bind FormatForPrintF!*
  22. lisp procedure PrintF(FormatForPrintF!*, A1, A2, A3, A4, A5,
  23. A6, A7, A8, A9, A10,
  24. A11, A12, A13, A14);
  25. PrintF1(FormatForPrintF!*, A1, A2, A3, A4, A5,
  26. A6, A7, A8, A9, A10,
  27. A11, A12, A13, A14);
  28. % Then, push all the registers on the stack and set up a pointer to them
  29. lap '((!*entry PrintF1 expr 15)
  30. (!*PUSH (reg 2))
  31. (!*LOC (reg 1) (frame 1))
  32. (!*PUSH (reg 3))
  33. (!*PUSH (reg 4))
  34. (!*PUSH (reg 5))
  35. (!*PUSH (reg 6))
  36. (!*PUSH (reg 7))
  37. (!*PUSH (reg 8))
  38. (!*PUSH (reg 9))
  39. (!*PUSH (reg 10))
  40. (!*PUSH (reg 11))
  41. (!*PUSH (reg 12))
  42. (!*PUSH (reg 13))
  43. (!*PUSH (reg 14))
  44. (!*PUSH (reg 15))
  45. (!*CALL PrintF2)
  46. (!*EXIT 14)
  47. );
  48. on SysLisp;
  49. % Finally, actual printf, with 1 argument, pointer to array of parameters
  50. syslsp procedure PrintF2 PrintFArgs; %. Formatted print
  51. %
  52. % Format is a string, either in the heap or not, whose characters will be
  53. % written on the currently selected output channel. The exception to this is
  54. % that when a % is encountered, the following character is interpreted as a
  55. % format character, to decide how to print one of the other arguments. The
  56. % following format characters are currently supported:
  57. % %b - blanks; take the next argument as integer and print that many
  58. % blanks
  59. % %c - print the next argument as a single character
  60. % %d - print the next argument as a decimal integer
  61. % %e - EVALs the next argument for side-effect -- most useful if the
  62. % thing EVALed does some printing
  63. % %f - fresh-line, print end-of-line char if not at beginning of line
  64. % %l - same as %w, except lists are printed without top level parens
  65. % %n - print end-of-line character
  66. % %o - print the next argument as an octal integer
  67. % %p - print the next argument as a Lisp item, using Prin1
  68. % %r - print the next argument as a Lisp item, using ErrPrin (`FOO')
  69. % %s - print the next argument as a string
  70. % %t - tab; take the next argument as an integer and
  71. % print spaces to that column
  72. % %w - print the next argument as a Lisp item, using Prin2
  73. % %x - print the next argument as a hexidecimal integer
  74. % %% - print a %
  75. %
  76. % If the character is not one of these (either upper or lower case), then an
  77. % error occurs.
  78. %
  79. begin scalar UpLim, I, Ch, UpCh;
  80. UpLim := StrLen StrInf LispVar FormatForPrintF!*;
  81. I := 0;
  82. while I <= UpLim do
  83. << Ch := StrByt(StrInf LispVar FormatForPrintF!*, I);
  84. if Ch neq char !% then
  85. WriteChar Ch
  86. else
  87. begin
  88. I := I + 1;
  89. Ch := StrByt(StrInf LispVar FormatForPrintF!*, I);
  90. UpCh := if LowerCaseChar Ch then RaiseChar Ch else Ch;
  91. case UpCh of
  92. char B:
  93. << Spaces @PrintFArgs;
  94. PrintFArgs := &PrintFArgs[StackDirection] >>;
  95. char C:
  96. << WriteChar @PrintFArgs;
  97. PrintFArgs := &PrintFArgs[StackDirection] >>;
  98. char D:
  99. << WriteSysInteger(@PrintFArgs, 10);
  100. PrintFArgs := &PrintFArgs[StackDirection] >>;
  101. char E:
  102. << Eval @PrintFArgs;
  103. PrintFArgs := &PrintFArgs[StackDirection] >>;
  104. char F:
  105. if Posn() > 0 then WriteChar char EOL;
  106. char L:
  107. << Prin2L @PrintFArgs;
  108. PrintFArgs := &PrintFArgs[StackDirection] >>;
  109. char N:
  110. WriteChar char EOL;
  111. char O:
  112. << WriteSysInteger(@PrintFArgs, 8);
  113. PrintFArgs := &PrintFArgs[StackDirection] >>;
  114. char X:
  115. << WriteSysInteger(@PrintFArgs, 16);
  116. PrintFArgs := &PrintFArgs[StackDirection] >>;
  117. char P:
  118. << Prin1 @PrintFArgs;
  119. PrintFArgs := &PrintFArgs[StackDirection] >>;
  120. char R:
  121. << ErrPrin @PrintFArgs;
  122. PrintFArgs := &PrintFArgs[StackDirection] >>;
  123. char S:
  124. << WriteString @PrintFArgs;
  125. PrintFArgs := &PrintFArgs[StackDirection] >>;
  126. char T:
  127. << Tab @PrintFArgs;
  128. PrintFArgs := &PrintFArgs[StackDirection] >>;
  129. char W:
  130. << Prin2 @PrintFArgs;
  131. PrintFArgs := &PrintFArgs[StackDirection] >>;
  132. char !%:
  133. WriteChar char !%;
  134. default:
  135. StdError BldMsg('"Unknown character code for PrintF: %r",
  136. MkID Ch);
  137. end;
  138. end;
  139. I := I + 1 >>;
  140. end;
  141. syslsp procedure ErrorPrintF(Format, A1, A2, A3, A4); % also A5..A14
  142. begin scalar SaveChannel;
  143. SaveChannel := WRS LispVar ErrOut!*;
  144. if LinePosition[IntInf LispVar ErrOut!*] > 0 then TerPri();
  145. PrintF(Format, A1, A2, A3, A4);
  146. if LinePosition[IntInf LispVar ErrOut!*] > 0 then TerPri();
  147. WRS SaveChannel;
  148. end;
  149. syslsp procedure ToStringWriteChar(Channel, Ch); % shares TokenBuffer
  150. << if TokenBuffer[0] >= MaxTokenSize - 1 then
  151. << TokenBuffer[0] := 80; % truncate to 80 chars
  152. StrByt(TokenBuffer, 80) := char NULL;
  153. StdError list('"Buffer overflow while constructing error message:",
  154. LispVar FormatForPrintF!*,
  155. '"The truncated result was:",
  156. CopyString MkSTR TokenBuffer) >>
  157. else
  158. << TokenBuffer[0] := TokenBuffer[0] + 1;
  159. StrByt(TokenBuffer, TokenBuffer[0]) := Ch >> >>;
  160. syslsp procedure BldMsg(Format, Arg1, Arg2, Arg3, Arg4); %. Print to string
  161. begin scalar TempChannel; % takes up to 14 args
  162. LinePosition[2] := 0;
  163. TokenBuffer[0] := -1;
  164. TempChannel := LispVar OUT!*;
  165. LispVar OUT!* := '2;
  166. PrintF(Format, Arg1, Arg2, Arg3, Arg4);
  167. StrByt(TokenBuffer, TokenBuffer[0] + 1) := char NULL;
  168. LispVar OUT!* := TempChannel;
  169. return CopyString TokenBuffer;
  170. end;
  171. syslsp procedure ErrPrin U; %. `Prin1 with quotes'
  172. << WriteChar char !`;
  173. Prin1 U;
  174. WriteChar char !' >>;
  175. off SysLisp;
  176. lisp procedure Prin2L Itm; %. Prin2 without top-level parens
  177. if null Itm then NIL % NIL is (), print nothing
  178. else if not PairP Itm then Prin2 Itm
  179. else
  180. << while << Prin2 car Itm;
  181. Itm := cdr Itm;
  182. PairP Itm >> do
  183. ChannelWriteBlankOrEOL OUT!*;
  184. if Itm then
  185. << ChannelWriteBlankOrEOL OUT!*;
  186. Prin2 Itm >> >>;
  187. syslsp procedure ChannelPrintF(OUT!*, Format, A1, A2, A3, A4, A5, A6, A7, A8,
  188. A9, A10, A11, A12, A13);
  189. PrintF(Format, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
  190. END;