From d96f6af2b3cd20f7f091f57d30512a47e62bee22 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 19 Jun 2020 20:25:36 -0700 Subject: 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. --- configure | 32 ++++++++++++++++++++++++++++++++ sysif.c | 16 ++++++++++++++++ txr.1 | 17 +++++++++++++++++ 3 files changed, 65 insertions(+) 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= @@ -2021,6 +2022,37 @@ else printf "no\n" fi +# +# errno stuff +# + +printf "Checking for strerror_r ..." + +for type in int 'char *' ; do + cat > conftest.c < + +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 ) -- cgit v1.2.3