Summary of C99 features in the C compiler
=========================================

The current compiler supports a significant subset of features from the
ISO C standard (ISO/IEC 9899:1999). This document summarises the available
facilities.

C99 features and examples
-------------------------

     bool

           #include <stdbool.h>
           bool on = true;
           
           struct flags
           {
               bool a:1;
               bool b:1;
               bool c:1;
           };

     restrict

           // a and b guaranteed to point to different objects, allowing
           // better optimisation
           void fred(char *restrict a, char *restrict b);

     inline

           Not the same as in C++ - read the C99 rationale document for
           details

     long long

           64 bit integers

     Type qualifiers and "static" inside function array parameters

           void fred(char a[static 4], char b[const]);
           /* is equivalent to */
           void fred(char *a, char * const b);
           /* with a guarantee that a points to at least 4 chars */

     Variable-length arrays

           void fred(int w, int h, char d[h][w])
           {
               for (int y=0; y<h; y++)
                   for (int x=0; x<w; x++)
                       d[y][x] ^= 0xff;
           }
           
           void iconsprites(const char *filename)
           {
               char buffer[sizeof "IconSprites " + strlen(filename)];
               sprintf(buffer, "IconSprites %s", filename);
               _kernel_oscli(buffer);
           }

     Interleaved statements and declarations

           foo();
           int b = 5;
           bar();

     Declarations in for(...;

           for (int i=0; i<10; i++)

     Designated structure initialisers

           struct mystruct a = { .foo = 1, .bar = 3, .jim = { .x=1, .y = 2},
                                 .harry.fred = "Dibble" };
           enum { ZERO, ONE, TWO, THREE };
           char wibble[] = { [ONE] = 1, [THREE] = 3 };

     Non-constant structure initialisers

           struct mystruct a = { x + y, foo() };

     Compound literals

           typedef struct Point { int x, y; } Point;
           void Draw(Point);
           Draw( (const Point) { 2, 3 } );

     __func__

           printf("Error in function %s\n", __func__);

     Variadic macros

           #define dprintf(...) fprintf(stderr, __VA_ARGS__)

     Flexible array members

           struct blah
           {
                int len;
                char data[];
           };
           
           struct blah *p = malloc(sizeof(struct blah) + 10);
           for (int i=0; i<10; i++) p->data[i] = i;
           
     Trailing comma allowed in enum declaration

           enum
           {
              ZERO,
              ONE,
              TWO,
              THREE,
           };

     Hexadecimal floating-point constants

           double a = 0x0.8p0;  // == 0.5 in decimal

     Digraphs

           %:include <stdio.h>
           char a<:2:> = <% 1, 3 %>;

     <fenv.h>, <stdbool.h>, <stdint.h>, <inttypes.h>, <iso646.h>

           Read the header files for more details.

     New functions in <math.h>

           All the new C99 functions in <math.h> are available. This
           includes float and long double forms of existing functions,
           plus many new ones.
           
     Complex (and imaginary) support in <complex.h>
     
          #include <complex.h>
          
          #define MAX_ITER 512
          int mandelbrot(complex double c)
          {
              complex double z = 0;
              int i;
              for (i = 0; i < MAX_ITER; i++)
              {
                  z = z*z + c;
                  if (cabs(z) > 2) break;
              }
              return i;
          }

          for (double y = 2.0; y >= -2.0; y -= 0.05)
          {
              for (double x = -2.0; x <= 2.0; x += 0.05)
              {
                  int i = mandelbrot(x + I*y);
                  // ...
              }
          }

     Type-generic mathematics macros in <tgmath.h>
     
           #include <tgmath.h>
           float f, g; double a, b, c;
           double complex z, w; double imaginary y;
           f = cos(g);  // invokes real function cosf
           a = cos(b);  // invokes real function cos
           z = cos(w);  // invokes complex function ccos
           c = cos(y);  // invokes real function cosh [cos(y)==cosh(y/I)]
           
     snprintf, vscanf family

           char buffer[20];
           snprintf(buffer, sizeof buffer, "String=%s", s);

     New C99 modifiers for printf, scanf and strftime

           size_t a; intmax_t i; long long l; float f;
           printf("a=%zu, i=%jd, l=%lld, f=0x%a\n", a, i, l, f);

           strftime(buffer, buflen, "ISO 8601 week number %G/%g", &tm);
           
     C99 standard pragmas
     
           #pragma STDC FENV_ACCESS ON
           
     Universal character names (in strings and character constants)
     
           char *s = "\uAC00\uAC01";

     A couple of minor other additions like llabs and va_copy.
 
C99 changes
-----------
     C99 scoping rules.
     Warns about old-style declarations in C99 by default (equivalent to -fo
     feature). This can be turned off with -Wd.

C99 removals
------------
     return statement must have expression for non-void function.
     Implicit int and missing function declarations now errors.
     Arrays of incomplete type not permitted.

Implementation notes
--------------------
If you use the new C99 library functions, long long variables, or variable
length arrays, you will need to ensure SharedCLibrary 5.43 or later is
loaded. Other C99 language features (and things implemented in headers
just as macros) do not need a newer C library, other than that required
for 32-bit programs (5.34); indeed they will work when compiled as APCS-R
with pre-32-bit C libraries. The new functions in the C library, including
the long long support code, will not work reliably if called from an APCS-R
program.

The functions in <complex.h> are provided by SharedCLibrary 5.52 or later.
This version of the C library also provides run-time support for complex
multiplication (both operands complex) and division (second operand complex).
Simpler operations are inlined by the compiler, so don't require C library
support (eg complex+complex, complex/real, and some functions inlined as
macros, eg creal and conj).

_Bool is an 8-bit type; any value other than 0 or 1 is a trap representation.
Unlike char, short or float, _Bool is "caller-narrowed" in function calls.

Any function that is declared with "inline" at the top-level before (or in)
its definition will be inlined when used subsequently in that translation
unit. Inlining does not occur if the -g or -Ospace options have been
selected.  An "inline" declaration is ineffective if first seen after the
function definition. In the event of recursion during inline expansion,
inlining stops after the first iteration.

VLAs use new library functions "__rt_allocauto" and "__rt_freeauto". In the
future these could be improved to make sure VLAs are freed correctly in
longjmp-type situations, by associating blocks with stack chunk and stack
pointer values.

long long uses a host of new run-time support functions - the functions used
are compatible with the ones used by the ARM ADS compiler. The compiler
inlines many long long operations. If you specify "-cpu 4" or similar, it
will inline some multiplications (signed * signed -> long long, unsigned *
unsigned -> long long, and unsigned * long long -> long long) using the UMULL
and SMULL instructions (available on StrongARM processors or later). The
compiler will also use UMLAL and SMLAL where appropriate.

If you use "-cpu 4" or later, also specify "-memaccess -L22-S22" if you want
your software to be Risc PC-compatible. This is to stop the compiler from
using the ARMv4 halfword memory access instructions, which although available
on the StrongARM, do not work in the Risc PC.

All three standard C99 pragmas default to OFF. Only FENV_ACCESS currently
has any effect on code generation.

See the separate document for details of what the restrict qualifier can
achieve in the current compiler.

There is no library support for those functions in <wchar.h> or <wctype.h>.

Selecting the standard
----------------------
The compiler defaults to C18 (or "-ansi" mode) which is highly compatible
with C99.
To explicitly select C99 or C90 mode use the "-c99" or "-c90" command-line
switches respectively. In the event of multiple standard selections the
highest version specifier (of "-pcc", "-c90", "-c99" and "-ansi/c18") wins.
