Net2/usr/src/contrib/isode/pepsy/prnt.c

Compare this file to the similar file:
Show the results in this format:

/* prnt.c */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/pepsy/RCS/prnt.c,v 7.9 91/02/22 09:49:54 mrose Interim $";
#endif

/* 
 * $Header: /f/osi/pepsy/RCS/prnt.c,v 7.9 91/02/22 09:49:54 mrose Interim $
 *
 *
 * $Log:	prnt.c,v $
 * Revision 7.9  91/02/22  09:49:54  mrose
 * Interim 6.8
 * 
 * Revision 7.8  90/12/23  17:25:20  mrose
 * patches
 * 
 * Revision 7.7  90/11/11  09:58:56  mrose
 * touch-up
 * 
 * Revision 7.6  90/11/04  19:21:00  mrose
 * update
 * 
 * Revision 7.5  90/10/23  20:43:16  mrose
 * update
 * 
 * Revision 7.4  90/08/08  14:14:38  mrose
 * update
 * 
 * Revision 7.3  90/07/27  08:48:34  mrose
 * update
 * 
 * Revision 7.2  90/07/09  14:53:08  mrose
 * sync
 * 
 * Revision 7.1  90/07/01  20:02:00  mrose
 * update
 * 
 */

/*
 *				  NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


/* LINTLIBRARY */

#include	<stdio.h>
#include	<ctype.h>
#include	<varargs.h>
#include	"pepsy-driver.h"
#include	"psap.h"
#include	"pepsy.h"
#include	"tailor.h"

#define PRINT_TYPES	0
#define	CHOICE_PUSH


extern PE p_setpresent();
extern IFP vfnx;
extern FILE *vfp;

extern ptpe *next_ptpe();
extern int pepsylose ();

int     xlevel = 0;
int     tabed = 0;
int     xpushed = 0;

#define NEXT_PTPE(p)	(p = next_ptpe(p))
#define CHKTAG(mod, p, pe)	p_ismatch(p, mod, pe->pe_class, pe->pe_id)

/* SUPPRESS 36 *//* for Saber C */

/*
 * to guarentee the rules that vname and a vprint-type routine are called
 * alternatively. Basically can't have two vname's in a row
 */
static vnamelock = 0;
   /* if vnamelock > 0 don't call vname */
#define VNAME(x)  if (vnamelock++ <= 0) vname(x); else
#define VTAG(class, tag)	if (vnamelock++ <= 0)  \
					vtag((int )class, (int )tag); else

/* as vprint takes a variable number of arguements we have to put all of
 * the arguements inside () and remove them when we expand to vprint
 */
#define VPRINT(x)	vnamelock = 0, vprint x
#define VSTRING(x)	vnamelock = 0, vstring(x)
#define VUNKNOWN(x)	vnamelock = 0, vunknown(x)
#define VPUSH		vnamelock = 0, vpush
#define VPOP		vnamelock = 0, vpop


/*
 * Print out ASN data given in pe using the information given in the tables
 */
prnt_f(typ, mod, pe, explicit, len, buf)
/* ARGSUSED */
int     typ;			/* which type it is */
modtyp *mod;			/* ASN Module it is from */
PE      pe;
int     explicit;	/* nonzero means we are call top level 
			 * print final \n
			 */
int    *len;
char  **buf;
{
    ptpe   *p;

    if (typ < 0 || typ >= mod->md_nentries) {
	return (ppepsylose (mod, NULLPTPE, pe, "prnt_f:Illegal type %d\n",typ));
    }

    p = mod->md_ptab[typ];

    if (p->pe_type != PE_START) {
	return (ppepsylose (mod, p, pe, "prnt_f: missing PE_START\n"));
    }

#if EXTRA_BRACKETS
    if (explicit) {
	if (p->pe_typename)
	    VNAME(p->pe_typename);
    }
    VPUSH();
#endif


    if (p_pr_obj(explicit, pe, p, mod) == NOTOK) {
#if EXTRA_BRACKETS
	VPOP();
#endif
	return (NOTOK);
    }
#if EXTRA_BRACKETS
    VPOP();
#endif
    return (OK);
}

/*
 * Parse an object. The top level of an object does not have any
 * offset field which makes it different to pr_type routine which
 * must assume that it has an offset.
 */
static int
p_pr_obj(expl, pe, p, mod)
int     expl;			/* do we look at the tag */
PE      pe;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    int     cnt = 0;

#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif

    p++;
    while (p->pe_type != PE_END) {

	if (ISDTYPE(p) && expl && CHKTAG(mod, p, pe) == 0) {
	    if (DEFAULT(p)) {
		return (ppepsylose (mod, p, pe,
		    "p_pr_obj:Default not implemented\n"));
	    }
	    else if (OPTIONAL(p))
		return (NO_DATA_USED);
	    else {
		return (ppepsylose (mod, p, pe,
		    "p_pr_obj:missing mandatory parameter", p, mod));
	    }
	}
	if (p->pe_typename)
	    VNAME(p->pe_typename);
	switch (p->pe_type) {
	case PE_END:
	case PE_START:
	    goto bad;

	case UCODE:
	    if (mod->md_pucode == NULLIFP
	    || (*mod->md_pucode) (pe, p) == NOTOK)
		goto bad;
	    break;


	default:
	    if (p_pr_type(expl, pe, p, mod) == NOTOK)
		goto bad;
	    break;
	}
	if (ISDTYPE(p) && cnt > 0)
	    return (ppepsylose (mod, p, pe, "p_pr_obj:compound type found\n"));
	if (ISDTYPE(p) && pe != NULLPE) {
	    return (OK);
	}
	if (NEXT_PTPE(p) == NULLPTPE)
	    goto bad;
    }

    return (OK);

bad:
    return (NOTOK);
}


/*
 * Parse a single type. If a basic type parse it, if a compound type
 * call the appropriate parsing routine
 */
static int
p_pr_type(expl, pe, p, mod)
int     expl;			/* do we look at the tag */
PE      pe;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    int     cnt = 0;
    integer     i;
    OID     oid;


    while (p->pe_type != PE_END) {

	if (ISDTYPE(p) && expl && CHKTAG(mod, p, pe) == 0) {
	    if (DEFAULT(p)) {
#ifdef	PRINT_DEFAULTS
		setpval(p, p + 1, mod);
#endif
		return (OK);
	    } else if (OPTIONAL(p))
		return (OK);
	    else {
		dmp_ptpe("p_pr_type:missing mandatory parameter", p, mod);
		goto bad;
	    }
	}
	switch (p->pe_type) {
	case PE_END:
	case PE_START:
	    goto bad;

        case BOPTIONAL:
            if (CHKTAG(mod, p + 1, pe) == 0) {
                return (OK);
            }
            p++;
            continue;

	case UCODE:
	    if (mod->md_pucode == NULLIFP
	    || (*mod->md_pucode) (pe, p) == NOTOK)
		goto bad;
	    break;

	case ETAG:
	    switch (p->pe_ucode) {
	    default:
		if (p_pr_etype(pe->pe_cons, p, mod) == NOTOK)
		    goto bad;
	    }
	    break;

	case SSEQ_START:
	case SEQ_START:
	    if (p_pr_seq(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SSEQOF_START:
	case SEQOF_START:
	    if (p_pr_seqof(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SSET_START:
	case SET_START:
	    if (p_pr_set(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SSETOF_START:
	case SETOF_START:
	    if (p_pr_setof(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case IMP_OBJ:
	    p++;
	    if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ) {
		if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		    (char **) 0) == NOTOK)
		    goto bad;
	    } else {
		if (p_pr_obj(0, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		    goto bad;
		}
	    }
	    break;

	case SOBJECT:
	case OBJECT:
	    if (p_pr_obj(expl, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SCHOICE_START:
	case CHOICE_START:
	    if (p_pr_choice(pe, p, mod) == NOTOK)
		goto bad;
	    break;

	case SEXTOBJ:
	case EXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		return (ppepsylose (mod, p, pe, "p_pr_type: missing EXTMOD"));
	    }
	    if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		   (char **) 0) == NOTOK)
		   goto bad;
	    break;

	case INTEGER:
	    if (pe != NULLPE) {
		if ((i = prim2num(pe)) == NOTOK && pe->pe_errno != PE_ERR_NONE)
		    goto bad;
		VPRINT(("%d", i));
	    }
	    break;

#ifdef	PEPSY_REALS
	case REALTYPE:
	    if (pe != NULLPE) {
		double r;

		if ((r = prim2real(pe)) == NOTOK
		    && pe->pe_errno != PE_ERR_NONE)
		    goto bad;
		VPRINT(("%g", r));
	    }
	    break;
#endif

	case BOOLEAN:
	    if (pe != NULLPE) {
		if ((i = prim2flag(pe)) == NOTOK)
		    goto bad;
		VPRINT((i ? "TRUE" : "FALSE"));
	    }
	    break;

	case T_NULL:
	    VPRINT(("NULL"));
	    break;

	case SANY:
	    if (pe != NULLPE) {
		if (pe->pe_errno != PE_ERR_NONE) {
		    goto bad;
		} else
		    VUNKNOWN(pe);
	    }
	    break;


	case ANY:
	    if (pe != NULLPE) {
		if (pe->pe_errno != PE_ERR_NONE) {
		    goto bad;
		} else
		    VUNKNOWN(pe);
	    }
	    break;

	case SOCTETSTRING:
	    if (pe != NULLPE) {
		VSTRING(pe);
	    }
	    break;

	case OCTETSTRING:
	case T_STRING:
	case OCTET_PTR:
	    if (pe != NULLPE) {
		VSTRING(pe);
	    }
	    break;

	case SBITSTRING:
	    if (pe != NULLPE) {
		PE	bstr;

		if ((bstr = prim2bit(pe)) == NULLPE)
		    goto bad;
		if (p -> pe_ucode >= 0 && mod->md_ptrtab &&
		    mod -> md_ptrtab[p -> pe_ucode] &&
		    bstr -> pe_nbits < LOTSOFBITS)
		    VPRINT (("%s", bit2str(bstr,
					   mod -> md_ptrtab[p -> pe_ucode])));
		else if (bstr->pe_nbits < LOTSOFBITS)
		    VPRINT(("%s", bit2str(bstr, "\020")));
		else
		    VUNKNOWN(pe);
	    }
	    break;

	case BITSTR_PTR:
	case BITSTRING:
	    if (pe != NULLPE) {
		PE	bstr;

		if ((bstr = prim2bit(pe)) == NULLPE)
		    goto bad;
		if (p -> pe_ucode >= 0 && mod->md_ptrtab &&
		    mod -> md_ptrtab[p -> pe_ucode] &&
		    bstr -> pe_nbits < LOTSOFBITS)
		    VPRINT (("%s", bit2str(bstr,
					   mod -> md_ptrtab[p -> pe_ucode])));
		else if (bstr->pe_nbits < LOTSOFBITS)
		    VPRINT(("%s", bit2str(bstr, "\020")));
		else
		    VUNKNOWN(pe);
	    }
	    break;

	case SOBJID:
	    if ((oid = (OID) prim2oid(pe)) == NULLOID) {
		goto bad;
	    } else {
		VPRINT(("%s", oid2ode(oid)));
	    }
	    break;

	case OBJID:
	    if ((oid = (OID) prim2oid(pe)) == NULLOID) {
		goto bad;
	    } else {
		VPRINT(("%s", oid2ode(oid)));
	    }
	    break;

	case FN_CALL:
	    if ((FN_PTR(mod, p))(pe) == NOTOK)
		return ppepsylose (mod, &p[1], NULLPE,
				  "p_pr_type:FN_CALL:call failed");
	    break;

	default:
	    return (ppepsylose (mod, p, pe, "p_pr_type: %d not implemented\n",
		p->pe_type));
	}
	if (ISDTYPE(p) && cnt > 0)
	    return (ppepsylose (mod, p, pe, "p_pr_type:compound type found\n"));
	if (ISDTYPE(p) && pe != NULLPE)
	    return (OK);
	if (NEXT_PTPE(p) == NULLPTPE)
	    goto bad;
    }

    return (OK);

bad:
    return (NOTOK);
}

/*
 * Parse a sequence, calling appropriate routines to parse each sub
 * type
 */
static int
p_pr_seq(head, p, mod)
PE      head;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    PE      pe;

    if (p->pe_type != SEQ_START && p->pe_type != SSEQ_START)
	return (ppepsylose (mod, p, head, "p_pr_seq: missing SEQ_START\n"));
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
    VPUSH();

    p++;
    if (p->pe_type == DFLT_B)
	p++;


    pe = first_member(head);
    while (p->pe_type != PE_END) {
	if (ISDTYPE(p) && OPTIONAL(p)) {
	    if (pe == NULLPE || CHKTAG(mod, p, pe) == 0)
		goto next;
	} else if (ISDTYPE(p) && (pe == NULLPE || CHKTAG(mod, p, pe) == 0)) {
	    if (DEFAULT(p)) {
#ifdef	PRINT_DEFAULTS
		setpval(p, p + 1, mod);
#endif
		goto next;
	    } else {
		dmp_ptpe("p_pr_seq:missing mandatory parameter", p, mod);
		goto bad;
	    }
	}
	if (p->pe_typename)
	    VNAME(p->pe_typename);
	switch (p->pe_type) {
	case OPTL:
	    break;

	case UCODE:
	    if (mod->md_pucode == NULLIFP
	    || (*mod->md_pucode) (pe, p) == NOTOK)
		goto bad;
	    break;

	case BOPTIONAL:
	    if (CHKTAG(mod, p + 1, pe) == 0)
		goto next;
	    p++;
	    continue;

	case ETAG:
	    if (p_pr_type(1, pe, p, mod) == NOTOK)
		goto bad;
	    break;

	case SEQ_START:
	    if (p_pr_seq(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SEQOF_START:
	    if (p_pr_seqof(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SET_START:
	    if (p_pr_set(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SETOF_START:
	    if (p_pr_setof(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case IMP_OBJ:
	    p++;
	    if (p->pe_type == EXTOBJ) {
		if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		    (char **) 0) == NOTOK)
		    goto bad;
	    } else {
		if (p_pr_obj(0, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		    goto bad;
		}
	    }
	    break;

	case SOBJECT:
	    if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case OBJECT:
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
	    if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SCHOICE_START:
	case CHOICE_START:
	    if (p_pr_choice(pe, p, mod) == NOTOK)
		goto bad;
	    break;

	case SEXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		return (ppepsylose (mod, p, pe, "p_pr_seq: missing EXTMOD"));
	    }
	    if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0,NULLIP,
		(char **)0) == NOTOK)
		goto bad;
	    break;

	case EXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		return (ppepsylose (mod, p, pe, "p_pr_seq: missing EXTMOD"));
	    }
	    if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		    (char **)0) == NOTOK)
		goto bad;
	    break;

	default:
	    if (p_pr_type(1, pe, p, mod) == NOTOK)
		goto bad;
	    break;
	}

	if (ISDTYPE(p) && pe != NULLPE)
	    pe = next_member(head, pe);
next:
	if (NEXT_PTPE(p) == NULLPTPE)
	    goto bad;
    }

    VPOP();
    return (OK);

bad:
    VPOP();
    return (NOTOK);
}


/*
 * Parse a set, calling appropriate routines to parse each sub type
 */
static int
p_pr_set(head, p, mod)
PE      head;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    PE      pe;

    if (p->pe_type != SET_START && p->pe_type != SSET_START)
	return (ppepsylose (mod, p, head, "p_pr_seq: missing SET_START\n"));
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
    VPUSH();

    p++;
    if (p->pe_type == DFLT_B)
	p++;

    while (p->pe_type != PE_END) {

	if (ISDTYPE(p) && OPTIONAL(p)) {
	    if ((pe = (PE) p_setpresent(head, p, mod)) == NULLPE)
		goto next;
	} else if (ISDTYPE(p)
	    && (pe = (PE) p_setpresent(head, p, mod)) == NULLPE) {
	    if (DEFAULT(p)) {
#ifdef PRINT_DEFAULTS
		setpval(p, p + 1, mod);
#endif
		goto next;
	    } else {
		dmp_ptpe("p_pr_set:missing mandatory parameter", p, mod);
		goto bad;
	    }
	}
	if (p->pe_typename)
	    VNAME(p->pe_typename);
	switch (p->pe_type) {
	case OPTL:
	    break;

	case UCODE:
	    if (mod->md_pucode == NULLIFP
	    || (*mod->md_pucode) (pe, p) == NOTOK)
		goto bad;
	    break;

	case BOPTIONAL:
	    if ((pe = (PE) p_setpresent(head, p + 1, mod)) == NULLPE)
		goto next;
	    p++;
	    continue;

	case ETAG:
	    if (p_pr_type(1, pe, p, mod) == NOTOK)
		goto bad;
	    break;

	case SEQ_START:
	    if (p_pr_seq(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SEQOF_START:
	    if (p_pr_seqof(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SET_START:
	    if (p_pr_set(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SETOF_START:
	    if (p_pr_setof(pe, p, mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case IMP_OBJ:
	    p++;
	    if (p->pe_type == EXTOBJ) {
		if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		       (char **) 0) == NOTOK)
		       goto bad;
	    } else {
		if (p_pr_obj(0, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		    goto bad;
		}
	    }
	    break;

	case SOBJECT:
	    if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case OBJECT:
	    if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		goto bad;
	    }
	    break;

	case SCHOICE_START:
	case CHOICE_START:
	    if (p_pr_choice(pe, p, mod) == NOTOK)
		goto bad;
	    break;

	case SEXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		return (ppepsylose (mod, p, pe, "p_pr_set: missing EXTMOD"));
	    }
	    if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP, (char **)0) == NOTOK)
		    return (NOTOK);
	    break;

	case EXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		return (ppepsylose (mod, p, pe, "p_pr_set: missing EXTMOD"));
	    }
	    if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		(char **)0) == NOTOK)
		goto bad;
	    break;

	default:
	    if (p_pr_type(1, pe, p, mod) == NOTOK)
		goto bad;
	    break;
	}

next:
	if (NEXT_PTPE(p) == NULLPTPE)
	    goto bad;
    }

    VPOP();
    return (OK);

bad:
    VPOP();
    return (NOTOK);
}


/*
 * Parse a sequence of calling appropriate routines to parse each sub
 * type
 */

static int
p_pr_seqof(head, p, mod)
PE      head;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    PE      pe;
    ptpe   *start;		/* first entry in list */
    int     dflt = 0;

    if (p->pe_type != SEQOF_START && p->pe_type != SSEQOF_START) {
	return (ppepsylose (mod, p, head, "p_pr_seqof: missing SEQOF_START\n"));
    }
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
    VPUSH();

    p++;

    if (p->pe_type == DFLT_B)
	p++;

    start = p;


    pe = first_member(head);
    while (pe != NULLPE) {
	while (p->pe_type != PE_END) {

	    if (ISDTYPE(p) && CHKTAG(mod, p, pe) == 0) {
		if (DEFAULT(p))
		    return (ppepsylose (mod, p, pe,
			"p_pr_seqof:Default not implemented\n"));
		else if (OPTIONAL(p))
		    goto next;
		else {
		    return (ppepsylose (mod, p, pe,
			"p_pr_seqof:missing mandatory parameter"));
		}
	    }
	    if (p->pe_typename)
		VNAME(p->pe_typename);
	    switch (p->pe_type) {
	    case UCODE:
		if (mod->md_pucode == NULLIFP
		|| (*mod->md_pucode) (pe, p) == NOTOK)
		    goto bad;
		break;

	    case BOPTIONAL:
		if (CHKTAG(mod, p + 1, pe) == 0)
		    goto next;
		p++;
		continue;

	    case ETAG:
		if (p_pr_type(1, pe, p, mod) == NOTOK)
		    goto bad;
		break;

		/*
		 * case SCTRL:  parm = (char *) ((char *) parm);
		 * break;
		 */

	    case SEQ_START:
		if (p_pr_seq(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SEQOF_START:
		if (p_pr_seqof(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SET_START:
		if (p_pr_set(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SETOF_START:
		if (p_pr_setof(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SOBJECT:
		if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case OBJECT:
		if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SCHOICE_START:
	    case CHOICE_START:
		if (p_pr_choice(pe, p, mod) == NOTOK)
		    goto bad;
		break;

	    case SEXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    return (ppepsylose (mod, p, pe,"p_pr_seqof:missing EXTMOD"));
		}
		if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		     (char **)0) == NOTOK)
		     goto bad;
		break;

	    case EXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    return (ppepsylose (mod, p, pe,"p_pr_seqof:missing EXTMOD"));
		}
		if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP, 
		    (char **) 0) == NOTOK)
		    goto bad;
		break;

	    default:
		if (p_pr_type(1, pe, p, mod) == NOTOK)
		    goto bad;
		break;
	    }

	    if (ISDTYPE(p) && dflt == 0)
		pe = next_member(head, pe);
    next:
	    if (NEXT_PTPE(p) == NULLPTPE)
		goto bad;
	}
	/* parm = (char *) (parm); */
	p = start;
    }

    VPOP();
    return (OK);

bad:
    VPOP();
    return (NOTOK);
}

/*
 * Parse a setof, calling appropriate routines to parse each sub type
 */
static int
p_pr_setof(head, p, mod)
PE      head;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    PE      pe;
    ptpe   *start;

    if (p->pe_type != SETOF_START && p->pe_type != SSETOF_START)
	return (ppepsylose (mod, p, head, "p_pr_setof: missing SETOF_START\n"));
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
    VPUSH();

    p++;
    if (p->pe_type == DFLT_B)
	p++;

    start = p;

    for (pe = first_member(head); pe; pe = next_member(head, pe)) {
	while (p->pe_type != PE_END) {
	    if (pe == NULLPE || CHKTAG(mod, p, pe) == 0) {
		if (DEFAULT(p)) {
#ifdef PRINT_DEFAULTS
		    setpval(p, p + 1, mod);
#endif
		    goto next;
		} else {
		    dmp_ptpe("p_pr_setof:missing mandatory parameter", p, mod);
		    goto bad;
		}
	    }

	    if (p->pe_typename)
		VNAME(p->pe_typename);
	    switch (p->pe_type) {
	    case UCODE:
		if (mod->md_pucode == NULLIFP
		|| (*mod->md_pucode) (pe, p) == NOTOK)
		    goto bad;
		break;

	    case BOPTIONAL:
		if ((pe = (PE) p_setpresent(head, p + 1, mod)) == NULLPE)
		    goto next;
		p++;
		continue;

	    case ETAG:
		if (p_pr_type(1, pe->pe_cons, p, mod) == NOTOK)
		    goto bad;
		break;

		/*
		 * case SCTRL: parm = (char *) (parm); break;
		 */

	    case SEQ_START:
		if (p_pr_seq(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SEQOF_START:
		if (p_pr_seqof(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SET_START:
		if (p_pr_set(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SETOF_START:
		if (p_pr_setof(pe, p, mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SOBJECT:
		if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case OBJECT:
		if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK) {
		    goto bad;
		}
		break;

	    case SCHOICE_START:
	    case CHOICE_START:
		if (p_pr_choice(pe, p, mod) == NOTOK)
		    goto bad;
		break;

	    case SEXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    return (ppepsylose (mod, p, pe,"p_pr_setof:missing EXTMOD"));
		}
		if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		    (char **) 0) == NOTOK)
		    goto bad;
		break;

	    case EXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    return (ppepsylose (mod, p, pe,"p_pr_setof:missing EXTMOD"));
		}
		if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		    (char **) 0) == NOTOK)
		    goto bad;
		break;

	    default:
		if (p_pr_type(1, pe, p, mod) == NOTOK)
		    goto bad;
		break;
	    }

    next:
	    if (NEXT_PTPE(p) == NULLPTPE)
		goto bad;
	}
	/* parm = (char *)(parm); */
	p = start;
    }

    VPOP();
    return (OK);

bad:
    VPOP();
    return (NOTOK);

}

/*
 * parse a choice field. This means find which choice is taken
 */
static int
p_pr_choice(head, p, mod)
PE      head;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    if (p->pe_type != CHOICE_START && p->pe_type != SCHOICE_START) {
	return (ppepsylose (mod, p, head, "p_pr_choice:missing CHOICE_START"));
    }
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
#ifdef CHOICE_PUSH
    VPUSH();
#endif

    p++;
    if (p->pe_type == DFLT_B)
	p++;

    if (p->pe_type == SCTRL) {
	p++;
    }

    for (; p->pe_type != PE_END; NEXT_PTPE(p)) {
	if (ISDTYPE(p) && p_ismatch(p, mod, head->pe_class, head->pe_id)) {
	    if (p->pe_typename)
		VNAME(p->pe_typename);
	    if (p_pr_type(0, head, p, mod) == NOTOK)
		return (NOTOK);
#ifdef CHOICE_PUSH
	    VPOP();
#endif
	    NEXT_PTPE(p);
	    if (p->pe_type == UCODE) {
		if (mod->md_pucode == NULLIFP
		|| (*mod->md_pucode) (head, p) == NOTOK)
		    return (NOTOK);
	    }
	    return (OK);
	}
    }

    dmp_ptpe("p_pr_choice: no choice taken", p, mod);
#ifdef CHOICE_PUSH
	VPOP();
#endif
    return (NOTOK);
}

/*
 * Calculate the next ptpe entry in the sequence. Count a sequence as
 * one element
 */
ptpe   *
next_ptpe(p)
ptpe   *p;
{
    int     level;

    level = 0;
    if (p->pe_type == PE_END) {
	(void) ppepsylose (NULLMODTYP, p, NULLPE,
	    "next_ptpe: unexpected PE_END");
	return (NULLPTPE);
    }
    do {
again:
	switch (p->pe_type) {
	case SSEQ_START:
	case SSEQOF_START:
	case SSET_START:
	case SSETOF_START:
	case SCHOICE_START:
	case SEQ_START:
	case SEQOF_START:
	case SET_START:
	case SETOF_START:
	case CHOICE_START:
	    level++;
	    break;

	case UCODE:
	case SCTRL:
	case CH_ACT:
	case INTEGER:
	case REALTYPE:
	case BOOLEAN:
	case SANY:
	case ANY:
	case T_NULL:
	case OBJECT:
	case SOBJECT:
	case BITSTRING:
	case SBITSTRING:
	case BITSTR_LEN:
	case OCTETSTRING:
	case T_STRING:
	case OCTET_LEN:
	case SOCTETSTRING:
	case OBJID:
	case SOBJID:
	case OPTL:
	case EXTMOD:
	case DFLT_B:
	case FN_CALL:
	case FFN_CALL:
	    break;

	case OCTET_PTR:
	case BITSTR_PTR:
	case IMP_OBJ:
	case ETAG:
	case EXTOBJ:
	case SEXTOBJ:
	case DFLT_F:
	case BOPTIONAL:
	    p++;
	    goto again;

	case PE_END:
	    level--;
	    break;

	default:
	    (void) ppepsylose (NULLMODTYP, p, NULLPE,
		"next_ptpe: unknown type %d\n", p->pe_type);
	    return (NULLPTPE);
	}
	p++;
    } while (level > 0 || p->pe_type == DFLT_B);

    return (p);
}

/*
 * Parse a single type for explicit tag If a basic type parse it, if
 * a compound type call the appropriate parsing routine
 */
static int
p_pr_etype(pe, p, mod)
PE      pe;
ptpe   *p;
modtyp *mod;			/* Module it is from */
{
    integer     i;
    OID     oid;

    if (p->pe_type != ETAG)
	return (ppepsylose (mod, p, pe, "p_pr_etype: missing ETAG\n"));
    

    if (PRINT_TAG(p))
	VTAG (CLASS (p), TAG (p));
    p++;

    switch (p->pe_type) {
    case PE_END:
    case PE_START:
	goto bad;

    case UCODE:
	if (mod->md_pucode == NULLIFP
	|| (*mod->md_pucode) (pe, p) == NOTOK)
	    goto bad;
	break;

    case BOPTIONAL:
	return (ppepsylose (mod, p, pe, "p_pr_etype:illegal BOPTIONAL\n"));

    case ETAG:
	switch (p->pe_ucode) {

	default:
	    if (p_pr_etype(pe->pe_cons, p, mod) == NOTOK)
		goto bad;
	}
	break;

    case SSEQ_START:
    case SEQ_START:
	if (p_pr_seq(pe, p, mod) == NOTOK)
	    goto bad;
	break;

    case SSEQOF_START:
    case SEQOF_START:
	if (p_pr_seqof(pe, p, mod) == NOTOK)
	    goto bad;
	break;

    case SSET_START:
    case SET_START:
	if (p_pr_set(pe, p, mod) == NOTOK)
	    goto bad;
	break;

    case SSETOF_START:
    case SETOF_START:
	if (p_pr_setof(pe, p, mod) == NOTOK)
	    goto bad;
	break;

    case IMP_OBJ:
	p++;
	if (p->pe_type == EXTOBJ) {
	    if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
		   (char **) 0) == NOTOK)
		   goto bad;
	} else {
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
	    if (p_pr_obj(0, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK)
		goto bad;
	}
	break;

    case SOBJECT:
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
	if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK)
	    goto bad;
	break;

    case OBJECT:
#if PRINT_TYPES
    if (p->pe_typename)
	VNAME(p->pe_typename);
#endif
	if (p_pr_obj(1, pe, mod->md_ptab[p->pe_tag], mod) == NOTOK)
	    goto bad;
	break;

    case SCHOICE_START:
    case CHOICE_START:
	if (p_pr_choice(pe, p, mod) == NOTOK)
	    goto bad;
	break;

    case SEXTOBJ:
	if (p[1].pe_type != EXTMOD) {
	    return (ppepsylose (mod, p, pe, "p_pr_etype: missing EXTMOD"));
	}
	if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
	       (char **) 0) == NOTOK)
	       goto bad;
	break;

    case EXTOBJ:
	if (p[1].pe_type != EXTMOD) {
	    return (ppepsylose (mod, p, pe, "p_pr_etype: missing EXTMOD"));
	}
	if (prnt_f(p->pe_tag, EXT2MOD(mod, (p + 1)), pe, 0, NULLIP,
	       (char **) 0) == NOTOK)
	       goto bad;
	break;

    case INTEGER:
	if (pe != NULLPE) {
	    if ((i = prim2num(pe)) == NOTOK && pe->pe_errno != PE_ERR_NONE)
		goto bad;
	    VPRINT(("%d", i));
	}
	break;

#ifdef	PEPSY_REALS
    case REALTYPE:
	if (pe != NULLPE) {
	    double r;

	    if ((r = prim2real(pe)) == NOTOK
		&& pe->pe_errno != PE_ERR_NONE)
		goto bad;
	    VPRINT(("%g", r));
	}
	break;
#endif


    case BOOLEAN:
	if (pe != NULLPE) {
	    if ((i= prim2flag(pe)) == NOTOK)
		goto bad;
	    VPRINT((i ? "TRUE" : "FALSE"));
	}
	break;

    case T_NULL:
	VPRINT(("NULL"));
	break;

    case ANY:
	if (pe != NULLPE) {
	    if (pe->pe_errno != PE_ERR_NONE) {
		goto bad;
	    } else
		VUNKNOWN(pe);
	}
	break;

    case SANY:
	if (pe != NULLPE) {
	    if (pe->pe_errno != PE_ERR_NONE) {
		goto bad;
	    } else
		VUNKNOWN(pe);
	}
	break;

    case SOCTETSTRING:
    case OCTETSTRING:
    case T_STRING:
    case OCTET_PTR:
	if (pe != NULLPE) {
	    VSTRING(pe);
	}
	break;

    case BITSTRING:
    case BITSTR_PTR:
    case SBITSTRING:
	if (pe != NULLPE) {
	    PE	bstr;

	    if ((bstr = prim2bit(pe)) == NULLPE)
		goto bad;
	    if (p -> pe_ucode >= 0 && mod->md_ptrtab &&
		mod -> md_ptrtab[p -> pe_ucode] &&
		bstr -> pe_nbits < LOTSOFBITS)
		VPRINT (("%s", bit2str(bstr,
				       mod -> md_ptrtab[p -> pe_ucode])));
	    else if (bstr->pe_nbits < LOTSOFBITS)
		VPRINT(("%s", bit2str(bstr, "\020")));
	    else
		VUNKNOWN(pe);
	}
	break;

    case SOBJID:
	if (((OID) oid = prim2oid(pe)) == NULLOID) {
	    goto bad;
	} else {
	    VPRINT(("%s", oid2ode(oid)));
	}
	break;

    case OBJID:
	if (((OID) oid = prim2oid(pe)) == NULLOID) {
	    goto bad;
	} else {
	    VPRINT(("%s", oid2ode(oid)));
	}
	break;

    default:
	return (ppepsylose (mod, p, pe, "p_pr_etype: %d not implemented\n",
	    p->pe_type));
    }

    return (OK);

bad:
    return (NOTOK);
}

/*
 * Is there a match at for this tag and class pair. Return 1 if yes 0
 * if no We will search through contained objects and through choices
 */
p_ismatch(p, mod, cl, tag)
ptpe   *p;
modtyp *mod;			/* Module it is from */
unsigned int cl, tag;
{
    if (!ISDTYPE(p))
	return (0);
    switch (p->pe_type) {
    case SOBJECT:
    case OBJECT:
	/* Needs to be changed for optional and default */
	return (p_ismatch(p = mod->md_ptab[p->pe_tag] + 1, mod, cl, tag));

    case SEXTOBJ:
    case EXTOBJ:
	if (p[1].pe_type != EXTMOD) {
	    (void) ppepsylose (mod, p, NULLPE, "p_ismatch: missing EXTMOD");
	    return (0); /* fixup ismatch return -1 */
	}
	return (p_ismatch(EXT2MOD(mod, (p + 1))->md_ptab[p->pe_tag] + 1,
			  EXT2MOD(mod, (p + 1)), cl, tag));

    case SCHOICE_START:
    case CHOICE_START:
	for (p++; p->pe_type != PE_END; p = NEXT_PTPE(p)) {
	    if (!ISDTYPE(p))
		continue;
	    if (p_ismatch(p, mod, cl, tag))
		return (1);
	}
	return (0);


    case SANY:
	return (1);

    case ANY:
	if (STAG(p) == -1)
	    return (1);
	/* else fall through - not sure if this is needed */

    default:
	return (tag == TAG(p) && cl == CLASS(p));
    }
    /* NOTREACHED */
    /* return (0); */
}

/*
 * determine if the given field is present in the data This is simple
 * if the field is a simple type with an obvious tag but in the case
 * of an object or a CHOICE type the tag is not obvious. If the
 * object is a CHOICE there are more than one possible tag that could
 * match and in this case we must try to match each one of them.
 */
PE
p_setpresent(head, p, mod)
PE      head;
ptpe   *p;
modtyp *mod;
{
    PE      pe;
    modtyp	*nmod;

    while (!ISDTYPE(p) && p->pe_type != PE_END) {
	p++;
    }
    if (!ISDTYPE(p) || p->pe_type == PE_END)
	return (NULLPE);

    switch (p->pe_type) {
    case EXTOBJ:
    case SEXTOBJ:
	/* Needs to be changed for optional and default */
	nmod = EXT2MOD(mod, (p + 1));
	return (p_setpresent(head, p = nmod->md_ptab[p->pe_tag] + 1, nmod));

    case OBJECT:
    case SOBJECT:
	{
	    /* Needs to be changed for optional and default */
	    return (p_setpresent(head, p = mod->md_ptab[p->pe_tag] + 1, mod));
	}

    case SCHOICE_START:
    case CHOICE_START:
	for (p++; p->pe_type != PE_END; p = NEXT_PTPE(p)) {
	    if (!ISDTYPE(p))
		continue;
	    if ((pe = (PE) p_setpresent(head, p, mod)))
		return (pe);
	}
	return (NULLPE);

    default:
	return (set_find(head, CLASS(p), TAG(p)));
    }
}

#ifdef PRINT_DEFAULTS
/*
 * set the default value to that value in the structure
 */
setpval(typ, dflt, mod)
ptpe   *typ, *dflt;
modtyp *mod;
{
    int     len, i;
    integer intval;
    char   *ptr, *optr;
    PE      pe_ptr;

    switch (typ->pe_type) {

    case INTEGER:
	intval = IVAL(mod, dflt);
	(*vfnx) (vfp, "%d (DEFAULT INTEGER)\n", intval);
	break;


#ifdef	PEPSY_REALS
    case REALTYPE:
	(*vfnx) (vfp, "%f (DEFAULT Real)\n", RVAL(mod, dflt));
	break;
#endif

    case BOOLEAN:
	intval = IVAL(mod, dflt);
	/*
	 * (*vfnx) (vfp, "%s  %d (DEFAULT BOOLEAN)\n",
	 * (typ->pe_typename) ? typ->pe_typename : "", charval);
	 */
	(*vfnx) (vfp, "%d (DEFAULT BOOLEAN)\n", intval);
	break;

    case T_NULL:
	/* Only one value */
	break;

    case SBITSTRING:
    case BITSTRING:
	(PE) pe_ptr = strb2bitstr(PVAL(mod, dflt), IVAL(mod, dflt), 0, 0);
	(*vfnx) (vfp, " '");
	optr = ptr = bitstr2strb((PE) pe_ptr, &len);
	for (i = 0; i < len; i += 8)
	    (*vfnx) (vfp, "%.2x", *ptr++);
	(*vfnx) (vfp, "'H (DEFAULT BITSTRING)\n");
	pe_free (pe_ptr);
	free (optr);
	break;

    case SOCTETSTRING:
    case OCTETSTRING:
        ptr = PVAL(mod, dflt);	/* array of octets */
        intval = IVAL(mod, dflt);		/* length of array */
	if (printable(ptr, intval)) {
	    (*vfnx) (vfp, "\"");
	    for (; *ptr && intval-- > 0; ptr++)
                (void) fputc(*ptr, vfp);
	    (*vfnx) (vfp, "\"\n");
	} else {
	    (*vfnx) (vfp, "'");
	    if (ptr) {
		for (; intval-- > 0; ptr++)
		    (*vfnx) (vfp, "%.2x", *ptr & 0xff);
	    }
	    (*vfnx) (vfp, "'H \n");
	}
	break;

    case OBJECT:
	setpval(mod->md_ptab[typ->pe_tag] + 1, dflt, mod);
	break;

    case SOBJECT:
	setpval(mod->md_ptab[typ->pe_tag] + 1, dflt, mod);
	break;

    case IMP_OBJ:
	typ++;

    case ANY:
    case SANY:
    case SEXTOBJ:
    case EXTOBJ:
    case OBJID:
    case SOBJID:
    case SEQ_START:
    case SET_START:
    case -1:			/* Just use the pepy method of null
				 * pointers */
	/*
	 * This is the posy/pepy hack way of doing things at the
	 * moment
	 */
	(char *) ptr = NULL;
	break;

    default:
	return (ppepsylose (mod, p, pe, "setpval: type %d not implemented\n",
	    typ->pe_type));
	break;
    }

}
#endif
/*
 * return non zero if we can print out the string
 */
printable(strptr, len)
char   *strptr;
int	len;
{
    if (strptr == NULL || *strptr == '\0') {
	return (0);
    }

     while (len-- > 0) {
	if (!isprint(*strptr++))
	    return (0);
    }

    return (1);
}

/*
 * (Dump) Print out a printable entry in a human recognisable form
 */
dmp_ptpe(s, p, mod)
char   *s;
modtyp *mod;			/* Module it is from */
ptpe   *p;
{
    int     i, j;
    ptpe  **par, **prev;
    char   *name;

    (void) fprintf(vfp, "%s:(%s)", s, mod->md_name);
    /*
     * Calculate what table it is in - we assume they are in order of
     * increasing address
     */

    par = NULL;
    if (mod->md_ptab != NULL && mod->md_ptab[0] < p) {
	par = mod->md_ptab;
	name = "Printing:";
    }
    if (par == NULL) {
	(void) fprintf(vfp, "can't find entry 0x%x\n", p);
	return;
    }
    prev = par;
    for (i = mod->md_nentries; i > 0; i--) {
	if (*par > p)
	    break;
	par++;
    }
    if (par == prev) {
	(void) ppepsylose (mod, p, NULLPE,
	    "dmp_ptpe:par == prev == 0x%x internal error\n", (int) par);
	return;
    }
    par--;
    j = p - *par;

    (void) fprintf(vfp, "%s type %d + %d ", name, par - prev, j);
    p_pr_entry(p);
}