DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T e

⟦150a33b29⟧ TextFile

    Length: 39567 (0x9a8f)
    Types: TextFile
    Names: »enc.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦041b9c0f8⟧ »EurOpenD22/isode/pepsy.system-6.0.Z« 
        └─⟦d49939f05⟧ 
            └─⟦6a28ec38e⟧ »pepsy.tar« 
                └─⟦this⟧ »pepsy/enc.c« 

TextFile

/* Copyright 1989 CSIRO Division of Information Technology 
 * May be given away but not sold for profit - See Copyright file for details
 */
/*
 * These routines are the driving routines for parsing encoding and printing
 * data
 */
#include	<stdio.h>
#include	<ctype.h>
#include	"../h/psap.h"
#include	"pep.h"
#include	"pepdefs.h"

#ifndef	PEPYPARM
#define PEPYPARM	char *
#endif

extern	PE	pr_seq(), pr_seqof(), pr_set(), pr_setof(), pr_type();
extern	PE	en_seq(), en_seqof(), en_set(), en_setof(), en_type();
extern	PE	pr_choice(), en_choice(), en_etype(), pr_etype(), en_obj();

extern	tpe	*next_tpe();
extern	int	_pverbose;
char	*idname(), *clname();

#define NEXT_TPE(p) p = next_tpe(p)
#define CHKTAG(mod, p, pe)	ismatch(p, mod, pe->pe_class, pe->pe_id) 
/*
 * encode the specified type of the specified module into the given pe
 */
enc_f(typ, mod, pe, explicit, len, buf, parm)
/*ARGSUSED*/
int	typ;	/* which type it is */
modtyp	*mod;	/* Module it is from */
register PE      *pe;
int     explicit;
int    len;
char  *buf;
PEPYPARM parm;
{
    register tpe	*p;

    if (typ < 0 || typ >= mod->md_nentries)
	ferrd(1, "enc_f:Illegal typ %d\n", typ);
    
    p = mod->md_etab[typ];
	if (p->pe_type != PE_START)
		ferr(1, "enc_f: missing PE_START\n");
    p++;
    if (((*pe) = en_obj(parm, p, mod)) == NULLPE)
		return (NOTOK);

    return (OK);
}

/*
 * Encode an object. If the object is a simple type it may have a compressed
 * type reference. If it is a compound type it will not have an offset. This
 * is very important as it means we cannot just use en_type to handle this
 * which must always assume the field can have an offset.
 */
PE
en_obj(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
	PE      pe;
	int	cnt = 0;
	tpe	*tmp;

    if (_pverbose > 5)
	printf("Encoding the type %d\n", p->pe_type);
    while (p->pe_type != PE_END) {

	switch (p->pe_type) {
	case PE_END:
	case PE_START:
		return (NULLPE);

	case UCODE:
		break;

	case ETAG:
	    if ((pe = pe_alloc(CLASS(p), PE_FORM_CONS, TAG(p))) == NULLPE) {
		    printf("en_obj: out of memory");
		    return NULLPE;
	    }
	    switch (p->pe_ucode) {

	    default:
		    p++;
		    pe->pe_cons = en_obj(parm, p, mod);
	    }
	    break;

	case SEQ_START:
	    pe = en_seq(parm, p, mod);
	    break;

	case SEQOF_START:
	    pe = en_seqof(parm, p, mod);
	    break;

	case SET_START:
	    pe = en_set(parm, p, mod);
	    break;

	case SETOF_START:
	    pe = en_setof(parm, p, mod);
	    break;

	case IMP_OBJ:
	    tmp = p++;
	    if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
		  NULL, NULL, (parm));
	    else
		pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
	    pe->pe_class = CLASS(tmp);
	    pe->pe_id = TAG(tmp);
	    break;

	case SOBJECT:
	    pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
	    break;

	case OBJECT:
	    pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
	    break;

	case CHOICE_START:
	    pe = en_choice(parm, p, mod);
	    break;

	default:
	    pe = en_type(parm, p, mod);
	    break;
	}
	if (ISDTYPE(p) && cnt++ > 0) {
	    dmp_tpe("en_obj:compound type found", p, mod);
	    ferr(1, "en_obj:compound type found\n"); 
	}
	if (ISDTYPE(p)) {
	    if (pe == NULLPE) {
		dmp_tpe("en_obj: missing mandatory value", p, mod);
		ferrd(1, "en_obj: %d missing mandatory value\n",
		  p->pe_type);
	    }
	}
	if (ISDTYPE(p) && pe != NULLPE)
	    return (pe);
	/*SUPPRESS 288*/
	next:
	    NEXT_TPE(p);
    }

    return (pe);
}

/*
 * Encode a single type.
 * If a basic type encode it, if a compound type call the appropriate
 * encoding routine
 */
PE
en_type(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
	PE      pe;
	int	cnt = 0;
	int	i;	/* Integer for encoding type */
	tpe	*tmp;
	char	*cp;

    if (_pverbose > 5)
	printf("Encoding the type %d\n", p->pe_type);
    while (p->pe_type != PE_END) {

	switch (p->pe_type) {
	case PE_END:
	case PE_START:
		return (NULLPE);

	case DFLT_F:
	    p++;
	    if (same(p, p - 1, parm, mod)) {
		return (NULLPE);	/* don't encode it */
	    }
	    continue;

	case UCODE:
		break;

	case ETAG:
	    if ((pe = pe_alloc(CLASS(p), PE_FORM_CONS, TAG(p))) == NULLPE) {
		    printf("en_type: out of memory");
		    return NULLPE;
	    }
	    switch (p->pe_ucode) {

	    default:
		    p++;
		    pe->pe_cons = en_etype(parm, p, mod);
	    }
	    break;

#if 0
	case SEQ_START:
		pe = en_seq(parm + p->pe_ucode, p, mod);
		break;

	case SEQOF_START:
		pe = en_seqof(parm + p->pe_ucode, p, mod);
		break;

	case SET_START:
		pe = en_set(parm + p->pe_ucode, p, mod);
		break;

	case SETOF_START:
		pe = en_setof(parm + p->pe_ucode, p, mod);
		break;

	case IMP_OBJ:
		tmp = p++;
		if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
		    enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
		      NULL, NULL, (parm + p->pe_ucode));
		else if (p->pe_type == SOBJECT) {
		    pe = en_obj((char *) parm, mod->md_etab[p->pe_tag] + 1,
			mod);
		} else
		    pe = en_obj(parm + p->pe_ucode,
		       mod->md_etab[p->pe_tag] + 1, mod);
		pe->pe_class = CLASS(tmp);
		pe->pe_id = TAG(tmp);
		break;

	case SOBJECT:
		pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
		break;

	case OBJECT:
		pe = en_obj(parm + p->pe_ucode, mod->md_etab[p->pe_tag] + 1, mod);
		break;

	case CHOICE_START:
		pe = en_choice(parm + p->pe_ucode, p, mod);
		break;
#endif
#if 1
	case SEQ_START:
		pe = en_seq(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	case SEQOF_START:
		pe = en_seqof(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	case SET_START:
		pe = en_set(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	case SETOF_START:
		pe = en_setof(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	case IMP_OBJ:
		tmp = p++;
		if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
		    enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
		      NULL, NULL, *(char **) (parm + p->pe_ucode));
		else if (p->pe_type == SOBJECT) {
		    pe = en_obj((char *) parm, mod->md_etab[p->pe_tag] + 1,
			mod);
		} else
		    pe = en_obj(*(char **) (parm + p->pe_ucode),
		       mod->md_etab[p->pe_tag] + 1, mod);
		pe->pe_class = CLASS(tmp);
		pe->pe_id = TAG(tmp);
		break;
		
	case SOBJECT:
	    pe = en_obj((char *) parm, mod->md_etab[p->pe_tag]+1, mod);
	    break;

	case OBJECT:
	    pe = en_obj(*(char **) (parm + p->pe_ucode),
	      mod->md_etab[p->pe_tag] + 1, mod);
	    break;

	case CHOICE_START:
		pe = en_choice(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	case SEXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		dmp_tpe("en_seq: missing EXTMOD", p, mod);
		ferr(1, "en_seq:internal error\n");
	    }
	    enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		(char *) parm);
	    break;

	case EXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		dmp_tpe("en_seq: missing EXTMOD", p, mod);
		ferr(1, "en_seq:internal error\n");
	    }
	    enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		*(char **) (parm + p->pe_ucode));
	    break;
#endif

	case INTEGER:
	    if (_pverbose > 5) {
		printf("offset is %d\n",p->pe_ucode);
		printf("value is %d\n", *(int *)(parm + p->pe_ucode));
	    }
	    if ((pe = num2prim(*(int *)(parm + p->pe_ucode),
	      CLASS(p), TAG(p))) == NULLPE) {
		printf("en_type:out of memory");
		return (NULLPE);
	    }
	    break;

	case BOOLEAN:
	    if (_pverbose > 5) {
		printf("offset is %d\n",p->pe_ucode);
		printf("value is %d\n", *(char *)(parm + p->pe_ucode));
	    }
	    if ((pe = flag2prim(*(char *)(parm + p->pe_ucode),
	      CLASS(p), TAG(p))) == NULLPE) {
		printf("en_type:out of memory");
		return (NULLPE);
	    }
	    break;

	case T_NULL:
	    if (_pverbose > 5)
		printf("offset is %d\n",p->pe_ucode);

	    if ((pe = pe_alloc(CLASS(p), PE_FORM_PRIM,
		TAG(p))) == NULLPE) {
		    printf("en_type:out of memory");
		    return (NULLPE);
	    }
	    break;
	
	case SCONS_ANY:
	case SANY:
	    (pe = (PE ) parm) -> pe_refcnt++;
	    break;

	case CONS_ANY:
	    (pe = *(PE *) (parm + p->pe_ucode)) -> pe_refcnt++;
	    break;

	case ANY:
	    (pe = *(PE *) (parm + p->pe_ucode)) -> pe_refcnt++;
	    break;

#if 0
	case SEXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		dmp_tpe("en_type: missing EXTMOD", p, mod);
		ferr(1, "en_type:internal error\n");
	    }
	    enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL, parm);
	    break;

	case EXTOBJ:
	    if (p[1].pe_type != EXTMOD) {
		dmp_tpe("en_type: missing EXTMOD", p, mod);
		ferr(1, "en_type:internal error\n");
	    }
	    enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL, parm + p->pe_ucode);
	    break;
#endif

	case SOCTETSTRING:
	    if ((pe = qb2prim((struct qbuf *)parm, CLASS(p), TAG(p)))
	    == NULLPE) {
		printf("en_type:SOCTETSTRING: out of memory");
		return (NULLPE);
	    }
	    break;

	case OCTETSTRING:
	    if ((pe = qb2prim(*(struct qbuf **)(parm + p->pe_ucode),
	      CLASS(p), TAG(p))) == NULLPE) {
		printf("en_type:OCTETSTRING: out of memory");
		return (NULLPE);
	    }
	    break;

	case SBITSTRING:
	    if ((cp = bitstr2strb((PE )parm, &i)) == NULL) {
		    printf("en_type:SBIT STRING: out of memory");
		    return (NULLPE);
	    }
	    if ((pe = strb2bitstr(cp, i, CLASS(p), TAG(p))) == NULLPE) {
		    printf("en_type:SBIT STRING: out of memory");
		    return (NULLPE);
	    }
	    free(cp);
	    if ((pe = bit2prim(pe)) == NULLPE) {
		    printf("en_type:SBIT STRING:bit2prim: out of memory");
		    return (NULLPE);
	    }
	    break;

	case BITSTRING:
	    if ((cp = bitstr2strb(*(PE *)(parm + p->pe_ucode), &i))
	      == NULL) {
		    printf("en_type:BIT STRING: out of memory");
		    return (NULLPE);
	    }
	    if ((pe = strb2bitstr(cp, i, CLASS(p), TAG(p))) == NULLPE) {
		    printf("en_type:BIT STRING: out of memory");
		    return (NULLPE);
	    }
	    free(cp);
	    if ((pe = bit2prim(pe)) == NULLPE) {
		    printf("en_type:BIT STRING:bit2prim: out of memory");
		    return (NULLPE);
	    }
	    break;

	case SOBJID:
	    if ((pe = obj2prim((OID )(parm), CLASS(p), TAG(p))) == NULLPE) {
		    printf("en_type:Object Identifier: out of memory");
		    return (NULLPE);
	    }
	    break;

	case OBJID:
	    if ((pe = obj2prim(*(OID *)(parm + p->pe_ucode), CLASS(p), TAG(p)))
	      == NULLPE) {
		    printf("en_type:Object Identifier: out of memory");
		    return (NULLPE);
	    }
	    break;

	default:
	    dmp_tpe("en_type: type not implemented", p, mod);
	    ferrd(1, "en_type: %d not implemented\n", p->pe_type);
	    break;
	}
	if (ISDTYPE(p) && cnt++ > 0) {
	    dmp_tpe("en_type:compound type found", p, mod);
	    ferr(1, "en_type:compound type found\n"); 
	}
	if (ISDTYPE(p)) {
	    if (pe == NULLPE) {
		dmp_tpe("en_type: missing mandatory value", p, mod);
		ferrd(1, "en_type: %d missing mandatory value\n",
		  p->pe_type);
	    }
	}
	if (ISDTYPE(p) && pe != NULLPE)
	    return (pe);
	/*SUPPRESS 288*/
	next:
	    NEXT_TPE(p);
    }

    return (pe);
}

/*
 * Build a sequence, calling appropriate routines to build each sub type
 */
PE
en_seq(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
	PE      head;
	PE 	pe;
	tpe	*tmp;		/* first entry in list */
	int	*popt = NULL;	/* Pointer to optional field */
	int	optcnt = 0;	/* Number of optionals bits so far */

	if (p->pe_type != SEQ_START)
		ferr(1, "en_seq: missing SEQ_START\n");

	if ((head = pe_alloc (CLASS(p), PE_FORM_CONS, TAG(p))) == NULLPE) {
		printf("en_type: out of memory");
		return (NULLPE);
	}
	p++;

	while (p->pe_type != PE_END) {

	    if (_pverbose > 5)
		printf("en_seq with the type%d\n",p->pe_type);

	    if (ISDTYPE(p) && OPTIONAL(p)) {
		switch (p->pe_type) {
		case INTEGER:
		case BOOLEAN:
		case T_NULL:
		    if (!TESTBIT(*popt, optcnt++))
			goto next;	/* Missing so skip */
		    break;
		
		case ETAG:
		    if (!hasdata(parm, p + 1, mod, popt, optcnt))
			goto next;
		    break;

		case IMP_OBJ:
		    if (p[1].pe_type == SOBJECT && parm == NULL
		    || *((char **)(parm + p[1].pe_ucode)) == NULL)
			goto next;
		    break;

		case SOBJECT:
		    if (((char *)parm) == NULL)
			goto next;
		    break;

		default:
		    if (*((char **)(parm + p->pe_ucode)) == NULL)
			goto next;
		    break;
		}
	    }

	    switch (p->pe_type) {
	    case OPTL:
		popt = (int *)(parm + p->pe_ucode);
		break;

	    case UCODE:
		    break;

	    case ETAG:
		    pe = en_type(parm, p, mod);
		    break;

	    case SEQ_START:
		    pe = en_seq(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SEQOF_START:
		    pe = en_seqof(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SET_START:
		    pe = en_set(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SETOF_START:
		    pe = en_setof(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case IMP_OBJ:
		    tmp = p++;
		    if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
			enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
			  NULL, NULL, *(char **) (parm + p->pe_ucode));
		    else if (p->pe_type == SOBJECT) {
			pe = en_obj((char *) parm, mod->md_etab[p->pe_tag] + 1,
			    mod);
		    } else
			pe = en_obj(*(char **) (parm + p->pe_ucode),
			   mod->md_etab[p->pe_tag] + 1, mod);
		    pe->pe_class = CLASS(tmp);
		    pe->pe_id = TAG(tmp);
		    break;
		    
	    case SOBJECT:
		pe = en_obj((char *) parm, mod->md_etab[p->pe_tag]+1, mod);
		break;
    
	    case OBJECT:
		pe = en_obj(*(char **) (parm + p->pe_ucode),
		  mod->md_etab[p->pe_tag] + 1, mod);
		break;
    
	    case CHOICE_START:
		    pe = en_choice(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SEXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_seq: missing EXTMOD", p, mod);
		    ferr(1, "en_seq:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    (char *) parm);
		break;

	    case EXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_seq: missing EXTMOD", p, mod);
		    ferr(1, "en_seq:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    *(char **) (parm + p->pe_ucode));
		break;

	    default:
		    pe = en_type(parm, p, mod);
		    break;
		    /*
		    ferrd(1, "en_seq: unknown type %d\n", p->pe_type);
		    */
	    }

	    if (_pverbose > 5) {
		print_pe(pe, 1);
		printf("\n\n");
	    }

	    if (ISDTYPE(p) && pe != NULLPE) {
		if (seq_add (head, pe, -1) == NOTOK) {
		    printf("en_seq bad sequence: %s",
		    pe_error (pe -> pe_errno));
		    return (NULLPE);
		}
		if (_pverbose > 7) {
		    print_pe(head, 1);
		    printf("\n\n");
		}
	    }
	next:
	    NEXT_TPE(p);
	}

	return (head);

}


/*
 * Parse a set, calling appropriate routines to parse each sub type
 */
PE
en_set(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
	PE      head;
	PE      pe;
	tpe	*tmp;
	int	*popt = NULL;	/* Pointer to optional field */
	int	optcnt = 0;	/* Number of optionals bits so far */

	if (p->pe_type != SET_START)
		ferr(1, "en_set: missing SET_START\n");

	if ((head = pe_alloc (CLASS(p), PE_FORM_CONS, TAG(p))) == NULLPE) {
		printf("en_set: out of memory");
		return (NULLPE);
	}
	p++;
	while (p->pe_type != PE_END) {

	    if (_pverbose > 5)
		printf("en_set with the type%d\n",p->pe_type);

	    if (ISDTYPE(p) && OPTIONAL(p)) {
		switch (p->pe_type) {
		case INTEGER:
		case BOOLEAN:
		case T_NULL:
		    if (!TESTBIT(*popt, optcnt++))
			goto next;	/* Missing so skip */
		    break;
		
		case ETAG:
		    if (!hasdata(parm, p + 1, mod, popt, optcnt))
			goto next;
		    break;

		case IMP_OBJ:
		    if (p[1].pe_type == SOBJECT && parm == NULL
		    || *((char **)(parm + p[1].pe_ucode)) == NULL)
			goto next;
		    break;

		case SOBJECT:
		    if (((char *)parm) == NULL)
			goto next;
		    break;

		default:
		    if (*((char **)(parm + p->pe_ucode)) == NULL)
			goto next;
		    break;
		}
	    }

	    switch (p->pe_type) {
	    case OPTL:
		popt = (int *) (parm + p->pe_ucode);
		break;

	    case UCODE:
		    break;

	    case ETAG:
		    pe = en_type(parm, p, mod);
		    break;

	    case SEQ_START:
		    pe = en_seq(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SEQOF_START:
		    pe = en_seqof(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SET_START:
		    pe = en_set(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SETOF_START:
		    pe = en_setof(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case IMP_OBJ:
		    tmp = p++;
		    if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
			enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
			  NULL, NULL, *(char **) (parm + p->pe_ucode));
		    else if (p->pe_type == SOBJECT) {
			pe = en_obj((char *) parm, mod->md_etab[p->pe_tag] + 1,
			    mod);
		    } else
			pe = en_obj(*(char **) (parm + p->pe_ucode),
			   mod->md_etab[p->pe_tag] + 1, mod);
		    pe->pe_class = CLASS(tmp);
		    pe->pe_id = TAG(tmp);
		    break;
    
	    case SOBJECT:
		    pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
		    break;
    
	    case OBJECT:
		    pe = en_obj(*(char **) (parm + p->pe_ucode),
		      mod->md_etab[p->pe_tag] + 1, mod);
		    break;
    
	    case CHOICE_START:
		    pe = en_choice(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SEXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_set: missing EXTMOD", p, mod);
		    ferr(1, "en_set:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    parm);
		break;

	    case EXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_set: missing EXTMOD", p, mod);
		    ferr(1, "en_set:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    *(char **) (parm + p->pe_ucode));
		break;

	    default:
		    pe = en_type(parm, p, mod);
		    break;
		    /*
		    ferrd(1, "en_set: unknown type %d\n", p->pe_type);
		    */
	    }

	    if (_pverbose > 5) {
		print_pe(pe, 1);
		printf("\n\n");
	    }

	    if (ISDTYPE(p) && pe != NULLPE) {
		if (set_add (head, pe) == NOTOK) {
		    printf("en_set bad set: %s",
		    pe_error (pe -> pe_errno));
		    return (NULLPE);
		}
	    }

	    if (_pverbose > 7) {
		print_pe(head, 1);
		printf("\n\n");
	    }

	next:
	    NEXT_TPE(p);
	}

    return (head);

}


/*
 * Parse a sequence of calling appropriate routines to parse each sub type
 */
PE
en_seqof(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
    PE      head;
    PE      pe;
    tpe  *start;		/* first entry in list */
    tpe  *tmp;

    if (p->pe_type != SEQOF_START) {
	dmp_tpe("en_seqof: missing SEQOF_START", p, mod);
	ferr(1, "en_seqof: missing SEQOF_START\n");
    }

    if ((head = pe_alloc (CLASS(p), PE_FORM_CONS, TAG(p))) == NULLPE) {
	printf("en_type: out of memory");
	return (NULLPE);
    }
    start = p;
    while ((char *)parm != NULL) {
	p++;
	while (p->pe_type != PE_END) {

	    if (_pverbose > 5)
		printf("en_seqof with the type%d\n",p->pe_type);

	    switch (p->pe_type) {
	    case UCODE:
		break;

	    case ETAG:
		pe = en_type(parm, p, mod);
		break;

	    case SEQ_START:
		pe = en_seq(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	    case SEQOF_START:
		pe = en_seqof(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	    case SET_START:
		pe = en_set(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	    case SETOF_START:
		pe = en_setof(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	    case IMP_OBJ:
		tmp = p++;
		if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
		    enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
		      NULL, NULL, *(char **) (parm + p->pe_ucode));
		else if (p->pe_type == SOBJECT) {
		    pe = en_obj((char *) parm, mod->md_etab[p->pe_tag] + 1,
			mod);
		} else
		    pe = en_obj(*(char **) (parm + p->pe_ucode),
		       mod->md_etab[p->pe_tag] + 1, mod);
		pe->pe_class = CLASS(tmp);
		pe->pe_id = TAG(tmp);
		break;

	    case SOBJECT:
		pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
		break;

	    case OBJECT:
		pe = en_obj(*(char **) (parm + p->pe_ucode),
	  	  mod->md_etab[p->pe_tag] + 1, mod);
		break;

	    case CHOICE_START:
		pe = en_choice(*(char **) (parm + p->pe_ucode), p, mod);
		break;

	    case SEXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_seqof: missing EXTMOD", p, mod);
		    ferr(1, "en_seqof:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    parm);
		break;

	    case EXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_seqof: missing EXTMOD", p, mod);
		    ferr(1, "en_seqof:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    *(char **) (parm + p->pe_ucode));
		break;

	    default:
		pe = en_type(parm, p, mod);
		break;
		/*
		ferrd(1, "en_seqof: unknown type %d\n", p->pe_type);
		*/
	    }
	    if (_pverbose > 5) {
		print_pe(pe, 1);
		printf("\n\n");
	    }

	    if (ISDTYPE(p) && pe != NULLPE) {
		if (seq_add (head, pe, -1) == NOTOK) {
		    printf("en_seqof bad sequence: %s",
		    pe_error (pe -> pe_errno));
		    return (NULLPE);
		}
	    }
	    if (_pverbose > 7) {
		print_pe(head, 1);
		printf("\n\n");
	    }
	/*SUPPRESS 288*/
	next:
	    NEXT_TPE(p);
	}
	parm = *(char **)(parm + p->pe_ucode);		/* Any more ? */
	p = start;
    }

    return (head);

}

/*
 * Parse a setof, calling appropriate routines to parse each sub type
 */
PE
en_setof(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
	PE      head;
	PE      pe, last = NULLPE;
	tpe	*start;
	tpe  *tmp;

	if (p->pe_type != SETOF_START) {
	    dmp_tpe("en_setof: missing SETOF_START", p, mod);
	    ferr(1, "en_setof: missing SETOF_START\n");
	}

	if ((head = pe_alloc (CLASS(p), PE_FORM_CONS, TAG(p))) == NULLPE) {
		printf("en_type: out of memory");
		return (NULLPE);
	}
#if 0
	p++;
	if (p->pe_type != SCTRL)
		ferr(1, "en_setof: missing SCTRL information\n");

	if (p->pe_tag != 0)
		ferr(1, "en_setof: tag field != 0\n");
#endif
	start = p;
	while ((char *)parm != NULL) {
		p++;
		while (p->pe_type != PE_END) {
    if (_pverbose > 5)
	printf("en_setof with the type%d\n", p->pe_type);

			
	    switch (p->pe_type) {
	    case UCODE:
		    break;

	    case ETAG:
		pe = en_type(parm, p, mod);
		break;

	    case SEQ_START:
		    pe = en_seq(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SEQOF_START:
		    pe = en_seqof(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SET_START:
		    pe = en_set(*(char **) (parm + p->pe_ucode), p, mod);
		    break;
    
	    case SETOF_START:
		    pe = en_setof(*(char **) (parm + p->pe_ucode), p, mod);
		    break;

	    case IMP_OBJ:
		    tmp = p++;
		    if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
			enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
			  NULL, NULL, *(char **) (parm + p->pe_ucode));
		    else if (p->pe_type == SOBJECT) {
			pe = en_obj((char *) parm, mod->md_etab[p->pe_tag] + 1,
			    mod);
		    } else
			pe = en_obj(*(char **) (parm + p->pe_ucode),
			   mod->md_etab[p->pe_tag] + 1, mod);
		    pe->pe_class = CLASS(tmp);
		    pe->pe_id = TAG(tmp);
		    break;
    
	    case SOBJECT:
		    pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
		    break;
    
	    case OBJECT:
		    pe = en_obj(*(char **) (parm + p->pe_ucode), mod->md_etab[p->pe_tag] + 1, mod);
		    break;
    
	    case CHOICE_START:
		    pe = en_choice(*(char **) (parm + p->pe_ucode), p, mod);
		    break;

	    case SEXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_setof: missing EXTMOD", p, mod);
		    ferr(1, "en_setof:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    parm);
		break;

	    case EXTOBJ:
		if (p[1].pe_type != EXTMOD) {
		    dmp_tpe("en_setof: missing EXTMOD", p, mod);
		    ferr(1, "en_setof:internal error\n");
		}
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
		    *(char **) (parm + p->pe_ucode));
		break;

	    default:
		    pe = en_type(parm, p, mod);
		    break;
		    /*
		    ferrd(1, "en_seq: unknown type %d\n", p->pe_type);
		    */
	    }

if (_pverbose > 5) {
    print_pe(pe, 1);
    printf("\n\n");
}
	    if (ISDTYPE(p) && pe != NULLPE) {
		    if (set_addon (head, last, pe) == NOTOK) {
				    printf("en_setof bad set: %s",
				    pe_error (pe -> pe_errno));
				    return (NULLPE);
		    }
		    else
			    last = pe;
	    }
if (_pverbose > 7) {
    print_pe(head, 1);
    printf("\n\n");
}
	    /*SUPPRESS 288 */
	    next:
		    NEXT_TPE(p);
	    }
	    parm = *(char **)(parm + p->pe_ucode);	/* Any more ? */
	    p = start;
	}

	return (head);

}

/*
 * encode a choice field. This means find which choice is taken and call
 * en_type to encode it
 */
PE
en_choice(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
    int	cnt;

    if (p->pe_type != CHOICE_START) {
	dmp_tpe("pr_choice:missing CHOICE_START", p, mod);
	ferrd(1, "pr_choice:illegal table entry %d\n", p->pe_type);
    }
    p++;
    if (p->pe_type != SCTRL) {
	dmp_tpe("pr_choice:missing SCTRL", p, mod);
	ferr(1, "en_choice: missing SCTRL information\n");
    }
    
    cnt = *(int *) (parm + p->pe_ucode);
    if (_pverbose > 5)
	printf("cnt is %d\n",cnt);
    if (cnt != 0)
	    cnt--; 
    if (cnt < 0) {
	dmp_tpe("en_choice:offset negative", p, mod);
	return (NULLPE);
    }
    for (p++; p->pe_type != PE_END; NEXT_TPE(p)) {
	    if (ISDTYPE(p)) {
		    if (cnt == 0)
			    return(en_etype(parm, p, mod));
		    cnt--;
	    }
    }
    dmp_tpe("en_choice: no choice taken", p, mod);
    return (NULLPE);
}


/*
 * check to see if the object is present or not
 */
chkobj(mod, p, head)
modtyp	*mod;
tpe	*p;
PE	head;
{

	for (;p->pe_type != PE_END; NEXT_TPE(p)) {
		if (!ISDTYPE(p))
			continue;
		
		if (p->pe_type == OBJECT) {
			if (chkobj(mod, p, head))
				return (1);
		} else if (CHKTAG(mod, p, head))
			return(1);

		if (OPTIONAL(p) || DEFAULT(p))
			continue;

		return (0);
	}
	return (0);
}

/*
	print the PE sructure pointed to by pe
*/
print_pe(pe, n)
PE pe;
int n;
{

	if (pe == NULL)
		return;
	printf("%*s",4*n,"");
#if 0
	printf("error = %d, context = %x, class = %x, form = %x, id = %x\n",
	  pe->pe_errno, pe->pe_context, pe->pe_class, pe->pe_form, pe->pe_id);
#endif
	if (pe->pe_errno)
		printf(" errno = %d", pe->pe_errno);
	if (pe->pe_class == PE_CLASS_UNIV)
		printf(" %s", idname(pe->pe_id));
	else if (pe->pe_class == PE_CLASS_CONT)
		printf("[%d]", pe->pe_id);
	else
		printf("[%s %d]", clname(pe->pe_class), pe->pe_id);

	printf("\n");

#if 0
	printf("%*s",4*n,"");
	printf("cardinality = %d offset = %d\n",pe->pe_cardinal, pe->pe_offset);
#endif
	if (pe->pe_form != 0x0) {
		if (pe->pe_cons != NULLPE)
			print_pe(pe->pe_cons, n + 1);
	}
	else {
		printf("%*s",4*n,"");
		switch(pe->pe_id) {
		    case PE_PRIM_BOOL:
			printf("%d", prim2flag(pe));
			break;

		    case PE_PRIM_INT:
			printf(" %d", prim2num(pe));
			break;
		    case PE_PRIM_BITS:
			prntbits(pe);
			break;

		    case PE_PRIM_OCTS:
			prntos(pe);
			break;

		    case PE_PRIM_NULL:
			break;


		    case PE_DEFN_NUMS:
		    case PE_DEFN_PRTS:
		    case PE_DEFN_T61S:
		    case PE_DEFN_VTXS:
		    case PE_DEFN_IA5S:
		    case PE_DEFN_GFXS:
		    case PE_DEFN_VISS:
		    case PE_DEFN_GENS:
		    case PE_DEFN_CHRS:
			prntstr(pe);
			break;


		    case PE_PRIM_OID:
		    case PE_CONS_EXTN:
		    case PE_PRIM_REAL:
		    case PE_PRIM_ENUM:
		    case PE_PRIM_ENCR:

		    case PE_CONS_SEQ:
		    case PE_CONS_SET:

		    case PE_DEFN_UTCT:
		    case PE_DEFN_GENT:
			default:
				printf("UNimplemented %d ", pe->pe_id);
				break;
		}
		printf("\n");
	}
	if (pe->pe_next != NULLPE) {
	    printf("%*s",4*n,"pe_next:\n");
	    print_pe(pe->pe_next,n);
	}
}

/*
 * return the string describing that class
 */
char	*
clname(cl)
int	cl;
{
    char	*p;
    static   char   buf[30];

    switch (cl) {
    case PE_CLASS_UNIV:
	p = "Universal";
	break;

    case PE_CLASS_APPL:
	p = "Application";
	break;

    case PE_CLASS_CONT:
	p = "Context";
	break;

    case PE_CLASS_PRIV:
	p = "Private";
	break;

    default:
	sprintf(buf, "Unknown Class %d", cl);
	p = buf;
	break;
    }
    return (p);
}


/*
 * return the string describing that identity or the number itself
 * Assuming a Universal class
 */
char	*
idname(id)
int	id;
{
    char	*p;
    static char    buf[40];

    switch (id) {
    case PE_PRIM_BOOL:
	p = "Boolean";
	break;

    case PE_PRIM_INT:
	p = "Integer";
	break;

    case PE_PRIM_BITS:
	p = "Bit String";
	break;

    case PE_PRIM_OCTS:
	p = "Octet String";
	break;

    case PE_PRIM_NULL:
	p = "Null";
	break;

    case PE_PRIM_OID:
	p = "Object Descriptor";
	break;

    case PE_CONS_EXTN:
	p = "External";
	break;

    case PE_PRIM_REAL:
	p = "Real";
	break;

    case PE_PRIM_ENUM:
	p = "Enumerated Type";
	break;

    case PE_PRIM_ENCR:
	p = "Encrypted Type";
	break;

    case PE_CONS_SEQ:
	p = "Sequence";
	break;

    case PE_CONS_SET:
	p = "Set";
	break;

    case PE_DEFN_NUMS:
	p = "Numeric String";
	break;

    case PE_DEFN_PRTS:
	p = "Printable String";
	break;

    case PE_DEFN_T61S:
	p = "T.61 String";
	break;

    case PE_DEFN_VTXS:
	p = "Videotex String";
	break;

    case PE_DEFN_IA5S:
	p = "IA5 String";
	break;

    case PE_DEFN_UTCT:
	p = "UTC Time";
	break;

    case PE_DEFN_GENT:
	p = "Generalised Time";
	break;

    case PE_DEFN_GFXS:
	p = "Graphics String";
	break;

    case PE_DEFN_VISS:
	p = "Visable String";
	break;

    case PE_DEFN_GENS:
	p = "General String";
	break;

    case PE_DEFN_CHRS:
	p = "Character String";
	break;

    default:
	sprintf(buf, "Unknown Universal %d", id);
	p = buf;
	break;
    }
    return (p);
}

/*
 * Encode a single type for an explicit tag field
 * If a basic type encode it, if a compound type call the appropriate
 * encoding routine. Similar to en_type except we do the indirection on the
 * ucode field
 */
PE
en_etype(parm, p, mod)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
{
    tpe *tmp;
    PE      pe;

    switch (p->pe_type) {
    case PE_END:
    case PE_START:
	return (NULLPE);

    case UCODE:
	break;

    case ETAG:
	if ((pe = pe_alloc(CLASS(p), PE_FORM_CONS, TAG(p))) == NULLPE) {
		printf("en_etype: out of memory");
		return NULLPE;
	}
	switch (p->pe_ucode) {
	default:
		p++;
		pe->pe_cons = en_etype(parm, p, mod);
	}
	break;

    case SEQ_START:
	    pe = en_seq(*(char **) (parm + p->pe_ucode), p, mod);
	    break;

    case SEQOF_START:
	    pe = en_seqof(*(char **) (parm + p->pe_ucode), p, mod);
	    break;

    case SET_START:
	    pe = en_set(*(char **) (parm + p->pe_ucode), p, mod);
	    break;

    case SETOF_START:
	    pe = en_setof(*(char **) (parm + p->pe_ucode), p, mod);
	    break;

    case IMP_OBJ:
	    tmp = p++;
	    if (p->pe_type == EXTOBJ || p->pe_type == SEXTOBJ)
		enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1,
		  NULL, NULL, *(char **) (parm + p->pe_ucode));
	    else if (p->pe_type == SOBJECT) {
		pe = en_obj((char *) parm, mod->md_etab[p->pe_tag] + 1,
		    mod);
	    } else
		pe = en_obj(*(char **) (parm + p->pe_ucode),
		   mod->md_etab[p->pe_tag] + 1, mod);
	    pe->pe_class = CLASS(tmp);
	    pe->pe_id = TAG(tmp);
	    break;

    case SOBJECT:
	    pe = en_obj(parm, mod->md_etab[p->pe_tag] + 1, mod);
	    break;

    case OBJECT:
	    pe = en_obj(*(char **) (parm + p->pe_ucode), mod->md_etab[p->pe_tag] + 1, mod);
	    break;

    case CHOICE_START:
	    pe = en_choice(*(char **) (parm + p->pe_ucode), p, mod);
	    break;

    case INTEGER:
            if (_pverbose > 5) {
		printf("offset is %d\n",p->pe_ucode);
		printf("value is %d\n", *(int *)(parm + p->pe_ucode));
	    }
	    if ((pe = num2prim(*(int *)(parm + p->pe_ucode), CLASS(p), TAG(p))) == NULLPE) {
		    printf("en_etype:out of memory");
		    return (NULLPE);
	    }
	    break;

    case BOOLEAN:
	    if (_pverbose > 5) {
		printf("offset is %d\n",p->pe_ucode);
		printf("value is %d\n", *(char *)(parm + p->pe_ucode));
	    }
	    if ((pe = flag2prim(*(char *)(parm + p->pe_ucode), CLASS(p), TAG(p))) == NULLPE) {
		    printf("en_etype:out of memory");
		    return (NULLPE);
	    }
	    break;

    case T_NULL:
	    if (_pverbose > 5)
		printf("offset is %d\n",p->pe_ucode);
	    if ((pe = pe_alloc(CLASS(p), PE_FORM_PRIM, TAG(p))) == NULLPE) {
		    printf("en_etype:out of memory");
		    return (NULLPE);
	    }
	    break;
    
    case SCONS_ANY:
    case SANY:
	    (pe = (PE )parm) -> pe_refcnt++;
	    break;

    case CONS_ANY:
    case ANY:
	    (pe = *(PE *) (parm + p->pe_ucode)) -> pe_refcnt++;
	    break;

    case SEXTOBJ:
	if (p[1].pe_type != EXTMOD) {
	    dmp_tpe("en_etype: missing EXTMOD", p, mod);
	    ferr(1, "en_etype:internal error\n");
	}
	enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL, parm);
	break;

    case EXTOBJ:
	if (p[1].pe_type != EXTMOD) {
	    dmp_tpe("en_etype: missing EXTMOD", p, mod);
	    ferr(1, "en_etype:internal error\n");
	}
	enc_f(p->pe_tag, (modtyp *)p[1].pe_ucode, &pe, 1, NULL, NULL,
	    *(char **) (parm + p->pe_ucode));
	break;

    case SOCTETSTRING:
	    if ((pe = qb2prim((struct qbuf *)parm, CLASS(p), TAG(p))) == NULLPE) {
		    printf("en_etype:SOCTETSTRING: out of memory");
		    return (NULLPE);
	    }
	    break;

    case SBITSTRING:
	    {
		    char	*cp;
		    int	i;

		    if ((cp = bitstr2strb((PE ) parm, &i)) == NULL) {
			    printf("en_etype:SBIT STRING: out of memory");
			    return (NULLPE);
		    }
		    if ((pe = strb2bitstr(cp, i, CLASS(p), TAG(p))) == NULLPE) {
			    printf("en_etype:SBIT STRING: out of memory");
			    return (NULLPE);
		    }
		    free(cp);
	    }
	    break;

    case OCTETSTRING:
	    if ((pe = qb2prim(*(struct qbuf **)(parm + p->pe_ucode), CLASS(p), TAG(p))) == NULLPE) {
		    printf("en_etype:OCTETSTRING: out of memory");
		    return (NULLPE);
	    }
	    break;

    case BITSTRING:
	    {
		    char	*cp;
		    int	i;

		    if ((cp = bitstr2strb(*(PE *)(parm + p->pe_ucode), &i)) == NULL) {
			    printf("en_etype:BIT STRING: out of memory");
			    return (NULLPE);
		    }
		    if ((pe = strb2bitstr(cp, i, CLASS(p), TAG(p))) == NULLPE) {
			    printf("en_etype:BIT STRING: out of memory");
			    return (NULLPE);
		    }
		    free(cp);
	    }
	    break;

    case SOBJID:
	if ((pe = obj2prim((OID )(parm), CLASS(p), TAG(p))) == NULLPE) {
		printf("en_etype:Object Identifier: out of memory");
		return (NULLPE);
	}
	break;

    case OBJID:
	if ((pe = obj2prim(*(OID *)(parm + p->pe_ucode), CLASS(p), TAG(p)))
	  == NULLPE) {
		printf("en_etype:Object Identifier: out of memory");
		return (NULLPE);
	}
	break;

    default:
	    dmp_tpe("en_etype: type not implemented", p, mod);
	    ferrd(1, "en_etype: %d not implemented\n", p->pe_type);
	    break;
    }

    return (pe);
}
/*
 * Print out the value of a bits string
 */
prntbits(pe)
PE	pe;
{
    int	len, i;

    if ((len = pe->pe_nbits) < 0) {
	printf("prntbits:Bad bistring\n");
	return;
    }

    printf("Bits:");
    for (i = 0; i < len; i++)
	if (bit_test(pe, i))
		printf(" %d", i);

    putchar('\n');
}

/*
 * Dump a bunch of hex digits printing out those that are printable
 * Print out a given length of octets as hex (with the ASCII characters
 * given if they have any
 */
pclen(s, len)
register char	*s;
register int	len;
{
	register int	cnt = 0;

	while (len-- > 0) {
		if (cnt % 8 == 0)
			printf("\n%d:", cnt/8 + 1);
		if (isprint(*s&0x7f))
			printf("\t%02x(%c)", *s&0xff, *s&0x7f);
		else
			printf("\t%02x", *s&0xff);
		s++;
		cnt++;
	}
	putchar('\n');
}

/*
 * print out an octet string
 */
prntos(pe)
PE	pe;
{
    struct	qbuf	*qb;

   if ((qb = prim2qb(pe)) == NULL) {
    bad:
	printf("prntos:bad octet string\n");
	return (-1);
    }

    if (qb_pullup(qb) == NOTOK)
	goto bad;
    
    if (qb->qb_forw->qb_data == NULL || qb->qb_forw->qb_len < 0)
	goto bad;
    
    pclen(qb->qb_forw->qb_data, qb->qb_forw->qb_len);
    return (0);
}

/*
 * print out a string which should be printable
 */
prntstr(pe)
PE	pe;
{
    struct	qbuf	*qb;

   if ((qb = prim2qb(pe)) == NULL) {
    bad:
	printf("prntstr:bad string\n");
	return (-1);
    }

    if (qb_pullup(qb) == NOTOK)
	goto bad;
    
    if (qb->qb_forw->qb_data == NULL || qb->qb_forw->qb_len < 0)
	goto bad;
    
    printf("\"%s\"", qb->qb_forw->qb_data);
    return (0);
}
/*
 * Is data present for the optional item? 1 for yes 0 for no
 */
hasdata(parm, p, mod, popt, optcnt)
PEPYPARM parm;
tpe	*p;
modtyp	*mod;	/* Module it is from */
int	*popt, optcnt;
{
	switch (p->pe_type) {
	    case INTEGER:
	    case BOOLEAN:
	    case T_NULL:
		if (DEFAULT(p)) {
		/* Default's don't have bit map */
		    if (p[1].pe_type == DFLT_B && same(p, p + 1, parm, mod)
		     || p[-1].pe_type == DFLT_F && same(p, p - 1, parm, mod))
		       goto next;
		    break;
		}
		if (!TESTBIT(*popt, optcnt++))
		    goto next;	/* Missing so skip */
		break;
	    
	    case ETAG:
		if (!hasdata(parm, p + 1, mod, popt, optcnt))
		    goto next;
		break;

	    case IMP_OBJ:
		if (p[1].pe_type == SOBJECT && parm == NULL
		|| *((char **)(parm + p[1].pe_ucode)) == NULL)
		    goto next;
		break;

	    default:
		if (*((char **)(parm + p->pe_ucode)) == NULL)
		    goto next;
		break;
	}
    return (1);

next:
    return (0);
}

/*
 * determine if the default value is the same as the value in the structure
 * and if so return non zero (meaning don't encode this item). 
 */
same(typ, dflt, parm, mod)
tpe	*typ, *dflt;
char 	*parm;
modtyp	*mod;	/* Module it is from */
{
    int val;
    char	*p1;
    PE	pe;
    struct	qbuf	*qb;

    switch (typ->pe_type) {
    case INTEGER:
	    val = IVAL(dflt) == *(int *)(parm + typ->pe_ucode);
	    break;

    case BOOLEAN:
	    val = IVAL(dflt) == *(char *)(parm + typ->pe_ucode);
	    break;

    case T_NULL:
	    val = 1;	/* Only one value */
	    break;	

    case SBITSTRING:
	if ((pe = (PE )parm) == NULL) {
	    val = 1;
	    break;
	}
	goto bstring;

    case BITSTRING:
	if ((pe = *(PE *)(parm + typ->pe_ucode)) == NULL) {
	    val = 1;
	    break;
	}
    bstring:
	if ((p1 = bitstr2strb(pe, &val)) == NULL)
	    ferr(1, "same:bad bitstring\n");
	if (val != IVAL(dflt) || bitscmp(PVAL(dflt), p1, val))
	    val = 0;
	else
	    val = 1;
	free(p1);
	break;

    case SOCTETSTRING:
	if ((qb = (struct qbuf *)parm) == NULL) {
	    val = 1;
	    break;
	}
	goto ostring;

    case OCTETSTRING:
	if ((qb = *(struct qbuf **)(parm + typ->pe_ucode)) == NULL) {
	    val = 1;
	    break;
	}
    ostring:
	if (ostrcmp(PVAL(dflt), IVAL(dflt), qb))
	    val = 0;
	else
	    val = 1;
	break;

    case OBJECT:
	if (*(char **)(parm + typ->pe_ucode) == NULL) {
	    val = 1; /* to conform with pepy's way of doing default */
	    break;
	}
	val = same(mod->md_etab[typ->pe_tag] + 1, dflt,
	  *(char **) (parm + typ->pe_ucode), mod);
	break;

    case SOBJECT:
	if ((char *)parm == NULL) {
	    val = 1; /* to conform with pepy's way of doing default */
	    break;
	}
	val = same(mod->md_etab[typ->pe_tag] + 1, dflt, parm, mod);
	break;

    case IMP_OBJ:
	typ++;	/* fall through */

    case SCONS_ANY:
    case ANY:
    case CONS_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 */
	    val = *(char **)(parm + typ->pe_ucode) == NULL;
	    break;

    default:
	/* dmp_tpe("same: type not implemented", typ, mod); - need mod*/
	ferrd(1, "same: %d not implemented\n", typ->pe_type);
	break;
    }

    return (val);
}