summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-06-19 20:25:36 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-06-19 20:25:36 -0700
commit29a25713116323adcac696a090420ed3c1e73e5f (patch)
tree53c4e86a83e015268ea435dace0a21d90ca6766e
parent09091bedcc6dd570262de4a72c362b161a492df7 (diff)
downloadtxr-29a25713116323adcac696a090420ed3c1e73e5f.tar.gz
txr-29a25713116323adcac696a090420ed3c1e73e5f.tar.bz2
txr-29a25713116323adcac696a090420ed3c1e73e5f.zip
New function: strerror
* configure (have_strerror_r): New variable. Detect whether we have strerror_r and which flavor: GNU or POSIX. Define HAVE_STRERROR_GNU or HAVE_STRERROR_POSIX in config.h. * sysif.c (strerror_wrap): New function. (sysif_init): Register strerror intrinsic. * txr.1: Documented.
-rwxr-xr-xconfigure32
-rw-r--r--sysif.c16
-rw-r--r--txr.117
3 files changed, 65 insertions, 0 deletions
diff --git a/configure b/configure
index 07d8d5a8..7ea5bea0 100755
--- a/configure
+++ b/configure
@@ -173,6 +173,7 @@ have_unistd=
have_sys_stat=
have_sys_types=
have_sys_time=
+have_strerror_r=
have_makedev=
have_syslog=
have_glob=
@@ -2022,6 +2023,37 @@ else
fi
#
+# errno stuff
+#
+
+printf "Checking for strerror_r ..."
+
+for type in int 'char *' ; do
+ cat > conftest.c <<!
+#include <string.h>
+
+int main(int argc, char **argv)
+{
+ $type (*fp)(int, char *, size_t) = strerror_r;
+ return 0;
+}
+!
+ if conftest EXTRA_FLAGS=-Werror=incompatible-pointer-types ; then
+ if [ "$type" = int ] ; then
+ printf "yes (POSIX)\n"
+ printf "#define HAVE_STRERROR_POSIX 1\n" >> config.h
+ else
+ printf "yes (GNU)\n"
+ printf "#define HAVE_STRERROR_GNU 1\n" >> config.h
+ fi
+ have_strerror_r=y
+ break
+ fi
+done
+
+[ $have_strerror_r ] || printf "no\n"
+
+#
# fcntl
#
diff --git a/sysif.c b/sysif.c
index 3f25bb7e..701a1eed 100644
--- a/sysif.c
+++ b/sysif.c
@@ -141,6 +141,21 @@ static val errno_wrap(val newval)
return oldval;
}
+static val strerror_wrap(val errnum)
+{
+ val self = lit("strerror");
+ int eno = c_int(errnum, self);
+#if HAVE_STRERROR_POSIX
+ char buf[128];
+ return strerror_r(eno, buf, sizeof buf) >= 0 ? string_utf8(buf) : nil;
+#elif HAVE_STRERROR_GNU
+ char buf[128];
+ return string_utf8(strerror_r(eno, buf, sizeof buf));
+#else
+ return string_utf8(strerror(eno));
+#endif
+}
+
#if HAVE_DAEMON
static val daemon_wrap(val nochdir, val noclose)
{
@@ -2327,6 +2342,7 @@ void sysif_init(void)
reg_varl(intern(lit("exdev"), user_package), num_fast(EXDEV));
reg_fun(intern(lit("errno"), user_package), func_n1o(errno_wrap, 0));
+ reg_fun(intern(lit("strerror"), user_package), func_n1o(strerror_wrap, 0));
reg_fun(intern(lit("exit"), user_package), func_n1(exit_wrap));
reg_fun(intern(lit("at-exit-call"), user_package), func_n1(at_exit_call));
reg_fun(intern(lit("at-exit-do-not-call"), user_package), func_n1(at_exit_do_not_call));
diff --git a/txr.1 b/txr.1
index 8d30662c..229d50ae 100644
--- a/txr.1
+++ b/txr.1
@@ -58584,6 +58584,23 @@ The place form of
.code errno
does not take an argument.
+.coNP Function @ strerror
+.synb
+.mets (strerror << errno-value )
+.syne
+.desc
+The
+.code strerror
+returns a character string which provides the host platform's description
+of the integer
+.meta errno-value
+obtained from the
+.code errno
+function.
+
+If the host platform fails to provide a descripion, the function returns
+.codn nil .
+
.coNP Function @ exit
.synb
.mets (exit << status )