/* (C) Copyright International Business Machines Corporation 23 January */
/* 1990.  All Rights Reserved. */
/*  */
/* See the file USERAGREEMENT distributed with this software for full */
/* terms and conditions of use. */
#ifndef lint
static char sccsinfo[] = "@(#)xdr.c	1.10 3/14/90";
#endif

#ifdef _AIX
#  include <sys/types.h>
#  include <sys/select.h>
#endif
#include <rpc/rpc.h>

#include "ops.h"
#include "recursiv.h"
#include "storage.h"

#include "accessors.h"

#define XDRBUFSIZE 1024

#define VARIANT_LENGTH (sizeof(dot_info) + sizeof(object))
#define PROGRAM_LENGTH (sizeof(dot_info) + (PROGRAM_SIZE * sizeof(object)))

/*ARGSUSED*/
xdr_status
hxdr_bottom(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    return(xdr_void());
}


/*ARGSUSED*/
xdr_status
hxdr_noop(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    nilerror("hxdr_noop", "HXDR for this datatype unimplemented");
    return(XDR_FAIL);
}


#define xdr_enumval xdr_u_int

xdr_status
hxdr_enumeration(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    xdr_status xdr_enumval();

    return(xdr_enumval(xdrs, & valp->enumeration));
}


xdr_status
hxdr_boolean(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    xdr_status myxdr_boolean();

    return(myxdr_boolean(xdrs, & valp->boolean));
}


xdr_status
myxdr_boolean(xdrs, boolp)
XDR *xdrs;
flag *boolp;
{
    flag num;

    if (xdrs->x_op is XDR_ENCODE)
      num = (*boolp) ? 1 : 0;

    if (!xdr_short(xdrs, &num))
      return(XDR_FAIL);

    if (xdrs->x_op is XDR_DECODE)
      if (num isnt 0 and num isnt 1)
	return(XDR_FAIL);
      else
	*boolp = (num is 1) ? nil_true : nil_false;

    return(XDR_OK);
}




xdr_status
hxdr_integer(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    return(xdr_int(xdrs, &(valp->integer)));
}


xdr_status
hxdr_nominal(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    xdr_status xdr_nominal_struct();

    if (xdrs->x_op is XDR_DECODE)
      if ((valp->nominal = new(dfd_nominal)) is nil)
	return(XDR_FAIL);
      else
	valp->nominal->refcount = 1;

    if (!xdr_long(xdrs, &valp->nominal->time))
      return(XDR_FAIL);
    if (!xdr_u_int(xdrs, &valp->nominal->num))
      return(XDR_FAIL);
#ifdef DISTRIBUTED
    {
	int size = HOSTIDSIZE;
	char *hostid = valp->nominal->hostid;
	if (!xdr_bytes(xdrs, &hostid, &size, HOSTIDSIZE))
	  return(XDR_FAIL);
    }
#endif

    if (xdrs->x_op is XDR_FREE) {
	if (valp->nominal isnt nil)
	  { dispose(valp->nominal, dfd_nominal); }
	valp->nominal = nil;
    }

    return(XDR_OK);
}


status
hxdr_record(xdrs, recordp)
XDR *xdrs;
valcell *recordp;
{
    dfd_record *new_record();

    counter size, i;

    switch (xdrs->x_op) {
      case XDR_ENCODE:
	size = recordp->record->info.record_size;
	break;
      case XDR_DECODE:
	recordp->record = nil;
	break;
      case XDR_FREE:
	if (recordp->record is nil)
	  return(XDR_OK);
	size = recordp->record->info.record_size;
	break;
    }

    if (!xdr_u_int(xdrs, &size))
      return(XDR_FAIL);

    if (xdrs->x_op is XDR_DECODE)
      if ((recordp->record = new_record(size)) is nil)
	return(XDR_FAIL);

    for (i = 0; i < size; i++)
      if (not hxdr_object(xdrs, & recordp->record->data[i]))
	return(XDR_FAIL);

    if (xdrs->x_op is XDR_FREE)
      { freedotmain(recordp->record, size); }

    return(XDR_OK);
}


xdr_status
hxdr_variant(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    xdr_status xdr_enumval();

    if (xdrs->x_op is XDR_DECODE)
      if ((valp->variant = (dfd_variant *) getdotmain(VARIANT_SIZE)) is nil)
	return(XDR_FAIL);

    if (xdrs->x_op is XDR_FREE)
      if (valp->variant is nil)
	return(XDR_OK);

    if (!xdr_enumval(xdrs, &valp->variant->info.variant_case))
      return(XDR_FAIL);

    if (!hxdr_object(xdrs, &valp->variant->data[VARIANT_COMPONENT]))
      return(XDR_FAIL);

    if (xdrs->x_op is XDR_FREE)
      { freedotmain(valp->variant, VARIANT_SIZE); }

    return(XDR_OK);
}


status
hxdr_program(xdrs, valp)
XDR *xdrs;
valcell *valp;
{
    int i;

    if (xdrs->x_op is XDR_DECODE)
      if ((valp->program = (pd_program *) getdotmain(PROGRAM_SIZE)) is nil)
	return(XDR_FAIL);

    if (xdrs->x_op is XDR_FREE)
      if (valp->program is nil)
	return(XDR_OK);

    for (i = 0; i < PROGRAM_SIZE; i++)
      if (!hxdr_object(xdrs, &valp->program->data[i]))
	return(XDR_FAIL);
    
    if (xdrs->x_op is XDR_DECODE)
      valp->program->info.program_refcount = 1;

    if (xdrs->x_op is XDR_FREE)
      { freedotmain(valp->program, PROGRAM_SIZE); }

    return(XDR_OK);
}



xdr_status
hxdr_polymorph(xdrs, poly)
XDR *xdrs;
valcell *poly;
{
    if (xdrs->x_op is XDR_DECODE) {
	poly->polymorph = new(dfd_polymorph);
	if (poly->polymorph is nil)
	  return(XDR_FAIL);
	set_bottom(& poly->polymorph->typename);
	set_bottom(& poly->polymorph->typestate);
    }

    if (hxdr_object(xdrs, & poly->polymorph->obj) is XDR_OK)
      return(XDR_OK);

    if (xdrs->x_op is XDR_DECODE)
      dispose(poly->polymorph, dfd_polymorph);
    return(XDR_FAIL);    
}
