
/*
 *         PVM version 3.3:  Parallel Virtual Machine System
 *               University of Tennessee, Knoxville TN.
 *           Oak Ridge National Laboratory, Oak Ridge TN.
 *                   Emory University, Atlanta GA.
 *      Authors:  A. L. Beguelin, J. J. Dongarra, G. A. Geist,
 *    W. C. Jiang, R. J. Manchek, B. K. Moore, and V. S. Sunderam
 *                   (C) 1992 All Rights Reserved
 *
 *                              NOTICE
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted
 * provided that the above copyright notice appear in all copies and
 * that both the copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * Neither the Institutions (Emory University, Oak Ridge National
 * Laboratory, and University of Tennessee) nor the Authors make any
 * representations about the suitability of this software for any
 * purpose.  This software is provided ``as is'' without express or
 * implied warranty.
 *
 * PVM version 3 was funded in part by the U.S. Department of Energy,
 * the National Science Foundation and the State of Tennessee.
 */

/*
 *	lpvmpack.c
 *
 *	Typed packing/unpacking, message buffer manip.
 *
$Log: lpvmpack.c,v $
 * Revision 1.5  1994/11/09  15:01:58  manchek
 * pvm_pkstr and pvm_packf(%s) must fail with PvmNotImpl if PvmDataInPlace
 * is used.
 *
 * Revision 1.4  1994/06/03  21:15:12  manchek
 * oops, missed a bcopy
 *
 * Revision 1.3  1994/06/03  20:38:17  manchek
 * version 3.3.0
 *
 * Revision 1.2  1993/10/04  19:20:22  manchek
 * fixed vpackf() - floats get passed as doubles, must unpack that way
 *
 * Revision 1.1  1993/08/30  23:26:48  manchek
 * Initial revision
 *
 */

#include <stdio.h>
#ifdef IMA_BSD386
#include <machine/endian.h>
#endif
#ifdef IMA_LINUX
#include <endian.h>
#endif
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <ctype.h>
#ifdef	__STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <pvm3.h>
#include "global.h"
#include "tdpro.h"
#include "ddpro.h"
#include "pvmfrag.h"
#include "pvmumbuf.h"
#include "listmac.h"
#include "bfunc.h"
#include <pvmtev.h>
#include "tevmac.h"


/***************
 **  Globals  **
 **           **
 ***************/

extern int pvmfrgsiz;					/* from lpvm.c */
extern struct mhp *pvmmidh;				/* from pvmumbuf.c */
extern int pvmmidhsiz;					/* from pvmumbuf.c */
extern int pvmmyndf;					/* from lpvm.c */
extern int pvmmytid;					/* from lpvm.c */
extern int pvmtoplvl;					/* from lpvm.c */
extern Pvmtmask pvmtrcmask;				/* from lpvm.c */
extern int pvmtrctid;					/* from lpvm.c */
extern int pvmudpmtu;					/* from lpvm.c */

int pvmrbufmid = 0;						/* current recv/unpack mid */
int pvmsbufmid = 0;						/* current send/pack mid */


/***************
 **  Private  **
 **           **
 ***************/

static char rcsid[] = "$Id: lpvmpack.c,v 1.5 1994/11/09 15:01:58 manchek Exp $";
static char pvmtxt[512];				/* scratch for error log */


/***************************
 **  Raw-format encoders  **
 **                       **
 ***************************/

/*	bytepk()
*
*	Insert a stream of bytes into sbuf.  Allocate more fragments as
*	necessary.
*	Returns 0 else PvmNoMem if malloc fails.
*/

static int
bytepk(cp, num, siz, lnc)
	char *cp;	/* base of data */
	int num;	/* num of chunks */
	int siz;	/* size of chunk */
	int lnc;	/* lead to next chunk */
{
	struct umbuf *up = midtobuf(pvmsbufmid);	/* working message */
	struct frag *fp;			/* working frag */
	int togo;					/* bytes left in chunk */
	int r;						/* bytes (space) left in frag */

	if (siz == lnc) {		/* if contiguous, treat as single chunk */
		lnc = (siz *= num);
		num = 1;
	}
	lnc -= siz;		/* now bytes between chunks */

	while (num-- > 0) {		/* copy chunks until done */

		for (togo = siz; togo > 0; ) {
			fp = up->ub_frag->fr_rlink;
			r = fp->fr_max - (fp->fr_dat - fp->fr_buf) - fp->fr_len;

			if (togo <= r) {	/* space in frag for entire chunk */
				BCOPY(cp, fp->fr_dat + fp->fr_len, togo);
				fp->fr_len += togo;
				cp += togo;
				togo = 0;

			} else {
				if (r > 0) {	/* space for part of chunk */
					BCOPY(cp, fp->fr_dat + fp->fr_len, r);
					fp->fr_len += r;
					togo -= r;
					cp += r;

				} else {		/* no space, add new frag */
					if (r = enc_step(up))
						return r;
				}
			}
		}
		cp += lnc;
	}
	return 0;
}


/*	byteupk()
*
*	Extract bytes from rbuf, continuing to new fragments as necessary.
*	Returns 0 else PvmNoData if end of message reached early.
*/

static int
byteupk(cp, num, siz, lnc)
	char *cp;	/* base of data */
	int num;	/* num of chunks */
	int siz;	/* size of chunk */
	int lnc;	/* lead to next chunk */
{
	struct umbuf *up = midtobuf(pvmrbufmid);	/* working message */
	struct frag *fp;			/* working frag */
	int togo;					/* bytes left in chunk */
	int r;						/* bytes (data) left in frag */

	if (siz == lnc) {		/* if contiguous, treat as single chunk */
		lnc = (siz *= num);
		num = 1;
	}
	lnc -= siz;		/* now bytes between chunks */

	while (num-- > 0) {		/* copy chunks until done */

		for (togo = siz; togo > 0; ) {
			fp = up->ub_cfrag;
			r = fp->fr_len - up->ub_cpos;

			if (togo <= r) {	/* frag contains rest of chunk */
				BCOPY(fp->fr_dat + up->ub_cpos, cp, togo);
				up->ub_cpos += togo;
				cp += togo;
				togo = 0;

			} else {
				if (r > 0) {	/* frag contains part of chunk */
					BCOPY(fp->fr_dat + up->ub_cpos, cp, r);
					up->ub_cpos += r;
					togo -= r;
					cp += r;

				} else {		/* no space, add new frag */
					if (r = dec_step(up))
						return r;
				}
			}
		}
		cp += lnc;
	}
	return 0;
}


/*	enc_raw_init()
*
*	Initialize a message buffer to pack raw data.
*/

static int
enc_raw_init()
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	struct frag *fp;

	fp = fr_new(pvmfrgsiz);			/* make a blank frag to write in */
	fp->fr_dat += MAXHDR;
	LISTPUTBEFORE(up->ub_frag, fp, fr_link, fr_rlink);
	return 0;
}


/*	dec_raw_init()
*
*	Initialize a message buffer to unpack raw data.
*/

static int
dec_raw_init()
{
	struct umbuf *up = midtobuf(pvmrbufmid);

	up->ub_cfrag = up->ub_frag->fr_link;
	up->ub_cpos = 0;
	return 0;
}


/*	enc_raw_any()
*
*	Encode any data type into a raw format message buffer.
*/

static int
enc_raw_any(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	return bytepk((char*)vp, cnt, siz, std * siz);
}


/*	dec_raw_any()
*
*	Decode any data type from a raw format message buffer.
*/

static int
dec_raw_any(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	return byteupk((char*)vp, cnt, siz, std * siz);
}


/***************************
 **  XDR-format encoders  **
 **                       **
 ***************************/

#ifdef FAKEXDRFLOAT

/*
** These two are missing on some machines.
*/

int
xdr_float(xdrp, fp)
	XDR *xdrp;
	float *fp;
{
	return xdr_long(xdrp, (long*)fp);
}


int
xdr_double(xdrp, dp)
	XDR *xdrp;
	double *dp;
{
	return xdr_long(xdrp, (long*)dp + 1) && xdr_long(xdrp, (long*)dp);
}

#endif/*FAKEXDRFLOAT*/

#if	defined(I860_NODE)

/*
** Encoders for machines without XDR routines but with XDR-format
** data.
*/

static int
enc_xdr_init()
{
    return enc_raw_init();
}

static int
enc_xdr_byte(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	struct frag *fp;
	int cc;

	fp = up->ub_frag->fr_rlink;
	if (cc = bytepk((char*)vp, cnt, siz, std * siz))
		return cc;
	fp->fr_len = (fp->fr_len + 3) & ~3;
	return 0;
}

static int
enc_xdr_short(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register short *np;
    register char *cp;
    char     buf[2];
    int cc = 0;

    for (np = (short*)vp; cnt-- > 0; np += std) {
        cp = (char *)np;
        buf[1] = *cp;
        buf[0] = *(cp+1);
        if (cc = bytepk(buf, 2, 1, 1))
            return cc;
    }
    return 0;
}

static int
enc_xdr_int(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register int *np;
    register char *cp;
    char     buf[4];
    int cc = 0;

    for (np = (int *)vp; cnt-- > 0; np += std) {
        cp = (char *)np;
        buf[3] = *cp;
        buf[2] = *(cp+1);
        buf[1] = *(cp+2);
        buf[0] = *(cp+3);
        if (cc = bytepk(buf, 4, 1, 1))
            return cc;
    }
    return 0;
}

static int
enc_xdr_long(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register long *np;
    register char *cp;
    char     buf[4];
    int cc = 0;

    for (np = (long *)vp; cnt-- > 0; np += std) {
        cp = (char *)np;
        buf[3] = *cp;
        buf[2] = *(cp+1);
        buf[1] = *(cp+2);
        buf[0] = *(cp+3);
        if (cc = bytepk(buf, 4, 1, 1))
            return cc;
    }
    return 0;
}

static int
enc_xdr_float(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register float *np;
    register char *cp;
    char     buf[4];
    int cc = 0;

    for (np = (float *)vp; cnt-- > 0; np += std) {
        cp = (char *)np;
        buf[3] = *cp;
        buf[2] = *(cp+1);
        buf[1] = *(cp+2);
        buf[0] = *(cp+3);
        if (cc = bytepk(buf, 4, 1, 1))
            return cc;
    }
    return 0;
}

static int
enc_xdr_double(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register double *np;
    register char *cp;
    char     buf[8];
    int cc = 0;

    for (np = (double *)vp; cnt-- > 0; np += std) {
        cp = (char *)np;
        buf[7] = *cp;
        buf[6] = *(cp+1);
        buf[5] = *(cp+2);
        buf[4] = *(cp+3);
        buf[3] = *(cp+4);
        buf[2] = *(cp+5);
        buf[1] = *(cp+6);
        buf[0] = *(cp+7);
        if (cc = bytepk(buf, 8, 1, 1))
            return cc;
    }
    return 0;
}

typedef struct {float r, i;} complex;
typedef struct {double r, i;} dcplx;

static int
enc_xdr_cplx(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register complex *np;
    register char *cp;
    char buf[8];
    int cc = 0;

    for (np = (complex *)vp; cnt-- > 0; np += std) {
        cp = (char *)np;
        buf[3] = *cp;
        buf[2] = *(cp+1);
        buf[1] = *(cp+2);
        buf[0] = *(cp+3);
        buf[7] = *(cp+4);
        buf[6] = *(cp+5);
        buf[5] = *(cp+6);
        buf[4] = *(cp+7);
        if (cc = bytepk(buf, 8, 1, 1))
            return cc;
    }
    return 0;
}

static int
enc_xdr_dcplx(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register dcplx *np;
    register char *cp;
    char buf[16];
    int cc = 0;

    for (np = (dcplx *)vp; cnt-- > 0; np += std) {
        cp = (char *)np;
        buf[7] = *cp;
        buf[6] = *(cp+1);
        buf[5] = *(cp+2);
        buf[4] = *(cp+3);
        buf[3] = *(cp+4);
        buf[2] = *(cp+5);
        buf[1] = *(cp+6);
        buf[0] = *(cp+7);
        buf[15] = *(cp+8);
        buf[14] = *(cp+9);
        buf[13] = *(cp+10);
        buf[12] = *(cp+11);
        buf[11] = *(cp+12);
        buf[10] = *(cp+13);
        buf[9] = *(cp+14);
        buf[8] = *(cp+15);
        if (cc = bytepk(buf, 16, 1, 1))
            return cc;
    }
    return 0;
}

static int
dec_xdr_init()
{
    struct umbuf *up = midtobuf(pvmrbufmid);

    up->ub_cfrag = up->ub_frag->fr_link;
    up->ub_cpos = 0;
    return 0;
}

static int
dec_xdr_byte(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	struct frag *fp;
	int cc;

	fp = up->ub_cfrag;
	if (cc = byteupk((char*)vp, cnt, siz, std * siz))
		return cc;
	up->ub_cpos = (up->ub_cpos + 3) & ~3;
	return 0;
}

static int
dec_xdr_short(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register short *np;
    register char *cp;
    char     buf[2];
    int cc = 0;

    for (np = (short*)vp; cnt-- > 0; np += std) {
        if (cc = byteupk(buf, 2, 1, 1))
            return cc;
        cp = (char *)np;
        *cp = buf[1];
        *(cp+1) = buf[0];
    }
    return 0;
}

static int
dec_xdr_int(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register int *np;
    register char *cp;
    char     buf[4];
    int cc = 0;

    for (np = (int *)vp; cnt-- > 0; np += std) {
        if (cc = byteupk(buf, 4, 1, 1))
            return cc;
        cp = (char *)np;
        *cp = buf[3];
        *(cp+1) = buf[2];
        *(cp+2) = buf[1];
        *(cp+3) = buf[0];
    }
    return 0;
}

static int
dec_xdr_long(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register long *np;
    register char *cp;
    char     buf[4];
    int cc = 0;

    for (np = (long *)vp; cnt-- > 0; np += std) {
        if (cc = byteupk(buf, 4, 1, 1))
            return cc;
        cp = (char *)np;
        *cp = buf[3];
        *(cp+1) = buf[2];
        *(cp+2) = buf[1];
        *(cp+3) = buf[0];
    }
    return 0;
}

static int
dec_xdr_float(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register float *np;
    register char *cp;
    char     buf[4];
    int cc = 0;

    for (np = (float *)vp; cnt-- > 0; np += std) {
        if (cc = byteupk(buf, 4, 1, 1))
            return cc;
        cp = (char *)np;
        *cp = buf[3];
        *(cp+1) = buf[2];
        *(cp+2) = buf[1];
        *(cp+3) = buf[0];
    }
    return 0;
}

static int
dec_xdr_double(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register double *np;
    register char *cp;
    char     buf[8];
    int cc = 0;

    for (np = (double *)vp; cnt-- > 0; np += std) {
        if (cc = byteupk(buf, 8, 1, 1))
            return cc;
        cp = (char *)np;
        *cp = buf[7];
        *(cp+1) = buf[6];
        *(cp+2) = buf[5];
        *(cp+3) = buf[4];
        *(cp+4) = buf[3];
        *(cp+5) = buf[2];
        *(cp+6) = buf[1];
        *(cp+7) = buf[0];
    }
    return 0;
}

static int
dec_xdr_cplx(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register complex *np;
    register char *cp;
    char     buf[8];
    int cc = 0;

    for (np = (complex *)vp; cnt-- > 0; np += std) {
        if (cc = byteupk(buf, 8, 1, 1))
            return cc;
        cp = (char *)np;
        *cp = buf[3];
        *(cp+1) = buf[2];
        *(cp+2) = buf[1];
        *(cp+3) = buf[0];
        *(cp+4) = buf[7];
        *(cp+5) = buf[6];
        *(cp+6) = buf[5];
        *(cp+7) = buf[4];
    }
    return 0;
}

static int
dec_xdr_dcplx(vp, cnt, std, siz)
    void *vp;
    int cnt, std, siz;
{
    register dcplx *np;
    register char *cp;
    char     buf[16];
    int cc = 0;

    for (np = (dcplx *)vp; cnt-- > 0; np += std) {
        if (cc = byteupk(buf, 16, 1, 1))
            return cc;
        cp = (char *)np;
        *cp     = buf[7];
        *(cp+1) = buf[6];
        *(cp+2) = buf[5];
        *(cp+3) = buf[4];
        *(cp+4) = buf[3];
        *(cp+5) = buf[2];
        *(cp+6) = buf[1];
        *(cp+7) = buf[0];
        *(cp+8) = buf[15];
        *(cp+9) = buf[14];
        *(cp+10) = buf[13];
        *(cp+11) = buf[12];
        *(cp+12) = buf[11];
        *(cp+13) = buf[10];
        *(cp+14) = buf[9];
        *(cp+15) = buf[8];
    }
    return 0;
}

#else	/*I860_NODE*/

/*
** These are the normal XDR encoders for machines with XDR functions.
*/

/*	enc_xdr_init()
*
*	Initialize a message buffer to pack XDR format data
*/

static int
enc_xdr_init()
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	struct frag *fp;

	fp = fr_new(pvmfrgsiz);			/* make a blank frag to write in */
	fp->fr_dat += MAXHDR;
	LISTPUTBEFORE(up->ub_frag, fp, fr_link, fr_rlink);

	xdrmem_create(&up->ub_encxdr,
			fp->fr_dat,
			(unsigned)(fp->fr_max - (fp->fr_dat - fp->fr_buf)),
			XDR_ENCODE);
	return 0;
}


/*	enc_xdr_step()
*
*	Add a new fragment to an XDR format message
*/

static int
enc_xdr_step()
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	struct frag *fp;
	int cc;

	if (cc = enc_step(up))
		return cc;
	fp = up->ub_frag->fr_rlink;
	xdrmem_create(&up->ub_encxdr,
			fp->fr_dat,
			(unsigned)(fp->fr_max - (fp->fr_dat - fp->fr_buf)),
			XDR_ENCODE);
	return 0;
}


static int
enc_xdr_byte(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	struct frag *fp;
	int cc;

	fp = up->ub_frag->fr_rlink;
	if (cc = bytepk((char*)vp, cnt, 1, std))
		return cc;
	if (fp != up->ub_frag->fr_rlink) {
		fp = up->ub_frag->fr_rlink;
		xdrmem_create(&up->ub_encxdr,
				fp->fr_dat,
				(unsigned)(fp->fr_max - (fp->fr_dat - fp->fr_buf)),
				XDR_ENCODE);
	}
	fp->fr_len = (fp->fr_len + 3) & ~3;
	xdr_setpos(&up->ub_encxdr, fp->fr_len);
	return 0;
}


static int
enc_xdr_short(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	XDR *xob = &up->ub_encxdr;
	register short *np;
	int cc = 0;

	for (np = (short*)vp; cnt-- > 0; np += std)
		if (!xdr_short(xob, np)) {
			up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_short(xob, np)) {
					cc = PvmNoMem;
					break;
				}
		}
	up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
	return cc;
}


static int
enc_xdr_int(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	XDR *xob = &up->ub_encxdr;
	register int *np;
	int cc = 0;

	for (np = (int*)vp; cnt-- > 0; np += std)
		if (!xdr_int(xob, np)) {
			up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_int(xob, np)) {
					cc = PvmNoMem;
					break;
				}
		}
	up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
	return cc;
}


static int
enc_xdr_long(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	XDR *xob = &up->ub_encxdr;
	register long *np;
	int cc = 0;

	for (np = (long*)vp; cnt-- > 0; np += std)
		if (!xdr_long(xob, np)) {
			up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_long(xob, np)) {
					cc = PvmNoMem;
					break;
				}
		}
	up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
	return cc;
}


static int
enc_xdr_float(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	XDR *xob = &up->ub_encxdr;
	register float *fp;
	int cc = 0;

	for (fp = (float*)vp; cnt-- > 0; fp += std)
		if (!xdr_float(xob, fp)) {
			up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_float(xob, fp)) {
					cc = PvmNoMem;
					break;
				}
		}
	up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
	return cc;
}


static int
enc_xdr_double(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	XDR *xob = &up->ub_encxdr;
	register double *dp;
	int cc = 0;
	int n;

	for (dp = (double*)vp; cnt-- > 0; dp += std) {
		if (!xdr_double(xob, dp)) {
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_double(xob, dp)) {
					cc = PvmNoMem;
					break;
				}
		}
		up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
	}
	return cc;
}


static int
enc_xdr_cplx(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	XDR *xob = &up->ub_encxdr;
	register float *xp;
	int cc = 0;

	std = std * 2 - 1;
	for (xp = (float*)vp; cnt-- > 0; xp += std) {
		if (!xdr_float(xob, xp)) {
			up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_float(xob, xp)) {
					cc = PvmNoMem;
					break;
				}
		}
		xp++;
		if (!xdr_float(xob, xp)) {
			up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_float(xob, xp)) {
					cc = PvmNoMem;
					break;
				}
		}
	}
	up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
	return cc;
}


static int
enc_xdr_dcplx(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	XDR *xob = &up->ub_encxdr;
	register double *zp;
	int cc = 0;

	std = std * 2 - 1;
	for (zp = (double*)vp; cnt-- > 0; zp += std) {
		if (!xdr_double(xob, zp)) {
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_double(xob, zp)) {
					cc = PvmNoMem;
					break;
				}
		}
		up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
		zp++;
		if (!xdr_double(xob, zp)) {
			if (cc = enc_xdr_step())
				break;
			else
				if (!xdr_double(xob, zp)) {
					cc = PvmNoMem;
					break;
				}
		}
		up->ub_frag->fr_rlink->fr_len = xdr_getpos(xob);
	}
	return cc;
}


/*	dec_xdr_init()
*
*	Initialize a message buffer to unpack XDR format data.
*/

static int
dec_xdr_init()
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	struct frag *fp = up->ub_frag->fr_link;

	up->ub_cfrag = fp;
	up->ub_cpos = 0;
	xdrmem_create(&up->ub_decxdr, fp->fr_dat, (unsigned)(fp->fr_len),
			XDR_DECODE);
	return 0;
}


/*	dec_xdr_step()
*
*	Step to the next fragment of an XDR format message.
*
*	The current fragment might not be fully consumed - messages are
*	refragmented on 4-byte boundaries, but XDR 'atomic' sizes for
*	us are 4 bytes and 8 bytes (doubles).
*	If the next fragment exists, copy the remaining bytes to the head
*	of its buffer and continue unpacking.
*	XXX 1. There might not be enough headroom (unlikely).
*	XXX 2. If we share databufs we can't modify them (maybe?).
*/

static int
dec_xdr_step()
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	struct frag *fp;
	int cc;
	int l;
	char *p;

	if (up->ub_cpos != up->ub_cfrag->fr_len) {
		p = up->ub_cfrag->fr_dat + up->ub_cpos;
		l = up->ub_cfrag->fr_len - up->ub_cpos;

		if (cc = dec_step(up))
			return cc;

		fp = up->ub_cfrag;
		if (fp->fr_dat - fp->fr_buf < l) {
			pvmlogerror("aaugh, no space for fixup, kill me\n");
			return PvmBadMsg;

		} else {
/*
			sprintf(pvmtxt, "fragment has %d bytes left, doing fixup\n", l);
			pvmlogerror(pvmtxt);
*/
			fp->fr_dat -= l;
			fp->fr_len += l;
			BCOPY(p, fp->fr_dat, l);
		}

	} else {
		if (cc = dec_step(up))
			return cc;
		fp = up->ub_cfrag;
	}
	xdrmem_create(&up->ub_decxdr, fp->fr_dat, (unsigned)(fp->fr_len),
			XDR_DECODE);
	return 0;
}


static int
dec_xdr_byte(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	struct frag *fp;
	int cc;

	fp = up->ub_cfrag;
	if (cc = byteupk((char*)vp, cnt, 1, std))
		return cc;
	if (fp != up->ub_cfrag) {
		fp = up->ub_cfrag;
		xdrmem_create(&up->ub_decxdr, fp->fr_dat, (unsigned)(fp->fr_len),
				XDR_DECODE);
	}
	up->ub_cpos = (up->ub_cpos + 3) & ~3;
	xdr_setpos(&up->ub_decxdr, up->ub_cpos);
	return 0;
}


static int
dec_xdr_short(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register short *np;
	int cc = 0;

	for (np = (short*)vp; cnt-- > 0; np += std)
		if (!xdr_short(xob, np)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_short(xob, np)) {
					cc = PvmNoData;
					break;
				}
		}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_int(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register int *np;
	int cc = 0;

	for (np = (int*)vp; cnt-- > 0; np += std)
		if (!xdr_int(xob, np)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_int(xob, np)) {
					cc = PvmNoData;
					break;
				}
		}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_long(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register long *np;
	int cc = 0;

	for (np = (long*)vp; cnt-- > 0; np += std)
		if (!xdr_long(xob, np)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_long(xob, np)) {
					cc = PvmNoData;
					break;
				}
		}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_ushort(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register unsigned short *np;
	int cc = 0;

	for (np = (unsigned short*)vp; cnt-- > 0; np += std)
		if (!xdr_u_short(xob, np)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_u_short(xob, np)) {
					cc = PvmNoData;
					break;
				}
		}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_uint(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register unsigned int *np;
	int cc = 0;

	for (np = (unsigned int*)vp; cnt-- > 0; np += std)
		if (!xdr_u_int(xob, np)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_u_int(xob, np)) {
					cc = PvmNoData;
					break;
				}
		}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_ulong(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register unsigned long *np;
	int cc = 0;

	for (np = (unsigned long*)vp; cnt-- > 0; np += std)
		if (!xdr_u_long(xob, np)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_u_long(xob, np)) {
					cc = PvmNoData;
					break;
				}
		}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_float(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register float *fp;
	int cc = 0;

	for (fp = (float*)vp; cnt-- > 0; fp += std)
		if (!xdr_float(xob, fp)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_float(xob, fp)) {
					cc = PvmNoData;
					break;
				}
		}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_double(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register double *dp;
	int cc = 0;

	for (dp = (double*)vp; cnt-- > 0; dp += std) {
		if (!xdr_double(xob, dp)) {
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_double(xob, dp)) {
					cc = PvmNoData;
					break;
				}
		}
		up->ub_cpos = xdr_getpos(xob);
	}
	return cc;
}


static int
dec_xdr_cplx(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register float *xp;
	int cc = 0;

	std = std * 2 - 1;
	for (xp = (float*)vp; cnt-- > 0; xp += std) {
		if (!xdr_float(xob, xp)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_float(xob, xp)) {
					cc = PvmNoData;
					break;
				}
		}
		xp++;
		if (!xdr_float(xob, xp)) {
			up->ub_cpos = xdr_getpos(xob);
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_float(xob, xp)) {
					cc = PvmNoData;
					break;
				}
		}
	}
	up->ub_cpos = xdr_getpos(xob);
	return cc;
}


static int
dec_xdr_dcplx(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmrbufmid);
	XDR *xob = &up->ub_decxdr;
	register double *zp;
	int cc = 0;

	std = std * 2 - 1;
	for (zp = (double*)vp; cnt-- > 0; zp += std) {
		if (!xdr_double(xob, zp)) {
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_double(xob, zp)) {
					cc = PvmNoData;
					break;
				}
		}
		up->ub_cpos = xdr_getpos(xob);
		zp++;
		if (!xdr_double(xob, zp)) {
			if (cc = dec_xdr_step())
				break;
			else
				if (!xdr_double(xob, zp)) {
					cc = PvmNoData;
					break;
				}
		}
		up->ub_cpos = xdr_getpos(xob);
	}
	return cc;
}

#endif	/*I860_NODE*/

/*************************
 **  In-place encoders  **
 **                     **
 *************************/

static int
enc_inp_init()
{
	return 0;
}


static int
enc_inp_any(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	struct frag *fp;

	if (std != 1)
		return PvmNotImpl;
	if (vp && cnt && siz) {
		fp = fr_snew((char *)vp, cnt * siz);
		LISTPUTBEFORE(up->ub_frag, fp, fr_link, fr_rlink);
	}
#if 0
	if (std != 1) {
		if (std < 1)
			return PvmBadParam;
		fp->fr_max = fp->fr_len = siz + (cnt - 1) * std * siz;
		fp->fr_csz = siz;
		fp->fr_lnc = std * siz;
		fp->fr_u.spr = 1;
	}
#endif
	return 0;
}


/*******************
 **  Foo encoders **
 **               **
 *******************/

static int
enc_foo_init()
{
	struct umbuf *up = midtobuf(pvmsbufmid);
	struct frag *fp;

	fp = fr_new(pvmfrgsiz);			/* make a blank frag to write in */
	fp->fr_dat += MAXHDR;
	LISTPUTBEFORE(up->ub_frag, fp, fr_link, fr_rlink);
	return 0;
}


static int
enc_foo_byte(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	return bytepk((char*)vp, cnt, siz, std * siz);
}


static int
enc_foo_int(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	register int *np;
	char buf[4];
	int n;
	int cc;

	for (np = (int*)vp; cnt-- > 0; np += std) {
		n = *np;
		buf[0] = n >> 24;
		buf[1] = n >> 16;
		buf[2] = n >> 8;
		buf[3] = n;
		if (cc = bytepk(buf, 4, 1, 1))
			return cc;
	}
	return 0;
}


static int
enc_foo_long(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	register long *np;
	char buf[4];
	long n;
	int cc;

	for (np = (long*)vp; cnt-- > 0; np += std) {
		n = *np;
		buf[0] = n >> 24;
		buf[1] = n >> 16;
		buf[2] = n >> 8;
		buf[3] = n;
		if (cc = bytepk(buf, 4, 1, 1))
			return cc;
	}
	return 0;
}


static int
dec_foo_init()
{
	struct umbuf *up = midtobuf(pvmrbufmid);

	up->ub_cfrag = up->ub_frag->fr_link;
	up->ub_cpos = 0;
	return 0;
}


static int
dec_foo_byte(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	return byteupk((char*)vp, cnt, siz, std * siz);
}


static int
dec_foo_int(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	register int *np;
	char buf[4];
	int cc;

	for (np = (int*)vp; cnt-- > 0; np += std) {
		if (cc = byteupk(buf, 4, 1, 1))
			return cc;
		*np = (0x80 & buf[0] ? ~0xffffffff : 0)
		+ ((0xff & buf[0]) << 24)
		+ ((0xff & buf[1]) << 16)
		+ ((0xff & buf[2]) << 8)
		+ (0xff & buf[3]);
	}
	return 0;
}


static int
dec_foo_uint(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	register int *np;
	char buf[4];
	int cc;

	for (np = (int*)vp; cnt-- > 0; np += std) {
		if (cc = byteupk(buf, 4, 1, 1))
			return cc;
		*np = ((0xff & buf[0]) << 24)
		+ ((0xff & buf[1]) << 16)
		+ ((0xff & buf[2]) << 8)
		+ (0xff & buf[3]);
	}
	return 0;
}


static int
dec_foo_long(vp, cnt, std, siz)
	void *vp;
	int cnt, std, siz;
{
	register long *np;
	char buf[4];
	int cc;

	for (np = (long*)vp; cnt-- > 0; np += std) {
		if (cc = byteupk(buf, 4, 1, 1))
			return cc;
		*np = (0x80 & buf[0] ? ~0xffffffff : 0)
		+ ((0xff & buf[0]) << 24)
		+ ((0xff & buf[1]) << 16)
		+ ((0xff & buf[2]) << 8)
		+ (0xff & buf[3]);
	}
	return 0;
}


static int
enc_foo_err()
{
	return PvmNotImpl;	/* don't implement this :-) */
}


/*******************************************
 **  Alien (can't do it) en/decoder stub  **
 **                                       **
 *******************************************/

static int
enc_alien()
{
	return PvmBadMsg;
}


/****************************
 **  Encoder switch table  **
 **                        **
 ****************************/

static struct encvec encoders[] = {

	{	enc_raw_init, dec_raw_init,		/* Raw (native) 0 */
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any,
		enc_raw_any, dec_raw_any },

	{	enc_xdr_init, dec_xdr_init,		/* XDR 1 */
		enc_xdr_byte, dec_xdr_byte,
		enc_xdr_short, dec_xdr_short,
		enc_xdr_int, dec_xdr_int,
		enc_xdr_long, dec_xdr_long,
#if	defined(I860_NODE)
		enc_xdr_short, dec_xdr_short,	/* XXX are handwritten anyhow */
		enc_xdr_int, dec_xdr_int,
		enc_xdr_long, dec_xdr_long,
#else
		enc_xdr_short, dec_xdr_ushort,
		enc_xdr_int, dec_xdr_uint,
		enc_xdr_long, dec_xdr_ulong,
#endif
		enc_xdr_float, dec_xdr_float,
		enc_xdr_double, dec_xdr_double,
		enc_xdr_cplx, dec_xdr_cplx,
		enc_xdr_dcplx, dec_xdr_dcplx },

	{	enc_inp_init, enc_alien,		/* In place (encode only) 2 */
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien,
		enc_inp_any, enc_alien },

	{	enc_foo_init, dec_foo_init,		/* Foo (for pvmd) 3 */
		enc_foo_byte, dec_foo_byte,
		enc_foo_err, enc_foo_err,
		enc_foo_int, dec_foo_int,
		enc_foo_long, enc_foo_long,
		enc_foo_err, enc_foo_err,
		enc_foo_int, dec_foo_uint,
		enc_foo_err, enc_foo_err,
		enc_foo_err, enc_foo_err,
		enc_foo_err, enc_foo_err,
		enc_foo_err, enc_foo_err,
		enc_foo_err, enc_foo_err },

	{	enc_alien, dec_raw_init,		/* Alien (can't deal) 4 */
		enc_alien, dec_raw_any,			/* unpacking bytes allowed */
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien,
		enc_alien, enc_alien },
};


/*	enctovec()
*
*	Map data encoding value to encode/decode function vector
*/

struct encvec *
enctovec(enc)
	int enc;
{
	if (enc == 0)			/* xdr */
		return &encoders[1];
	if (enc == 1)			/* foo */
		return &encoders[3];
	if (enc == 2)			/* inplace */
		return &encoders[2];
	if (enc == pvmmyndf)	/* native */
		return &encoders[0];
	return &encoders[4];	/* alien */
}


int
enc_step(up)
	struct umbuf *up;
{
	struct frag *fp = up->ub_frag;
	struct frag *nfp;

	if (!(nfp = fr_new(pvmfrgsiz)))
		return PvmNoMem;
	nfp->fr_dat += MAXHDR;
	LISTPUTBEFORE(fp, nfp, fr_link, fr_rlink);
	return 0;
}


int
dec_step(up)
	struct umbuf *up;
{
	up->ub_cpos = 0;
	if (up->ub_cfrag == up->ub_frag)		/* no message left */
		return PvmNoData;
	up->ub_cfrag = up->ub_cfrag->fr_link;
	if (up->ub_cfrag == up->ub_frag)
		return PvmNoData;
	return 0;
}


/************************
 **  Libpvm Functions  **
 **                    **
 ************************/

int
pvm_mkbuf(enc)
	int enc;		/* data format */
{
	struct umbuf *up;
	struct frag *fp;
	int cc = 0;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_MKBUF0)) {
			pvm_pkint(&enc, 1, 1);
			TEV_FIN;
		}
	}

	switch (enc) {						/* verify encoding */
	case PvmDataDefault:
		enc = 0;		/* XXX this just forces XDR */
		break;

	case PvmDataRaw:
		enc = pvmmyndf;
		break;

	case PvmDataFoo:
		enc = 1;
		break;

	case PvmDataInPlace:
		enc = 2;
		break;

	default:
		cc = PvmBadParam;
	}
	if (!cc)
		if ((cc = umbuf_new()) > 0) {
			up = midtobuf(cc);					/* set encoders */
			up->ub_enc = enc;
			up->ub_codef = enctovec(enc);
			up->ub_src = pvmmytid;

#if 0
			fp = fr_new(pvmfrgsiz);			/* make a blank frag to write in */
			fp->fr_dat += MAXHDR;
			LISTPUTBEFORE(up->ub_frag, fp, fr_link, fr_rlink);
#endif
		}

	if (x) {
		if (TEV_DO_TRACE(TEV_MKBUF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_mkbuf", cc);
	return cc;
}


int
pvm_freebuf(mid)
	int mid;		/* message handle */
{
	int cc;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_FREEBUF0)) {
			pvm_pkint(&mid, 1, 1);
			TEV_FIN;
		}
	}
	if (pvmsbufmid == mid)
		pvmsbufmid = 0;
	if (pvmrbufmid == mid)
		pvmrbufmid = 0;
	cc = umbuf_free(mid);

	if (x) {
		if (TEV_DO_TRACE(TEV_FREEBUF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_freebuf", cc);
	return cc;
}


int
pvm_setsbuf(mid)
	int mid;
{
	struct umbuf *up = 0;
	int cc = 0;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_SETSBUF0)) {
			pvm_pkint(&mid, 1, 1);
			TEV_FIN;
		}
	}

	if (mid < 0)
		cc = PvmBadParam;
	else
		if (mid) {
			if (mid >= pvmmidhsiz || !(up = pvmmidh[mid].m_umb))
				cc = PvmNoSuchBuf;
			else
				if (mid == pvmrbufmid)
					pvmrbufmid = 0;
		}
	if (!cc) {
		cc = pvmsbufmid > 0 ? pvmsbufmid : 0;
		pvmsbufmid = mid;
		if (up && !(up->ub_flag & UB_PACK)) {
			(up->ub_codef->enc_init)();
			up->ub_flag &= ~UB_UPACK;
			up->ub_flag |= UB_PACK;
		}
	}

	if (x) {
		if (TEV_DO_TRACE(TEV_SETSBUF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_setsbuf", cc);
	return cc;
}


int
pvm_getsbuf()
{
	int cc;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_GETSBUF0))
			TEV_FIN;
	}

	cc =  pvmsbufmid > 0 ? pvmsbufmid : 0;

	if (x) {
		if (TEV_DO_TRACE(TEV_GETSBUF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	return cc;
}


int
pvm_setrbuf(mid)
	int mid;
{
	struct umbuf *up = 0;
	int cc = 0;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_SETRBUF0)) {
			pvm_pkint(&mid, 1, 1);
			TEV_FIN;
		}
	}
	if (mid < 0)
		cc = PvmBadParam;
	else
		if (mid) {
			if (mid >= pvmmidhsiz || !(up = pvmmidh[mid].m_umb))
				cc = PvmNoSuchBuf;
			else
				if (mid == pvmsbufmid)
					pvmsbufmid = 0;
		}
	if (!cc) {
		cc = pvmrbufmid > 0 ? pvmrbufmid : 0;
		pvmrbufmid = mid;
		if (up && !(up->ub_flag & UB_UPACK)) {
			if (up->ub_flag & UB_PACK) {
				up->ub_flag &= ~UB_PACK;
				setublen(up);
			}
			(up->ub_codef->dec_init)();
			up->ub_flag |= UB_UPACK;
		}
	}

	if (x) {
		if (TEV_DO_TRACE(TEV_SETRBUF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_setrbuf", cc);
	return cc;
}


int
pvm_getrbuf()
{
	int cc;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_GETRBUF0))
			TEV_FIN;
	}

	cc = pvmrbufmid > 0 ? pvmrbufmid : 0;

	if (x) {
		if (TEV_DO_TRACE(TEV_GETRBUF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	return cc;
}


int
pvm_initsend(enc)
	int enc;
{
	int cc;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_INITSEND0)) {
			pvm_pkint(&enc, 1, 1);
			TEV_FIN;
		}
	}

	if ((cc = pvm_mkbuf(enc)) >= 0) {
		if (pvmsbufmid > 0)
			pvm_freebuf(pvmsbufmid);
		pvm_setsbuf(cc);
	}

	if (x) {
		if (TEV_DO_TRACE(TEV_INITSEND1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_initsend", cc);
	return cc;
}


int
pvm_bufinfo(mid, len, code, tid)
	int mid;
	int *len;
	int *code;
	int *tid;
{
	struct umbuf *up;
	int cc;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_BUFINFO0)) {
			pvm_pkint(&mid, 1, 1);
			TEV_FIN;
		}
	}

	if (mid <= 0)
		cc = PvmBadParam;
	else
		if (mid >= pvmmidhsiz || !(up = pvmmidh[mid].m_umb))
			cc = PvmNoSuchBuf;

		else {
			cc = PvmOk;
			if (len) {
				if (up->ub_flag & UB_PACK)
					setublen(up);
				*len = up->ub_len;
			}
			if (code)
				*code = up->ub_cod;
			if (tid)
				*tid = up->ub_src;
		}

	if (x) {
		if (TEV_DO_TRACE(TEV_BUFINFO1)) {
			pvm_pkint(&cc, 1, 1);
			if (!cc) {
				pvm_pkint(&up->ub_len, 1, 1);
				pvm_pkint(&up->ub_cod, 1, 1);
				pvm_pkint(&up->ub_src, 1, 1);
			}
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_bufinfo", cc);
	return cc;
}


int
pvm_pkbyte(cp, cnt, std)
	char *cp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKBYTE0)) {
			ad = (long)cp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_byte)
					((void*)cp, cnt, std, 1);

	if (x) {
		if (TEV_DO_TRACE(TEV_PKBYTE1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkbyte", cc) : PvmOk);
}


int
pvm_upkbyte(cp, cnt, std)
	char *cp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKBYTE0)) {
			ad = (long)cp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_byte)
					((void*)cp, cnt, std, 1);

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKBYTE1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkbyte", cc) : PvmOk);
}


int
pvm_pkcplx(xp, cnt, std)
	float *xp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKCPLX0)) {
			ad = (long)xp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_cplx)
					((void*)xp, cnt, std, sizeof(float)*2);

	if (x) {
		if (TEV_DO_TRACE(TEV_PKCPLX1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkcplx", cc) : PvmOk);
}


int
pvm_upkcplx(xp, cnt, std)
	float *xp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKCPLX0)) {
			ad = (long)xp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_cplx)
					((void*)xp, cnt, std, sizeof(float)*2);

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKCPLX1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkcplx", cc) : PvmOk);
}


int
pvm_pkdcplx(zp, cnt, std)
	double *zp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKDCPLX0)) {
			ad = (long)zp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_dcplx)
					((void*)zp, cnt, std, sizeof(double)*2);

	if (x) {
		if (TEV_DO_TRACE(TEV_PKDCPLX1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkdcplx", cc) : PvmOk);
}


int
pvm_upkdcplx(zp, cnt, std)
	double *zp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKDCPLX0)) {
			ad = (long)zp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_dcplx)
					((void*)zp, cnt, std, sizeof(double)*2);

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKDCPLX1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkdcplx", cc) : PvmOk);
}


int
pvm_pkdouble(dp, cnt, std)
	double *dp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKDOUBLE0)) {
			ad = (long)dp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_double)
					((void*)dp, cnt, std, sizeof(double));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKDOUBLE1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkdouble", cc) : PvmOk);
}


int
pvm_upkdouble(dp, cnt, std)
	double *dp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKDOUBLE0)) {
			ad = (long)dp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_double)
					((void*)dp, cnt, std, sizeof(double));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKDOUBLE1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkdouble", cc) : PvmOk);
}


int
pvm_pkfloat(fp, cnt, std)
	float *fp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKFLOAT0)) {
			ad = (long)fp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_float)
					((void*)fp, cnt, std, sizeof(float));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKFLOAT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkfloat", cc) : PvmOk);
}


int
pvm_upkfloat(fp, cnt, std)
	float *fp;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKFLOAT0)) {
			ad = (long)fp;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_float)
					((void*)fp, cnt, std, sizeof(float));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKFLOAT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkfloat", cc) : PvmOk);
}


int
pvm_pkint(np, cnt, std)
	int *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKINT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_int)
					((void*)np, cnt, std, sizeof(int));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKINT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkint", cc) : PvmOk);
}


int
pvm_pkuint(np, cnt, std)
	unsigned int *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKUINT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_int)
					((void*)np, cnt, std, sizeof(int));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKUINT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkuint", cc) : PvmOk);
}


int
pvm_upkint(np, cnt, std)
	int *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKINT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_int)
					((void*)np, cnt, std, sizeof(int));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKINT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkint", cc) : PvmOk);
}


int
pvm_upkuint(np, cnt, std)
	unsigned int *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKUINT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_uint)
					((void*)np, cnt, std, sizeof(int));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKUINT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkuint", cc) : PvmOk);
}


int
pvm_pklong(np, cnt, std)
	long *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKLONG0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_long)
					((void*)np, cnt, std, sizeof(long));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKLONG1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pklong", cc) : PvmOk);
}


int
pvm_pkulong(np, cnt, std)
	unsigned long *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKULONG0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_long)
					((void*)np, cnt, std, sizeof(long));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKULONG1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkulong", cc) : PvmOk);
}


int
pvm_upklong(np, cnt, std)
	long *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKLONG0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_long)
					((void*)np, cnt, std, sizeof(long));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKLONG1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upklong", cc) : PvmOk);
}


int
pvm_upkulong(np, cnt, std)
	unsigned long *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKULONG0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_ulong)
					((void*)np, cnt, std, sizeof(long));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKULONG1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkulong", cc) : PvmOk);
}


int
pvm_pkshort(np, cnt, std)
	short *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKSHORT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_short)
					((void*)np, cnt, std, sizeof(short));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKSHORT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkshort", cc) : PvmOk);
}


int
pvm_pkushort(np, cnt, std)
	unsigned short *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKUSHORT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmsbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmsbufmid)->ub_codef->enc_short)
					((void*)np, cnt, std, sizeof(short));

	if (x) {
		if (TEV_DO_TRACE(TEV_PKUSHORT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkushort", cc) : PvmOk);
}


int
pvm_upkshort(np, cnt, std)
	short *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKSHORT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_short)
					((void*)np, cnt, std, sizeof(short));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKSHORT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkshort", cc) : PvmOk);
}


int
pvm_upkushort(np, cnt, std)
	unsigned short *np;
	int cnt, std;
{
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKUSHORT0)) {
			ad = (long)np;
			pvm_pklong(&ad, 1, 1);
			pvm_pkint(&cnt, 1, 1);
			pvm_pkint(&std, 1, 1);
			TEV_FIN;
		}
	}

	if (cnt < 0)
		cc = PvmBadParam;
	else
		if (pvmrbufmid <= 0)
			cc = PvmNoBuf;
		else
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_ushort)
					((void*)np, cnt, std, sizeof(short));

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKUSHORT1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkushort", cc) : PvmOk);
}


int
pvm_pkstr(cp)
	char *cp;
{
	int l = strlen(cp) + 1;
	int cc;
	long ad;
	int x;
	struct umbuf *up;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PKSTR0)) {
			ad = (long)cp;
			pvm_pklong(&ad, 1, 1);
			TEV_FIN;
		}
	}

	if (pvmsbufmid <= 0)
		cc = PvmNoBuf;
	else {
		up = midtobuf(pvmsbufmid);
		if (up->ub_enc == 2)	/* oops, can't do this without a lot of grief */
			cc = PvmNotImpl;
		else
			if (!(cc = (up->ub_codef->enc_int)
					((void*)&l, 1, 1, sizeof(int))))
				cc = (up->ub_codef->enc_byte)
						((void*)cp, l, 1, 1);
	}

	if (x) {
		if (TEV_DO_TRACE(TEV_PKSTR1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_pkstr", cc) : PvmOk);
}


int
pvm_upkstr(cp)
	char *cp;
{
	int l;
	int cc;
	long ad;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UPKSTR0)) {
			ad = (long)cp;
			pvm_pklong(&ad, 1, 1);
			TEV_FIN;
		}
	}

	if (pvmrbufmid <= 0)
		cc = PvmNoBuf;
	else
		if (!(cc = (midtobuf(pvmrbufmid)->ub_codef->dec_int)
				((void*)&l, 1, 1, sizeof(int))))
			cc = (midtobuf(pvmrbufmid)->ub_codef->dec_byte)
					((void*)cp, l, 1, 1);

	if (x) {
		if (TEV_DO_TRACE(TEV_UPKSTR1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}
	return (cc < 0 ? lpvmerr("pvm_upkstr", cc) : PvmOk);
}


int
pvm_vpackf(fmt, ap)
	char *fmt;
	va_list ap;
{
	char *p = fmt;
	int cc;
	int cnt, std;			/* count and stride of element */
	int vh, vl, vu;			/* short, long, unsigned variety */
	int isv;				/* param is a value not address */
	struct encvec *codef;
	struct umbuf *up;
	char tc, *cp;			/* each type and a pointer */
	short th, *hp;
	int tn, *np;
	long tl, *lp;
	float tf, *fp;
	double td, *dp;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_PACKF0)) {
			pvm_pkstr(fmt);
			TEV_FIN;
		}
	}

	if (p[0] == '%' && p[1] == '+') {
		cc = va_arg(ap, int);
		if ((cc = pvm_initsend(cc)) < 0)
			goto hork;
		p += 2;
	}

	if (pvmsbufmid <= 0) {
		cc = PvmNoBuf;
		goto hork;
	}

	up = midtobuf(pvmsbufmid);
	codef = up->ub_codef;

	while (*p) {
		if (*p++ == '%') {
			cnt = 1;
			std = 1;
			isv = 1;
			vl = vh = vu = 0;
			if (*p == '*') {
				cnt = va_arg(ap, int);
				isv = 0;
				p++;
			} else
				if (isdigit(*p)) {
					cnt = atoi(p);
					isv = 0;
					while (isdigit(*++p)) ;
				}
			if (*p == '.') {
				isv = 0;
				if (*++p == '*') {
					std = va_arg(ap, int);
					p++;
				} else
					if (isdigit(*p)) {
						std = atoi(p);
						while (isdigit(*++p)) ;
					}
			}
			for (cc = 1; cc; ) {
				switch (*p++) {

				case 'h':
					vh = 1;
					break;

				case 'l':
					vl = 1;
					break;

				case 'u':
					vu = 1;
					break;

				default:
					p--;
					cc = 0;
				}
			}

			switch (*p++) {

			case 'c':
				if (isv) {
					tc = va_arg(ap, char);
					cp = &tc;
				} else
					cp = va_arg(ap, char *);
				cc = (codef->enc_byte) ((void*)cp, cnt, std, 1);
#ifdef	DEBUGPACKF
				printf("%d %d %s%schar\n", cnt, std, (vu ? "unsigned " : ""),
						(isv ? "" : "&"));
#endif
				break;

			case 'd':
				if (vl) {
					if (isv) {
						tl = va_arg(ap, long);
						lp = &tl;
					} else
						lp = va_arg(ap, long *);
					cc = (codef->enc_long)
							((void*)lp, cnt, std, sizeof(long));
				} else
					if (vh) {
						if (isv) {
							th = va_arg(ap, short);
							hp = &th;
						} else
							hp = va_arg(ap, short *);
						cc = (codef->enc_short)
								((void*)hp, cnt, std, sizeof(short));
					} else {
						if (isv) {
							tn = va_arg(ap, int);
							np = &tn;
						} else
							np = va_arg(ap, int *);
						cc = (codef->enc_int)
								((void*)np, cnt, std, sizeof(int));
					}
#ifdef	DEBUGPACKF
				printf("%d %d %s%s%s%sint\n", cnt, std,
						(vu ? "unsigned " : ""),
						(vl ? "long " : ""),
						(vh ? "short " : ""),
						(isv ? "" : "&"));
#endif
				break;

			case 'f':
				if (vl) {
					if (isv) {
						td = va_arg(ap, double);
						dp = &td;
					} else
						dp = va_arg(ap, double *);
					cc = (codef->enc_double)
							((void*)dp, cnt, std, sizeof(double));
				} else {
					if (isv) {
/*
						tf = va_arg(ap, float);
*/
						td = va_arg(ap, double);
						tf = td;
						fp = &tf;
					} else
						fp = va_arg(ap, float *);
					cc = (codef->enc_float)
							((void*)fp, cnt, std, sizeof(float));
				}
#ifdef	DEBUGPACKF
				printf("%d %d %s%s\n", cnt, std, (isv ? "" : "&"),
						(vl ? "double" : "float"));
#endif
				break;

			case 'x':
				if (vl) {
					dp = va_arg(ap, double *);
					cc = (codef->enc_dcplx)
							((void*)dp, cnt, std, sizeof(double)*2);
				} else {
					fp = va_arg(ap, float *);
					cc = (codef->enc_cplx)
							((void*)fp, cnt, std, sizeof(float)*2);
				}
#ifdef	DEBUGPACKF
				printf("%d %d %s&cplx\n", cnt, std, (vl ? "double " : ""));
#endif
				break;

			case 's':
				if (up->ub_enc == 2)	/* oops, can't do this */
					cc = PvmNotImpl;
				else {
					cp = va_arg(ap, char *);
					cnt = strlen(cp) + 1;
					if (!(cc = (codef->enc_int) ((void*)&cnt, 1, 1, sizeof(int))))
						cc = (codef->enc_byte) ((void*)cp, cnt, 1, 1);
#ifdef	DEBUGPACKF
					printf("string\n");
#endif
				}
				break;

			default:
				cc = PvmBadParam;
				break;
			}

			if (cc)
				goto hork;
		}
/*
		else
			printf("'%c'\n", *(p - 1));
*/
	}
	cc = PvmOk;

hork:
	if (x) {
		if (TEV_DO_TRACE(TEV_PACKF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_packf", cc);
	return cc;
}


int
#ifdef __STDC__
pvm_packf(const char *fmt, ...)
#else
pvm_packf(va_alist)
	va_dcl
#endif
{
	va_list ap;
	int cc;

#ifdef __STDC__
	va_start(ap, fmt);
#else
	char    *fmt;

	va_start(ap);
	fmt = va_arg(ap, char *);
#endif

	cc = pvm_vpackf(fmt, ap);
	va_end(ap);

	return cc;
}


int
pvm_vunpackf(fmt, ap)
	char *fmt;
	va_list ap;
{
	char *p = fmt;
	int cc;
	int cnt, std;		/* count and stride of element */
	int vh, vl, vu;		/* short, long, unsigned variety */
	struct encvec *codef;
	char *cp;			/* pointers for each type */
	short *hp;
	int *np;
	long *lp;
	float *fp;
	double *dp;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_UNPACKF0)) {
			pvm_pkstr(fmt);
			TEV_FIN;
		}
	}

	if (pvmrbufmid <= 0) {
		cc = PvmNoBuf;
		goto hork;
	}

	codef = midtobuf(pvmrbufmid)->ub_codef;

	while (*p) {
		if (*p++ == '%') {
			cnt = 1;
			std = 1;
			vl = vh = vu = 0;
			if (*p == '*') {
				cnt = va_arg(ap, int);
				p++;
			} else
				if (isdigit(*p)) {
					cnt = atoi(p);
					while (isdigit(*++p)) ;
				}
			if (*p == '.') {
				if (*++p == '*') {
					std = va_arg(ap, int);
					p++;
				} else
					if (isdigit(*p)) {
						std = atoi(p);
						while (isdigit(*++p)) ;
					}
			}
			for (cc = 1; cc; ) {
				switch (*p++) {

				case 'h':
					vh = 1;
					break;

				case 'l':
					vl = 1;
					break;

				case 'u':
					vu = 1;
					break;

				default:
					p--;
					cc = 0;
				}
			}

			switch (*p++) {

			case 'c':
				cp = va_arg(ap, char *);
				cc = (codef->dec_byte) ((void*)cp, cnt, std, 1);
				break;

			case 'd':
				if (vl) {
					lp = va_arg(ap, long *);
					cc = (vu ? codef->dec_ulong : codef->dec_long)
							((void*)lp, cnt, std, sizeof(long));
				} else
					if (vh) {
						hp = va_arg(ap, short *);
						cc = (vu ? codef->dec_ushort : codef->dec_short)
								((void*)hp, cnt, std, sizeof(short));
					} else {
						np = va_arg(ap, int *);
						cc = (vu ? codef->dec_uint : codef->dec_int)
								((void*)np, cnt, std, sizeof(int));
					}
				break;

			case 'f':
				if (vl) {
					dp = va_arg(ap, double *);
					cc = (codef->dec_double)
							((void*)dp, cnt, std, sizeof(double));
				} else {
					fp = va_arg(ap, float *);
					cc = (codef->dec_float)
							((void*)fp, cnt, std, sizeof(float));
				}
				break;

			case 'x':
				if (vl) {
					dp = va_arg(ap, double *);
					cc = (codef->dec_dcplx)
							((void*)dp, cnt, std, sizeof(double)*2);
				} else {
					fp = va_arg(ap, float *);
					cc = (codef->dec_cplx)
							((void*)fp, cnt, std, sizeof(float)*2);
				}
				break;

			case 's':
				cp = va_arg(ap, char *);
				if (!(cc = (codef->dec_int) ((void*)&cnt, 1, 1, sizeof(int))))
					cc = (codef->dec_byte) ((void*)cp, cnt, 1, 1);
				break;

			default:
				cc = PvmBadParam;
				break;
			}

			if (cc)
				goto hork;
		}
	}
	cc = PvmOk;

hork:
	if (x) {
		if (TEV_DO_TRACE(TEV_UNPACKF1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_unpackf", cc);
	return cc;
}


int
#ifdef __STDC__
pvm_unpackf(const char *fmt, ...)
#else
pvm_unpackf(va_alist)
	va_dcl
#endif
{
	va_list ap;
	int cc;

#ifdef __STDC__
	va_start(ap, fmt);
#else
	char    *fmt;

	va_start(ap);
	fmt = va_arg(ap, char *);
#endif

	cc = pvm_vunpackf(fmt, ap);
	va_end(ap);

	return cc;
}


int
pvm_getmwid(mid)
	int mid;
{
	struct umbuf *up = 0;
	int cc = 0;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_GETMWID0)) {
			pvm_pkint(&mid, 1, 1);
			TEV_FIN;
		}
	}

	if (mid < 0)
		cc = PvmBadParam;
	else
		if (mid >= pvmmidhsiz || !(up = pvmmidh[mid].m_umb))
			cc = PvmNoSuchBuf;
		else
			cc = up->ub_wid;

	if (x) {
		if (TEV_DO_TRACE(TEV_GETMWID1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_getmwid", cc);
	return cc;
}


int
pvm_setmwid(mid, wid)
	int mid;
	int wid;
{
	struct umbuf *up = 0;
	int cc = 0;
	int x;

	if (x = pvmtoplvl) {
		pvmtoplvl = 0;
		if (TEV_DO_TRACE(TEV_SETMWID0)) {
			pvm_pkint(&mid, 1, 1);
			pvm_pkint(&wid, 1, 1);
			TEV_FIN;
		}
	}

	if (mid < 0)
		cc = PvmBadParam;
	else
		if (mid >= pvmmidhsiz || !(up = pvmmidh[mid].m_umb))
			cc = PvmNoSuchBuf;
		else
			up->ub_wid = wid;

	if (x) {
		if (TEV_DO_TRACE(TEV_SETMWID1)) {
			pvm_pkint(&cc, 1, 1);
			TEV_FIN;
		}
		pvmtoplvl = x;
	}

	if (cc < 0)
		lpvmerr("pvm_setmwid", cc);
	return cc;
}


