INTRODUCTION
======================
This directory contains a port of eXternal Data Representation
(XDR) code from SunRPC (derived from the relicensed -- to
3-clause BSD -- implementation in Fedora 11's libtirpc package
version 0.1.10-7). It has been adapted for newlib in the
following ways:

1) xdr_* functions for fixed-width integral types have been
   added, such as xdr_int32_t() and similar. The implementation
   of stream-specific x_putlong() and x_getlong() functions
   has been modified to work properly whenever possible, even
   if sizeof(long) > 32bits -- and to correctly report failure
   when that is not possible.
2) Use of DEFUN(), EXFUN(), and various other portability
   macros.
3) Uses of 64bit types, such as xdr_hyper, xdr_u_longlong_t,
   and xdr_int64_t, as well as the xdr-specific typedefs
   quad_t and u_quad_t, are guarded by ___int64_t_defined.
4) Out-of-memory conditions are indicated by returning FALSE
   and setting errno = ENOMEM, rather than by printing error
   messages to stderr. (See #8, below).
5) Only xdrstdio.c requires stdio support, and it is only
   compiled if the target supports stdio (see stdio_dir in
   configure.host)
6) Uses a local implementation of ntohl/htonl, rather than
   one provided elsewhere. No dependency on any networking
   functions.
7) Floating point support refactored. Currently supports
   IEEE single and double precision, and VAX single and
   double precision.
   a) Those platforms which use float to represent double
      do not provide xdr_double().
8) Error reporting can be customized using a private hook.
   This is described below.

xdr is compiled and supported only for those platforms which
set xdr_dir nonempty in configure.host. At present, the list
of platforms which do this is:
   cygwin


PORTING
======================
To port XDR to a new newlib target, first enable building it
by modifying configure.host.  Search for the 'case' statement
where various *_dir= variables are set, and look for your
target's entry (or add one if not present).  Set xdr_dir:

  *-*-myplatform*)
        xdr_dir=xdr
	;;

If your platform does not use IEEE754 standard formats for
floating point values (floats, doubles) you may need to add
a new xdr_float_*.c implementation, and modify the bottom of
xdr_float.c:

  ...
  #elif defined(__vax__)
  #include "xdr_float_vax.c"
 +#elif defined(__my_platform__)
 +#include "xdr_float_my_platform.c"
  #endif

You may want to customize your platform's startup objects to set
the error reporting callback for xdr (not likely, but see ERROR
MESSAGES section). 

You may also want to customize the memory allocation semantics
employed by the xdr routines.  As stated in the xdr.h header:

  XDR_DECODE may allocate space if the pointer [to the location
  at which the decoded data is to be stored] is NULL. This
  data can be freed with the XDR_FREE operation.

The default implementation defines the following macros in
rpc/types.h, used throughout xdr/ to deal with memory
allocation:

  #ifndef mem_alloc
  #define mem_alloc(bsize)        calloc(1, bsize)
  #endif
  #ifndef mem_free
  #define mem_free(ptr, bsize)    free(ptr)
  #endif

By arranging that these symbols are #defined to some other
memory allocation functions, different memory semantics can be
imposed. To disallow memory allocation entirely, use the
following:

  -D'mem_alloc(a)'=NULL -D'mem_free(a,b)'='do { ; } while(0)'

In this case, any operations which would otherwise require
memory to be allocated, will instead fail (return FALSE),
and set errno=ENOMEM.


ERROR MESSAGES
======================
This implementation of xdr provides a special hook, so that
error messages generated by xdr may be captured by a user-
defined facility. For certain error conditions, the internal
printf-like function
  xdr_warnx (fmt, ...)
is called.  However, that function simply delegates to an
internal function pointer to a callback function if set;
otherwise, xdr_warnx does nothing.

By setting this function pointer to a user-defined callback,
the user can enable these messages to go to a syslog, stderr,
or some other facility.  The function should match the
following typedef (see xdr_private.h):

  typedef void (* xdr_vprintf_t) (const char *, va_list);

The desired callback can be registered by calling:

  xdr_vprintf_t xdr_set_vprintf (xdr_vprintf_t fnptr);

The return value is the "old" function pointer, which may
be NULL.

However, neither the typedef nor the registration function
are declared in the public headers. Clients wishing to use
them must either declare the necessary symbols manually,
or #include "xdr_private.h". More on this point, below.

For instance:
  #include <stdarg.h>
  #include <stdio.h>
  typedef void (* xdr_vprintf_t) (const char *, va_list);
  xdr_vprintf_t xdr_set_vprintf (xdr_vprintf_t fnptr);

  void my_vwarnx (const char * fmt, va_list ap)
  {
    (void) fprintf (stderr, fmt, ap);
  }
  
  main()
  {
    (void) xdr_set_vprintf (&my_vwarnx);
    ...
  }

will cause xdr-generated error messages to go to stderr.

It is not expected that end-user applications will make use
of this facility.  Rather, it is expected that IF certain
*platforms* desire that these error messages be recorded,
instead of expecting client apps to print error messages as
necessary (*), then those platforms will, in their startup
objects or static initialization, direct these messages to
a logging facility, strace debug facility, etc.

Therefore, the platform startup code, if part of newlib, can
#include "xdr_private.h", or simply copy the two declarations
from that file.

However, most newlib targets will probably be satisfied with
the default (silent) behavior. Note that the original Sun RPC
implementation of XDR, as well as the glibc implementation,
print these error messages to stderr.  Cygwin, for greater
similarity to glibc, registers an error message handler similar
to the example above, within its startup code.

(*) Client apps should already check for FALSE return values.
    In this case when xdr function return FALSE, the client
    app would then check errno and act appropriately.


LICENSING AND PEDIGREE
======================
For years, the Sun RPC code, and the XDR implementation, was in
legal license limbo
  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=181493
as its license terms, while open, were of debatable compatibility
with the GPL. In February of 2009, that changed:
  http://blogs.sun.com/webmink/entry/old_code_and_old_licenses
  http://lwn.net/Articles/319648/

As documented in the libtirpc rpm.spec file from Fedora 11:
* Tue May 19 2009 Tom "spot" Callaway <xxxx@redhat.com> 0.1.10-7
  - Replace the Sun RPC license with the BSD license, with the
    explicit permission of Sun Microsystems

So, in the XDR implementation from Fedora 11's libtirpc package,
after the modification above by Tom Callaway, each file carries
the 3-clause BSD license and not the so-called "SunRPC" license.
It is from this version that the newlib implementation here was
derived, with the modifications described in the introduction,
above.

