s48-channel.scm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ; Copyright (c) 1993-2007 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Implementation of OS channels in Scheme.
  3. ;
  4. ; A channel an index into a vector of ports in the underlying Scheme
  5. ; implementation.
  6. ; Vector mapping indicies to ports.
  7. (define *channels* '#())
  8. (define (vector-posq vec thing)
  9. (let loop ((i 0))
  10. (cond ((= i (vector-length vec))
  11. #f)
  12. ((eq? thing (vector-ref vec i))
  13. i)
  14. (else
  15. (loop (+ i 1))))))
  16. (define (channel->port channel)
  17. (vector-ref *channels* channel))
  18. (define input-channel->port channel->port)
  19. (define output-channel->port channel->port)
  20. (define (port->channel port)
  21. (or (vector-posq *channels* port)
  22. (make-channel port)))
  23. (define input-port->channel port->channel)
  24. (define output-port->channel port->channel)
  25. ; Add PORT to the vector of channels, reusing a slot if possible.
  26. (define (make-channel port)
  27. (let ((channel (or (vector-posq *channels* #f)
  28. (let ((channel (vector-length *channels*)))
  29. (set! *channels* (list->vector
  30. (append (vector->list *channels*)
  31. (list #f #f #f #f))))
  32. channel))))
  33. (vector-set! *channels* channel port)
  34. channel))
  35. ; The default ports
  36. (define (current-input-channel)
  37. (port->channel (current-input-port)))
  38. (define (current-output-channel)
  39. (port->channel (current-output-port)))
  40. (define (current-error-channel)
  41. (port->channel (current-error-port)))
  42. ; These just open or close the appropriate port and coerce it to a channel.
  43. (define (open-input-file-channel filename)
  44. (receive (port status)
  45. (prescheme:open-input-file filename)
  46. (if (eq? status (enum prescheme:errors no-errors))
  47. (values (port->channel port) status)
  48. (values #f status))))
  49. (define (open-output-file-channel filename)
  50. (receive (port status)
  51. (prescheme:open-output-file filename)
  52. (if (eq? status (enum prescheme:errors no-errors))
  53. (values (port->channel port) status)
  54. (values #f status))))
  55. (define (close-input-channel channel)
  56. (prescheme:close-input-port (channel->port channel)))
  57. (define (close-output-channel channel)
  58. (prescheme:close-output-port (channel->port channel)))
  59. (define (channel-ready? channel read?)
  60. (values (if read?
  61. (char-ready? (channel->port channel))
  62. #t)
  63. (enum prescheme:errors no-errors)))
  64. (define (channel-crlf?) #f)
  65. ;----------------
  66. ; Non-blocking I/O (implemented using CHAR-READY?)
  67. ;
  68. ; We keep a list of channels for which the user is waiting. These will
  69. ; all be input channels as CHAR-READY? only works on input ports.
  70. (define *pending-channels* '())
  71. (define (channel-read-block channel start count wait?)
  72. (cond ((char-ready? (channel->port channel))
  73. (receive (count eof? status)
  74. (read-block (channel->port channel) start count)
  75. (values count eof? #f status)))
  76. (wait?
  77. (set! *pending-channels* (cons channel *pending-channels*))
  78. (values 0 #f #t (enum prescheme:errors no-errors)))
  79. (else
  80. (values 0 #f #f (enum prescheme:errors no-errors)))))
  81. (define (channel-write-block channel start count)
  82. (values count #f (write-block (channel->port channel) start count)))
  83. (define (channel-buffer-size) 4096)
  84. (define (channel-console-encoding channel) "ISO8859-1")
  85. (define (channel-abort channel)
  86. (set! *pending-channels* (delq channel *pending-channels*))
  87. 0)
  88. ;----------------
  89. ; Events
  90. ;
  91. ; A keyboard interrupt can be generated by setting the following to #t.
  92. (define *pending-keyboard-interrupt?* #f)
  93. (define (initialize-events)
  94. (set! *channels* (make-vector 10 #f))
  95. (set! *pending-channels* '())
  96. (set! *pending-keyboard-interrupt?* #f))
  97. (define (pending-event?)
  98. (or *pending-keyboard-interrupt?*
  99. (any? (lambda (channel)
  100. (char-ready? (channel->port channel)))
  101. *pending-channels*)))
  102. ; The event enumeration is copied from the C version of this code.
  103. (define-enumeration events
  104. (keyboard-interrupt-event
  105. io-completion-event
  106. io-error-event
  107. alarm-event
  108. os-signal-event
  109. error-event
  110. no-event
  111. ))
  112. (define (get-next-event)
  113. (cond (*pending-keyboard-interrupt?*
  114. (set! *pending-keyboard-interrupt?* #f)
  115. (values (enum events keyboard-interrupt-event) #f #f))
  116. ((any (lambda (channel)
  117. (char-ready? (channel->port channel)))
  118. *pending-channels*)
  119. => (lambda (channel)
  120. (set! *pending-channels* (delq channel *pending-channels*))
  121. (values (enum events io-completion-event)
  122. channel
  123. 0)))
  124. (else
  125. (values (enum events no-event) #f #f))))
  126. (define (wait-for-event max-wait minutes?)
  127. (breakpoint "Waiting"))