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

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

/* pepsy.c - table driven posy/pepy replacement system */

/* OPEN QUESTIONS:

	How to do smarter DEFAULT determination for the other types and NULLs

	Perhaps pull-up primitive IDentifiers

	Abort a CHOICE encoding if the structure is empty


				  HEURISTICS

   1. LANGUAGE SIMPLIFICATIONS:


	Pull-up uni-member SEQUENCEs/SETs/CHOICEs


   2. LANGUAGE ASSUMPTIONS:

	Unique tags to avoid conflicts for internal structures (-h1 option)


   3. STYLE ISSUES:

	SEQUENCE/SET OF Type should have Type be an ID for nicer naming
 */

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

/*
 * $Header: /f/osi/pepsy/RCS/pepsy.c,v 7.12 91/02/22 09:49:38 mrose Interim $
 *
 *
 * $Log:	pepsy.c,v $
 * Revision 7.12  91/02/22  09:49:38  mrose
 * Interim 6.8
 * 
 * Revision 7.11  91/01/24  14:51:00  mrose
 * update
 * 
 * Revision 7.10  91/01/08  12:50:24  mrose
 * update
 * 
 * Revision 7.9  90/12/23  17:24:58  mrose
 * patches
 * 
 * Revision 7.8  90/12/11  10:33:57  mrose
 * sync
 * 
 * Revision 7.7  90/11/20  15:27:21  mrose
 * update
 * 
 * Revision 7.6  90/11/11  10:54:05  mrose
 * update
 * 
 * Revision 7.5  90/11/04  19:17:13  mrose
 * update
 * 
 * Revision 7.4  90/10/23  20:43:04  mrose
 * update
 * 
 * Revision 7.3  90/09/07  17:34:20  mrose
 * touch-up
 * 
 * Revision 7.2  90/08/08  14:14:28  mrose
 * update
 * 
 * Revision 7.1  90/07/09  14:52:50  mrose
 * sync
 * 
 * Revision 7.0  90/07/01  19:54:25  mrose
 * *** empty log message ***
 * 
 * Revision 7.3  90/02/23  17:50:09  mrose
 * update
 * 
 * Revision 7.2  90/02/19  13:09:35  mrose
 * update
 * 
 * Revision 7.1  90/01/11  18:37:05  mrose
 * real-sync
 * 
 * Revision 7.0  89/11/23  22:11:59  mrose
 * Release 6.0
 * 
 */

/*
 *				  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.
 *
 */


#include <ctype.h>
#include <stdio.h>
#include <varargs.h>
#include "pepsydefs.h"
#include "pass2.h"


#define	SVAL(s)		((s) ? (s) : "")
#define PARVAL(s)	((s) ? (s) : "parm")

/*    DATA */

static int aflag = 0;
int	Aflag = 0;	/* Don't so all modes by default */
int	Cflag = 0;		/* posy */
int	dflag = 0;
int	Pflag = 0;		/* pepy compat ... */
char    *bflag = NULL;		/*  .. */
char	*iflag = NULL;		/* -i file => #include users file */
char    *module_actions = NULL;
int	pepydebug = 0;
int	doexternals = 1;
static int fflag = 0;
static int linepos = 0;
int mflag = 0;
int sflag = 0;

int p_debug = 3;
int options[NOPTIONS];

char *eval = NULLCP;

char   *mymodule = "";
OID	mymoduleid = NULLOID;
static char modulename[BUFSIZ];

int yysection = YP_DECODER;
char *yyencpref = "encode";
char *yydecpref = "decode";
char *yyprfpref = "print";
char *yyencdflt = "encode";
char *yydecdflt = "decode";
char *yyprfdflt = "print";

static char *classes[] = {
    "UNIVERSAL ",
    "APPLICATION ",
    "",
    "PRIVATE "
};

static char *tags[] = {
    "", "BOOLEAN", "INTEGER", "INTEGER", "BIT STRING", "BIT STRING",
    "OCTET STRING", "NULL", "SEQUENCE", "SEQUENCE OF", "SEQUENCE",  "SET",
    "SET OF", "SET", "CHOICE", "ANY", "OBJECT IDENTIFIER", "", "ENUMERATED",
    "REAL", "",

    NULL
};

struct tuple tuples[] = {
	YP_BOOL, "PE_CLASS_UNIV", "PE_FORM_PRIM", "PE_PRIM_BOOL",
		PE_CLASS_UNIV, PE_PRIM_BOOL,
	YP_INT, "PE_CLASS_UNIV", "PE_FORM_PRIM", "PE_PRIM_INT",
		PE_CLASS_UNIV, PE_PRIM_INT,
	YP_INTLIST, "PE_CLASS_UNIV", "PE_FORM_PRIM", "PE_PRIM_INT",
		PE_CLASS_UNIV, PE_PRIM_INT,
	YP_BIT, "PE_CLASS_UNIV", NULLCP, "PE_PRIM_BITS",
		PE_CLASS_UNIV, PE_PRIM_BITS,
	YP_BITLIST, "PE_CLASS_UNIV", NULLCP, "PE_PRIM_BITS",
		PE_CLASS_UNIV, PE_PRIM_BITS,
	YP_OCT, "PE_CLASS_UNIV", NULLCP, "PE_PRIM_OCTS",
		PE_CLASS_UNIV, PE_PRIM_OCTS,
	YP_NULL, "PE_CLASS_UNIV", NULLCP, "PE_PRIM_NULL",
		PE_CLASS_UNIV, PE_PRIM_NULL,
	YP_OID, "PE_CLASS_UNIV", "PE_FORM_PRIM", "PE_PRIM_OID",
		PE_CLASS_UNIV, PE_PRIM_OID,
	YP_SEQ, "PE_CLASS_UNIV", "PE_FORM_CONS", "PE_CONS_SEQ",
		PE_CLASS_UNIV, PE_CONS_SEQ,
	YP_SEQTYPE, "PE_CLASS_UNIV", "PE_FORM_CONS", "PE_CONS_SEQ",
		PE_CLASS_UNIV, PE_CONS_SEQ,
	YP_SEQLIST, "PE_CLASS_UNIV", "PE_FORM_CONS", "PE_CONS_SEQ",
		PE_CLASS_UNIV, PE_CONS_SEQ,
	YP_SET, "PE_CLASS_UNIV", "PE_FORM_CONS", "PE_CONS_SET",
		PE_CLASS_UNIV, PE_CONS_SET,
	YP_SETTYPE, "PE_CLASS_UNIV", "PE_FORM_CONS", "PE_CONS_SET",
		PE_CLASS_UNIV, PE_CONS_SET,
	YP_SETLIST, "PE_CLASS_UNIV", "PE_FORM_CONS", "PE_CONS_SET",
		PE_CLASS_UNIV, PE_CONS_SET,
	YP_ENUMLIST, "PE_CLASS_UNIV", "PE_FORM_PRIM", "PE_PRIM_ENUM",
		PE_CLASS_UNIV, PE_PRIM_ENUM,
	YP_REAL,     "PE_CLASS_UNIV", "PE_FORM_PRIM", "PE_PRIM_REAL",
		PE_CLASS_UNIV, PE_PRIM_REAL,

	YP_UNDF
};


static char autogen[BUFSIZ];

char   *sysin = NULLCP;
static char sysout[BUFSIZ];
static char sysdef[BUFSIZ];
static char sysact[BUFSIZ];

static FILE *fdef;

typedef struct modlist {
    char   *md_module;
    OID    md_oid;
    int	   md_flags;
#define MDF_SEEN		1	/* Seen this module */

    struct modlist *md_next;
}		modlist, *MD;
#define	NULLMD	((MD) 0)

static  MD	mymodules = NULLMD;

typedef struct symlist {
    char   *sy_encpref;
    char   *sy_decpref;
    char   *sy_prfpref;
    char   *sy_module;
    char   *sy_name;

    YP	    sy_type;

    struct symlist *sy_next;
}		symlist, *SY;
#define	NULLSY	((SY) 0)

SY	mysymbols = NULLSY;


char   *gensym (), *modsym (), *array ();
extern	char	*my_strcat(), *gfree(), *concat(), *my_new_str();
extern	char	*getid();
MD	lookup_module ();
SY	new_symbol (), add_symbol ();
static double val2real ();
static void prime_default ();

extern void exit();	/* to keep lint happy */

FILE   *open_ph_file ();

YP	lookup_type ();

YT  lookup_tag ();

/*    MAIN */

/* ARGSUSED */

main (argc, argv, envp)
int	argc;
char  **argv,
      **envp;
{
    int	    i;
    register char  *cp,
		   *dp;

    dp = pepsyversion + strlen ("pepsy ");
    (void) fprintf (stderr, "pepsy %s\n", dp);

    sysout[0] = sysdef[0] = sysact[0] = NULL;
    for (argc--, argv++; argc > 0; argc--, argv++) {
	cp = *argv;

	if (strcmp (cp, "-A") == 0) {
	    Aflag++;
	    continue;
	}
	if (strcmp (cp, "-a") == 0) {
	    aflag++;
	    continue;
	}
	if (strcmp (cp, "-d") == 0) {
	    dflag++;
	    continue;
	}
	if (strcmp (cp, "-f") == 0) {
	    dflag++, fflag++;
	    continue;
	}
	if (strncmp (cp, "-h", 2) == 0) {
	    if (cp[2] == NULL) {
		hflag++;
		continue;
	    }
	    if (sscanf (cp + 2, "%d", &i) != 1 || i >= NOPTIONS)
		goto usage;
	    hflag++, options[i]++;
	    continue;
	}
	if (strcmp (cp, "-m") == 0) {
	    mflag++;
	    continue;
	}
	if (strcmp (cp, "-s") == 0) {
	    sflag++;
	    continue;
	}
	if (strcmp (cp, "-i") == 0) {
	    argv++;
	    if (argc-- > 0)
		iflag = *argv;
	    continue;
	}

	if (sysin) {
    usage:  ;
	    (void) fprintf (stderr,
		    "usage: pepsy [-A] [-a] [-d] [-f] [-h] [-s] module.py\n");
	    exit (1);
	}

	if (*cp == '-') {
	    if (*++cp != NULL)
		goto usage;
	    sysin = "";
	}
	sysin = cp;
    }

    switch (pepydebug = (cp = getenv ("PEPSYTEST")) && *cp ? atoi (cp) : 0) {
	case 2: 
	    yydebug++;		/* fall */
	case 1: 
	    sflag++;		/*   .. */
	case 0: 
	    break;
    }

    if (sysin == NULLCP)
	sysin = "";

    if (*sysin && freopen (sysin, "r", stdin) == NULL) {
	(void) fprintf (stderr, "unable to read "), perror (sysin);
	exit (1);
    }

    if (strcmp (sysout, "-") == 0)
	sysout[0] = NULL;
    if (*sysout && freopen (sysout, "w", stdout) == NULL) {
	(void) fprintf (stderr, "unable to write "), perror (sysout);
	exit (1);
    }

    if (cp = index (dp, ')')) {
	for (cp++; *cp != ' '; cp++)
	    if (*cp == NULL)
		break;
	if (*cp == NULL)
	    cp = NULL;
    }
    if (cp == NULL)
	cp = dp + strlen (dp);
    (void) sprintf (autogen, "pepsy %*.*s", cp - dp, cp - dp, dp);

    initoidtbl ();

    exit (yyparse ());		/* NOTREACHED */
}

/*    ERRORS */

yyerror (s)
register char   *s;
{
    yyerror_aux (s);

    if (*sysout)
	(void) unlink (sysout);
    if (*sysdef)
	(void) unlink (sysdef);
    if (*sysact)
	(void) unlink (sysact);

    exit (1);
}

#ifndef lint
warning (va_alist)
va_dcl
{
    char	buffer[BUFSIZ];
    char	buffer2[BUFSIZ];
    char	*cp;
    va_list	ap;

    va_start (ap);

    _asprintf (buffer, NULLCP, ap);

    va_end (ap);

    (void) sprintf (buffer2, "Warning: %s", buffer);
    yyerror_aux (buffer2);
}

#else

/* VARARGS1 */
warning (fmt)
char	*fmt;
{
    warning (fmt);
}
#endif

static	yyerror_aux (s)
register char   *s;
{
    if (linepos)
	(void) fprintf (stderr, "\n"), linepos = 0;

    if (eval)
	(void) fprintf (stderr, "type %s: ", eval);
    else
	(void) fprintf (stderr, "line %d: ", yylineno);
    (void) fprintf (stderr, "%s\n", s);
    if (!eval)
	(void) fprintf (stderr, "last token read was \"%s\"\n", yytext);
}

/*  */

#ifndef	lint
myyerror (va_alist)
va_dcl
{
    char    buffer[BUFSIZ];
    va_list ap;

    va_start (ap);

    _asprintf (buffer, NULLCP, ap);

    va_end (ap);

    yyerror (buffer);
}
#else
/* VARARGS */

myyerror (fmt)
char   *fmt;
{
    myyerror (fmt);
}
#endif


#ifndef	lint
static	pyyerror (va_alist)
va_dcl
{
    char    buffer[BUFSIZ];
    register YP	yp;
    va_list	ap;

    va_start (ap);

    yp = va_arg (ap, YP);

    _asprintf (buffer, NULLCP, ap);

    va_end (ap);

    yyerror_aux (buffer);
    print_type (yp, 0);


    if (*sysout)
	(void) unlink (sysout);
    if (*sysdef)
	(void) unlink (sysdef);
    if (*sysact)
	(void) unlink (sysact);

    exit (1);
}
#else
/* VARARGS */

static	pyyerror (yp, fmt)
YP	yp;
char   *fmt;
{
    pyyerror (yp, fmt);
}
#endif

/*  */

yywrap () {
    if (linepos)
	(void) fprintf (stderr, "\n"), linepos = 0;

    return 1;
}

/*  */

/* ARGSUSED */

yyprint (s, f, top)
char    *s;
int	f;
int	top;
{
    int     len;
    static int  nameoutput = 0;
    static int  outputlinelen = 79;
    static int didf = 0;

    if (sflag || !s)
	return;

    if (f && didf == 0) {
	if (linepos)
	    fprintf (stderr, "\n\n");
	else fprintf (stderr, "\n");

        fprintf (stderr, "%s includes:", mymodule);
        linepos = (nameoutput = strlen (mymodule) + 10) + 1;

        didf = 1;
    }

    if (!nameoutput || top) {
	if (linepos)
	    (void) fprintf (stderr, "\n\n");

	(void) fprintf (stderr, "%s", mymodule);
	nameoutput = (linepos = strlen (mymodule)) + 1;

#define section(flag,prefix) \
        if (yysection & (flag)) { \
            fprintf (stderr, " %s", (prefix)); \
            linepos += strlen (prefix) + 1; \
        } \
        else \
            fprintf (stderr, " none"), linepos += 5
        section (YP_ENCODER, yyencpref);
        section (YP_DECODER, yydecpref);
        section (YP_PRINTER, yyprfpref);


	(void) fprintf (stderr, ":");
	linepos += 2;

	if (top)
	    return;
    }

    len = strlen (s) + (f ? 2 : 0);
    if (linepos != nameoutput)
	if (len + linepos + 1 > outputlinelen)
	    (void) fprintf (stderr, "\n%*s", linepos = nameoutput, "");
	else
	    (void) fprintf (stderr, " "), linepos++;
    (void) fprintf (stderr, f ? "(%s)" : "%s", s);
    linepos += len;
}

/*    PASS1 */

pass1 ()
{
}

/*  */

pass1_type (encpref, decpref, prfpref, mod, id, yp)
register char  *encpref,
	       *decpref,
	       *prfpref,
	       *mod,
	       *id;
register YP	yp;
{
    register SY	    sy;

    if (lookup_type (mod, id))	/* no duplicate entries, please... */
	return;

    if (pepydebug) {
	if (linepos)
	    (void) fprintf (stderr, "\n"), linepos = 0;

	(void) fprintf (stderr, "%s.%s\n", mod ? mod : mymodule, id);
	print_type (yp, 0);
	(void) fprintf (stderr, "--------\n");
    }
    else
	if (!(yp -> yp_flags & YP_IMPORTED))
	    yyprint (id, 0, 0);

    sy = new_symbol (encpref, decpref, prfpref, mod, id, yp);
    mysymbols = add_symbol (mysymbols, sy);
}

/*    PASS2 */

pass2 () {
    register SY	    sy;
    register YP	    yp;


    modsym_aux (mymodule, modulename);

    (void) sprintf (sysdef, "%s-types.h", mymodule);
    if ((fdef = fopen (sysdef, "w")) == NULL)
	myyerror ("unable to write %s", sysdef);
    (void) fprintf (fdef, "/* automatically generated by %s, do not edit! */\n\n",
	    autogen);
    (void) fprintf (fdef, "#ifndef\t_module_%s_defined_\n", modulename);
    (void) fprintf (fdef, "#define\t_module_%s_defined_\n\n", modulename);

    (void) fprintf (fdef, "#ifndef\tPEPSY_VERSION\n");
    (void) fprintf (fdef, "#define\tPEPSY_VERSION\t\t%d\n", PEPSY_VERSION_NUMBER);
    (void) fprintf (fdef, "#endif\n\n");

    {
#define NFILES 	5
	char *files[NFILES];
	    /* { "psap.h", "pepsy.h", "UNIV-types.h", (char *)0 }; */

	int last = 0;	/* last slot available in files */

	files[last++] = "psap.h";
	files[last++] = "pepsy.h";

	if (strcmp (mymodule, "UNIV")) {
	    files[last++] = "pepsy/UNIV-types.h";
	}

	 files[last++] = (char *)0;

	 doincl(fdef, files);

#undef NFILES
    }

    if (mflag) {
	    (void) fprintf (fdef, "#ifndef\tPEPYPATH\n");
	    (void) fprintf (fdef, "#include <isode/pepsy/%s%s>\n", mymodule, HFILE1);
	    (void) fprintf (fdef, "#else\n");
	    (void) fprintf (fdef, "#include \"%s%s\"\n", mymodule, HFILE1);
	    (void) fprintf (fdef, "#endif\n");
    }
    else
	    (void) fprintf (fdef, "#include \"%s%s\"\n", mymodule, HFILE1);

    /* User's #include file */
    if (iflag) {
	(void) fprintf (fdef, "#include \"%s\"\n", iflag);
    }

    /*
     * pull up some symbols 
     */
    for (sy = mysymbols; sy; sy = sy -> sy_next) {
	eval = sy -> sy_name;
	yp = sy -> sy_type;
	if (sy -> sy_module == NULLCP)
	    yyerror ("no module name associated with symbol");
	if (yp -> yp_flags & YP_IMPORTED)
	    continue;

	do_struct0 (yp, eval);
	if (ferror (stdout) || ferror (fdef))
	    myyerror ("write error - %s", sys_errname (errno));
    }
    /* dump out the references to the external types */
    proc_extmod(fdef);

    /*
     * generate the #define's for simple type definitions
     */
    for (sy = mysymbols; sy; sy = sy -> sy_next) {
	eval = sy -> sy_name;
	yp = sy -> sy_type;
	if (yp -> yp_flags & YP_IMPORTED)
	    continue;

	do_struct1 (yp, eval, NULLCP);
	if (ferror (stdout) || ferror (fdef))
	    myyerror ("write error - %s", sys_errname (errno));
    }

    /*
     * generate the C structure definitions
     */
    for (sy = mysymbols; sy; sy = sy -> sy_next) {
	eval = sy -> sy_name;
	yp = sy -> sy_type;
	if (yp -> yp_flags & YP_IMPORTED)
	    continue;

	do_struct2 (yp, eval, NULLCP);
	if (ferror (stdout) || ferror (fdef))
	    myyerror ("write error - %s", sys_errname (errno));
    }

    peri_pass2();

    (void) fprintf (fdef, "#endif\n");
    (void) fflush (fdef);
    (void) fflush (stdout);
    if (ferror (stdout) || ferror (fdef))
	myyerror ("write error - %s", sys_errname (errno));
    (void) fclose (fdef);

    write_ph_file();
    if (!sflag) {
	if (linepos) fprintf (stderr, "\n"), linepos = 0;
	(void) fflush (stderr);
    }
}

/*  */

/* ARGSUSED */

static	do_struct0 (yp, id)
register YP	yp;
char   *id;
{
    register YP	    y;
    MD	md;

    switch (yp -> yp_code) {
	case YP_SEQLIST:
	case YP_SETLIST:
	    components_pullup (yp);
	    break;

	default:
	    break;
    }

    switch (yp -> yp_code) {
	case YP_SEQTYPE: 
	case YP_SETTYPE: 
	    do_struct0 (yp -> yp_type, id);
	    break;

	case YP_CHOICE: 
	case YP_SETLIST: 
	    choice_pullup (yp, yp -> yp_code == YP_CHOICE ? CH_FULLY
							  : CH_PARTIAL);
	    /* and fall */
	case YP_SEQLIST: 
	    for (y = yp -> yp_type; y; y = y -> yp_next)
		do_struct0 (y, id);
	    break;

	case YP_IDEFINED: 
	    if (yp -> yp_module && strcmp (yp -> yp_module, mymodule)) {
		if ((md = lookup_module (yp -> yp_module, yp -> yp_modid))
		  == NULLMD || (md->md_flags & MDF_SEEN) == 0) {
			addextmod(yp -> yp_module);
		    if (md)
			md->md_flags |= MDF_SEEN;
		}
	    }
	    /* correct for IMPLICIT Tag of a CHOICE or ANY if possible */
	    if ((yp->yp_flags & (YP_IMPLICIT|YP_TAG)) == (YP_IMPLICIT|YP_TAG)) {
		yp->yp_flags &= ~YP_IMPLICIT; /* clear it */
		yp->yp_flags |= comptag(YP_IMPLICIT, yp);
	    }
	    break;

	default: 
	    break;
    }
}

/*  */

static	do_struct1 (yp, id, pullup)
register YP	yp;
char   *id,
       *pullup;
{
    register int    i,
                    j;
    char    buf1[BUFSIZ];
    register YP	    y;
    register YV	    yv;

    switch (yp -> yp_code) {
	case YP_BIT: 
	case YP_BITLIST: 
	case YP_SEQ: 
	case YP_SET: 
	case YP_ANY: 
	    (void) fprintf (fdef, "\n");
	    if (aflag)
		printag (yp, 4, pullup);
	    (void) fprintf (fdef, "#define\t%s\tPElement\n",
		    modsym (mymodule, id, "type"));
	    if (yp -> yp_code == YP_BITLIST) {
		i = -1;
		for (yv = yp -> yp_value; yv; yv = yv -> yv_next)
		    if ((j = val2int (yv)) < 0)
			pyyerror (yp, "invalid bit number in BIT STRING");
		    else
			if (j > i)
			    i = j;
		if (i < sizeof (int) * 8) {	/* NBBY */
		    (void) fprintf (fdef, "#define\t%s\t\"\\020",
			    modsym (mymodule, eval, "bits"));
		    for (yv = yp -> yp_value; yv; yv = yv -> yv_next)
			if (yv -> yv_flags & YV_NAMED)
			    (void) fprintf (fdef, "\\0%o%s",
				    val2int (yv) + 1, yv -> yv_named);
			else
			    (void) fprintf (fdef, "\\0%oBIT%d",
				    val2int (yv) + 1, val2int (yv));
		    (void) fprintf (fdef, "\"\n");
		}
		for (yv = yp -> yp_value; yv; yv = yv -> yv_next) {
		    modsym_aux (yv -> yv_named, buf1);
		    (void) fprintf (fdef, "#define\t%s_%s\t%d\n",
			    modsym (mymodule, eval, "bit"),
			    buf1, val2int (yv));
		}
	    }
	    if (fflag)
		(void) fprintf (fdef, "#define\t%s\tpe_free\n",
			modsym (mymodule, id, "free"));
	    break;

	case YP_OCT: 
	    (void) fprintf (fdef, "\n");
	    if (aflag)
		printag (yp, 4, pullup);
	    (void) fprintf (fdef, "#define\t%s\tqbuf\n",
		    modsym (mymodule, id, "type"));
	    if (fflag)
		(void) fprintf (fdef, "#define\t%s\tqb_free\n",
			modsym (mymodule, id, "free"));
	    break;

	case YP_OID: 
	    (void) fprintf (fdef, "\n");
	    if (aflag)
		printag (yp, 4, pullup);
	    (void) fprintf (fdef, "#define\t%s\tOIDentifier\n",
		    modsym (mymodule, id, "type"));
	    if (fflag)
		(void) fprintf (fdef, "#define\t%s\toid_free\n",
			modsym (mymodule, id, "free"));
	    break;

	case YP_IDEFINED: 
	    (void) fprintf (fdef, "\n");
	    if (aflag)
		printag (yp, 4, pullup);
	    (void) fprintf (fdef, "#define\t%s\t",
		    modsym (mymodule, id, "type"));
	    (void) fprintf (fdef, "%s\n",
		    modsym (yp -> yp_module, yp -> yp_identifier, "type"));
	    if (fflag) {
		(void) fprintf (fdef, "#define\t%s\t",
			modsym (mymodule, id, "free"));
		(void) fprintf (fdef, "%s\n",
			modsym (yp -> yp_module, yp -> yp_identifier, "free"));
	    }
	    break;

	case YP_SEQLIST: 
	case YP_SETLIST: 
	case YP_CHOICE: 
	    if (hflag && (y = yp -> yp_type) && !y -> yp_next) {
		do_struct1 (y, id, tags[yp -> yp_code]);
		break;
	    }
	/* else fall */

	default: 
	    break;
    }
}

/*  */

static	do_struct2 (yp, id, pullup)
register YP	yp;
char   *id,
       *pullup;
{
    register YP	    y;
    int	flg = (yp -> yp_code == YP_SEQTYPE || yp -> yp_code == YP_SETTYPE);

    switch (yp -> yp_code) {
	case YP_BIT: 
	case YP_BITLIST: 
	case YP_SEQ: 
	case YP_SET: 
	case YP_ANY: 
	case YP_OCT: 
	case YP_OID: 
	case YP_IDEFINED: 
	    break;

	case YP_SEQLIST: 
	case YP_SETLIST: 
	case YP_CHOICE: 
	    if (hflag && (y = yp -> yp_type) && !y -> yp_next) {
		do_struct2 (y, id, tags[yp -> yp_code]);
		break;
	    }
	    /* else fall */

	default: 
	    (void) fprintf (fdef, "\n");
	    if (aflag)
		printag (yp, 4, pullup);
	    (void) fprintf (fdef, "struct %s {\n", modsym (mymodule, id, "type"));
	    pepsy (yp, 1, 1, "parm", id, "parm", flg && h2flag);
	    (void) fprintf (fdef, "};\n");
	    (void) fprintf (fdef, "#define\t%s(parm)\\\n\t%s\n", modsym (mymodule, id, "free"), gfree(mymodule, id, "parm"));
		
	    break;
    }
}

/*  */

/* ARGSUSED */

static	do_type1 (yp, top, level, id, var, action2, direction)
register YP yp;
int	top,
	level;
char   *id,
       *var,
       *action2;
int	direction;
{
    int	    i;
    char   *cp,
	   *ep,
	    buffer[BUFSIZ],
    	    varbuf[BUFSIZ];
    register YP	    y;
    register YV	    yv;
    register YT	    yt;

    (void) printf ("%*s", level * 4, "");

    if (yp -> yp_flags & YP_ID) {
	(void) printf ("%s", yp -> yp_id);
	if (!(yp -> yp_flags & YP_TAG))
	    (void) printf ("\n%*s", ++level * 4, "");
    }

    if (yp -> yp_flags & YP_TAG) {
	yt = yp -> yp_tag;
	(void) printf ("[%s%d]\n", classes[yt -> yt_class], val2int (yt -> yt_value));
	level++;
	(void) printf ("%*s", level * 4, "");
    }
    if (yp -> yp_flags & YP_OPTIONAL && yp -> yp_varexp) {
	if ((ep = index (yp -> yp_varexp, ' ')) == NULL)
	    yyerror ("Bug in varexp!");

	(void) sprintf (varbuf, "%*.*s", ep - yp -> yp_varexp,
			ep - yp -> yp_varexp, yp -> yp_varexp);
    }

    switch (yp -> yp_code) {
	case YP_BOOL: 
	    if ((yp -> yp_flags & (YP_OPTIONAL|YP_DEFAULT)) &&
		direction == YP_DECODER) {
		if (!top && !(yp -> yp_flags & (YP_ID | YP_TAG)))
		    (void) printf ("dummy-for-default\n%*s", ++level * 4, "");
		if (yp -> yp_flags & YP_OPTIONAL)
		    (void) printf ("%%{ %s -> optionals |= %s; %%}\n%*s",
			    varbuf, yp -> yp_optcontrol, level * 4, "");
		else
		    (void) printf ("%%{ %s%s = %d; %%}\n%*s",
			    var, SVAL (yp -> yp_varexp),
			    val2int (yp -> yp_default) ? 1 : 0, level * 4, "");
	    }
	    break;

	case YP_INT: 
	    if ((yp -> yp_flags & (YP_OPTIONAL|YP_DEFAULT)) &&
		direction == YP_DECODER) {
		if (!top && !(yp -> yp_flags & (YP_ID | YP_TAG)))
		    (void) printf ("dummy-for-default\n%*s", ++level * 4, "");
		if (yp -> yp_flags & YP_OPTIONAL)
		    (void) printf ("%%{ %s -> optionals |= %s; %%}\n%*s",
			    varbuf, yp -> yp_optcontrol, level * 4, "");
		else
		    (void) printf ("%%{ %s%s = %d; %%}\n%*s",
			    var, SVAL (yp -> yp_varexp),
			    val2int (yp -> yp_default), level * 4, "");
	    }
	    break;

	case YP_INTLIST:
	case YP_ENUMLIST:
	    if ((yp -> yp_flags & (YP_OPTIONAL|YP_DEFAULT)) &&
		direction == YP_DECODER) {
		if (!top && !(yp -> yp_flags & (YP_ID | YP_TAG)))
		    (void) printf ("dummy-for-default\n%*s", ++level * 4, "");
		if (yp -> yp_flags & YP_OPTIONAL)
		    (void) printf ("%%{ %s -> optionals |= %s; %%}\n%*s",
			    varbuf, yp -> yp_optcontrol, level * 4, "");
		else
		    (void) printf ("%%{ %s%s = %d; %%}\n%*s",
			    var, SVAL (yp -> yp_varexp), dfl2int (yp),
			    level * 4, "");
	    }
	    break;

	case YP_REAL: 
	    if ((yp -> yp_flags & (YP_OPTIONAL|YP_DEFAULT)) &&
		direction == YP_DECODER) {
		if (!top && !(yp -> yp_flags & (YP_ID | YP_TAG)))
		    (void) printf ("dummy-for-default\n%*s", ++level * 4, "");
		if (yp -> yp_flags & YP_OPTIONAL)
		    (void) printf ("%%{ %s -> optionals |= %s; %%}\n%*s",
			    varbuf, yp -> yp_optcontrol, level * 4, "");
		else
		    (void) printf ("%%{ %s%s = %g; %%}\n%*s",
			    var, SVAL (yp -> yp_varexp),
			    val2real (yp -> yp_default), level * 4, "");
	    }
	    break;

	case YP_NULL:
	    if ((yp -> yp_flags & YP_OPTIONAL) && direction == YP_DECODER) {
		if (!top && !(yp -> yp_flags & (YP_ID | YP_TAG)))
		    (void) printf ("dummy-for-default\n%*s", ++level * 4, "");
		(void) printf ("%%{ %s -> optionals |= %s; %%}\n%*s",
			varbuf, yp -> yp_optcontrol, level * 4, "");
	    }
	    break;
    }

    if ((yp -> yp_flags & (YP_TAG | YP_IMPLICIT)) == (YP_TAG | YP_IMPLICIT))
	(void) printf ("IMPLICIT ");
    if (yp -> yp_flags & YP_BOUND)
	(void) printf ("%s < ", yp -> yp_bound);
    if (yp -> yp_flags & YP_COMPONENTS)
	(void) printf ("COMPONENTS OF ");
    if (yp -> yp_flags & YP_ENCRYPTED)
	(void) printf ("ENCRYPTED ");

    switch (yp -> yp_code) {
	case YP_BOOL: 
	    (void) printf ("BOOLEAN");
	    switch (direction) {
		case YP_ENCODER: 
		case YP_DECODER: 
		    (void) printf (top ? "\n%*s[[b %s -> %s ]]" : "\n%*s[[b %s%s ]]",
			    level * 4, "", var, SVAL (yp -> yp_varexp));
		    break;
	    }
	    break;

	case YP_INT: 
	    (void) printf ("INTEGER");
	    switch (direction) {
		case YP_ENCODER: 
		case YP_DECODER: 
		    (void) printf (top ? "\n%*s[[i %s -> %s ]]" : "\n%*s[[i %s%s ]]",
			    level * 4, "", var, SVAL (yp -> yp_varexp));
		    break;
	    }
	    break;

	case YP_INTLIST:
	case YP_ENUMLIST:
	    if (yp -> yp_code == YP_ENUMLIST)
		(void) printf ("ENUMERATED");
	    else
		(void) printf ("INTEGER");
	    switch (direction) {
		case YP_ENCODER: 
		case YP_DECODER: 
		    (void) printf (top ? "\n%*s[[i %s -> %s ]]\n%*s{\n"
			    : "\n%*s[[i %s%s ]]\n%*s{\n",
			    level * 4, "", var, SVAL (yp -> yp_varexp),
			    level * 4, "");
		    break;

		default: 
		    (void) printf (" {\n");
		    break;
	    }
	    level++;
	    for (yv = yp -> yp_value; yv; yv = yv -> yv_next)
		(void) printf ("%*s%s(%d)%s\n", level * 4, "", yv -> yv_named,
			val2int (yv), yv -> yv_next ? "," : "");
	    level--;
	    (void) printf ("%*s}", level * 4, "");
	    break;

	case YP_BIT: 
	    (void) printf ("BIT STRING");
	    switch (direction) {
		case YP_ENCODER: 
		    (void) printf ("\n%*s[[x bit_parm = bitstr2strb (%s%s, &len) $ len]]",
			    level * 4, "", var, SVAL (yp -> yp_varexp));
		    (void) printf ("\n%*s%%{\n%*sfree (bit_parm);\n", level * 4, "",
			    (level + 1) * 4, "");
		    if (action2)
			(void) printf ("%*s%s\n", (level + 1) * 4, "", action2);
		    (void) printf ("%*s%%}\n", level * 4, "");
		    break;

		case YP_DECODER: 
		    balloc (yp, var, action2, level);
		    break;
	    }
	    break;

	case YP_BITLIST: 
	    (void) printf ("BIT STRING");
	    switch (direction) {
		case YP_ENCODER: 
		    (void) printf ("\n%*s[[x bit_parm = bitstr2strb (%s%s, &len) $ len]]\n%*s{\n",
			    level * 4, "", var, SVAL (yp -> yp_varexp),
			    level * 4, "");
		    break;

		case YP_DECODER: 
		default: 
		    (void) printf (" {\n");
		    break;
	    }
	    level++;
	    for (yv = yp -> yp_value; yv; yv = yv -> yv_next)
		(void) printf ("%*s%s(%d)%s\n", level * 4, "", yv -> yv_named,
			val2int (yv), yv -> yv_next ? "," : "");
	    level--;
	    (void) printf ("%*s}", level * 4, "");
	    switch (direction) {
		case YP_DECODER: 
		    balloc (yp, var, action2, level);
		    break;

		case YP_ENCODER:
		    (void) printf ("\n%*s%%{\n%*sfree (bit_parm);\n", level * 4, "",
			    (level + 1) * 4, "");
		    if (action2)
			(void) printf ("%*s%s\n", (level + 1) * 4, "", action2);
		    (void) printf ("%*s%%}\n", level * 4, "");
		    break;
	    }
	    break;

	case YP_OCT: 
	    (void) printf ("OCTET STRING");
	    switch (direction) {
		case YP_ENCODER: 
		    (void) printf ("\n%*s[[q %s%s ]]", level * 4, "",
			    var, SVAL (yp -> yp_varexp));
		    break;

		case YP_DECODER: 
		    (void) printf ("\n%*s[[q %s%s ]]", level * 4, "",
			    var, SVAL (yp -> yp_varexp));
		    break;
	    }
	    break;

	case YP_REAL:
	    (void) printf ("REAL");
	    (void) printf (top ? "\n%*s[[r %s -> %s ]]" : "\n%*s[[r %s%s ]]",
		    level * 4, "", var, SVAL (yp -> yp_varexp));
	    break;

	case YP_NULL: 
	    (void) printf ("NULL");
	    break;

	case YP_SEQ: 
	case YP_SET:
	case YP_ANY:
	    (void) printf ("%s", tags[yp -> yp_code]);
	    switch (direction) {
		case YP_ENCODER:
		case YP_DECODER:
			(void) printf ("\n%*s[[a %s%s ]]",
				level * 4, "", var, SVAL (yp -> yp_varexp));
		    break;
	    }
	    break;

	case YP_SEQTYPE: 
	case YP_SETTYPE: 
	    ep = yp -> yp_code != YP_SETTYPE ? "element" : "member";
	    (void) printf ("%s\n", tags [yp -> yp_code]);
	    switch (direction) {
		case YP_ENCODER: 
		    if ((y = yp -> yp_type) -> yp_declexp) {
			(void) printf ("%*s%%{ %s = %s; %%}\n",
				(level + 1) * 4, "", y -> yp_declexp,
				SVAL (y -> yp_varexp));
		    }
		    if (h2flag) {
			if (top) {
			    (void) printf ("%*s<<n_parm = 0; ", (level + 1) * 4, "");
			    (void) printf ("n_parm < parm -> nelem; n_parm++>>\n");
			}
			else {
			    (void) printf ("%*s<<n_%s = 0;\n%*sn_%s < %s -> nelem;\n",
				    (level + 1) * 4, "", yp -> yp_declexp,
				    (level + 3) * 4, "", yp -> yp_declexp,
				    yp -> yp_declexp);
			    (void) printf ("%*sn_%s++>>\n",
				    (level + 3) * 4, "", yp -> yp_declexp);
			}
		    }
		    else {
			if (top)
			    (void) printf ("%*s<<; parm; parm = parm -> next>>\n",
				    (level + 1) * 4, "");
			else
			    (void) printf ("%*s<<%s = %s%s;\n%*s%s;\n%*s%s = %s -> next>>\n",
				    (level + 1) * 4, "", yp -> yp_declexp,
				    var, SVAL (yp -> yp_varexp),
				    (level + 3) * 4, "", yp -> yp_declexp,
				    (level + 3) * 4, "", yp -> yp_declexp,
				    yp -> yp_declexp);
		    }
		    break;

		case YP_DECODER: 
		    if (h2flag) {
			y = yp -> yp_type;
			xalloc (y, 0, level + 2, y -> yp_declexp,
				y -> yp_declexp, 1);
		    }
		    else
			xalloc (yp, 0, level + 1,
				top ? "parm" : yp -> yp_declexp,
				top ? modsym (mymodule, eval, "type")
				: yp -> yp_declexp, 1);
		    break;
	    }
	    do_type1 (yp -> yp_type, 0, level + 1, ep, "", NULLCP, direction);
	    switch (direction) {
		case YP_DECODER:
		    (void) printf ("\n%*s%%{ ", (level + 1) * 4, "");
		    if (h2flag)
			(void) printf ("n_%s++;", top ? "parm" : yp -> yp_declexp);
		    else
			if (top)
			    (void) printf ("parm = &((*parm) -> next);");
			else
			    (void) printf ("%s = &((*%s) -> next);",
				    yp -> yp_declexp, yp -> yp_declexp);
		    if (action2)
			(void) printf (" %s", action2);
		    (void) printf (" %%}");
		    break;
	    }
	    break;

	case YP_SEQLIST: 
	case YP_SETLIST: 
	    ep = yp -> yp_code != YP_SETLIST ? "element" : "member";
	    (void) printf ("%s", tags [yp -> yp_code]);
	    (void) printf ("\n%*s%%{\n", (level + 1) * 4, "");
	    if (direction == YP_DECODER)
		xalloc (yp, 1, level + 2, yp -> yp_declexp,
			yp -> yp_declexp, 0);
	    for (y = yp -> yp_type; y; y = y -> yp_next) {
		if (y -> yp_declexp)
		    switch (direction) {
		    case YP_ENCODER: 
			(void) printf ("%*s%s = %s;\n",
				(level + 2) * 4, "",
				y -> yp_declexp, y -> yp_varexp);
			break;

		    case YP_DECODER:
			(void) printf ("%*s%s = &(%s);\n",
				(level + 2) * 4, "",
				y -> yp_declexp, y -> yp_varexp);
			break;
		    }
		if (direction == YP_DECODER &&
			 y -> yp_flags & YP_DEFAULT) {
		    prime_default (y, level + 2);
		}
	    }
	    (void) printf ("%*s%%}\n%*s{\n", (level + 1) * 4, "",
		    level * 4, "");
	    
	    if (!hflag || !(y = yp -> yp_type) || y -> yp_next) {
		var = "";
		top = 0;
	    }
	    for (y = yp -> yp_type; y; y = y -> yp_next) {
		do_type1 (y, top,
			level + ((y -> yp_flags & (YP_ID | YP_TAG)) ? 1 : 2),
			ep, var, NULLCP, direction);
		(void) printf ("%s\n", y -> yp_next ? ",\n" : "");
	    }
	    (void) printf ("%*s}", level * 4, "");
	    break;

	case YP_CHOICE: 
	    (void) printf ("CHOICE");
	    if (!hflag || !(y = yp -> yp_type) || y -> yp_next)
		var = "";
	    i = 0;
	    for (y = yp -> yp_type; y; y = y -> yp_next)
		if (y -> yp_declexp)
		    i++;
	    switch (direction) {
		case YP_ENCODER: 
		    if (i) {
			(void) printf ("\n%*s%%{\n", (level + 1) * 4, "");
			for (y = yp -> yp_type; y; y = y -> yp_next)
			    if (y -> yp_declexp)
				(void) printf ("%*s%s = %s;\n", (level + 2) * 4, "",
					y -> yp_declexp, y -> yp_varexp);
			(void) printf ("%*s%%}\n%*s", (level + 1) * 4, "",
				(level + 1) * 4 - 1, "" );
		    }
		    if (*var)
			(void) printf (" <<1>>");
		    else
			if (top)
			    (void) printf (" <<parm -> offset>>");
			else
			    (void) printf (" <<%s -> offset>>",
				    yp -> yp_declexp);
		    (void) printf (i ? "\n%*s{\n" : " {\n", level * 4, "");
		    break;

		case YP_DECODER: 
		    (void) printf ("\n");
		    xalloc (yp, 0, level + 1, yp -> yp_declexp,
			    yp -> yp_declexp, 1);
		    (void) printf ("%*s{\n", level * 4, "");
		    break;

		default: 
		    (void) printf (" {\n");
		    break;
	    }
	    if (direction == YP_DECODER) {
		(void) sprintf (cp = buffer, "(*(%s)) -> offset = ",
			    top ? "parm" : yp -> yp_declexp);
		cp += strlen (cp);
	    }
	    else
		cp = NULL;
	    if (!hflag || !(y = yp -> yp_type) || y -> yp_next)
		top = 0;
	    else
		if (top)
		    cp = NULL;
	    for (y = yp -> yp_type; y; y = y -> yp_next) {
		if (cp)
		    (void) sprintf (cp, "%s;", y -> yp_offset);
		do_type1 (y, top, level + 1, "choice", var,
			cp ? buffer : NULLCP, direction);
		(void) printf ("%s\n", y -> yp_next ? ",\n" : "");
	    }
	    (void) printf ("%*s}", level * 4, "");
	    break;
	
	case YP_OID: 
	    (void) printf ("OBJECT IDENTIFIER");
	    switch (direction) {
		case YP_ENCODER: 
		case YP_DECODER: 
		    (void) printf ("\n%*s[[O %s%s ]]",
			    level * 4, "", var, SVAL (yp -> yp_varexp));
		    break;
	    }
	    break;

	case YP_IDEFINED: 
	    if (yp -> yp_module && strcmp (yp -> yp_module, mymodule))
		(void) printf ("%s.", yp -> yp_module);
	    (void) printf ("%s", yp -> yp_identifier);
	    switch (direction) {
		case YP_ENCODER: 
		    (void) printf ("\n%*s[[p %s%s ]]",
			    level * 4, "", var, SVAL (yp -> yp_varexp));
		    break;

		case YP_DECODER: 
		    (void) printf ("\n%*s[[p &(%s%s)]]",
			    level * 4, "", var, SVAL (yp -> yp_varexp));
		    break;
	    }
	    break;

	default: 
	    myyerror ("unknown type: %d", yp -> yp_code);
    }

    if (action2)
	switch (yp -> yp_code) {
	    case YP_BIT:
	    case YP_BITLIST:
	    	if (direction == YP_ENCODER)
		    break;
	    case YP_SEQTYPE:
	    case YP_SETTYPE:
		if (direction == YP_DECODER)
		    break;
		/* else fall */

	    default:		
		(void) printf ("\n%*s%%{ %s %%}", level * 4, "", action2);
		break;
	}

    if (yp -> yp_flags & YP_OPTIONAL) {
	(void) printf ("\n%*sOPTIONAL", level * 4, "");

	if (direction == YP_ENCODER)
	    switch (yp -> yp_code) {
		case YP_BOOL: 
		case YP_INT: 
		case YP_INTLIST:
	    	case YP_ENUMLIST:
		case YP_NULL:
		case YP_REAL:
		    (void) printf (" <<%s -> optionals & %s >>",
			    varbuf, yp -> yp_optcontrol);
		default: 
		    break;

		case YP_BIT: 
		case YP_BITLIST: 
		case YP_OCT: 
		case YP_SEQ: 
		case YP_SEQTYPE: 
		case YP_SEQLIST: 
		case YP_SET: 
		case YP_SETTYPE: 
		case YP_SETLIST: 
		case YP_CHOICE: 
		case YP_ANY: 
		case YP_OID: 
		case YP_IDEFINED: 
		    (void) printf (" <<%s%s>>", var, SVAL (yp -> yp_varexp));
		    break;
	    }
    }
    else
	if (yp -> yp_flags & YP_DEFAULT) {
	    (void) printf ("\n%*sDEFAULT ", level * 4, "");
	    val2prf (yp -> yp_default, level + 2);

	    if (direction == YP_ENCODER)
		switch (yp -> yp_code) {
		    case YP_BOOL: 
			(void) printf (" <<%s%s%s>>",
				val2int (yp -> yp_default) ? "!" : "",
				var, SVAL (yp -> yp_varexp));
			break;

		    case YP_INT: 
		    case YP_INTLIST:
		    case YP_ENUMLIST:
			(void) printf (" <<%s%s != %d>>", var, SVAL (yp -> yp_varexp),
				dfl2int (yp));
			break;

		    case YP_REAL:
			(void) printf (" << %s%s != %g >>",
				var, SVAL (yp -> yp_varexp),
				val2real (yp -> yp_default));
			break;

		    case YP_NULL: 
		    default: 
			break;

		    case YP_BIT: 
		    case YP_BITLIST: 
		    case YP_OCT: 
		    case YP_SEQ: 
		    case YP_SEQTYPE: 
		    case YP_SEQLIST: 
		    case YP_SET: 
		    case YP_SETTYPE: 
		    case YP_SETLIST: 
		    case YP_CHOICE: 
		    case YP_ANY: 
		    case YP_OID: 
		    case YP_IDEFINED: 
			(void) printf (" <<%s%s>>", var, SVAL (yp -> yp_varexp));
			break;
		}
	}

    if (direction == YP_ENCODER
	    && yp -> yp_varexp
	    && (cp = index (yp -> yp_varexp, ' '))
	    && strncmp (cp + 1, "-> ", 3) == 0) {
	*cp = NULL;
	(void) sprintf (buffer, "(*%s) -> %s", yp -> yp_varexp, cp + 4);
	yp -> yp_varexp = new_string (buffer);
    }
}

/*    TYPE HANDLING */

YP  lookup_type (mod, id)
register char *mod,
	      *id;
{
    register SY	    sy;

    for (sy = mysymbols; sy; sy = sy -> sy_next) {
	if (mod) {
	    if (strcmp (sy -> sy_module, mod))
		continue;
	}
	else
	    if (strcmp (sy -> sy_module, mymodule)
		    && strcmp (sy -> sy_module, "UNIV"))
		continue;

	if (strcmp (sy -> sy_name, id) == 0)
	    return sy -> sy_type;
    }

    return NULLYP;
}

/*  */

pepsy (yp, top, level, id, val, var, arrayflg)
register YP	yp;
int	top,
	level,
        arrayflg;
char   *id,
       *val,
       *var;
{
    register int    i,
		    j;
    register char  *bp;
    char   *cp,
	   *dp,
           *ep,
    	   *newid,
            buf1[BUFSIZ],
	    buf2[BUFSIZ],
	    buf3[BUFSIZ];
    register YP	    y;
    register YV	    yv;

    (void) strcpy (bp = buf2, var);
    bp += strlen (bp);
    /* Preserve the name of the field */
    yp->yp_varexp = new_string(yp -> yp_ptrname ? yp -> yp_ptrname : id);

    switch (yp -> yp_code) {
	case YP_BOOL: 
	    if (aflag)
		printag (yp, level + 4, NULLCP);
	    (void) fprintf (fdef, "%*schar    %s;\n", level * 4, "",
		     array(id, arrayflg));
	    break;

	case YP_INT: 
	case YP_INTLIST:
	case YP_ENUMLIST:
	    if (aflag)
		printag (yp, level + 4, NULLCP);
	    (void) fprintf (fdef, "%*sinteger     %s;\n", level * 4, "",
		     array(id, arrayflg));
	    if (yp -> yp_code == YP_INT)
		break;
	    for (yv = yp -> yp_value; yv; yv = yv -> yv_next) {
		modsym_aux (yv -> yv_named, buf1);
		(void) fprintf (fdef, "#define\t%s_%s\t%d\n",
			modsym (mymodule, top ? eval : id, "int"),
			buf1, val2int (yv));
	    }
	    break;

	case YP_BIT: 
	case YP_BITLIST: 
	    if (!top) {
		if (aflag)
		    printag (yp, level + 4, NULLCP);
		(void) fprintf (fdef, "%*sPE      %s;\n", level * 4, "",
			 array(id, arrayflg));
	    }
	    if (yp -> yp_code != YP_BITLIST)
		break;
	    i = -1;
	    for (yv = yp -> yp_value; yv; yv = yv -> yv_next)
		if ((j = val2int (yv)) < 0)
		    pyyerror (yp, "invalid bit number in BIT STRING");
		else
		    if (j > i)
			i = j;
	    if (i < sizeof (int) * 8) {		/* NBBY */
		(void) fprintf (fdef, "#define\t%s\t\"\\020",
			modsym (mymodule, top ? eval : id, "bits"));
		for (yv = yp -> yp_value; yv; yv = yv -> yv_next)
		    if (yv -> yv_flags & YV_NAMED)
			(void) fprintf (fdef, "\\0%o%s",
				val2int (yv) + 1, yv -> yv_named);
		    else
			(void) fprintf (fdef, "\\0%oBIT%d",
				val2int (yv) + 1, val2int (yv));
		(void) fprintf (fdef, "\"\n");
	    }
	    for (yv = yp -> yp_value; yv; yv = yv -> yv_next) {
		modsym_aux (yv -> yv_named, buf1);
		(void) fprintf (fdef, "#define\t%s_%s\t%d\n",
			modsym (mymodule, top ? eval : id, "bit"),
			buf1, val2int (yv));
	    }
	    break;

	case YP_REAL: 
	    if (aflag)
		printag (yp, level + 4, NULLCP);
	    (void) fprintf (fdef, "%*sdouble    %s;\n", level * 4, "",
		     array(id, arrayflg));
	    yp -> yp_varexp = new_string (buf2);
	    break;

	case YP_OCT: 
	    if (!top) {
		if (aflag)
		    printag (yp, level + 4, NULLCP);
		(void) fprintf (fdef, "%*sstruct qbuf *%s;\n", level * 4, "",
			 array(id, arrayflg));
	    }
	    break;

	case YP_NULL: 
	    if (aflag)
		printag (yp, level + 4, NULLCP);
	    (void) fprintf (fdef, "%*schar    %s;\n", level * 4, "",
		     array(id, arrayflg));
	    break;

	case YP_SEQ: 
	case YP_SET: 
	case YP_ANY: 
	    if (!top) {
		if (aflag)
		    printag (yp, level + 4, NULLCP);
		(void) fprintf (fdef, "%*sPE      %s;\n", level * 4, "",
			 array(id, arrayflg));
	    }
	    break;

	case YP_SEQTYPE: 
	case YP_SETTYPE: 
	    ep = yp -> yp_code != YP_SETTYPE ? "element" : "member";
	    if ((cp = rindex (buf2, ' ')) && *++cp) {
		if ((dp = rindex (cp, '.')) && *++dp)
		    cp = dp;
		(void) sprintf (dp = buf1, "%*.*s",
			cp - buf2, cp - buf2, buf2);
		dp += strlen (dp);
	    }
	    else {
		(void) strcpy (buf1, buf2);
		dp = NULL;
	    }
	    newid = yp -> yp_ptrname ? yp -> yp_ptrname : id;
	    if (h2flag && top)
		(void) fprintf (fdef, "%*sinteger\tnelem;\n", level * 4, "");
	    if (!top) {
		if (yp -> yp_structname)
		    id = yp -> yp_structname;
		else if (!Hflag)
		    id = gensym (ep, NULLCP);
		if (aflag)
		    printag (yp, level + 4, NULLCP);
		(void) fprintf (fdef, "%*sstruct %s {\n", level * 4, "", id);
		if (h2flag)
		    (void) fprintf (fdef, "%*sinteger\tnelem;\n", (level + 1) * 4, "");
	    }
	    if (dp)
		(void) strcpy (dp, newid);
	    (void) strcpy (bp = buf2, id);
	    bp += strlen (bp);

	    if (!top)
		yp -> yp_declexp = new_string (id);

	    if (dp)
		(void) strcpy (dp, newid);
	    if ((y = yp -> yp_type) -> yp_code == YP_IDEFINED && hflag) {
		modsym_aux (y -> yp_identifier, cp = buf3);
		if (h2flag) {
		    cp += strlen(cp);
		    (void) sprintf (cp, "[n_%s]", PARVAL (yp->yp_declexp));
		    cp = buf3;
		}
	    }
	    else {
		switch (y -> yp_code) {
		case YP_SEQLIST:
		case YP_SETLIST:
		case YP_SETTYPE:
		case YP_SEQTYPE:
		case YP_CHOICE:
		case YP_IDEFINED:
		    cp = gensym (ep, h2flag ? PARVAL(yp->yp_declexp) : NULLCP);
		    break;
		default:
		    cp = gensym (ep, NULLCP);
		    break;
		}
	    }
	    (void) sprintf (bp, " -> %s", cp);
	    level++;
	    pepsy (y, 0, level, cp, ep, buf2, h2flag);
	    *bp = NULL;
	    if (y -> yp_code != YP_IDEFINED)
		free (cp);
	    if (!h2flag)
		(void) fprintf (fdef, "\n%*sstruct %s *next;\n", level * 4, "",
			 top ? modsym (mymodule, val, "type") : id);

	    level--;

	    (void) strcpy (bp = buf2, var);
	    bp += strlen (bp);

	    if (!top) {
		(void) fprintf (fdef, "%*s} *%s;\n", level * 4, "",
			 array(newid, arrayflg));
		if (!Hflag)
		    free (id);
	    }
	    break;

	case YP_SEQLIST: 
	case YP_SETLIST: 
	    ep = yp -> yp_code != YP_SETLIST ? "element" : "member";
	    if ((cp = rindex (buf2, ' ')) && *++cp) {
		if ((dp = rindex (cp, '.')) && *++dp)
		    cp = dp;
		(void) sprintf (dp = buf1, "%*.*s",
			cp - buf2, cp - buf2, buf2);
		dp += strlen (dp);
	    }
	    else {
		(void) strcpy (buf1, buf2);
		dp = NULL;
	    }
	    newid = yp -> yp_ptrname ? yp -> yp_ptrname : id;
	    if (!top) {
		if (yp -> yp_structname)
		    id = yp -> yp_structname;
		else if (!Hflag)
		    id = gensym (ep, NULLCP);
		if (aflag)
		    printag (yp, level + 4, NULLCP);
		(void) fprintf (fdef, "%*sstruct %s {\n", level * 4, "", id);

		if (dp)
		    (void) strcpy (dp, newid);

		(void) strcpy (bp = buf2, id);
		bp += strlen (bp);
		yp -> yp_declexp = new_string (id);

		level++;
	    }
	    if (dp)
		(void) strcpy (dp, newid);
	    for (y = yp -> yp_type, i = 0; y; y = y -> yp_next) {
		if (y -> yp_flags & YP_OPTIONAL)
		    switch (y -> yp_code) {
		        case YP_BOOL:
		        case YP_INT:
		        case YP_INTLIST:
			case YP_ENUMLIST:
			case YP_REAL:
			case YP_NULL:
		    	    {
				char obuf[BUFSIZ];
				
				if (i == 0)
				    (void) fprintf (fdef, "%*sinteger     optionals;\n",
					     level * 4, "");
				if (y -> yp_flags & YP_ID)
				    modsym_aux (y -> yp_id, cp = buf1);
				else {
				    cp = gensym (ep, NULLCP);
				    (void) strcpy (buf1, cp);
				    free (cp);
				    cp = buf1;
				}
				(void) sprintf (obuf, "%s_%s",
						modsym (mymodule,
							top ? eval : id,
							"opt"), cp);
				(void) fprintf (fdef, "#define\t%s (0%08o)\n", obuf,
					 1 << i);
#ifdef ASN1_OUTPUT
				y -> yp_optcontrol = new_string (obuf);
				y -> yp_flags |= YP_OPTCONTROL;
#endif

				i ++;
				if (i >= 8 * sizeof (int))
				    yyerror ("too many optionals in structure");
			    }
			    break;
			}
	    }
	    if (i > 0) (void) fprintf (fdef, "\n");

	    for (y = yp -> yp_type, i = 1; y; y = y -> yp_next, i++) {
		if (y -> yp_flags & YP_ID)
		    modsym_aux (y -> yp_id, cp = buf1);
		else
		    cp = gensym (ep, NULLCP);
		(void) sprintf (bp, " -> %s", cp);
		pepsy (y, 0, level, cp, ep, buf2, 0);
		*bp = NULL;
		if (!(y -> yp_flags & YP_ID))
		    free (cp);
		if (y -> yp_next)
		    (void) fprintf (fdef, "\n");
	    }
	    if (i == 1)
		(void) fprintf (fdef, "%*schar    dummy;\n", level * 4, "");
	    if (!top) {
		level--;

		(void) strcpy (bp = buf2, var);
		bp += strlen (bp);

		(void) fprintf (fdef, "%*s} *%s;\n", level * 4, "",
			 array(newid, arrayflg));
		if (!Hflag)
		    free (id);
	    }
	    break;

	case YP_CHOICE: 
	    if ((cp = rindex (buf2, ' ')) && *++cp) {
		if ((dp = rindex (cp, '.')) && *++dp)
		    cp = dp;
		(void) sprintf (dp = buf1, "%*.*s",
			cp - buf2, cp - buf2, buf2);
		dp += strlen (dp);
	    }
	    else {
		(void) strcpy (buf1, buf2);
		dp = NULL;
	    }
	    newid = yp -> yp_ptrname ? yp -> yp_ptrname : id;
	    if (!top) {
		if (yp -> yp_structname)
		    id = yp -> yp_structname;
		else if (!Hflag)
		    id = gensym ("choice", NULLCP);
		if (aflag)
		    printag (yp, level + 4, NULLCP);
		(void) fprintf (fdef, "%*sstruct %s {\n", level * 4, "", id);

		if (dp)
		    (void) strcpy (dp, newid);
		(void) strcpy (bp = buf2, id);
		bp += strlen (bp);
		yp -> yp_declexp = new_string (id);

		level++;
	    }
	    if (dp)
		(void) strcpy (dp, newid);
	    (void) fprintf (fdef, "%*sint         offset;\n", level * 4, "");
	    if (top)
		cp = modsym (mymodule, val, "type");
	    else
		cp = id;
	    (void) sprintf (ep = buf1, "%s_", cp);
	    ep += strlen (ep);
	    for (y = yp -> yp_type, i = 1; y; y = y -> yp_next, i++) {
		if (y -> yp_flags & YP_ID)
		    modsym_aux (y -> yp_id, ep);
		else
		    (void) sprintf (ep, "%d", i);
		y -> yp_offset = new_string (buf1);
		(void) fprintf (fdef, "#define\t%s\t%d\n", y -> yp_offset, i);
	    }
	    (void) fprintf (fdef, "\n%*sunion {\n", level * 4, "");
	    level++;
	    for (y = yp -> yp_type; y; y = y -> yp_next) {
		char	*t;

		if (y -> yp_flags & YP_ID)
		    modsym_aux (y -> yp_id, cp = buf1);
		else
		    cp = gensym ("choice", NULLCP);
		(void) sprintf (bp, " -> un.%s", cp);
		pepsy (y, 0, level, cp, "choice", buf2, 0);
    /* prefix yp_varexp (field name) with un. so we will generate offsets that
     * allow for the union all the CHOICE fields are imbedded in
     */
		t = y->yp_varexp;
		y->yp_varexp = my_strcat("un.",  t);
		free(t);

		*bp = NULL;
		if (!(y -> yp_flags & YP_ID))
		    free (cp);
		if (y -> yp_next)
		    (void) fprintf (fdef, "\n");
	    }
	    level--;
	    (void) fprintf (fdef, "%*s}       un;\n", level * 4, "");
	    if (!top) {
		level--;

		(void) strcpy (bp = buf2, var);
		bp += strlen (bp);

		(void) fprintf (fdef, "%*s} *%s;\n", level * 4, "",
			 array(newid, arrayflg));
		if (!Hflag)
		    free (id);
	    }
	    break;

	case YP_OID: 
	    if (!top) {
		if (aflag)
		    printag (yp, level + 4, NULLCP);
		(void) fprintf (fdef, "%*sOID     %s;\n", level * 4, "",
			 array(id, arrayflg));
	    }
	    break;

	case YP_IDEFINED: 
	    if (aflag)
		printag (yp, level + 4, NULLCP);
	    {
		/* Predefined Universal Type */
		struct univ_typ *p;
		if ((p = univtyp(yp->yp_identifier))) {
		    (void) fprintf (fdef, "%*s%s%s;\n", level * 4, "",
			p->univ_data, array(id, arrayflg));
		    /*
                    if (fflag)
                        ferr(1, "pepsy:YP_IDEFINED:fflag not implemented\n");
		    */
		    break;
		}
	    }
	    (void) fprintf (fdef, "%*sstruct %s *%s;\n", level * 4, "",
		    modsym (yp -> yp_module, yp -> yp_identifier, "type"),
		    array(id, arrayflg));
	    break;

	default: 
	    myyerror ("unknown type: %d", yp -> yp_code);
    }
}

/*  */

static	printag (yp, level, pullup)
register YP	yp;
int	level;
char   *pullup;
{
    (void) fprintf (fdef, "%*s/* ", level * 4, "");
    switch (yp -> yp_code) {
	case YP_IDEFINED: 
	    if (yp -> yp_module && strcmp (yp -> yp_module, mymodule))
		(void) fprintf (fdef, "%s.", yp -> yp_module);
	    (void) fprintf (fdef, "%s", yp -> yp_identifier);
	    break;

	default: 
	    (void) fprintf (fdef, "%s", tags[yp -> yp_code]);
	    break;
    }
    if (pullup)
	(void) fprintf (fdef, " pulled up from %s", pullup);
    (void) fprintf (fdef, " */\n");
}

/*  */

static	xalloc (yp, top, level, arg, type, brackets)
register YP	yp;
int	top,
	level,
	brackets;
char   *arg,
       *type;
{
    int	    didone;
    register YP	    y;

    if (hflag && !arg && !type)
	return;

    didone = 0;

    if (arg && type) {
	if (brackets && !didone) {
	    (void) printf ("%*s%%{\n", level * 4, "");
	    level++, didone++;
	}

	if (h2flag && (yp -> yp_code == YP_SEQTYPE ||
		       yp -> yp_code == YP_SETTYPE)) {
	    (void) printf ("%*s{\n%*sPE      xx_pe = prim2%s ($$);\n\n",
		    level * 4, "", (level +1) * 4, "",
		    yp -> yp_code == YP_SEQTYPE ? "seq" : "set");
	    (void) printf ("%*sn_%s = xx_pe -> pe_cardinal > 0 ",
		    (level + 1) * 4, "", arg);
	    (void) printf ("? xx_pe -> pe_cardinal : 0;\n%*s}\n", level * 4, "");
	    (void) printf ("%*sif ((*(%s) = (struct %s *)\n",
		    level * 4, "", arg, type);
	    (void) printf ("%*scalloc (1 + (unsigned) n_%s, sizeof **(%s)",
		    (level + 2) * 4, "", arg, arg);
	    (void) printf (")) == ((struct %s *) 0)) {\n", type);
	    (void) printf ("%*sadvise (NULLCP, \"%%s\", PEPY_ERR_NOMEM);\n",
		    (level + 1) * 4, "");
	    (void) printf ("%*sreturn NOTOK;\n%*s}\n", (level + 1) * 4, "",
		    level * 4, "");
	    (void) printf ("%*s(*%s) -> nelem = n_%s;\n", level * 4, "", arg, arg);
	    (void) printf ("%*sn_%s = 0;\n", level * 4, "", arg);
	} else {
	    (void) printf ("%*sif ((*(%s) = (struct %s *)\n",
		    level * 4, "", arg, type);
	    (void) printf ("%*scalloc (1, sizeof **(%s))) == ((struct %s *) 0)) {\n",
		    (level + 2) * 4, "", arg, type);
	    (void) printf ("%*sadvise (NULLCP, \"%%s\", PEPY_ERR_NOMEM);\n",
		    (level + 1) * 4, "");
	    (void) printf ("%*sreturn NOTOK;\n%*s}\n", (level + 1) * 4, "",
		    level * 4, "");
	}
    }
    switch (yp -> yp_code) {
    case YP_SEQTYPE:
    case YP_SETTYPE:
	if (top) break;
    case YP_CHOICE:
    case YP_SEQLIST:
    case YP_SETLIST:
	for (y = yp -> yp_type; y; y = y -> yp_next)
	    switch (y -> yp_code) {
	    case YP_SEQTYPE: 
	    case YP_SETTYPE:
		if (h2flag && (yp -> yp_code == YP_SETLIST ||
			       yp -> yp_code == YP_SEQLIST)) {
		    /* include allocation here - no chance later */
		    if (brackets && !didone) {
			(void) printf ("%*s%%{\n", level * 4, "");
			level++, didone++;
		    }
		    if (y -> yp_declexp)
			(void) printf ("%*s%s = &(%s);\n", level * 4, "",
				y -> yp_declexp,
				y -> yp_varexp);
		    xalloc (y, top, level, y -> yp_declexp,
			    y -> yp_declexp, 0);
		}
		/* and continue ... */
	    case YP_SEQLIST: 
	    case YP_SETLIST: 
	    case YP_CHOICE:
		if (brackets && !didone) {
		    (void) printf ("%*s%%{\n", level * 4, "");
		    level++, didone++;
		}
		(void) printf ("%*s%s = &(%s);\n",
			level * 4, "", y -> yp_declexp,
			y -> yp_varexp);
		break;
	    }
	break;
    }

    if (brackets && didone) {
	level--;
	(void) printf ("%*s%%}\n", level * 4, "");
    }
}


static	balloc (yp, var, action2, level)
register YP	yp;
char   *var, *action2;
int	level;
{
    (void) printf ("\n%*s%%{\n", level * 4, "");
    level++;

    (void) printf ("%*sif ((%s%s = prim2bit (pe_cpy ($$))) == NULLPE) {\n",
	    level * 4, "", var, SVAL (yp -> yp_varexp));
    (void) printf ("%*sadvise (NULLCP, \"%%s\", PEPY_ERR_NOMEM);\n", (level + 1) * 4, "");
    (void) printf ("%*sreturn NOTOK;\n%*s}\n", (level + 1) * 4, "", level * 4, "");

    if (action2)
	(void) printf ("\n%*s%s\n", level * 4, "", action2);

    level--;
    (void) printf ("%*s%%}", level * 4, "");
}

#ifdef	notdef
static	qalloc (yp, var, action2, level)
register YP	yp;
char   *var,
       *action2;
int	level;
{
    (void) printf ("\n%*s%%{\n", level * 4, "");
    level++;

    (void) printf ("%*sif ((%s%s = str2qb ($$, $$_len, 1)) == ((struct qbuf *) 0)) {\n",
	    level * 4, "", var, SVAL (yp -> yp_varexp));
    (void) printf ("%*sadvise (NULLCP, \"%%s\", PEPY_ERR_NOMEM);\n", (level + 1) * 4, "");
    (void) printf ("%*sreturn NOTOK;\n%*s}\n", (level + 1) * 4, "", level * 4, "");

    if (action2)
	(void) printf ("\n%*s%s\n", level * 4, "", action2);

    level--;
    (void) printf ("%*s%%}", level * 4, "");
}
#endif

/*  */

/*
 * now we don't pull up things if they have actions associated with them
 * this should be okay for those who want exact posy equivalence and
 * yet keep those who want the pepy support able to have multiple
 * actions in CHOICE { CHOICE {} } and such like
 */
static	choice_pullup (yp, partial)
register YP	yp;
int	partial;
{
    register YP	   *x,
		    y,
		    z,
		   *z1,
		    z2,
		    z3;

    for (x = &yp -> yp_type; y = *x; x = &y -> yp_next) {
	if (y -> yp_flags & (YP_TAG | YP_BOUND))
	    continue;

	switch (y -> yp_code) {
	    case YP_IDEFINED:
		if ((z = lookup_type (y -> yp_module, y -> yp_identifier))
			== NULLYP
			|| z -> yp_code != YP_CHOICE)
		    continue;
		if (z -> yp_control_act || z ->yp_bef_alist || z-> yp_aft_alist)
		    continue;

		choice_pullup (z2 = copy_type (z), CH_FULLY);
		goto patch;

	    case YP_CHOICE:
		if (y -> yp_control_act || y ->yp_bef_alist || y-> yp_aft_alist)
		    continue;

		choice_pullup (z2 = copy_type (y), CH_FULLY);
patch: ;
		if (partial) {
		    *x = z2;
		    z2 -> yp_next =  y -> yp_next;
		    continue;
		}
		break;

	    default:
		continue;
	}
	z = z3 = z2 -> yp_type;
	for (z1 = &z -> yp_next; z2 = *z1; z1 = &z2 -> yp_next)
	    z3 = z2;
	*z1 = y -> yp_next;
	*x = z;
	y = z3;
    }
}

/*  */

static	components_pullup (yp)
register YP	yp;
{
    register YP    *x,
		    y,
		    z,
		    z1,
		    z2;

    for (x = &yp -> yp_type; y = *x; x = &y -> yp_next) {
	if (!(y -> yp_flags & YP_COMPONENTS))
	    continue;

	switch (y -> yp_code) {
	    case YP_SEQLIST:
	    case YP_SETLIST:
	        z = y;
		break;

	    case YP_IDEFINED:
		if ((z = lookup_type (y -> yp_module, y -> yp_identifier))
		        == NULLYP) {
		    warning ("COMPONENTS OF target \"%s\" is undefined",
			     y -> yp_identifier);
		    continue;
		}
		break;
	}
	if (yp -> yp_code != z -> yp_code) {
	    warning ("COMPONENTS OF target \"%s\" is wrong type, should be %s",
		     y -> yp_code == YP_IDEFINED ? y -> yp_identifier
		     				 : y -> yp_id ? y -> yp_id
						 : "",
		     yp -> yp_code == YP_SEQLIST ? "SEQUENCE" : "SET");
	    continue;
	}
	if (z -> yp_type == NULLYP)
	    continue;
	components_pullup (z = copy_type (z));
	*x = z2 = z -> yp_type;
	for (x = &z -> yp_type; z1 = *x; x = &z1 -> yp_next)
	    z2 = z1;
	*x = y -> yp_next;
	y = z2;
    }
}

/*    VALUE HANDLING */

static int  val2int (yv)
register YV	yv;
{
    switch (yv -> yv_code) {
	case YV_BOOL:
	case YV_NUMBER:
	    return yv -> yv_number;

	case YV_STRING:
	    yyerror ("need an integer, not a string");

	case YV_IDEFINED:
	case YV_IDLIST:
	    yyerror ("haven't written symbol table for values yet");

	case YV_NULL:
	    yyerror ("need an integer, not NULL");

	default:
	    myyerror ("unknown value: %d", yv -> yv_code);
    }
/* NOTREACHED */
}

static double  val2real (yv)
register YV	yv;
{
    switch (yv -> yv_code) {
	case YV_NUMBER:
	    return yv -> yv_number;

	case YV_REAL:
	    return yv -> yv_real;

	case YV_STRING:
	    yyerror ("need an integer, not a string");

	case YV_IDEFINED:
	case YV_IDLIST:
	    yyerror ("haven't written symbol table for values yet");

	case YV_NULL:
	    yyerror ("need an integer, not NULL");

	default:
	    myyerror ("unknown value: %d", yv -> yv_code);
    }
/* NOTREACHED */
}

/*  */

static	val2prf (yv, level)
register YV	yv;
int	level;
{
    register YV    y;

    if (yv -> yv_flags & YV_ID)
	(void) printf ("%s ", yv -> yv_id);

    if (yv -> yv_flags & YV_TYPE)	/* will this REALLY work??? */
	do_type1 (yv -> yv_type, 0, level, NULLCP, NULLCP, NULLCP, NULL);

    switch (yv -> yv_code) {
	case YV_BOOL: 
	    (void) printf (yv -> yv_number ? "TRUE" : "FALSE");
	    break;

	case YV_NUMBER: 
	    if (yv -> yv_named)
		(void) printf ("%s", yv -> yv_named);
	    else
		(void) printf ("%d", yv -> yv_number);
	    break;

	case YV_REAL:
	    dump_real (yv -> yv_real);
	    break;

	case YV_STRING: 
	    (void) printf ("\"%s\"", yv -> yv_string);
	    break;

	case YV_IDEFINED: 
	    if (yv -> yv_module)
		(void) printf ("%s.", yv -> yv_module);
	    (void) printf ("%s", yv -> yv_identifier);
	    break;

	case YV_IDLIST: 
	case YV_VALIST: 
	    (void) printf ("{");
	    for (y = yv -> yv_idlist; y; y = y -> yv_next) {
		(void) printf (" ");
		val2prf (y, level + 1);
		(void) printf (y -> yv_next ? ", " : " ");
	    }
	    (void) printf ("}");
	    break;

	case YV_NULL: 
	    (void) printf ("NULL");
	    break;

	default: 
	    myyerror ("unknown value: %d", yv -> yv_code);
	/* NOTREACHED */
    }
}
static dump_real (r)
double	r;
{
#ifndef	BSD44
	extern char *ecvt ();
	char	*cp;
	char	sbuf[128];
	int	decpt, sign;

	cp = ecvt (r, 20, &decpt, &sign);
	(void) strcpy (sbuf, cp);	/* cp gets overwritten by printf */
	(void) printf ("{ %s%s, 10, %d }", sign ? "-" : "", sbuf,
		decpt - strlen (sbuf));
#else
    register char   *cp,
		    *dp,
		    *sp;
    char    sbuf[128];

    (void) sprintf (sbuf, "%.19e", r);
    if (*(dp = sbuf) == '-')
	sp = "-", dp++;
    else
	sp = "";
    
    if (dp[1] != '.' || (cp = index (dp, 'e')) == NULL) {
	(void) printf ("{ 0, 10, 0 } -- %s --", sbuf);
	return;
    }
    *cp++ = NULL;
    (void) printf ("{ %s%c%s, 10, %d }",
	    sp, *dp, dp + 2, atoi (cp) - strlen (dp + 2));
#endif
}

/*  */

static int  dfl2int (yp)
register YP	yp;
{
    register YV	    yv,
		    y;

    yv = yp -> yp_default;
    switch (yv -> yv_code) {
	case YV_BOOL:
	case YV_NUMBER:
	    return yv -> yv_number;

	case YV_STRING:
	    yyerror ("need an integer, not a string");

	case YV_REAL:
	    yyerror ("need an integer, not a real");

	case YV_IDEFINED:
	    for (y = yp -> yp_value; y; y = y -> yv_next)
		if (y -> yv_code == YV_NUMBER
			&& (y -> yv_flags & YV_NAMED)
			&& strcmp (yv -> yv_identifier, y -> yv_named) == 0)
		    return y -> yv_number;
	    /* and fall */

	case YV_IDLIST:
	    yyerror ("haven't written symbol table for values yet");

	case YV_NULL:
	    yyerror ("need an integer, not NULL");

	default:
	    myyerror ("unknown value: %d", yv -> yv_code);
    }
/* NOTREACHED */
}

/*    DEBUG */

print_type (yp, level)
register YP	yp;
register int	level;
{
    register YP	    y;
    register YV	    yv;

    if (yp == NULLYP)
	return;

    (void) fprintf (stderr, "%*scode=0x%x flags=%s direction=0x%x\n", level * 4, "",
	    yp -> yp_code, sprintb (yp -> yp_flags, YPBITS),
	    yp -> yp_direction);
    (void) fprintf (stderr,
	    "%*sintexp=\"%s\" strexp=\"%s\" prfexp=0%o declexp=\"%s\" varexp=\"%s\"\n",
	    level * 4, "", yp -> yp_intexp, yp -> yp_strexp, yp -> yp_prfexp,
	    yp -> yp_declexp, yp -> yp_varexp);
    if (yp -> yp_param_type)
	(void) fprintf (stderr, "%*sparameter type=\"%s\"\n", level * 4, "",
		 yp -> yp_param_type);
    if (yp -> yp_action0)
	(void) fprintf (stderr, "%*saction0 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act0_lineno, yp -> yp_action0);
    if (yp -> yp_action05)
	(void) fprintf (stderr, "%*saction05 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act05_lineno, yp -> yp_action05);
    if (yp -> yp_action1)
	(void) fprintf (stderr, "%*saction1 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act1_lineno, yp -> yp_action1);
    if (yp -> yp_action2)
	(void) fprintf (stderr, "%*saction2 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act2_lineno, yp -> yp_action2);
    if (yp -> yp_action3)
	(void) fprintf (stderr, "%*saction3 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act3_lineno, yp -> yp_action3);

    if (yp -> yp_flags & YP_TAG) {
	(void) fprintf (stderr, "%*stag class=0x%x value=0x%x\n", level * 4, "",
		yp -> yp_tag -> yt_class, yp -> yp_tag -> yt_value);
	print_value (yp -> yp_tag -> yt_value, level + 1);
    }

    if (yp -> yp_flags & YP_DEFAULT) {
	(void) fprintf (stderr, "%*sdefault=0x%x\n", level * 4, "", yp -> yp_default);
	print_value (yp -> yp_default, level + 1);
    }

    if (yp -> yp_flags & YP_ID)
	(void) fprintf (stderr, "%*sid=\"%s\"\n", level * 4, "", yp -> yp_id);

    if (yp -> yp_flags & YP_BOUND)
	(void) fprintf (stderr, "%*sbound=\"%s\"\n", level * 4, "", yp -> yp_bound);

    if (yp -> yp_offset)
	(void) fprintf (stderr, "%*soffset=\"%s\"\n", level * 4, "", yp -> yp_offset);

    switch (yp -> yp_code) {
	case YP_INTLIST:
        case YP_ENUMLIST:
	case YP_BITLIST:
	    (void) fprintf (stderr, "%*svalue=0x%x\n", level * 4, "", yp -> yp_value);
	    for (yv = yp -> yp_value; yv; yv = yv -> yv_next) {
		print_value (yv, level + 1);
		(void) fprintf (stderr, "%*s----\n", (level + 1) * 4, "");
	    }
	    break;

	case YP_SEQTYPE:
	case YP_SEQLIST:
	case YP_SETTYPE:
	case YP_SETLIST:
	case YP_CHOICE:
	    (void) fprintf (stderr, "%*stype=0x%x\n", level * 4, "", yp -> yp_type);
	    for (y = yp -> yp_type; y; y = y -> yp_next) {
		print_type (y, level + 1);
		(void) fprintf (stderr, "%*s----\n", (level + 1) * 4, "");
	    }
	    break;

	case YP_IDEFINED:
	    (void) fprintf (stderr, "%*smodule=\"%s\" identifier=\"%s\"\n",
		    level * 4, "", yp -> yp_module ? yp -> yp_module : "",
		    yp -> yp_identifier);
	    break;

	default:
	    break;
    }
}

/*  */

static	print_value (yv, level)
register YV	yv;
register int	level;
{
    register YV	    y;

    if (yv == NULLYV)
	return;

    (void) fprintf (stderr, "%*scode=0x%x flags=%s\n", level * 4, "",
	    yv -> yv_code, sprintb (yv -> yv_flags, YVBITS));

    if (yv -> yv_action)
	(void) fprintf (stderr, "%*saction at line %d=\"%s\"\n", level * 4, "",
		yv -> yv_act_lineno, yv -> yv_action);

    if (yv -> yv_flags & YV_ID)
	(void) fprintf (stderr, "%*sid=\"%s\"\n", level * 4, "", yv -> yv_id);

    if (yv -> yv_flags & YV_NAMED)
	(void) fprintf (stderr, "%*snamed=\"%s\"\n", level * 4, "", yv -> yv_named);

    if (yv -> yv_flags & YV_TYPE) {
	(void) fprintf (stderr, "%*stype=0x%x\n", level * 4, "", yv -> yv_type);
	print_type (yv -> yv_type, level + 1);
    }

    switch (yv -> yv_code) {
	case YV_NUMBER:
	case YV_BOOL:
	    (void) fprintf (stderr, "%*snumber=0x%x\n", level * 4, "",
		    yv -> yv_number);
	    break;

	case YV_STRING:
	    (void) fprintf (stderr, "%*sstring=\"%s\"\n", level * 4, "",
		    yv -> yv_string);
	    break;

	case YV_IDEFINED:
	    if (yv -> yv_flags & YV_BOUND)
		(void) fprintf (stderr, "%*smodule=\"%s\" identifier=\"%s\"\n",
			level * 4, "", yv -> yv_module, yv -> yv_identifier);
	    else
		(void) fprintf (stderr, "%*sbound identifier=\"%s\"\n",
			level * 4, "", yv -> yv_identifier);
	    break;

	case YV_IDLIST:
	case YV_VALIST:
	    for (y = yv -> yv_idlist; y; y = y -> yv_next) {
		print_value (y, level + 1);
		(void) fprintf (stderr, "%*s----\n", (level + 1) * 4, "");
	    }
	    break;

	default:
	    break;
    }
}

/*    SYMBOLS */

static SY  new_symbol (encpref, decpref, prfpref, mod, id, type)
register char  *encpref,
	       *decpref,
	       *prfpref,
	       *mod,
	       *id;
register YP	type;
{
    register SY    sy;

    if ((sy = (SY) calloc (1, sizeof *sy)) == NULLSY)
	yyerror ("out of memory");
    sy -> sy_encpref = encpref;
    sy -> sy_decpref = decpref;
    sy -> sy_prfpref = prfpref;
    sy -> sy_module = mod;
    sy -> sy_name = id;
    sy -> sy_type = type;

    return sy;
}


static SY  add_symbol (s1, s2)
register SY	s1,
		s2;
{
    register SY	    sy;

    if (s1 == NULLSY)
	return s2;

    for (sy = s1; sy -> sy_next; sy = sy -> sy_next)
	continue;
    sy -> sy_next = s2;

    return s1;
}

/*    MODULES */

MD  lookup_module (module, oid)
char   *module;
OID	oid;
{
    register MD	    md;

    for (md = mymodules; md; md = md -> md_next) {
	if (module && md -> md_module && strcmp (md -> md_module, module) == 0)
	    return md;
	if (oid && md -> md_oid && oid_cmp(oid, md->md_oid) == 0)
	    return md;
    }

    read_ph_file (module, oid);

    if ((md = (MD) calloc (1, sizeof *md)) == NULLMD)
	yyerror ("out of memory");
    md -> md_module = new_string (module);
    if (oid)
	md -> md_oid = oid_cpy(oid);
    else
	md -> md_oid = NULLOID;

    if (mymodules != NULLMD)
	md -> md_next = mymodules;

    return (mymodules = md);
}

/*    TYPES */

YP	new_type (code, lineno)
int	code;
int	lineno;
{
    register YP    yp;

    if ((yp = (YP) calloc (1, sizeof *yp)) == NULLYP)
	yyerror ("out of memory");
    yp -> yp_code = code;
    yp -> yp_lineno = lineno;

    return yp;
}


YP	add_type (y, z)
register YP	y,
		z;
{
    register YP	    yp;

    for (yp = y; yp -> yp_next; yp = yp -> yp_next)
	continue;
    yp -> yp_next = z;

    return y;
}

/*  */

YP	copy_type (yp)
register YP	yp;
{
    register YP	    y;

    if (yp == NULLYP)
	return NULLYP;

    y = new_type (yp -> yp_code, yp -> yp_lineno);
    y -> yp_direction = yp -> yp_direction;

    switch (yp -> yp_code) {
	case YP_IDEFINED:
	    if (yp -> yp_module)
		y -> yp_module = new_string (yp -> yp_module);
	    y -> yp_identifier = new_string (yp -> yp_identifier);
	    y -> yp_modid = oid_cpy (yp -> yp_modid);
	    break;

	case YP_SEQTYPE:
	case YP_SEQLIST:
	case YP_SETTYPE:
	case YP_SETLIST:
	case YP_CHOICE:
	    y -> yp_type = copy_type (yp -> yp_type);
	    break;

	case YP_INTLIST:
	case YP_ENUMLIST:
	case YP_BITLIST:
	    y -> yp_value = copy_value (yp -> yp_value);
	    break;

	default:
	    break;
    }

    y -> yp_intexp = yp -> yp_intexp;
    y -> yp_strexp = yp -> yp_strexp;
    y -> yp_prfexp = yp -> yp_prfexp;

    y -> yp_declexp = yp -> yp_declexp;
    y -> yp_varexp = yp -> yp_varexp;

    if (yp -> yp_structname)
	y -> yp_structname = new_string (yp -> yp_structname);
    if (yp -> yp_ptrname)
	y -> yp_ptrname = new_string (yp -> yp_ptrname);

    if (yp -> yp_param_type)
	y -> yp_param_type = new_string (yp -> yp_param_type);

    if (yp -> yp_action0) {
	y -> yp_action0 = new_string (yp -> yp_action0);
	y -> yp_act0_lineno = yp -> yp_act0_lineno;
    }

    if (yp -> yp_action05) {
	y -> yp_action05 = new_string (yp -> yp_action05);
	y -> yp_act05_lineno = yp -> yp_act05_lineno;
    }

    if (yp -> yp_action1) {
	y -> yp_action1 = new_string (yp -> yp_action1);
	y -> yp_act1_lineno = yp -> yp_act1_lineno;
    }

    if (yp -> yp_action2) {
	y -> yp_action2 = new_string (yp -> yp_action2);
	y -> yp_act2_lineno = yp -> yp_act2_lineno;
    }

    if (yp -> yp_action3) {
	y -> yp_action3 = new_string (yp -> yp_action3);
	y -> yp_act3_lineno = yp -> yp_act3_lineno;
    }

    y -> yp_flags = yp -> yp_flags;

    if (yp -> yp_flags & YP_DEFAULT)
	y -> yp_default = copy_value (yp -> yp_default);

    if (yp -> yp_flags & YP_ID)
	y -> yp_id = new_string (yp -> yp_id);

    if (yp -> yp_flags & YP_TAG)
	y -> yp_tag = copy_tag (yp -> yp_tag);

    if (yp -> yp_flags & YP_BOUND)
	y -> yp_bound = new_string (yp -> yp_bound);

    if (yp -> yp_flags & YP_PARMVAL)
	y -> yp_parm = new_string (yp -> yp_parm);

    if (yp -> yp_flags & YP_CONTROLLED)
        y -> yp_control = new_string (yp -> yp_control);

    if (yp -> yp_flags & YP_OPTCONTROL)
        y -> yp_optcontrol = new_string (yp -> yp_optcontrol);

    if (yp -> yp_offset)
	y -> yp_offset = new_string (yp -> yp_offset);

    if (yp -> yp_control_act) {
	y -> yp_control_act = yp -> yp_control_act;
    }
    if (yp -> yp_optional_act) {
	y -> yp_optional_act = yp -> yp_optional_act;
    }
    if (yp -> yp_bef_alist) {
	y -> yp_bef_alist = yp -> yp_bef_alist;
    }
    if (yp -> yp_aft_alist) {
	y -> yp_aft_alist = yp -> yp_aft_alist;
    }


    if (yp -> yp_next)
	y -> yp_next = copy_type (yp -> yp_next);

    return y;
}

/*    VALUES */

YV	new_value (code)
int	code;
{
    register YV    yv;

    if ((yv = (YV) calloc (1, sizeof *yv)) == NULLYV)
	yyerror ("out of memory");
    yv -> yv_code = code;

    return yv;
}


YV	add_value (y, z)
register YV	y,
		z;
{
    register YV	    yv;

    for (yv = y; yv -> yv_next; yv = yv -> yv_next)
	continue;
    yv -> yv_next = z;

    return y;
}

/*  */

YV	copy_value (yv)
register YV	yv;
{
    register YV	    y;

    if (yv == NULLYV)
	return NULLYV;

    y = new_value (yv -> yv_code);
    y -> yv_flags = yv -> yv_flags;

    if (yv -> yv_action) {
	y -> yv_action = new_string (yv -> yv_action);
	y -> yv_act_lineno = yv -> yv_act_lineno;
    }

    if (yv -> yv_flags & YV_ID)
	y -> yv_id = new_string (yv -> yv_id);

    if (yv -> yv_flags & YV_NAMED)
	y -> yv_named = new_string (yv -> yv_named);

    if (yv -> yv_flags & YV_TYPE)
	y -> yv_type = copy_type (yv -> yv_type);

    switch (yv -> yv_code) {
	case YV_NUMBER:
	case YV_BOOL:
	    y -> yv_number = yv -> yv_number;
	    break;

	case YV_STRING:
	    y -> yv_string = new_string (yv -> yv_string);
	    break;

	case YV_IDEFINED:
	    if (yv -> yv_module)
		y -> yv_module = new_string (yv -> yv_module);
	    y -> yv_identifier = new_string (yv -> yv_identifier);
	    break;

	case YV_IDLIST:
	case YV_VALIST:
	    y -> yv_idlist = copy_value (yv -> yv_idlist);
	    break;

	default:
	    break;
    }

    if (yv -> yv_next)
	y -> yv_next = copy_value (yv -> yv_next);

    return y;
}

/*    TAGS */

YT	new_tag (class)
PElementClass	class;
{
    register YT    yt;

    if ((yt = (YT) calloc (1, sizeof *yt)) == NULLYT)
	yyerror ("out of memory");
    yt -> yt_class = class;

    return yt;
}

/*  */

YT	copy_tag (yt)
register YT	yt;
{
    register YT	    y;

    if (yt == NULLYT)
	return NULLYT;

    y = new_tag (yt -> yt_class);

    y -> yt_value = copy_value (yt -> yt_value);

    return y;
}

/*    STRINGS */

char   *new_string (s)
register char  *s;
{
    register char  *p;

    if (s == NULLCP)
	    return NULLCP;

    if ((p = malloc ((unsigned) (strlen (s) + 1))) == NULLCP)
	yyerror ("out of memory");

    (void) strcpy (p, s);
    return p;
}

/*    SYMBOLS */

static struct triple {
    char	   *t_name;
    PElementClass   t_class;
    PElementID	    t_id;
}		triples[] = {
    "IA5String", PE_CLASS_UNIV,	PE_DEFN_IA5S,
    "ISO646String", PE_CLASS_UNIV, PE_DEFN_IA5S,
    "NumericString", PE_CLASS_UNIV, PE_DEFN_NUMS,
    "PrintableString", PE_CLASS_UNIV, PE_DEFN_PRTS,
    "T61String", PE_CLASS_UNIV, PE_DEFN_T61S,
    "TeletexString", PE_CLASS_UNIV, PE_DEFN_T61S,
    "VideotexString", PE_CLASS_UNIV, PE_DEFN_VTXS,
    "GeneralizedTime", PE_CLASS_UNIV, PE_DEFN_GENT,
    "GeneralisedTime", PE_CLASS_UNIV, PE_DEFN_GENT,
    "UTCTime", PE_CLASS_UNIV, PE_DEFN_UTCT,
    "UniversalTime", PE_CLASS_UNIV, PE_DEFN_UTCT,
    "GraphicString", PE_CLASS_UNIV, PE_DEFN_GFXS,
    "VisibleString", PE_CLASS_UNIV, PE_DEFN_VISS,
    "GeneralString", PE_CLASS_UNIV, PE_DEFN_GENS,
    "EXTERNAL", PE_CLASS_UNIV, PE_CONS_EXTN,
    "ObjectDescriptor", PE_CLASS_UNIV, PE_PRIM_ODE,

    NULL
};

/*  */

char *modsym (module, id, prefix)
register char  *module,
	       *id;
char   *prefix;
{
    char    buf1[BUFSIZ],
            buf2[BUFSIZ],
            buf3[BUFSIZ];
    register struct triple *t;
    static char buffer[BUFSIZ];

    if (module == NULLCP)
	for (t = triples; t -> t_name; t++)
	    if (strcmp (t -> t_name, id) == 0) {
		module = "UNIV";
		break;
	    }

    if (prefix)
	modsym_aux (prefix, buf1);
    modsym_aux (module ? module : mymodule, buf2);
    modsym_aux (id, buf3);
    if (prefix)
	(void) sprintf (buffer, "%s_%s_%s", buf1, buf2, buf3);
    else
	(void) sprintf (buffer, "%s_%s", buf2, buf3);

    return buffer;
}


static	modsym_aux (name, bp)
register char  *name,
	       *bp;
{
    register char   c;

    while (c = *name++)
	switch (c) {
	    case '-':
		*bp++ = '_';
		*bp++ = '_';
		break;

	    default:
		*bp++ = c;
		break;
	}

    *bp = NULL;
}

/*  */

static char *gensym (s, a)
char   *s, *a;
{
    int     i;
    register char  *p;
    char    buffer[BUFSIZ];
    static int  cP = 0;
    static int  eP = 0;
    static int  mP = 0;

    switch (*s) {
	case 'c': 
	    i = cP++;
	    break;
	case 'e': 
	    i = eP++;
	    break;
	case 'm': 
	    i = mP++;
	    break;

	default: 
	    myyerror ("unknown gensym argument \"%s\"", s);
	/* NOTREACHED */
    }
    if (a)
	(void) sprintf (buffer, "%s_%s_%d[n_%s]", s, modulename, i, a);
    else
	(void) sprintf (buffer, "%s_%s_%d", s, modulename, i);

    if ((p = malloc ((unsigned) (strlen (buffer) + 11))) == NULLCP)
	yyerror ("out of memory");

    (void) strcpy (p, buffer);
    return p;
}

/* pepy compatible routines - you know how it is ... */
init_new_file () 
{
    ;
}

end_file ()
{
    ;
}

static char *array (s, flg)
char	*s;
int	flg;
{
    static char buf[BUFSIZ];
    char	*p;

    if (!flg) return s;

    if (p = index (s, '[')) {
	(void) sprintf (buf, "%*.*s[1]", p - s, p - s, s);
	return buf;
    }
    return s;
}

static void prime_default (yp, level)
YP	yp;
int	level;
{
    switch (yp -> yp_code) {
    case YP_BOOL:
	(void) printf ("%*s%s = %d;\n", level * 4, "",
		SVAL (yp->yp_varexp),
		val2int (yp -> yp_default) ? 1 : 0);
	break;

    case YP_INT:
	(void) printf ("%*s%s = %d;\n", level * 4, "",
		SVAL (yp -> yp_varexp), val2int (yp -> yp_default));
	break;

    case YP_INTLIST:
    case YP_ENUMLIST:
	(void) printf ("%*s%s = %d;\n", level * 4, "",
		SVAL (yp -> yp_varexp), dfl2int (yp));
	break;

    case YP_REAL:
	(void) printf ("%*s%s = %g;\n", level * 4, "",
		SVAL (yp -> yp_varexp),
		val2real (yp -> yp_default));

    default:
	break;
    }
}
/* PH FILES */

/* really need much more information in the .ph file... */

static	read_ph_file (module, oid)
register char *module;
OID	oid;
{
    int     class,
	    value,
	    direction;
    char    buffer[BUFSIZ],
	    file[BUFSIZ],
	    id[BUFSIZ],
    	    encpref[BUFSIZ],
    	    decpref[BUFSIZ],
    	    printpref[BUFSIZ];
    char    *p, *ep, *dp, *ppp;
    register FILE  *fp;
    register YP	    yp;
    register YT	    yt;
    register YV	    yv;

    (void) sprintf (file, "%s.ph", module);
    if (oid)
	(void) sprintf (p = buffer, "%s.ph", sprintoid(oid));
    else
	p = NULLCP;
    if ((fp = open_ph_file (file, p, "r")) == NULL)
    {
	warning ("Can't find file %s%s%s failed\n",
		     file, p ? "/" : "", p ? p : "");
	return;
    }

    if (strcmp (module, "UNIV"))
	yyprint (module, 1, 0);

    while (fgets (buffer, sizeof buffer, fp)) {
	if (sscanf (buffer, "%d/%d/%d: %s",
		    &class, &value, &direction, id) !=4) {
	    myyerror ("bad external definition in %s: %s",
		    file, buffer);
	    continue;
	}
	ppp = dp = ep = NULLCP;
	if (p = index(buffer, '|')) {
	    if( sscanf (p+1, "%s %s %s\n", encpref, decpref, printpref) == 3) {
		ppp = new_string (printpref);
		dp = new_string (decpref);
		ep = new_string (encpref);
	    }
	}
		
	yp = new_type (class == -1 ? YP_ANY : YP_IMPTYPE, -1);
	yp -> yp_flags = YP_IMPORTED;
	if (class >= 0) {
	    yp -> yp_flags |= YP_TAG;
	    yp -> yp_tag = yt = new_tag ((PElementClass) class);
	    yt -> yt_value = yv = new_value (YV_NUMBER);
	    yv -> yv_number = value;
	}
	yp -> yp_direction = direction;
	pass1_type (ep, dp, ppp, new_string (module),
		new_string (id), yp);
    }

    (void) fclose (fp);
}

/*  */

static	write_ph_file () {
    int	    msave;
    char    file[BUFSIZ];
    char    fileoid[BUFSIZ];
    char	*cp;
    register FILE  *fp;
    register SY	    sy;
    register YT	    yt;
    register YP	    yp;

    (void) sprintf (file, "%s.ph", mymodule);
    if (mymoduleid)
	(void) sprintf (cp = fileoid, "%s.ph", sprintoid(mymoduleid));
    else
	cp = NULLCP;
    msave = mflag, mflag = 0;
    if ((fp = open_ph_file (file, cp, "w")) == NULL)
	myyerror ("unable to write %s", file);
    mflag = msave;

    for (sy = mysymbols; sy; sy = sy -> sy_next) {
	yp = sy -> sy_type;
	if (yp -> yp_flags & YP_IMPORTED)
	    continue;
	if (doexternals == 0 && (yp->yp_flags & YP_EXPORTED) == 0)
	    continue;

	if (is_any_type (yp)) {
	    (void) fprintf (fp, "-1/0/%d: %s", yp -> yp_direction, sy -> sy_name);
	    (void) fprintf (fp, " |%s %s %s\n", yyencpref, yydecpref, yyprfpref);
	}
	else
	    if ((yt = lookup_tag (yp)) && yt -> yt_class != PE_CLASS_CONT) {
		(void) fprintf (fp, "%d/%d/%d: %s", yt -> yt_class,
			    val2int (yt -> yt_value), yp -> yp_direction,
			    sy -> sy_name);
		(void) fprintf (fp, " |%s %s %s\n", yyencpref, yydecpref, yyprfpref);
	    }
    }

    (void) fclose (fp);
}

/*  */

#ifndef	PEPSYPATH
#define	PEPSYPATH	""
#endif


static FILE *open_ph_file (fn, fnoid, mode)
char *fn,
     *fnoid,
     *mode;
{
    register char  *dst,
		   *path;
    char    fnb[BUFSIZ];
    register FILE  *fp;
    static char *pepypath = NULL;

    if (*fn == '/')
	return fopen (fn, mode);

    if (mflag) {	/* MOBY HACK */
	if (fnoid && (fp = fopen (fnoid, mode)) != NULL)
	    return fp;
	if ((fp = fopen (fn, mode)) != NULL)
	    return fp;

	if (fnoid) {
	    (void) sprintf (fnb, "../pepy/%s", fnoid);
	    if ((fp = fopen (fnb, mode)) != NULL)
		return fp;
	}
	(void) sprintf (fnb, "../pepy/%s", fn);
	if ((fp = fopen (fnb, mode)) != NULL)
	    return fp;

	if (fnoid) {
	    (void) sprintf (fnb, "../../pepy/%s", fnoid);
	    if ((fp = fopen (fnb, mode)) != NULL)
		return fp;
	}
	(void) sprintf (fnb, "../../pepy/%s", fn);
	return fopen (fnb, mode);
    }

    if (pepypath == NULL && (pepypath = getenv ("PEPSYPATH")) == NULL)
	pepypath = PEPSYPATH;
    path = pepypath;

    do {
	dst = fnb;
	while (*path && *path != ':')
	    *dst++ = *path++;
	if (dst != fnb)
	    *dst++ = '/';
	if (fnoid) {
	    (void) strcpy (dst, fnoid);
	    if ((fp = fopen (fnb, mode)) != NULL)
		break;
	}
	(void) strcpy (dst, fn);
	if ((fp = fopen (fnb, mode)) != NULL)
	    break;
    } while (*path++);

    return fp;
}

YT  lookup_tag (yp)
register YP     yp;
{
    register struct tuple *t;
    static struct ypt ypts;
    register YT     yt = &ypts;
    static struct ypv ypvs;
    register YV     yv = &ypvs;
    register YP     z;

    if (yp -> yp_flags & YP_TAG)
        return yp -> yp_tag;

    while (yp -> yp_code == YP_IDEFINED) {
        if (yp -> yp_module && strcmp (yp -> yp_module, mymodule))
            (void) lookup_module (yp -> yp_module, yp -> yp_modid);
 
        if (z = lookup_type (yp -> yp_module, yp -> yp_identifier)) {
            yp = z;
 
            if (yp -> yp_flags & YP_TAG)
                return yp -> yp_tag;
 
            continue;
        }
 
        break;
    }
 
    for (t = tuples; t -> t_type != YP_UNDF; t++)
        if (t -> t_type == yp -> yp_code) {
            yt -> yt_class = t -> t_classnum;
            yt -> yt_value = yv;
            yv -> yv_code = YV_NUMBER;
            yv -> yv_number = t -> t_idnum;
 
            return yt;
        }
 
    return NULLYT;
}
 
int  is_any_type (yp)
register YP     yp;
{
    register    YP z;

    while (yp -> yp_code == YP_IDEFINED) {
        if (yp -> yp_flags & YP_TAG)
            return 0;

        if (yp -> yp_module && strcmp (yp -> yp_module, mymodule))
            (void) lookup_module (yp -> yp_module, yp -> yp_modid);

        if (z = lookup_type (yp -> yp_module, yp -> yp_identifier)) {
            yp = z;

            continue;
        }
 
        break;
    }
 
    return (yp -> yp_code == YP_ANY && !(yp -> yp_flags & YP_TAG));
}

/*
 * return a string with the leading pathname stripped off
 */
char *
pstrip(p)
char *p;
{
    char *p1;

    if (p1 = rindex(p, '/'))
	return (p1 + 1);
    return (p);
}

 
/*
 * produce a #include on the given file descriptor according to what ever
 * rules are in fashion today. Unfortunately these keep changing so to
 * minimise the effort involved in keeping up we put all the code to change
 * in the one place, here. -- amrw
 *
 * actually, the rules have never changed, andrew just can't figure them out.
 *	-- mtr
 */
doincl(fp, file)
FILE	*fp;		/* where #include is to be written to */
char	*file[];	/* files to be included */
{
    char	**p;

    if (mflag) {
	/* PEPYPATH version */

	(void) fprintf (fp, "#ifndef	PEPYPATH\n");
	for (p = file; *p; p++) {
	    if (is_stand(*p))
		(void) fprintf (fp, "#include <isode/%s>\n", *p);
	    else
		(void) fprintf (fp, "#include \"%s\"\n", pstrip(*p));
	}
	(void) fprintf (fp, "#else\n");
	for (p = file; *p; p++) {
	    (void) fprintf (fp, "#include \"%s\"\n", pstrip(*p));
	}
	(void) fprintf (fp, "#endif\n\n");

    }
    else {
	for (p = file; *p; p++) {
	    if (is_stand(*p))
		(void) fprintf (fp, "#include <isode/%s>\n", *p);
	    else
		(void) fprintf (fp, "#include \"%s\"\n", pstrip(*p));
	}
    }
    (void) fprintf (fp, "\n");
}

/* standard files  - that should be found in the <isode> directory */
static char *stand_f[] = {
	"psap.h",
	"pepsy.h",
	"UNIV-types.h",
	"UNIV_defs.h",
	"UNIV_pre_defs.h",

	(char *)0	/* terminating NULL pointer */
	};


/*
 * determine if the given (after stripping any path) file is a standard
 * include file which should be in the include/isode directory.
 * return nonzero (true) if it is.
 */
is_stand(file)
char *file;
{
    char	**p;
    char	*f = pstrip (file);
    for (p = stand_f; *p; p++) {
	if (strcmp(f, pstrip(*p)) == 0)
	    return (1);
    }

    return (0);
}

/* Number of different external modules that can referenced */
#define EXTMODSIZE	50

/* table of external modules we reference */
static char *extmodtab[EXTMODSIZE];
static int   nextmod = 0;	/* next free slot in external module table */

/*
 * build up a list of external modules we have referenced
 */
addextmod(p)
char	*p;	/* name of external module */
{

    if (nextmod >= EXTMODSIZE)
	ferr(1, "Too many external modules reference, table overflow\n");

    extmodtab[nextmod++] = p;
}

/*
 * process all the external modules collected to produce the includes
 * required
 */
proc_extmod(fp)
FILE	*fp;
{
    char	**p;
    char 	*files[EXTMODSIZE + 1];
    char 	*buf;
    char	*tail = "-types.h";
    char	*prefix = "pepsy/";
    int		last = 0;

    if (nextmod <= 0)
	return;		/* no external definitions */

    for (p = extmodtab; p < extmodtab + nextmod; p++) {
	if (last >= EXTMODSIZE)
	    ferr(1, "proc_extmod: too many external modules\n");

	buf = concat(*p, tail);
	if (mflag || is_stand(buf)) /* need to prepend a "pepsy/" */
	    files[last++] = my_strcat(prefix, buf);
	else
	    files[last++] = my_new_str(buf);
    }
    files[last++] = (char *)0;

    doincl(fp, files);

    /* free up this memory */
    --last; /* don't free the NULL pointer - can core dump */
    while (last > 0)
	free(files[--last]);

}

/*
 * allocate a yfn structure and intialise it
 */
YFN
new_yfn(efn, dfn, pfn, ffn)
char	*efn, *dfn, *pfn, *ffn;
{
	
    register YFN    fn;
    char	buf[STRSIZE];

    if ((fn = (YFN) calloc (1, sizeof *fn)) == NULLYFN)
	yyerror ("out of memory");

    if (efn) {
        if (getid(efn, buf, STRSIZE) == NULLCP)
	    yyerror("Bad Encoding function\n");
	fn -> yfn_enc = strdup(buf);
	free(efn);
    }

    if (dfn) {
        if (getid(dfn, buf, STRSIZE) == NULLCP)
	    yyerror("Bad Decoding function\n");
	fn -> yfn_dec = strdup(buf);
	free(dfn);
    }

    if (pfn) {
        if (getid(pfn, buf, STRSIZE) == NULLCP)
	    yyerror("Bad Printing function\n");
	fn -> yfn_prt = strdup(buf);
	free(pfn);
    }

    if (ffn) {
        if (getid(ffn, buf, STRSIZE) == NULLCP)
	    yyerror("Bad Printing function\n");
	fn -> yfn_fre = strdup(buf);
	free(ffn);
    }

    return fn;
}

/*
 * support routine for action_t = allocate space for it and fill it in with
 * the given yy_action field
 */
Action
new_action_t(text, lineno, num)
char	*text;
int	lineno;
{
    Action	act;

    if ((act = (Action) malloc(sizeof (action_t))) == NULLAction)
	yyerror("out of memory\n");
    
    act->a_data = text;
    act->a_line = lineno;
    act->a_num = num;

    return (act);
}

/*
 * support routine for YAL = allocate space for it and make sure it is
 * zero'd
 */
YAL
new_yal()
{
    YAL	yal;

    if ((yal = (YAL) calloc(1, sizeof (*yal))) == NULLYAL)
	yyerror("out of memory\n");
    
    return (yal);
}
YAL
yal_join(yal1, yal2)
YAL	yal1, yal2;
{
    if (yal2 == NULLYAL)
	return (yal1);
    if (yal1 == NULLYAL)
	return (yal2);

    if (yal1->yal_enc == NULLAction && yal2->yal_enc != NULLAction)
	yal1->yal_enc = yal2->yal_enc;
    else if (yal1->yal_enc != NULLAction && yal2->yal_enc != NULLAction)
	yyerror("two encoding actions in the same place\n merge into one\n");

    if (yal1->yal_dec == NULLAction && yal2->yal_dec != NULLAction)
	yal1->yal_dec = yal2->yal_dec;
    else if (yal1->yal_dec != NULLAction && yal2->yal_dec != NULLAction)
	yyerror("two decoding actions in the same place\n merge into one\n");

    if (yal1->yal_prn == NULLAction && yal2->yal_prn != NULLAction)
	yal1->yal_prn = yal2->yal_prn;
    else if (yal1->yal_prn != NULLAction && yal2->yal_prn != NULLAction)
	yyerror("two printing actions in the same place\n merge into one\n");

    free((char *)yal2);
    return (yal1);
}
/*
 * join two yfn structures
 */
YFN
join_yfn(fn1, fn2)
register YFN	fn1, fn2;
{
	
    if (fn2 == NULLYFN)
	return (fn1);
    if (fn1 == NULLYFN)
	return (fn2);

    if (fn1->yfn_enc == NULLCP && fn2->yfn_enc != NULLCP)
	fn1->yfn_enc = fn2->yfn_enc;
    else if (fn1->yfn_enc != NULLCP && fn2->yfn_enc != NULLCP)
	yyerror("Illegal: two encoding functions for the same type\n");

    if (fn1->yfn_dec == NULLCP && fn2->yfn_dec != NULLCP)
	fn1->yfn_dec = fn2->yfn_dec;
    else if (fn1->yfn_dec != NULLCP && fn2->yfn_dec != NULLCP)
	yyerror("Illegal: two decoding functions for the same type\n");

    if (fn1->yfn_prt == NULLCP && fn2->yfn_prt != NULLCP)
	fn1->yfn_prt = fn2->yfn_prt;
    else if (fn1->yfn_prt != NULLCP && fn2->yfn_prt != NULLCP)
	yyerror("Illegal: two printing functions for the same type\n");

    free((char *)fn2);

    return (fn1);
}

/*  */

char   *strdup (s)
char   *s;
{
    char   *p;

    if ((p = malloc ((unsigned) (strlen (s) + 1))) == NULL)
	abort ();

    (void) strcpy (p, s);
    return p;
}