// Sample code file: XDR.H

// Warning: This code has been marked up for HTML
/*
//赏屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯突
//� (c) 1995 Novell, Inc.  All rights reserved.                              �
//�                                                                          �
//� THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND        �
//� TREATIES.                                                                �
//�                                                                          �
//� NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, COPIED,          �
//� DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, CONDENSED,         �
//� EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, TRANSFORMED OR ADAPTED    �
//� WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC.                        �
//�                                                                          �
//� ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT �
//� THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.                         �
//掏屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯凸
//� Source module name: XDR.H                                                �
//韧屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯图
*/
/* Inclusion Control */
#if !defined( _RPC_XDR_H )
   #define _RPC_XDR_H

#include <rpc/ndpsrpc.h>

#if defined(NWDOS) || defined(N_PLAT_DOS)

#include <stdio.h>               /* FILE                             */
 
#ifndef _RPC_TYPES_H
#include <rpc/types.h>           /* u_int, u_long, caddr_t ...       */
#endif

#ifndef _RPC_NETCVT_H
#include <rpc/netcvt.h>          /* ntoh[sl], hton[sl]               */
#endif

/*
 * XDR provides a conventional way for converting between C data
 * types and an external bit-string representation.  Library supplied
 * routines provide for the conversion on built-in C data types.  These
 * routines and utility routines defined here are used to help implement
 * a type encode/decode routine for each user-defined type.
 *
 * Each data type provides a single procedure which takes two arguments:
 *
 *    bool_t
 *    xdrproc(xdrs, argresp)
 *       XDR *xdrs;
 *       <type> *argresp;
 *
 * xdrs is an instance of a XDR handle, to which or from which the data
 * type is to be converted.  argresp is a pointer to the structure to be
 * converted.  The XDR handle contains an operation field which indicates
 * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
 *
 * XDR_DECODE may allocate space if the pointer argresp is null.  This
 * data can be freed with the XDR_FREE operation.
 *
 * We write only one procedure per data type to make it easy
 * to keep the encode and decode procedures for a data type consistent.
 * In many cases the same code performs all operations on a user defined type,
 * because all the hard work is done in the component type routines.
 * decode as a series of calls on the nested data types.
 */

/*
 * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
 * stream.  XDR_DECODE causes the type to be extracted from the stream.
 * XDR_FREE can be used to release the space allocated by an XDR_DECODE
 * request.
 */
enum xdr_op {
   XDR_ENCODE=0,
   XDR_DECODE=1,
   XDR_FREE=2
};

/*
 * This is the number of bytes per unit of external data.
 */
#define BYTES_PER_XDR_UNIT    (4)

/*
 * Threshold size for bcopy avoidence hack in xdrXXX_putbytes().
 *
 * The number of bytes to look for in the buffer is determined by
 * comparing the cost of bcopy with the cost of a write system call
 * times 3. The reason for this is that each write here could cause
 * a read of the same number of bytes in the receiving process, plus
 * you need some slop for good luck.
 */
#define BIGBLKSZ      2500
#define RNDDOWN(x)   ((x) & (BYTES_PER_XDR_UNIT - 1))
#define RNDUP(x)     \
   ((((x)+BYTES_PER_XDR_UNIT-1)/BYTES_PER_XDR_UNIT)*BYTES_PER_XDR_UNIT)


/*
 * Constants specific to the xdr "protocol"
 */
#define XDR_FALSE       ((long) 0)
#define XDR_TRUE        ((long) 1)

#define LASTUNSIGNED    ((u_int)~0)

/*
 * The XDR handle.
 * Contains operation which is being applied to the stream,
 * an operations vector for the particular implementation (e.g. see xdr_mem.c),
 * and two private fields for the use of the particular impelementation.
 */
typedef struct xdr {
   enum xdr_op x_op;          /* operation; fast additional param */
   struct xdr_ops {
      bool_t (far *x_getlong)(struct xdr far *, long far *);           
      bool_t (far *x_putlong)(struct xdr far *, long far *);           
      bool_t (far *x_getbytes)(struct xdr far *, caddr_t, u_int);  
      bool_t (far *x_putbytes)(struct xdr far *, caddr_t, u_int);  
      u_int  (far *x_getpostn)(struct xdr far *);                  
      bool_t (far *x_setpostn)(struct xdr far *, u_int);           
      long far *(far  *x_inline)(struct xdr far *, u_int);            
      void    (far *x_destroy)(struct xdr far *);                   
   }  far     *x_ops;
   caddr_t     x_public;         /* users' data                      */
   caddr_t     x_private;        /* pointer to private data          */
   caddr_t     x_base;           /* private used for position info   */
   int         x_handy;          /* extra private word               */
} XDR;

/*
 * Operations defined on a XDR handle
 */
#define XDR_GETLONG(xdrs, longp) \
    (*(xdrs)->x_ops->x_getlong)((XDR far *)xdrs, (long far *)longp)
#define xdr_getlong(xdrs, longp) \
    (*(xdrs)->x_ops->x_getlong)((XDR far *)xdrs, (long far *)longp)

#define XDR_PUTLONG(xdrs, longp) \
    (*(xdrs)->x_ops->x_putlong)((XDR far *)xdrs, (long far *)longp)
#define xdr_putlong(xdrs, longp) \
    (*(xdrs)->x_ops->x_putlong)((XDR far *)xdrs, (long far *)longp)

#define XDR_GETBYTES(xdrs, addr, len)        \
   (*(xdrs)->x_ops->x_getbytes)((XDR far *)xdrs, (caddr_t)addr, len)
#define xdr_getbytes(xdrs, addr, len)        \
   (*(xdrs)->x_ops->x_getbytes)((XDR far *)xdrs, (caddr_t)addr, len)

#define XDR_PUTBYTES(xdrs, addr, len)        \
   (*(xdrs)->x_ops->x_putbytes)((XDR far *)xdrs, (caddr_t)addr, len)
#define xdr_putbytes(xdrs, addr, len)        \
   (*(xdrs)->x_ops->x_putbytes)((XDR far *)xdrs, (caddr_t)addr, len)

#define XDR_GETPOS(xdrs)   \
   (*(xdrs)->x_ops->x_getpostn)((XDR far *)xdrs)
#define xdr_getpos(xdrs)   \
   (*(xdrs)->x_ops->x_getpostn)((XDR far *)xdrs)

#define XDR_SETPOS(xdrs, pos) \
   (*(xdrs)->x_ops->x_setpostn)((XDR far *)xdrs, pos)
#define xdr_setpos(xdrs, pos) \
   (*(xdrs)->x_ops->x_setpostn)((XDR far *)xdrs, pos)

#define  XDR_INLINE(xdrs, len)   \
   (*(xdrs)->x_ops->x_inline)((XDR far *)xdrs, len)
#define  xdr_inline(xdrs, len)   \
   (*(xdrs)->x_ops->x_inline)((XDR far *)xdrs, len)

#define  XDR_DESTROY(xdrs) \
   (*(xdrs)->x_ops->x_destroy)((XDR far *)xdrs)
#define  xdr_destroy(xdrs) \
   (*(xdrs)->x_ops->x_destroy)((XDR far *)xdrs)

/*
 * A xdrproc_t exists for each data type which is to be encoded or decoded.
 *
 * The second argument to the xdrproc_t is a pointer to an opaque pointer.
 * The opaque pointer generally points to a structure of the data type
 * to be decoded.  If this pointer is 0, then the type routines should
 * allocate dynamic storage of the appropriate size and return it.
 * bool_t   (*xdrproc_t)(XDR *, caddr_t *);
 */
typedef   bool_t (far *xdrproc_t)();

/*
 * Support struct for discriminated unions.
 * You create an array of xdrdiscrim structures, terminated with
 * a entry with a null procedure pointer.  The xdr_union routine gets
 * the discriminant value and then searches the array of structures
 * for a matching value.  If a match is found the associated xdr routine
 * is called to handle that part of the union.  If there is
 * no match, then a default routine may be called.
 * If there is no match and no default routine it is an error.
 */
#define NULL_xdrproc_t ((xdrproc_t)0)
typedef struct xdr_discrim {
   enum_t    value;
   xdrproc_t proc;
} xdr_discrim;

/*
 * Common opaque bytes objects used by many rpc protocols;
 * declared here due to commonality.
 */
#define MAX_NETOBJ_SZ 1024 
typedef struct netobj {
   u_int     n_len;
   char far *n_bytes;
} netobj;

/*
 * In-line routines for fast encode/decode of primitve data types.
 * Caveat emptor: these use single memory cycles to get the
 * data from the underlying buffer, and will fail to operate
 * properly if the data is not aligned.  The standard way to use these
 * is to say:
 *    if ((buf = XDR_INLINE(xdrs, count)) == NULL)
 *       return (FALSE);
 *    <<< macro calls >>>
 * where ``count'' is the number of bytes of data occupied
 * by the primitive data types.
 *
 * N.B. and frozen for all time: each data type here uses 4 bytes
 * of external representation.
 */
#define IXDR_GET_LONG(buf)       ((long)ntohl((u_long)*((long far *)buf)++))
#define IXDR_PUT_LONG(buf, v)    (*((long far *)buf)++=(long)htonl((u_long)v))

#define IXDR_GET_BOOL(buf)       ((bool_t)IXDR_GET_LONG(buf))
#define IXDR_GET_ENUM(buf, t)    ((t)IXDR_GET_LONG(buf))
#define IXDR_GET_U_LONG(buf)     ((u_long)IXDR_GET_LONG(buf))
#define IXDR_GET_SHORT(buf)      ((short)IXDR_GET_LONG(buf))
#define IXDR_GET_U_SHORT(buf)    ((u_short)IXDR_GET_LONG(buf))

#define IXDR_PUT_BOOL(buf, v)    IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_ENUM(buf, v)    IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_U_LONG(buf, v)  IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_SHORT(buf, v)   IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))

#ifdef __cplusplus
extern "C" {
#endif

/*
 * These are the "generic" xdr routines.
 */
      /* XDR primitive data types */
bool_t   xdr_void(void);
bool_t   xdr_bool( XDR far *, bool_t far * );
bool_t   xdr_bytes( XDR far *, char far * far *, u_int far *, u_int );
bool_t   xdr_char( XDR far *, char far * );
bool_t   xdr_enum( XDR far *, enum_t far * );
bool_t   xdr_int( XDR far *, int far * );
bool_t   xdr_long( XDR far *, long far * );
bool_t   xdr_opaque( XDR far *, caddr_t , u_int );
bool_t   xdr_short( XDR far *, short far * );
bool_t   xdr_string( XDR far *, char far * far *, u_int );
bool_t   xdr_wrapstring( XDR far *, char far * far * );
bool_t   xdr_u_char( XDR far *, u_char far * );
bool_t   xdr_u_int( XDR far *, u_int far * );
bool_t   xdr_u_long( XDR far *, u_long far * );
bool_t   xdr_union( XDR far *, enum_t far *, char far *, struct xdr_discrim far *, xdrproc_t );
bool_t   xdr_u_short( XDR far *, u_short far * );
      /* XDR float types */
bool_t   xdr_double( XDR far *, double far * );
bool_t   xdr_float( XDR far *, float far * );
      /* XDR "non-trivial" types */
bool_t   xdr_array( XDR far *, caddr_t far *, u_int far *, u_int , u_int , xdrproc_t );
bool_t   xdr_vector( XDR far *, caddr_t, u_int, u_int, xdrproc_t );
bool_t   xdr_pointer( XDR far *, caddr_t far *, u_int, xdrproc_t );
bool_t   xdr_reference( XDR far *, caddr_t far *, u_int, xdrproc_t );
      /* here due to commonality. used by many rpc protocols */
bool_t   xdr_netobj( XDR far *, netobj far *);

/*
 * These are the public routines for the various implementations of
 * xdr streams.
 */
void    xdrstdio_create( XDR far *, FILE far *, enum xdr_op );
void    xdrmem_create( XDR far *, caddr_t, u_int, enum xdr_op );
void    xdrrec_create( XDR far *, u_int, u_int , caddr_t ,int (far *)(), int (far *)());
bool_t  xdrrec_skiprecord(XDR far *);
bool_t  xdrrec_eof(XDR far *);
bool_t  xdrrec_endofrecord( XDR far *, bool_t );
void    xdr_free( xdrproc_t, caddr_t );

#ifdef  __cplusplus
}
#endif

#endif /* NWDOS */

#if defined(NWWIN) || defined(N_PLAT_MSW) || defined(N_PLAT_MSW4)

#include <rpc/types.h>
#include <rpc/netcvt.h>


/*
 * XDR provides a conventional way for converting between C data
 * types and an external bit-string representation.  Library supplied
 * routines provide for the conversion on built-in C data types.  These
 * routines and utility routines defined here are used to help implement
 * a type encode/decode routine for each user-defined type.
 *
 * Each data type provides a single procedure which takes two arguments:
 *
 *   bool_t
 *   xdrproc(xdrs, argresp)
 *      XDR *xdrs;
 *      <type> *argresp;
 *
 * xdrs is an instance of a XDR handle, to which or from which the data
 * type is to be converted.  argresp is a pointer to the structure to be
 * converted.  The XDR handle contains an operation field which indicates
 * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
 *
 * XDR_DECODE may allocate space if the pointer argresp is null.  This
 * data can be freed with the XDR_FREE operation.
 *
 * We write only one procedure per data type to make it easy
 * to keep the encode and decode procedures for a data type consistent.
 * In many cases the same code performs all operations on a user defined type,
 * because all the hard work is done in the component type routines.
 * decode as a series of calls on the nested data types.
 */

/*
 * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
 * stream.  XDR_DECODE causes the type to be extracted from the stream.
 * XDR_FREE can be used to release the space allocated by an XDR_DECODE
 * request.
 */
enum xdr_op {
   XDR_ENCODE=0,
   XDR_DECODE=1,
   XDR_FREE=2
};

/*
 * This is the number of bytes per unit of external data.
 */
#define BYTES_PER_XDR_UNIT   (4)
#define RNDUP(x)  ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
          * BYTES_PER_XDR_UNIT)

/*
 * The XDR handle.
 * Contains operation which is being applied to the stream,
 * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
 * and two private fields for the use of the particular impelementation.
 */

typedef struct xdr_tag XDR;
struct xdr_tag {
   enum xdr_op   x_op;      /* operation; fast additional param */
   struct xdr_ops {
      bool_t   (N_API *x_getlong)(XDR FAR *, caddr_t);      /* get a long from underlying stream */
      bool_t   (N_API *x_putlong)(XDR FAR *, caddr_t);      /* put a long to " */
      bool_t   (N_API *x_getbytes)(XDR FAR *, caddr_t, int);   /* get some bytes from " */
      bool_t   (N_API *x_putbytes)(XDR FAR *, caddr_t, int);   /* put some bytes to " */
      unsigned int (N_API *x_getpostn)(XDR FAR *);      /* returns bytes off from beginning */
      bool_t  (N_API *x_setpostn)(XDR FAR *, unsigned int);   /* lets you reposition the stream */
      long FAR * (N_API *x_inline)(XDR FAR *, int);      /* buf quick ptr to buffered data */
      void   (N_API *x_destroy)(XDR FAR *);         /* free privates of this xdr_stream */
   } FAR *x_ops;
   caddr_t    x_public;   /* users' data */
   caddr_t      x_private;   /* pointer to private data */
   caddr_t    x_base;      /* private used for position info */
   int      x_handy;   /* extra private word */
} ;

/*
 * A xdrproc_t exists for each data type which is to be encoded or decoded.
 *
 * The second argument to the xdrproc_t is a pointer to an opaque pointer.
 * The opaque pointer generally points to a structure of the data type
 * to be decoded.  If this pointer is 0, then the type routines should
 * allocate dynamic storage of the appropriate size and return it.
 * bool_t   (*xdrproc_t)(XDR *, caddr_t *);
 */


typedef   bool_t (N_API *xdrproc_t)(XDR FAR *, caddr_t);

/*
 * Operations defined on a XDR handle
 *
 * XDR      *xdrs;
 * long      *longp;
 * caddr_t    addr;
 * u_int    len;
 * u_int    pos;
 */
#define XDR_GETLONG(xdrs, longp)         \
   (*(xdrs)->x_ops->x_getlong)((XDR FAR *)xdrs, (caddr_t)longp)
#define xdr_getlong(xdrs, longp)         \
   (*(xdrs)->x_ops->x_getlong)((XDR FAR *)xdrs, (caddr_t)longp)

#define XDR_PUTLONG(xdrs, longp)         \
   (*(xdrs)->x_ops->x_putlong)((XDR FAR *)xdrs, (caddr_t)longp)
#define xdr_putlong(xdrs, longp)         \
   (*(xdrs)->x_ops->x_putlong)((XDR FAR *)xdrs, (caddr_t)longp)

#define XDR_GETBYTES(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_getbytes)((XDR FAR *)xdrs, (caddr_t)addr, len)
#define xdr_getbytes(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_getbytes)((XDR FAR *)xdrs, (caddr_t)addr, len)

#define XDR_PUTBYTES(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_putbytes)((XDR FAR *)xdrs, (caddr_t)addr, len)
#define xdr_putbytes(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_putbytes)((XDR FAR *)xdrs, (caddr_t)addr, len)

#define XDR_GETPOS(xdrs)            \
   (*(xdrs)->x_ops->x_getpostn)((XDR FAR *)xdrs)
#define xdr_getpos(xdrs)            \
   (*(xdrs)->x_ops->x_getpostn)((XDR FAR *)xdrs)

#define XDR_SETPOS(xdrs, pos)            \
   (*(xdrs)->x_ops->x_setpostn)((XDR FAR *)xdrs, pos)
#define xdr_setpos(xdrs, pos)            \
   (*(xdrs)->x_ops->x_setpostn)((XDR FAR *)xdrs, pos)

#define   XDR_INLINE(xdrs, len)            \
   (*(xdrs)->x_ops->x_inline)((XDR FAR *)xdrs, len)
#define   xdr_inline(xdrs, len)            \
   (*(xdrs)->x_ops->x_inline)((XDR FAR *)xdrs, len)

#define   XDR_DESTROY(xdrs)            \
   (*(xdrs)->x_ops->x_destroy)((XDR FAR *)xdrs)
#define   xdr_destroy(xdrs) XDR_DESTROY(xdrs)

/*
 * Support struct for discriminated unions.
 * You create an array of xdrdiscrim structures, terminated with
 * a entry with a null procedure pointer.  The xdr_union routine gets
 * the discriminant value and then searches the array of structures
 * for a matching value.  If a match is found the associated xdr routine
 * is called to handle that part of the union.  If there is
 * no match, then a default routine may be called.
 * If there is no match and no default routine it is an error.
 */
#define NULL_xdrproc_t ((xdrproc_t)0)
struct xdr_discrim {
   int   value;
   xdrproc_t proc;
};

/*
 * In-line routines for fast encode/decode of primitve data types.
 * Caveat emptor: these use single memory cycles to get the
 * data from the underlying buffer, and will fail to operate
 * properly if the data is not aligned.  The standard way to use these
 * is to say:
 *   if ((buf = XDR_INLINE(xdrs, count)) == NULL)
 *      return (FALSE);
 *   <<< macro calls >>>
 * where ``count'' is the number of bytes of data occupied
 * by the primitive data types.
 *
 * N.B. and frozen for all time: each data type here uses 4 bytes
 * of external representation.
 */
#define IXDR_GET_LONG(buf)      ((long)RPCntohl((unsigned long)*(buf)++))
#define IXDR_PUT_LONG(buf, v)      (*(buf)++ = (long)RPChtonl((unsigned long)v))

#define IXDR_GET_BOOL(buf)      ((bool_t)IXDR_GET_LONG(buf))
#define IXDR_GET_ENUM(buf, t)      ((t)IXDR_GET_LONG(buf))
#define IXDR_GET_U_LONG(buf)      ((unsigned long)IXDR_GET_LONG(buf))
#define IXDR_GET_SHORT(buf)      ((short)IXDR_GET_LONG(buf))
#define IXDR_GET_U_SHORT(buf)      ((unsigned short)IXDR_GET_LONG(buf))

#define IXDR_PUT_BOOL(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_ENUM(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_U_LONG(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_SHORT(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_U_SHORT(buf, v)   IXDR_PUT_LONG((buf), ((long)(v)))

/*
 * These are the "generic" xdr routines.
 */

extern void N_API 
xdr_free(xdrproc_t,caddr_t);

extern int N_API 
xdr_void(XDR FAR *,int FAR *);

extern int N_API 
xdr_int(XDR FAR *,int FAR *);

extern int N_API 
xdr_u_int(XDR FAR *,unsigned int FAR *);

extern int N_API 
xdr_long(XDR FAR *,long FAR *);

extern int N_API 
xdr_u_long(XDR FAR *,unsigned long FAR *);

extern int N_API 
xdr_short(XDR FAR *,short FAR *);

extern int N_API 
xdr_u_short(XDR FAR *,unsigned short FAR *);

extern int N_API 
xdr_char(XDR FAR *,char FAR *);

extern int N_API 
xdr_u_char(XDR FAR *,unsigned char FAR *);

extern int N_API 
xdr_bool(XDR FAR *,int FAR *);

extern int N_API 
xdr_enum(XDR FAR *,int FAR *);

extern int N_API 
xdr_opaque(XDR FAR *,caddr_t,unsigned int);

extern int N_API 
xdr_bytes(XDR FAR *,char FAR * FAR *,unsigned int FAR *,unsigned int);

extern int N_API 
xdr_netobj(XDR FAR *,struct netobj FAR *);

extern int N_API 
xdr_union(XDR FAR *,int FAR *,char FAR *,struct xdr_discrim FAR *,xdrproc_t);

extern int N_API 
xdr_string(XDR FAR *,char FAR * FAR *,unsigned int);

extern int N_API 
xdr_wrapstring(XDR FAR *,char FAR * FAR *);

extern int N_API 
xdr_float(XDR FAR *,float FAR *);

extern int N_API 
xdr_double(XDR FAR *,double FAR *);

extern int N_API 
xdr_array(XDR FAR *,caddr_t FAR *,unsigned int FAR *,unsigned int, unsigned int,xdrproc_t);

extern int N_API 
xdr_vector(XDR FAR *,char FAR *,unsigned int,unsigned int,xdrproc_t);

extern int N_API 
xdr_reference(XDR FAR *,caddr_t FAR *,unsigned int,xdrproc_t);

extern int N_API 
xdr_pointer(XDR FAR *,char FAR * FAR *,unsigned int,xdrproc_t);

/*
 * Common opaque bytes objects used by many rpc protocols;
 * declared here due to commonality.
 */
#define MAX_NETOBJ_SZ 1024 
struct netobj {
   unsigned int   n_len;
   char   FAR *n_bytes;
};
typedef struct netobj netobj;

/*
 * These are the public routines for the various implementations of
 * xdr streams.
 */

extern void N_API
xdrmem_create(XDR FAR *,caddr_t ,unsigned int ,enum xdr_op );

extern bool_t N_API
xdrstdio_create(XDR FAR *,caddr_t,enum xdr_op );

extern void N_API
xdrstdio_close(XDR FAR *);

extern bool_t N_API
win_xdrstdio_create(XDR FAR *,caddr_t,enum xdr_op );

extern void N_API
xdrrec_create(XDR FAR *,unsigned int,unsigned int,caddr_t, int (FAR *)(),int (FAR *)());

extern bool_t N_API
xdrrec_endofrecord(XDR FAR *,bool_t);   /* make end of xdr record */

extern bool_t N_API
xdrrec_skiprecord(XDR FAR *);    /* move to beginning of next record */

extern bool_t N_API
xdrrec_eof(XDR FAR *);      /* true if no more input */

#endif /* NWWIN */


#if defined(NWNLM) || defined(N_PLAT_NLM) || defined(N_PLAT_NIOS)

#if !defined(N_PLAT_NIOS)
#ifndef _STDIO_H_INCLUDED
#include <stdio.h>
#endif
#else
#include <ndpsclib.h>
#endif

#ifndef _RPC_TYPES_H
#include <rpc/types.h>
#endif

#ifndef _RPC_NETCVT_H
#include <rpc/netcvt.h>
#endif

#if defined(N_PLAT_NIOS)
#include <nios.h>
#endif

/*
 * XDR provides a conventional way for converting between C data
 * types and an external bit-string representation.  Library supplied
 * routines provide for the conversion on built-in C data types.  These
 * routines and utility routines defined here are used to help implement
 * a type encode/decode routine for each user-defined type.
 *
 * Each data type provides a single procedure which takes two arguments:
 *
 *   bool_t
 *   xdrproc(xdrs, argresp)
 *      XDR *xdrs;
 *      <type> *argresp;
 *
 * xdrs is an instance of a XDR handle, to which or from which the data
 * type is to be converted.  argresp is a pointer to the structure to be
 * converted.  The XDR handle contains an operation field which indicates
 * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
 *
 * XDR_DECODE may allocate space if the pointer argresp is null.  This
 * data can be freed with the XDR_FREE operation.
 *
 * We write only one procedure per data type to make it easy
 * to keep the encode and decode procedures for a data type consistent.
 * In many cases the same code performs all operations on a user defined type,
 * because all the hard work is done in the component type routines.
 * decode as a series of calls on the nested data types.
 */

/*
 * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
 * stream.  XDR_DECODE causes the type to be extracted from the stream.
 * XDR_FREE can be used to release the space allocated by an XDR_DECODE
 * request.
 */
enum xdr_op
{
   XDR_ENCODE=0,
   XDR_DECODE=1,
   XDR_FREE=2
};

/*
 * This is the number of bytes per unit of external data.
 */
#define BYTES_PER_XDR_UNIT   (4)
#define RNDDOWN(x)   ((x) & ~(BYTES_PER_XDR_UNIT - 1))
#define RNDUP(x)  (RNDDOWN((x) + BYTES_PER_XDR_UNIT - 1))

/*
 * Threshold size for bcopy avoidence hack in xdrXXX_putbytes().
 *
 * The number of bytes to look for in the buffer is determined by
 * comparing the cost of bcopy with the cost of a write system call
 * times 3. The reason for this is that each write here could cause
 * another write of the previous buffer and record header, plus at least one
 * following write of four bytes for the record terminator.
 */
#define BIGBLKSZ   1500

/*
 * A xdrproc_t exists for each data type which is to be encoded or decoded.
 *
 * The second argument to the xdrproc_t is a pointer to an opaque pointer.
 * The opaque pointer generally points to a structure of the data type
 * to be decoded.  If this pointer is 0, then the type routines should
 * allocate dynamic storage of the appropriate size and return it.
 * bool_t   (*xdrproc_t)(XDR *, caddr_t *);
 */


typedef   bool_t (*xdrproc_t)();

/*
 * The XDR handle.
 * Contains operation which is being applied to the stream,
 * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
 * and two private fields for the use of the particular impelementation.
 */
typedef struct XDR {
   enum xdr_op   x_op;      /* operation; fast additional param */
   struct xdr_ops {
      bool_t   (*x_getlong)();   /* get a long from underlying stream */
      bool_t   (*x_putlong)();   /* put a long to " */
      bool_t   (*x_getbytes)();/* get some bytes from " */
      bool_t   (*x_putbytes)();/* put some bytes to " */
      unsigned int (*x_getpostn)();/* returns bytes off from start */
      bool_t  (*x_setpostn)();/* lets you reposition the stream */
      long *   (*x_inline)();   /* buf quick ptr to buffered data */
      void   (*x_destroy)();   /* free privates of this xdr_stream */
   } *x_ops;
   caddr_t    x_public;   /* users' data */
   caddr_t      x_private;   /* pointer to private data */
   caddr_t    x_base;      /* private used for position info */
   int      x_handy;   /* extra private word */
} XDR;

/*
 * Operations defined on a XDR handle
 *
 * XDR      *xdrs;
 * long      *longp;
 * caddr_t    addr;
 * u_int    len;
 * u_int    pos;
 */
#define XDR_GETLONG(xdrs, longp)         \
   (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
#define xdr_getlong(xdrs, longp)         \
   (*(xdrs)->x_ops->x_getlong)(xdrs, longp)

#define XDR_PUTLONG(xdrs, longp)         \
   (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
#define xdr_putlong(xdrs, longp)         \
   (*(xdrs)->x_ops->x_putlong)(xdrs, longp)

#define XDR_GETBYTES(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
#define xdr_getbytes(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)

#define XDR_PUTBYTES(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
#define xdr_putbytes(xdrs, addr, len)         \
   (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)

#define XDR_GETPOS(xdrs)            \
   (*(xdrs)->x_ops->x_getpostn)(xdrs)
#define xdr_getpos(xdrs)            \
   (*(xdrs)->x_ops->x_getpostn)(xdrs)

#define XDR_SETPOS(xdrs, pos)            \
   (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
#define xdr_setpos(xdrs, pos)            \
   (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)

#define   XDR_INLINE(xdrs, len)            \
   (*(xdrs)->x_ops->x_inline)(xdrs, len)
#define   xdr_inline(xdrs, len)            \
   (*(xdrs)->x_ops->x_inline)(xdrs, len)

#define   XDR_DESTROY(xdrs)            \
   (*(xdrs)->x_ops->x_destroy)(xdrs)
#define   xdr_destroy(xdrs) XDR_DESTROY(xdrs)

/*
 * Support struct for discriminated unions.
 * You create an array of xdrdiscrim structures, terminated with
 * a entry with a null procedure pointer.  The xdr_union routine gets
 * the discriminant value and then searches the array of structures
 * for a matching value.  If a match is found the associated xdr routine
 * is called to handle that part of the union.  If there is
 * no match, then a default routine may be called.
 * If there is no match and no default routine it is an error.
 */
#define NULL_xdrproc_t ((xdrproc_t)0)
struct xdr_discrim {
   int   value;
   xdrproc_t proc;
};

/*
 * In-line routines for fast encode/decode of primitve data types.
 * Caveat emptor: these use single memory cycles to get the
 * data from the underlying buffer, and will fail to operate
 * properly if the data is not aligned.  The standard way to use these
 * is to say:
 *   if ((buf = XDR_INLINE(xdrs, count)) == NULL)
 *      return (FALSE);
 *   <<< macro calls >>>
 * where ``count'' is the number of bytes of data occupied
 * by the primitive data types.
 *
 * N.B. and frozen for all time: each data type here uses 4 bytes
 * of external representation.
 */
#define IXDR_GET_LONG(buf)      ((long)ntohl((unsigned long)*(buf)++))
#define IXDR_PUT_LONG(buf, v)      (*(buf)++ = (long)htonl((unsigned long)v))

#define IXDR_GET_BOOL(buf)      ((bool_t)IXDR_GET_LONG(buf))
#define IXDR_GET_ENUM(buf, t)      ((t)IXDR_GET_LONG(buf))
#define IXDR_GET_U_LONG(buf)      ((unsigned long)IXDR_GET_LONG(buf))
#define IXDR_GET_SHORT(buf)      ((short)IXDR_GET_LONG(buf))
#define IXDR_GET_U_SHORT(buf)      ((unsigned short)IXDR_GET_LONG(buf))

#define IXDR_PUT_BOOL(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_ENUM(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_U_LONG(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_SHORT(buf, v)      IXDR_PUT_LONG((buf), ((long)(v)))
#define IXDR_PUT_U_SHORT(buf, v)   IXDR_PUT_LONG((buf), ((long)(v)))

/*
 * These are the "generic" xdr routines.
 */
extern void xdr_free(xdrproc_t,caddr_t);
extern int xdr_void(XDR *xdrs, caddr_t addr);
extern int xdr_int(XDR *,int *);
extern int xdr_u_int(XDR *,unsigned int *);
extern int xdr_long(XDR *,long *);
extern int xdr_u_long(XDR *,unsigned long *);
extern int xdr_short(XDR *,short *);
extern int xdr_u_short(XDR *,unsigned short *);
extern int xdr_char(XDR *,char *);
extern int xdr_u_char(XDR *,char *);
extern int xdr_bool(XDR *,int *);
extern int xdr_enum(XDR *,int *);
extern int xdr_opaque(XDR *,caddr_t,unsigned int);
extern int xdr_bytes(XDR *,char **,unsigned int *,unsigned int);
extern int xdr_union(XDR *,int *,char *,struct xdr_discrim *,xdrproc_t);
extern int xdr_string(XDR *,char **,unsigned int);
extern int xdr_fast_string(XDR *, char **, u_int, u_int);
extern int xdr_wrapstring(XDR *,char **);
extern int xdr_float(XDR *,float *);
extern int xdr_double(XDR *,double *);
extern int xdr_array(XDR *,caddr_t *,unsigned int *,unsigned int,\
                     unsigned int,xdrproc_t);
extern int xdr_vector(XDR *,char *,unsigned int,unsigned int,xdrproc_t);
extern int xdr_reference(XDR *,caddr_t *,unsigned int,xdrproc_t);
#define xdr_fast_reference(xdrs, cpp, proc) (*proc)(xdrs, cpp, (u_int)0 - 1)
extern int xdr_pointer(XDR *,char **,unsigned int,xdrproc_t);
extern int xdr_fast_pointer(XDR *, char **, xdrproc_t);

/*
 * Common opaque bytes objects used by many rpc protocols;
 * declared here due to commonality.
 */
#define MAX_NETOBJ_SZ 1024 
struct netobj {
   unsigned int   n_len;
   char   *n_bytes;
};
typedef struct netobj netobj;
extern bool_t xdr_netobj(XDR *, struct netobj *);

/*
 * These are the public routines for the various implementations of
 * xdr streams.
 */
/* XDR using memory buffers */
extern void xdrmem_create(XDR *, caddr_t, unsigned int, int);

/* XDR using stdio library */
extern void xdrstdio_create(XDR *, FILE *, enum xdr_op);

/* XDR pseudo records for transport */
extern bool_t xdrrec_create(XDR *, unsigned int, unsigned int, caddr_t,\
                          int (*)(), int (*)());

extern bool_t xdrrec_endofrecord(XDR *,bool_t);   /* make end of xdr record */
extern bool_t xdrrec_skiprecord(XDR *);    /* move to start of next rec */
extern bool_t xdrrec_eof(XDR *);      /* true if no more input */

/* New Legato XDR routines */
extern void xdrcount_create(XDR *, u_long *);
               /* XDR byte counter */
extern bool_t xdrfr_create(XDR *, char *(*)(), char *(*)(), bool_t);
               /* XDR using "fixed records" */
extern bool_t xdrfd_create(XDR *, int, enum xdr_op);
               /* XDR using open file descriptor */
extern bool_t xdrpipe_create(XDR *, int, enum xdr_op);
               /* XDR using pipes descriptor */
extern void xdrpipe_setup(int (*)(), int (*)(), int (*)());
               /* set up pipes */
extern void xdrpipe_destroy(XDR *, bool_t);
               /* destroy pipes */
extern bool_t xdrrec_flush(XDR *);   /* flush data w/o creating record */
extern bool_t xdr_flush(XDR *);      /* flush any buffered data */

extern int xdrfr_refill(XDR *);
extern int xdrfr_flush(XDR *);
extern int xdrfr_remaining(XDR *);
extern void xdr_free_pointer(xdrproc_t ,caddr_t);   /* free pointer too */
extern bool_t xdrrec_splice(XDR *, XDR *, u_int);

#endif /* NWNLM */ /* N_PLAT_NLM */ /* N_PLAT_NIOS */


#endif /* _RPC_XDR_H */