diff --git a/TODO b/TODO index 93f7c837..3e01c1f5 100644 --- a/TODO +++ b/TODO @@ -60,7 +60,8 @@ - State "DONE" [2009-07-07 Tue 14:42] ** TODO unicode ** TODO threads -** TODO virtual ports +** DONE virtual ports + - State "DONE" [2010-01-02 Sat 20:12] ** DONE dynamic-wind - State "DONE" [2009-12-26 Sat 01:51] Adapted a version from Scheme48. @@ -114,7 +115,8 @@ - State "DONE" [2009-12-26 Sat 01:50] *** DONE time interface - State "DONE" [2009-12-26 Sat 01:50] -*** TODO host system interface +*** DONE host system interface + - State "DONE" [2010-01-02 Sat 20:12] ** DONE pathname library - State "DONE" [2009-12-16 Wed 18:58] ** DONE uri library diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 369e3b65..491e70a9 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -460,6 +460,10 @@ sexp sexp_make_flonum(sexp ctx, double f); #define SEXP_THREE sexp_make_fixnum(3) #define SEXP_FOUR sexp_make_fixnum(4) #define SEXP_FIVE sexp_make_fixnum(5) +#define SEXP_SIX sexp_make_fixnum(6) +#define SEXP_SEVEN sexp_make_fixnum(7) +#define SEXP_EIGHT sexp_make_fixnum(8) +#define SEXP_NINE sexp_make_fixnum(9) #define sexp_make_character(n) ((sexp) ((((sexp_sint_t)(n))<<SEXP_EXTENDED_BITS) + SEXP_CHAR_TAG)) #define sexp_unbox_character(n) ((int) (((sexp_sint_t)(n))>>SEXP_EXTENDED_BITS)) diff --git a/lib/chibi/io.module b/lib/chibi/io.module index f9d531f3..ec765c04 100644 --- a/lib/chibi/io.module +++ b/lib/chibi/io.module @@ -2,7 +2,12 @@ (define-module (chibi io) (export read-string read-string! write-string read-line write-line port-fold port-fold-right port-map - port->list port->string-list port->sexp-list port->string) + port->list port->string-list port->sexp-list port->string + file-position set-file-position! seek/set seek/cur seek/end + make-custom-input-port make-custom-output-port + make-null-output-port make-broadcast-port make-concatenated-port + make-generated-input-port make-filtered-output-port + make-filtered-input-port) (import-immutable (scheme)) (include-shared "io/io") (include "io/io.scm")) diff --git a/lib/chibi/io/io.scm b/lib/chibi/io/io.scm index a6e0f8d2..97de1cc6 100644 --- a/lib/chibi/io/io.scm +++ b/lib/chibi/io/io.scm @@ -1,8 +1,22 @@ +;; io.scm -- various input/output utilities +;; Copyright (c) 2010 Alex Shinn. All rights reserved. +;; BSD-style license: http://synthcode.com/license.txt + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; utilities (define eof (call-with-input-string " " (lambda (in) (read-char in) (read-char in)))) +(define (string-copy! dst start src from to) + (do ((i from (+ i 1)) (j start (+ j 1))) + ((>= i to)) + (string-set! dst j (string-ref src i)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; reading and writing + (define (write-line str . o) (let ((out (if (pair? o) (car o) (current-output-port)))) (display str out) @@ -21,6 +35,9 @@ eof (cadr res))))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; higher order port operations + (define (port-fold kons knil . o) (let ((read (if (pair? o) (car o) read)) (in (if (and (pair? o) (pair? (cdr o))) @@ -53,3 +70,94 @@ (define (port->string in) (string-concatenate (port->list (lambda (in) (read-string 1024 in)) in))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; custom port utilities + +(define (make-custom-input-port read . o) + (let ((seek (and (pair? o) (car o))) + (close (and (pair? o) (pair? (cdr o)) (car (cdr o))))) + (%make-custom-input-port read seek close))) + +(define (make-custom-output-port write . o) + (let ((seek (and (pair? o) (car o))) + (close (and (pair? o) (pair? (cdr o)) (car (cdr o))))) + (%make-custom-output-port write seek close))) + +(define (make-null-output-port) + (make-custom-output-port (lambda (str n) 0))) + +(define (make-broadcast-port . ports) + (make-custom-output-port + (lambda (str n) + (for-each (lambda (p) (write-string str n p)) ports) + n))) + +(define (make-filtered-output-port filter out) + (make-custom-output-port + (lambda (str n) + (let* ((len (string-length str)) + (s1 (if (= n len) str (substring str 0 n))) + (s2 (filter s1))) + (if (string? s2) + (write-string s2 (string-length s2) out)))))) + +(define (make-concatenated-port . ports) + (make-custom-input-port + (lambda (str n) + (if (null? ports) + 0 + (let lp ((i (read-string! str n (car ports)))) + (cond + ((>= i n) + i) + (else + (set! ports (cdr ports)) + (cond + ((null? ports) + i) + (else + (let* ((s (read-string (- n i) (car ports))) + (len (if (string? s) (string-length s) 0))) + (if (and (string? str) (> len 0)) + (string-copy! str i s 0 len)) + (lp (+ i len)))))))))))) + +(define (make-generated-input-port generator) + (let ((buf "") + (len 0) + (offset 0)) + (make-custom-input-port + (lambda (str n) + (cond + ((>= (- len offset) n) + (string-copy! str 0 buf offset (+ offset n)) + (set! offset (+ offset n)) + n) + (else + (string-copy! str 0 buf offset len) + (let lp ((i (- len offset))) + (set! buf (generator)) + (cond + ((not (string? buf)) + (set! buf "") + (set! len 0) + (set! offset 0) + (- n i)) + (else + (set! len (string-length buf)) + (set! offset 0) + (cond + ((>= (- len offset) (- n i)) + (string-copy! str i buf offset (+ offset (- n i))) + (set! offset (+ offset (- n i))) + n) + (else + (string-copy! str i buf offset len) + (lp (+ i (- len offset)))))))))))))) + +(define (make-filtered-input-port filter in) + (make-generated-input-port + (lambda () + (let ((res (read-string 1024 in))) + (if (string? res) (filter res) res))))) diff --git a/lib/chibi/io/io.stub b/lib/chibi/io/io.stub index 685e1832..208d0a18 100644 --- a/lib/chibi/io/io.stub +++ b/lib/chibi/io/io.stub @@ -6,8 +6,22 @@ ((result (array char arg2)) (value 1 size_t) size_t (default (current-input-port) input-port))) (define-c size_t (read-string! "fread") - (string size_t (value 1 size_t) (default (current-input-port) input-port))) + (string (value 1 size_t) size_t (default (current-input-port) input-port))) (define-c size_t (write-string "fwrite") - (string size_t (value 1 size_t) (default (current-output-port) output-port))) + (string (value 1 size_t) size_t (default (current-output-port) output-port))) +(define-c-const int (seek/set "SEEK_SET")) +(define-c-const int (seek/cur "SEEK_CUR")) +(define-c-const int (seek/end "SEEK_END")) + +(define-c long (file-position "ftell") (port)) +(define-c long (set-file-position! "fseek") (port long int)) + +(c-include "port.c") + +(define-c sexp (%make-custom-input-port "sexp_make_custom_input_port") + ((value ctx sexp) sexp sexp sexp)) + +(define-c sexp (%make-custom-output-port "sexp_make_custom_output_port") + ((value ctx sexp) sexp sexp sexp)) diff --git a/sexp.c b/sexp.c index b6eab627..5e313b12 100644 --- a/sexp.c +++ b/sexp.c @@ -291,7 +291,9 @@ sexp sexp_make_context (sexp ctx, sexp_uint_t size) { #if ! SEXP_USE_GLOBAL_HEAP void sexp_destroy_context (sexp ctx) { sexp_heap heap; + size_t sum_freed; if (sexp_context_heap(ctx)) { + sexp_sweep(ctx, &sum_freed); /* sweep w/o mark to run finalizers */ heap = sexp_context_heap(ctx); sexp_context_heap(ctx) = NULL; free(heap);