system-io.red 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. %==============================================================================
  2. %
  3. % SYSTEM-IO.RED - System independent IO routines for PSL
  4. %
  5. % Author: Modified by Robert R. Kessler
  6. % From System-io.red for the VAX by Eric Benson
  7. % Computer Science Dept.
  8. % University of Utah
  9. % Date: Modified 16 August 1982
  10. % Original Date 16 September 1981
  11. %
  12. % Copyright (c) 1982 University of Utah
  13. %
  14. %==============================================================================
  15. % Each individual system must have the following routines defined.
  16. %
  17. % The following definitions are used in the routines:
  18. % FileDescriptor - A machine dependent word that references a file once
  19. % opened; generated by the Open
  20. % FileName - A Lisp string of the file name.
  21. %
  22. % FileDescriptor := SysOpenRead (Channel,FileName);
  23. % % Open FileName for input and
  24. % % return a file descriptor used
  25. % % in later references to the
  26. % % file. Channel used only
  27. % % if needed to generate FileDesc
  28. % FileDescriptor := SysOpenWrite (Channel,FileName);
  29. % % Open FileName for output and
  30. % % return a file descriptor used
  31. % % in later references to the
  32. % % file. Channel used only
  33. % % if needed to generate FileDesc
  34. % SysWriteRec (FileDescriptor, StringToWrite, StringLength);
  35. % % Write StringLength characters
  36. % % from StringToWrite from the
  37. % % first position.
  38. % LengthRead := SysReadRec (FileDescriptor, StringBuffer);
  39. % % Read from the FileDescriptor, a
  40. % % record into the StringBuffer.
  41. % % Return the length of the
  42. % % string read.
  43. % SysClose (FileDescriptor); % Close FileDescriptor, allowing
  44. % % it to be reused.
  45. % TerminalInputHandler (FileDescriptor); % Input from the terminal, on
  46. % % FileDescriptor. This routine
  47. % % is expected to use the prompt
  48. % % in PromptString!*.
  49. %
  50. %==============================================================================
  51. CompileTime Load Fast!-Vector;
  52. global '(IN!* OUT!*);
  53. LoadTime <<
  54. IN!* := 0;
  55. OUT!* := 1;
  56. >>;
  57. fluid '(StdIN!* StdOUT!* ErrOUT!* PromptOUT!* !*Echo);
  58. LoadTime <<
  59. StdIN!* := 0;
  60. StdOUT!* := 1;
  61. ErrOUT!* := 5;
  62. PromptOUT!* := 6;
  63. >>;
  64. %==============================================================================
  65. %
  66. on SysLisp;
  67. % The channel table contains the actual file descriptor as returned from
  68. % the open routines. Since the file descriptor may be any value, it
  69. % may not be used in finding a free channel. Therefore, we now have a
  70. % warray ChannelStatus that is the current status of the channel.
  71. % NOTE: ChannelStatus must be initialized to all closed.
  72. % The following constants are used to indicate the status of the Channel.
  73. WConst ChannelClosed = 0,
  74. ChannelOpenRead = 1,
  75. ChannelOpenWrite = 2,
  76. ChannelOpenSpecial = 3;
  77. % Look into the ChannelStatus array for a free channel.
  78. syslsp procedure FindFreeChannel();
  79. begin scalar Channel;
  80. Channel := 0;
  81. while ChannelStatus [Channel] neq ChannelClosed do
  82. << if Channel >= MaxChannels then
  83. IOError "No free channels left";
  84. Channel := Channel + 1 >>;
  85. return Channel;
  86. end;
  87. CompileTime fluid '(IOBuffer);
  88. % Open the argument filename as a read only file.
  89. syslsp procedure SystemOpenFileForInput FileName;
  90. begin scalar Channel;
  91. Channel := FindFreeChannel();
  92. ChannelTable [Channel] := SysOpenRead (Channel,FileName);
  93. ChannelStatus[Channel] := ChannelOpenRead;
  94. MaxBuffer [Channel] := SysMaxBuffer (ChannelTable [Channel]);
  95. ReadFunction [Channel] := 'IndependentReadChar;
  96. WriteFunction [Channel] := 'ReadOnlyChannel;
  97. CloseFunction [Channel] := 'IndependentCloseChannel;
  98. IGetV (LispVar IOBuffer, Channel) :=
  99. MkString (MaxBuffer [Channel], 32);
  100. NextPosition [Channel] := 0; % Will be post Incremented
  101. BufferLength [Channel] := -1;
  102. return Channel;
  103. end;
  104. syslsp procedure SystemOpenFileForOutput FileName;
  105. begin scalar Channel;
  106. Channel := FindFreeChannel();
  107. ChannelTable [Channel] := SysOpenWrite (Channel,FileName);
  108. ChannelStatus[Channel] := ChannelOpenWrite;
  109. MaxBuffer [Channel] := SysMaxBuffer (ChannelTable [Channel]);
  110. ReadFunction [Channel] := 'WriteOnlyChannel;
  111. WriteFunction [Channel] := 'IndependentWriteChar;
  112. CloseFunction [Channel] := 'IndependentCloseChannel;
  113. Igetv(LispVar IOBuffer,Channel) := MkString (MaxBuffer [Channel], 32);
  114. NextPosition [Channel] := -1; % Will be set pre-incremented
  115. BufferLength [Channel] := MaxBuffer [Channel];
  116. return Channel;
  117. end;
  118. % Mark a channel as open for a special purpose.
  119. syslsp procedure SystemOpenFileSpecial FileName;
  120. begin scalar Channel;
  121. ChannelStatus [Channel] := ChannelOpenSpecial;
  122. return Channel
  123. end;
  124. syslsp procedure TestLegalChannel Channel;
  125. If not( PosIntP Channel and Channel <=MaxChannels)
  126. then IoError List(Channel," is not a legal channel ");
  127. % This function will read in a character from the buffer. It will read
  128. % the record on buffer length overflow only. Thus when an EOL character
  129. % is read, it is processed as any other character, except, if it is the last
  130. % one, in the record, it will do the read automatically.
  131. % Note, this will not read the next record until after the final character
  132. % has been processed.
  133. syslsp procedure IndependentReadChar Channel;
  134. begin scalar Chr;
  135. TestLegalChannel Channel;
  136. if NextPosition [Channel] > BufferLength [Channel] then
  137. << BufferLength [Channel] :=
  138. SysReadRec (ChannelTable[Channel],
  139. IGetV(LispVar IOBuffer, Channel));
  140. NextPosition [Channel] := 0 >>;
  141. Chr := StrByt (IGetV (LispVar IOBuffer, Channel),
  142. NextPosition [Channel]);
  143. NextPosition [Channel] := NextPosition [Channel] + 1;
  144. if LispVar !*Echo then WriteChar Chr;
  145. return Chr;
  146. end;
  147. % Write a character into the buffer. Actually dump the buffer when the
  148. % EOL character is found, or when the buffer is full. This happens
  149. % immediately upon meeting this condition, not waiting for the
  150. % next character. Note, that this places the EOL character into the
  151. % buffer for machine dependent treatment as CR/LF etc
  152. syslsp procedure IndependentWriteChar (Channel, Chr);
  153. Begin
  154. TestLegalChannel Channel;
  155. NextPosition [Channel] := NextPosition [Channel] + 1;
  156. StrByt (IGetV (LispVar IOBuffer, Channel), NextPosition [Channel])
  157. := Chr;
  158. if (Chr eq char EOL) or
  159. (NextPosition [Channel] >= BufferLength [Channel]) then
  160. % 12/13/82 - rrk Placed code in FlushBuffer and added a call.
  161. FlushBuffer Channel;
  162. End;
  163. % 12/13/82 - rrk Added FlushBuffer procedure.
  164. % Flush out the buffer whether or not we have an EOL character.
  165. Procedure FlushBuffer Channel;
  166. << SysWriteRec (ChannelTable[Channel],
  167. IGetV (LispVar IOBuffer, Channel),
  168. NextPosition [Channel]);
  169. NextPosition[Channel] :=-1 >>; % Start Fresh Buffer
  170. % Mark the argument channel as closed and update the read, write and
  171. % close functions likewise. Careful, if the caller does this first
  172. % and then trys to access a read, write or close function we are
  173. % in big trouble. Is it correct to do this????? Or is a marking of
  174. % the channel status table sufficient.
  175. syslsp procedure SystemMarkAsClosedChannel Channel;
  176. << TestLegalChannel Channel;
  177. ChannelStatus [Channel] := ChannelClosed;
  178. ReadFunction [Channel] := WriteFunction [Channel] :=
  179. CloseFunction [Channel] := 'ChannelNotOpen >>;
  180. % Actually close the argument channel.
  181. syslsp procedure IndependentCloseChannel Channel;
  182. << TestLegalChannel Channel;
  183. SysClose ChannelTable [Channel]>>;
  184. % Initialize Channel Tables etc
  185. Syslsp procedure ClearOneChannel(Chn,Bufflen,How);
  186. << MaxBuffer [Chn] := Bufflen;
  187. NextPosition [Chn] := 0;
  188. % SAL - Next two not properly initialized.
  189. LinePosition [Chn] := 0;
  190. UnreadBuffer [Chn] := 0;
  191. If how eq 'Input then BufferLength [Chn] := -1
  192. else BufferLength [Chn] := 0;
  193. IGetV (LispVar IOBuffer, Chn) := MkString(Bufflen,32)>>;
  194. syslsp procedure ClearIO();
  195. << SysClearIo();
  196. If not VectorP LispVar Iobuffer then
  197. <<LispVar IOBuffer := MkVect (MaxChannels);
  198. ClearOneChannel(LispVar StdIn!*,200,'Input);
  199. ClearOneChannel(LispVar StdOut!*,200,'Output);
  200. ClearOneChannel(LispVar ErrOut!*,200,'OutPut);
  201. ClearOneChannel(LispVar PromptOut!*,200,'Output)>>;
  202. LispVar IN!* := LispVar StdIN!*;
  203. LispVar OUT!* := LispVar StdOUT!* >>;
  204. syslsp procedure TerminalInputHandler Channel;
  205. begin scalar Chr;
  206. TestLegalChannel Channel;
  207. if NextPosition [Channel] > BufferLength [Channel] then
  208. << ChannelWriteString(LispVar PromptOUT!*,
  209. if StringP LispVar PromptString!*
  210. then LispVar PromptString!*
  211. else ">");
  212. % 12/13/82 - rrk Flush out the Prompt character.
  213. FlushBuffer LispVar PromptOut!*;
  214. BufferLength [Channel] := SysReadRec (ChannelTable[Channel],
  215. IGetV (LispVar IOBuffer, Channel));
  216. NextPosition [Channel] := 0 >>;
  217. Chr := StrByt (IGetV (LispVar IOBuffer, Channel),
  218. NextPosition [Channel]);
  219. NextPosition [Channel] := NextPosition [Channel] + 1;
  220. if LispVar !*Echo then WriteChar Chr;
  221. return Chr;
  222. end;
  223. off SysLisp;
  224. END;