From f126a1ab89baea9e3462f7df71f7b39bc171b3d8 Mon Sep 17 00:00:00 2001
From: Kevin Bracey <kbracey@gitlab.riscosopen.org>
Date: Tue, 15 Apr 2003 16:50:30 +0000
Subject: [PATCH] * __assert2() added to support for C99 assert(), which
 displays function name.

* _Exit() added.
* Lots of new <math.h> functions (acosh, asinh, atanh, exp2, expm1,
  ilogb, log1p, log2, logb, scalbn, scalbln, cbrt, erf, erfc,
  lgamma, tgamma, nexttoward, fmaf). Float and long double forms
  of every function added; long double forms are included as another
  library object in the stubs rather than the shared library, as they
  just branch to the double form.
* Subnormal/NaN/infinity cases in various <math.h> functions improved.
* Added <tgmath.h>.
* Headers brought into line with CC 5.54.
* RMEnsures added to C library initialisation to try to load minimum
  CallASWI, FPEmulator, CLib. No errors reported if load fails.
* A few pointless inter-file dependencies removed to reduce minimum
  size of included ANSILib.

Version 5.46. Tagged as 'RISC_OSLib-5_46'
---
 Doc/APCS_HowTo             |   2 +-
 Makefile                   |  20 +-
 VersionASM                 |  12 +-
 VersionNum                 |  20 +-
 c/armsys                   |  67 ++-
 c/error                    |  19 +-
 c/math                     | 852 ++++++++++++++++++++++++++++++++++---
 c/stdio                    |  25 ++
 c/stdlib                   |  24 +-
 c/string                   |  12 +-
 clib/Resources/UK/Messages |   3 +
 clib/h/assert              |  25 +-
 clib/h/ctype               |  28 +-
 clib/h/errno               |   2 +-
 clib/h/float               |   6 +-
 clib/h/inttypes            |  12 +-
 clib/h/locale              |   2 +-
 clib/h/math                | 434 +++++++++++++------
 clib/h/setjmp              |   6 +-
 clib/h/signal              |  12 +-
 clib/h/stddef              |   2 +-
 clib/h/stdio               | 121 +++---
 clib/h/stdlib              | 126 +++---
 clib/h/string              |  46 +-
 clib/h/tgmath              | 175 ++++++++
 clib/h/time                |  20 +-
 clib/s/cl_body             | 381 ++++++++++++++++-
 clib/s/cl_entry2           |  55 +++
 clib/s/cl_stub             |  46 ++
 h/hostsys                  |   8 +-
 kernel/s/k_body            |  23 +-
 rlib/c/txt1                |  10 +-
 rlib/c/txtar               |   6 +-
 s/mathl                    |  93 ++++
 34 files changed, 2230 insertions(+), 465 deletions(-)
 create mode 100644 clib/h/tgmath
 create mode 100644 s/mathl

diff --git a/Doc/APCS_HowTo b/Doc/APCS_HowTo
index 6bc2984..88f5561 100644
--- a/Doc/APCS_HowTo
+++ b/Doc/APCS_HowTo
@@ -15,4 +15,4 @@ To make Shared C Library compatible with 32-bit RISC OS, build with APCS = APCS-
 An APCS-32 Shared C Library will NOT run 26-bit programs, even on a 26-bit
 system; an APCS-R Shared C Library must be used. In a build using APCS-32,
 the SCL must be forced to APCS-R - pass the option SCL_APCS="-APCS 3/26bit"
-in the components file to acheive this.
+in the components file to achieve this.
diff --git a/Makefile b/Makefile
index 6383555..b3e9aad 100644
--- a/Makefile
+++ b/Makefile
@@ -181,6 +181,7 @@ HEADERS =\
  CLIB:h.stdlib \
  CLIB:h.string \
  CLIB:h.swis \
+ CLIB:h.tgmath \
  CLIB:h.time \
  CLIB:h.varargs \
  RISC_OSLib:h.akbd \
@@ -278,7 +279,7 @@ ANSI_OBJS =\
  o.alloc o.armprof o.armsys o.clib o.ctype o.error o.fpprintf \
  o.kernel o.locale o.math o.memcpset o.overmgr o.printf o.scanf \
  o.signal o.sort o.stdio o.stdlib o.string o.swiv o.time o.fenv \
- o.longlong
+ o.longlong o.mathl
 
 RM_OBJS =\
  rm_o.k_modbody \
@@ -587,17 +588,17 @@ rm_o.k_stub2_rm: kernel.s.k_stub2_rm
 rm_o_rl.rl_stub_rm: rlib.s.rl_stub_rm
 	${OBJASM} ${ALFLAGS} -from rlib.s.rl_stub_rm -to $@
 
-lib.stubs: o.cl_stub_r o.k_stub2_r o.cl_stub2_r
-	${LIBFILE} ${LIBFLAGS} $@ o.cl_stub_r o.k_stub2_r o.cl_stub2_r
+lib.stubs: o.cl_stub_r o.k_stub2_r o.cl_stub2_r o.mathl
+	${LIBFILE} ${LIBFLAGS} $@ o.cl_stub_r o.k_stub2_r o.cl_stub2_r o.mathl
 
-lib.rstubs: o_rl.rl_stub_r o.k_stub2_r o.cl_stub2_r
-	${LIBFILE} ${LIBFLAGS} $@ o_rl.rl_stub_r o.k_stub2_r o.cl_stub2_r
+lib.rstubs: o_rl.rl_stub_r o.k_stub2_r o.cl_stub2_r o.mathl
+	${LIBFILE} ${LIBFLAGS} $@ o_rl.rl_stub_r o.k_stub2_r o.cl_stub2_r o.mathl
 
-lib.romcstubs: rm_o.cl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm
-	${LIBFILE} ${LIBFLAGS} $@ rm_o.cl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm
+lib.romcstubs: rm_o.cl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm o.mathl
+	${LIBFILE} ${LIBFLAGS} $@ rm_o.cl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm o.mathl
 
-lib.romstubs: rm_o_rl.rl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm
-	${LIBFILE} ${LIBFLAGS} $@ rm_o_rl.rl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm
+lib.romstubs: rm_o_rl.rl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm o.mathl
+	${LIBFILE} ${LIBFLAGS} $@ rm_o_rl.rl_stub_rm rm_o.k_stub2_rm rm_o.cl_stub2_rm o.mathl
 
 lib.romastubs: rlib.s.rl_stub_a
 	${OBJASM} ${AFLAGS} -from rlib.s.rl_stub_a -to $@
@@ -648,6 +649,7 @@ CLIB:h.stdint: clib.h.stdint;     ${CP} clib.h.stdint $@ ${CPFLAGS}
 CLIB:h.stdio: clib.h.stdio;       ${CP} clib.h.stdio $@ ${CPFLAGS}
 CLIB:h.stdlib: clib.h.stdlib;     ${CP} clib.h.stdlib $@ ${CPFLAGS}
 CLIB:h.string: clib.h.string;     ${CP} clib.h.string $@ ${CPFLAGS}
+CLIB:h.tgmath: clib.h.tgmath;     ${CP} clib.h.tgmath $@ ${CPFLAGS}
 CLIB:h.time: clib.h.time;         ${CP} clib.h.time $@ ${CPFLAGS}
 CLIB:h.varargs: clib.h.varargs;   ${CP} clib.h.varargs $@ ${CPFLAGS}
 
diff --git a/VersionASM b/VersionASM
index bee29ec..8ac6c0b 100644
--- a/VersionASM
+++ b/VersionASM
@@ -11,13 +11,13 @@
                         GBLS    Module_HelpVersion
                         GBLS    Module_ComponentName
                         GBLS    Module_ComponentPath
-Module_MajorVersion     SETS    "5.45"
-Module_Version          SETA    545
+Module_MajorVersion     SETS    "5.46"
+Module_Version          SETA    546
 Module_MinorVersion     SETS    ""
-Module_Date             SETS    "17 Jan 2003"
-Module_ApplicationDate  SETS    "17-Jan-03"
+Module_Date             SETS    "15 Apr 2003"
+Module_ApplicationDate  SETS    "15-Apr-03"
 Module_ComponentName    SETS    "RISC_OSLib"
 Module_ComponentPath    SETS    "RiscOS/Sources/Lib/RISC_OSLib"
-Module_FullVersion      SETS    "5.45"
-Module_HelpVersion      SETS    "5.45 (17 Jan 2003)"
+Module_FullVersion      SETS    "5.46"
+Module_HelpVersion      SETS    "5.46 (15 Apr 2003)"
                         END
diff --git a/VersionNum b/VersionNum
index 56c0684..fc0b5cd 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,23 +1,23 @@
-/* (5.45)
+/* (5.46)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  * Last processed by srccommit version: 1.68.
  *
  */
-#define Module_MajorVersion_CMHG        5.45
+#define Module_MajorVersion_CMHG        5.46
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                17 Jan 2003
+#define Module_Date_CMHG                15 Apr 2003
 
-#define Module_MajorVersion             "5.45"
-#define Module_Version                  545
+#define Module_MajorVersion             "5.46"
+#define Module_Version                  546
 #define Module_MinorVersion             ""
-#define Module_Date                     "17 Jan 2003"
+#define Module_Date                     "15 Apr 2003"
 
-#define Module_ApplicationDate          "17-Jan-03"
+#define Module_ApplicationDate          "15-Apr-03"
 
 #define Module_ComponentName            "RISC_OSLib"
 #define Module_ComponentPath            "RiscOS/Sources/Lib/RISC_OSLib"
 
-#define Module_FullVersion              "5.45"
-#define Module_HelpVersion              "5.45 (17 Jan 2003)"
-#define Module_LibraryVersionInfo       "5:45"
+#define Module_FullVersion              "5.46"
+#define Module_HelpVersion              "5.46 (15 Apr 2003)"
+#define Module_LibraryVersionInfo       "5:46"
diff --git a/c/armsys b/c/armsys
index 68d4ffc..b37a21e 100644
--- a/c/armsys
+++ b/c/armsys
@@ -40,6 +40,7 @@ extern int main(int argc, char **argv);         /* the point of it all   */
 extern FILEHANDLE __dup(int new, int old);
 extern void _ctype_init(void);
 extern int _fprintf_lf(FILE *fp, const char *fmt, ...);
+extern int _sprintf(char *buff, const char *fmt, ...);
 extern int _sprintf_lf(char *buff, const char *fmt, ...);
 extern _kernel_oserror *_kernel_peek_last_oserror(void);
 
@@ -160,22 +161,25 @@ time_t time(time_t *timer)
  */
 int _desktop_task()
 {
-    int h = 0;
+    _kernel_swi_regs r;
     if (_kernel_processor_mode() & 0xF) return 0;
-    _swix(TaskWindow_TaskInfo, _IN(0)|_OUT(0), 0, &h);
-    if (h) return 0;
-    _swix(Wimp_ReadSysInfo, _IN(0)|_OUT(0), 3, &h);
-    if (h == 0) return 0;
-    _swix(Wimp_ReadSysInfo, _IN(0)|_OUT(0), 5, &h);
-    return h;
+    r.r[0] = 0;
+    if (_kernel_swi(TaskWindow_TaskInfo, &r, &r) || r.r[0])
+        return 0;
+    r.r[0] = 3;
+    _kernel_swi(Wimp_ReadSysInfo, &r, &r);
+    if (r.r[0] == 0) return 0;
+    r.r[0] = 5;
+    _kernel_swi(Wimp_ReadSysInfo, &r, &r);
+    return r.r[0];
 }
 
 static int _desktop_report(const char *s, const char *but)
 {
+    _kernel_swi_regs r;
     _kernel_oserror err, *e;
-    const char *n = NULL;
     char *p, *end;
-    int flags, r, h = _desktop_task();
+    int flags, h = _desktop_task();
     if (h == 0) return 0;
 
     flags = 0x102; /* New error, cancel button */
@@ -210,17 +214,26 @@ static int _desktop_report(const char *s, const char *but)
 
         e = &err;
     }
-    _swix(TaskManager_TaskNameFromHandle, _IN(0)|_OUT(0), h, &n);
-
-    r = 0;
-    _swix(Wimp_ReportError, _INR(0,5)|_OUT(1), e, flags, n, NULL, 1, but, &r);
-    return r;
+    r.r[0] = h;
+    if (_kernel_swi(TaskManager_TaskNameFromHandle, &r, &r) == 0)
+        r.r[2] = r.r[0];
+    else
+        r.r[2] = 0;
+    r.r[0] = (int) e;
+    r.r[1] = flags;
+    r.r[3] = 0;
+    r.r[4] = 1;
+    r.r[5] = (int) but;
+    if (_kernel_swi(Wimp_ReportError, &r, &r) == 0)
+        return r.r[1];
+    else
+        return 0;
 }
 
-bool _sys__assert(const char *s, const char *expr, const char *file, int line)
+bool _sys__assert(const char *s, const char *expr, const char *func, const char *file, int line)
 {
     char buffer[252];
-    int len, exprlen, filelen;
+    int len, funclen, exprlen, filelen;
 
     if (!istty(stderr->__file)) return false;
 
@@ -228,29 +241,39 @@ bool _sys__assert(const char *s, const char *expr, const char *file, int line)
 
     if (strlen(s) > 200) return false; /* Be safe */
 
-    len = sprintf(buffer, s, "", "", line);
+    len = func ? _sprintf(buffer, s, "", "", "", line)
+               : _sprintf(buffer, s, "", "", line);
+    funclen = func ? strlen(func) : 0;
     exprlen = strlen(expr);
     filelen = strlen(file);
-    if (len + exprlen + filelen < 251)
+    if (len + funclen + exprlen + filelen < 251)
     {
-        sprintf(buffer, s, expr, file, line);
+        func ? _sprintf(buffer, s, expr, func, file, line)
+             : _sprintf(buffer, s, expr, file, line);
     }
     else
     {
         char expr2[200];
+        char func2[50];
         char file2[100];
 
         #define min(a,b) a<b?a:b
         exprlen = min(exprlen, 199);
+        funclen = min(funclen, 49);
         filelen = min(filelen, 99);
-        filelen = min(filelen, 251-len-exprlen);
+        filelen = min(filelen, 251-len-funclen-exprlen);
         if (filelen < 0) filelen = 0;
-        exprlen = min(exprlen, 251-len-filelen);
+        funclen = min(funclen, 251-len-exprlen-filelen);
+        if (funclen < 0) funclen = 0;
+        exprlen = min(exprlen, 251-len-funclen-filelen);
         memcpy(expr2, expr, exprlen);
+        memcpy(func2, func, funclen);
         memcpy(file2, file, filelen);
         expr2[exprlen]='\0';
+        func2[funclen]='\0';
         file2[filelen]='\0';
-        sprintf(buffer, s, expr2, file2, line);
+        func ? _sprintf(buffer, s, expr2, func2, file2, line)
+             : _sprintf(buffer, s, expr2, file2, line);
     }
     return _desktop_report(buffer, NULL);
 }
diff --git a/c/error b/c/error
index 00c3eac..f90a9b5 100644
--- a/c/error
+++ b/c/error
@@ -47,14 +47,27 @@ void _sysdie(const char *s)
 }
 
 /* from <assert.h> */
-void __assert(char *expr, char *file, int line)
+void __assert(const char *expr, const char *file, int line)
 {
     const char *s;
     s = _kernel_getmessage("*** assertion failed: %s, file %s, line %d", "C34");
 
-    if (!_sys__assert(s, expr, file, line))
+    if (!_sys__assert(s, expr, NULL, file, line)) {
         _fprintf_lf(stderr, s, expr, file, line);
-    fputc('\n', stderr);
+        fputc('\n', stderr);
+    }
+    abort();
+}
+
+void __assert2(const char *expr, const char *func, const char *file, int line)
+{
+    const char *s;
+    s = _kernel_getmessage_def("*** assertion failed: %s, function %s, file %s, line %d", "C73");
+
+    if (!_sys__assert(s, expr, func, file, line)) {
+        _fprintf_lf(stderr, s, expr, func, file, line);
+        fputc('\n', stderr);
+    }
     abort();
 }
 
diff --git a/c/math b/c/math
index b971525..ede25d3 100644
--- a/c/math
+++ b/c/math
@@ -35,6 +35,7 @@
 
 #include "hostsys.h"
 #include <limits.h>
+#include <float.h>
 #include <errno.h>
 
 /* This file contains code for most of the math routines from <math.h>      */
@@ -63,7 +64,7 @@ double frexp(double d, int *lvn)
     int n;
     if (d==0.0)
     {   *lvn = 0;
-        return 0.0;
+        return d;
     }
     d1.d = d;
     if ((n = d1.i.x - 0x3fe) == -0x3fe)
@@ -73,8 +74,9 @@ double frexp(double d, int *lvn)
 /* suitable nonzero bit appears to go in the implicit-bit place in the   */
 /* fractional result. For each bit shifted I need to adjust the final    */
 /* exponent that will be returned.                                       */
-/* I have already tested to see if d was zero so the fllowing loop MUST  */
+/* I have already tested to see if d was zero so the following loop MUST */
 /* terminate.                                                            */
+        n++;
         do
         {   flag = d1.i.mhi & 0x00080000;
             d1.i.mhi = (d1.i.mhi << 1) | (d1.i.mlo >> 31);
@@ -82,11 +84,46 @@ double frexp(double d, int *lvn)
             n--;
         } while (flag==0);
     }
+    else if (n == 0x401)
+    {
+/* Here d1 has 0x7ff in its exponent field - it's a NaN or infinity      */
+        *lvn = (d1.i.mhi || d1.i.mlo) ? FP_ILOGBNAN : INT_MAX;
+        return d1.d;
+    }
     *lvn = n;
     d1.i.x = 0x3fe;
     return d1.d;
 }
 
+float frexpf(float s, int *lvn)
+{
+    fp_number_single s1;
+    int n;
+    if (s==0.0F)
+    {   *lvn = 0;
+        return s;
+    }
+    s1.s = s;
+    if ((n = s1.i.x - 0x7e) == -0x7e)
+    {   int flag;
+        n++;
+        do
+        {   flag = s1.i.m & 0x00400000;
+            s1.i.m = s1.i.m << 1;
+            n--;
+        } while (flag==0);
+    }
+    else if (n == 0x81)
+    {
+/* Here d1 has 0xff in its exponent field - it's a NaN or infinity       */
+        *lvn = (s1.i.m) ? FP_ILOGBNAN : INT_MAX;
+        return s1.s;
+    }
+    *lvn = n;
+    s1.i.x = 0x7e;
+    return s1.s;
+}
+
 #else   /* DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS */
 
 double frexp(double d, int *lvn)
@@ -94,7 +131,7 @@ double frexp(double d, int *lvn)
     fp_number d1;
     if (d==0.0)
     {   *lvn = 0;
-        return 0.0;
+        return d;
     }
     d1.d = d;
     *lvn = d1.i.x - 0x3fe;
@@ -102,29 +139,246 @@ double frexp(double d, int *lvn)
     return d1.d;
 }
 
+float frexpf(float s, int *lvn)
+{
+    fp_number_single s1;
+    int n;
+    if (s==0.0F)
+    {   *lvn = 0;
+        return s;
+    }
+    s1.s = s;
+    *lvn = s1.i.x - 0x7e;
+    s1.i.x = 0x7e;
+    return s1.s;
+}
+
 #endif   /* DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS */
 
-double ldexp(double d, int n)
+double scalbln(double d, long int n)
 {
-    fp_number d1;
-    int nx;
-    if (d==0.0) return 0.0;        /* special case                       */
-    d1.d = d;
-    nx = (int) d1.i.x + n;
-    if (nx >= 0x7ff)
-    { errno = ERANGE;
-      return HUGE_VAL;              /* overflow yields 'infinity'        */
+    fp_number x;
+    long int exponent;
+    if (n == 0 || d == 0.0) return d;
+    x.d = d;
+    exponent = x.i.x;
+    if (exponent == 0x7ff) return d; /* NaN or infinite */
+#ifndef DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS
+    if (exponent == 0) /* starting subnormal */
+    {   int flag;
+        exponent++;
+        do
+        {   flag = x.i.mhi & 0x00080000;
+            x.i.mhi = (x.i.mhi << 1) | (x.i.mlo >> 31);
+            x.i.mlo = x.i.mlo << 1;
+            exponent--;
+        } while (flag==0);
     }
-/* Maybe I should be prepared to generate un-normalized numbers here, or */
-/* even deal with input d un-normalized and n positive yielding a proper */
-/* result. All that seems like a lot of work and so I will not even try  */
-/* in this version of the code!                                          */
-    else if (nx <= 0) return 0.0;  /* deal with underflow                */
-    d1.i.x = nx;
-    return (d1.d);
+#endif
+    if (n > 0x1000 || exponent + n >= 0x7ff) /* overflow */
+    {   errno = ERANGE;
+        return x.i.s ? -HUGE_VAL : HUGE_VAL;
+    }
+    if (n < -0x1000 || exponent + n <= -53) /* total underflow */
+    {   x.i.x = x.i.mhi = x.i.mlo = 0;
+        errno = ERANGE;
+        return x.d;
+    }
+    if (exponent + n <= 0) /* subnormal result */
+    {   unsigned round = 0, hi;
+        n = 1 - (exponent + n);
+        hi = 0x00100000 | x.i.mhi;
+
+        if (n >= 32)
+        {   round = x.i.mlo;
+            x.i.mlo = hi;
+            hi = 0;
+            n -= 32;
+        }
+        if (n > 0)
+        {   round = (x.i.mlo << (32-n)) | (round != 0);
+            x.i.mlo = (hi << (32-n)) | (x.i.mlo >> n);
+            hi = hi >> n;
+        }
+        x.i.mhi = hi;
+        x.i.x = 0;
+        /* perform round-to-nearest; to even in tie cases */
+        if (round > 0x80000000 ||
+            (round == 0x80000000 && (x.i.mlo & 1)))
+            if (++x.i.mlo == 0)
+                if (++x.i.mhi == 0)
+                    x.i.x = 1;
+
+        if (round != 0) errno = ERANGE; /* only if inexact */
+
+        return x.d;
+    }
+    /* normal result */
+    x.i.x = (int) (exponent + n);
+    return x.d;
 }
 
+float scalblnf(float s, long int n)
+{
+    fp_number_single x;
+    long int exponent;
+    if (n == 0 || s == 0.0F) return s;
+    x.s = s;
+    exponent = x.i.x;
+    if (exponent == 0xff) return s; /* NaN or infinite */
+#ifndef DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS
+    if (exponent == 0) /* starting subnormal */
+    {   int flag;
+        exponent++;
+        do
+        {   flag = x.i.m & 0x00400000;
+            x.i.m = x.i.m << 1;
+            exponent--;
+        } while (flag==0);
+    }
+#endif
+    if (n > 0x1000 || exponent + n >= 0xff) /* overflow */
+    {   errno = ERANGE;
+        return x.i.s ? -HUGE_VALF : HUGE_VALF;
+    }
+    if (n < -0x1000 || exponent + n <= -24) /* total underflow */
+    {   x.i.x = x.i.m = 0;
+        errno = ERANGE;
+        return x.s;
+    }
+    if (exponent + n <= 0) /* subnormal result */
+    {   unsigned round, m;
+        n = 1 - (exponent + n);
+        m = 0x00800000 | x.i.m;
+
+        round = m << (32-n);
+        x.i.m = m >> n;
+        x.i.x = 0;
+        /* perform round-to-nearest; to even in tie cases */
+        if (round > 0x80000000 ||
+            (round == 0x80000000 && (x.i.m & 1)))
+            if (++x.i.m == 0)
+                  x.i.x = 1;
+
+        if (round != 0) errno = ERANGE; /* only if inexact */
+
+        return x.s;
+    }
+    /* normal result */
+    x.i.x = (int) (exponent + n);
+    return x.s;
+}
+
+double scalbn(double x, int n)
+{
+    return scalbln(x, n);
+}
+
+float scalbnf(float x, int n)
+{
+    return scalblnf(x, n);
+}
+
+double ldexp(double x, int n)
+{
+    return scalbn(x, n);
+}
 
+float ldexpf(float x, int n)
+{
+    return scalbnf(x, n);
+}
+
+int ilogb(double d)
+{
+    fp_number x;
+    int exponent;
+
+    if (d == 0.0)
+    {   errno = ERANGE;
+        return FP_ILOGB0;
+    }
+
+    x.d = d;
+    exponent = x.i.x;
+#ifndef DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS
+    if (exponent == 0)
+    {   int flag;
+        exponent = 1;
+        do
+        {   flag = x.i.mhi & 0x00080000;
+            x.i.mhi = (x.i.mhi << 1) | (x.i.mlo >> 31);
+            x.i.mlo = x.i.mlo << 1;
+            exponent--;
+        } while (flag==0);
+    }
+    else if (exponent == 0x7ff)
+    {   if (x.i.mhi || x.i.mlo)
+            return FP_ILOGBNAN;
+        else
+            return INT_MAX;
+    }
+#endif
+    return exponent - 0x3ff;
+}
+
+int ilogbf(float s)
+{
+    fp_number_single x;
+    int exponent;
+
+    if (s == 0.0F)
+    {   errno = ERANGE;
+        return FP_ILOGB0;
+    }
+
+    x.s = s;
+    exponent = x.i.x;
+#ifndef DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS
+    if (exponent == 0)
+    {   int flag;
+        exponent = 1;
+        do
+        {   flag = x.i.m & 0x00400000;
+            x.i.m = x.i.m << 1;
+            exponent--;
+        } while (flag==0);
+    }
+    else if (exponent == 0xff)
+    {   if (x.i.m)
+            return FP_ILOGBNAN;
+        else
+            return INT_MAX;
+    }
+#endif
+    return exponent - 0x7f;
+}
+
+double logb(double d)
+{
+    int x = ilogb(d);
+
+    switch (x)
+    {
+        case FP_ILOGB0:   return -HUGE_VAL;
+        case FP_ILOGBNAN: return d;
+        case INT_MAX:     return INFINITY;
+        default:          return x;
+    }
+}
+
+float logbf(float s)
+{
+    int x = ilogbf(s);
+
+    switch (x)
+    {
+        case FP_ILOGB0:   return -HUGE_VALF;
+        case FP_ILOGBNAN: return s;
+        case INT_MAX:     return INFINITY;
+        default:          return x;
+    }
+}
 
 #define _exp_arg_limit 709.78271289338397
 
@@ -595,11 +849,15 @@ double pow(double x, double y)
 
 double atan2(double y, double x)
 {
-    if (x==0.0 && y==0.0)
-    {   errno = EDOM;
-        return -HUGE_VAL;
-    }
-    if (fabs(x) < fabs(y))
+    if (isunordered(y, x)) return y+x;
+
+    if (y==0.0 || (isinf(x) && isfinite(y)))
+        return signbit(x) ? copysign(_pi_, y) : y;
+
+    if (isinf(x)) /* y must also be infinite, from above */
+        return copysign(x > 0 ? _pi_4 : 3*_pi_4, y);
+
+    if (fabs(x) < fabs(y)) /* handles infinite y, finite x */
     {   if (fabs(x / y)<1.0e-20)
         {   if (y<0.0) return - _pi_2;
             else return _pi_2;
@@ -613,6 +871,30 @@ double atan2(double y, double x)
     return y;
 }
 
+float atan2f(float y, float x)
+{
+    if (isunordered(y, x)) return y+x;
+
+    if (y==0.0F || (isinf(x) && isfinite(y)))
+        return signbit(x) ? copysignf((float)_pi_, y) : y;
+
+    if (isinf(x)) /* y must also be infinite, from above */
+        return copysignf(x > 0 ? (float)_pi_4 : (float)(3*_pi_4), y);
+
+    if (fabsf(x) < fabsf(y)) /* handles infinite y, finite x */
+    {   if (fabsf(x / y)<1.0e-12F)
+        {   if (y<0.0F) return (float) - _pi_2;
+            else return (float) _pi_2;
+        }
+    }
+    y = atanf(y / x);
+    if (x<0.0F)
+    {   if (y>0.0F) y -= (float) _pi_;
+        else y += (float) _pi_;
+    }
+    return y;
+}
+
 #ifndef HOST_HAS_TRIG
 double hypot(double x, double y)
 {
@@ -701,8 +983,9 @@ double sinh(double x)
 {
     int sign;
     double y;
-    if (x<0.0) y = -x, sign = 1; else y = x, sign = 0;
-    if (y>1.0)
+    if (x==0) return x;
+    if (isless(x,0.0)) y = -x, sign = 1; else y = x, sign = 0;
+    if (isgreater(y,1.0))
     {
 /* _sinh_lnv is REQUIRED to read in as a number with the lower part of   */
 /* its floating point representation zero.                               */
@@ -711,7 +994,8 @@ double sinh(double x)
 #define    _sinh_v2m1    0.13830277879601902638e-4       /* (v/2) - 1    */
         double w = y - _sinh_lnv, z, r;
         if (w>_exp_arg_limit)
-        {   errno = ERANGE;
+        {   if (isinf(x)) return x;
+            errno = ERANGE;
             if (sign) return -HUGE_VAL;
             else return HUGE_VAL;
         }
@@ -721,7 +1005,7 @@ double sinh(double x)
         if (sign) return -r;
         else return r;
     }
-    else if (y<=1.0e-10) return x;
+    else if (!isgreater(y,1.0e-10)) return x;
     else
     {
 #define _sinh_p0    -0.35181283430177117881e6
@@ -743,12 +1027,12 @@ double sinh(double x)
 
 double cosh(double x)
 {
-    if (x<0.0) x = -x;
-    if (x>1.0)
-    {
-        x = x - _sinh_lnv;
+    x = fabs(x);
+    if (isgreater(x,1.0))
+    {   x = x - _sinh_lnv;
         if (x>_exp_arg_limit)
-        {   errno = ERANGE;
+        {   if (isinf(x)) return x;
+            errno = ERANGE;
             return HUGE_VAL;
         }
         x = exp(x);   /* the range check above ensures that this does    */
@@ -768,11 +1052,11 @@ double tanh(double x)
 /* The first two exits avoid premature overflow as well as needless use  */
 /* of the exp() function.                                                */
     int sign;
-    if (x>27.0) return 1.0;         /* here exp(2x) dominates 1.0        */
-    else if (x<-27.0) return -1.0;
-    if (x<0.0) x = -x, sign = 1;
+    if (isgreater(x,27.0)) return 1.0;  /* here exp(2x) dominates 1.0    */
+    else if (isless(x,-27.0)) return -1.0;
+    if (isless(x,0.0)) x = -x, sign = 1;
     else sign = 0;
-    if (x>0.549306144334054846)     /* ln(3)/2 is crossover point        */
+    if (isgreater(x,0.549306144334054846)) /* ln(3)/2 is crossover point */
     {   x = exp(2.0*x);
         x = 1.0 - 2.0/(x + 1.0);
         if (sign) return -x;
@@ -785,7 +1069,7 @@ double tanh(double x)
 #define _tanh_q1     0.22337720718962312926e4
 #define _tanh_q2     0.11274474380534949335e3
 #define _tanh_q3     1.0
-    if (x>1.0e-10)
+    if (isgreater(x,1.0e-10))
     {   double y = x*x;
         /* minimax rational approximation                                */
         y = (((_tanh_p2*y + _tanh_p1)*y + _tanh_p0)*y) /
@@ -796,6 +1080,100 @@ double tanh(double x)
     else return x;
 }
 
+/* Simple forms for now */
+float coshf(float x)
+{
+    return (float)cosh(x);
+}
+
+float sinhf(float x)
+{
+    return (float)sinh(x);
+}
+
+float tanhf(float x)
+{
+    return (float)tanh(x);
+}
+
+double asinh(double x)
+{
+    if (isless(x, 0.0))
+        return -asinh(-x);
+
+    if (x == 0) return x; // asinh(ą0) returns ą0
+
+    return log(x+hypot(x,1.0));
+}
+
+double acosh(double x)
+{
+    if (isless(x, 1.0))
+    {   errno = EDOM;
+        return NAN;
+    }
+
+    // acosh(0) = 2.0*log(sqrt(1)+sqrt(0)) = 2.0*log(1) = +0
+    return 2.0*log(sqrt((x+1)*0.5)+sqrt((x-1)*0.5));
+}
+
+double atanh(double x)
+{
+    if (isless(x, 0.0))
+        return -atanh(-x);
+
+    if (x == 0) return x; // atanh(ą0) returns ą0
+    if (isgreater(x, 1.0))
+    {   errno = EDOM;
+        return NAN;
+    }
+    if (x == 1) // atanh(ą1) returns ąinf
+    {   errno = ERANGE;
+        return HUGE_VAL;
+    }
+
+    return 0.5*log((1+x)/(1-x));
+}
+
+float asinhf(float x)
+{
+    if (isless(x, 0.0F))
+        return -asinhf(-x);
+
+    if (x == 0) return x; // asinhf(ą0) returns ą0
+
+    return (float) log(x+hypot(x,1.0));
+}
+
+float acoshf(float x)
+{
+    if (isless(x, 1.0F))
+    {   errno = EDOM;
+        return NAN;
+    }
+
+    // acoshf(0) = 2.0*log(sqrt(1)+sqrt(0)) = 2.0*log(1) = +0
+    return (float) (2.0*log(sqrt((x+1.0)*0.5)+sqrt((x-1.0)*0.5)));
+}
+
+float atanhf(float x)
+{
+    if (isless(x, 0.0F))
+        return -atanhf(-x);
+
+    if (x == 0) return x; // atanhf(ą0) returns ą0
+    if (isgreater(x, 1.0))
+    {   errno = EDOM;
+        return NAN;
+    }
+    if (x == 1) // atanhf(ą1) returns ąinf
+    {   errno = ERANGE;
+        return HUGE_VALF;
+    }
+
+    return (float) (0.5*log((1.0+x)/(1.0-x)));
+}
+
 double fmod(double x, double y)
 {
 /* floating point remainder of (x/y) for integral quotient. Remainder    */
@@ -823,6 +1201,34 @@ double fmod(double x, double y)
     return r;
 }
 
+float fmodf(float x, float y)
+{
+/* floating point remainder of (x/y) for integral quotient. Remainder    */
+/* has same sign as x.                                                   */
+    float q, r;
+    if (y==0.0F)
+    {
+      errno = EDOM;
+      return -HUGE_VALF;
+    }
+    if (x==0.0F) return x;
+    if (y < 0.0F) y = -y;
+    r = modff(x/y, &q);
+    r = x - q * y;
+/* The next few lines are an ultra-cautious scheme to ensure that the    */
+/* result is less than fabs(y) in value and that it has the sign of x.   */
+    if (x > 0.0F)
+    {   while (r >= y) r -= y;
+        while (r < 0.0F) r += y;
+    }
+    else
+    {   while (r <= -y) r += y;
+        while (r > 0.0F) r -= y;
+    }
+    return r;
+}
+
+#if 0
 double (floor)(double d)
 {
 /* round x down to an integer towards minus infinity.                    */
@@ -855,7 +1261,7 @@ double (ceil)(double d)
 /* round x up to an integer towards plus infinity.                       */
     fp_number x;
     int exponent, mask, exact;
-    if (d == 0.0) return 0.0;
+    if (d == 0.0) return d;
     x.d = d;                            /* pun on union type             */
     if ((exponent = x.i.x - 0x3ff) < 0)
     {   if (x.i.s) return 0.0;
@@ -876,10 +1282,11 @@ double (ceil)(double d)
     if (exact!=0 && x.i.s==0) return x.d + 1.0;
     else return x.d;
 }
+#endif
 
-/*double (ceil)(double x)                { return ceil(x); }*/
+double (ceil)(double x)                { return ceil(x); }
 float (ceilf)(float x)                 { return ceilf(x); }
-/*double (floor)(double x)               { return floor(x); }*/
+double (floor)(double x)               { return floor(x); }
 float (floorf)(float x)                { return floorf(x); }
 double (rint)(double x)                { return rint(x); }
 float (rintf)(float x)                 { return rintf(x); }
@@ -889,11 +1296,11 @@ double (trunc)(double x)               { return trunc(x); }
 float (truncf)(float x)                { return truncf(x); }
 
 double (atan)(double x)                { return atan(x); }
-/*float (atanf)(float x)                 { return atanf(x); }*/
+float (atanf)(float x)                 { return atanf(x); }
 double (sin)(double x)                 { return sin(x); }
-/*float (sinf)(float x)                  { return sinf(x); }*/
+float (sinf)(float x)                  { return sinf(x); }
 double (cos)(double x)                 { return cos(x); }
-/*float (cosf)(float x)                  { return cosf(x); }*/
+float (cosf)(float x)                  { return cosf(x); }
 
 double modf(double value, double *iptr)
 {
@@ -901,17 +1308,17 @@ double modf(double value, double *iptr)
     fp_number x;
     int exponent, mask;
     if (value == 0.0)
-    {   *iptr = 0.0;
-        return 0.0;
+    {   *iptr = value;
+        return value;
     }
     x.d = value;
     if ((exponent = x.i.x - 0x3ff) < 0)
-    {   *iptr = 0.0;
+    {   *iptr = copysign(0.0, value);
         return value;
     }
     else if (exponent >= 52)
     {   *iptr = value;
-        return 0.0;
+        return copysign(0.0, value);
     }
     if (exponent >= 20)
     {   mask = ((unsigned) 0xffffffff) >> (exponent - 20);
@@ -926,6 +1333,30 @@ double modf(double value, double *iptr)
     return value - x.d;
 }
 
+float modff(float value, float *iptr)
+{
+/* splits value into integral part & fraction (both same sign)           */
+    fp_number_single x;
+    int exponent, mask;
+    if (value == 0.0F)
+    {   *iptr = value;
+        return value;
+    }
+    x.s = value;
+    if ((exponent = x.i.x - 0xff) < 0)
+    {   *iptr = copysignf(0.0F, value);
+        return value;
+    }
+    else if (exponent >= 23)
+    {   *iptr = value;
+        return copysignf(0.0F, value);
+    }
+    mask = 0x7fffff >> exponent;
+    x.i.m &= ~mask;
+    *iptr = x.s;
+    return value - x.s;
+}
+
 double nan(const char *s)
 {
     return (double) NAN;
@@ -952,6 +1383,331 @@ float fdimf(float x, float y)
        return x - y; /* Will return NaN for NaN input */
 }
 
+#define _sqrt2pi   2.50662827463100050242
+
+/*
+ * Gamma functions computed using Lanczos' approximation.
+ * Double version uses coefficients computed as per Spouge (1994)
+ * to achieve (theoretically) < 1 ulp error.
+ * Float version uses original Lanczos coefficients.
+ *
+ * Lanczos' approximation:
+ *
+ * G(x+1) = (x+a)^(x+.5)* e^-(x+a) * sqrt(2*pi) *
+ *            [ c0 + c1/(x+1) + c2/(x+3).. + cn/(x+n) ]    (x > 0)
+ *
+ *
+ * Spouge's coefficients:
+ *  c0 = 1
+ *  c[k] = (-1)^(k-1) * e^(a-k) * (a-k)^(k-0.5)        ( 1 <= k < ceil(a) )
+ *        ------------------------------------
+ *                  sqrt(2*pi) * (k-1)!
+ *
+ * giving relative error < sqrt(a) * (2*pi)^-(a+0.5) / (a+x)
+ *
+ * Useful relations: gamma(x+1) = x*gamma(x)
+ *                   gamma(1-x) = pi / (gamma(x)*sin(pi*x))
+ *                   gamma(n+1) = n!
+ */
+
+#define _lgamma_c1   166599025.853949811570  // actually c[k]*sqrt(2*pi)
+#define _lgamma_c2  -981939810.195007931170
+#define _lgamma_c3   2548964102.46316408700
+#define _lgamma_c4  -3836248618.43839895348
+#define _lgamma_c5   3709080184.61731236844
+#define _lgamma_c6  -2412708472.49486138749
+#define _lgamma_c7   1075449464.75190680642
+#define _lgamma_c8  -328534715.011179056348
+#define _lgamma_c9   67752870.4715251633277
+#define _lgamma_c10 -9145761.20044444915581
+#define _lgamma_c11  768402.637723269577278
+#define _lgamma_c12 -37175.9448951564986832
+#define _lgamma_c13  917.944248521710658895
+#define _lgamma_c14 -9.51510944794615044564
+#define _lgamma_c15  0.0294177178100457006509
+#define _lgamma_c16 -1.37185031730621246722e-5
+#define _lgamma_c17  1.72316912091954830013e-10
+#define _lgamma_c18 -2.50065513100139951901e-20
+
+static inline double _gamma_sum(double x)
+{
+    /* Do it like this to avoid using client static data for an array */
+    return _sqrt2pi
+           + _lgamma_c1 / (x + 1)
+           + _lgamma_c2 / (x + 2)
+           + _lgamma_c3 / (x + 3)
+           + _lgamma_c4 / (x + 4)
+           + _lgamma_c5 / (x + 5)
+           + _lgamma_c6 / (x + 6)
+           + _lgamma_c7 / (x + 7)
+           + _lgamma_c8 / (x + 8)
+           + _lgamma_c9 / (x + 9)
+           + _lgamma_c10 / (x + 10)
+           + _lgamma_c11 / (x + 11)
+           + _lgamma_c12 / (x + 12)
+           + _lgamma_c13 / (x + 13)
+           + _lgamma_c14 / (x + 14)
+           + _lgamma_c15 / (x + 15)
+           + _lgamma_c16 / (x + 16)
+           + _lgamma_c17 / (x + 17)
+           + _lgamma_c18 / (x + 18);
+}
+
+#define _lgammaf_c0  1.000000000190015
+#define _lgammaf_c1  76.18009172947146
+#define _lgammaf_c2 -86.50532032941677
+#define _lgammaf_c3  24.01409824083091
+#define _lgammaf_c4 -1.231739572450155
+#define _lgammaf_c5  1.208650973866179e-3
+#define _lgammaf_c6 -5.395239384953e-6
+
+static inline double _gammaf_sum(double x)
+{
+    return _lgammaf_c0
+           + _lgammaf_c1 / (x + 1)
+           + _lgammaf_c2 / (x + 2)
+           + _lgammaf_c3 / (x + 3)
+           + _lgammaf_c4 / (x + 4)
+           + _lgammaf_c5 / (x + 5)
+           + _lgammaf_c6 / (x + 6);
+}
+
+double lgamma(double x)
+{
+    if (isinf(x)) return INFINITY;
+    if (isnan(x)) return x;
+
+    if (x < 1)
+    {
+        if (floor(x) == x)
+        {   errno = ERANGE;
+            return HUGE_VAL;
+        }
+
+        return log(fabs((1-x)*_pi_/sin(_pi_*x)))-lgamma(2-x);
+    }
+
+    if (x == 1 || x == 2) return +0;
+
+    return (x+0.5)*log(x+18.5) - (x+18.5) + log(_gamma_sum(x) / x);
+}
+
+float lgammaf(float x)
+{
+    if (isinf(x)) return INFINITY;
+    if (isnan(x)) return x;
+
+    if (x < 1)
+    {
+        if (floorf(x) == x)
+        {   errno = ERANGE;
+            return HUGE_VALF;
+        }
+
+        return (float) log(fabs((1.0-x)*_pi_/sin(_pi_*x)))-lgammaf(2-x);
+    }
+
+    if (x == 1 || x == 2) return +0;
+
+    return (float) ((x+0.5)*log(x+5.5) - (x+5.5) + log(_sqrt2pi * _gammaf_sum(x) / x));
+}
+
+double tgamma(double x)
+{
+    if (isinf(x))
+    {   if (x > 0)
+            return x;
+        else
+        {   errno = ERANGE;
+            return NAN;
+        }
+    }
+    if (isnan(x)) return x;
+
+    if (x == 0)
+    {   errno = ERANGE;
+        return copysign(HUGE_VAL, x);
+    }
+
+    if (floor(x) == x)
+    {
+        if (x < 0)
+        {   errno = EDOM;
+            return NAN;
+        }
+        else if (x <= 171)
+        {  double r = 1;
+            for (int n = (int) x - 1; n > 1; n--)
+                r *= n;
+            return r;
+        }
+    }
+
+    if (x < 1)
+        return (1-x)*_pi_/(sin(_pi_*x)*tgamma(2-x));
+
+    return exp(lgamma(x));
+}
+
+float tgammaf(float x)
+{
+    if (isinf(x))
+    {   if (x > 0)
+            return x;
+        else
+        {   errno = ERANGE;
+            return NAN;
+        }
+    }
+    if (isnan(x)) return x;
+
+    if (x == 0)
+    {   errno = ERANGE;
+        return copysignf(HUGE_VALF, x);
+    }
+
+    if (floorf(x) == x)
+    {
+        if (x < 0)
+        {   errno = EDOM;
+            return NAN;
+        }
+        else if (x <= 35)
+        {
+            float r = 1;
+            for (int n = (int) x - 1; n > 1; n--)
+                r *= n;
+            return r;
+        }
+    }
+
+    if (x < 1)
+        return (float) ((1.0-x)*_pi_/(sin(_pi_*x)*tgammaf(2-x)));
+
+    return expf(lgammaf(x));
+}
+
+/* Error function algorithms derived from "Numerical recipes in C" */
+
+#define _log_sqrt_pi 0.5723649429247000870717137 // == lgamma(0.5)
+
+/* Series calculation for incomplete gamma function P(0.5,x); good for */
+/* x <= 1.5. */
+static double gser05(double x, double epsilon)
+{
+    double sum,del,ap;
+
+    ap = 0.5;
+    del = sum = 2;
+    for (;;)
+    {   ++ap;
+        del *= x/ap;
+        sum += del;
+        if (fabs(del) < fabs(sum)*epsilon)
+            return sum*exp(-x+0.5*log(x)-_log_sqrt_pi);
+    }
+}
+
+/* Continued fraction calculation for incomplete gamma function */
+/* 1 - P(0.5,x); good for x >= 1.5. */
+static double gcf05(double x, double epsilon)
+{
+    double an,b,c,d,del,h;
+    #define FPMIN 1e-300
+
+    b = x+0.5;
+    c = 1/FPMIN;
+    d = 1/b;
+    h = d;
+    for (int i=1; ; i++)
+    {   an = i*(0.5-i);
+        b += 2;
+        d = an*d+b;
+        if (fabs(d) < FPMIN) d = FPMIN;
+        c = b + an/c;
+        if (fabs(c) < FPMIN) c = FPMIN;
+        d = 1/d;
+        del = d*c;
+        h *= del;
+        if (fabs(del-1) < epsilon) break;
+    }
+    return exp(-x+0.5*log(x)-_log_sqrt_pi)*h;
+}
+
+static double gammp05(double x, double epsilon)
+{
+    if (isunordered(x, 1.5))
+        return x;
+    else if (isless(x, 1.5))
+        return gser05(x,epsilon);
+    else
+        return 1 - gcf05(x,epsilon);
+}
+
+static double gammq05(double x, double epsilon)
+{
+    if (isunordered(x, 1.5))
+        return x;
+    else if (isless(x, 1.5))
+        return 1 - gser05(x,epsilon);
+    else
+        return gcf05(x,epsilon);
+}
+
+double erf(double x)
+{
+    if (x == 0) return x;
+    if (isless(x, 0.0)) return -erf(-x);
+    if (isgreater(x, 1e100)) return 1.0;
+
+    return gammp05(x*x, 3*DBL_EPSILON);
+}
+
+double erfc(double x)
+{
+    if (isgreater(fabs(x), 1e100)) return isless(x, 0.0) ? 2 : 0;
+
+    return isless(x, 0.0) ? 1+gammp05(x*x, 3*DBL_EPSILON)
+                          : gammq05(x*x, 3*DBL_EPSILON);
+}
+
+float erff(float x)
+{
+    if (x == 0) return x;
+    if (isless(x, 0.0)) return -erff(-x);
+    if (isgreater(x, 1e15F)) return 1.0F;
+
+    return (float) gammp05((double) x*x, 3.0*FLT_EPSILON);
+}
+
+#define _erfcf_c0  -1.26551223
+#define _erfcf_c1   1.00002368
+#define _erfcf_c2   0.37409196
+#define _erfcf_c3   0.09678418
+#define _erfcf_c4  -0.18628806
+#define _erfcf_c5   0.27886807
+#define _erfcf_c6  -1.13520398
+#define _erfcf_c7   1.48851586
+#define _erfcf_c8  -0.82215223
+#define _erfcf_c9   0.17087277
+
+float erfcf(float x)
+{
+    double t,r;
+
+    if (isgreater(fabsf(x), 1e15F)) return isless(x, 0.0F) ? 2 : 0;
+
+    t = 1/(1+0.5*fabsf(x));
+
+    r = (((((((((_erfcf_c9) * t + _erfcf_c8) * t + _erfcf_c7) * t +
+                 _erfcf_c6) * t + _erfcf_c5) * t + _erfcf_c4) * t +
+                 _erfcf_c3) * t + _erfcf_c2) * t + _erfcf_c1) * t +
+                 _erfcf_c0;
+
+    r = t*exp(r - (double)x*x);
+    return (float) (isless(x, 0.0F) ? 2-r : r);
+}
+
 #endif /* NO_FLOATING_POINT */
 
 /* end of math.c */
diff --git a/c/stdio b/c/stdio
index bad330c..26bb4c7 100644
--- a/c/stdio
+++ b/c/stdio
@@ -94,10 +94,32 @@ typedef struct __extradata {
   int __buflim;              /* used size of buffer                       */
   int __savedicnt;           /* after unget contains old icnt             */
   int __savedocnt;           /* after unget contains old ocnt             */
+#ifdef SUPPORT_WIDE
+  int __orientation;
+  mbstate_t __mbstate;       /* must be stored in fpos_t */
+#endif
 } _extradata, *_extradatap;
 
 static _extradatap _extra;
 
+#ifdef SUPPORT_WIDE
+#define O_NONE 0
+#define O_BYTE (-1)
+#define O_WIDE (+1)
+#define ORIENTATION(stream) ((stream)->__extrap->__orientation)
+#define BYTEORIENT(stream) (ORIENTATION(stream) == 0 ? \
+                            ORIENTATION(stream) = O_BYTE : \
+                            ORIENTATION(stream))
+#define ENSUREBYTE(stream,e) do { if (BYTEORIENT(stream) != O_BYTE) return e; } while (0)
+#define WIDEORIENT(stream) (ORIENTATION(stream) == 0 ? \
+                            ORIENTATION(stream) = O_WIDE : \
+                            ORIENTATION(stream))
+#define ENSUREWIDE(stream,e) do { if (WIDEORIENT(stream) != O_WIDE) return e; } while (0)
+#else
+#define BYTEORIENT(stream)
+#define ENSUREBYTE(stream,e)
+#endif
+
 #define EXTENT(stream) ((stream)->__extrap->__extent > (stream)->__ptr \
                        ? (stream)->__extrap->__extent : (stream)->__ptr)
 
@@ -222,6 +244,7 @@ int __backspace(FILE *stream)
 
 int ungetc(int c,FILE *stream)
 {   /* made into a fn to evaluate each arg once. */
+    ENSUREBYTE(stream, EOF);
     if (c==EOF || (stream->__flag & (_IOUNGET+_IONOREADS))) return EOF;
     /* put char into unget buffer */
     stream->__extrap->__lilbuf[1] = c;
@@ -808,6 +831,7 @@ size_t fread(void *ptr, size_t itemsize, size_t count, FILE *stream)
       * is concerned and that the number of WHOLE items read is returned.
       */
 dbmsg("fread %d\n", count);
+    ENSUREBYTE(stream, 0);
     return itemsize == 0 ? 0   /* slight ansi irrationality */
                          : _read(ptr, itemsize*count, stream) / itemsize;
 }
@@ -917,6 +941,7 @@ size_t fwrite(const void *ptr, size_t itemsize, size_t count, FILE *stream)
 /* The comments made about fread apply here too */
 dbmsg_noNL("fwrite %d ", count);
 dbmsg("itemsize %d (decimal)\n", itemsize);
+    ENSUREBYTE(fwrite, 0);
     return itemsize == 0 ? count
                          : _write(ptr, itemsize*count, stream) / itemsize;
 }
diff --git a/c/stdlib b/c/stdlib
index 2bdac5a..256ad21 100644
--- a/c/stdlib
+++ b/c/stdlib
@@ -154,23 +154,27 @@ void exit(int n)
     _exit(n);
 }
 
+void _Exit(int n)
+{
+/* Is this the best way of doing this? abort() probably shouldn't be calling
+ * atexit functions either...
+ */
+    while (exit_s.number_of_exit_functions!=0) {
+        int flags = _exitvector[exit_s.number_of_exit_functions].i;
+        if ((flags & 3) != 0) { ++exit_s.number_of_exit_functions; break; };
+    }
+    _exit(n);
+}
+
 void abort()
 {
     raise(SIGABRT);
     exit(1);
 }
 
-int abs(int x)
-{
-    if (x<0) return (-x);
-    else return x;
-}
+int (abs)(int x) { return abs(x); }
 
-long int labs(long int x)
-{
-    if (x<0) return (-x);
-    else return x;
-}
+long int (labs)(long int x) { return labs(x); }
 
 #if 0
 /* Compiler generates poo code at the minute - in machine code for now */
diff --git a/c/string b/c/string
index 24fd608..bf3e024 100644
--- a/c/string
+++ b/c/string
@@ -349,15 +349,17 @@ size_t strxfrm(char *s1, const char *s2, size_t n)
 
 int strcoll(const char *a, const char *b)
 {
-    int ret;
+    _kernel_swi_regs r;
 
     if (strcoll_territory == 0) return strcmp(a, b);  /* C locale */
-    if (_swix(Territory_Collate, _INR(0,3)|_OUT(0),
-                                 strcoll_territory, a, b, 0,
-                                 &ret))
+    r.r[0] = strcoll_territory;
+    r.r[1] = (int) a;
+    r.r[2] = (int) b;
+    r.r[3] = 0;
+    if (_kernel_swi(Territory_Collate, &r, &r))
         return 0;
 
-    return ret;
+    return r.r[0];
 }
 
 void _set_strcoll(int territory)
diff --git a/clib/Resources/UK/Messages b/clib/Resources/UK/Messages
index 0350496..ee7f547 100644
--- a/clib/Resources/UK/Messages
+++ b/clib/Resources/UK/Messages
@@ -74,3 +74,6 @@ C70:unknown error
 #{DictTokens}
 C71:Calling standard APCS-A no longer supported by C library
 C72:Application is not 32-bit compatible
+
+#{Default}
+C73:*** assertion failed: %s, function %s, file %s, line %d
diff --git a/clib/h/assert b/clib/h/assert
index ed1b5e1..00d464e 100644
--- a/clib/h/assert
+++ b/clib/h/assert
@@ -14,19 +14,20 @@
  */
 #pragma force_top_level
 
-/* assert.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.2 */
+/* assert.h: ISO 'C' (9899:1999) library header, section 7.2 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
-/* version 2.00 */
+/* version 2.01 */
 
 /*
  * The assert macro puts diagnostics into programs. When it is executed,
  * if its argument expression is false, it writes information about the
  * call that failed (including the text of the argument, the name of the
- * source file, and the source line number - the latter are respectively
- * the values of the preprocessing macros __FILE__ and __LINE__) on the
+ * source file, the source line number, and the name of the enclosing
+ * function - the latter are respectively the values of the preprocessing
+ * macros __FILE__ and __LINE__ and of the identifier __func__) on the
  * standard error stream. It then calls the abort function.
- * If its argument expression is true, the assert macro returns no value.
+ * The assert macro returns no value.
  */
 
 /*
@@ -38,9 +39,11 @@
 #ifndef __assert_h
 #  define __assert_h
 #ifdef __cplusplus
-   extern "C" void __assert(char *, char *, int);
+   extern "C" void __assert(const char *, const char *, int);
+   extern "C" void __assert2(const char *, const char *, const char *, int);
 #else
-   extern void __assert(char *, char *, int);
+   extern void __assert(const char *, const char *, int);
+   extern void __assert2(const char *, const char *, const char *, int);
 #endif
 #else
 #  undef assert
@@ -49,7 +52,13 @@
 #ifdef NDEBUG
 #  define assert(ignore) ((void)0)
 #else
-#  define assert(e) ((e) ? (void)0 : __assert(#e, __FILE__, __LINE__))
+#    define assert(e) ((e) ? (void)0 : __assert(#e, __FILE__, __LINE__))
+#  ifdef __STDC_VERSION__
+#    if __STDC_VERSION__ >= 199901
+#      undef assert
+#      define assert(e) ((e) ? (void)0 : __assert2(#e, __func__, __FILE__, __LINE__))
+#    endif
+#  endif
 #endif
 
 /* end of assert.h */
diff --git a/clib/h/ctype b/clib/h/ctype
index 3a79b1f..1a3cddc 100644
--- a/clib/h/ctype
+++ b/clib/h/ctype
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* ctype.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.3 */
+/* ctype.h: ISO 'C' (9899:1999) library header, section 7.4 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 2.00 */
@@ -89,27 +89,27 @@ extern unsigned char __ctype[];
     /* non-0 iff c is a digit, in 'a'..'f', or in 'A'..'F' */
 
 #ifndef __cplusplus
-extern int (isalnum)(int c);
-extern int (isalpha)(int c);
-extern int (iscntrl)(int c);
-extern int (isdigit)(int c);
-extern int (isgraph)(int c);
-extern int (islower)(int c);
-extern int (isprint)(int c);
-extern int (ispunct)(int c);
-extern int (isspace)(int c);
-extern int (isupper)(int c);
-extern int (isxdigit)(int c);
+int (isalnum)(int c);
+int (isalpha)(int c);
+int (iscntrl)(int c);
+int (isdigit)(int c);
+int (isgraph)(int c);
+int (islower)(int c);
+int (isprint)(int c);
+int (ispunct)(int c);
+int (isspace)(int c);
+int (isupper)(int c);
+int (isxdigit)(int c);
 #endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern int tolower(int c);
+int tolower(int c);
     /* if c is an upper-case letter then return the corresponding */
     /* lower-case letter, otherwise return c.                     */
 
-extern int toupper(int c);
+int toupper(int c);
     /* if c is an lower-case letter then return the corresponding */
     /* upper-case letter, otherwise return c.                     */
 #ifdef __cplusplus
diff --git a/clib/h/errno b/clib/h/errno
index 5a43702..ff628b6 100644
--- a/clib/h/errno
+++ b/clib/h/errno
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* errno.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.1.3 */
+/* errno.h: ISO 'C' (9899:1999) library header, section 7.5 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 2.00 */
diff --git a/clib/h/float b/clib/h/float
index abb3081..a764343 100644
--- a/clib/h/float
+++ b/clib/h/float
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* float.h: ISO 'C' (9899 Dec 99) library header, section 5.2.4.2 */
+/* float.h: ISO 'C' (9899 Dec 99) library header, section 5.2.4.2.2 */
 /* Copyright (C) Codemist Ltd, 1988 */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 3.00 */
@@ -50,7 +50,7 @@
      *       range of the double type, evaluate long double operations and
      *       constants to the range and precision of the long double type;
      *   2 : evaluate all operations and constants to the range and precision
-     *       of the lang double type;
+     *       of the long double type;
      *   ? : all other negative values are implementation defined.
      */
 
@@ -84,6 +84,8 @@
 #define DBL_MAX_EXP  1024
 #define LDBL_MAX_EXP 1024
     /* maximum integer such that FLT_RADIX raised to that power minus 1 is a */
+    /* representable finite floating-point number. */
+
 #define FLT_MAX_10_EXP  38
 #define DBL_MAX_10_EXP  308
 #define LDBL_MAX_10_EXP 308
diff --git a/clib/h/inttypes b/clib/h/inttypes
index d32a13b..024a817 100644
--- a/clib/h/inttypes
+++ b/clib/h/inttypes
@@ -200,21 +200,21 @@
 typedef struct imaxdiv_t { intmax_t quot, rem; } imaxdiv_t;
    /* type of the value returned by the imaxdiv function. */
 
-extern intmax_t imaxabs(intmax_t /*j*/);
+intmax_t imaxabs(intmax_t /*j*/);
    /*
     * computes the absolute value of an integer j. If the result cannot be
     * represented, the behaviour is undefined.
     * Returns: the absolute value.
     */
-extern imaxdiv_t imaxdiv(intmax_t /*numer*/, intmax_t /*denom*/);
+imaxdiv_t imaxdiv(intmax_t /*numer*/, intmax_t /*denom*/);
    /*
     * computes numer / denom and numer % denom in a single operation.
     * Returns: a structure of type imaxdiv_t, comprising both the quotient and
     *          the remainder.
     */
 
-extern intmax_t strtoimax(const char * restrict /*nptr*/,
-                                char ** restrict /*endptr*/, int /*base*/);
+intmax_t strtoimax(const char * restrict /*nptr*/,
+                         char ** restrict /*endptr*/, int /*base*/);
    /*
     * equivalent to the strtoll function, except that the initial portion of the
     * string is converted to intmax_t representation.
@@ -224,8 +224,8 @@ extern intmax_t strtoimax(const char * restrict /*nptr*/,
     *          (according to the sign of the value), and the value of the
     *          macro ERANGE is stored in errno.
     */
-extern uintmax_t strtoumax(const char * restrict /*nptr*/,
-                                 char ** restrict /*endptr*/, int /*base*/);
+uintmax_t strtoumax(const char * restrict /*nptr*/,
+                          char ** restrict /*endptr*/, int /*base*/);
    /*
     * equivalent to the strtoull function, except that the initial portion of
     * the string is converted to uintmax_t representation.
diff --git a/clib/h/locale b/clib/h/locale
index 8a1d674..1e9db56 100644
--- a/clib/h/locale
+++ b/clib/h/locale
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* locale.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.3 */
+/* locale.h: ISO 'C' (9899:1999) library header, section 7.11 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 2.00 */
diff --git a/clib/h/math b/clib/h/math
index e01bb28..09093cc 100644
--- a/clib/h/math
+++ b/clib/h/math
@@ -15,10 +15,10 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* math.h: ISO 'C' (9899:1999) library header, section 7.22 */
+/* math.h: ISO 'C' (9899:1999) library header, section 7.12 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991 */
-/* version 0.04 */
+/* version 0.05 */
 
 #ifndef __math_h
 #define __math_h
@@ -37,6 +37,10 @@ extern const double HUGE_VAL;
 #endif
 #endif
 
+#ifndef HUGE_VALL
+#define HUGE_VALL ((long double) HUGE_VAL)
+#endif
+
 #ifndef __cplusplus
 #ifndef HUGE_VALF
 #  define HUGE_VALF INFINITY
@@ -55,14 +59,17 @@ extern const double HUGE_VAL;
    /* the mutually exclusive kinds of floating-point values for fpclassify() */
 #endif
 
+#define FP_ILOGB0    (-0x7fffffff) /* -INT_MAX */
+#define FP_ILOGBNAN  (~0x7fffffff) /* INT_MIN */
+   /* integer constant expressions whose values are returned by ilogb(x) if */
+   /* x is zero or NaN, respectively. */
+
 #define MATH_ERRNO 1
 #define MATH_ERREXCEPT 2
 
 #define math_errhandling MATH_ERRNO
    /* <math.h> functions just set errno - no exceptions are raised */
 
-/*#pragma no_side_effects*/
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -73,16 +80,16 @@ extern "C" {
 
 #pragma no_side_effects
 #pragma force_fpargs_in_regs
-extern int __fpclassifyf(float);
-extern int __fpclassifyd(double);
-extern int __signbitf(float);
-extern int __signbitd(double);
+__caller_narrow int __fpclassifyf(float);
+int __fpclassifyd(double);
+__caller_narrow int __signbitf(float);
+int __signbitd(double);
 #pragma no_force_fpargs_in_regs
 #pragma side_effects
 
 #ifdef __cplusplus
-#define __classmacro(fn,r) (sizeof(r) == 4 ? __##fn##f(r) : \
-                                             __##fn##d(r))
+#define __classmacro(fn,r) (sizeof(r) == 4 ? __##fn##f((float)(r)) : \
+                                             __##fn##d((double)(r)))
 #else
 #define __assertfp(r) ___assert(___typeof(r) == 0x002 ||\
                                 ___typeof(r) == 0x202 ||\
@@ -90,8 +97,8 @@ extern int __signbitd(double);
                                 "Illegal type used with classification macro")
 
 #define __classmacro(fn,r) (__assertfp(r),\
-                            ___typeof(r) == 0x402 ? __##fn##f(r) : \
-                                                    __##fn##d(r))
+                            ___typeof(r) == 0x402 ? __##fn##f((float)(r)) : \
+                                                    __##fn##d((double)(r)))
 #endif
 
 #define fpclassify(r) __classmacro(fpclassify,(r))
@@ -109,232 +116,369 @@ extern int __signbitd(double);
 
 #endif
 
-extern double acos(double /*x*/);
+double acos(double /*x*/);
+float acosf(float /*x*/);
+long double acosl(long double /*x*/);
    /* computes the principal value of the arc cosine of x */
    /* a domain error occurs for arguments not in the range -1 to 1 */
    /* Returns: the arc cosine in the range 0 to Pi. */
-extern double asin(double /*x*/);
+double asin(double /*x*/);
+float asinf(float /*x*/);
+long double asinl(long double /*x*/);
    /* computes the principal value of the arc sine of x */
    /* a domain error occurs for arguments not in the range -1 to 1 */
    /* and -HUGE_VAL is returned. */
    /* Returns: the arc sine in the range -Pi/2 to Pi/2. */
-extern double atan(double /*x*/);
+double atan(double /*x*/);
+float atanf(float /*x*/);
+long double atanl(long double /*x*/);
    /* computes the principal value of the arc tangent of x */
    /* Returns: the arc tangent in the range -Pi/2 to Pi/2. */
-extern double atan2(double /*x*/, double /*y*/);
+double atan2(double /*y*/, double /*x*/);
+float atan2f(float /*y*/, float /*x*/);
+long double atan2l(long double /*y*/, long double /*x*/);
    /* computes the principal value of the arc tangent of y/x, using the */
    /* signs of both arguments to determine the quadrant of the return value */
-   /* a domain error occurs if both args are zero, and -HUGE_VAL returned. */
    /* Returns: the arc tangent of y/x, in the range -Pi to Pi. */
-
-extern double __d_atan(double);
-#define atan(x) __d_atan(x)
-#ifndef __cplusplus
-extern __caller_narrow float __r_atan(float);
-#define atanf(x) __r_atan(x)
-#endif
-
-extern double cos(double /*x*/);
+double cos(double /*x*/);
+float cosf(float /*x*/);
+long double cosl(long double /*x*/);
    /* computes the cosine of x (measured in radians). A large magnitude */
    /* argument may yield a result with little or no significance */
    /* Returns: the cosine value. */
-extern double sin(double /*x*/);
+double sin(double /*x*/);
+float sinf(float /*x*/);
+long double sinl(long double /*x*/);
    /* computes the sine of x (measured in radians). A large magnitude */
    /* argument may yield a result with little or no significance */
    /* Returns: the sine value. */
-
-extern double __d_cos(double);
-extern double __d_sin(double);
-#define cos(x) __d_cos(x)
-#define sin(x) __d_sin(x)
-#ifndef __cplusplus
-extern __caller_narrow float __r_sin(float);
-extern __caller_narrow float __r_cos(float);
-#define sinf(x) __r_sin(x)
-#define cosf(x) __r_cos(x)
-#endif
-
-extern double tan(double /*x*/);
+double tan(double /*x*/);
+float tanf(float /*x*/);
+long double tanl(long double /*x*/);
    /* computes the tangent of x (measured in radians). A large magnitude */
    /* argument may yield a result with little or no significance */
    /* Returns: the tangent value. */
    /*          if range error; returns HUGE_VAL. */
 
-extern double cosh(double /*x*/);
+double acosh(double /*x*/);
+float acoshf(float /*x*/);
+long double acoshl(long double /*x*/);
+   /* computes the (non-negative) arc hyperbolic cosine of x. */
+   /* A domain error occurs for arguments less than 1. */
+   /* Returns: arcosh x in the interval [0,+inf] */
+double asinh(double /*x*/);
+float asinhf(float /*x*/);
+long double asinhl(long double /*x*/);
+   /* computes the arc hyperbolic sine of x. */
+   /* Returns: arsinh x */
+double atanh(double /*x*/);
+float atanhf(float /*x*/);
+long double atanhl(long double /*x*/);
+   /* computes the arc hyperbolic tangent of x. A domain error occurs */
+   /* for arguments not in the interval [-1,+1]. A range error occurs */
+   /* if the argument equals -1 or +1. */
+   /* Returns: artanh x */
+double cosh(double /*x*/);
+float coshf(float /*x*/);
+long double coshl(long double /*x*/);
    /* computes the hyperbolic cosine of x. A range error occurs if the */
    /* magnitude of x is too large. */
    /* Returns: the hyperbolic cosine value. */
    /*          if range error; returns HUGE_VAL. */
-extern double sinh(double /*x*/);
+double sinh(double /*x*/);
+float sinhf(float /*x*/);
+long double sinhl(long double /*x*/);
    /* computes the hyperbolic sine of x. A range error occurs if the */
    /* magnitude of x is too large. */
    /* Returns: the hyperbolic sine value. */
    /*          if range error; returns -HUGE_VAL or HUGE_VAL depending */
    /*          on the sign of the argument */
-extern double tanh(double /*x*/);
+double tanh(double /*x*/);
+float tanhf(float /*x*/);
+long double tanhl(long double /*x*/);
    /* computes the hyperbolic tangent of x. */
    /* Returns: the hyperbolic tangent value. */
 
-extern double exp(double /*x*/);
-   /* computes the exponential function of x. A range error occurs if the */
+double exp(double /*x*/);
+float expf(float /*x*/);
+long double expl(long double /*x*/);
+   /* computes the base-e exponential of x. A range error occurs if the */
+   /* magnitude of x is too large. */
+   /* Returns: e^x */
+   /*          if underflow range error; 0 is returned. */
+   /*          if overflow range error; HUGE_VAL is returned. */
+double exp2(double /*x*/);
+float exp2f(float /*x*/);
+long double exp2l(long double /*x*/);
+   /* computes the base-2 exponential of x. A range error occurs if the */
    /* magnitude of x is too large. */
-   /* Returns: the exponential value. */
+   /* Returns: 2^x */
    /*          if underflow range error; 0 is returned. */
    /*          if overflow range error; HUGE_VAL is returned. */
-extern double frexp(double /*value*/, int * /*exp*/);
+double expm1(double /*x*/);
+float expm1f(float /*x*/);
+long double expm1l(long double /*x*/);
+   /* computes the base-e exponential of x, minus 1. A range error occurs if */
+   /* the magnitude of x is too large. */
+   /* Returns: e^x - 1 */
+double frexp(double /*value*/, int * /*exp*/);
+float frexpf(float /*value*/, int * /*exp*/);
+long double frexpl(long double /*value*/, int * /*exp*/);
    /* breaks a floating-point number into a normalised fraction and an */
    /* integral power of 2. It stores the integer in the int object pointed */
    /* to by exp. */
    /* Returns: the value x, such that x is a double with magnitude in the */
    /* interval 0.5 to 1.0 or zero, and value equals x times 2 raised to the */
    /* power *exp. If value is zero, both parts of the result are zero. */
-extern double ldexp(double /*x*/, int /*exp*/);
+int ilogb(double /*x*/);
+int ilogbf(float /*x*/);
+int ilogbl(long double /*x*/);
+   /* extracts the exponent of x as a signed int value. If x is zero it */
+   /* computes the value FP_ILOGB0; if x is infinite it computes the value */
+   /* INT_MAX; if x is a NaN it computes the value FP_ILOGBNAN; otherwise it */
+   /* is equivalent to calling the corresponding logb function and casting */
+   /* the returned value to type int. A range error occurs if x is 0. */
+   /* Returns: the exponent of x as a signed int value. */
+double ldexp(double /*x*/, int /*exp*/);
+float ldexpf(float /*x*/, int /*exp*/);
+long double ldexpl(long double /*x*/, int /*exp*/);
    /* multiplies a floating-point number by an integral power of 2. */
    /* A range error may occur. */
    /* Returns: the value of x times 2 raised to the power of exp. */
    /*          if range error; HUGE_VAL is returned. */
-extern double log(double /*x*/);
-   /* computes the natural logarithm of x. A domain error occurs if the */
-   /* argument is negative, and -HUGE_VAL is returned. A range error occurs */
-   /* if the argument is zero. */
+double log(double /*x*/);
+float logf(float /*x*/);
+long double logl(long double /*x*/);
+   /* computes the base-e (natural) logarithm of x. A domain error occurs if */
+   /* the argument is negative, and -HUGE_VAL is returned. A range error */
+   /* occurs if the argument is zero. */
    /* Returns: the natural logarithm. */
    /*          if range error; -HUGE_VAL is returned. */
-extern double log10(double /*x*/);
-   /* computes the base-ten logarithm of x. A domain error occurs if the */
-   /* argument is negative. A range error occurs if the argument is zero. */
+double log10(double /*x*/);
+float log10f(float /*x*/);
+long double log10l(long double /*x*/);
+   /* computes the base-ten (common) logarithm of x. A domain error occurs if */
+   /* the argument is negative. A range error occurs if the argument is zero. */
    /* Returns: the base-ten logarithm. */
-extern double modf(double /*value*/, double * /*iptr*/);
+double log1p(double /*x*/);
+float log1pf(float /*x*/);
+long double log1pl(long double /*x*/);
+   /* computes the base-e (natural) logarithm of 1 plus the argument. A */
+   /* domain error occurs if the argument is less than -1. A range error */
+   /* occurs if the argument equals -1. */
+   /* Returns: the natural logarithm of (1+x). */
+double log2(double /*x*/);
+float log2f(float /*x*/);
+long double log2l(long double /*x*/);
+   /* computes the base-two logarithm of x. A domain error occurs if the */
+   /* argument is negative. A range error occurs if the argument is zero. */
+   /* Returns: the base-two logarithm. */
+double logb(double /*x*/);
+float logbf(float /*x*/);
+long double logbl(long double /*x*/);
+   /* extracts the exponent of x, as a signed integer value in floating- */
+   /* point format. If x is subnormal it is treated as though it were */
+   /* normalised; thus, for positive finite x, */
+   /*      1  <=  x * FLT_RADIX ^ -logb(x)  <  FLT_RADIX     */
+   /* A domain error occurs if the argument is zero. */
+   /* Returns: the signed exponent of x */
+double modf(double /*value*/, double * /*iptr*/);
+float modff(float /*value*/, float * /*iptr*/);
+long double modfl(long double /*value*/, long double *  /*iptr*/);
    /* breaks the argument value into integral and fraction parts, each of */
    /* which has the same sign as the argument. It stores the integral part */
    /* as a double in the object pointed to by iptr. */
    /* Returns: the signed fractional part of value. */
-
-extern double hypot(double /*x*/, double /*y*/);
-extern float hypotf(float /*x*/, float /*y*/);
+double scalbn(double /*x*/, int /*n*/);
+float scalbnf(float /*x*/, int /*n*/);
+long double scalbnl(long double /*x*/, int /*n*/);
+double scalbln(double /*x*/, long int /*n*/);
+float scalblnf(float /*x*/, long int /*n*/);
+long double scalblnl(long double /*x*/, long int /*n*/);
+   /* computes x * FLT_RADIX^n efficiently. A range error may occur. */
+   /* Returns: x * FLT_RADIX^n */
+
+double cbrt(double /*x*/);
+float cbrtf(float /*x*/);
+long double cbrtl(long double /*x*/);
+   /* computes the real cube root of x. */
+   /* Returns: x^(1/3) */
+#pragma no_side_effects
+double fabs(double /*x*/);
+float fabsf(float /*x*/);
+long double fabsl(long double /*x*/);
+   /* computes the absolute value of the floating-point number x. */
+   /* Returns: the absolute value of x. */
+#pragma side_effects
+double hypot(double /*x*/, double /*y*/);
+float hypotf(float /*x*/, float /*y*/);
+long double hypotl(long double /*x*/, long double /*y*/);
    /* computes the square root of the sum of the squares of x and y, without */
-   /* undue overflow or underflow. A ronge error may occur. */
+   /* undue overflow or underflow. A range error may occur. */
    /* Returns: sqrt(x^2 + y^2) */
-extern double pow(double /*x*/, double /*y*/);
+double pow(double /*x*/, double /*y*/);
+float powf(float /*x*/, float /*y*/);
+long double powl(long double /*x*/, long double /*y*/);
    /* computes x raised to the power of y. A domain error occurs if x is */
    /* zero and y is less than or equal to zero, or if x is negative and y */
    /* is not an integer, and -HUGE_VAL returned. A range error may occur. */
    /* Returns: the value of x raised to the power of y. */
    /*          if underflow range error; 0 is returned. */
    /*          if overflow range error; HUGE_VAL is returned. */
-extern double sqrt(double /*x*/);
+double sqrt(double /*x*/);
+float sqrtf(float /*x*/);
+long double sqrtl(long double /*x*/);
    /* computes the non-negative square root of x. A domain error occurs */
    /* if the argument is negative, and -HUGE_VAL returned. */
    /* Returns: the value of the square root. */
 
-extern double fabs(double /*x*/);
-extern float fabsf(float /*x*/);
-   /* computes the absolute value of the floating-point number x. */
-   /* Returns: the absolute value of x. */
-extern double ceil(double /*x*/);
-extern float ceilf(float /*x*/);
+double erf(double /*x*/);
+float erff(float /*x*/);
+long double erfl(long double /*x*/);
+   /* computes the error function of x. */
+   /* Returns: erf x = 2/sqrt(pi) * integral[0,x] (e^(-t^2)) dt */
+double erfc(double /*x*/);
+float erfcf(float /*x*/);
+long double erfcl(long double /*x*/);
+   /* computes the complementary error function of x. A range error occurs */
+   /* if x is too large.
+   /* Returns: erfc x = 1 - erf x                                  */
+   /*                 = 2/sqrt(pi) * integral[x,inf] (e^(-t^2)) dt */
+double lgamma(double /*x*/);
+float lgammaf(float /*x*/);
+long double lgammal(long double /*x*/);
+   /* computes the natural logarithm of the absolute value of gamma of x. */
+   /* A range error occurs if x is too large. A range error occurs if x is */
+   /* a negative integer or zero. */
+   /* Returns: log |Gamma(x)| */
+double tgamma(double /*x*/);
+float tgammaf(float /*x*/);
+long double tgammal(long double /*x*/);
+   /* computes the gamma function of x. A domain error occurs if x is a */
+   /* negative integer or if the result cannot be represented when x is */
+   /* zero. A range error may occur if the magnitude of x is too large or */
+   /* too small. */
+   /* Returns: Gamma(x) */
+
+#pragma no_side_effects
+double ceil(double /*x*/);
+float ceilf(float /*x*/);
+long double ceill(long double /*x*/);
    /* computes the smallest integer not less than x. */
    /* Returns: the smallest integer not less than x, expressed as a double. */
-extern double floor(double /*x*/);
-extern float floorf(float /*x*/);
+double floor(double /*x*/);
+float floorf(float /*x*/);
+long double floorl(long double /*x*/);
    /* computes the largest integer not greater than x. */
    /* Returns: the largest integer not greater than x, expressed as a double */
-extern double nearbyint(double /*x*/);
-extern float nearbyintf(float /*x*/);
+double nearbyint(double /*x*/);
+float nearbyintf(float /*x*/);
+long double nearbyintl(long double /*x*/);
    /* rounds its argument to an integer value, using the current rounding */
    /* direction. Does not raise the inexact exception. */
    /* Returns: the rounded integer value. */
-extern double rint(double /*x*/);
-extern float rintf(float /*x*/);
+double rint(double /*x*/);
+float rintf(float /*x*/);
+long double rintl(long double /*x*/);
    /* rounds its argument to an integer value, using the current rounding */
    /* direction. Raises "inexact" if the result differs from the argument. */
    /* Returns: the rounded integer value. */
-extern long int lrint(double /*x*/);
-extern long int lrintf(float /*x*/);
+#pragma side_effects
+long int lrint(double /*x*/);
+long int lrintf(float /*x*/);
+long int lrintl(long double /*x*/);
    /* rounds its argument to an integer value, using the current rounding */
    /* direction. Raises "inexact" if the result differs from the argument. */
    /* Returns: the rounded integer value. */
-extern double round(double /*x*/);
-extern float roundf(float /*x*/);
+#pragma no_side_effects
+double round(double /*x*/);
+float roundf(float /*x*/);
+long double roundl(long double /*x*/);
    /* rounds its argument to the nearest integer value, rounding halfway */
    /* cases away from zero. */
    /* Returns: the rounded integer value. */
-extern long int lround(double /*x*/);
-extern long int lroundf(float /*x*/);
+#pragma side_effects
+long int lround(double /*x*/);
+long int lroundf(float /*x*/);
+long int lroundl(long double /*x*/);
    /* rounds its argument to the nearest integer value, rounding halfway */
    /* cases away from zero. */
    /* Returns: the rounded integer value. */
-extern double trunc(double /*x*/);
-extern float truncf(float /*x*/);
+#pragma no_side_effects
+double trunc(double /*x*/);
+float truncf(float /*x*/);
+long double truncl(long double /*x*/);
    /* rounds its argument to the integer value, nearest to but no larger in */
    /* magnitude than the argument. */
    /* Returns: the truncated integer value. */
-extern double fmod(double /*x*/, double /*y*/);
+#pragma side_effects
+double fmod(double /*x*/, double /*y*/);
+float fmodf(float /*x*/, float /*y*/);
+long double fmodl(long double /*x*/, long double /*y*/);
    /* computes the floating-point remainder of x/y. */
    /* Returns: the value x - i * y, for some integer i such that, if y is */
    /*          nonzero, the result has the same sign as x and magnitude */
    /*          less than the magnitude of y. If y is zero, a domain error */
    /*          occurs and -HUGE_VAL is returned. */
-extern double remainder(double /*x*/, double /*y*/);
-extern float remainderf(float /*x*/, float /*y*/);
+double remainder(double /*x*/, double /*y*/);
+float remainderf(float /*x*/, float /*y*/);
+long double remainderl(long double /*x*/, long double /*y*/);
    /* computes the remainder x REM y required by IEEE 754 */
    /* Returns: x REM y */
 
-extern double __d_abs(double);
-extern double __d_floor(double);
-extern double __d_ceil(double);
-extern double __d_trunc(double);
-extern double __d_rint(double);
-extern long int __d_lrint(double);
-extern float __r_abs(float);
-#define fabs(x) __d_abs(x)
-#define floor(x) __d_floor(x)
-#define ceil(x) __d_ceil(x)
-#define trunc(x) __d_trunc(x)
-#define rint(x) __d_rint(x)
-#define lrint(x) __d_lrint(x)
-#ifndef __cplusplus
-extern __caller_narrow float __r_floor(float);
-extern __caller_narrow float __r_ceil(float);
-extern __caller_narrow float __r_trunc(float);
-extern __caller_narrow float __r_rint(float);
-extern __caller_narrow long int __r_lrint(float);
-#define fabsf(x) __r_abs(x)
-#define floorf(x) __r_floor(x)
-#define ceilf(x) __r_ceil(x)
-#define truncf(x) __r_trunc(x)
-#define rintf(x) __r_rint(x)
-#define lrintf(x) __r_lrint(x)
-#endif
-
+#pragma no_side_effects
 #ifndef __cplusplus
 #pragma force_fpargs_in_regs
-extern double copysign(double /*x*/, double /*y*/);
-extern float copysignf(float /*x*/, float /*y*/);
+double copysign(double /*x*/, double /*y*/);
+__caller_narrow float copysignf(float /*x*/, float /*y*/);
+long double copysignl(long double /*x*/, long double /*y*/);
 #pragma no_force_fpargs_in_regs
    /* produce a value with the magnitude of x and the sign of y. They */
    /* produce a NaN (with the sign of y) if x is a NaN. */
    /* Returns: a value with the magnitude of x and the sign of y. */
 #endif
-extern double nan(const char * /*tagp*/);
-extern float nanf(const char * /*tagp*/);
+double nan(const char * /*tagp*/);
+float nanf(const char * /*tagp*/);
+long double nanl(const char * /*tagp*/);
    /* Returns: a quiet NaN, with content indicated through tagp. */
-extern double nextafter(double /*x*/, double /*y*/);
-extern float nextafterf(float /*x*/, float /*y*/);
+#pragma side_effects
+double nextafter(double /*x*/, double /*y*/);
+float nextafterf(float /*x*/, float /*y*/);
+long double nextafterl(long double /*x*/, long double /*y*/);
    /* Returns: the next representable value in the specified format after */
    /*          x in the direction of y */
-extern double fdim(double /*x*/, double /*y*/);
-extern float fdimf(float /*x*/, float /*y*/);
+double nexttoward(double /*x*/, long double /*y*/);
+float nexttowardf(float /*x*/, long double /*y*/);
+long double nexttowardl(long double /*x*/, long double /*y*/);
+   /* equivalent to the nextafter functions except that the second parameter */
+   /* has type long double. */
+double fdim(double /*x*/, double /*y*/);
+float fdimf(float /*x*/, float /*y*/);
+long double fdiml(long double /*x*/, long double /*y*/);
    /* determine the positive difference between their arguments: */
    /* { x-y if x > y  */
    /* { +0  if x <= y */
    /* A range error may occur. */
    /* Returns: the positive difference value. */
-extern double fmax(double /*x*/, double /*y*/);
-extern float fmaxf(float /*x*/, float /*y*/);
+#pragma no_side_effects
+double fmax(double /*x*/, double /*y*/);
+float fmaxf(float /*x*/, float /*y*/);
+long double fmaxl(long double /*x*/, long double /*y*/);
    /* Returns: the maximum numeric value of their arguments. */
-extern double fmin(double /*x*/, double /*y*/);
-extern float fminf(float /*x*/, float /*y*/);
+double fmin(double /*x*/, double /*y*/);
+float fminf(float /*x*/, float /*y*/);
+long double fminl(long double /*x*/, long double /*y*/);
    /* Returns: the minimum numeric value of their arguments. */
+#pragma side_effects
+
+double fma(double /*x*/, double /*y*/, double /*z*/);
+float fmaf(float /*x*/, float /*y*/, float /*z*/);
+long double fmal(long double /*x*/, long double /*y*/, long double /*z*/);
+   /* computes (x*y)+z, rounded as one ternary operation: it computes */
+   /* the value (as if) to infinite precision and rounds once to the result */
+   /* format, according to the rounding mode characterised by the value of */
+   /* FLT_ROUNDS. */
+   /* Returns: (x*y)+z, rounded as one ternary operation. */
 
 #ifndef __cplusplus
 #define isgreater(x,y)      ((x) __greater (y))
@@ -349,12 +493,50 @@ extern float fminf(float /*x*/, float /*y*/);
    /* "invalid" floating-point exception. */
 #endif
 
+/* Some functions can be safely inlined - appropriate macros defined here */
+double __d_atan(double);
+double __d_cos(double);
+double __d_sin(double);
+double __d_abs(double);
+double __d_floor(double);
+double __d_ceil(double);
+double __d_trunc(double);
+double __d_rint(double);
+long int __d_lrint(double);
+float __r_abs(float);
+#define atan(x) __d_atan(x)
+#define cos(x) __d_cos(x)
+#define sin(x) __d_sin(x)
+#define fabs(x) ((void) sizeof fabs(x), __abs (double) (x))
+#define floor(x) __d_floor(x)
+#define ceil(x) __d_ceil(x)
+#define trunc(x) __d_trunc(x)
+#define rint(x) __d_rint(x)
+#define lrint(x) __d_lrint(x)
+#ifndef __cplusplus
+__caller_narrow float __r_atan(float);
+__caller_narrow float __r_sin(float);
+__caller_narrow float __r_cos(float);
+__caller_narrow float __r_floor(float);
+__caller_narrow float __r_ceil(float);
+__caller_narrow float __r_trunc(float);
+__caller_narrow float __r_rint(float);
+__caller_narrow long int __r_lrint(float);
+#define atanf(x) __r_atan(x)
+#define sinf(x) __r_sin(x)
+#define cosf(x) __r_cos(x)
+#define fabsf(x) ((void) sizeof fabsf(x), __abs (float) (x))
+#define floorf(x) __r_floor(x)
+#define ceilf(x) __r_ceil(x)
+#define truncf(x) __r_trunc(x)
+#define rintf(x) __r_rint(x)
+#define lrintf(x) __r_lrint(x)
+#endif
+
 #ifdef __cplusplus
 }
 #endif
 
-#pragma side_effects
-
 #endif
 
 /* end of math.h */
diff --git a/clib/h/setjmp b/clib/h/setjmp
index 2388f48..1110dd5 100644
--- a/clib/h/setjmp
+++ b/clib/h/setjmp
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* setjmp.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.6 */
+/* setjmp.h: ISO 'C' (9899:1999) library header, section 7.13 */
 /* Copyright (C) A.C. Norman and A. Mycroft */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 2.00 */
@@ -49,7 +49,7 @@ typedef int jmp_buf[22];    /* size suitable for the ARM */
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern int setjmp(jmp_buf /*env*/);
+int setjmp(jmp_buf /*env*/);
    /* Saves its calling environment in its jmp_buf argument, for later use
     * by the longjmp function.
     * Returns: If the return is from a direct invocation, the setjmp function
@@ -57,7 +57,7 @@ extern int setjmp(jmp_buf /*env*/);
     *          function, the setjmp function returns a non zero value.
     */
 
-extern void longjmp(jmp_buf /*env*/, int /*val*/);
+void longjmp(jmp_buf /*env*/, int /*val*/);
    /* Restores the environment saved by the most recent call to setjmp in the
     * same invocation of the program, with the corresponding jmp_buf argument.
     * If there has been no such call, or if the function containing the call
diff --git a/clib/h/signal b/clib/h/signal
index 85d5593..7c8a565 100644
--- a/clib/h/signal
+++ b/clib/h/signal
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* signal.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.7 */
+/* signal.h: ISO 'C' (9899:1999) library header, section 7.14 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 2.00 */
@@ -36,9 +36,9 @@ typedef int sig_atomic_t;
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern void __SIG_DFL(int);
-extern void __SIG_ERR(int);
-extern void __SIG_IGN(int);
+void __SIG_DFL(int);
+void __SIG_ERR(int);
+void __SIG_IGN(int);
    /*
     * Each of the following macros expand to a constant expression with a
     * distinct value and has the same type as the second argument to, and the
@@ -69,7 +69,7 @@ extern void __SIG_IGN(int);
 #define SIGUSR2 9
 #define SIGOSERROR 10
 
-extern void (*signal (int /*sig*/, void (* /*func*/ )(int)))(int);
+void (*signal (int /*sig*/, void (* /*func*/ )(int)))(int);
    /*
     * Chooses one of three ways in which receipt of the signal number sig is to
     * be subsequently handled. If the value of func is SIG_DFL, default
@@ -102,7 +102,7 @@ extern void (*signal (int /*sig*/, void (* /*func*/ )(int)))(int);
     *          integer expression errno is set to indicate the error.
     */
 
-extern int raise(int /*sig*/);
+int raise(int /*sig*/);
    /* sends the signal sig to the executing program. */
    /* Returns: zero if successful, non-zero if unsuccessful. */
 #ifdef __cplusplus
diff --git a/clib/h/stddef b/clib/h/stddef
index d2e8015..2668361 100644
--- a/clib/h/stddef
+++ b/clib/h/stddef
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* stddef.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.1.4 */
+/* stddef.h: ISO 'C' (9899:1999) library header, section 7.17 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 2.01 */
diff --git a/clib/h/stdio b/clib/h/stdio
index 180623d..a1ed212 100644
--- a/clib/h/stdio
+++ b/clib/h/stdio
@@ -15,19 +15,16 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* stdio.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.9 */
+/* stdio.h: ISO 'C' (9899:1999) library header, section 7.19 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd., 1990, 1992 */
-/* version 3.00 */
-
-/* AM July-88 changes to all prototypes so that                         */
-/*      #define mode 3; #include <stdio.h> can work as ANSI require.    */
+/* version 3.01 */
 
 /*
- * stdio.h declares two types, several macros, and many functions for
+ * stdio.h declares three types, several macros, and many functions for
  * performing input and output. For a discussion on Streams and Files
- * refer to sections 4.9.2 and 4.9.3 in the above ANSI draft, or to a
- * modern textbook on C.
+ * refer to sections 7.19.2 and 7.19.3 in the above ISO standard, or
+ * to a modern textbook on C.
  */
 
 #ifndef __stdio_h
@@ -152,7 +149,7 @@ extern FILE __iob[];
    /* pointer to a FILE object associated with standard error stream */
 #endif
 
-extern int remove(const char * /*filename*/);
+int remove(const char * /*filename*/);
    /*
     * causes the file whose name is the string pointed to by filename to be
     * removed. Subsequent attempts to open the file will fail, unless it is
@@ -161,7 +158,7 @@ extern int remove(const char * /*filename*/);
     * fails).
     * Returns: zero if the operation succeeds, nonzero if it fails.
     */
-extern int rename(const char * /*old*/, const char * /*new*/);
+int rename(const char * /*old*/, const char * /*new*/);
    /*
     * causes the file whose name is the string pointed to by old to be
     * henceforth known by the name given by the string pointed to by new. The
@@ -173,14 +170,14 @@ extern int rename(const char * /*old*/, const char * /*new*/);
     *          case if the file existed previously it is still known by its
     *          original name.
     */
-extern FILE *tmpfile(void);
+FILE *tmpfile(void);
    /*
     * creates a temporary binary file that will be automatically removed when
     * it is closed or at program termination. The file is opened for update.
     * Returns: a pointer to the stream of the file that it created. If the file
     *          cannot be created, a null pointer is returned.
     */
-extern char *tmpnam(char * /*s*/);
+char *tmpnam(char * /*s*/);
    /*
     * generates a string that is not the same as the name of an existing file.
     * The tmpnam function generates a different string each time it is called,
@@ -198,7 +195,7 @@ extern char *tmpnam(char * /*s*/);
     *          the argument as its value.
     */
 
-extern int fclose(FILE * /*stream*/);
+int fclose(FILE * /*stream*/);
    /*
     * causes the stream pointed to by stream to be flushed and the associated
     * file to be closed. Any unwritten buffered data for the stream are
@@ -208,7 +205,7 @@ extern int fclose(FILE * /*stream*/);
     * Returns: zero if the stream was succesfully closed, or nonzero if any
     *          errors were detected or if the stream was already closed.
     */
-extern int fflush(FILE * /*stream*/);
+int fflush(FILE * /*stream*/);
    /*
     * If the stream points to an output or update stream in which the most
     * recent operation was output, the fflush function causes any unwritten
@@ -218,7 +215,7 @@ extern int fflush(FILE * /*stream*/);
     * on the stream.
     * Returns: nonzero if a write error occurs.
     */
-extern FILE *fopen(const char * /*filename*/, const char * /*mode*/);
+FILE *fopen(const char * /*filename*/, const char * /*mode*/);
    /*
     * opens the file whose name is the string pointed to by filename, and
     * associates a stream with it.
@@ -261,8 +258,8 @@ extern FILE *fopen(const char * /*filename*/, const char * /*mode*/);
     * Returns: a pointer to the object controlling the stream. If the open
     *          operation fails, fopen returns a null pointer.
     */
-extern FILE *freopen(const char * /*filename*/, const char * /*mode*/,
-                     FILE * /*stream*/);
+FILE *freopen(const char * /*filename*/, const char * /*mode*/,
+              FILE * /*stream*/);
    /*
     * opens the file whose name is the string pointed to by filename and
     * associates the stream pointed to by stream with it. The mode argument is
@@ -273,15 +270,14 @@ extern FILE *freopen(const char * /*filename*/, const char * /*mode*/,
     * Returns: a null pointer if the operation fails. Otherwise, freopen
     *          returns the value of the stream.
     */
-extern void setbuf(FILE * /*stream*/, char * /*buf*/);
+void setbuf(FILE * /*stream*/, char * /*buf*/);
    /*
     * Except that it returns no value, the setbuf function is equivalent to the
     * setvbuf function invoked with the values _IOFBF for mode and BUFSIZ for
     * size, or (if buf is a null pointer), with the value _IONBF for mode.
     * Returns: no value.
     */
-extern int setvbuf(FILE * /*stream*/, char * /*buf*/,
-                   int /*mode*/, size_t /*size*/);
+int setvbuf(FILE * /*stream*/, char * /*buf*/, int /*mode*/, size_t /*size*/);
    /*
     * may be used after the stream pointed to by stream has been associated
     * with an open file but before it is read or written. The argument mode
@@ -301,7 +297,7 @@ extern int setvbuf(FILE * /*stream*/, char * /*buf*/,
     */
 
 #pragma -v1   /* hint to the compiler to check f/s/printf format */
-extern int fprintf(FILE * /*stream*/, const char * /*format*/, ...);
+int fprintf(FILE * /*stream*/, const char * /*format*/, ...);
    /*
     * writes output to the stream pointed to by stream, under control of the
     * string pointed to by format that specifies how subsequent arguments are
@@ -322,14 +318,14 @@ extern int fprintf(FILE * /*stream*/, const char * /*format*/, ...);
     * Returns: the number of characters transmitted, or a negative value if an
     *          output error occurred.
     */
-extern int printf(const char * /*format*/, ...);
+int printf(const char * /*format*/, ...);
    /*
     * is equivalent to fprintf with the argument stdout interposed before the
     * arguments to printf.
     * Returns: the number of characters transmitted, or a negative value if an
     *          output error occurred.
     */
-extern int snprintf(char * /*s*/, size_t /*n*/, const char * /*format*/, ...);
+int snprintf(char * /*s*/, size_t /*n*/, const char * /*format*/, ...);
    /*
     * is equivalent to fprintf, except that the argument s specifies an array
     * into which the generated output is to be written, rather than to a
@@ -343,7 +339,7 @@ extern int snprintf(char * /*s*/, size_t /*n*/, const char * /*format*/, ...);
     *          written if and only if the returned value is nonnegative and
     *          less than n.
     */
-extern int sprintf(char * /*s*/, const char * /*format*/, ...);
+int sprintf(char * /*s*/, const char * /*format*/, ...);
    /*
     * is equivalent to fprintf, except that the argument s specifies an array
     * into which the generated output is to be written, rather than to a
@@ -353,7 +349,7 @@ extern int sprintf(char * /*s*/, const char * /*format*/, ...);
     *          terminating null character.
     */
 #pragma -v2   /* hint to the compiler to check f/s/scanf format */
-extern int fscanf(FILE * /*stream*/, const char * /*format*/, ...);
+int fscanf(FILE * /*stream*/, const char * /*format*/, ...);
    /*
     * reads input from the stream pointed to by stream, under control of the
     * string pointed to by format that specifies the admissible input sequences
@@ -386,7 +382,7 @@ extern int fscanf(FILE * /*stream*/, const char * /*format*/, ...);
     *          even zero, in the event of an early conflict between an input
     *          character and the format.
     */
-extern int scanf(const char * /*format*/, ...);
+int scanf(const char * /*format*/, ...);
    /*
     * is equivalent to fscanf with the argument stdin interposed before the
     * arguments to scanf.
@@ -395,7 +391,7 @@ extern int scanf(const char * /*format*/, ...);
     *          input items assigned, which can be fewer than provided for, or
     *          even zero, in the event of an early matching failure.
     */
-extern int sscanf(const char * /*s*/, const char * /*format*/, ...);
+int sscanf(const char * /*s*/, const char * /*format*/, ...);
    /*
     * is equivalent to fscanf except that the argument s specifies a string
     * from which the input is to be obtained, rather than from a stream.
@@ -407,8 +403,7 @@ extern int sscanf(const char * /*s*/, const char * /*format*/, ...);
     *          even zero, in the event of an early matching failure.
     */
 #pragma -v0   /* back to default */
-extern int vfprintf(FILE * /*stream*/,
-                   const char * /*format*/, __va_list /*arg*/);
+int vfprintf(FILE * /*stream*/, const char * /*format*/, __va_list /*arg*/);
    /*
     * is equivalent to fprintf, with the variable argument list replaced by
     * arg, which has been initialised by the va_start macro (and possibly
@@ -417,8 +412,7 @@ extern int vfprintf(FILE * /*stream*/,
     * Returns: the number of characters transmitted, or a negative value if an
     *          output error occurred.
     */
-extern int vfscanf(FILE * /*stream*/,
-                   const char * /*format*/, __va_list /*arg*/);
+int vfscanf(FILE * /*stream*/, const char * /*format*/, __va_list /*arg*/);
    /*
     * is equivalent to fscanf, with the variable argument list replaced by
     * arg, which has been initialised by the va_start macro (and possibly
@@ -429,7 +423,7 @@ extern int vfscanf(FILE * /*stream*/,
     *          of input items assigned, which can be fewer than provided for,
     *          or even zero, in the event of an early matching failure.
     */
-extern int vprintf(const char * /*format*/, __va_list /*arg*/);
+int vprintf(const char * /*format*/, __va_list /*arg*/);
    /*
     * is equivalent to printf, with the variable argument list replaced by arg,
     * which has been initialised by the va_start macro (and possibly subsequent
@@ -437,7 +431,7 @@ extern int vprintf(const char * /*format*/, __va_list /*arg*/);
     * Returns: the number of characters transmitted, or a negative value if an
     *          output error occurred.
     */
-extern int vscanf(const char * /*format*/, __va_list /*arg*/);
+int vscanf(const char * /*format*/, __va_list /*arg*/);
    /*
     * is equivalent to scanf, with the variable argument list replaced by arg,
     * which has been initialised by the va_start macro (and possibly subsequent
@@ -447,8 +441,8 @@ extern int vscanf(const char * /*format*/, __va_list /*arg*/);
     *          input items assigned, which can be fewer than provided for, or
     *          even zero, in the event of an early matching failure.
     */
-extern int vsnprintf(char * /*s*/, size_t /*n*/,
-                     const char * /*format*/, __va_list /*arg*/);
+int vsnprintf(char * /*s*/, size_t /*n*/,
+              const char * /*format*/, __va_list /*arg*/);
    /*
     * is equivalent to snprintf, with the variable argument list replaced by
     * arg, which has been initialised by the va_start macro (and possibly
@@ -460,7 +454,7 @@ extern int vsnprintf(char * /*s*/, size_t /*n*/,
     *          written if and only if the returned value is nonnegative and
     *          less than n.
     */
-extern int vsprintf(char * /*s*/, const char * /*format*/, __va_list /*arg*/);
+int vsprintf(char * /*s*/, const char * /*format*/, __va_list /*arg*/);
    /*
     * is equivalent to sprintf, with the variable argument list replaced by
     * arg, which has been initialised by the va_start macro (and possibly
@@ -469,8 +463,7 @@ extern int vsprintf(char * /*s*/, const char * /*format*/, __va_list /*arg*/);
     * Returns: the number of characters written in the array, not counting the
     *          terminating null character.
     */
-extern int vsscanf(const char * /*s*/,
-                   const char * /*format*/, __va_list /*arg*/);
+int vsscanf(const char * /*s*/, const char * /*format*/, __va_list /*arg*/);
    /*
     * is equivalent to sscanf, with the variable argument list replaced by arg,
     * which has been initialised by the va_start macro (and possibly subsequent
@@ -481,7 +474,7 @@ extern int vsscanf(const char * /*s*/,
     *          even zero, in the event of an early matching failure.
     */
 
-extern int fgetc(FILE * /*stream*/);
+int fgetc(FILE * /*stream*/);
    /*
     * obtains the next character (if present) as an unsigned char converted to
     * an int, from the input stream pointed to by stream, and advances the
@@ -491,7 +484,7 @@ extern int fgetc(FILE * /*stream*/);
     *          set and fgetc returns EOF. If a read error occurs, the error
     *          indicator is set and fgetc returns EOF.
     */
-extern char *fgets(char * /*s*/, int /*n*/, FILE * /*stream*/);
+char *fgets(char * /*s*/, int /*n*/, FILE * /*stream*/);
    /*
     * reads at most one less than the number of characters specified by n from
     * the stream pointed to by stream into the array pointed to by s. No
@@ -504,7 +497,7 @@ extern char *fgets(char * /*s*/, int /*n*/, FILE * /*stream*/);
     *          during the operation, the array contents are indeterminate and a
     *          null pointer is returned.
     */
-extern int fputc(int /*c*/, FILE * /*stream*/);
+int fputc(int /*c*/, FILE * /*stream*/);
    /*
     * writes the character specified by c (converted to an unsigned char) to
     * the output stream pointed to by stream, at the position indicated by the
@@ -514,14 +507,14 @@ extern int fputc(int /*c*/, FILE * /*stream*/);
     * Returns: the character written. If a write error occurs, the error
     *          indicator is set and fputc returns EOF.
     */
-extern int fputs(const char * /*s*/, FILE * /*stream*/);
+int fputs(const char * /*s*/, FILE * /*stream*/);
    /*
     * writes the string pointed to by s to the stream pointed to by stream.
     * The terminating null character is not written.
     * Returns: EOF if a write error occurs; otherwise it returns a nonnegative
     *          value.
     */
-extern int __filbuf(FILE * /*stream*/);
+int __filbuf(FILE * /*stream*/);
    /*
     * SYSTEM USE ONLY, called by getc to refill buffer and or sort out flags.
     * Returns: first character put into buffer or EOF on error.
@@ -529,7 +522,7 @@ extern int __filbuf(FILE * /*stream*/);
 #define getc(p) \
     (--((p)->__icnt) >= 0 ? *((p)->__ptr)++ : __filbuf(p))
 #ifndef __cplusplus
-extern int (getc)(FILE * /*stream*/);
+int (getc)(FILE * /*stream*/);
 #endif
    /*
     * is equivalent to fgetc except that it may be (and is under
@@ -543,7 +536,7 @@ extern int (getc)(FILE * /*stream*/);
     */
 #define getchar() getc(stdin)
 #ifndef __cplusplus
-extern int (getchar)(void);
+int (getchar)(void);
 #endif
    /*
     * is equivalent to getc with the argument stdin.
@@ -552,7 +545,7 @@ extern int (getchar)(void);
     *          set and getchar returns EOF. If a read error occurs, the error
     *          indicator is set and getchar returns EOF.
     */
-extern char *gets(char * /*s*/);
+char *gets(char * /*s*/);
    /*
     * reads characters from the input stream pointed to by stdin into the array
     * pointed to by s, until end-of-file is encountered or a new-line character
@@ -564,7 +557,7 @@ extern char *gets(char * /*s*/);
     *          during the operation, the array contents are indeterminate and a
     *          null pointer is returned.
     */
-extern int __flsbuf(int /*c*/, FILE * /*stream*/);
+int __flsbuf(int /*c*/, FILE * /*stream*/);
    /*
     * SYSTEM USE ONLY, called by putc to flush buffer and or sort out flags.
     * Returns: character put into buffer or EOF on error.
@@ -572,7 +565,7 @@ extern int __flsbuf(int /*c*/, FILE * /*stream*/);
 #define putc(ch, p) \
     (--((p)->__ocnt) >= 0 ? (*((p)->__ptr)++ = (ch)) : __flsbuf(ch,p))
 #ifndef __cplusplus
-extern int (putc)(int /*c*/, FILE * /*stream*/);
+int (putc)(int /*c*/, FILE * /*stream*/);
 #endif
    /*
     * is equivalent to fputc except that it may be (and is under
@@ -584,14 +577,14 @@ extern int (putc)(int /*c*/, FILE * /*stream*/);
     */
 #define putchar(ch) putc(ch, stdout)
 #ifndef __cplusplus
-extern int (putchar)(int /*c*/);
+int (putchar)(int /*c*/);
 #endif
    /*
     * is equivalent to putc with the second argument stdout.
     * Returns: the character written. If a write error occurs, the error
     *          indicator is set and putc returns EOF.
     */
-extern int puts(const char * /*s*/);
+int puts(const char * /*s*/);
    /*
     * writes the string pointed to by s to the stream pointed to by stdout, and
     * appends a new-line character to the output. The terminating null
@@ -599,7 +592,7 @@ extern int puts(const char * /*s*/);
     * Returns: EOF if a write error occurs; otherwise it returns a nonnegative
     *          value.
     */
-extern int ungetc(int /*c*/, FILE * /*stream*/);
+int ungetc(int /*c*/, FILE * /*stream*/);
    /*
     * pushes the character specified by c (converted to an unsigned char) back
     * onto the input stream pointed to by stream. The character will be
@@ -625,8 +618,8 @@ extern int ungetc(int /*c*/, FILE * /*stream*/);
     *          operation fails.
     */
 
-extern size_t fread(void * /*ptr*/,
-                    size_t /*size*/, size_t /*nmemb*/, FILE * /*stream*/);
+size_t fread(void * /*ptr*/,
+             size_t /*size*/, size_t /*nmemb*/, FILE * /*stream*/);
    /*
     * reads into the array pointed to by ptr, up to nmemb members whose size is
     * specified by size, from the stream pointed to by stream. The file
@@ -640,8 +633,8 @@ extern size_t fread(void * /*ptr*/,
     *          nmemb is zero, fread returns zero and the contents of the array
     *          and the state of the stream remain unchanged.
     */
-extern size_t fwrite(const void * /*ptr*/,
-                    size_t /*size*/, size_t /*nmemb*/, FILE * /*stream*/);
+size_t fwrite(const void * /*ptr*/,
+              size_t /*size*/, size_t /*nmemb*/, FILE * /*stream*/);
    /*
     * writes, from the array pointed to by ptr up to nmemb members whose size
     * is specified by size, to the stream pointed to by stream. The file
@@ -652,7 +645,7 @@ extern size_t fwrite(const void * /*ptr*/,
     *          than nmemb only if a write error is encountered.
     */
 
-extern int fgetpos(FILE * /*stream*/, fpos_t * /*pos*/);
+int fgetpos(FILE * /*stream*/, fpos_t * /*pos*/);
    /*
     * stores the current value of the file position indicator for the stream
     * pointed to by stream in the object pointed to by pos. The value stored
@@ -663,7 +656,7 @@ extern int fgetpos(FILE * /*stream*/, fpos_t * /*pos*/);
     *          integer expression errno is set to an implementation-defined
     *          nonzero value (under RISCOS/Arthur/Brazil fgetpos cannot fail).
     */
-extern int fseek(FILE * /*stream*/, long int /*offset*/, int /*whence*/);
+int fseek(FILE * /*stream*/, long int /*offset*/, int /*whence*/);
    /*
     * sets the file position indicator for the stream pointed to by stream.
     * For a binary stream, the new position is at the signed number of
@@ -680,7 +673,7 @@ extern int fseek(FILE * /*stream*/, long int /*offset*/, int /*whence*/);
     * the next operation on an update stream may be either input or output.
     * Returns: nonzero only for a request that cannot be satisfied.
     */
-extern int fsetpos(FILE * /*stream*/, const fpos_t * /*pos*/);
+int fsetpos(FILE * /*stream*/, const fpos_t * /*pos*/);
    /*
     * sets  the file position indicator for the stream pointed to by stream
     * according to the value of the object pointed to by pos, which shall be a
@@ -694,7 +687,7 @@ extern int fsetpos(FILE * /*stream*/, const fpos_t * /*pos*/);
     *          nonzero value (under RISCOS/Arthur/Brazil the value that of EDOM
     *          in math.h).
     */
-extern long int ftell(FILE * /*stream*/);
+long int ftell(FILE * /*stream*/);
    /*
     * obtains the current value of the file position indicator for the stream
     * pointed to by stream. For a binary stream, the value is the number of
@@ -709,7 +702,7 @@ extern long int ftell(FILE * /*stream*/);
     *          expression errno to an implementation-defined nonzero value
     *          (under RISCOS/Arthur/Brazil ftell cannot fail).
     */
-extern void rewind(FILE * /*stream*/);
+void rewind(FILE * /*stream*/);
    /*
     * sets the file position indicator for the stream pointed to by stream to
     * the beginning of the file. It is equivalent to
@@ -718,7 +711,7 @@ extern void rewind(FILE * /*stream*/);
     * Returns: no value.
     */
 
-extern void clearerr(FILE * /*stream*/);
+void clearerr(FILE * /*stream*/);
    /*
     * clears the end-of-file and error indicators for the stream pointed to by
     * stream. These indicators are cleared only when the file is opened or by
@@ -728,7 +721,7 @@ extern void clearerr(FILE * /*stream*/);
 
 #define feof(stream) ((stream)->__flag & _IOEOF)
 #ifndef __cplusplus
-extern int (feof)(FILE * /*stream*/);
+int (feof)(FILE * /*stream*/);
 #endif
    /*
     * tests the end-of-file indicator for the stream pointed to by stream.
@@ -736,13 +729,13 @@ extern int (feof)(FILE * /*stream*/);
     */
 #define ferror(stream) ((stream)->__flag & _IOERR)
 #ifndef __cplusplus
-extern int (ferror)(FILE * /*stream*/);
+int (ferror)(FILE * /*stream*/);
 #endif
    /*
     * tests the error indicator for the stream pointed to by stream.
     * Returns: nonzero iff the error indicator is set for stream.
     */
-extern void perror(const char * /*s*/);
+void perror(const char * /*s*/);
    /*
     * maps the error number  in the integer expression errno to an error
     * message. It writes a sequence of characters to the standard error stream
diff --git a/clib/h/stdlib b/clib/h/stdlib
index 9d79483..2f96be2 100644
--- a/clib/h/stdlib
+++ b/clib/h/stdlib
@@ -18,7 +18,7 @@
 /* stdlib.h: ISO 'C' (9899:1999) library header, section 7.20 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd., 1990, 1992 */
-/* version 2.01 */
+/* version 2.03 */
 
 /*
  * stdlib.h declares four types, several general purpose functions,
@@ -91,19 +91,19 @@ typedef struct lldiv_t { long long int quot, rem; } lldiv_t;
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern double atof(const char * /*nptr*/);
+double atof(const char * /*nptr*/);
    /*
     * converts the initial part of the string pointed to by nptr to double
     * representation.
     * Returns: the converted value.
     */
-extern int atoi(const char * /*nptr*/);
+int atoi(const char * /*nptr*/);
    /*
     * converts the initial part of the string pointed to by nptr to int
     * representation.
     * Returns: the converted value.
     */
-extern long int atol(const char * /*nptr*/);
+long int atol(const char * /*nptr*/);
    /*
     * converts the initial part of the string pointed to by nptr to long int
     * representation.
@@ -111,7 +111,7 @@ extern long int atol(const char * /*nptr*/);
     */
 #ifdef __STDC_VERSION__
 #if __STDC_VERSION__ >= 199901
-extern long long int atoll(const char * /*nptr*/);
+long long int atoll(const char * /*nptr*/);
    /*
     * converts the initial part of the string pointed to by nptr to long long
     * int representation.
@@ -120,7 +120,7 @@ extern long long int atoll(const char * /*nptr*/);
 #endif
 #endif
 
-extern double strtod(const char * /*nptr*/, char ** /*endptr*/);
+double strtod(const char * /*nptr*/, char ** /*endptr*/);
    /*
     * converts the initial part of the string pointed to by nptr to double
     * representation. First it decomposes the input string into three parts:
@@ -140,7 +140,7 @@ extern double strtod(const char * /*nptr*/, char ** /*endptr*/);
     *          underflow, zero is returned and the value of the macro ERANGE is
     *          stored in errno.
     */
-extern long int strtol(const char * /*nptr*/, char **/*endptr*/, int /*base*/);
+long int strtol(const char * /*nptr*/, char **/*endptr*/, int /*base*/);
    /*
     * converts the initial part of the string pointed to by nptr to long int
     * representation. First it decomposes the input string into three parts:
@@ -169,8 +169,8 @@ extern long int strtol(const char * /*nptr*/, char **/*endptr*/, int /*base*/);
     *          (according to the sign of the value), and the value of the
     *          macro ERANGE is stored in errno.
     */
-extern unsigned long int strtoul(const char * /*nptr*/,
-                                       char ** /*endptr*/, int /*base*/);
+unsigned long int strtoul(const char * /*nptr*/,
+                                char ** /*endptr*/, int /*base*/);
    /*
     * converts the initial part of the string pointed to by nptr to unsigned
     * long int representation. First it decomposes the input string into three
@@ -200,8 +200,8 @@ extern unsigned long int strtoul(const char * /*nptr*/,
     */
 #ifdef __STDC_VERSION__
 #if __STDC_VERSION__ >= 199901
-extern long long int strtoll(const char * restrict /*nptr*/,
-                                   char ** restrict /*endptr*/, int /*base*/);
+long long int strtoll(const char * restrict /*nptr*/,
+                            char ** restrict /*endptr*/, int /*base*/);
    /*
     * converts the initial part of the string pointed to by nptr to long long
     * int representation. First it decomposes the input string into three parts:
@@ -230,9 +230,9 @@ extern long long int strtoll(const char * restrict /*nptr*/,
     *          (according to the sign of the value), and the value of the
     *          macro ERANGE is stored in errno.
     */
-extern unsigned long long int strtoull(const char * restrict /*nptr*/,
-                                             char ** restrict /*endptr*/,
-                                             int /*base*/);
+unsigned long long int strtoull(const char * restrict /*nptr*/,
+                                      char ** restrict /*endptr*/,
+                                      int /*base*/);
    /*
     * converts the initial part of the string pointed to by nptr to unsigned
     * long long int representation. First it decomposes the input string into
@@ -263,7 +263,7 @@ extern unsigned long long int strtoull(const char * restrict /*nptr*/,
 #endif
 #endif
 
-extern int rand(void);
+int rand(void);
    /*
     * Computes a sequence of pseudo-random integers in the range 0 to RAND_MAX.
     * Uses an additive generator (Mitchell & Moore) of the form:
@@ -273,7 +273,7 @@ extern int rand(void);
     * conjectured to be good. Empirical testing since 1958 has shown no flaws.
     * Returns: a pseudo-random integer.
     */
-extern void srand(unsigned int /*seed*/);
+void srand(unsigned int /*seed*/);
    /*
     * uses its argument as a seed for a new sequence of pseudo-random numbers
     * to be returned by subsequent calls to rand. If srand is then called with
@@ -282,7 +282,7 @@ extern void srand(unsigned int /*seed*/);
     * sequence is generated as when srand is first called with a seed value
     * of 1.
     */
-extern int _ANSI_rand(void);
+int _ANSI_rand(void);
    /*
     * The ANSI-defined 16-bit random number generator which computes
     * a sequence of pseudo-random integers in the range 0 to _ANSI_RAND_MAX.
@@ -290,7 +290,7 @@ extern int _ANSI_rand(void);
     * *** NOT AVAILABLE IN THE SHARED C LIBRARY ***
     * Returns: a pseudo-random integer.
     */
-extern void _ANSI_srand(unsigned int /*seed*/);
+void _ANSI_srand(unsigned int /*seed*/);
    /*
     * Uses its argument as a seed for a new sequence of pseudo-random numbers
     * to be returned by subsequent calls to _ANSI_rand. If _ANSI_srand is then
@@ -307,19 +307,19 @@ extern void _ANSI_srand(unsigned int /*seed*/);
 
 typedef char *malloc_t;
 
-extern char *calloc(size_t /*nmemb*/, size_t /*size*/);
-extern void free(void * /*ptr*/);
-extern char *malloc(size_t /*size*/);
-extern char *realloc(void * /*ptr*/, size_t /*size*/);
+char *calloc(size_t /*nmemb*/, size_t /*size*/);
+void free(void * /*ptr*/);
+char *malloc(size_t /*size*/);
+char *realloc(void * /*ptr*/, size_t /*size*/);
 #endif
 #else
-extern void *calloc(size_t /*nmemb*/, size_t /*size*/);
+void *calloc(size_t /*nmemb*/, size_t /*size*/);
    /*
     * allocates space for an array of nmemb objects, each of whose size is
     * 'size'. The space is initialised to all bits zero.
     * Returns: either a null pointer or a pointer to the allocated space.
     */
-extern void free(void * /*ptr*/);
+void free(void * /*ptr*/);
    /*
     * causes the space pointed to by ptr to be deallocated (i.e., made
     * available for further allocation). If ptr is a null pointer, no action
@@ -327,13 +327,13 @@ extern void free(void * /*ptr*/);
     * calloc, malloc or realloc or if the space has been deallocated by a call
     * to free or realloc, the behaviour is undefined.
     */
-extern void *malloc(size_t /*size*/);
+void *malloc(size_t /*size*/);
    /*
     * allocates space for an object whose size is specified by 'size' and whose
     * value is indeterminate.
     * Returns: either a null pointer or a pointer to the allocated space.
     */
-extern void *realloc(void * /*ptr*/, size_t /*size*/);
+void *realloc(void * /*ptr*/, size_t /*size*/);
    /*
     * changes the size of the object pointed to by ptr to the size specified by
     * size. The contents of the object shall be unchanged up to the lesser of
@@ -351,17 +351,17 @@ extern void *realloc(void * /*ptr*/, size_t /*size*/);
     */
 #endif
 
-extern void abort(void);
+void abort(void);
    /*
     * causes abnormal program termination to occur, unless the signal SIGABRT
     * is being caught and the signal handler does not return. Whether open
     * output streams are flushed or open streams are closed or temporary files
-    * removed is implementation-defined (under Arthur/Brazil all these occur).
+    * removed is implementation-defined (under RISC OS all these occur).
     * An implementation-defined form of the status 'unsuccessful termination'
-    * (1 under Arthur/Brazil) is returned to the host environment by means
-    * of a call to raise(SIGABRT).
+    * (1 under RISC OS) is returned to the host environment by means of a call
+    * to raise(SIGABRT).
     */
-extern int atexit(void (* /*func*/)(void));
+int atexit(void (* /*func*/)(void));
    /*
     * registers the function pointed to by func, to be called without its
     * arguments at normal program termination. It is possible to register at
@@ -369,7 +369,7 @@ extern int atexit(void (* /*func*/)(void));
     * Returns: zero if the registration succeeds, nonzero if it fails.
     */
 
-extern void exit(int status);
+void exit(int /*status*/);
    /*
     * causes normal program termination to occur. If more than one call to the
     * exit function is executed by a program, the behaviour is undefined.
@@ -379,14 +379,26 @@ extern void exit(int status);
     * and all files created by the tmpfile function are removed.
     * Finally, control is returned to the host environment. If the value of
     * status is zero or EXIT_SUCCESS, an implementation-defined form of the
-    * status 'successful termination' (0 under Arthur/Brazil) is returned. If
-    * the value of status is EXIT_FAILURE, an implementation-defined form of
-    * the status 'unsuccessful termination' (1 under Arthur/Brazil) is
-    * returned. Otherwise the status returned is implementation-defined (the
-    * value of status is returned under Arthur/Brazil).
+    * status 'successful termination' (0 under RISC OS) is returned. If the
+    * value of status is EXIT_FAILURE, an implementation-defined form of the
+    * status 'unsuccessful termination' (1 under RISC OS) is returned.
+    * Otherwise the status returned is implementation-defined (the value of
+    * status is returned under RISC OS).
     */
 
-extern char *getenv(const char * /*name*/);
+void _Exit(int /*status*/);
+   /*
+    * causes normal program termination to occur and control to be returned to
+    * the host environment. No functions registered by the atexit function or
+    * signal handlers registered by the signal function are called.
+    * The status returned to the host environment is determined in the same
+    * way as for the exit function.
+    * Whether open streams with unwritten buffered data are flushed, open
+    * streams are closed or temporary files are removed is implementation-
+    * defined (under RISC OS all these occur).
+    */
+
+char *getenv(const char * /*name*/);
    /*
     * searches the environment list, provided by the host environment, for a
     * string that matches the string pointed to by name. The set of environment
@@ -398,14 +410,14 @@ extern char *getenv(const char * /*name*/);
     *          If the specified name cannot be found, a null pointer is
     *          returned.
     */
-extern int  system(const char * /*string*/);
+int  system(const char * /*string*/);
    /*
     * passes the string pointed to by string to the host environment to be
     * executed by a command processor in an implementation-defined manner.
     * A null pointer may be used for string, to inquire whether a command
     * processor exists.
     *
-    * Under Arthur/Brazil care must be taken when executing a command, that the
+    * Under RISC OS care must be taken when executing a command, that the
     * command does not overwrite the calling program. The string 'chain:' or
     * 'call:' may immediately precede the actual command. The effect of 'call:'
     * is the same as if 'call:' were not present, which is to attempt to return
@@ -415,12 +427,12 @@ extern int  system(const char * /*string*/);
     * Returns: If the argument is a null pointer, the system function returns
     *          non-zero only if a command processor is available. If the
     *          argument is not a null pointer, the system function returns an
-    *          implementation-defined value (under Arthur/Brazil 0 is returned
+    *          implementation-defined value (under RISC OS 0 is returned
     *          for success, -2 for failure to invoke the command and any other
     *          value is the return code from the executed command).
     */
 
-extern void *bsearch(const void * /*key*/, const void * /*base*/,
+void *bsearch(const void * /*key*/, const void * /*base*/,
               size_t /*nmemb*/, size_t /*size*/,
               int (* /*compar*/)(const void *, const void *));
    /*
@@ -437,7 +449,7 @@ extern void *bsearch(const void * /*key*/, const void * /*base*/,
     *          if no match is found. If two members compare as equal, which
     *          member is matched is unspecified.
     */
-extern void qsort(void * /*base*/, size_t /*nmemb*/, size_t /*size*/,
+void qsort(void * /*base*/, size_t /*nmemb*/, size_t /*size*/,
            int (* /*compar*/)(const void *, const void *));
    /*
     * sorts an array of nmemb objects, the initial member of which is pointed
@@ -451,25 +463,25 @@ extern void qsort(void * /*base*/, size_t /*nmemb*/, size_t /*size*/,
     * sorted array is unspecified.
     */
 
-extern int abs(int /*j*/);
+int abs(int /*j*/);
    /*
     * computes the absolute value of an integer j. If the result cannot be
     * represented, the behaviour is undefined.
     * Returns: the absolute value.
     */
-extern div_t div(int /*numer*/, int /*denom*/);
+div_t div(int /*numer*/, int /*denom*/);
    /*
     * computes numer / denom and numer % denom in a single operation.
     * Returns: a structure of type div_t, comprising both the quotient and the
     *          remainder.
     */
-extern long int labs(long int /*j*/);
+long int labs(long int /*j*/);
    /*
     * computes the absolute value of an integer j. If the result cannot be
     * represented, the behaviour is undefined.
     * Returns: the absolute value.
     */
-extern ldiv_t ldiv(long int /*numer*/, long int /*denom*/);
+ldiv_t ldiv(long int /*numer*/, long int /*denom*/);
    /*
     * computes numer / denom and numer % denom in a single operation.
     * Returns: a structure of type ldiv_t, comprising both the quotient and the
@@ -477,13 +489,13 @@ extern ldiv_t ldiv(long int /*numer*/, long int /*denom*/);
     */
 #ifdef __STDC_VERSION__
 #if __STDC_VERSION__ >= 199901
-extern long long int llabs(long long int /*j*/);
+long long int llabs(long long int /*j*/);
    /*
     * computes the absolute value of an integer j. If the result cannot be
     * represented, the behaviour is undefined.
     * Returns: the absolute value.
     */
-extern lldiv_t lldiv(long long int /*numer*/, long long int /*denom*/);
+lldiv_t lldiv(long long int /*numer*/, long long int /*denom*/);
    /*
     * computes numer / denom and numer % denom in a single operation.
     * Returns: a structure of type lldiv_t, comprising both the quotient and the
@@ -492,6 +504,12 @@ extern lldiv_t lldiv(long long int /*numer*/, long long int /*denom*/);
 #endif
 #endif
 
+#ifndef __cplusplus
+/* the sizeof expression performs the necessary type-checking */
+#define abs(j)  ((void) sizeof abs(j), __abs (int) (j))
+#define labs(j) ((void) sizeof labs(j), __abs (long int) (j))
+#endif
+
 /*
  * Multibyte Character Functions.
  * The behaviour of the multibyte character functions is affected by the
@@ -504,7 +522,7 @@ extern lldiv_t lldiv(long long int /*numer*/, long long int /*denom*/);
  * otherwise. After the LC_CTYPE category is changed, the shift state of these
  * functions is indeterminate.
  */
-extern int mblen(const char * /*s*/, size_t /*n*/);
+int mblen(const char * /*s*/, size_t /*n*/);
    /*
     * If s is not a null pointer, the mblen function determines the number of
     * bytes compromising the multibyte character pointed to by s. Except that
@@ -519,7 +537,7 @@ extern int mblen(const char * /*s*/, size_t /*n*/);
     *          valid multibyte character), or returns -1 (they do not form a
     *          valid multibyte character).
     */
-extern int mbtowc(wchar_t * /*pwc*/, const char * /*s*/, size_t /*n*/);
+int mbtowc(wchar_t * /*pwc*/, const char * /*s*/, size_t /*n*/);
    /*
     * If s is not a null pointer, the mbtowc function determines the number of
     * bytes that compromise the multibyte character pointed to by s. It then
@@ -537,7 +555,7 @@ extern int mbtowc(wchar_t * /*pwc*/, const char * /*s*/, size_t /*n*/);
     *          fewer bytes form a valid multibyte character), or returns -1
     *          (they do not form a valid multibyte character).
     */
-extern int wctomb(char * /*s*/, wchar_t /*wchar*/);
+int wctomb(char * /*s*/, wchar_t /*wchar*/);
    /*
     * determines the number of bytes need to represent the multibyte character
     * corresponding to the code whose value is wchar (including any change in
@@ -559,7 +577,7 @@ extern int wctomb(char * /*s*/, wchar_t /*wchar*/);
  * The behaviour of the multibyte string functions is affected by the LC_CTYPE
  * category of the current locale.
  */
-extern size_t mbstowcs(wchar_t * /*pwcs*/, const char * /*s*/, size_t /*n*/);
+size_t mbstowcs(wchar_t * /*pwcs*/, const char * /*s*/, size_t /*n*/);
    /*
     * converts a sequence of multibyte character that begins in the initial
     * shift state from the array pointed to by s into a sequence of
@@ -576,7 +594,7 @@ extern size_t mbstowcs(wchar_t * /*pwcs*/, const char * /*s*/, size_t /*n*/);
     *          returns the number of array elements modified, not including
     *          a terminating zero code, if any.
     */
-extern size_t wcstombs(char * /*s*/, const wchar_t * /*pwcs*/, size_t /*n*/);
+size_t wcstombs(char * /*s*/, const wchar_t * /*pwcs*/, size_t /*n*/);
    /*
     * converts a sequence of codes that correspond to multibyte characters
     * from the array pointed to by pwcs into a sequence of multibyte
diff --git a/clib/h/string b/clib/h/string
index 0826b38..27a2567 100644
--- a/clib/h/string
+++ b/clib/h/string
@@ -15,7 +15,7 @@
 #pragma force_top_level
 #pragma include_only_once
 
-/* string.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.11 */
+/* string.h: ISO 'C' (9899:1999) library header, section 7.21 */
 /* Copyright (C) Codemist Ltd. */
 /* Copyright (C) Acorn Computers Ltd. 1991, 1992 */
 /* version 2.00 */
@@ -44,14 +44,14 @@ typedef unsigned int size_t;   /* from <stddef.h> */
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern char *strcpy(char * /*s1*/, const char * /*s2*/);
+char *strcpy(char * /*s1*/, const char * /*s2*/);
    /*
     * copies the string pointed to by s2 (including the terminating nul
     * character) into the array pointed to by s1. If copying takes place
     * between objects that overlap, the behaviour is undefined.
     * Returns: the value of s1.
     */
-extern char *strncpy(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
+char *strncpy(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
    /*
     * copies not more than n characters (characters that follow a null
     * character are not copied) from the array pointed to by s2 into the array
@@ -60,14 +60,14 @@ extern char *strncpy(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
     * Returns: the value of s1.
     */
 
-extern char *strcat(char * /*s1*/, const char * /*s2*/);
+char *strcat(char * /*s1*/, const char * /*s2*/);
    /*
     * appends a copy of the string pointed to by s2 (including the terminating
     * null character) to the end of the string pointed to by s1. The initial
     * character of s2 overwrites the null character at the end of s1.
     * Returns: the value of s1.
     */
-extern char *strncat(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
+char *strncat(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
    /*
     * appends not more than n characters (a null character and characters that
     * follow it are not appended) from the array pointed to by s2 to the end of
@@ -84,7 +84,7 @@ extern char *strncat(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
  * objects being compared.
  */
 
-extern int memcmp(const void * /*s1*/, const void * /*s2*/, size_t /*n*/);
+int memcmp(const void * /*s1*/, const void * /*s2*/, size_t /*n*/);
    /*
     * compares the first n characters of the object pointed to by s1 to the
     * first n characters of the object pointed to by s2.
@@ -92,14 +92,14 @@ extern int memcmp(const void * /*s1*/, const void * /*s2*/, size_t /*n*/);
     *          as the object pointed to by s1 is greater than, equal to, or
     *          less than the object pointed to by s2.
     */
-extern int strcmp(const char * /*s1*/, const char * /*s2*/);
+int strcmp(const char * /*s1*/, const char * /*s2*/);
    /*
     * compares the string pointed to by s1 to the string pointed to by s2.
     * Returns: an integer greater than, equal to, or less than zero, according
     *          as the string pointed to by s1 is greater than, equal to, or
     *          less than the string pointed to by s2.
     */
-extern int strncmp(const char * /*s1*/, const char * /*s2*/, size_t /*n*/);
+int strncmp(const char * /*s1*/, const char * /*s2*/, size_t /*n*/);
    /*
     * compares not more than n characters (characters that follow a null
     * character are not compared) from the array pointed to by s1 to the array
@@ -108,7 +108,7 @@ extern int strncmp(const char * /*s1*/, const char * /*s2*/, size_t /*n*/);
     *          as the string pointed to by s1 is greater than, equal to, or
     *          less than the string pointed to by s2.
     */
-extern int strcoll(const char * /*s1*/, const char * /*s2*/);
+int strcoll(const char * /*s1*/, const char * /*s2*/);
    /*
     * compares the string pointed to by s1 to the string pointed to by s2, both
     * interpreted as appropriate to the LC_COLLATE category of the current
@@ -119,7 +119,7 @@ extern int strcoll(const char * /*s1*/, const char * /*s2*/);
     *          as appropriate to the current locale.
     */
 
-extern size_t strxfrm(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
+size_t strxfrm(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
    /*
     * transforms the string pointed to by s2 and places the resulting string
     * into the array pointed to by s1. The transformation function is such that
@@ -136,28 +136,28 @@ extern size_t strxfrm(char * /*s1*/, const char * /*s2*/, size_t /*n*/);
     *          indeterminate.
     */
 
-extern char *strchr(const char * /*s*/, int /*c*/);
+char *strchr(const char * /*s*/, int /*c*/);
    /*
     * locates the first occurence of c (converted to an char) in the string
     * pointed to by s (including the terminating null character).
     * Returns: a pointer to the located character, or a null pointer if the
     *          character does not occur in the string.
     */
-extern size_t strcspn(const char * /*s1*/, const char * /*s2*/);
+size_t strcspn(const char * /*s1*/, const char * /*s2*/);
    /*
     * computes the length of the initial segment of the string pointed to by s1
     * which consists entirely of characters not from the string pointed to by
     * s2. The terminating null character is not considered part of s2.
     * Returns: the length of the segment.
     */
-extern char *strpbrk(const char * /*s1*/, const char * /*s2*/);
+char *strpbrk(const char * /*s1*/, const char * /*s2*/);
    /*
     * locates the first occurence in the string pointed to by s1 of any
     * character from the string pointed to by s2.
     * Returns: returns a pointer to the character, or a null pointer if no
     *          character form s2 occurs in s1.
     */
-extern char *strrchr(const char * /*s*/, int /*c*/);
+char *strrchr(const char * /*s*/, int /*c*/);
    /*
     * locates the last occurence of c (converted to a char) in the string
     * pointed to by s. The terminating null character is considered part of
@@ -165,13 +165,13 @@ extern char *strrchr(const char * /*s*/, int /*c*/);
     * Returns: returns a pointer to the character, or a null pointer if c does
     *          not occur in the string.
     */
-extern size_t strspn(const char * /*s1*/, const char * /*s2*/);
+size_t strspn(const char * /*s1*/, const char * /*s2*/);
    /*
     * computes the length of the initial segment of the string pointed to by s1
     * which consists entirely of characters from the string pointed to by S2
     * Returns: the length of the segment.
     */
-extern char *strstr(const char * /*s1*/, const char * /*s2*/);
+char *strstr(const char * /*s1*/, const char * /*s2*/);
    /*
     * locates the first occurence in the string pointed to by s1 of the
     * sequence of characters (excluding the terminating null character) in the
@@ -179,7 +179,7 @@ extern char *strstr(const char * /*s1*/, const char * /*s2*/);
     * Returns: a pointer to the located string, or a null pointer if the string
     *          is not found.
     */
-extern char *strtok(char * /*s1*/, const char * /*s2*/);
+char *strtok(char * /*s1*/, const char * /*s2*/);
    /*
     * A sequence of calls to the strtok function breaks the string pointed to
     * by s1 into a sequence of tokens, each of which is delimited by a
@@ -206,14 +206,14 @@ extern char *strtok(char * /*s1*/, const char * /*s2*/);
     *          there is no token.
     */
 
-extern void *memcpy(void * /*s1*/, const void * /*s2*/, size_t /*n*/);
+void *memcpy(void * /*s1*/, const void * /*s2*/, size_t /*n*/);
    /*
     * copies n characters from the object pointed to by s2 into the object
     * pointed to by s1. If copying takes place between objects that overlap,
     * the behaviour is undefined.
     * Returns: the value of s1.
     */
-extern void *memmove(void * /*s1*/, const void * /*s2*/, size_t /*n*/);
+void *memmove(void * /*s1*/, const void * /*s2*/, size_t /*n*/);
    /*
     * copies n characters from the object pointed to by s2 into the object
     * pointed to by s1. Copying takes place as if the n characters from the
@@ -223,7 +223,7 @@ extern void *memmove(void * /*s1*/, const void * /*s2*/, size_t /*n*/);
     * object pointed to by s1.
     * Returns: the value of s1.
     */
-extern void *memchr(const void * /*s*/, int /*c*/, size_t /*n*/);
+void *memchr(const void * /*s*/, int /*c*/, size_t /*n*/);
    /*
     * locates the first occurence of c (converted to an unsigned char) in the
     * initial n characters (each interpreted as unsigned char) of the object
@@ -231,14 +231,14 @@ extern void *memchr(const void * /*s*/, int /*c*/, size_t /*n*/);
     * Returns: a pointer to the located character, or a null pointer if the
     *          character does not occur in the object.
     */
-extern void *memset(void * /*s*/, int /*c*/, size_t /*n*/);
+void *memset(void * /*s*/, int /*c*/, size_t /*n*/);
    /*
     * copies the value of c (converted to an unsigned char) into each of the
     * first n charactes of the object pointed to by s.
     * Returns: the value of s.
     */
 
-extern char *strerror(int /*errnum*/);
+char *strerror(int /*errnum*/);
    /*
     * maps the error number in errnum to an error message string.
     * Returns: a pointer to the string, the contents of which are
@@ -253,7 +253,7 @@ extern char *strerror(int /*errnum*/);
     *          modified by the program, but may be overwritten by a subsequent
     *          call to the strerror function.
     */
-extern size_t strlen(const char * /*s*/);
+size_t strlen(const char * /*s*/);
    /*
     * computes the length of the string pointed to by s.
     * Returns: the number of characters that precede the terminating null
diff --git a/clib/h/tgmath b/clib/h/tgmath
new file mode 100644
index 0000000..f0ae590
--- /dev/null
+++ b/clib/h/tgmath
@@ -0,0 +1,175 @@
+/* Copyright 2003 Tematic Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma force_top_level
+#pragma include_only_once
+
+/* tgmath.h: ISO 'C' (9899:1999) library header, section 7.22 */
+/* Copyright (C) Acorn Computers Ltd. 2002 */
+/* version 1.00 */
+
+/*
+ * tgmath.h includes the headers <math.h> and <complex.h> and defines
+ * several type-generic macros.
+ */
+#ifndef __tgmath_h
+#define __tgmath_h
+
+#include <math.h>
+
+#define _TG(o, ...)      (___select(0, o##f, o, o##l, __VA_ARGS__))(__VA_ARGS__)
+#define _TG1(o, x,...)   (___select(0, o##f, o, o##l, x))(x,__VA_ARGS__)
+#define _TG2(o, x,y,...) (___select(0, o##f, o, o##l, x,y))(x,y,__VA_ARGS__)
+
+#define _TGx(f,d,l, ...) (___select(0, f, d, l, __VA_ARGS__))(__VA_ARGS__)
+
+/* Type-generic macros for functions with both real and complex forms */
+#undef acos
+#undef asin
+#undef atan
+#undef acosh
+#undef asinh
+#undef atanh
+#undef cos
+#undef sin
+#undef tan
+#undef cosh
+#undef sinh
+#undef tanh
+#undef exp
+#undef log
+#undef pow
+#undef sqrt
+#undef fabs
+
+#define acos(x)  _TG(acos, x)
+#define asin(x)  _TG(asin, x)
+#define atan(x)  _TG(atan, x)
+#define acosh(x) _TG(acosh, x)
+#define asinh(x) _TG(asinh, x)
+#define atanh(x) _TG(atanh, x)
+#define cos(x)   _TG(cos, x)
+#define sin(x)   _TG(sin, x)
+#define tan(x)   _TG(tan, x)
+#define cosh(x)  _TG(cosh, x)
+#define sinh(x)  _TG(sinh, x)
+#define tanh(x)  _TG(tanh, x)
+#define exp(x)   _TG(exp, x)
+#define log(x)   _TG(log, x)
+#define pow(x)   _TG(pow, x)
+#define sqrt(x)  _TG(sqrt, x)
+#define fabs(x)  _TG(fabs, x)
+
+/* Type-generic macros for real-only functions */
+#undef atan2
+#undef cbrt
+#undef ceil
+#undef copysign
+#undef erf
+#undef erfc
+#undef expm1
+#undef fdim
+#undef floor
+#undef fma
+#undef fmax
+#undef fmin
+#undef fmod
+#undef frexp
+#undef hypot
+#undef ilogb
+#undef ldexp
+#undef lgamma
+#undef llrint
+#undef llround
+#undef log10
+#undef log1p
+#undef log2
+#undef logb
+#undef lrint
+#undef lround
+#undef nearbyint
+#undef nextafter
+#undef nexttoward
+#undef remainder
+#undef remquo
+#undef rint
+#undef round
+#undef scalbn
+#undef scalbln
+#undef tgamma
+#undef trunc
+
+#define atan2(y,x)      _TG(atan2, y,x)
+#define cbrt(x)         _TG(cbrt, x)
+#define ceil(x)         _TG(ceil, x)
+#define copysign(x,y)   _TG(copysign, x,y)
+#define erf(x)          _TG(erf, x)
+#define erfc(x)         _TG(erfc, x)
+#define expm1(x)        _TG(expm1, x)
+#define fdim(x,y)       _TG(fdim, x,y)
+#define floor(x)        _TG(floor, x)
+#define fma(x,y,z)      _TG(fma, x,y,z)
+#define fmax(x,y)       _TG(fmax, x,y)
+#define fmin(x,y)       _TG(fmin, x,y)
+#define fmod(x,y)       _TG(fmod, x,y)
+#define frexp(v,e)      _TG1(frexp, v,e)
+#define hypot(x,y)      _TG(hypot, x,y)
+#define ilogb(x)        _TG(ilogb, x)
+#define ldexp(x,e)      _TG1(ldexp, x,e)
+#define lgamma(x)       _TG(lgamma, x)
+#define llrint(x)       _TG(llrint, x)
+#define llround(x)      _TG(llround, x)
+#define log10(x)        _TG(log10, x)
+#define log1p(x)        _TG(log1p, x)
+#define log2(x)         _TG(log2, x)
+#define logb(x)         _TG(logb, x)
+#define lrint(x)        _TG(lrint, x)
+#define lround(x)       _TG(lround, x)
+#define nearbyint(x)    _TG(nearbyint, x)
+#define nextafter(x,y)  _TG(nextafter, x,y)
+#define nexttoward(x,y) _TG1(nexttoward, x,y)
+#define remainder(x,y)  _TG(remainder, x,y)
+#define remquo(x,y,q)   _TG2(remquo, x,y,q)
+#define rint(x)         _TG(rint, x)
+#define round(x)        _TG(round, x)
+#define scalbn(x,n)     _TG1(scalbn, x,n)
+#define scalbln(x,n)    _TG1(scalbln, x,n)
+#define tgamma(x)       _TG(tgamma, x)
+#define trunc(x)        _TG(trunc, x)
+
+/* Ensure inlining still happens, unless requested otherwise */
+#ifndef __TGMATH_NO_INLINING
+#undef atan
+#undef cos
+#undef sin
+#undef fabs
+#undef floor
+#undef ceil
+#undef trunc
+#undef rint
+#undef lrint
+#define atan(x)  _TGx(__r_atan, __d_atan, atanl, x)
+#define cos(x)   _TGx(__r_cos, __d_cos, cosl, x)
+#define sin(x)   _TGx(__r_sin, __d_sin, sinl, x)
+#define fabs(x)  (___select(0, __abs (x), __abs (double) (x), __abs (x), x))
+#define floor(x) _TGx(__r_floor, __d_floor, floorl, x)
+#define ceil(x)  _TGx(__r_ceil, __d_ceil, ceill, x)
+#define trunc(x) _TGx(__r_trunc, __d_trunc, truncl, x)
+#define rint(x)  _TGx(__r_rint, __d_rint, rintl, x)
+#define lrint(x) _TGx(__r_lrint, __d_lrint, lrintl, x)
+#endif
+
+#endif
+
+/* end of tgmath.h */
diff --git a/clib/h/time b/clib/h/time
index ee770e0..4dbbcd8 100644
--- a/clib/h/time
+++ b/clib/h/time
@@ -74,7 +74,7 @@ struct tm {
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern clock_t clock(void);
+clock_t clock(void);
    /* determines the processor time used.
     * Returns: the implementation's best approximation to the processor time
     *          used by the program since program invocation. The time in
@@ -82,12 +82,12 @@ extern clock_t clock(void);
     *          CLK_TCK. The value (clock_t)-1 is returned if the processor time
     *          used is not available.
     */
-extern double difftime(time_t /*time1*/, time_t /*time0*/);
+double difftime(time_t /*time1*/, time_t /*time0*/);
    /*
     * computes the difference between two calendar times: time1 - time0.
     * Returns: the difference expressed in seconds as a double.
     */
-extern time_t mktime(struct tm * /*timeptr*/);
+time_t mktime(struct tm * /*timeptr*/);
    /*
     * converts the broken-down time, expressed as local time, in the structure
     * pointed to by timeptr into a calendar time value with the same encoding
@@ -103,7 +103,7 @@ extern time_t mktime(struct tm * /*timeptr*/);
     *          If the calendar time cannot be represented, the function returns
     *          the value (time_t)-1.
     */
-extern time_t time(time_t * /*timer*/);
+time_t time(time_t * /*timer*/);
    /*
     * determines the current calendar time. The encoding of the value is
     * unspecified.
@@ -113,33 +113,33 @@ extern time_t time(time_t * /*timer*/);
     *          is also assigned to the object it points to.
     */
 
-extern char *asctime(const struct tm * /*timeptr*/);
+char *asctime(const struct tm * /*timeptr*/);
    /*
     * converts the broken-down time in the structure pointed to by timeptr into
     * a string in the form Sun Sep 16 01:03:52 1973\n\0.
     * Returns: a pointer to the string containing the date and time.
     */
-extern char *ctime(const time_t * /*timer*/);
+char *ctime(const time_t * /*timer*/);
    /*
     * converts the calendar time pointed to by timer to local time in the form
     * of a string. It is equivalent to asctime(localtime(timer));
     * Returns: the pointer returned by the asctime function with that
     *          broken-down time as argument.
     */
-extern struct tm *gmtime(const time_t * /*timer*/);
+struct tm *gmtime(const time_t * /*timer*/);
    /*
     * converts the calendar time pointed to by timer into a broken-down time,
     * expressed as Greenwich Mean Time (GMT).
     * Returns: a pointer to that object or a null pointer if GMT not available.
     */
-extern struct tm *localtime(const time_t * /*timer*/);
+struct tm *localtime(const time_t * /*timer*/);
    /*
     * converts the calendar time pointed to by timer into a broken-down time,
     * expressed a local time.
     * Returns: a pointer to that object.
     */
-extern size_t strftime(char * /*s*/, size_t /*maxsize*/,
-                       const char * /*format*/, const struct tm * /*timeptr*/);
+size_t strftime(char * /*s*/, size_t /*maxsize*/,
+                const char * /*format*/, const struct tm * /*timeptr*/);
    /*
     * places characters into the array pointed to by s as controlled by the
     * string pointed to by format. The format string consists of zero or more
diff --git a/clib/s/cl_body b/clib/s/cl_body
index 24dfdb0..00bc5ec 100644
--- a/clib/s/cl_body
+++ b/clib/s/cl_body
@@ -57,6 +57,12 @@ $Label  MOV     r1, #0
         WFS     r1
         MEND
 
+        MACRO
+$Label  CheckFPInterrupts $nocheck
+        ; Sets r1 to the current fp flags.
+        RFS     r1
+        MEND
+
         MACRO
 $Label  ReEnableFPInterrupts $nocheck
         ; Reinstates the exception mask state which prevailed before the call
@@ -152,6 +158,8 @@ $Label
         EXPORT  copysignf
         EXPORT  nextafter
         EXPORT  nextafterf
+        EXPORT  nexttoward
+        EXPORT  nexttowardf
 
         EXPORT  |__rt_stkovf_split_small|
         EXPORT  |__rt_stkovf_split_big|
@@ -175,6 +183,8 @@ $Label
         EXPORT  fmax
         EXPORT  fmaxf
 
+        EXPORT  fmaf
+
         EXPORT  nearbyint
         EXPORT  nearbyintf
         EXPORT  round
@@ -184,14 +194,31 @@ $Label
         EXPORT  remainder
         EXPORT  remainderf
         EXPORT  exp
+        EXPORT  expf
+        EXPORT  expm1
+        EXPORT  expm1f
+        EXPORT  exp2
+        EXPORT  exp2f
         EXPORT  log10
+        EXPORT  log10f
         EXPORT  log
+        EXPORT  logf
+        EXPORT  log1p
+        EXPORT  log1pf
+        EXPORT  log2
+        EXPORT  log2f
         EXPORT  sqrt
         EXPORT  sqrtf
+        EXPORT  cbrt
+        EXPORT  cbrtf
         EXPORT  tan
+        EXPORT  tanf
         EXPORT  asin
+        EXPORT  asinf
         EXPORT  acos
+        EXPORT  acosf
         EXPORT  pow
+        EXPORT  powf
         EXPORT  hypot
         EXPORT  hypotf
 
@@ -852,6 +879,7 @@ chunks_deallocated
 |_osbyte|
         B       |_kernel_osbyte|
 
+        LTORG
 
 ; double _ldfp(void *x) converts packed decimal at x to a double
 
@@ -951,6 +979,8 @@ copysignf
 
 ; Back to normal calling conventions
 
+nexttoward
+        NOP
 nextafter
         [ :LNOT:FloatingPointArgsInRegs
         STMFD   sp!, {r0-r3}
@@ -1166,7 +1196,6 @@ fminf
         Return  ,LinkNotStacked,VC
         B       fcmpnan
 
- [ {FALSE}
 fmaf
         [ :LNOT:FloatingPointArgsInRegs
         STMFD   sp!, {r0-r3}
@@ -1180,7 +1209,6 @@ fmaf
         MUFE    f0, f0, f1              ; totally accurate result
         ADFS    f0, f0, f2
         Return  ,LinkNotStacked
- ]
 
 nearbyint
         [ :LNOT:FloatingPointArgsInRegs
@@ -1292,7 +1320,9 @@ exp
         |
         DisableFPInterrupts
         ]
+exp_common
         EXPD    f0, f0
+exp_exit
         ReEnableFPInterrupts
         TST     r1, #&0F
         Return  ,LinkNotStacked, EQ
@@ -1300,6 +1330,52 @@ exp
         BNE     underflow_error
         B       huge_error
 
+expf
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        MVFS    f0, f0
+expf_common
+        EXPS    f0, f0
+expf_exit
+        ReEnableFPInterrupts
+        TST     r1, #&0F
+        Return  ,LinkNotStacked, EQ
+        TST     r1, #8
+        BNE     underflow_error
+        B       huge_errorf
+
+; Mickey-mouse implementations, but they are still better than the user
+; doing it, because of intermediate extended precision.
+expm1
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        EXPE    f0, f0
+        SUFD    f0, f0, #1
+        B       exp_exit
+
+expm1f
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        MVFS    f0, f0
+        EXPE    f0, f0
+        SUFS    f0, f0, #1
+        B       expf_exit
+
 ldfp_overflow
         LDR     r0, [r0, #0]
         CMPS    r0, #0
@@ -1323,6 +1399,13 @@ huge_val
         DCD     &7FEFFFFF               ; put constant where it is easy to find
         DCD     &FFFFFFFF
 
+huge_negative_resultf
+        MOV     r0, #ERANGE
+        LDFS    f0, negative_huge_valf
+        B       Set_errno
+negative_huge_valf
+        DCD     &FF800000
+
 huge_errorf
         MOV     r0, #ERANGE
         LDFS    f0, huge_valf
@@ -1340,8 +1423,6 @@ negative_errorf
         MOV     r0, #EDOM
         LDFS    f0, negative_huge_valf  ; @@@@!!!!
         B       Set_errno
-negative_huge_valf
-        DCD     &FF800000               ; put constant where it is easy to find
 
 underflow_error
         MOV     r0, #ERANGE
@@ -1353,31 +1434,221 @@ log10
         STMFD   sp!, {r0, r1}
         LDFD    f0, [sp], #8
         ]
-        CMFE    f0, #0
+        CMF     f0, #0
         BEQ     huge_negative_result
         BMI     negative_error
         LOGD    f0, f0
         Return  ,LinkNotStacked
 
+log10f
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        MVFS    f0, f0
+        CMF     f0, #0
+        BEQ     huge_negative_resultf
+        BMI     negative_errorf
+        LOGGTS  f0, f0
+        Return  ,LinkNotStacked
+
 log
         [ :LNOT: FloatingPointArgsInRegs
         STMFD   sp!, {r0, r1}
         LDFD    f0, [sp], #8
         ]
-        CMFE    f0, #0
+        CMF     f0, #0
+        BEQ     huge_negative_result
+        BMI     negative_error
+        LGNGTD  f0, f0
+        Return  ,LinkNotStacked
+
+logf
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        MVFS    f0, f0
+        CMF     f0, #0
+        BEQ     huge_negative_resultf
+        BMI     negative_errorf
+        LGNGTS  f0, f0
+        Return  ,LinkNotStacked
+
+; Mickey-mouse implementations, but they are still better than the user
+; doing it, because of intermediate extended precision.
+log1p
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        CNF     f0, #1
         BEQ     huge_negative_result
         BMI     negative_error
-        LGND    f0, f0
+        ADFGTE  f0, f0, #1
+        LGNGTD  f0, f0
         Return  ,LinkNotStacked
 
+log1pf
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        MVFS    f0, f0
+        CNF     f0, #1
+        BEQ     huge_negative_result
+        BMI     negative_error
+        ADFGTE  f0, f0, #1
+        LGNGTS  f0, f0
+        Return  ,LinkNotStacked
+
+log2
+        [ FloatingPointArgsInRegs
+        STFD    f0, [sp, #-8]!
+        LDMFD   sp!, {r0, r1}
+        |
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        ; Now argument is in both {r0,r1} and f0
+        CMF     f0, #0
+        BEQ     huge_negative_result
+        BMI     negative_error
+        Return  ,LinkNotStacked,VS
+        ; Argument is strictly positive and finite
+        MOVS    r2, r0, LSR #20         ; r2 = exponent field
+        BNE     %FT30
+        ; Subnormal case - normalise
+        MOV     r2, #1
+10      ADDS    r1, r1, r1
+        ADCS    r0, r0, r0
+        SUB     r2, r2, #1
+        TST     r0, #&00100000
+        BEQ     %BT10
+30      ORRS    r3, r1, r0, LSL #12     ; EQ if exact power of 2
+        ; If exact, just convert exponent field to FP, else
+        ; compute log2(e)*log(x)
+        BEQ     log2_exact
+        LDFE    f1, log2_e
+        LGNE    f0, f0
+        MUFD    f0, f0, f1
+        Return  ,LinkNotStacked
+log2_exact
+        SUB     r2, r2, #&400
+        ADD     r2, r2, #1
+        TEQ     r2, #&400               ; EQ if infinity
+        FLTNED  f0, r2
+        Return  ,LinkNotStacked
+
+log2f
+        [ :LNOT:FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        MVFS    f0, f0
+        STFS    f0, [sp, #-4]!
+        LDR     r0, [sp], #4
+        ; Now argument is in both r0 and f0
+        CMF     f0, #0
+        BEQ     huge_negative_result
+        BMI     negative_error
+        Return  ,LinkNotStacked,VS
+        ; Argument is strictly positive and finite
+        MOVS    r2, r0, LSR #23         ; r2 = exponent field
+        MOV     r0, r0, LSL #9          ; r0 = fraction
+        BNE     %FT30
+        ; Subnormal case - normalise
+        MOV     r2, #1
+10      ADDS    r0, r0, r0
+        SUB     r2, r2, #1
+        BCC     %BT10
+30      TEQ     r0, #0                  ; EQ if exact power of 2
+        ; If exact, just convert exponent field to FP, else
+        ; compute log2(e)*log(x)
+        BEQ     log2f_exact
+        LDFE    f1, log2_e
+        LGNE    f0, f0
+        MUFS    f0, f0, f1
+        Return  ,LinkNotStacked
+log2f_exact
+        SUB     r2, r2, #&400
+        ADD     r2, r2, #1
+        TEQ     r2, #&400               ; EQ if infinity
+        FLTNES  f0, r2
+        Return  ,LinkNotStacked
+
+log2_e  DCD     &00003FFF, &B8AA3B29, &5C17F0BC
+loge_2  DCD     &00003FFE, &B17217F7, &D1CF79AC
+
+        IMPORT  scalbln
+exp2
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        FIX     r0, f0
+        CheckFPInterrupts
+        ANDS    r1, r1, #&1F            ; inexact or invalid?
+        BNE     exp2_inexact
+        ; exp2 of an integer - can create an exact result using scalbn
+        ReEnableFPInterrupts nocheck
+        [ FloatingPointArgsInRegs
+        MVFD    f0, #1
+        |
+        MOV     r2, r0
+        ADR     r3, D_one
+        LDMIA   r3, {r0,r1}
+        ]
+        B       scalbln
+exp2_inexact
+        LDFE    f1, loge_2
+        MUFE    f0, f0, f1
+        B       exp_common
+
+        IMPORT  scalblnf
+exp2f
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        MVFS    f0, f0
+        FIX     r0, f0
+        CheckFPInterrupts
+        ANDS    r1, r1, #&1F            ; inexact or invalid?
+        BNE     exp2f_inexact
+        ; exp2f of an integer - can create an exact result using scalbn
+        ReEnableFPInterrupts nocheck
+        [ FloatingPointArgsInRegs
+        MVFS    f0, #1
+        |
+        MOV     r2, r0
+        ADR     r3, D_one
+        LDMIA   r3, {r0,r1}
+        ]
+        B       scalblnf
+exp2f_inexact
+        LDFE    f1, loge_2
+        MUFE    f0, f0, f1
+        B       expf_common
+
+D_one   DCFD    1
+OneThird
+        DCD     &00003FFD, &AAAAAAAA, &AAAAAAAB
+
 sqrt
         [ :LNOT: FloatingPointArgsInRegs
         STMFD   sp!, {r0, r1}
         LDFD    f0, [sp], #8
         ]
-        CMFE    f0, #0
+        CMF     f0, #0
         BMI     negative_error
-        SQTD    f0, f0
+        SQTGED  f0, f0
         Return  ,LinkNotStacked
 
 sqrtf
@@ -1386,9 +1657,36 @@ sqrtf
         LDFD    f0, [sp], #8
         ]
         MVFS    f0, f0
-        CMFE    f0, #0
+        CMF     f0, #0
         BMI     negative_errorf
-        SQTS    f0, f0
+        SQTGES  f0, f0
+        Return  ,LinkNotStacked
+
+cbrt
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        CMF     f0, #0
+        Return  ,LinkNotStacked,EQ
+        LDFVCE  f1, OneThird
+        ABSVCE  f0, f0
+        POWVCD  f0, f0, f1
+        MNFMID  f0, f0
+        Return  ,LinkNotStacked
+
+cbrtf
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        LDFD    f0, [sp], #8
+        ]
+        MVFS    f0, f0
+        CMF     f0, #0
+        Return  ,LinkNotStacked,EQ
+        LDFVCE  f1, OneThird
+        ABSVCE  f0, f0
+        POWVCS  f0, f0, f1
+        MNFMIS  f0, f0
         Return  ,LinkNotStacked
 
 tan
@@ -1405,7 +1703,6 @@ tan
         Return  ,LinkNotStacked, EQ
         B       huge_error
 
- [ {FALSE}
 tanf
         [ :LNOT: FloatingPointArgsInRegs
         STMFD   sp!, {r0, r1}
@@ -1420,7 +1717,6 @@ tanf
         TST     r1, #&07
         Return  ,LinkNotStacked, EQ
         B       huge_errorf
- ]
 
 asin
         [ :LNOT: FloatingPointArgsInRegs
@@ -1439,6 +1735,24 @@ asin
         Return  ,LinkNotStacked, EQ
         B       negative_error
 
+asinf
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        MVFS    f0, f0
+        ASNS    f0, f0
+        ReEnableFPInterrupts
+        ; A range error is not possible; any error must be a domain error.
+        ; (And the only plausible error flag is IVO, but I don't check).
+        ; Dunno what result is sensible.
+        TST     r1, #&07
+        Return  ,LinkNotStacked, EQ
+        B       negative_errorf
+
 
 acos
         [ :LNOT: FloatingPointArgsInRegs
@@ -1457,6 +1771,24 @@ acos
         Return  ,LinkNotStacked, EQ
         B       negative_error
 
+acosf
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        MVFS    f0, f0
+        ACSS    f0, f0
+        ReEnableFPInterrupts
+        ; A range error is not possible; any error must be a domain error.
+        ; (And the only plausible error flag is IVO, but I don't check).
+        ; Dunno what result is sensible.
+        TST     r1, #&07
+        Return  ,LinkNotStacked, EQ
+        B       negative_errorf
+
 
 pow
         [ :LNOT: FloatingPointArgsInRegs
@@ -1470,6 +1802,7 @@ pow
         CMFE    f0, #0
         BEQ     POWFirstArgZero
         POWD    f0, f0, f1
+POWCommonExit
         ReEnableFPInterrupts
         ; Plausibly, there may have been either an overflow or IVO error.
         ; I assume that the former is always a range error, and the latter
@@ -1484,6 +1817,22 @@ pow
         BNE     underflow_error
         B       huge_error
 
+powf
+        [ :LNOT: FloatingPointArgsInRegs
+        STMFD   sp!, {r0, r1, r2, r3}
+        DisableFPInterrupts
+        LDFD    f0, [sp], #8
+        LDFD    f1, [sp], #8
+        |
+        DisableFPInterrupts
+        ]
+        MVFS    f0, f0
+        MVFS    f1, f1
+        CMFE    f0, #0
+        BEQ     POWFirstArgZero
+        POWS    f0, f0, f1
+        B       POWCommonExit
+
 POWFirstArgZero
         CMFE    f1, #0
         MVFEQD  f0, #1              ; return 1.0 if both args 0.0
@@ -1502,7 +1851,8 @@ hypot
         LDFD    f0, [sp], #8
         LDFD    f1, [sp], #8
         ]
-        LDFS    f3, infinity
+        ADRL    r0, infinity
+        LDFS    f3, [r0]
         CMF     f0, f1
         BVS     hypot_nan
         MVFMID  f2, f0
@@ -1538,7 +1888,8 @@ hypotf
         ]
         ABSS    f0, f0
         ABSS    f1, f1
-        LDFS    f3, infinity
+        ADRL    r0, infinity
+        LDFS    f3, [r0]
         CMF     f0, f1
         BVS     hypot_nan
         MVFMIS  f2, f0
diff --git a/clib/s/cl_entry2 b/clib/s/cl_entry2
index 924e0ef..5238709 100644
--- a/clib/s/cl_entry2
+++ b/clib/s/cl_entry2
@@ -85,4 +85,59 @@
         Entry   strtoimax, imported, , unveneered
         Entry   strtoumax, imported, , unveneered
 
+        Entry   __assert2, imported, , unveneered
+        Entry   _Exit, imported, , unveneered
+
+        Entry   acosf, , , unveneered
+        Entry   asinf, , , unveneered
+        Entry   atanf, imported, , unveneered
+        Entry   atan2f, imported, , unveneered
+        Entry   cosf, imported, , unveneered
+        Entry   sinf, imported, , unveneered
+        Entry   tanf, , , unveneered
+        Entry   acosh, imported, , unveneered
+        Entry   acoshf, imported, , unveneered
+        Entry   asinh, imported, , unveneered
+        Entry   asinhf, imported, , unveneered
+        Entry   atanh, imported, , unveneered
+        Entry   atanhf, imported, , unveneered
+        Entry   expf, , , unveneered
+        Entry   exp2, , , unveneered
+        Entry   exp2f, , , unveneered
+        Entry   expm1, , , unveneered
+        Entry   expm1f, , , unveneered
+        Entry   frexpf, imported, , unveneered
+        Entry   ilogb, imported, , unveneered
+        Entry   ilogbf, imported, , unveneered
+        Entry   ldexpf, imported, , unveneered
+        Entry   logf, , , unveneered
+        Entry   log10f, , , unveneered
+        Entry   log1p, , , unveneered
+        Entry   log1pf, , , unveneered
+        Entry   log2, , , unveneered
+        Entry   log2f, , , unveneered
+        Entry   logb, imported, , unveneered
+        Entry   logbf, imported, , unveneered
+        Entry   modff, imported, , unveneered
+        Entry   fmodf, imported, , unveneered
+        Entry   scalbn, imported, , unveneered
+        Entry   scalbnf, imported, , unveneered
+        Entry   scalbln, imported, , unveneered
+        Entry   scalblnf, imported, , unveneered
+        Entry   cbrt, , , unveneered
+        Entry   cbrtf, , , unveneered
+        Entry   powf, , , unveneered
+        Entry   sqrtf, , , unveneered
+        Entry   erf, imported, , unveneered
+        Entry   erff, imported, , unveneered
+        Entry   erfc, imported, , unveneered
+        Entry   erfcf, imported, , unveneered
+        Entry   lgamma, imported, , unveneered
+        Entry   lgammaf, imported, , unveneered
+        Entry   tgamma, imported, , unveneered
+        Entry   tgammaf, imported, , unveneered
+        Entry   nexttoward, , , unveneered
+        Entry   nexttowardf, , , unveneered
+        Entry   fmaf, , , unveneered
+
         END
diff --git a/clib/s/cl_stub b/clib/s/cl_stub
index 8e45955..c1030c3 100644
--- a/clib/s/cl_stub
+++ b/clib/s/cl_stub
@@ -79,6 +79,11 @@ SharedLibrary      SETL  {TRUE}
 
 |_kernel_entrypoint|
         SWI     GetEnv
+ [ APCS_Type <> "APCS-R" :LAND: Code_Destination = "RAM"
+        MOV     sp, r1
+        BL      EnsureCLib
+;        SWIVS   GenerateError
+ ]
         MOV     r2, r1
         LDR     r1, =|Image$$RW$$Limit|
         MOV     r3, #-1
@@ -185,6 +190,10 @@ LookupError
         ; Note that finalise always discards the RMA (whether fatal or not)
         ; so initialise always acquires it.  Is this reasonable?
         STMFD   sp!, {r14}
+   [ APCS_Type <> "APCS-R" :LAND: Code_Destination = "RAM"
+        BL      EnsureCLib
+;        LDMVSFD sp!, {pc}
+   ]
         MOV     r9, r0                  ; save 'copy statics' flag
 ;      [ Code_Destination = "RAM"
 ; Old versions of RelocCode would "return" the last field of the
@@ -305,6 +314,43 @@ LookupError
         LDMIA   sp!, {pc}
       ]
 
+   [ APCS_Type <> "APCS-R" :LAND: Code_Destination = "RAM"
+EnsureCLib
+        STMFD   sp!, {r0,lr}
+;        ADR     r0, RMEnsure1
+;        SWI     CLI
+        ADR     r0, RMEnsure2
+        SWI     CLI
+;        ADRVC   r0, RMEnsure3
+;        SWIVC   CLI
+        ADRVC   r0, RMEnsure4
+        SWIVC   CLI
+;        ADRVC   r0, RMEnsure5
+;        SWIVC   CLI
+        ADRVC   r0, RMEnsure6
+        SWIVC   CLI
+;        ADRVC   r0, RMEnsure7
+;        SWIVC   CLI
+        STRVS   r0, [sp]
+        LDMFD   sp!, {r0,pc}
+
+;RMEnsure1
+;        = "RMEnsure UtilityModule 3.10", 0
+RMEnsure2
+        = "RMEnsure UtilityModule 3.70 RMEnsure CallASWI 0.02 RMLoad System:Modules.CallASWI", 0
+;RMEnsure3
+;        = "RMEnsure UtilityModule 3.70 RMEnsure CallASWI 0.02", 0
+RMEnsure4
+        = "RMEnsure FPEmulator 4.03 RMLoad System:Modules.FPEmulator", 0
+;RMEnsure5
+;        = "RMEnsure FPEmulator 4.03", 0
+RMEnsure6
+        = "RMEnsure SharedCLibrary 5.17 RMLoad System:Modules.CLib", 0
+;RMEnsure7
+;        = "RMEnsure SharedCLibrary 5.34", 0
+        ALIGN
+   ]
+
         EXPORT  |_clib_initialisemodule|
 |_clib_initialisemodule|
         STMFD   sp!, {r14}
diff --git a/h/hostsys b/h/hostsys
index 603ab2d..e8c9904 100644
--- a/h/hostsys
+++ b/h/hostsys
@@ -100,8 +100,8 @@ extern void *_sys_alloc(size_t n);
 extern void _init_user_alloc(void);
 extern void _terminate_user_alloc(void);
 extern void _sys_msg(const char *);
-extern bool _sys__assert(const char *fmt,
-                         const char *expr, const char *file, int line);
+extern bool _sys__assert(const char *fmt, const char *expr,
+                         const char *func, const char *file, int line);
 extern void _exit(int n);
 extern void _terminate_getenv(void);
 
@@ -153,7 +153,7 @@ extern struct _svcwto _io_emsg;  /* beware only 64 bytes thereof */
 /* For the current ARM floating point system that Acorn use the first    */
 /* word of a floating point value is the one containing the exponent.    */
 #        undef OTHER_WORD_ORDER_FOR_FP_NUMBERS
-#        define DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS 1
+/*#        define DO_NOT_SUPPORT_UNNORMALIZED_NUMBERS 1*/
 #     endif
 #  endif
 #endif
@@ -350,9 +350,11 @@ extern FILE *_fopen_string_file(const char *data, int length);
 #ifdef DEFAULT_TEXT
 extern char *_kernel_getmessage(char *msg, char *tag);
 extern char *_kernel_getmessage2(char *msg, char *tag, char *dst, size_t len);
+#define _kernel_getmessage_def(msg, tag) _kernel_getmessage(msg, tag)
 #else
 extern char *_kernel_getmessage(char *tag);
 extern char *_kernel_getmessage2(char *tag, char *dst, size_t len);
+extern char *_kernel_getmessage_def(char *msg, char *tag);
 #define _kernel_getmessage(msg, tag) _kernel_getmessage(tag)
 #define _kernel_getmessage2(msg, tag, dst, len) _kernel_getmessage2(tag, dst, len)
 #endif
diff --git a/kernel/s/k_body b/kernel/s/k_body
index 850546d..f0ad347 100644
--- a/kernel/s/k_body
+++ b/kernel/s/k_body
@@ -3150,6 +3150,7 @@ dividebyzero
 
         EXPORT  |_kernel_copyerror|
         EXPORT  |_kernel_getmessage|
+        EXPORT  |_kernel_getmessage_def|
         EXPORT  |_kernel_getmessage2|
 
         [ SharedLibrary   ; Only works with module for the moment
@@ -3197,15 +3198,14 @@ n_module_lookupname EQU 18
 ; Return:
 ;   R0 = Message
 ;
+      [ :DEF:DEFAULT_TEXT
 |_kernel_getmessage|
+      ]
+|_kernel_getmessage_def|
         FunctionEntry "r0-r7,r12"
         BL      open_messagefile
         MOV     r0, r1
-      [ :DEF:DEFAULT_TEXT
         LDR     r1, [sp, #4]
-      |
-        LDR     r1, [sp]
-      ]
         MOV     r2, #0
         MOV     r4, #0
         MOV     r5, #0
@@ -3215,6 +3215,20 @@ n_module_lookupname EQU 18
         STRVC   r2, [sp]
         Return  "r0-r7,r12"
 
+      [ :LNOT::DEF:DEFAULT_TEXT
+; On entry:
+;   R0 = Message tag
+;
+; Return:
+;   R0 = Message
+;
+|_kernel_getmessage|
+        FunctionEntry "r1"
+        MOV     r1, r0
+        BL      |_kernel_getmessage_def|
+        Return  "r1"
+      ]
+
 ; On entry:
 ; [ DEFAULT_TEXT
 ;   R0 = Message to use if failed to get message from message file
@@ -3292,6 +3306,7 @@ open_messagefile
         Return  ,LinkNotStacked
 
 |_kernel_getmessage|
+|_kernel_getmessage_def|
 |_kernel_getmessage2|
         Return  ,LinkNotStacked
 
diff --git a/rlib/c/txt1 b/rlib/c/txt1
index a07972d..02cb06b 100644
--- a/rlib/c/txt1
+++ b/rlib/c/txt1
@@ -267,8 +267,6 @@ static int txt1__min(int a, int b) {return(a < b ? a : b);}
 
 static int txt1__max(int a, int b) {return(a > b ? a : b);}
 
-static int txt1__abs(int a) {return(a < 0 ? -a : a);}
-
 /* -------- checking and debugging. -------- */
 
 #if TRACE
@@ -1405,7 +1403,7 @@ of the succuessor line rather than the end of the previous one. */
     txt1__horizmeasure(t, x, t->w->caretx + t->w->caretoffsetx, &at);
     if (
        0 == (txt_DISPLAY & t->charoptionset)
-    || (txt1__abs(by) < (3 * t->w->limy) / (4 * t->w->linesep))) {
+    || (abs(by) < (3 * t->w->limy) / (4 * t->w->linesep))) {
       /* could end up doing on-screen block copies */
       tracef0("movevertical is near.\n");
       txt1_dosetdot(t, txt1__bufindextoindex(t, at));
@@ -1476,7 +1474,7 @@ void txt1_domovehorizontal(txt t, int by)
     caret = 0 != (txt_CARET & t->charoptionset);
     t->charoptionset &= ~txt_CARET;
     spacewidth = txt1__spacewidth(t);
-    for (i = 1; i <= txt1__abs(by); i++) {
+    for (i = 1; i <= abs(by); i++) {
       if (((t->w->caretoffsetx > 0) || ((t->w->caretoffsetx == 0) && (by > 0)))
       && ((t->gapend == txt1__termchbi(t)) || (t->buf[t->gapend] == '\n'))
       && (t->w->caretoffsetx + t->w->caretx + by*spacewidth <= t->w->limx)
@@ -2440,7 +2438,7 @@ void txt1__updatescrollbar(txt t)
       offset = (first * 100) / max;
     };
     /* try not to keep fiddling the size by small amounts. */
-    if (t->w->isize != 0 && txt1__abs(size - t->w->isize) < 3) {
+    if (t->w->isize != 0 && abs(size - t->w->isize) < 3) {
       size = t->w->isize;
     };
     if (size != t->w->isize || offset != t->w->ioffset) {
@@ -3376,7 +3374,7 @@ a move or replace. */
     tracef3("limy=%i lastvisy=%i linesep=%i\n",
       t->w->limy, t->w->lastvisy, t->w->linesep);
     if (by == 0) return;
-    byy = txt1__abs(by) * t->w->linesep;
+    byy = abs(by) * t->w->linesep;
 
 /* >>>> replaced by stuff below
     if ((by > 0) && (t->w->lastvis.pos == txt1__termchbi(t))) {
diff --git a/rlib/c/txtar b/rlib/c/txtar
index d5c4d4e..46507cc 100644
--- a/rlib/c/txtar
+++ b/rlib/c/txtar
@@ -216,8 +216,6 @@ static int txtar__max(int a, int b) {return(a > b ? a : b);}
 
 static int txtar__min(int a, int b) {return(a < b ? a : b);}
 
-static int txtar__abs(int a) {return(a < 0 ? -a : a);}
-
 static void txtar__setmode(txtar__sysdata *s) {
   txt t = s->t;
 #ifdef BIG_WINDOWS
@@ -2466,8 +2464,8 @@ drag event. */
     m = 0;
   };
 
-  if ((txtar__abs(s->prevmousex - e->data.but.m.x) <= 2 * wimpt_dx())
-  && (txtar__abs(s->prevmousey - e->data.but.m.y) <= 2 * wimpt_dy())
+  if ((abs(s->prevmousex - e->data.but.m.x) <= 2 * wimpt_dx())
+  && (abs(s->prevmousey - e->data.but.m.y) <= 2 * wimpt_dy())
   && (mousetime - s->prevmousetime < 100)) {
     tracef0("mouse exact multi-click.\n");
     m |= txt_MEXACT;
diff --git a/s/mathl b/s/mathl
new file mode 100644
index 0000000..8977503
--- /dev/null
+++ b/s/mathl
@@ -0,0 +1,93 @@
+; Copyright 2003 Tematic Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+; As long double is the same as double, all the long double <math.h> functions
+; can just bounce to the double ones. These bounces are included in ANSILib
+; and the stubs as is - the Shared C Library doesn't contain or export them.
+
+        AREA    |C$$code|, CODE, READONLY
+
+        MACRO
+        DoL     $func
+        EXPORT  $func.l
+        IMPORT  $func
+$func.l B       $func
+        MEND
+
+        DoL     acos
+        DoL     asin
+        DoL     atan
+        DoL     atan2
+        DoL     cos
+        DoL     sin
+        DoL     tan
+
+        DoL     acosh
+        DoL     asinh
+        DoL     atanh
+        DoL     cosh
+        DoL     sinh
+        DoL     tanh
+
+        DoL     exp
+        DoL     exp2
+        DoL     expm1
+        DoL     frexp
+        DoL     ilogb
+        DoL     ldexp
+        DoL     log
+        DoL     log10
+        DoL     log1p
+        DoL     log2
+        DoL     logb
+        DoL     modf
+        DoL     scalbn
+        DoL     scalbln
+
+        DoL     cbrt
+        DoL     fabs
+        DoL     hypot
+        DoL     pow
+        DoL     sqrt
+
+        DoL     erf
+        DoL     erfc
+        DoL     lgamma
+        DoL     tgamma
+
+        DoL     ceil
+        DoL     floor
+        DoL     nearbyint
+        DoL     rint
+        DoL     lrint
+        DoL     round
+        DoL     lround
+        DoL     trunc
+
+        DoL     fmod
+        DoL     remainder
+;       DoL     remquo
+
+        DoL     copysign
+        DoL     nan
+        DoL     nextafter
+        DoL     nexttoward
+
+        DoL     fdim
+        DoL     fmax
+        DoL     fmin
+
+;        DoL     fma
+
+        END
-- 
GitLab