home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / runtime / io.scm < prev    next >
Text File  |  2001-06-08  |  40KB  |  1,173 lines

  1. #| -*-Scheme-*-
  2.  
  3. $Id: io.scm,v 14.64 2001/06/09 00:30:38 cph Exp $
  4.  
  5. Copyright (c) 1988-2001 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  20. 02111-1307, USA.
  21. |#
  22.  
  23. ;;;; Input/Output Utilities
  24. ;;; package: (runtime primitive-io)
  25.  
  26. (declare (usual-integrations))
  27.  
  28. (define open-channels-list)
  29. (define open-directories)
  30. (define have-select?)
  31.  
  32. (define (initialize-package!)
  33.   (set! open-channels-list (list 'OPEN-CHANNELS-LIST))
  34.   (add-gc-daemon! close-lost-open-files-daemon)
  35.   (set! open-directories
  36.     (make-gc-finalizer (ucode-primitive new-directory-close 1)))
  37.   (set! have-select? ((ucode-primitive have-select? 0)))
  38.   (add-event-receiver! event:after-restore primitive-io/reset!))
  39.  
  40. (define-structure (channel (constructor %make-channel))
  41.   ;; This structure serves two purposes.  First, because a descriptor
  42.   ;; is a non-pointer, it is necessary to store it in an allocated
  43.   ;; object in order to determine when all references to it have been
  44.   ;; dropped.  Second, the structure provides a type predicate.
  45.   descriptor
  46.   (type #f read-only #t)
  47.   port)
  48.  
  49. (define (open-channel procedure)
  50.   ;; A bunch of hair to permit microcode descriptors be opened with
  51.   ;; interrupts turned on, yet not leave a dangling descriptor around
  52.   ;; if the open is interrupted before the runtime system's data
  53.   ;; structures are updated.
  54.   (let ((p (system-pair-cons (ucode-type weak-cons) #f #f)))
  55.     (dynamic-wind
  56.      (lambda () unspecific)
  57.      (lambda ()
  58.        (and (procedure p)
  59.         (make-channel-1 p)))
  60.      (lambda ()
  61.        (if (and (not (system-pair-car p)) (system-pair-cdr p))
  62.        (begin
  63.          ((ucode-primitive channel-close 1) (system-pair-cdr p))
  64.          (system-pair-set-cdr! p #f)))))))
  65.  
  66. (define (make-channel descriptor)
  67.   (make-channel-1 (system-pair-cons (ucode-type weak-cons) #f descriptor)))
  68.  
  69. (define (make-channel-1 p)
  70.   (let ((channel
  71.      (let ((d (system-pair-cdr p)))
  72.        (%make-channel d (descriptor-type-name d) #f))))
  73.     (without-interrupts
  74.      (lambda ()
  75.        (system-pair-set-car! p channel)
  76.        (set-cdr! open-channels-list (cons p (cdr open-channels-list)))))
  77.     channel))
  78.  
  79. (define (descriptor->channel descriptor)
  80.   (let loop ((channels (cdr open-channels-list)))
  81.     (and (not (null? channels))
  82.      (if (fix:= descriptor (system-pair-cdr (car channels)))
  83.          (system-pair-car (car channels))
  84.          (loop (cdr channels))))))
  85.  
  86. (define (descriptor-type-name descriptor)
  87.   (let ((name ((ucode-primitive channel-type-name 1) descriptor)))
  88.     (and name
  89.      (intern name))))
  90.  
  91. (define-integrable (channel-type=unknown? channel)
  92.   (false? (channel-type channel)))
  93.  
  94. (define-integrable (channel-type=file? channel)
  95.   (eq? 'FILE (channel-type channel)))
  96.  
  97. (define-integrable (channel-type=directory? channel)
  98.   (eq? 'DIRECTORY (channel-type channel)))
  99.  
  100. (define (channel-type=terminal? channel)
  101.   (let ((type (channel-type channel)))
  102.     (or (eq? 'TERMINAL type)
  103.     (eq? 'UNIX-PTY-MASTER type)
  104.     (eq? 'OS/2-CONSOLE type))))
  105.  
  106. (define (channel-close channel)
  107.   (without-interrupts
  108.    (lambda ()
  109.      (if (channel-descriptor channel)
  110.      (begin
  111.        ((ucode-primitive channel-close 1) (channel-descriptor channel))
  112.        (set-channel-descriptor! channel #f)
  113.        (let loop
  114.            ((l1 open-channels-list)
  115.         (l2 (cdr open-channels-list)))
  116.          (cond ((null? l2)
  117.             (error "CHANNEL-CLOSE: lost channel" channel))
  118.            ((eq? channel (system-pair-car (car l2)))
  119.             (set-cdr! l1 (cdr l2)))
  120.            (else
  121.             (loop l2 (cdr l2))))))))))
  122.  
  123. (define-integrable (channel-open? channel)
  124.   (channel-descriptor channel))
  125.  
  126. (define-integrable (channel-closed? channel)
  127.   (not (channel-descriptor channel)))
  128.  
  129. (define (close-all-open-files)
  130.   (close-all-open-channels channel-type=file?))
  131.  
  132. (define (close-all-open-channels #!optional filter)
  133.   (let ((filter (if (default-object? filter) #f filter)))
  134.     (for-each (lambda (channel)
  135.         (if (or (not filter) (filter channel))
  136.             (let ((port (channel-port channel)))
  137.               (if port
  138.               (close-port port)
  139.               (channel-close channel)))))
  140.           (all-open-channels))
  141.     (if (not filter)
  142.     (close-all-open-channels-internal (ucode-primitive channel-close 1)))))
  143.  
  144. (define (all-open-channels)
  145.   (without-interrupts
  146.    (lambda ()
  147.      (let loop ((l (cdr open-channels-list)) (result '()))
  148.        (if (null? l)
  149.        result
  150.        (loop (cdr l) (cons (system-pair-car (car l)) result)))))))
  151.  
  152. (define (primitive-io/reset!)
  153.   ;; This is invoked after disk-restoring.
  154.   ;; It "cleans" the new runtime system.
  155.   (close-all-open-channels-internal (lambda (ignore) ignore))
  156.   (set! have-select? ((ucode-primitive have-select? 0)))
  157.   unspecific)
  158.  
  159. (define (close-all-open-channels-internal action)
  160.   (without-interrupts
  161.    (lambda ()
  162.      (let loop ((l (cdr open-channels-list)))
  163.        (if (not (null? l))
  164.        (begin
  165.          (let ((channel (system-pair-car (car l))))
  166.            (if channel
  167.            (set-channel-descriptor! channel #f)))
  168.          (action (system-pair-cdr (car l)))
  169.          (let ((l (cdr l)))
  170.            (set-cdr! open-channels-list l)
  171.            (loop l))))))))
  172.  
  173. (define (close-lost-open-files-daemon)
  174.   ;; This is the daemon that closes files that no one points to.
  175.   (let loop ((l1 open-channels-list) (l2 (cdr open-channels-list)))
  176.     (cond ((null? l2)
  177.        unspecific)
  178.       ((system-pair-car (car l2))
  179.        (loop l2 (cdr l2)))
  180.       (else
  181.        ((ucode-primitive channel-close 1) (system-pair-cdr (car l2)))
  182.        (set-cdr! l1 (cdr l2))
  183.        (loop l1 (cdr l1))))))
  184.  
  185. ;;;; Channel Primitives
  186.  
  187. (define (port-error-test operator operands)
  188.   ;; If the performance of this `memq' is a problem, change this to
  189.   ;; use a string hash table based on the primitive name.
  190.   (and (memq operator channel-primitives)
  191.        (not (null? operands))
  192.        (let ((descriptor (car operands)))
  193.      (and (exact-nonnegative-integer? descriptor)
  194.           (let ((channel (descriptor->channel descriptor)))
  195.         (and channel
  196.              (channel-port channel)))))))
  197.  
  198. (define channel-primitives
  199.   (list (ucode-primitive channel-blocking 1)
  200.     (ucode-primitive channel-blocking? 1)
  201.     (ucode-primitive channel-close 1)
  202.     (ucode-primitive channel-descriptor 1)
  203.     (ucode-primitive channel-nonblocking 1)
  204.     (ucode-primitive channel-read 4)
  205.     (ucode-primitive channel-write 4)
  206.     (ucode-primitive file-length-new 1)
  207.     (ucode-primitive file-position 1)
  208.     (ucode-primitive file-set-position 2)
  209.     (ucode-primitive pty-master-continue 1)
  210.     (ucode-primitive pty-master-interrupt 1)
  211.     (ucode-primitive pty-master-kill 1)
  212.     (ucode-primitive pty-master-quit 1)
  213.     (ucode-primitive pty-master-send-signal 2)
  214.     (ucode-primitive pty-master-stop 1)
  215.     (ucode-primitive terminal-buffered 1)
  216.     (ucode-primitive terminal-buffered? 1)
  217.     (ucode-primitive terminal-cooked-output 1)
  218.     (ucode-primitive terminal-cooked-output? 1)
  219.     (ucode-primitive terminal-drain-output 1)
  220.     (ucode-primitive terminal-flush-input 1)
  221.     (ucode-primitive terminal-flush-output 1)
  222.     (ucode-primitive terminal-get-ispeed 1)
  223.     (ucode-primitive terminal-get-ospeed 1)
  224.     (ucode-primitive terminal-set-ispeed 2)
  225.     (ucode-primitive terminal-set-ospeed 2)
  226.     (ucode-primitive terminal-get-state 1)
  227.     (ucode-primitive terminal-nonbuffered 1)
  228.     (ucode-primitive terminal-raw-output 1)
  229.     (ucode-primitive terminal-set-state 2)))
  230.  
  231. (define (channel-read channel buffer start end)
  232.   (let ((do-read
  233.      (lambda ()
  234.        ((ucode-primitive channel-read 4)
  235.         (channel-descriptor channel)
  236.         (if (external-string? buffer)
  237.         (external-string-descriptor buffer)
  238.         buffer)
  239.         start
  240.         end))))
  241.     (declare (integrate-operator do-read))
  242.     (if (and have-select? (not (channel-type=file? channel)))
  243.     (with-thread-events-blocked
  244.       (lambda ()
  245.         (let ((do-test
  246.            (lambda (k)
  247.              (let ((result (test-for-input-on-channel channel)))
  248.                (case result
  249.              ((INPUT-AVAILABLE)
  250.               (do-read))
  251.              ((PROCESS-STATUS-CHANGE)
  252.               (handle-subprocess-status-change)
  253.               (if (channel-closed? channel) 0 (k)))
  254.              (else
  255.               (k)))))))
  256.           (if (channel-blocking? channel)
  257.           (let loop () (do-test loop))
  258.           (do-test (lambda () #f))))))
  259.     (do-read))))
  260.  
  261. (define (channel-read-block channel buffer start end)
  262.   (let loop ()
  263.     (or (channel-read channel buffer start end)
  264.     (loop))))
  265.  
  266. (define-integrable (test-for-input-on-channel channel)
  267.   (test-for-input-on-descriptor (channel-descriptor-for-select channel)
  268.                 (channel-blocking? channel)))
  269.  
  270. (define (test-for-input-on-descriptor descriptor block?)
  271.   (if block?
  272.       (or (select-descriptor descriptor #f)
  273.       (block-on-input-descriptor descriptor))
  274.       (select-descriptor descriptor #f)))
  275.  
  276. (define-integrable (channel-descriptor-for-select channel)
  277.   ((ucode-primitive channel-descriptor 1) (channel-descriptor channel)))
  278.  
  279. (define (channel-write channel buffer start end)
  280.   ((ucode-primitive channel-write 4) (channel-descriptor channel)
  281.                      (if (external-string? buffer)
  282.                      (external-string-descriptor buffer)
  283.                      buffer)
  284.                      start
  285.                      end))
  286.  
  287. (define (channel-write-block channel buffer start end)
  288.   (let loop ((start start) (n-left (- end start)))
  289.     (let ((n (channel-write channel buffer start end)))
  290.       (cond ((not n) (loop start n-left))
  291.         ((< n n-left) (loop (+ start n) (- n-left n)))))))
  292.  
  293. (define (channel-write-string-block channel string)
  294.   (channel-write-block channel string 0 (string-length string)))
  295.  
  296. (define (channel-write-char-block channel char)
  297.   (channel-write-block channel (string char) 0 1))
  298.  
  299. (define (channel-blocking? channel)
  300.   ((ucode-primitive channel-blocking? 1) (channel-descriptor channel)))
  301.  
  302. (define (channel-blocking channel)
  303.   ((ucode-primitive channel-blocking 1) (channel-descriptor channel)))
  304.  
  305. (define (channel-nonblocking channel)
  306.   ((ucode-primitive channel-nonblocking 1) (channel-descriptor channel)))
  307.  
  308. (define (with-channel-blocking channel blocking? thunk)
  309.   (if (channel-open? channel)
  310.       (let ((blocking-outside?))
  311.     (dynamic-wind
  312.      (lambda ()
  313.        (if (channel-open? channel)
  314.            (begin
  315.          (set! blocking-outside? (channel-blocking? channel))
  316.          (if blocking?
  317.              (channel-blocking channel)
  318.              (channel-nonblocking channel)))))
  319.      thunk
  320.      (lambda ()
  321.        (if (channel-open? channel)
  322.            (begin
  323.          (set! blocking? (channel-blocking? channel))
  324.          (if blocking-outside?
  325.              (channel-blocking channel)
  326.              (channel-nonblocking channel)))))))
  327.       (thunk)))
  328.  
  329. (define (channel-table)
  330.   (without-interrupts
  331.    (lambda ()
  332.      (let ((descriptors ((ucode-primitive channel-table 0))))
  333.        (and descriptors
  334.         (vector-map (lambda (descriptor)
  335.               (or (descriptor->channel descriptor)
  336.                   (make-channel descriptor)))
  337.             descriptors))))))
  338.  
  339. ;;;; File Primitives
  340.  
  341. (define (file-open primitive filename)
  342.   (let ((channel (open-channel (lambda (p) (primitive filename p)))))
  343.     (if (or (channel-type=directory? channel)
  344.         (channel-type=unknown? channel))
  345.     (begin
  346.       (channel-close channel)
  347.       (error:bad-range-argument filename primitive)))
  348.     channel))
  349.  
  350. (define (file-open-input-channel filename)
  351.   (file-open (ucode-primitive new-file-open-input-channel 2) filename))
  352.  
  353. (define (file-open-output-channel filename)
  354.   (file-open (ucode-primitive new-file-open-output-channel 2) filename))
  355.  
  356. (define (file-open-io-channel filename)
  357.   (file-open (ucode-primitive new-file-open-io-channel 2) filename))
  358.  
  359. (define (file-open-append-channel filename)
  360.   (file-open (ucode-primitive new-file-open-append-channel 2) filename))
  361.  
  362. (define (channel-file-length channel)
  363.   ((ucode-primitive file-length-new 1) (channel-descriptor channel)))
  364.  
  365. (define (channel-file-position channel)
  366.   ((ucode-primitive file-position 1) (channel-descriptor channel)))
  367.  
  368. (define (channel-file-set-position channel position)
  369.   ((ucode-primitive file-set-position 2) (channel-descriptor channel)
  370.                      position))
  371.  
  372. (define (make-pipe)
  373.   (without-interrupts
  374.    (lambda ()
  375.      (let ((pipe ((ucode-primitive make-pipe 0))))
  376.        (values (make-channel (car pipe))
  377.            (make-channel (cdr pipe)))))))
  378.  
  379. ;;;; Terminal Primitives
  380.  
  381. (define (tty-input-channel)
  382.   (without-interrupts
  383.    (lambda ()
  384.      (make-channel ((ucode-primitive tty-input-channel 0))))))
  385.  
  386. (define (tty-output-channel)
  387.   (without-interrupts
  388.    (lambda ()
  389.      (make-channel ((ucode-primitive tty-output-channel 0))))))
  390.  
  391. (define (terminal-get-state channel)
  392.   ((ucode-primitive terminal-get-state 1) (channel-descriptor channel)))
  393.  
  394. (define (terminal-set-state channel state)
  395.   ((ucode-primitive terminal-set-state 2) (channel-descriptor channel) state))
  396.  
  397. (define (terminal-cooked-input? channel)
  398.   ((ucode-primitive terminal-buffered? 1) (channel-descriptor channel)))
  399.  
  400. (define (terminal-cooked-input channel)
  401.   ((ucode-primitive terminal-buffered 1) (channel-descriptor channel)))
  402.  
  403. (define (terminal-raw-input channel)
  404.   ((ucode-primitive terminal-nonbuffered 1) (channel-descriptor channel)))
  405.  
  406. (define (terminal-cooked-output? channel)
  407.   ((ucode-primitive terminal-cooked-output? 1) (channel-descriptor channel)))
  408.  
  409. (define (terminal-cooked-output channel)
  410.   ((ucode-primitive terminal-cooked-output 1) (channel-descriptor channel)))
  411.  
  412. (define (terminal-raw-output channel)
  413.   ((ucode-primitive terminal-raw-output 1) (channel-descriptor channel)))
  414.  
  415. (define (terminal-flush-input channel)
  416.   ((ucode-primitive terminal-flush-input 1) (channel-descriptor channel)))
  417.  
  418. (define (terminal-flush-output channel)
  419.   ((ucode-primitive terminal-flush-output 1) (channel-descriptor channel)))
  420.  
  421. (define (terminal-drain-output channel)
  422.   ((ucode-primitive terminal-drain-output 1) (channel-descriptor channel)))
  423.  
  424. (define (terminal-input-baud-rate channel)
  425.   ((ucode-primitive baud-index->rate 1)
  426.    ((ucode-primitive terminal-get-ispeed 1) (channel-descriptor channel))))
  427.  
  428. (define (terminal-output-baud-rate channel)
  429.   ((ucode-primitive baud-index->rate 1)
  430.    ((ucode-primitive terminal-get-ospeed 1) (channel-descriptor channel))))
  431.  
  432. (define (set-terminal-input-baud-rate! channel baud)
  433.   ((ucode-primitive terminal-set-ispeed 2)
  434.    (channel-descriptor channel)
  435.    ((ucode-primitive baud-rate->index 1) baud)))
  436.  
  437. (define (set-terminal-output-baud-rate! channel baud)
  438.   ((ucode-primitive terminal-set-ospeed 2)
  439.    (channel-descriptor channel)
  440.    ((ucode-primitive baud-rate->index 1) baud)))
  441.  
  442. ;;;; PTY Master Primitives
  443.  
  444. (define (open-pty-master)
  445.   (without-interrupts
  446.    (lambda ()
  447.      (let ((result ((ucode-primitive open-pty-master 0))))
  448.        (values (make-channel (vector-ref result 0))
  449.            (vector-ref result 1)
  450.            (vector-ref result 2))))))
  451.  
  452. (define (pty-master-send-signal channel signal)
  453.   ((ucode-primitive pty-master-send-signal 2) (channel-descriptor channel)
  454.                           signal))
  455.  
  456. (define (pty-master-kill channel)
  457.   ((ucode-primitive pty-master-kill 1) (channel-descriptor channel)))
  458.  
  459. (define (pty-master-stop channel)
  460.   ((ucode-primitive pty-master-stop 1) (channel-descriptor channel)))
  461.  
  462. (define (pty-master-continue channel)
  463.   ((ucode-primitive pty-master-continue 1) (channel-descriptor channel)))
  464.  
  465. (define (pty-master-interrupt channel)
  466.   ((ucode-primitive pty-master-interrupt 1) (channel-descriptor channel)))
  467.  
  468. (define (pty-master-quit channel)
  469.   ((ucode-primitive pty-master-quit 1) (channel-descriptor channel)))
  470.  
  471. (define (pty-master-hangup channel)
  472.   ((ucode-primitive pty-master-hangup 1) (channel-descriptor channel)))
  473.  
  474. ;;;; Directory Primitives
  475.  
  476. (define-structure (directory-channel (conc-name directory-channel/))
  477.   descriptor)
  478.  
  479. (define (directory-channel-open name)
  480.   (without-interrupts
  481.    (lambda ()
  482.      (let ((descriptor ((ucode-primitive new-directory-open 1) name)))
  483.        (let ((channel (make-directory-channel descriptor)))
  484.      (add-to-gc-finalizer! open-directories channel descriptor)
  485.      channel)))))
  486.  
  487. (define (directory-channel-close channel)
  488.   (without-interrupts
  489.    (lambda ()
  490.      (if (directory-channel/descriptor channel)
  491.      (begin
  492.        (remove-from-gc-finalizer! open-directories channel)
  493.        (set-directory-channel/descriptor! channel #f))))))
  494.  
  495. (define (directory-channel-read channel)
  496.   ((ucode-primitive new-directory-read 1)
  497.    (directory-channel/descriptor channel)))
  498.  
  499. (define (directory-channel-read-matching channel prefix)
  500.   ((ucode-primitive new-directory-read-matching 2)
  501.    (directory-channel/descriptor channel)
  502.    prefix))
  503.  
  504. ;;;; Buffered Output
  505.  
  506. (define-structure (output-buffer
  507.            (conc-name output-buffer/)
  508.            (constructor %make-output-buffer))
  509.   (channel #f read-only #t)
  510.   string
  511.   position
  512.   line-translation            ; string that newline maps to
  513.   logical-size
  514.   closed?
  515.   line-start?)
  516.  
  517. (define (output-buffer-sizes translation buffer-size)
  518.   (let ((logical-size
  519.      (if (and translation (fix:< buffer-size 1))
  520.          1
  521.          buffer-size)))
  522.     (values logical-size
  523.         (if (not translation)
  524.         logical-size
  525.         (fix:+ logical-size
  526.                (fix:- (string-length translation) 1))))))
  527.  
  528. (define (make-output-buffer channel buffer-size #!optional line-translation)
  529.   (let ((translation
  530.      (if (or (default-object? line-translation)
  531.          ;; Kludge because of DEFAULT-OBJECT?:
  532.          (eq? 'DEFAULT line-translation))
  533.          (if (eq? 'TCP-STREAM-SOCKET (channel-type channel))
  534.          "\r\n"
  535.          (os/default-end-of-line-translation))
  536.          (if (and (string? line-translation)
  537.               (string=? "\n" line-translation))
  538.          #f
  539.          line-translation))))
  540.     (with-values (lambda () (output-buffer-sizes translation buffer-size))
  541.       (lambda (logical-size string-size)
  542.     (%make-output-buffer channel
  543.                  (and (fix:> string-size 0)
  544.                   (make-string string-size))
  545.                  0
  546.                  translation
  547.                  logical-size
  548.                  #f
  549.                  #t)))))
  550.  
  551. (define (output-buffer/close buffer associated-buffer)
  552.   (output-buffer/drain-block buffer)
  553.   (without-interrupts
  554.    (lambda ()
  555.      (set-output-buffer/closed?! buffer #t)
  556.      (let ((channel (output-buffer/channel buffer)))
  557.        (if (not (and (input-buffer? associated-buffer)
  558.              (eq? channel (input-buffer/channel associated-buffer))
  559.              (input-buffer/open? associated-buffer)))
  560.        (channel-close channel))))))
  561.  
  562. (define-integrable (output-buffer/open? buffer)
  563.   (not (output-buffer/closed? buffer)))
  564.  
  565. (define (output-buffer/size buffer)
  566.   (output-buffer/logical-size buffer))
  567.  
  568. (define (output-buffer/set-size buffer buffer-size)
  569.   (output-buffer/drain-block buffer)
  570.   (with-values
  571.       (lambda ()
  572.     (output-buffer-sizes (output-buffer/line-translation buffer)
  573.                  buffer-size))
  574.     (lambda (logical-size string-size)
  575.       (set-output-buffer/logical-size! buffer logical-size)
  576.       (set-output-buffer/string!
  577.        buffer
  578.        (and (fix:> string-size 0) (make-string string-size))))))
  579.  
  580. (define output-buffer/buffered-chars
  581.   output-buffer/position)
  582.  
  583. (define (output-buffer/write-substring buffer string start end)
  584.   (let ((name 'OUTPUT-BUFFER/WRITE-SUBSTRING))
  585.     (if (output-buffer/closed? buffer)
  586.     (error:bad-range-argument buffer name))
  587.     (cond ((string? string)
  588.        (if (not (index-fixnum? start))
  589.            (error:wrong-type-argument start "string index" name))
  590.        (if (not (index-fixnum? end))
  591.            (error:wrong-type-argument end "string index" name))
  592.        (if (not (fix:<= end (string-length string)))
  593.            (error:bad-range-argument end name))
  594.        (cond ((fix:< start end)
  595.           (output-buffer/write-substring-1 buffer string start end))
  596.          ((fix:= start end) 0)
  597.          (else (error:bad-range-argument start name))))
  598.       ((external-string? string)
  599.        (if (not (exact-nonnegative-integer? start))
  600.            (error:wrong-type-argument start "exact nonnegative integer"
  601.                       name))
  602.        (if (not (exact-nonnegative-integer? end))
  603.            (error:wrong-type-argument end "exact nonnegative integer"
  604.                       name))
  605.        (if (not (<= end (external-string-length string)))
  606.            (error:bad-range-argument end name))
  607.        (cond ((< start end)
  608.           (output-buffer/write-xsubstring buffer string start end))
  609.          ((= start end) 0)
  610.          (else (error:bad-range-argument start name))))
  611.       (else
  612.        (error:wrong-type-argument string "string" name)))))
  613.  
  614. (define (output-buffer/write-xsubstring buffer string start end)
  615.   (cond ((output-buffer/line-translation buffer)
  616.      (let* ((n 65536)
  617.         (b (make-string n)))
  618.        (let loop ((index start))
  619.          (if (< index end)
  620.          (let ((n-to-write (min (- end index) n)))
  621.            (xsubstring-move! string index (+ index n-to-write) b 0)
  622.            (let ((n-written
  623.               (output-buffer/write-substring-1 buffer
  624.                                b 0 n-to-write)))
  625.              (let ((index* (+ n-written index)))
  626.                (if (< n-written n-to-write)
  627.                (- index* start)
  628.                (loop index*)))))
  629.          (- index start)))))
  630.     ((and (output-buffer/string buffer)
  631.           (<= (- end start)
  632.           (fix:- (output-buffer/logical-size buffer)
  633.              (output-buffer/position buffer))))
  634.      (xsubstring-move! string start end
  635.                (output-buffer/string buffer)
  636.                (output-buffer/position buffer))
  637.      (set-output-buffer/position! buffer
  638.                       (fix:+ (output-buffer/position buffer)
  639.                          (- end start))))
  640.     (else
  641.      (output-buffer/drain-block buffer)
  642.      (or (channel-write (output-buffer/channel buffer) string start end)
  643.          0))))
  644.  
  645. (define (output-buffer/write-substring-1 buffer string start end)
  646.   (define (write-buffered start end n-previous)
  647.     (if (fix:< start end)
  648.     (let loop ((start start) (n-previous n-previous))
  649.       (let ((n-left (fix:- end start))
  650.         (max-posn (output-buffer/logical-size buffer)))
  651.         (let ((room (fix:- max-posn (output-buffer/position buffer))))
  652.           (cond ((fix:>= room n-left)
  653.              (add-to-buffer string start end)
  654.              (if (fix:= n-left room)
  655.              (output-buffer/drain buffer))
  656.              (fix:+ n-previous n-left))
  657.             ((fix:> room 0)
  658.              (let ((new-start (fix:+ start room))
  659.                (n-previous (fix:+ n-previous room)))
  660.                (add-to-buffer string start new-start)
  661.                (if (fix:< (output-buffer/drain buffer) max-posn)
  662.                (loop new-start n-previous)
  663.                n-previous)))
  664.             (else
  665.              (if (fix:< (output-buffer/drain buffer) max-posn)
  666.              (loop start n-previous)
  667.              n-previous))))))
  668.     n-previous))
  669.  
  670.   (define (write-newline)
  671.     ;; This transfers the end-of-line string atomically.  In this way,
  672.     ;; as far as the Scheme program is concerned, either the newline
  673.     ;; has been completely buffered/written, or it has not at all.
  674.     (let ((translation (output-buffer/line-translation buffer)))
  675.       (let ((tlen (string-length translation)))
  676.     (let loop ()
  677.       (let ((posn (output-buffer/position buffer)))
  678.         (if (fix:<= tlen
  679.             (fix:- (string-length (output-buffer/string buffer))
  680.                    posn))
  681.         (begin
  682.           (add-to-buffer translation 0 tlen)
  683.           #t)
  684.         (and (fix:< (output-buffer/drain buffer) posn)
  685.              (loop))))))))
  686.  
  687.   (define (add-to-buffer string start end)
  688.     (let ((posn (output-buffer/position buffer)))
  689.       (substring-move! string start end (output-buffer/string buffer) posn)
  690.       (set-output-buffer/position! buffer (fix:+ posn (fix:- end start)))))
  691.  
  692.   (let ((n-written
  693.      (cond ((not (output-buffer/string buffer))
  694.         (or (channel-write (output-buffer/channel buffer)
  695.                    string start end)
  696.             0))
  697.            ((not (output-buffer/line-translation buffer))
  698.         (write-buffered start end 0))
  699.            (else
  700.         (let loop ((start start) (n-prev 0))
  701.           (let find-newline ((index start))
  702.             (cond ((fix:= index end)
  703.                (write-buffered start end n-prev))
  704.               ((not (char=? (string-ref string index) #\newline))
  705.                (find-newline (fix:+ index 1)))
  706.               (else
  707.                (let ((n-prev* (write-buffered start index n-prev)))
  708.                  (if (or (fix:< n-prev*
  709.                         (fix:+ n-prev (fix:- start index)))
  710.                      (not (write-newline)))
  711.                  n-prev*
  712.                  (loop (fix:+ index 1)
  713.                        (fix:+ n-prev* 1))))))))))))
  714.     (if (fix:> n-written 0)
  715.     (set-output-buffer/line-start?!
  716.      buffer
  717.      (char=? #\newline
  718.          (string-ref string (fix:+ start (fix:- n-written 1))))))
  719.     n-written))
  720.  
  721. (define (output-buffer/drain buffer)
  722.   (let ((string (output-buffer/string buffer))
  723.     (position (output-buffer/position buffer)))
  724.     (if (or (not string) (zero? position) (output-buffer/closed? buffer))
  725.     0
  726.     (let ((n (channel-write
  727.           (output-buffer/channel buffer)
  728.           string
  729.           0
  730.           (let ((logical-size (output-buffer/logical-size buffer)))
  731.             (if (fix:> position logical-size)
  732.             logical-size
  733.             position)))))
  734.       (cond ((or (not n) (fix:= n 0))
  735.          position)
  736.         ((fix:< n position)
  737.          (let ((position* (fix:- position n)))
  738.            (substring-move! string n position string 0)
  739.            (set-output-buffer/position! buffer position*)
  740.            position*))
  741.         (else
  742.          (set-output-buffer/position! buffer 0)
  743.          0))))))
  744.  
  745. (define (output-buffer/flush buffer)
  746.   (set-output-buffer/position! buffer 0))
  747.  
  748. (define (output-buffer/drain-block buffer)
  749.   (let loop ()
  750.     (if (not (fix:= (output-buffer/drain buffer) 0))
  751.     (loop))))
  752.  
  753. (define (output-buffer/write-substring-block buffer string start end)
  754.   (do ((start start
  755.           (+ start
  756.          (output-buffer/write-substring buffer string start end))))
  757.       ((>= start end))))
  758.  
  759. (define (output-buffer/write-char-block buffer char)
  760.   (output-buffer/write-substring-block buffer (string char) 0 1))
  761.  
  762. ;;;; Buffered Input
  763.  
  764. (define-structure (input-buffer
  765.            (conc-name input-buffer/)
  766.            (constructor %make-input-buffer))
  767.   (channel #f read-only #t)
  768.   string
  769.   start-index
  770.   end-index
  771.   line-translation            ; string that maps to newline
  772.   ;; REAL-END is zero iff the buffer is closed.
  773.   real-end)
  774.  
  775. (define (input-buffer-size translation buffer-size)
  776.   (cond ((not translation)
  777.      (if (fix:< buffer-size 1)
  778.          1
  779.          buffer-size))
  780.     ((fix:< buffer-size (string-length translation))
  781.      (string-length translation))
  782.     (else
  783.      buffer-size)))
  784.  
  785. (define (make-input-buffer channel buffer-size #!optional line-translation)
  786.   (let* ((translation
  787.       (if (or (default-object? line-translation)
  788.           ;; Kludge because of DEFAULT-OBJECT?:
  789.           (eq? 'DEFAULT line-translation))
  790.           (if (eq? 'TCP-STREAM-SOCKET (channel-type channel))
  791.           "\r\n"
  792.           (os/default-end-of-line-translation))
  793.           (if (and (string? line-translation)
  794.                (string=? "\n" line-translation))
  795.           #f
  796.           line-translation)))
  797.      (string-size (input-buffer-size translation buffer-size)))
  798.     (%make-input-buffer channel
  799.             (make-string string-size)
  800.             string-size
  801.             string-size
  802.             translation
  803.             string-size)))
  804.  
  805. (define (input-buffer/close buffer associated-buffer)
  806.   (without-interrupts
  807.    (lambda ()
  808.      (set-input-buffer/real-end! buffer 0)
  809.      (let ((channel (input-buffer/channel buffer)))
  810.        (if (not (and (output-buffer? associated-buffer)
  811.              (eq? channel (output-buffer/channel associated-buffer))
  812.              (output-buffer/open? associated-buffer)))
  813.        (channel-close channel))))))
  814.  
  815. (define-integrable (input-buffer/closed? buffer)
  816.   (fix:= 0 (input-buffer/real-end buffer)))
  817.  
  818. (define-integrable (input-buffer/open? buffer)
  819.   (not (input-buffer/closed? buffer)))
  820.  
  821. (define (input-buffer/size buffer)
  822.   (string-length (input-buffer/string buffer)))
  823.  
  824. (define (input-buffer/set-size buffer buffer-size)
  825.   ;; Returns the actual buffer size, which may be different from the arg.
  826.   ;; Discards any buffered characters.
  827.   (without-interrupts
  828.    (lambda ()
  829.      (if (input-buffer/closed? buffer)
  830.      0
  831.      (let ((string-size
  832.         (input-buffer-size (input-buffer/line-translation buffer)
  833.                    buffer-size)))
  834.        (let ((old-string (input-buffer/string buffer))
  835.          (delta (fix:- (input-buffer/real-end buffer)
  836.                    (input-buffer/end-index buffer))))
  837.          (set-input-buffer/string! buffer (make-string string-size))
  838.          (let ((logical-end
  839.             (if (fix:zero? delta)
  840.             string-size
  841.             (let ((logical-end (fix:- string-size delta)))
  842.               (substring-move! old-string
  843.                        (input-buffer/end-index buffer)
  844.                        (input-buffer/real-end buffer)
  845.                        (input-buffer/string buffer)
  846.                        logical-end)
  847.               logical-end))))
  848.            (set-input-buffer/start-index! buffer logical-end)
  849.            (set-input-buffer/end-index! buffer logical-end)
  850.            (set-input-buffer/real-end! buffer string-size)
  851.            string-size)))))))
  852.  
  853. (define (input-buffer/flush buffer)
  854.   (without-interrupts
  855.    (lambda ()
  856.      (set-input-buffer/start-index! buffer (input-buffer/end-index buffer)))))
  857.  
  858. (define (input-buffer/buffered-chars buffer)
  859.   (without-interrupts
  860.    (lambda ()
  861.      (fix:- (input-buffer/end-index buffer)
  862.         (input-buffer/start-index buffer)))))
  863.  
  864. (define (input-buffer/fill buffer)
  865.   ;; Assumption:
  866.   ;; (and (input-buffer/open? buffer)
  867.   ;;      (fix:= (input-buffer/start-index buffer)
  868.   ;;             (input-buffer/end-index buffer)))
  869.   (let ((delta
  870.      (fix:- (input-buffer/real-end buffer)
  871.         (input-buffer/end-index buffer)))
  872.     (string (input-buffer/string buffer)))
  873.     (if (not (fix:= delta 0))
  874.     (substring-move! string
  875.              (input-buffer/end-index buffer)
  876.              (input-buffer/real-end buffer)
  877.              string
  878.              0))
  879.     (let ((n-read
  880.        (channel-read (input-buffer/channel buffer)
  881.              string delta (string-length string))))
  882.       (and n-read
  883.        (input-buffer/after-fill! buffer (fix:+ delta n-read))))))
  884.  
  885. (define (input-buffer/after-fill! buffer end-index)
  886.   (set-input-buffer/start-index! buffer 0)
  887.   (set-input-buffer/end-index! buffer end-index)
  888.   (set-input-buffer/real-end! buffer end-index)
  889.   (if (and (input-buffer/line-translation buffer)
  890.        (not (fix:= end-index 0)))
  891.       (input-buffer/translate! buffer)
  892.       end-index))
  893.  
  894. (define-integrable (input-buffer/fill* buffer)
  895.   (let ((n (input-buffer/fill buffer)))
  896.     (and n
  897.      (fix:> n 0))))
  898.  
  899. (define (input-buffer/chars-remaining buffer)
  900.   (without-interrupts
  901.    (lambda ()
  902.      (and (input-buffer/open? buffer)
  903.       (not (input-buffer/line-translation buffer))
  904.       (let ((channel (input-buffer/channel buffer)))
  905.         (and (channel-type=file? channel)
  906.          (let ((n
  907.             (fix:- (channel-file-length channel)
  908.                    (channel-file-position channel))))
  909.            (and (fix:>= n 0)
  910.             (fix:+ (input-buffer/buffered-chars buffer) n)))))))))
  911.  
  912. (define (input-buffer/char-ready? buffer interval)
  913.   (without-interrupts
  914.    (lambda ()
  915.      (char-ready? buffer
  916.        (lambda (buffer)
  917.      (with-channel-blocking (input-buffer/channel buffer) #f
  918.        (lambda ()
  919.          (if (positive? interval)
  920.          (let ((timeout (+ (real-time-clock) interval)))
  921.            (let loop ()
  922.              (let ((n (input-buffer/fill buffer)))
  923.                (if n
  924.                (fix:> n 0)
  925.                (and (< (real-time-clock) timeout)
  926.                 (loop))))))
  927.          (input-buffer/fill* buffer)))))))))
  928.  
  929. (define (char-ready? buffer fill)
  930.   (and (input-buffer/open? buffer)
  931.        (or (fix:< (input-buffer/start-index buffer)
  932.           (input-buffer/end-index buffer))
  933.        (fill buffer))))
  934.  
  935. (define (input-buffer/eof? buffer)
  936.   ;; This returns #t iff it knows that it is at EOF.
  937.   ;; If BUFFER is non-blocking with no input available, it returns #f.
  938.   (and (not (input-buffer/char-ready? buffer 0))
  939.        (input-buffer/closed? buffer)))
  940.  
  941. (define (input-buffer/translate! buffer)
  942.   (with-values
  943.       (lambda ()
  944.     (substring/input-translate! (input-buffer/string buffer)
  945.                     (input-buffer/line-translation buffer)
  946.                     0
  947.                     (input-buffer/real-end buffer)))
  948.     (lambda (logical-end real-end)
  949.       (set-input-buffer/end-index! buffer logical-end)
  950.       (set-input-buffer/real-end! buffer real-end)
  951.       (and (fix:> logical-end 0) logical-end))))
  952.  
  953. (define (substring/input-translate! string translation start end)
  954.   ;; This maps a multi-character (perhaps only 1) sequence into a
  955.   ;; single newline character.
  956.   (let ((tlen (string-length translation))
  957.     (match (string-ref translation 0)))
  958.  
  959.     (define (find-loop index)
  960.       (cond ((fix:= index end)
  961.          (values index index))
  962.         ((char=? match (string-ref string index))
  963.          (case (verify index)
  964.            ((#F) (find-loop (fix:+ index 1)))
  965.            ((TOO-SHORT) (values index end))
  966.            (else (clobber-loop index (fix:+ index tlen)))))
  967.         (else
  968.          (find-loop (fix:+ index 1)))))
  969.  
  970.     (define verify
  971.       (if (fix:= tlen 2)
  972.       (lambda (index)
  973.         (let ((index (fix:+ index 1)))
  974.           (if (fix:= index end)
  975.           'TOO-SHORT
  976.           (char=? (string-ref translation 1)
  977.               (string-ref string index)))))
  978.       (lambda (index)
  979.         (let loop ((tind 1) (index (fix:+ index 1)))
  980.           (cond ((fix:= tind tlen)
  981.              #t)
  982.             ((fix:= index end)
  983.              'TOO-SHORT)
  984.             (else
  985.              (and (char=? (string-ref translation tind)
  986.                   (string-ref string index))
  987.               (loop (fix:+ tind 1)
  988.                 (fix:+ index 1)))))))))
  989.  
  990.     (define (clobber-loop target source)
  991.       ;; Found one match, continue looking at source
  992.       (string-set! string target #\newline)
  993.       (let find-next ((target (fix:+ target 1)) (source source))
  994.     (cond ((fix:= source end)
  995.            ;; Pointers in sync.
  996.            (values target target))
  997.           ((char=? match (string-ref string source))
  998.            (case (verify source)
  999.          ((#F)
  1000.           (string-set! string target (string-ref string source))
  1001.           (find-next (fix:+ target 1) (fix:+ source 1)))
  1002.          ((TOO-SHORT)
  1003.           ;; Pointers not in sync: buffer ends in what might
  1004.           ;; be the middle of a translation sequence.
  1005.           (do ((target* target (fix:+ target* 1))
  1006.                (source source (fix:+ source 1)))
  1007.               ((fix:= source end)
  1008.                (values target target*))
  1009.             (string-set! string target* (string-ref string source))))
  1010.          (else
  1011.           (clobber-loop target (fix:+ source tlen)))))
  1012.           (else
  1013.            (string-set! string target (string-ref string source))
  1014.            (find-next (fix:+ target 1) (fix:+ source 1))))))
  1015.  
  1016.     (find-loop start)))
  1017.  
  1018. (define (input-buffer/read-char buffer)
  1019.   (without-interrupts
  1020.    (lambda ()
  1021.      (let ((start-index (input-buffer/start-index buffer)))
  1022.        (cond ((fix:< start-index (input-buffer/end-index buffer))
  1023.           (set-input-buffer/start-index! buffer (fix:+ start-index 1))
  1024.           (string-ref (input-buffer/string buffer) start-index))
  1025.          ((input-buffer/closed? buffer)
  1026.           eof-object)
  1027.          (else
  1028.           (let ((n (input-buffer/fill buffer)))
  1029.         (cond ((not n) #f)
  1030.               ((fix:= n 0) eof-object)
  1031.               (else
  1032.                (set-input-buffer/start-index! buffer 1)
  1033.                (string-ref (input-buffer/string buffer) 0))))))))))
  1034.  
  1035. (define (input-buffer/peek-char buffer)
  1036.   (without-interrupts
  1037.    (lambda ()
  1038.      (let ((start-index (input-buffer/start-index buffer)))
  1039.        (cond ((fix:< start-index (input-buffer/end-index buffer))
  1040.           (string-ref (input-buffer/string buffer) start-index))
  1041.          ((input-buffer/closed? buffer)
  1042.           eof-object)
  1043.          (else
  1044.           (let ((n (input-buffer/fill buffer)))
  1045.         (cond ((not n) #f)
  1046.               ((fix:= n 0) eof-object)
  1047.               (else
  1048.                (string-ref (input-buffer/string buffer) 0))))))))))
  1049.  
  1050. (define (input-buffer/discard-char buffer)
  1051.   (without-interrupts
  1052.    (lambda ()
  1053.      (let ((start-index (input-buffer/start-index buffer)))
  1054.        (cond ((fix:< start-index (input-buffer/end-index buffer))
  1055.           (set-input-buffer/start-index! buffer (fix:+ start-index 1)))
  1056.          ((input-buffer/open? buffer)
  1057.           (if (let ((n (input-buffer/fill buffer)))
  1058.             (and n
  1059.              (not (fix:= n 0))))
  1060.           (set-input-buffer/start-index! buffer 1))))))))
  1061.  
  1062. (define (input-buffer/read-substring buffer string start end)
  1063.   (define (transfer-input-buffer index)
  1064.     (let ((bstart (input-buffer/start-index buffer))
  1065.       (bend (input-buffer/end-index buffer)))
  1066.       (cond ((fix:< bstart bend)
  1067.          (let ((bstring (input-buffer/string buffer))
  1068.            (available (fix:- bend bstart))
  1069.            (needed (- end index)))
  1070.            (if (>= available needed)
  1071.            (begin
  1072.              (let ((bend (fix:+ bstart needed)))
  1073.                (substring-move! bstring bstart bend string index)
  1074.                (set-input-buffer/start-index! buffer bend))
  1075.              end)
  1076.            (begin
  1077.              (substring-move! bstring bstart bend string index)
  1078.              (set-input-buffer/start-index! buffer bend)
  1079.              (if (input-buffer/char-ready? buffer 0)
  1080.              (transfer-input-buffer (+ index available))
  1081.              (+ index available))))))
  1082.         ((input-buffer/closed? buffer)
  1083.          index)
  1084.         (else
  1085.          (read-directly index)))))
  1086.  
  1087.   (define (read-directly index)
  1088.     (if (and (not (input-buffer/line-translation buffer))
  1089.          (>= (- end index) (input-buffer/size buffer)))
  1090.     (let ((n
  1091.            (channel-read (input-buffer/channel buffer) string index end)))
  1092.       (if n
  1093.           (+ index n)
  1094.           (and (not (= index start)) index)))
  1095.     (if (input-buffer/fill buffer)
  1096.         (transfer-input-buffer index)
  1097.         (and (not (= index start)) index))))
  1098.  
  1099.   (without-interrupts
  1100.    (lambda ()
  1101.      (let ((index (transfer-input-buffer start)))
  1102.        (and index
  1103.         (- index start))))))
  1104.  
  1105. (define (input-buffer/read-until-delimiter buffer delimiters)
  1106.   (without-interrupts
  1107.    (lambda ()
  1108.      (if (and (input-buffer/open? buffer)
  1109.           (char-ready? buffer input-buffer/fill-block))
  1110.      (apply string-append
  1111.         (let ((string (input-buffer/string buffer)))
  1112.           (let loop ()
  1113.             (let ((start (input-buffer/start-index buffer))
  1114.               (end (input-buffer/end-index buffer)))
  1115.               (let ((delimiter
  1116.                  (substring-find-next-char-in-set
  1117.                   string start end delimiters)))
  1118.             (if delimiter
  1119.                 (let ((head (substring string start delimiter)))
  1120.                   (set-input-buffer/start-index! buffer
  1121.                                  delimiter)
  1122.                   (list head))
  1123.                 (let ((head (substring string start end)))
  1124.                   (set-input-buffer/start-index! buffer end)
  1125.                   (cons head
  1126.                     (if (input-buffer/fill-block buffer)
  1127.                     (loop)
  1128.                     '())))))))))
  1129.      eof-object))))
  1130.  
  1131. (define (input-buffer/discard-until-delimiter buffer delimiters)
  1132.   (without-interrupts
  1133.    (lambda ()
  1134.      (if (and (input-buffer/open? buffer)
  1135.           (char-ready? buffer input-buffer/fill-block))
  1136.      (let ((string (input-buffer/string buffer)))
  1137.        (let loop ()
  1138.          (let ((end-index (input-buffer/end-index buffer)))
  1139.            (let ((index
  1140.               (substring-find-next-char-in-set
  1141.                string
  1142.                (input-buffer/start-index buffer)
  1143.                end-index
  1144.                delimiters)))
  1145.          (if index
  1146.              (set-input-buffer/start-index! buffer index)
  1147.              (begin
  1148.                (set-input-buffer/start-index! buffer end-index)
  1149.                (if (input-buffer/fill-block buffer)
  1150.                (loop))))))))))))
  1151.  
  1152. (define (input-buffer/fill-block buffer)
  1153.   (fix:> (let loop () (or (input-buffer/fill buffer) (loop))) 0))
  1154.  
  1155. (define (input-buffer/buffer-contents buffer)
  1156.   (without-interrupts
  1157.    (lambda ()
  1158.      (and (fix:< (input-buffer/start-index buffer)
  1159.          (input-buffer/end-index buffer))
  1160.       (substring (input-buffer/string buffer)
  1161.              (input-buffer/start-index buffer)
  1162.              (input-buffer/end-index buffer))))))
  1163.  
  1164. (define (input-buffer/set-buffer-contents buffer contents)
  1165.   (without-interrupts
  1166.    (lambda ()
  1167.      (let ((contents-size (string-length contents)))
  1168.        (if (fix:> contents-size 0)
  1169.        (let ((string (input-buffer/string buffer)))
  1170.          (if (fix:> contents-size (string-length string))
  1171.          (input-buffer/set-size buffer contents-size))
  1172.          (substring-move! contents 0 contents-size string 0)
  1173.          (input-buffer/after-fill! buffer contents-size)))))))