195 lines
6.9 KiB
Plaintext
195 lines
6.9 KiB
Plaintext
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.
|
|
|