mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-20 22:29:16 +02:00
Adding support for bi-directional ports, and making (chibi net) use them for sockets.
Also modifying FFI to automatically make input ports non-blocking, and fixing R7RS incompatibility where closing an already closed port signalled an error.
This commit is contained in:
parent
380a551f43
commit
1dd61a26f3
8 changed files with 68 additions and 17 deletions
7
eval.c
7
eval.c
|
@ -1,5 +1,5 @@
|
||||||
/* eval.c -- evaluator library implementation */
|
/* eval.c -- evaluator library implementation */
|
||||||
/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */
|
/* Copyright (c) 2009-2012 Alex Shinn. All rights reserved. */
|
||||||
/* BSD-style license: http://synthcode.com/license.txt */
|
/* BSD-style license: http://synthcode.com/license.txt */
|
||||||
|
|
||||||
#include "chibi/eval.h"
|
#include "chibi/eval.h"
|
||||||
|
@ -1050,8 +1050,6 @@ sexp sexp_open_binary_output_file (sexp ctx, sexp self, sexp_sint_t n, sexp path
|
||||||
|
|
||||||
sexp sexp_close_port_op (sexp ctx, sexp self, sexp_sint_t n, sexp port) {
|
sexp sexp_close_port_op (sexp ctx, sexp self, sexp_sint_t n, sexp port) {
|
||||||
sexp_assert_type(ctx, sexp_portp, SEXP_OPORT, port);
|
sexp_assert_type(ctx, sexp_portp, SEXP_OPORT, port);
|
||||||
if (! sexp_port_openp(port))
|
|
||||||
return sexp_user_exception(ctx, self, "port already closed", port);
|
|
||||||
return sexp_finalize_port(ctx, self, n, port);
|
return sexp_finalize_port(ctx, self, n, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1964,6 +1962,9 @@ static const char* sexp_initial_features[] = {
|
||||||
#if SEXP_USE_DL
|
#if SEXP_USE_DL
|
||||||
"dynamic-loading",
|
"dynamic-loading",
|
||||||
#endif
|
#endif
|
||||||
|
#if SEXP_USE_BIDIRECTIONAL_PORTS
|
||||||
|
"bidir-ports",
|
||||||
|
#endif
|
||||||
#if SEXP_USE_STRING_STREAMS
|
#if SEXP_USE_STRING_STREAMS
|
||||||
"string-streams",
|
"string-streams",
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* features.h -- general feature configuration */
|
/* features.h -- general feature configuration */
|
||||||
/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */
|
/* Copyright (c) 2009-2012 Alex Shinn. All rights reserved. */
|
||||||
/* BSD-style license: http://synthcode.com/license.txt */
|
/* BSD-style license: http://synthcode.com/license.txt */
|
||||||
|
|
||||||
/* uncomment this to disable most features */
|
/* uncomment this to disable most features */
|
||||||
|
@ -510,6 +510,10 @@
|
||||||
#define SEXP_USE_GC_FILE_DESCRIPTORS (SEXP_USE_AUTOCLOSE_PORTS &&!SEXP_USE_BOEHM && !defined(PLAN9))
|
#define SEXP_USE_GC_FILE_DESCRIPTORS (SEXP_USE_AUTOCLOSE_PORTS &&!SEXP_USE_BOEHM && !defined(PLAN9))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEXP_USE_BIDIRECTIONAL_PORTS
|
||||||
|
#define SEXP_USE_BIDIRECTIONAL_PORTS ! SEXP_USE_NO_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef SEXP_USE_2010_EPOCH
|
#ifndef SEXP_USE_2010_EPOCH
|
||||||
#define SEXP_USE_2010_EPOCH ! SEXP_USE_NO_FEATURES
|
#define SEXP_USE_2010_EPOCH ! SEXP_USE_NO_FEATURES
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* sexp.h -- header for sexp library */
|
/* sexp.h -- header for sexp library */
|
||||||
/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */
|
/* Copyright (c) 2009-2012 Alex Shinn. All rights reserved. */
|
||||||
/* BSD-style license: http://synthcode.com/license.txt */
|
/* BSD-style license: http://synthcode.com/license.txt */
|
||||||
|
|
||||||
#ifndef SEXP_H
|
#ifndef SEXP_H
|
||||||
|
@ -315,7 +315,7 @@ struct sexp_struct {
|
||||||
struct {
|
struct {
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
char *buf;
|
char *buf;
|
||||||
char openp, binaryp, no_closep, sourcep, blockedp, fold_casep;
|
char openp, bidirp, binaryp, no_closep, sourcep, blockedp, fold_casep;
|
||||||
sexp_uint_t offset, line, flags;
|
sexp_uint_t offset, line, flags;
|
||||||
size_t size;
|
size_t size;
|
||||||
sexp name;
|
sexp name;
|
||||||
|
@ -604,7 +604,11 @@ sexp sexp_make_flonum(sexp ctx, double f);
|
||||||
#define sexp_bytesp(x) (sexp_check_tag(x, SEXP_BYTES))
|
#define sexp_bytesp(x) (sexp_check_tag(x, SEXP_BYTES))
|
||||||
#define sexp_vectorp(x) (sexp_check_tag(x, SEXP_VECTOR))
|
#define sexp_vectorp(x) (sexp_check_tag(x, SEXP_VECTOR))
|
||||||
#define sexp_iportp(x) (sexp_check_tag(x, SEXP_IPORT))
|
#define sexp_iportp(x) (sexp_check_tag(x, SEXP_IPORT))
|
||||||
|
#if SEXP_USE_BIDIRECTIONAL_PORTS
|
||||||
|
#define sexp_oportp(x) (sexp_check_tag(x, SEXP_OPORT) || (sexp_check_tag(x, SEXP_IPORT) && sexp_port_bidirp(x)))
|
||||||
|
#else
|
||||||
#define sexp_oportp(x) (sexp_check_tag(x, SEXP_OPORT))
|
#define sexp_oportp(x) (sexp_check_tag(x, SEXP_OPORT))
|
||||||
|
#endif
|
||||||
#if SEXP_USE_BIGNUMS
|
#if SEXP_USE_BIGNUMS
|
||||||
#define sexp_bignump(x) (sexp_check_tag(x, SEXP_BIGNUM))
|
#define sexp_bignump(x) (sexp_check_tag(x, SEXP_BIGNUM))
|
||||||
#else
|
#else
|
||||||
|
@ -651,7 +655,7 @@ sexp sexp_make_flonum(sexp ctx, double f);
|
||||||
#define sexp_idp(x) \
|
#define sexp_idp(x) \
|
||||||
(sexp_symbolp(x) || (sexp_synclop(x) && sexp_symbolp(sexp_synclo_expr(x))))
|
(sexp_symbolp(x) || (sexp_synclop(x) && sexp_symbolp(sexp_synclo_expr(x))))
|
||||||
|
|
||||||
#define sexp_portp(x) (sexp_iportp(x) || sexp_oportp(x))
|
#define sexp_portp(x) (sexp_check_tag(x, SEXP_IPORT) || sexp_check_tag(x, SEXP_OPORT))
|
||||||
|
|
||||||
#if SEXP_USE_STRING_STREAMS
|
#if SEXP_USE_STRING_STREAMS
|
||||||
#define sexp_stream_portp(x) 1
|
#define sexp_stream_portp(x) 1
|
||||||
|
@ -842,6 +846,7 @@ SEXP_API sexp sexp_make_unsigned_integer(sexp ctx, sexp_luint_t x);
|
||||||
#define sexp_port_name(p) (sexp_pred_field(p, port, sexp_portp, name))
|
#define sexp_port_name(p) (sexp_pred_field(p, port, sexp_portp, name))
|
||||||
#define sexp_port_line(p) (sexp_pred_field(p, port, sexp_portp, line))
|
#define sexp_port_line(p) (sexp_pred_field(p, port, sexp_portp, line))
|
||||||
#define sexp_port_openp(p) (sexp_pred_field(p, port, sexp_portp, openp))
|
#define sexp_port_openp(p) (sexp_pred_field(p, port, sexp_portp, openp))
|
||||||
|
#define sexp_port_bidirp(p) (sexp_pred_field(p, port, sexp_portp, bidirp))
|
||||||
#define sexp_port_binaryp(p) (sexp_pred_field(p, port, sexp_portp, binaryp))
|
#define sexp_port_binaryp(p) (sexp_pred_field(p, port, sexp_portp, binaryp))
|
||||||
#define sexp_port_no_closep(p) (sexp_pred_field(p, port, sexp_portp, no_closep))
|
#define sexp_port_no_closep(p) (sexp_pred_field(p, port, sexp_portp, no_closep))
|
||||||
#define sexp_port_sourcep(p) (sexp_pred_field(p, port, sexp_portp, sourcep))
|
#define sexp_port_sourcep(p) (sexp_pred_field(p, port, sexp_portp, sourcep))
|
||||||
|
@ -1248,6 +1253,7 @@ SEXP_API sexp sexp_make_input_port (sexp ctx, FILE* in, sexp name);
|
||||||
SEXP_API sexp sexp_make_output_port (sexp ctx, FILE* out, sexp name);
|
SEXP_API sexp sexp_make_output_port (sexp ctx, FILE* out, sexp name);
|
||||||
SEXP_API sexp sexp_make_non_null_input_port (sexp ctx, FILE* in, sexp name);
|
SEXP_API sexp sexp_make_non_null_input_port (sexp ctx, FILE* in, sexp name);
|
||||||
SEXP_API sexp sexp_make_non_null_output_port (sexp ctx, FILE* out, sexp name);
|
SEXP_API sexp sexp_make_non_null_output_port (sexp ctx, FILE* out, sexp name);
|
||||||
|
SEXP_API sexp sexp_make_non_null_input_output_port (sexp ctx, FILE* io, sexp name);
|
||||||
SEXP_API sexp sexp_port_binaryp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port);
|
SEXP_API sexp sexp_port_binaryp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port);
|
||||||
SEXP_API sexp sexp_port_openp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port);
|
SEXP_API sexp sexp_port_openp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port);
|
||||||
#if SEXP_USE_FOLD_CASE_SYMS
|
#if SEXP_USE_FOLD_CASE_SYMS
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(define-library (chibi filesystem)
|
(define-library (chibi filesystem)
|
||||||
(export open-input-file-descriptor open-output-file-descriptor
|
(export open-input-file-descriptor open-output-file-descriptor
|
||||||
|
open-input-output-file-descriptor
|
||||||
duplicate-file-descriptor duplicate-file-descriptor-to
|
duplicate-file-descriptor duplicate-file-descriptor-to
|
||||||
close-file-descriptor renumber-file-descriptor
|
close-file-descriptor renumber-file-descriptor
|
||||||
delete-file link-file symbolic-link-file rename-file
|
delete-file link-file symbolic-link-file rename-file
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
;; filesystem.stub -- filesystem bindings
|
;; filesystem.stub -- filesystem bindings
|
||||||
;; Copyright (c) 2009-2011 Alex Shinn. All rights reserved.
|
;; Copyright (c) 2009-2012 Alex Shinn. All rights reserved.
|
||||||
;; BSD-style license: http://synthcode.com/license.txt
|
;; BSD-style license: http://synthcode.com/license.txt
|
||||||
|
|
||||||
(c-system-include "sys/types.h")
|
(c-system-include "sys/types.h")
|
||||||
|
@ -75,6 +75,11 @@
|
||||||
(define-c output-port (open-output-file-descriptor "fdopen")
|
(define-c output-port (open-output-file-descriptor "fdopen")
|
||||||
(int (value "w" string)))
|
(int (value "w" string)))
|
||||||
|
|
||||||
|
;;> Creates a new bidirectional port from the file descriptor @var{int}.
|
||||||
|
|
||||||
|
(define-c input-output-port (open-input-output-file-descriptor "fdopen")
|
||||||
|
(int (value "r+" string)))
|
||||||
|
|
||||||
;;> Unlinks the file named @var{string} from the filesystem.
|
;;> Unlinks the file named @var{string} from the filesystem.
|
||||||
;;> Returns @scheme{#t} on success and @scheme{#f} on failure.
|
;;> Returns @scheme{#t} on success and @scheme{#f} on failure.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
;; Copyright (c) 2010-2011 Alex Shinn. All rights reserved.
|
;; Copyright (c) 2010-2012 Alex Shinn. All rights reserved.
|
||||||
;; BSD-style license: http://synthcode.com/license.txt
|
;; BSD-style license: http://synthcode.com/license.txt
|
||||||
|
|
||||||
;;> @subsubsubsection{@scheme{(get-address-info host service [addrinfo])}}
|
;;> @subsubsubsection{@scheme{(get-address-info host service [addrinfo])}}
|
||||||
|
@ -42,8 +42,13 @@
|
||||||
(cond-expand
|
(cond-expand
|
||||||
(threads (set-file-descriptor-flags! sock open/non-block))
|
(threads (set-file-descriptor-flags! sock open/non-block))
|
||||||
(else #f))
|
(else #f))
|
||||||
(list (open-input-file-descriptor sock)
|
(cond-expand
|
||||||
(open-output-file-descriptor sock)))))))))
|
(bidir-ports
|
||||||
|
(let ((port (open-input-output-file-descriptor sock)))
|
||||||
|
(list port port)))
|
||||||
|
(else
|
||||||
|
(list (open-input-file-descriptor sock)
|
||||||
|
(open-output-file-descriptor sock)))))))))))
|
||||||
|
|
||||||
;;> Convenience wrapper around @scheme{open-net-io}, opens
|
;;> Convenience wrapper around @scheme{open-net-io}, opens
|
||||||
;;> the connection then calls @var{proc} with two arguments,
|
;;> the connection then calls @var{proc} with two arguments,
|
||||||
|
@ -56,8 +61,9 @@
|
||||||
(let ((io (open-net-io host service)))
|
(let ((io (open-net-io host service)))
|
||||||
(if (not (pair? io))
|
(if (not (pair? io))
|
||||||
(error "couldn't find address" host service)
|
(error "couldn't find address" host service)
|
||||||
(let ((res (proc (car io) (car (cdr io)))))
|
(let ((res (proc (car io) (cadr io))))
|
||||||
(close-input-port (car io))
|
(close-input-port (car io))
|
||||||
|
(close-output-port (cadr io))
|
||||||
res))))
|
res))))
|
||||||
|
|
||||||
;;> @subsubsubsection{@scheme{(make-listener-socket addrinfo [max-conn])}}
|
;;> @subsubsubsection{@scheme{(make-listener-socket addrinfo [max-conn])}}
|
||||||
|
|
15
sexp.c
15
sexp.c
|
@ -1,5 +1,5 @@
|
||||||
/* sexp.c -- standalone sexp library implementation */
|
/* sexp.c -- standalone sexp library implementation */
|
||||||
/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */
|
/* Copyright (c) 2009-2012 Alex Shinn. All rights reserved. */
|
||||||
/* BSD-style license: http://synthcode.com/license.txt */
|
/* BSD-style license: http://synthcode.com/license.txt */
|
||||||
|
|
||||||
#include "chibi/sexp.h"
|
#include "chibi/sexp.h"
|
||||||
|
@ -1390,6 +1390,7 @@ sexp sexp_make_input_port (sexp ctx, FILE* in, sexp name) {
|
||||||
sexp_port_flags(p) = SEXP_PORT_UNKNOWN_FLAGS;
|
sexp_port_flags(p) = SEXP_PORT_UNKNOWN_FLAGS;
|
||||||
sexp_port_buf(p) = NULL;
|
sexp_port_buf(p) = NULL;
|
||||||
sexp_port_openp(p) = 1;
|
sexp_port_openp(p) = 1;
|
||||||
|
sexp_port_bidirp(p) = 0;
|
||||||
sexp_port_binaryp(p) = 1;
|
sexp_port_binaryp(p) = 1;
|
||||||
sexp_port_no_closep(p) = 0;
|
sexp_port_no_closep(p) = 0;
|
||||||
sexp_port_sourcep(p) = 0;
|
sexp_port_sourcep(p) = 0;
|
||||||
|
@ -1418,6 +1419,18 @@ sexp sexp_make_non_null_output_port (sexp ctx, FILE* out, sexp name) {
|
||||||
return sexp_make_output_port(ctx, out, name);
|
return sexp_make_output_port(ctx, out, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SEXP_USE_BIDIRECTIONAL_PORTS
|
||||||
|
sexp sexp_make_non_null_input_output_port (sexp ctx, FILE* io, sexp name) {
|
||||||
|
sexp res;
|
||||||
|
if (!io) return sexp_user_exception(ctx, SEXP_FALSE, "null input-output-port", name);
|
||||||
|
res = sexp_make_input_port(ctx, io, name);
|
||||||
|
if (sexp_portp(res)) sexp_port_bidirp(res) = 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define sexp_make_non_null_input_output_port sexp_make_non_null_input_port
|
||||||
|
#endif
|
||||||
|
|
||||||
sexp sexp_port_binaryp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port) {
|
sexp sexp_port_binaryp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port) {
|
||||||
sexp_assert_type(ctx, sexp_portp, SEXP_IPORT, port);
|
sexp_assert_type(ctx, sexp_portp, SEXP_IPORT, port);
|
||||||
return sexp_make_boolean(sexp_port_binaryp(port));
|
return sexp_make_boolean(sexp_port_binaryp(port));
|
||||||
|
|
|
@ -149,7 +149,7 @@
|
||||||
(eq? 'char (type-base type)))))
|
(eq? 'char (type-base type)))))
|
||||||
|
|
||||||
(define (port-type? type)
|
(define (port-type? type)
|
||||||
(memq type '(port input-port output-port)))
|
(memq type '(port input-port output-port input-output-port)))
|
||||||
|
|
||||||
(define (error-type? type)
|
(define (error-type? type)
|
||||||
(memq type '(errno non-null-string non-null-pointer)))
|
(memq type '(errno non-null-string non-null-pointer)))
|
||||||
|
@ -400,6 +400,7 @@
|
||||||
((eq? base 'port) "sexp_portp")
|
((eq? base 'port) "sexp_portp")
|
||||||
((eq? base 'input-port) "sexp_iportp")
|
((eq? base 'input-port) "sexp_iportp")
|
||||||
((eq? base 'output-port) "sexp_oportp")
|
((eq? base 'output-port) "sexp_oportp")
|
||||||
|
((eq? base 'input-output-port) "sexp_ioportp")
|
||||||
(else #f))))
|
(else #f))))
|
||||||
|
|
||||||
(define (type-name type)
|
(define (type-name type)
|
||||||
|
@ -424,6 +425,7 @@
|
||||||
((eq? base 'port) "SEXP_IPORT")
|
((eq? base 'port) "SEXP_IPORT")
|
||||||
((eq? base 'input-port) "SEXP_IPORT")
|
((eq? base 'input-port) "SEXP_IPORT")
|
||||||
((eq? base 'output-port) "SEXP_OPORT")
|
((eq? base 'output-port) "SEXP_OPORT")
|
||||||
|
((eq? base 'input-output-port) "SEXP_IPORT")
|
||||||
((void-pointer-type? type) "SEXP_CPOINTER")
|
((void-pointer-type? type) "SEXP_CPOINTER")
|
||||||
((assq base *types*)
|
((assq base *types*)
|
||||||
;; (string-append "sexp_type_tag(" (type-id-name base) ")")
|
;; (string-append "sexp_type_tag(" (type-id-name base) ")")
|
||||||
|
@ -495,6 +497,8 @@
|
||||||
(cat "sexp_make_non_null_input_port(ctx, " val ", SEXP_FALSE)"))
|
(cat "sexp_make_non_null_input_port(ctx, " val ", SEXP_FALSE)"))
|
||||||
((eq? 'output-port base)
|
((eq? 'output-port base)
|
||||||
(cat "sexp_make_non_null_output_port(ctx, " val ", SEXP_FALSE)"))
|
(cat "sexp_make_non_null_output_port(ctx, " val ", SEXP_FALSE)"))
|
||||||
|
((eq? 'input-output-port base)
|
||||||
|
(cat "sexp_make_non_null_input_output_port(ctx, " val ", SEXP_FALSE)"))
|
||||||
(else
|
(else
|
||||||
(let ((ctype (assq base *types*))
|
(let ((ctype (assq base *types*))
|
||||||
(void*? (void-pointer-type? type)))
|
(void*? (void-pointer-type? type)))
|
||||||
|
@ -895,7 +899,17 @@
|
||||||
(else #f)))
|
(else #f)))
|
||||||
(cat ";\n")
|
(cat ";\n")
|
||||||
(if (type-array ret-type)
|
(if (type-array ret-type)
|
||||||
(write-result ret-type))))
|
(write-result ret-type)
|
||||||
|
(write-result-adjustment ret-type))))
|
||||||
|
|
||||||
|
(define (write-result-adjustment result)
|
||||||
|
(cond
|
||||||
|
((memq (type-base result) '(input-port input-output-port))
|
||||||
|
(let ((res (string-append "res" (type-index-string result))))
|
||||||
|
(cat "#ifdef SEXP_USE_GREEN_THREADS\n"
|
||||||
|
" if (sexp_portp(" res "))\n"
|
||||||
|
" fcntl(fileno(sexp_port_stream(" res ")), F_SETFL, O_NONBLOCK);\n"
|
||||||
|
"#endif\n")))))
|
||||||
|
|
||||||
(define (write-result result)
|
(define (write-result result)
|
||||||
(let ((res (string-append "res" (type-index-string result)))
|
(let ((res (string-append "res" (type-index-string result)))
|
||||||
|
@ -934,7 +948,8 @@
|
||||||
(c->scheme-converter
|
(c->scheme-converter
|
||||||
result
|
result
|
||||||
(string-append "tmp" (type-index-string result)))
|
(string-append "tmp" (type-index-string result)))
|
||||||
(cat ";\n")))))
|
(cat ";\n")))
|
||||||
|
(write-result-adjustment result)))
|
||||||
|
|
||||||
(define (write-results func)
|
(define (write-results func)
|
||||||
(let ((error-res? (error-type? (type-base (func-ret-type func))))
|
(let ((error-res? (error-type? (type-base (func-ret-type func))))
|
||||||
|
@ -998,7 +1013,7 @@
|
||||||
(if (number? len)
|
(if (number? len)
|
||||||
(cat " if (len" i " != " len ")\n"
|
(cat " if (len" i " != " len ")\n"
|
||||||
" free(tmp" i ");\n"))))
|
" free(tmp" i ");\n"))))
|
||||||
((eq? (type-base a) 'input-port)
|
((memq (type-base a) '(input-port input-output-port))
|
||||||
(cat " sexp_maybe_unblock_port(ctx, arg" (type-index a) ");\n"))
|
(cat " sexp_maybe_unblock_port(ctx, arg" (type-index a) ");\n"))
|
||||||
((and (type-result? a) (not (basic-type? a))
|
((and (type-result? a) (not (basic-type? a))
|
||||||
(not (assq (type-base a) *types*))
|
(not (assq (type-base a) *types*))
|
||||||
|
|
Loading…
Add table
Reference in a new issue