string-input.sl 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %%% Input from strings
  3. %%% Cris Perdue
  4. %%% 12/1/82
  5. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6. (compiletime (load if fast-int))
  7. (fluid '(channel-string channel-string-pos))
  8. %%% Takes two arguments: a string and a function.
  9. %%% The function must take 1 argument. With-input-from-string
  10. %%% will call the function and pass it a channel number. If the
  11. %%% function takes input from the channel (which is the point of
  12. %%% all this), it will receive successive characters from the
  13. %%% string as its input.
  14. %%%
  15. %%% This is not currently unwind-protected.
  16. (defun with-input-from-string (str fn)
  17. (let ((specialreadfunction* 'string-readchar)
  18. (specialwritefunction* 'readonlychannel)
  19. (specialclosefunction* 'null)
  20. (channel-string str) (channel-string-pos 0))
  21. (let ((chan (open "" 'special))
  22. value)
  23. (setq value (apply fn (list chan)))
  24. (close chan)
  25. value)))
  26. %%% This is similar to with-input-from-string, but the string
  27. %%% passed in is effectively padded on the right with a single
  28. %%% blank. No storage allocation is performed to give this
  29. %%% effect.
  30. (defun with-input-from-terminated-string (str fn)
  31. (let ((specialreadfunction* 'string-readchar-terminated)
  32. (specialwritefunction* 'readonlychannel)
  33. (specialclosefunction* 'null)
  34. (channel-string str)
  35. (channel-string-pos 0))
  36. (let ((chan (open "" 'special))
  37. value)
  38. (setq value (apply fn (list chan)))
  39. (close chan)
  40. value)))
  41. %%% Reads from the string. The string is effectively padded with
  42. %%% a blank at the end so if the expression in the string is for
  43. %%% example a single token, it need not be followed by a terminator.
  44. (defun string-read (str)
  45. (with-input-from-terminated-string str 'channelread))
  46. %%% Reads a single token from the string using channelreadtoken.
  47. %%% The string need contain no terminator character; a blank is
  48. %%% provided if necessary by string-readtoken.
  49. (defun string-readtoken (str)
  50. (with-input-from-terminated-string str 'channelreadtoken))
  51. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  52. %%% Internal routines.
  53. (defun string-readchar (chan)
  54. (if (> channel-string-pos (size channel-string)) then
  55. $eof$
  56. else
  57. (prog1
  58. (indx channel-string channel-string-pos)
  59. (setq channel-string-pos (+ channel-string-pos 1)))))
  60. %%% Includes hack that tacks on a blank for termination of READ
  61. %%% and friends.
  62. (defun string-readchar-terminated (chan)
  63. (if (<= channel-string-pos (size channel-string)) then
  64. (prog1
  65. (indx channel-string channel-string-pos)
  66. (setq channel-string-pos (+ channel-string-pos 1)))
  67. elseif (= channel-string-pos (+ 1 (size channel-string))) then
  68. (prog1
  69. 32 % Blank
  70. (setq channel-string-pos (+ channel-string-pos 1)))
  71. else
  72. $eof$))