ports.scm 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. ;;; Ports
  2. ;;; Copyright (C) 2016 Free Software Foundation, Inc.
  3. ;;;
  4. ;;; This library is free software: you can redistribute it and/or modify
  5. ;;; it under the terms of the GNU Lesser General Public License as
  6. ;;; published by the Free Software Foundation, either version 3 of the
  7. ;;; License, or (at your option) any later version.
  8. ;;;
  9. ;;; This library is distributed in the hope that it will be useful, but
  10. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;; Lesser General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU Lesser General Public
  15. ;;; License along with this program. If not, see
  16. ;;; <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;;;
  19. ;;; Implementation of input/output routines over ports.
  20. ;;;
  21. ;;; Note that loading this module overrides some core bindings; see the
  22. ;;; `replace-bootstrap-bindings' invocation below for details.
  23. ;;;
  24. ;;; Code:
  25. (define-module (ice-9 ports)
  26. #:export (;; Definitions from ports.c.
  27. %port-property
  28. %set-port-property!
  29. current-input-port current-output-port
  30. current-error-port current-warning-port
  31. set-current-input-port set-current-output-port
  32. set-current-error-port
  33. port-mode
  34. port?
  35. input-port?
  36. output-port?
  37. port-closed?
  38. eof-object?
  39. close-port
  40. close-input-port
  41. close-output-port
  42. ;; These two are currently defined by scm_init_ports; fix?
  43. ;; %default-port-encoding
  44. ;; %default-port-conversion-strategy
  45. port-encoding
  46. set-port-encoding!
  47. port-conversion-strategy
  48. set-port-conversion-strategy!
  49. read-char
  50. peek-char
  51. unread-char
  52. unread-string
  53. setvbuf
  54. drain-input
  55. force-output
  56. char-ready?
  57. seek SEEK_SET SEEK_CUR SEEK_END
  58. truncate-file
  59. port-line
  60. set-port-line!
  61. port-column
  62. set-port-column!
  63. port-filename
  64. set-port-filename!
  65. port-for-each
  66. flush-all-ports
  67. %make-void-port
  68. ;; Definitions from fports.c.
  69. open-file
  70. file-port?
  71. port-revealed
  72. set-port-revealed!
  73. adjust-port-revealed!
  74. ;; note: %file-port-name-canonicalization is used in boot-9
  75. ;; Definitions from ioext.c.
  76. ftell
  77. redirect-port
  78. dup->fdes
  79. dup2
  80. fileno
  81. isatty?
  82. fdopen
  83. primitive-move->fdes
  84. fdes->ports
  85. ;; Definitions in Scheme
  86. file-position
  87. file-set-position
  88. move->fdes
  89. release-port-handle
  90. dup->port
  91. dup->inport
  92. dup->outport
  93. dup
  94. duplicate-port
  95. fdes->inport
  96. fdes->outport
  97. port->fdes
  98. OPEN_READ OPEN_WRITE OPEN_BOTH
  99. *null-device*
  100. open-input-file
  101. open-output-file
  102. open-io-file
  103. call-with-input-file
  104. call-with-output-file
  105. with-input-from-port
  106. with-output-to-port
  107. with-error-to-port
  108. with-input-from-file
  109. with-output-to-file
  110. with-error-to-file
  111. call-with-input-string
  112. with-input-from-string
  113. call-with-output-string
  114. with-output-to-string
  115. with-error-to-string
  116. the-eof-object
  117. inherit-print-state))
  118. (define (replace-bootstrap-bindings syms)
  119. (for-each
  120. (lambda (sym)
  121. (let* ((var (module-variable the-scm-module sym))
  122. (mod (current-module))
  123. (iface (module-public-interface mod)))
  124. (unless var (error "unbound in root module" sym))
  125. (module-add! mod sym var)
  126. (when (module-local-variable iface sym)
  127. (module-add! iface sym var))))
  128. syms))
  129. (replace-bootstrap-bindings '(open-file
  130. open-input-file
  131. set-port-encoding!
  132. eof-object?
  133. force-output
  134. call-with-output-string
  135. close-port
  136. current-error-port
  137. current-warning-port))
  138. (load-extension (string-append "libguile-" (effective-version))
  139. "scm_init_ice_9_ports")
  140. (load-extension (string-append "libguile-" (effective-version))
  141. "scm_init_ice_9_fports")
  142. (load-extension (string-append "libguile-" (effective-version))
  143. "scm_init_ice_9_ioext")
  144. (define (port-encoding port)
  145. "Return, as a string, the character encoding that @var{port} uses to
  146. interpret its input and output."
  147. (symbol->string (%port-encoding port)))
  148. (define-module (ice-9 ports internal)
  149. #:use-module (ice-9 ports)
  150. #:export (port-read-buffer
  151. port-write-buffer
  152. port-auxiliary-write-buffer
  153. port-line-buffered?
  154. expand-port-read-buffer!
  155. port-buffer-bytevector
  156. port-buffer-cur
  157. port-buffer-end
  158. port-buffer-has-eof?
  159. port-buffer-position
  160. set-port-buffer-cur!
  161. set-port-buffer-end!
  162. set-port-buffer-has-eof?!
  163. port-position-line
  164. port-position-column
  165. set-port-position-line!
  166. set-port-position-column!
  167. port-read
  168. port-write
  169. port-clear-stream-start-for-bom-read
  170. port-clear-stream-start-for-bom-write
  171. %port-encoding
  172. specialize-port-encoding!
  173. port-random-access?
  174. port-decode-char
  175. port-encode-char
  176. port-encode-chars
  177. port-read-buffering
  178. port-poll
  179. port-read-wait-fd
  180. port-write-wait-fd
  181. put-char
  182. put-string))
  183. (define-syntax-rule (port-buffer-bytevector buf) (vector-ref buf 0))
  184. (define-syntax-rule (port-buffer-cur buf) (vector-ref buf 1))
  185. (define-syntax-rule (port-buffer-end buf) (vector-ref buf 2))
  186. (define-syntax-rule (port-buffer-has-eof? buf) (vector-ref buf 3))
  187. (define-syntax-rule (port-buffer-position buf) (vector-ref buf 4))
  188. (define-syntax-rule (set-port-buffer-cur! buf cur)
  189. (vector-set! buf 1 cur))
  190. (define-syntax-rule (set-port-buffer-end! buf end)
  191. (vector-set! buf 2 end))
  192. (define-syntax-rule (set-port-buffer-has-eof?! buf has-eof?)
  193. (vector-set! buf 3 has-eof?))
  194. (define-syntax-rule (port-position-line position)
  195. (car position))
  196. (define-syntax-rule (port-position-column position)
  197. (cdr position))
  198. (define-syntax-rule (set-port-position-line! position line)
  199. (set-car! position line))
  200. (define-syntax-rule (set-port-position-column! position column)
  201. (set-cdr! position column))
  202. (eval-when (expand)
  203. (define-syntax-rule (private-port-bindings binding ...)
  204. (begin
  205. (define binding (@@ (ice-9 ports) binding))
  206. ...)))
  207. (private-port-bindings port-read-buffer
  208. port-write-buffer
  209. port-auxiliary-write-buffer
  210. port-line-buffered?
  211. expand-port-read-buffer!
  212. port-read
  213. port-write
  214. port-clear-stream-start-for-bom-read
  215. port-clear-stream-start-for-bom-write
  216. %port-encoding
  217. specialize-port-encoding!
  218. port-decode-char
  219. port-encode-char
  220. port-encode-chars
  221. port-random-access?
  222. port-read-buffering
  223. port-poll
  224. port-read-wait-fd
  225. port-write-wait-fd
  226. put-char
  227. put-string)
  228. ;; And we're back.
  229. (define-module (ice-9 ports))
  230. ;;; Current ports as parameters.
  231. ;;;
  232. (define current-input-port
  233. (fluid->parameter %current-input-port-fluid
  234. (lambda (x)
  235. (unless (input-port? x)
  236. (error "expected an input port" x))
  237. x)))
  238. (define current-output-port
  239. (fluid->parameter %current-output-port-fluid
  240. (lambda (x)
  241. (unless (output-port? x)
  242. (error "expected an output port" x))
  243. x)))
  244. (define current-error-port
  245. (fluid->parameter %current-error-port-fluid
  246. (lambda (x)
  247. (unless (output-port? x)
  248. (error "expected an output port" x))
  249. x)))
  250. (define current-warning-port
  251. (fluid->parameter %current-warning-port-fluid
  252. (lambda (x)
  253. (unless (output-port? x)
  254. (error "expected an output port" x))
  255. x)))
  256. ;;; {File Descriptors and Ports}
  257. ;;;
  258. (define file-position ftell)
  259. (define* (file-set-position port offset #:optional (whence SEEK_SET))
  260. (seek port offset whence))
  261. (define (move->fdes fd/port fd)
  262. (cond ((integer? fd/port)
  263. (dup->fdes fd/port fd)
  264. (close fd/port)
  265. fd)
  266. (else
  267. (primitive-move->fdes fd/port fd)
  268. (set-port-revealed! fd/port 1)
  269. fd/port)))
  270. (define (release-port-handle port)
  271. (let ((revealed (port-revealed port)))
  272. (if (> revealed 0)
  273. (set-port-revealed! port (- revealed 1)))))
  274. (define dup->port
  275. (case-lambda
  276. ((port/fd mode)
  277. (fdopen (dup->fdes port/fd) mode))
  278. ((port/fd mode new-fd)
  279. (let ((port (fdopen (dup->fdes port/fd new-fd) mode)))
  280. (set-port-revealed! port 1)
  281. port))))
  282. (define dup->inport
  283. (case-lambda
  284. ((port/fd)
  285. (dup->port port/fd "r"))
  286. ((port/fd new-fd)
  287. (dup->port port/fd "r" new-fd))))
  288. (define dup->outport
  289. (case-lambda
  290. ((port/fd)
  291. (dup->port port/fd "w"))
  292. ((port/fd new-fd)
  293. (dup->port port/fd "w" new-fd))))
  294. (define dup
  295. (case-lambda
  296. ((port/fd)
  297. (if (integer? port/fd)
  298. (dup->fdes port/fd)
  299. (dup->port port/fd (port-mode port/fd))))
  300. ((port/fd new-fd)
  301. (if (integer? port/fd)
  302. (dup->fdes port/fd new-fd)
  303. (dup->port port/fd (port-mode port/fd) new-fd)))))
  304. (define (duplicate-port port modes)
  305. (dup->port port modes))
  306. (define (fdes->inport fdes)
  307. (let loop ((rest-ports (fdes->ports fdes)))
  308. (cond ((null? rest-ports)
  309. (let ((result (fdopen fdes "r")))
  310. (set-port-revealed! result 1)
  311. result))
  312. ((input-port? (car rest-ports))
  313. (set-port-revealed! (car rest-ports)
  314. (+ (port-revealed (car rest-ports)) 1))
  315. (car rest-ports))
  316. (else
  317. (loop (cdr rest-ports))))))
  318. (define (fdes->outport fdes)
  319. (let loop ((rest-ports (fdes->ports fdes)))
  320. (cond ((null? rest-ports)
  321. (let ((result (fdopen fdes "w")))
  322. (set-port-revealed! result 1)
  323. result))
  324. ((output-port? (car rest-ports))
  325. (set-port-revealed! (car rest-ports)
  326. (+ (port-revealed (car rest-ports)) 1))
  327. (car rest-ports))
  328. (else
  329. (loop (cdr rest-ports))))))
  330. (define (port->fdes port)
  331. (set-port-revealed! port (+ (port-revealed port) 1))
  332. (fileno port))
  333. ;; Legacy interfaces.
  334. (define (set-current-input-port port)
  335. "Set the current default input port to @var{port}."
  336. (current-input-port port))
  337. (define (set-current-output-port port)
  338. "Set the current default output port to @var{port}."
  339. (current-output-port port))
  340. (define (set-current-error-port port)
  341. "Set the current default error port to @var{port}."
  342. (current-error-port port))
  343. ;;;; high level routines
  344. ;;; {High-Level Port Routines}
  345. ;;;
  346. ;; These are used to request the proper mode to open files in.
  347. ;;
  348. (define OPEN_READ "r")
  349. (define OPEN_WRITE "w")
  350. (define OPEN_BOTH "r+")
  351. (define *null-device* "/dev/null")
  352. (define* (open-input-file
  353. file #:key (binary #f) (encoding #f) (guess-encoding #f))
  354. "Takes a string naming an existing file and returns an input port
  355. capable of delivering characters from the file. If the file
  356. cannot be opened, an error is signalled."
  357. (open-file file (if binary "rb" "r")
  358. #:encoding encoding
  359. #:guess-encoding guess-encoding))
  360. (define* (open-output-file file #:key (binary #f) (encoding #f))
  361. "Takes a string naming an output file to be created and returns an
  362. output port capable of writing characters to a new file by that
  363. name. If the file cannot be opened, an error is signalled. If a
  364. file with the given name already exists, the effect is unspecified."
  365. (open-file file (if binary "wb" "w")
  366. #:encoding encoding))
  367. (define (open-io-file str)
  368. "Open file with name STR for both input and output."
  369. (open-file str OPEN_BOTH))
  370. (define* (call-with-input-file
  371. file proc #:key (binary #f) (encoding #f) (guess-encoding #f))
  372. "PROC should be a procedure of one argument, and FILE should be a
  373. string naming a file. The file must
  374. already exist. These procedures call PROC
  375. with one argument: the port obtained by opening the named file for
  376. input or output. If the file cannot be opened, an error is
  377. signalled. If the procedure returns, then the port is closed
  378. automatically and the values yielded by the procedure are returned.
  379. If the procedure does not return, then the port will not be closed
  380. automatically unless it is possible to prove that the port will
  381. never again be used for a read or write operation."
  382. (let ((p (open-input-file file
  383. #:binary binary
  384. #:encoding encoding
  385. #:guess-encoding guess-encoding)))
  386. (call-with-values
  387. (lambda () (proc p))
  388. (lambda vals
  389. (close-input-port p)
  390. (apply values vals)))))
  391. (define* (call-with-output-file file proc #:key (binary #f) (encoding #f))
  392. "PROC should be a procedure of one argument, and FILE should be a
  393. string naming a file. The behaviour is unspecified if the file
  394. already exists. These procedures call PROC
  395. with one argument: the port obtained by opening the named file for
  396. input or output. If the file cannot be opened, an error is
  397. signalled. If the procedure returns, then the port is closed
  398. automatically and the values yielded by the procedure are returned.
  399. If the procedure does not return, then the port will not be closed
  400. automatically unless it is possible to prove that the port will
  401. never again be used for a read or write operation."
  402. (let ((p (open-output-file file #:binary binary #:encoding encoding)))
  403. (call-with-values
  404. (lambda () (proc p))
  405. (lambda vals
  406. (close-output-port p)
  407. (apply values vals)))))
  408. (define (with-input-from-port port thunk)
  409. (parameterize ((current-input-port port))
  410. (thunk)))
  411. (define (with-output-to-port port thunk)
  412. (parameterize ((current-output-port port))
  413. (thunk)))
  414. (define (with-error-to-port port thunk)
  415. (parameterize ((current-error-port port))
  416. (thunk)))
  417. (define* (with-input-from-file
  418. file thunk #:key (binary #f) (encoding #f) (guess-encoding #f))
  419. "THUNK must be a procedure of no arguments, and FILE must be a
  420. string naming a file. The file must already exist. The file is opened for
  421. input, an input port connected to it is made
  422. the default value returned by `current-input-port',
  423. and the THUNK is called with no arguments.
  424. When the THUNK returns, the port is closed and the previous
  425. default is restored. Returns the values yielded by THUNK. If an
  426. escape procedure is used to escape from the continuation of these
  427. procedures, their behavior is implementation dependent."
  428. (call-with-input-file file
  429. (lambda (p) (with-input-from-port p thunk))
  430. #:binary binary
  431. #:encoding encoding
  432. #:guess-encoding guess-encoding))
  433. (define* (with-output-to-file file thunk #:key (binary #f) (encoding #f))
  434. "THUNK must be a procedure of no arguments, and FILE must be a
  435. string naming a file. The effect is unspecified if the file already exists.
  436. The file is opened for output, an output port connected to it is made
  437. the default value returned by `current-output-port',
  438. and the THUNK is called with no arguments.
  439. When the THUNK returns, the port is closed and the previous
  440. default is restored. Returns the values yielded by THUNK. If an
  441. escape procedure is used to escape from the continuation of these
  442. procedures, their behavior is implementation dependent."
  443. (call-with-output-file file
  444. (lambda (p) (with-output-to-port p thunk))
  445. #:binary binary
  446. #:encoding encoding))
  447. (define* (with-error-to-file file thunk #:key (binary #f) (encoding #f))
  448. "THUNK must be a procedure of no arguments, and FILE must be a
  449. string naming a file. The effect is unspecified if the file already exists.
  450. The file is opened for output, an output port connected to it is made
  451. the default value returned by `current-error-port',
  452. and the THUNK is called with no arguments.
  453. When the THUNK returns, the port is closed and the previous
  454. default is restored. Returns the values yielded by THUNK. If an
  455. escape procedure is used to escape from the continuation of these
  456. procedures, their behavior is implementation dependent."
  457. (call-with-output-file file
  458. (lambda (p) (with-error-to-port p thunk))
  459. #:binary binary
  460. #:encoding encoding))
  461. (define (call-with-input-string string proc)
  462. "Calls the one-argument procedure @var{proc} with a newly created
  463. input port from which @var{string}'s contents may be read. The value
  464. yielded by the @var{proc} is returned."
  465. (proc (open-input-string string)))
  466. (define (with-input-from-string string thunk)
  467. "THUNK must be a procedure of no arguments.
  468. The test of STRING is opened for
  469. input, an input port connected to it is made,
  470. and the THUNK is called with no arguments.
  471. When the THUNK returns, the port is closed.
  472. Returns the values yielded by THUNK. If an
  473. escape procedure is used to escape from the continuation of these
  474. procedures, their behavior is implementation dependent."
  475. (call-with-input-string string
  476. (lambda (p) (with-input-from-port p thunk))))
  477. (define (call-with-output-string proc)
  478. "Calls the one-argument procedure @var{proc} with a newly created output
  479. port. When the function returns, the string composed of the characters
  480. written into the port is returned."
  481. (let ((port (open-output-string)))
  482. (proc port)
  483. (get-output-string port)))
  484. (define (with-output-to-string thunk)
  485. "Calls THUNK and returns its output as a string."
  486. (call-with-output-string
  487. (lambda (p) (with-output-to-port p thunk))))
  488. (define (with-error-to-string thunk)
  489. "Calls THUNK and returns its error output as a string."
  490. (call-with-output-string
  491. (lambda (p) (with-error-to-port p thunk))))
  492. (define (inherit-print-state old-port new-port)
  493. (if (get-print-state old-port)
  494. (port-with-print-state new-port (get-print-state old-port))
  495. new-port))