summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c2
-rw-r--r--ftw.c4
-rw-r--r--lib.c39
-rw-r--r--lib.h2
-rw-r--r--parser.c4
-rw-r--r--socket.c70
-rw-r--r--stdlib/doc-syms.tl26
-rw-r--r--stream.c94
-rw-r--r--sysif.c150
-rw-r--r--termios.c28
-rw-r--r--tests/018/errno.tl8
-rw-r--r--txr.1109
-rw-r--r--unwind.c15
-rw-r--r--unwind.h1
14 files changed, 365 insertions, 187 deletions
diff --git a/eval.c b/eval.c
index def3586d..5d542fc9 100644
--- a/eval.c
+++ b/eval.c
@@ -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));
diff --git a/ftw.c b/ftw.c
index 9b39cc28..921f809b 100644
--- a/ftw.c
+++ b/ftw.c
@@ -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);
diff --git a/lib.c b/lib.c
index 3e9cca80..cb8bcde8 100644
--- a/lib.c
+++ b/lib.c
@@ -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)) {
diff --git a/lib.h b/lib.h
index 19cedbf8..75aed65a 100644
--- a/lib.h
+++ b/lib.h
@@ -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);
diff --git a/parser.c b/parser.c
index 527b94c3..3a14d4ed 100644
--- a/parser.c
+++ b/parser.c
@@ -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:
diff --git a/socket.c b/socket.c
index 37c7b730..0e83cadb 100644
--- a/socket.c
+++ b/socket.c
@@ -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")
diff --git a/stream.c b/stream.c
index 9db94380..0b6897cb 100644
--- a/stream.c
+++ b/stream.c
@@ -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
diff --git a/sysif.c b/sysif.c
index 207597ef..058cc407 100644
--- a/sysif.c
+++ b/sysif.c
@@ -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;
}
diff --git a/termios.c b/termios.c
index 1b9c63f3..3fb28670 100644
--- a/termios.c
+++ b/termios.c
@@ -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)
diff --git a/txr.1 b/txr.1
index 01322a70..a1a8fbd9 100644
--- a/txr.1
+++ b/txr.1
@@ -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 *)
diff --git a/unwind.c b/unwind.c
index 9d4c7586..efc321ef 100644
--- a/unwind.c
+++ b/unwind.c
@@ -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();
diff --git a/unwind.h b/unwind.h
index 97280abc..3a881641 100644
--- a/unwind.h
+++ b/unwind.h
@@ -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);