;;; Ports
;;; Copyright (C) 2016,2019,2021,2024 Free Software Foundation, Inc.
;;;
;;; This library is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU Lesser General Public License as
;;; published by the Free Software Foundation, either version 3 of the
;;; License, or (at your option) any later version.
;;;
;;; This library is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Lesser General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General Public
;;; License along with this program.  If not, see
;;; <http://www.gnu.org/licenses/>.

;;; Commentary:
;;;
;;; Implementation of input/output routines over ports.
;;;
;;; Note that loading this module overrides some core bindings; see the
;;; `replace-bootstrap-bindings' invocation below for details.
;;;
;;; Code:


(define-module (ice-9 ports)
  #:export (;; Definitions from ports.c.
            %port-property
            %set-port-property!
            current-input-port current-output-port
            current-error-port current-warning-port
            current-load-port
            set-current-input-port set-current-output-port
            set-current-error-port
            port-mode
            port?
            input-port?
            output-port?
            port-closed?
            eof-object?
            close-port
            close-input-port
            close-output-port
            ;; These two are currently defined by scm_init_ports; fix?
            ;; %default-port-encoding
            ;; %default-port-conversion-strategy
            port-encoding
            set-port-encoding!
            port-conversion-strategy
            set-port-conversion-strategy!
            read-char
            peek-char
            unread-char
            unread-string
            setvbuf
            drain-input
            force-output
            char-ready?
            seek SEEK_SET SEEK_CUR SEEK_END
            truncate-file
            port-line
            set-port-line!
            port-column
            set-port-column!
            port-filename
            set-port-filename!
            port-for-each
            flush-all-ports
            %make-void-port

            ;; Definitions from fports.c.
            open-file
            file-port?
            port-revealed
            set-port-revealed!
            adjust-port-revealed!
            ;; note: %file-port-name-canonicalization is used in boot-9

            ;; Definitions from ioext.c.
            ftell
            redirect-port
            dup->fdes
            dup2
            fileno
            isatty?
            fdopen
            primitive-move->fdes
            fdes->ports

            ;; Definitions in Scheme
            file-position
            file-set-position
            move->fdes
            release-port-handle
            dup->port
            dup->inport
            dup->outport
            dup
            duplicate-port
            fdes->inport
            fdes->outport
            port->fdes
            OPEN_READ OPEN_WRITE OPEN_BOTH
            *null-device*
            open-input-file
            open-output-file
            open-io-file
            call-with-port
            call-with-input-file
            call-with-output-file
            with-input-from-port
            with-output-to-port
            with-error-to-port
            with-input-from-file
            with-output-to-file
            with-error-to-file
            call-with-input-string
            with-input-from-string
            call-with-output-string
            with-output-to-string
            with-error-to-string
            the-eof-object
            inherit-print-state))

(define (replace-bootstrap-bindings syms)
  (for-each
   (lambda (sym)
     (let* ((var (module-variable the-scm-module sym))
            (mod (current-module))
            (iface (module-public-interface mod)))
       (unless var (error "unbound in root module" sym))
       (module-add! mod sym var)
       (when (module-local-variable iface sym)
         (module-add! iface sym var))))
   syms))

(replace-bootstrap-bindings '(open-file
                              open-input-file
                              set-port-encoding!
                              eof-object?
                              force-output
                              call-with-output-string
                              close-port
                              current-error-port
                              current-warning-port))

(load-extension (string-append "libguile-" (effective-version))
                "scm_init_ice_9_ports")
(load-extension (string-append "libguile-" (effective-version))
                "scm_init_ice_9_fports")
(load-extension (string-append "libguile-" (effective-version))
                "scm_init_ice_9_ioext")

(eval-when (load eval expand)
  (when (defined? 'SEEK_DATA)
    (module-export! (current-module) '(SEEK_DATA)))
  (when (defined? 'SEEK_HOLE)
    (module-export! (current-module) '(SEEK_HOLE))))

