diff --git a/racket/src/rktio/parse.rkt b/racket/src/rktio/parse.rkt index 1c55d802db..eb66c447f7 100644 --- a/racket/src/rktio/parse.rkt +++ b/racket/src/rktio/parse.rkt @@ -1,10 +1,32 @@ #lang racket/base (require racket/cmdline racket/pretty + racket/list + racket/match parser-tools/lex (prefix-in : parser-tools/lex-sre) parser-tools/yacc) +;; Parse "rktio.h" to produce a seqeuence +;; (define-constant ) ... +;; ... +;; ... +;; +;; where +;; = (define-type ) +;; | (define-struct-type ([ ] ...)) +;; +;; = (define-function ([ ] ...)) +;; => never fails +;; | (define-function/errno ([ ] ...)) +;; => fails when result equals +;; | (define-function/errno+step ([ ] ...)) +;; => fails when result equals , keep step +;; +;; = +;; | (ref ) ; opaque, needs to be deallocated somehow +;; | (* ) ; transparent argument, can be represented by a byte string + (define output-file #f) (define input-file @@ -22,7 +44,7 @@ (define-empty-tokens delim-tokens (EOF WHITESPACE OPEN CLOSE COPEN CCLOSE SEMI COMMA STAR LSHIFT EQUAL - __RKTIO_H__ EXTERN EXTERN/NOERR EXTERN/STEP + __RKTIO_H__ EXTERN EXTERN/NOERR EXTERN/STEP EXTERN/ERR DEFINE TYPEDEF ENUM STRUCT VOID UNSIGNED SHORT INT CONST)) (define lex @@ -50,6 +72,7 @@ ["RKTIO_EXTERN" 'EXTERN] ["RKTIO_EXTERN_NOERR" 'EXTERN/NOERR] ["RKTIO_EXTERN_STEP" 'EXTERN/STEP] + ["RKTIO_EXTERN_ERR" 'EXTERN/ERR] [(:seq (:or #\_ (:/ #\A #\Z #\a #\z)) (:* (:or #\_ (:/ #\A #\Z #\a #\z #\0 #\9)))) (token-ID (string->symbol lexeme))] @@ -77,11 +100,12 @@ (grammar ( [() null] [( ) (cons $1 $2)]) - ( [(DEFINE ID ) `(define ,$2 ,$3)] + ( [(DEFINE ID ) `(define-constant ,$2 ,$3)] [(DEFINE __RKTIO_H__ ) #f] [(DEFINE EXTERN ID) #f] [(DEFINE EXTERN/NOERR EXTERN) #f] [(DEFINE EXTERN/STEP EXTERN) #f] + [(DEFINE EXTERN/ERR OPEN ID CLOSE EXTERN) #f] [(STRUCT ID SEMI) #f] [(TYPEDEF SEMI) (if (eq? $2 $3) @@ -92,12 +116,14 @@ `(define-struct-type ,$2 ,$4) (error 'parse "typedef struct names don't match at ~s" $5))] [( OPEN SEMI) - (let ([r-type (shift-stars $3 $2)]) - `(,(adjust-errno $1 r-type) ,r-type ,(unstar $3) ,$5))] + (let ([r-type (shift-stars $3 $2)] + [id (unstar $3)]) + `(,@(adjust-errno $1 r-type id) ,r-type ,id ,$5))] [(ENUM COPEN SEMI) `(begin . ,(enum-definitions $3))]) ( [(EXTERN) 'define-function/errno] [(EXTERN/STEP) 'define-function/errno+step] - [(EXTERN/NOERR) 'define-function]) + [(EXTERN/NOERR) 'define-function] + [(EXTERN/ERR OPEN ID CLOSE) `(define-function/errno ,$3)]) ( [(VOID CLOSE) null] [() $1]) ( [( CLOSE) `((,(shift-stars $2 $1) ,(unstar $2)))] @@ -130,11 +156,15 @@ [(STRUCT ID) $2]) ( [() $1])))) -(define (adjust-errno def-kind r) +(define (adjust-errno def-kind r id) (cond - [(eq? r 'rktio_bool_t) 'define-function] - [(eq? r 'void) 'define-function] - [else def-kind])) + [(eq? id 'rktio_init) '(define-function)] ; init is special, because we can't get an error + [(eq? r 'rktio_bool_t) '(define-function)] + [(eq? r 'void) '(define-function)] + [(pair? def-kind) def-kind] + [(pair? r) '(define-function/errno NULL)] + [(eq? r 'rktio_ok_t) '(define-function/errno #f)] + [else (list def-kind)])) (define (shift-stars from to) (if (and (pair? from) @@ -155,16 +185,16 @@ [(pair? (car l)) (let ([i (cadar l)]) (cons - `(define ,(caar l) ,i) + `(define-constant ,(caar l) ,i) (loop (cdr l) (add1 i))))] [else (cons - `(define ,(car l) ,i) + `(define-constant ,(car l) ,i) (loop (cdr l) (add1 i)))]))) ;; ---------------------------------------- -(define content +(define unsorted-unflattened-content (call-with-input-file input-file (lambda (i) (port-count-lines! i) @@ -175,14 +205,84 @@ [(eq? (position-token-token v) 'WHITESPACE) (loop)] [else v])))))))) +(define unsorted-content + (for*/list ([l (in-list unsorted-unflattened-content)] + [e (in-list (if (and (pair? l) + (eq? 'begin (car l))) + (cdr l) + (list l)))]) + e)) + +(define (constant-defn? e) + (and (pair? e) + (eq? (car e) 'define-constant))) + +(define (type-defn? e) + (and (pair? e) + (or (eq? (car e) 'define-type) + (eq? (car e) 'define-struct-type)))) + +(define constant-content + (filter constant-defn? unsorted-content)) + +(define type-content + (filter type-defn? unsorted-content)) + +(define defined-types + (let ([ht (for/hash ([e (in-list type-content)]) + (values (cadr e) #t))]) + (for/fold ([ht ht]) ([t (in-list '(char int unsigned-short + intptr_t rktio_int64_t))]) + (hash-set ht t #t)))) + +;; A pointer to a defined type in an argument position +;; is transparent, and it make sense to pass a byte +;; string directly (possibly to be filled in). +;; A pointer to an undefined type is opaque, and a pointer +;; to a defined type is "opaque" in a result position in +;; the sense that it should be explicitly dereferenced and +;; explicitly freed. +(define (update-type t #:as-argument? [as-argument? #f]) + (cond + [(and (pair? t) (eq? (car t) '*)) + (let ([s (update-type (cadr t))]) + (if (and as-argument? + (or (pair? s) + (hash-ref defined-types s #f))) + `(* ,s) + `(ref ,s)))] + [else t])) + +(define (update-bind a #:as-argument? [as-argument? #f]) + `(,(update-type (car a) #:as-argument? as-argument?) ,(cadr a))) + +(define (update-types e) + (match e + [`(,def ,ret ,name ,args) + `(,def ,(update-type ret) ,name + ,(map (lambda (a) (update-bind a #:as-argument? #t)) args))] + [else e])) + +(define (update-type-types e) + (match e + [`(define-struct-type ,name ,fields) + `(define-struct-type ,name ,(map update-bind fields))] + [else e])) + +(define content + (append + constant-content + (map update-type-types type-content) + (map update-types + (filter (lambda (e) (not (or (constant-defn? e) (type-defn? e)))) + unsorted-content)))) + (define (show-content) + (printf "(begin\n") (for ([e (in-list content)] #:when e) - (if (and (pair? e) - (eq? 'begin (car e))) - (for ([e (in-list (cdr e))]) - (pretty-write e)) - (pretty-write e)))) + (pretty-write e)) + (printf ")\n")) (if output-file (with-output-to-file output-file diff --git a/racket/src/rktio/rktio.h b/racket/src/rktio/rktio.h index 729a4ebd6f..a1d8a48932 100644 --- a/racket/src/rktio/rktio.h +++ b/racket/src/rktio/rktio.h @@ -30,9 +30,10 @@ Return type conventions: - A return type `rktio_tri_t` (alias for `int`) means that 0 is returned for an expected failuree, some `RKTIO_...` (alias for 1) is returned for success, and `RKTIO_...ERROR` (alias for -2) is - returned for some error. Use `rktio_get_last_error_kind` and - `rktio_get_last_error` for more information about a - `RKTIO_...ERROR` result. + returned for some error. The function will be annotated with + `RKTIO_EXTERN_ERR(...)` to indicate the error value. Use + `rktio_get_last_error_kind` and `rktio_get_last_error` for more + information about a `RKTIO_...ERROR` result. - A return type `rktio_bool_t` means that the result is a simple 0 or 1, and no error is possible. @@ -82,8 +83,9 @@ Thread and signal conventions: # define RKTIO_EXTERN extern #endif -#define RKTIO_EXTERN_NOERR RKTIO_EXTERN -#define RKTIO_EXTERN_STEP RKTIO_EXTERN +#define RKTIO_EXTERN_ERR(n) RKTIO_EXTERN +#define RKTIO_EXTERN_NOERR RKTIO_EXTERN +#define RKTIO_EXTERN_STEP RKTIO_EXTERN /*************************************************/ /* Initialization and general datatypes */ @@ -95,7 +97,9 @@ typedef struct rktio_t rktio_t; RKTIO_EXTERN rktio_t *rktio_init(void); /* Call `rktio_init` before anything else. The first call to `rktio_init` must return before any additional calls (in other - threads), but there's no ordering requirement after that. */ + threads), but there's no ordering requirement after that. + If the result is NULL, then there's no way to get an error + code, so assume `RKTIO_ERROR_INIT_FAILED`. */ RKTIO_EXTERN void rktio_destroy(rktio_t *rktio); /* Call `rktio_destroy` as the last thing. Everything else must be @@ -232,7 +236,8 @@ RKTIO_EXTERN rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which); #define RKTIO_STDOUT 1 #define RKTIO_STDERR 2 -RKTIO_EXTERN intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len); +RKTIO_EXTERN_ERR(RKTIO_READ_ERROR) +intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len); /* Returns the number of bytes read, possibly 0, in non-blocking mode. Alternatively, the result can be `RKTIO_READ_EOF` for end-of-file or `RKTIO_READ_ERROR` for an error. Although rktio_read is intended @@ -242,7 +247,8 @@ RKTIO_EXTERN intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, i #define RKTIO_READ_EOF (-1) #define RKTIO_READ_ERROR (-2) -RKTIO_EXTERN intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, const char *buffer, intptr_t len); +RKTIO_EXTERN_ERR(RKTIO_WRITE_ERROR) +intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, const char *buffer, intptr_t len); /* Returns the number of bytes written, possibly 0, in non-blocking mode. Alternatively, the result can be `RKTIO_WRITE_ERROR` for an error. Although `rktio_write` is intended to write only bytes that @@ -253,32 +259,45 @@ RKTIO_EXTERN intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, const char *bu #define RKTIO_WRITE_ERROR (-2) -RKTIO_EXTERN intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len, - char *is_converted); +RKTIO_EXTERN_ERR(RKTIO_READ_ERROR) +intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len, + char *is_converted); /* Like `rktio_read`, but also reports whether each character was originally two characters that were converted to a single newline for text mode. */ +RKTIO_EXTERN_ERR(RKTIO_READ_ERROR) +intptr_t rktio_read_in(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t start, intptr_t end); +RKTIO_EXTERN_ERR(RKTIO_WRITE_ERROR) +intptr_t rktio_write_in(rktio_t *rktio, rktio_fd_t *fd, const char *buffer, intptr_t start, intptr_t end); +/* Like `rktio_read` and `rktio_write`, but accepting start and end + positions within `buffer`. */ + RKTIO_EXTERN_NOERR intptr_t rktio_buffered_byte_count(rktio_t *rktio, rktio_fd_t *fd); /* Reports the number of bytes that are buffered from the file descriptor. The result is normally zero, but text-mode conversion and the rare uncooperative corner of an OS can make the result 1 byte. */ -RKTIO_EXTERN rktio_tri_t rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd); -RKTIO_EXTERN rktio_tri_t rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd); +RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR) +rktio_tri_t rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd); +RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR) +rktio_tri_t rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd); /* Each polling function returns one of the following: */ #define RKTIO_POLL_NOT_READY 0 #define RKTIO_POLL_READY 1 #define RKTIO_POLL_ERROR (-2) -RKTIO_EXTERN rktio_tri_t rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd); +RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR) +rktio_tri_t rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd); /* See `rktio_write` above. Currently, the result is `RKTIO_POLL_NO_READY` only on Windows, and only for a pipe or similar non-regular file. A pipe counts as "flushed" when the other end has received the data (because the sent data doesn't persist beyond closing the pipe). */ -RKTIO_EXTERN rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl); -RKTIO_EXTERN rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd); +RKTIO_EXTERN_ERR(RKTIO_LOCK_ERROR) +rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl); +RKTIO_EXTERN_ERR(RKTIO_LOCK_ERROR) +rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd); /* Advisory file locks, where `excl` attempts to claim an exclusive lock. Whether these work in various situations depend on many OS details, where the differences involve promoting from non-exlcusive @@ -335,7 +354,8 @@ RKTIO_EXTERN rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio #define RKTIO_FAMILY_ANY (-1) RKTIO_EXTERN_NOERR int rktio_get_ipv4_family(rktio_t *rktio); -RKTIO_EXTERN rktio_tri_t rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup); +RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR) +rktio_tri_t rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup); /* Check whether an address is available for a lookup request. */ RKTIO_EXTERN rktio_addrinfo_t *rktio_addrinfo_lookup_get(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup); @@ -358,7 +378,8 @@ RKTIO_EXTERN rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *lo RKTIO_EXTERN void rktio_listen_stop(rktio_t *rktio, rktio_listener_t *l); /* Stops a listener. */ -RKTIO_EXTERN rktio_tri_t rktio_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener); +RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR) +rktio_tri_t rktio_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener); /* Returns one of `RKTIO_POLL_READY`, etc. */ RKTIO_EXTERN rktio_fd_t *rktio_accept(rktio_t *rktio, rktio_listener_t *listener); @@ -377,7 +398,8 @@ RKTIO_EXTERN rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *c RKTIO_EXTERN void rktio_connect_stop(rktio_t *rktio, rktio_connect_t *conn); /* Stops a connection whose result or error has not been received. */ -RKTIO_EXTERN rktio_tri_t rktio_poll_connect_ready(rktio_t *rktio, rktio_connect_t *conn); +RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR) +rktio_tri_t rktio_poll_connect_ready(rktio_t *rktio, rktio_connect_t *conn); /* Returns one of `RKTIO_POLL_READY`, etc. */ RKTIO_EXTERN rktio_fd_t *rktio_connect_trying(rktio_t *rktio, rktio_connect_t *conn); @@ -405,8 +427,9 @@ RKTIO_EXTERN rktio_ok_t rktio_udp_bind(rktio_t *rktio, rktio_fd_t *rfd, rktio_ad rktio_bool_t reuse); RKTIO_EXTERN rktio_ok_t rktio_udp_connect(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr); -RKTIO_EXTERN intptr_t rktio_udp_sendto(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr, - const char *buffer, intptr_t len); +RKTIO_EXTERN_ERR(RKTIO_WRITE_ERROR) +intptr_t rktio_udp_sendto(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr, + const char *buffer, intptr_t len); /* Extends `rktio_write` to accept a destination `addr`, and binds `rfd` if it is not bound aready. The `addr` can be NULL if the socket is connected. */ @@ -421,10 +444,9 @@ RKTIO_EXTERN rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rkt be `RKTIO_ERROR_TRY_AGAIN` or `RKTIO_ERROR_INFO_TRY_AGAIN`, where the latter can happen if the sock claims to be ready to read. */ -/* The following accessors return `RKTIO_PROP_ERROR` on failure */ -RKTIO_EXTERN rktio_tri_t rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd); +RKTIO_EXTERN_ERR(RKTIO_PROP_ERROR) rktio_tri_t rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd); RKTIO_EXTERN rktio_ok_t rktio_udp_set_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd, rktio_bool_t on); -RKTIO_EXTERN rktio_tri_t rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd); +RKTIO_EXTERN_ERR(RKTIO_PROP_ERROR) rktio_tri_t rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd); RKTIO_EXTERN rktio_ok_t rktio_udp_set_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd, int ttl_val); #define RKTIO_PROP_ERROR (-2) @@ -487,7 +509,7 @@ RKTIO_EXTERN char *rktio_envvars_get(rktio_t *rktio, rktio_envvars_t *envvars, c RKTIO_EXTERN void rktio_envvars_set(rktio_t *rktio, rktio_envvars_t *envvars, const char *name, const char *value); /* Access/update environment-variables record by name. */ -RKTIO_EXTERN intptr_t rktio_envvars_count(rktio_t *rktio, rktio_envvars_t *envvars); +RKTIO_EXTERN_NOERR intptr_t rktio_envvars_count(rktio_t *rktio, rktio_envvars_t *envvars); RKTIO_EXTERN char *rktio_envvars_name_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i); RKTIO_EXTERN char *rktio_envvars_value_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i); /* Access/update environment-variables record by index. */ @@ -576,7 +598,8 @@ RKTIO_EXTERN rktio_fs_change_t *rktio_fs_change(rktio_t *rktio, const char *path RKTIO_EXTERN void rktio_fs_change_forget(rktio_t *rktio, rktio_fs_change_t *fc); -RKTIO_EXTERN rktio_tri_t rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc); +RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR) +rktio_tri_t rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc); /* Returns one of `RKTIO_POLL_READY`, etc. */ /*************************************************/ @@ -703,7 +726,7 @@ RKTIO_EXTERN rktio_bool_t rktio_directory_exists(rktio_t *rktio, const char *dir RKTIO_EXTERN rktio_bool_t rktio_link_exists(rktio_t *rktio, const char *filename); RKTIO_EXTERN rktio_bool_t rktio_is_regular_file(rktio_t *rktio, const char *filename); -RKTIO_EXTERN rktio_ok_t rktio_delete_file(rktio_t *rktio, const char *fn, int enable_write_on_fail); +RKTIO_EXTERN rktio_ok_t rktio_delete_file(rktio_t *rktio, const char *fn, rktio_bool_t enable_write_on_fail); RKTIO_EXTERN rktio_ok_t rktio_rename_file(rktio_t *rktio, const char *dest, const char *src, int exists_ok); /* Can report `RKTIO_ERROR_EXISTS`. */ @@ -757,7 +780,8 @@ RKTIO_EXTERN rktio_identity_t *rktio_path_identity(rktio_t *rktio, const char *p #define RKTIO_PERMISSION_ERROR (-1) -RKTIO_EXTERN int rktio_get_file_or_directory_permissions(rktio_t *rktio, const char *filename, int all_bits); +RKTIO_EXTERN_ERR(RKTIO_PERMISSION_ERROR) +int rktio_get_file_or_directory_permissions(rktio_t *rktio, const char *filename, int all_bits); /* Result is `RKTIO_PERMISSION_ERROR` for error, otherwise a combination of bits. If not `all_bits`, then use constants above. */ @@ -973,10 +997,11 @@ RKTIO_EXTERN rktio_converter_t *rktio_converter_open(rktio_t *rktio, const char RKTIO_EXTERN void rktio_converter_close(rktio_t *rktio, rktio_converter_t *cvt); /* Destroys an encoding converter. */ -RKTIO_EXTERN intptr_t rktio_convert(rktio_t *rktio, - rktio_converter_t *cvt, - char **in, intptr_t *in_left, - char **out, intptr_t *out_left); +RKTIO_EXTERN_ERR(RKTIO_CONVERT_ERROR) +intptr_t rktio_convert(rktio_t *rktio, + rktio_converter_t *cvt, + char **in, intptr_t *in_left, + char **out, intptr_t *out_left); /* Converts some bytes, following the icon protocol: each consumed by increments `*in` and decrements `*in_left`, and each produced by increments `*out` and decrements `*out_left`. In case of an error, @@ -1005,15 +1030,15 @@ RKTIO_EXTERN rktio_char16_t *rktio_recase_utf16(rktio_t *rktio, Takes and optionally returns a length (`olen` can be NULL), but the UTF-16 sequence is expected to have no nuls. */ -RKTIO_EXTERN int rktio_locale_strcoll(rktio_t *rktio, char *s1, char *s2); +RKTIO_EXTERN_NOERR int rktio_locale_strcoll(rktio_t *rktio, char *s1, char *s2); /* Returns -1 if `s1` is less than `s2` by the current locale's comparison, positive is `s1` is greater, and 0 if the strings are equal. */ -RKTIO_EXTERN int rktio_strcoll_utf16(rktio_t *rktio, - rktio_char16_t *s1, intptr_t l1, - rktio_char16_t *s2, intptr_t l2, - rktio_bool_t cvt_case); +RKTIO_EXTERN_NOERR int rktio_strcoll_utf16(rktio_t *rktio, + rktio_char16_t *s1, intptr_t l1, + rktio_char16_t *s2, intptr_t l2, + rktio_bool_t cvt_case); /* Compares two strings encoded in UTF-16 for the system's default locale if the OS provided direct support for it. The `RKTIO_CONVERT_STRCOLL_UTF16 property from diff --git a/racket/src/rktio/rktio_fd.c b/racket/src/rktio/rktio_fd.c index 6ed2a3a7bc..4656d4095f 100644 --- a/racket/src/rktio/rktio_fd.c +++ b/racket/src/rktio/rktio_fd.c @@ -853,6 +853,16 @@ intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len) return rktio_read_converted(rktio, rfd, buffer, len, NULL); } +intptr_t rktio_read_in(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t start, intptr_t end) +{ + return rktio_read_converted(rktio, rfd, buffer+start, end-start, NULL); +} + +intptr_t rktio_write_in(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr_t start, intptr_t end) +{ + return rktio_write(rktio, rfd, buffer+start, end-start); +} + RKTIO_EXTERN intptr_t rktio_buffered_byte_count(rktio_t *rktio, rktio_fd_t *fd) { #ifdef RKTIO_SYSTEM_UNIX