| 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. |
| |