add more codes to lookup-errno, relax contract (#1433)

lookup-errno now returns #f when given an unknown symbol instead
of raising a contract error. It should not return #f for any
symbol that it previously accepted.
This commit is contained in:
Ryan Culpepper 2016-09-12 18:07:44 -04:00 committed by GitHub
parent 6e6056b9b8
commit fd4ce5afe4
5 changed files with 451 additions and 34 deletions

View File

@ -12,7 +12,7 @@
(define collection 'multi) (define collection 'multi)
(define version "6.6.0.4") (define version "6.6.0.5")
(define deps `("racket-lib" (define deps `("racket-lib"
["racket" #:version ,version])) ["racket" #:version ,version]))

View File

@ -37,12 +37,23 @@ to create mock foreign functions for testing).
@history[#:changed "6.4.0.9"]{Added the one-argument variant.}} @history[#:changed "6.4.0.9"]{Added the one-argument variant.}}
@defproc[(lookup-errno [sym (or/c 'EINTR 'EEXIST 'EAGAIN)]) @defproc[(lookup-errno [sym symbol?])
exact-integer?]{ (or/c exact-integer? #f)]{
Returns a platform-specific value corresponding to a Posix @tt{errno} Returns a platform-specific positive integer corresponding to a POSIX
symbol. The set of supported symbols is likely to expand in the @tt{errno} code, or @racket[#f] if the code is unknown. A code's value
future.} is known if the code is one of the recognized symbols described below
@emph{and} the code was defined by the @tt{"errno.h"} header used to
compile Racket. Note that the contents of @tt{"errno.h"} vary based on
platform and compiler.
The recognized symbols currently consist of the 81 codes defined by
@hyperlink["http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html"]{IEEE
Std 1003.1, 2013 Edition} (also known as POSIX.1), including
@racket['EINTR], @racket['EEXIST], and @racket['EAGAIN].
@history[#:changed "6.6.0.5" @elem{Relaxed the contract and added
support for more symbols.}]}
@defproc[(cast [v any/c] [from-type ctype?] [to-type ctype?]) any/c]{ @defproc[(cast [v any/c] [from-type ctype?] [to-type ctype?]) any/c]{

View File

@ -4326,16 +4326,337 @@ static Scheme_Object *foreign_saved_errno(int argc, Scheme_Object *argv[])
static Scheme_Object *foreign_lookup_errno(int argc, Scheme_Object *argv[]) static Scheme_Object *foreign_lookup_errno(int argc, Scheme_Object *argv[])
{ {
Scheme_Object *v = argv[0]; Scheme_Object *v = argv[0];
if (SCHEME_SYMBOLP(v) && !SCHEME_SYM_WEIRDP(v)) { if (!SCHEME_SYMBOLP(v)) {
if (!strcmp("EINTR", SCHEME_SYM_VAL(v))) scheme_wrong_contract(MYNAME, "symbol?", 0, argc, argv);
return scheme_make_integer(EINTR); return NULL;
if (!strcmp("EEXIST", SCHEME_SYM_VAL(v))) }
return scheme_make_integer(EEXIST); if (SCHEME_SYM_WEIRDP(v))
return scheme_false;
#ifdef E2BIG
if (!strcmp("E2BIG", SCHEME_SYM_VAL(v)))
return scheme_make_integer(E2BIG);
#endif
#ifdef EACCES
if (!strcmp("EACCES", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EACCES);
#endif
#ifdef EADDRINUSE
if (!strcmp("EADDRINUSE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EADDRINUSE);
#endif
#ifdef EADDRNOTAVAIL
if (!strcmp("EADDRNOTAVAIL", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EADDRNOTAVAIL);
#endif
#ifdef EAFNOSUPPORT
if (!strcmp("EAFNOSUPPORT", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EAFNOSUPPORT);
#endif
#ifdef EAGAIN
if (!strcmp("EAGAIN", SCHEME_SYM_VAL(v))) if (!strcmp("EAGAIN", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EAGAIN); return scheme_make_integer(EAGAIN);
} #endif
scheme_wrong_contract(MYNAME, "(or/c 'EINTR 'EEXIST 'EAGAIN)",0, argc, argv); #ifdef EALREADY
return NULL; if (!strcmp("EALREADY", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EALREADY);
#endif
#ifdef EBADF
if (!strcmp("EBADF", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EBADF);
#endif
#ifdef EBADMSG
if (!strcmp("EBADMSG", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EBADMSG);
#endif
#ifdef EBUSY
if (!strcmp("EBUSY", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EBUSY);
#endif
#ifdef ECANCELED
if (!strcmp("ECANCELED", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ECANCELED);
#endif
#ifdef ECHILD
if (!strcmp("ECHILD", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ECHILD);
#endif
#ifdef ECONNABORTED
if (!strcmp("ECONNABORTED", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ECONNABORTED);
#endif
#ifdef ECONNREFUSED
if (!strcmp("ECONNREFUSED", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ECONNREFUSED);
#endif
#ifdef ECONNRESET
if (!strcmp("ECONNRESET", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ECONNRESET);
#endif
#ifdef EDEADLK
if (!strcmp("EDEADLK", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EDEADLK);
#endif
#ifdef EDESTADDRREQ
if (!strcmp("EDESTADDRREQ", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EDESTADDRREQ);
#endif
#ifdef EDOM
if (!strcmp("EDOM", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EDOM);
#endif
#ifdef EDQUOT
if (!strcmp("EDQUOT", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EDQUOT);
#endif
#ifdef EEXIST
if (!strcmp("EEXIST", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EEXIST);
#endif
#ifdef EFAULT
if (!strcmp("EFAULT", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EFAULT);
#endif
#ifdef EFBIG
if (!strcmp("EFBIG", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EFBIG);
#endif
#ifdef EHOSTUNREACH
if (!strcmp("EHOSTUNREACH", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EHOSTUNREACH);
#endif
#ifdef EIDRM
if (!strcmp("EIDRM", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EIDRM);
#endif
#ifdef EILSEQ
if (!strcmp("EILSEQ", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EILSEQ);
#endif
#ifdef EINPROGRESS
if (!strcmp("EINPROGRESS", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EINPROGRESS);
#endif
#ifdef EINTR
if (!strcmp("EINTR", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EINTR);
#endif
#ifdef EINVAL
if (!strcmp("EINVAL", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EINVAL);
#endif
#ifdef EIO
if (!strcmp("EIO", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EIO);
#endif
#ifdef EISCONN
if (!strcmp("EISCONN", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EISCONN);
#endif
#ifdef EISDIR
if (!strcmp("EISDIR", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EISDIR);
#endif
#ifdef ELOOP
if (!strcmp("ELOOP", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ELOOP);
#endif
#ifdef EMFILE
if (!strcmp("EMFILE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EMFILE);
#endif
#ifdef EMLINK
if (!strcmp("EMLINK", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EMLINK);
#endif
#ifdef EMSGSIZE
if (!strcmp("EMSGSIZE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EMSGSIZE);
#endif
#ifdef EMULTIHOP
if (!strcmp("EMULTIHOP", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EMULTIHOP);
#endif
#ifdef ENAMETOOLONG
if (!strcmp("ENAMETOOLONG", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENAMETOOLONG);
#endif
#ifdef ENETDOWN
if (!strcmp("ENETDOWN", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENETDOWN);
#endif
#ifdef ENETRESET
if (!strcmp("ENETRESET", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENETRESET);
#endif
#ifdef ENETUNREACH
if (!strcmp("ENETUNREACH", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENETUNREACH);
#endif
#ifdef ENFILE
if (!strcmp("ENFILE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENFILE);
#endif
#ifdef ENOBUFS
if (!strcmp("ENOBUFS", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOBUFS);
#endif
#ifdef ENODATA
if (!strcmp("ENODATA", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENODATA);
#endif
#ifdef ENODEV
if (!strcmp("ENODEV", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENODEV);
#endif
#ifdef ENOENT
if (!strcmp("ENOENT", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOENT);
#endif
#ifdef ENOEXEC
if (!strcmp("ENOEXEC", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOEXEC);
#endif
#ifdef ENOLCK
if (!strcmp("ENOLCK", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOLCK);
#endif
#ifdef ENOLINK
if (!strcmp("ENOLINK", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOLINK);
#endif
#ifdef ENOMEM
if (!strcmp("ENOMEM", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOMEM);
#endif
#ifdef ENOMSG
if (!strcmp("ENOMSG", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOMSG);
#endif
#ifdef ENOPROTOOPT
if (!strcmp("ENOPROTOOPT", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOPROTOOPT);
#endif
#ifdef ENOSPC
if (!strcmp("ENOSPC", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOSPC);
#endif
#ifdef ENOSR
if (!strcmp("ENOSR", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOSR);
#endif
#ifdef ENOSTR
if (!strcmp("ENOSTR", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOSTR);
#endif
#ifdef ENOSYS
if (!strcmp("ENOSYS", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOSYS);
#endif
#ifdef ENOTCONN
if (!strcmp("ENOTCONN", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOTCONN);
#endif
#ifdef ENOTDIR
if (!strcmp("ENOTDIR", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOTDIR);
#endif
#ifdef ENOTEMPTY
if (!strcmp("ENOTEMPTY", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOTEMPTY);
#endif
#ifdef ENOTRECOVERABLE
if (!strcmp("ENOTRECOVERABLE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOTRECOVERABLE);
#endif
#ifdef ENOTSOCK
if (!strcmp("ENOTSOCK", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOTSOCK);
#endif
#ifdef ENOTSUP
if (!strcmp("ENOTSUP", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOTSUP);
#endif
#ifdef ENOTTY
if (!strcmp("ENOTTY", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENOTTY);
#endif
#ifdef ENXIO
if (!strcmp("ENXIO", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ENXIO);
#endif
#ifdef EOPNOTSUPP
if (!strcmp("EOPNOTSUPP", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EOPNOTSUPP);
#endif
#ifdef EOVERFLOW
if (!strcmp("EOVERFLOW", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EOVERFLOW);
#endif
#ifdef EOWNERDEAD
if (!strcmp("EOWNERDEAD", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EOWNERDEAD);
#endif
#ifdef EPERM
if (!strcmp("EPERM", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EPERM);
#endif
#ifdef EPIPE
if (!strcmp("EPIPE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EPIPE);
#endif
#ifdef EPROTO
if (!strcmp("EPROTO", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EPROTO);
#endif
#ifdef EPROTONOSUPPORT
if (!strcmp("EPROTONOSUPPORT", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EPROTONOSUPPORT);
#endif
#ifdef EPROTOTYPE
if (!strcmp("EPROTOTYPE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EPROTOTYPE);
#endif
#ifdef ERANGE
if (!strcmp("ERANGE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ERANGE);
#endif
#ifdef EROFS
if (!strcmp("EROFS", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EROFS);
#endif
#ifdef ESPIPE
if (!strcmp("ESPIPE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ESPIPE);
#endif
#ifdef ESRCH
if (!strcmp("ESRCH", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ESRCH);
#endif
#ifdef ESTALE
if (!strcmp("ESTALE", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ESTALE);
#endif
#ifdef ETIME
if (!strcmp("ETIME", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ETIME);
#endif
#ifdef ETIMEDOUT
if (!strcmp("ETIMEDOUT", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ETIMEDOUT);
#endif
#ifdef ETXTBSY
if (!strcmp("ETXTBSY", SCHEME_SYM_VAL(v)))
return scheme_make_integer(ETXTBSY);
#endif
#ifdef EWOULDBLOCK
if (!strcmp("EWOULDBLOCK", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EWOULDBLOCK);
#endif
#ifdef EXDEV
if (!strcmp("EXDEV", SCHEME_SYM_VAL(v)))
return scheme_make_integer(EXDEV);
#endif
return scheme_false;
} }
#undef MYNAME #undef MYNAME

View File

@ -3469,27 +3469,112 @@ static void save_errno_values(int kind)
} }
} }
@(define standard-errnos
;; Error codes defined by IEEE Std 1003.1, 2013 Edition
;; (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html)
;; Linux, Mac, *BSD, MinGW all seem to support most (but not necessarily all)
;; of these codes.
'(E2BIG
EACCES
EADDRINUSE
EADDRNOTAVAIL
EAFNOSUPPORT
EAGAIN
EALREADY
EBADF
EBADMSG
EBUSY
ECANCELED
ECHILD
ECONNABORTED
ECONNREFUSED
ECONNRESET
EDEADLK
EDESTADDRREQ
EDOM
EDQUOT
EEXIST
EFAULT
EFBIG
EHOSTUNREACH
EIDRM
EILSEQ
EINPROGRESS
EINTR
EINVAL
EIO
EISCONN
EISDIR
ELOOP
EMFILE
EMLINK
EMSGSIZE
EMULTIHOP
ENAMETOOLONG
ENETDOWN
ENETRESET
ENETUNREACH
ENFILE
ENOBUFS
ENODATA
ENODEV
ENOENT
ENOEXEC
ENOLCK
ENOLINK
ENOMEM
ENOMSG
ENOPROTOOPT
ENOSPC
ENOSR
ENOSTR
ENOSYS
ENOTCONN
ENOTDIR
ENOTEMPTY
ENOTRECOVERABLE
ENOTSOCK
ENOTSUP
ENOTTY
ENXIO
EOPNOTSUPP
EOVERFLOW
EOWNERDEAD
EPERM
EPIPE
EPROTO
EPROTONOSUPPORT
EPROTOTYPE
ERANGE
EROFS
ESPIPE
ESRCH
ESTALE
ETIME
ETIMEDOUT
ETXTBSY
EWOULDBLOCK
EXDEV))
@cdefine[lookup-errno 1 #:kind immed]{ @cdefine[lookup-errno 1 #:kind immed]{
Scheme_Object *v = argv[0]; Scheme_Object *v = argv[0];
@(let* ([errnos '(EINTR EEXIST EAGAIN)] @(let ()
[syms (string-append
"(or/c "
(let loop ([errnos errnos])
(if (null? (cdr errnos))
(format "'~a" (car errnos))
(format "'~a ~a" (car errnos) (loop (cdr errnos)))))
")")])
@list{ @list{
if (SCHEME_SYMBOLP(v) && !SCHEME_SYM_WEIRDP(v)) { if (!SCHEME_SYMBOLP(v)) {
scheme_wrong_contract(MYNAME, "symbol?", 0, argc, argv);
return NULL;
}
if (SCHEME_SYM_WEIRDP(v))
return scheme_false;
@(add-newlines @(add-newlines
(for/list ([e errnos]) (for/list ([e standard-errnos])
@string-append{ @string-append{
#ifdef @symbol->string[e]
if (!strcmp("@symbol->string[e]", SCHEME_SYM_VAL(v))) if (!strcmp("@symbol->string[e]", SCHEME_SYM_VAL(v)))
return scheme_make_integer(@symbol->string[e]); return scheme_make_integer(@symbol->string[e]);
#endif
})) }))
} return scheme_false;
scheme_wrong_contract(MYNAME, "@syms",0, argc, argv);
return NULL;
}) })
} }

View File

@ -13,12 +13,12 @@
consistently.) consistently.)
*/ */
#define MZSCHEME_VERSION "6.6.0.4" #define MZSCHEME_VERSION "6.6.0.5"
#define MZSCHEME_VERSION_X 6 #define MZSCHEME_VERSION_X 6
#define MZSCHEME_VERSION_Y 6 #define MZSCHEME_VERSION_Y 6
#define MZSCHEME_VERSION_Z 0 #define MZSCHEME_VERSION_Z 0
#define MZSCHEME_VERSION_W 4 #define MZSCHEME_VERSION_W 5
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y) #define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W) #define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)