diff options
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | ftw.c | 4 | ||||
-rw-r--r-- | lib.c | 39 | ||||
-rw-r--r-- | lib.h | 2 | ||||
-rw-r--r-- | parser.c | 4 | ||||
-rw-r--r-- | socket.c | 70 | ||||
-rw-r--r-- | stdlib/doc-syms.tl | 26 | ||||
-rw-r--r-- | stream.c | 94 | ||||
-rw-r--r-- | sysif.c | 150 | ||||
-rw-r--r-- | termios.c | 28 | ||||
-rw-r--r-- | tests/018/errno.tl | 8 | ||||
-rw-r--r-- | txr.1 | 109 | ||||
-rw-r--r-- | unwind.c | 15 | ||||
-rw-r--r-- | unwind.h | 1 |
14 files changed, 365 insertions, 187 deletions
@@ -7145,6 +7145,8 @@ void eval_init(void) reg_fun(intern(lit("downcase-str"), user_package), func_n1(downcase_str)); reg_fun(intern(lit("string-extend"), user_package), func_n3o(string_extend, 2)); reg_fun(intern(lit("string-finish"), user_package), func_n1(string_finish)); + reg_fun(intern(lit("string-set-code"), user_package), func_n2(string_set_code)); + reg_fun(intern(lit("string-get-code"), user_package), func_n1(string_get_code)); reg_fun(intern(lit("stringp"), user_package), func_n1(stringp)); reg_fun(intern(lit("lazy-stringp"), user_package), func_n1(lazy_stringp)); reg_fun(intern(lit("length-str"), user_package), func_n1(length_str)); @@ -130,8 +130,8 @@ val ftw_wrap(val dirpath, val fn, val flags_in, val nopenfd_in) case -1: { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("~a ~a: ~d/~s"), - self, dirpath, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("~a ~a: ~d/~s"), + self, dirpath, num(eno), errno_to_str(eno), nao); } default: return num(res); @@ -4862,6 +4862,45 @@ val string_finish(val str) return str; } +val string_set_code(val str, val code) +{ + val self = lit("string-set-code"); + type_check(self, str, STR); + + { + cnum len = c_fixnum(length_str(str), self); + cnum alloc = c_fixnum(str->st.alloc, self); + + if (alloc < len + 2) { + string_extend(str, one, t); + alloc = c_fixnum(str->st.alloc, self); + set(mkloc(str->st.len, str), num(len)); + } + + { + str->st.str[len + 1] = c_int(code, self); + } + } + + return str; +} + +val string_get_code(val str) +{ + val self = lit("string-get-code"); + type_check(self, str, STR); + + { + cnum len = c_fixnum(length_str(str), self); + cnum alloc = c_fixnum(str->st.alloc, self); + + if (alloc >= len + 2) + return num(str->st.str[len + 1]); + } + + return nil; +} + val stringp(val str) { switch (type(str)) { @@ -886,6 +886,8 @@ val upcase_str(val str); val downcase_str(val str); val string_extend(val str, val tail, val finish); val string_finish(val str); +val string_set_code(val str, val code); +val string_get_code(val str); val stringp(val str); val lazy_stringp(val str); val length_str(val str); @@ -596,8 +596,8 @@ void open_txr_file(val spec_file, val *txr_lisp_p, val *name, val *stream, #ifdef ENOENT except: #endif - uw_throwf(errno_to_file_error(errno), - lit("unable to open ~a"), spec_file_try, nao); + uw_ethrowf(errno_to_file_error(errno), + lit("unable to open ~a"), spec_file_try, nao); } found: @@ -382,8 +382,8 @@ static void dgram_overflow(val stream) * increasing the datagram size. */ struct dgram_stream *d = coerce(struct dgram_stream *, stream->co.handle); - d->err = ENOBUFS; - uw_throwf(socket_error_s, lit("dgram write overflow on ~s"), stream, nao); + errno = d->err = ENOBUFS; + uw_ethrowf(socket_error_s, lit("dgram write overflow on ~s"), stream, nao); } static int dgram_put_byte_callback(int b, mem_t *ctx) @@ -444,9 +444,9 @@ static int dgram_get_byte_callback(mem_t *ctx) if (nbytes == -1) { d->err = errno; - uw_throwf(socket_error_s, - lit("get-byte: recv on ~s failed: ~d/~s"), - d->stream, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, + lit("get-byte: recv on ~s failed: ~d/~s"), + d->stream, num(errno), errno_to_str(errno), nao); } uw_unwind { @@ -531,21 +531,21 @@ static val dgram_flush(val stream) if (nwrit != d->tx_pos) { d->err = (nwrit < 0) ? errno : ENOBUFS; - uw_throwf(socket_error_s, - lit("flush-stream: sendto on ~s ~a: ~d/~s"), - stream, - (nwrit < 0) ? lit("failed") : lit("truncated"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, + lit("flush-stream: sendto on ~s ~a: ~d/~s"), + stream, + (nwrit < 0) ? lit("failed") : lit("truncated"), + num(errno), errno_to_str(errno), nao); } free(d->tx_buf); d->tx_buf = 0; d->tx_pos = 0; } else { - d->err = ENOTCONN; - uw_throwf(socket_error_s, - lit("flush-stream: cannot transmit on ~s: peer not set"), - stream, nao); + errno = d->err = ENOTCONN; + uw_ethrowf(socket_error_s, + lit("flush-stream: cannot transmit on ~s: peer not set"), + stream, nao); } } return t; @@ -712,8 +712,8 @@ static val sock_bind(val sock, val sockaddr) sockaddr_pack(sockaddr, family, &sa, &salen, self); if (bind(fd, coerce(struct sockaddr *, &sa), salen) != 0) - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); stream_set_prop(sock, addr_k, sockaddr); return t; @@ -807,8 +807,8 @@ static int to_connect(int fd, struct sockaddr *addr, socklen_t len, case -1: return -1; case 0: - uw_throwf(timeout_error_s, lit("~a: ~s: timeout on ~s"), - self, sock, sockaddr, nao); + uw_ethrowf(timeout_error_s, lit("~a: ~s: timeout on ~s"), + self, sock, sockaddr, nao); default: return 0; } @@ -842,8 +842,8 @@ static val open_sockfd(val fd, val family, val type, val mode_str, val self) if (!f) { int eno = errno; close(c_num(fd, self)); - uw_throwf(errno_to_file_error(eno), lit("error creating stream for socket ~a: ~d/~s"), - fd, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("error creating stream for socket ~a: ~d/~s"), + fd, num(eno), errno_to_str(eno), nao); } return set_mode_props(m, make_sock_stream(f, family, type)); @@ -864,8 +864,8 @@ static val sock_connect(val sock, val sockaddr, val timeout) if (to_connect(c_num(sfd, self), coerce(struct sockaddr *, &sa), salen, sock, sockaddr, default_null_arg(timeout), self) != 0) - uw_throwf(socket_error_s, lit("~a: ~s to addr ~s: ~d/~s"), - self, sock, sockaddr, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a: ~s to addr ~s: ~d/~s"), + self, sock, sockaddr, num(errno), errno_to_str(errno), nao); sock_set_peer(sock, sockaddr); @@ -925,8 +925,8 @@ static val sock_listen(val sock, val backlog) return t; failed: - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); } static val sock_accept(val sock, val mode_str, val timeout_in) @@ -952,7 +952,7 @@ static val sock_accept(val sock, val mode_str, val timeout_in) case -1: goto badfd; case 0: - uw_throwf(timeout_error_s, lit("~a: ~s: timeout"), self, sock, nao); + uw_ethrowf(timeout_error_s, lit("~a: ~s: timeout"), self, sock, nao); default: break; } @@ -1038,11 +1038,11 @@ static val sock_accept(val sock, val mode_str, val timeout_in) } } failed: - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), self, num(errno), errno_to_str(errno), nao); badfd: - uw_throwf(socket_error_s, lit("~a: cannot accept on ~s"), - self, sock, nao); + uw_ethrowf(socket_error_s, lit("~a: cannot accept on ~s"), + self, sock, nao); } static val sock_shutdown(val sock, val how) @@ -1053,8 +1053,8 @@ static val sock_shutdown(val sock, val how) flush_stream(sock); if (shutdown(c_num(sfd, self), c_num(default_arg(how, num_fast(SHUT_WR)), self))) - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); return t; } @@ -1070,9 +1070,9 @@ static val sock_timeout(val sock, val usec, val name, int which, val self) tv.tv_usec = u % 1000000; if (setsockopt(fd, SOL_SOCKET, which, &tv, sizeof tv) != 0) - uw_throwf(socket_error_s, lit("~a failed on ~s: ~d/~s"), - name, sock, num(errno), - errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed on ~s: ~d/~s"), + name, sock, num(errno), + errno_to_str(errno), nao); return sock; } @@ -1118,8 +1118,8 @@ static val socketpair_wrap(val family, val type, val mode_str) uw_simple_catch_begin; if (res < 0) - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); #if SOCK_NONBLOCK || SOCK_CLOEXEC type = num_fast(c_num(type, self) & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)); diff --git a/stdlib/doc-syms.tl b/stdlib/doc-syms.tl index 2f95f333..8875254b 100644 --- a/stdlib/doc-syms.tl +++ b/stdlib/doc-syms.tl @@ -81,7 +81,7 @@ ("<!" "N-02B10DF9") ("<-" "N-02B10DF9") ("<=" "D-001E") - ("=" "D-0077") + ("=" "D-0078") (">" "D-0060") (">=" "D-0053") ("TXR_COMPAT" "N-03F5D03D") @@ -296,8 +296,8 @@ ("cdar" "N-001FA3CB") ("cdddddr" "N-001FA3CB") ("cddr" "N-001FA3CB") - ("cdr" "D-0076") - ("ceil" "D-007B") + ("cdr" "D-0077") + ("ceil" "D-007C") ("ceil-rem" "N-02DE978F") ("ceil1" "N-02C8FF28") ("chain" "N-00C53CF7") @@ -409,7 +409,7 @@ ("copy-tree-iter" "N-025C3140") ("copy-vec" "N-010E7635") ("cos" "D-0021") - ("cosh" "D-007F") + ("cosh" "D-0080") ("count-if" "N-00BBC726") ("count-until-match" "N-00EFD668") ("countq" "N-01DF131F") @@ -637,11 +637,11 @@ ("eprototype" "N-036B1BDB") ("eq" "N-02550B35") ("eql" "N-02550B35") - ("equal" "D-0079") + ("equal" "D-007A") ("equot" "N-02ACCDDF") ("erange" "N-036B1BDB") ("erofs" "N-036B1BDB") - ("errno" "N-03A7137C") + ("errno" "D-0076") ("error" "N-015466AD") ("espipe" "N-036B1BDB") ("esrch" "N-036B1BDB") @@ -726,7 +726,7 @@ ("file-put" "N-0041C2E5") ("file-put-buf" "N-02AE3A31") ("file-put-json" "D-002A") - ("file-put-jsons" "D-007C") + ("file-put-jsons" "D-007D") ("file-put-lines" "N-0041C2E5") ("file-put-string" "N-0041C2E5") ("fileno" "N-008ACF75") @@ -739,7 +739,7 @@ ("filter-equal" "N-03136087") ("filter-string-tree" "N-00C9EEB0") ("finalize" "N-01230613") - ("finally" "D-0078") + ("finally" "D-0079") ("find" "N-00C9DFF6") ("find-frame" "N-02B97226") ("find-frames" "N-02B97226") @@ -1114,7 +1114,7 @@ ("listp" "N-03F70343") ("lnew" "N-0230059D") ("lnew*" "N-021E6FDC") - ("load" "D-0080") + ("load" "D-0081") ("load-for" "N-0020A085") ("load-time" "D-0047") ("loff-t" "N-01153D9E") @@ -1476,7 +1476,7 @@ ("push-after-load" "N-01F489FE") ("pushhash" "N-022660B2") ("pushnew" "N-02C37AB0") - ("put-buf" "D-007E") + ("put-buf" "D-007F") ("put-byte" "D-002F") ("put-carray" "N-00737951") ("put-char" "D-0003") @@ -1486,7 +1486,7 @@ ("put-line" "N-012163C3") ("put-lines" "N-0367B282") ("put-obj" "N-025DB229") - ("put-string" "D-007A") + ("put-string" "D-007B") ("put-strings" "N-0367B282") ("pwd" "N-0047F5F6") ("qquote" "N-01665185") @@ -1572,7 +1572,7 @@ ("replace-struct" "N-01A8343B") ("replace-tree-iter" "N-01225FF3") ("replace-vec" "N-01F59E62") - ("require" "D-007D") + ("require" "D-007E") ("reset-struct" "N-002A609F") ("rest" "N-02288559") ("ret" "N-033F39EF") @@ -1820,7 +1820,9 @@ ("string-encode" "N-033502F8") ("string-extend" "N-03D5358A") ("string-finish" "N-0295275B") + ("string-get-code" "N-01CF6D14") ("string-lt" "N-03ABBED1") + ("string-set-code" "N-01CF6D14") ("stringp" "N-00BB392B") ("strsignal" "N-00234BED") ("struct" "D-001B") @@ -459,8 +459,8 @@ static val dev_null_get_fd(val stream) struct dev_null *n = coerce(struct dev_null *, stream->co.handle); if (n->fd == -1 && (n->fd = open("/dev/null", O_RDWR)) == -1) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("error opening /dev/null: ~d/~s"), - num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("error opening /dev/null: ~d/~s"), + num(eno), errno_to_str(eno), nao); } return num(n->fd); } @@ -596,10 +596,10 @@ static val stdio_maybe_read_error(val stream) h->err = err; #ifdef EAGAIN if (errno == EAGAIN) - uw_throwf(timeout_error_s, lit("timed out reading ~s"), stream, nao); + uw_ethrowf(timeout_error_s, lit("timed out reading ~s"), stream, nao); #endif - uw_throwf(file_error_s, lit("error reading ~s: ~d/~s"), - stream, err, errno_to_string(err), nao); + uw_ethrowf(file_error_s, lit("error reading ~s: ~d/~s"), + stream, err, errno_to_string(err), nao); } if (feof(h->f)) h->err = t; @@ -611,14 +611,14 @@ static val stdio_maybe_error(val stream, val action) struct stdio_handle *h = coerce(struct stdio_handle *, stream->co.handle); val err = num(errno); if (h->f == 0) - uw_throwf(file_error_s, lit("error ~a ~s: file closed"), action, stream, nao); + uw_ethrowf(file_error_s, lit("error ~a ~s: file closed"), action, stream, nao); h->err = err; #ifdef EAGAIN if (errno == EAGAIN) - uw_throwf(timeout_error_s, lit("timed out on ~s"), stream, nao); + uw_ethrowf(timeout_error_s, lit("timed out on ~s"), stream, nao); #endif - uw_throwf(file_error_s, lit("error ~a ~s: ~d/~s"), - action, stream, err, errno_to_string(err), nao); + uw_ethrowf(file_error_s, lit("error ~a ~s: ~d/~s"), + action, stream, err, errno_to_string(err), nao); } static int se_putc(int ch, FILE *f) @@ -982,8 +982,8 @@ static val stdio_close(val stream, val throw_on_error) h->f = 0; if (result == EOF && default_null_arg(throw_on_error)) { h->err = num(errno); - uw_throwf(file_error_s, lit("error closing ~s: ~d/~s"), - stream, num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("error closing ~s: ~d/~s"), + stream, num(errno), errno_to_str(errno), nao); } return result != EOF ? t : nil; } @@ -1377,9 +1377,9 @@ static val pipe_close(val stream, val throw_on_error) if (status < 0) { if (throw_on_error) - uw_throwf(process_error_s, - lit("unable to obtain status of command ~s: ~d/~s"), - stream, num(errno), errno_to_str(errno), nao); + uw_ethrowf(process_error_s, + lit("unable to obtain status of command ~s: ~d/~s"), + stream, num(errno), errno_to_str(errno), nao); } else { #if HAVE_SYS_WAIT if (default_null_arg(throw_on_error)) { @@ -4202,9 +4202,9 @@ val open_directory(val path) if (!d) { int eno = errno; - uw_throwf(errno_to_file_error(eno), - lit("error opening directory ~s: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), + lit("error opening directory ~s: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } return make_dir_stream(d); @@ -4219,8 +4219,8 @@ val open_file(val path, val mode_str) if (!f) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("error opening ~s: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("error opening ~s: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } return set_mode_props(m, make_stdio_stream(f, path)); @@ -4237,8 +4237,8 @@ val open_fileno(val fd, val mode_str) if (!f) { int eno = errno; close(c_num(fd, self)); - uw_throwf(errno_to_file_error(eno), lit("error opening descriptor ~a: ~d/~s"), - fd, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("error opening descriptor ~a: ~d/~s"), + fd, num(eno), errno_to_str(eno), nao); } return set_mode_props(m, make_stdio_stream(f, format(nil, @@ -4258,8 +4258,8 @@ val open_tail(val path, val mode_str, val seek_end_p) if (f && default_null_arg(seek_end_p)) if (fseek(f, 0, SEEK_END) < 0) - uw_throwf(file_error_s, lit("error seeking to end of ~s: ~d/~s"), - path, num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("error seeking to end of ~s: ~d/~s"), + path, num(errno), errno_to_str(errno), nao); stream = make_tail_stream(f, path); h = coerce(struct stdio_handle *, stream->co.handle); @@ -4314,8 +4314,8 @@ static int fds_subst(int fd_sub, int fd_std, val self) return fd_dup; } - uw_throwf(file_error_s, lit("~a: failed to duplicate file descriptor: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("~a: failed to duplicate file descriptor: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); } } #endif @@ -4419,9 +4419,9 @@ static val open_subprocess(val name, val mode_str, val args, val fun) if (pipe(fd) == -1) { int eno = errno; free(argv); - uw_throwf(errno_to_file_error(eno), - lit("opening pipe ~s, pipe syscall failed: ~d/~s"), - name, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), + lit("opening pipe ~s, pipe syscall failed: ~d/~s"), + name, num(eno), errno_to_str(eno), nao); } if (argv) { @@ -4440,8 +4440,8 @@ static val open_subprocess(val name, val mode_str, val args, val fun) free(argv[i]); free(argv); } - uw_throwf(process_error_s, lit("opening pipe ~s, fork syscall failed: ~d/~s"), - name, num(errno), errno_to_str(errno), nao); + uw_ethrowf(process_error_s, lit("opening pipe ~s, fork syscall failed: ~d/~s"), + name, num(errno), errno_to_str(errno), nao); } if (pid == 0) { @@ -4523,8 +4523,8 @@ static val open_subprocess(val name, val mode_str, val args, val fun) while (waitpid(pid, &status, 0) == -1 && errno == EINTR) ; free(utf8mode); - uw_throwf(file_error_s, lit("opening pipe ~s, fdopen failed: ~d/~s"), - name, num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("opening pipe ~s, fdopen failed: ~d/~s"), + name, num(errno), errno_to_str(errno), nao); } free(utf8mode); @@ -4581,8 +4581,8 @@ val open_command(val path, val mode_str) if (!f) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("~a: error opening pipe ~s: ~d/~s"), - self, path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("~a: error opening pipe ~s: ~d/~s"), + self, path, num(eno), errno_to_str(eno), nao); } uw_unwind { @@ -4802,8 +4802,8 @@ static val run(val name, val args) for (i = 0; i < nargs; i++) free(argv[i]); free(argv); - uw_throwf(process_error_s, lit("opening process ~s, fork syscall failed: ~d/~s"), - name, num(errno), errno_to_str(errno), nao); + uw_ethrowf(process_error_s, lit("opening process ~s, fork syscall failed: ~d/~s"), + name, num(errno), errno_to_str(errno), nao); } if (pid == 0) { @@ -4849,8 +4849,8 @@ val remove_path(val path, val throw_on_error) if (w_remove(c_str(path, self)) < 0) { if (default_null_arg(throw_on_error) || errno != ENOENT) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("trying to remove ~s: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("trying to remove ~s: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } return nil; } @@ -4864,9 +4864,9 @@ val rename_path(val from, val to) if (w_rename(c_str(from, self), c_str(to, self)) < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), - lit("trying to rename ~s to ~s: ~d/~s"), - from, to, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), + lit("trying to rename ~s to ~s: ~d/~s"), + from, to, num(eno), errno_to_str(eno), nao); } return t; @@ -5312,8 +5312,8 @@ val tmpfile_wrap(void) FILE *tf = tmpfile(); if (tf != 0) return set_mode_props(m, make_stdio_stream(tf, self)); - uw_throwf(file_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); } #if HAVE_MKDTEMP @@ -5330,8 +5330,8 @@ val mkdtemp_wrap(val prefix) } free(tmpl); - uw_throwf(file_error_s, lit("mkdtemp failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("mkdtemp failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); } #endif @@ -5364,8 +5364,8 @@ val mkstemp_wrap(val prefix, val suffix) stream_set_prop(stream, name_k, name); return stream; } - uw_throwf(file_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); } #endif @@ -389,8 +389,8 @@ static val mkdir_wrap(val path, val mode) if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("mkdir ~a: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("mkdir ~a: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } return t; @@ -403,8 +403,8 @@ static val mkdir_wrap(val path, val mode) (void) mode; if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("mkdir ~a: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("mkdir ~a: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } return t; @@ -522,9 +522,9 @@ static val ensure_dir(val path, val mode) if (integerp(ret)) { int eno = c_num(ret, self); - uw_throwf(errno_to_file_error(eno), - lit("ensure-dir: ~a: ~d/~s"), path, ret, - errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), + lit("ensure-dir: ~a: ~d/~s"), path, ret, + errno_to_str(eno), nao); } return ret; @@ -541,8 +541,8 @@ static val chdir_wrap(val path) if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("chdir ~a: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("chdir ~a: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } return t; @@ -559,13 +559,13 @@ val getcwd_wrap(void) int eno = errno; free(u8buf); if (eno != ERANGE) { - uw_throwf(errno_to_file_error(eno), lit("getcwd: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("getcwd: ~d/~s"), + num(errno), errno_to_str(errno), nao); } if (2 * guess > guess) guess *= 2; else - uw_throwf(file_error_s, lit("getcwd: weird problem"), nao); + uw_ethrowf(file_error_s, lit("getcwd: weird problem"), nao); } else { val out = string_utf8(u8buf); free(u8buf); @@ -583,8 +583,8 @@ static val rmdir_wrap(val path) if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("rmdir ~a: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("rmdir ~a: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } return t; @@ -627,13 +627,13 @@ static val mknod_wrap(val path, val mode, val dev) if (err < 0) { int eno = errno; #if HAVE_MAKEDEV - uw_throwf(errno_to_file_error(eno), lit("mknod ~a ~a ~a (~d:~d): ~d/~s"), - path, mode, dev, major_wrap(dev), minor_wrap(dev), num(eno), - errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("mknod ~a ~a ~a (~d:~d): ~d/~s"), + path, mode, dev, major_wrap(dev), minor_wrap(dev), num(eno), + errno_to_str(eno), nao); #else - uw_throwf(errno_to_file_error(eno), lit("mknod ~a ~a ~a: ~d/~s"), - path, mode, dev, num(eno), - errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("mknod ~a ~a ~a: ~d/~s"), + path, mode, dev, num(eno), + errno_to_str(eno), nao); #endif } @@ -654,9 +654,9 @@ static val mkfifo_wrap(val path, val mode) if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("mknod ~a ~a: ~d/~s"), - path, mode, num(eno), - errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("mknod ~a ~a: ~d/~s"), + path, mode, num(eno), + errno_to_str(eno), nao); } return t; @@ -833,11 +833,11 @@ inval: val errstr = errno_to_str(eno); if (stringp(mode)) - uw_throwf(error, lit("~a ~a ~a: ~d/~s"), - self, target, mode, num(eno), errstr, nao); + uw_ethrowf(error, lit("~a ~a ~a: ~d/~s"), + self, target, mode, num(eno), errstr, nao); else - uw_throwf(error, lit("~a ~a #o~o: ~d/~s"), - self, target, mode, num(eno), errstr, nao); + uw_ethrowf(error, lit("~a ~a #o~o: ~d/~s"), + self, target, mode, num(eno), errstr, nao); } return t; @@ -864,9 +864,9 @@ static val do_chown(val target, val uid, val gid, val link_p, val self) if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("~a ~a ~a ~a: ~d/~s"), - self, target, uid, gid, num(eno), - errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("~a ~a ~a ~a: ~d/~s"), + self, target, uid, gid, num(eno), + errno_to_str(eno), nao); } return t; @@ -899,8 +899,8 @@ static val symlink_wrap(val target, val to) if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("symlink ~a ~a: ~d/~s"), - target, to, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("symlink ~a ~a: ~d/~s"), + target, to, num(eno), errno_to_str(eno), nao); } return t; @@ -919,8 +919,8 @@ static val link_wrap(val target, val to) if (err < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("link ~a ~a: ~d/~s"), - target, to, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("link ~a ~a: ~d/~s"), + target, to, num(eno), errno_to_str(eno), nao); } return t; @@ -941,12 +941,12 @@ static val readlink_wrap(val path) if (2 * guess > guess) guess *= 2; else - uw_throwf(file_error_s, lit("readlink: weird problem"), nao); + uw_ethrowf(file_error_s, lit("readlink: weird problem"), nao); } else if (bytes <= 0) { int eno = errno; free(u8buf); - uw_throwf(errno_to_file_error(eno), lit("readlink ~a: ~d/~s"), - path, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("readlink ~a: ~d/~s"), + path, num(eno), errno_to_str(eno), nao); } else { val out; u8buf[bytes] = 0; @@ -1120,8 +1120,8 @@ static val close_wrap(val fd, val throw_on_error) if (res < 0) { if (default_null_arg(throw_on_error)) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("close ~a: ~d/~s"), - fd, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("close ~a: ~d/~s"), + fd, num(eno), errno_to_str(eno), nao); } return nil; } @@ -1148,8 +1148,8 @@ val exec_wrap(val file, val args_opt) argv[i] = 0; if (execvp(argv[0], argv) < 0) - uw_throwf(process_error_s, lit("~s ~a: ~d/~s"), - self, file, num(errno), errno_to_str(errno), nao); + uw_ethrowf(process_error_s, lit("~s ~a: ~d/~s"), + self, file, num(errno), errno_to_str(errno), nao); uw_throwf(process_error_s, lit("~s ~a returned"), self, file, nao); } @@ -1253,8 +1253,8 @@ static val stat_impl(val obj, int (*statfn)(val, struct stat *, val), if (res == -1) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("unable to ~a ~a: ~d/~s"), - name, obj, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("unable to ~a ~a: ~d/~s"), + name, obj, num(eno), errno_to_str(eno), nao); } return if3(opt_compat && opt_compat <= 113, @@ -1351,8 +1351,8 @@ static val do_utimes(val target, val atime, val atimens, if (res == -1) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("~s: failed: ~d/~s"), - self, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("~s: failed: ~d/~s"), + self, num(eno), errno_to_str(eno), nao); } return t; @@ -1398,8 +1398,8 @@ static val pipe_wrap(void) int fd[2]; if (pipe(fd) < 0) { int eno = errno; - uw_throwf(errno_to_file_error(eno), lit("pipe failed: ~d/~s"), - num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("pipe failed: ~d/~s"), + num(eno), errno_to_str(eno), nao); } return cons(num(fd[0]), num(fd[1])); } @@ -1519,8 +1519,8 @@ static val poll_wrap(val poll_list, val timeout_in) sig_restore_enable; if (res < 0) - uw_throwf(file_error_s, lit("poll failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(file_error_s, lit("poll failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); if (res == 0) return nil; @@ -1588,8 +1588,8 @@ static val getgroups_wrap(void) free(arr); } - uw_throwf(system_error_s, lit("~s failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~s failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); abort(); } @@ -1597,8 +1597,8 @@ static val setuid_wrap(val nval) { val self = lit("setuid"); if (setuid(c_num(nval, self)) == -1) - uw_throwf(system_error_s, lit("setuid failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("setuid failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); return t; } @@ -1606,8 +1606,8 @@ static val seteuid_wrap(val nval) { val self = lit("seteuid"); if (seteuid(c_num(nval, self)) == -1) - uw_throwf(system_error_s, lit("seteuid failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("seteuid failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); return t; } @@ -1615,8 +1615,8 @@ static val setgid_wrap(val nval) { val self = lit("setgid"); if (setgid(c_num(nval, self)) == -1) - uw_throwf(system_error_s, lit("setgid failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("setgid failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); return t; } @@ -1624,7 +1624,7 @@ static val setegid_wrap(val nval) { val self = lit("setegid"); if (setegid(c_num(nval, self)) == -1) - uw_throwf(system_error_s, lit("setegid failed: ~d/~s"), + uw_ethrowf(system_error_s, lit("setegid failed: ~d/~s"), num(errno), errno_to_str(errno), nao); return t; } @@ -1776,7 +1776,7 @@ static val setgroups_wrap(val list) free(arr); if (res != 0) - uw_throwf(system_error_s, lit("setgroups failed: ~d/~s"), + uw_ethrowf(system_error_s, lit("setgroups failed: ~d/~s"), num(errno), errno_to_str(errno), nao); return t; @@ -1791,8 +1791,8 @@ static val getresuid_wrap(void) { uid_t r, e, s; if (getresuid(&r, &e, &s) != 0) - uw_throwf(system_error_s, lit("getresuid failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("getresuid failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); return list(num(r), num(e), num(s), nao); } @@ -1809,8 +1809,8 @@ static val setresuid_wrap(val r, val e, val s) { val self = lit("setresuid"); if (setresuid(c_num(r, self), c_num(e, self), c_num(s, self)) != 0) - uw_throwf(system_error_s, lit("setresuid failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("setresuid failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); return t; } @@ -1818,8 +1818,8 @@ static val setresgid_wrap(val r, val e, val s) { val self = lit("setresgid"); if (setresuid(c_num(r, self), c_num(e, self), c_num(s, self)) != 0) - uw_throwf(system_error_s, lit("setresuid failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("setresuid failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); return t; } @@ -2088,8 +2088,8 @@ static val crypt_wrap(val wkey, val wsalt) return string_utf8(hash); } - uw_throwf(error_s, lit("crypt failed: ~d/~s"), num(errno), - errno_to_str(errno), nao); + uw_ethrowf(error_s, lit("crypt failed: ~d/~s"), num(errno), + errno_to_str(errno), nao); } #endif @@ -2183,8 +2183,8 @@ static val uname_wrap(void) #endif return out; } - uw_throwf(error_s, lit("uname failed: ~d/~s"), num(errno), - errno_to_str(errno), nao); + uw_ethrowf(error_s, lit("uname failed: ~d/~s"), num(errno), + errno_to_str(errno), nao); } #endif @@ -2367,8 +2367,8 @@ static val opendir_wrap(val path, val prefix_p) DIR *dir = w_opendir(c_str(path, self)); if (dir == 0) { - uw_throwf(system_error_s, lit("opendir failed for ~a: ~d/~s"), - path, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("opendir failed for ~a: ~d/~s"), + path, num(errno), errno_to_str(errno), nao); } else { struct dir *d = coerce(struct dir *, chk_malloc(sizeof *d)); val obj = cobj(coerce(mem_t *, d), dir_cls, &opendir_ops); @@ -2462,8 +2462,8 @@ val getrlimit_wrap(val resource, val rlim_opt) int res = getrlimit(c_int(resource, self), &rl); if (res != 0) - uw_throwf(system_error_s, lit("~a failed for ~a: ~d/~s"), - self, resource, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a failed for ~a: ~d/~s"), + self, resource, num(errno), errno_to_str(errno), nao); if (missingp(rlim)) { args_decl(args, ARGS_MIN); @@ -2484,8 +2484,8 @@ val setrlimit_wrap(val resource, val rlim) int res = setrlimit(c_int(resource, self), &rl); if (res != 0) - uw_throwf(system_error_s, lit("~a failed for ~a: ~d/~s"), - self, resource, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a failed for ~a: ~d/~s"), + self, resource, num(errno), errno_to_str(errno), nao); return t; } @@ -258,8 +258,8 @@ static val tcgetattr_wrap(val stream) res = tcgetattr(c_num(fd, self), &tio); if (res < 0) - uw_throwf(system_error_s, lit("~a: failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a: failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); return termios_unpack(&tio); } @@ -276,16 +276,16 @@ static val tcsetattr_wrap(val termios, val actions, val stream) res = tcgetattr(c_num(fd, self), &tio); if (res < 0) - uw_throwf(system_error_s, lit("~a: failed to retrieve settings: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a: failed to retrieve settings: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); termios_pack(&tio, termios, self); res = tcsetattr(c_num(fd, self), c_num(actions, self), &tio); if (res < 0) - uw_throwf(system_error_s, lit("~a: failed: ~d/~s"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a: failed: ~d/~s"), + num(errno), errno_to_str(errno), nao); return termios; } @@ -298,8 +298,8 @@ static val tcsendbreak_wrap(val duration, val stream) 500, c_num(duration, self))); if (res < 0) - uw_throwf(system_error_s, lit("~a: failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a: failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); return t; } @@ -311,8 +311,8 @@ static val tcdrain_wrap(val stream) int res = tcdrain(c_num(fd, self)); if (res < 0) - uw_throwf(system_error_s, lit("~a: failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a: failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); return t; } @@ -324,8 +324,8 @@ static val tcflush_wrap(val queue, val stream) int res = tcflush(c_num(fd, self), c_num(queue, self)); if (res < 0) - uw_throwf(system_error_s, lit("~a: failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a: failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); return t; } @@ -337,8 +337,8 @@ static val tcflow_wrap(val action, val stream) int res = tcflow(c_num(fd, self), c_num(action, self)); if (res < 0) - uw_throwf(system_error_s, lit("~a: failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(system_error_s, lit("~a: failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); return t; } diff --git a/tests/018/errno.tl b/tests/018/errno.tl new file mode 100644 index 00000000..ec204b23 --- /dev/null +++ b/tests/018/errno.tl @@ -0,0 +1,8 @@ +(load "../common") + +(vtest + (catch + (open-file "/NoNeXiStEnT") + (error (msg) + (string-get-code msg))) + enoent) @@ -25026,6 +25026,83 @@ function produces a copy of from which leading and trailing tabs, spaces and newlines are removed. +.coNP Functions @ string-set-code and @ string-get-code +.synb +.mets (string-set-code < string << value ) +.mets (string-get-code << string ) +.syne +.desc +The +.code string-set-code +and +.code string-get-code +functions provide a mechanism for associating an integer code +with a string. + +Note: this mechanism is the basis for associating system error messages passed +in exceptions with the +.code errno +values of the failed system library calls which precipitated these error +exceptions. + +Not all string types can have an integer code: lazy strings and literal +strings do not have this capability. The +.meta string +argument must be of type +.codn str . + +The +.meta value +argument must be an integer or character. It is recommended that its +value be confined to the non-negative range of the platform's +.code int +C type. Otherwise it is unspecified whether the same value shall be +observed by +.code string-get-code +as what was stored with +.codn string-set-code . + +The +.code string-set-code +function associates the integer +.meta value +with the given +.codn string , +and returns +.codn string . +Any previously associated value is overwritten. + +The +.code string-get-code +function retrieves the value most recently associated with +.metn string . +If +.meta string +has no associated value, then +.code nil +is returned. + +If the +.code string-extend +is invoked on a +.meta string +then it is unspecified whether or not +.meta string +has an associated value and, if so, what value that is, except in the +following case: if +.code string-extend +is invoked with a +.meta final +argument which is true, then +.meta string +is caused not to have an associated value. + +If the +.code string-finish +function is invoked on a +.metn string , +that string is caused not to have an associated value. + .coNP Function @ chrp .synb .mets (chrp << obj ) @@ -47907,6 +47984,38 @@ symbol, either by inheriting directly from .code restart or from an exception subtype of that symbol. +.coNP Treatment of @ errno In Built-in Exceptions +Some \*(TL library functions generate exceptions in response to +conditions arising in the operating system, and those conditions +are associated with a numeric code in the POSIX/ISO C variable +.codn errno . +This code isn't represented as an exception argument. Rather, +in many of these situations, the +.code errno +value is attached to the error message string which is passed +as the first and only exception argument. The value can be +retrieved by using the function +.code string-get-code +on the error message string. If this function returns +.codn nil , +then no such code is available in connection with the given +error. + +.TP* Example: + +.verb +;; the errno value 2 is retrieved from the ser +; + (catch + (open-file "AsDf") + (error (msg) + ;; the value 2 is retrieved from msg + ;; 2 is the common common value of ENOENT + (list (string-get-code msg) msg))) + + -> (2 "error opening \e"AsDf\e": 2/\e"No such file or directory\e"") +.brev + .coNP Functions @, throw @ throwf and @ error .synb .mets (throw < symbol << arg *) @@ -33,6 +33,7 @@ #include <assert.h> #include <stdarg.h> #include <signal.h> +#include <errno.h> #include "config.h" #if HAVE_VALGRIND #include <valgrind/memcheck.h> @@ -803,6 +804,20 @@ val uw_throwf(val sym, val fmt, ...) abort(); } +val uw_ethrowf(val sym, val fmt, ...) +{ + va_list vl; + val eno = num(errno); + val stream = make_string_output_stream(); + + va_start (vl, fmt); + (void) vformat(stream, fmt, vl); + va_end (vl); + + uw_throw(sym, string_set_code(get_string_from_stream(stream), eno)); + abort(); +} + val uw_errorfv(val fmt, struct args *args) { val stream = make_string_output_stream(); @@ -348,6 +348,7 @@ val uw_rthrowv(val sym, struct args *); val uw_rthrowfv(val sym, val fmt, struct args *); NORETURN val uw_throw(val sym, val exception); NORETURN val uw_throwf(val sym, val fmt, ...); +NORETURN val uw_ethrowf(val sym, val fmt, ...); NORETURN val uw_errorfv(val fmt, struct args *args); val uw_warningf(val fmt, ...); val uw_defer_warning(val args); |