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 p

⟦24863efcd⟧ TextFile

    Length: 42008 (0xa418)
    Types: TextFile
    Names: »pepy.c«

Derivation

└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape
    └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« 
        └─⟦d3ac74d73⟧ 
            └─⟦this⟧ »isode-5.0/pepy/pepy.c« 

TextFile

/* pepy.c - PE parser (yacc-based) */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/pepy/RCS/pepy.c,v 6.0 89/03/18 23:37:36 mrose Rel $";
#endif

/*
 * $Header: /f/osi/pepy/RCS/pepy.c,v 6.0 89/03/18 23:37:36 mrose Rel $
 *
 *
 * $Log:	pepy.c,v $
 * Revision 6.0  89/03/18  23:37:36  mrose
 * Release 5.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 "pepy.h"

/* \f

   DATA */

static char *aflag = NULL;
int	Cflag = 1;		/* pepy */
int	dflag = 0;
int	hflag = 0;
int	Pflag = 0;
int	rflag = 0;
char   *bflag = NULLCP;
static int bwidth = 1;
char   *module_actions = NULLCP;
int	pepydebug = 0;
int	doexternals = 1;
static int linepos = 0;
static int mflag = 0;
static int pflag = 0;
static int sflag = 0;

static  char *eval = NULLCP;

char   *mymodule = "";
OID	mymoduleid = NULLOID;

int yysection = YP_DECODER;
char *yyencpref = "build";
char *yydecpref = "parse";
char *yyprfpref = "print";
char *yyencdflt = "build";
char *yydecdflt = "parse";
char *yyprfdflt = "print";
static char *yyprefix;

static struct section {
    char   *s_name;
    int	    s_mode;
}	sections[] = {
    "ENCODE", YP_ENCODER,
    "DECODE", YP_DECODER,
    "PRINT", YP_PRINTER,

    NULL
};
    
char   *sysin = NULLCP;
static char sysout[BUFSIZ];

typedef struct modlist {
    char   *md_module;
    OID	   md_oid;

    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)

static	SY	mysymbols = NULLSY;


char   *gensym (), *modsym ();
MD	lookup_module ();
FILE   *open_ph_file ();
SY	new_symbol (), add_symbol ();

YP	lookup_type (), lookup_binding ();
YT	lookup_tag ();

/* \f

   MAIN */

/* ARGSUSED */

main (argc, argv, envp)
int	argc;
char  **argv,
      **envp;
{
    register char  *cp,
		   *sp;
    register struct section *sectp;

    fprintf (stderr, "%s\n", pepyversion);

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

	if (strcmp (cp, "-a") == 0) {
	    argc--, argv++;
	    if ((aflag = *argv) == NULL || *aflag == '-')
		goto usage;
	    continue;
	}
	if (strcmp (cp, "-A") == 0) {
	    yysection = YP_ENCODER | YP_DECODER | YP_PRINTER;
	    continue;
	}
	if (strcmp (cp, "-d") == 0) {
	    dflag++;
	    continue;
	}
	if (strcmp (cp, "-h") == 0) {
	    hflag++;
	    continue;
	}
	if (strcmp (cp, "-m") == 0) {
	    mflag++;
	    continue;
	}
	if (strcmp (cp, "-P") == 0) {
	    Pflag++;
	    continue;
	}
	if (strcmp (cp, "-p") == 0) {
	    pflag++;
	    continue;
	}
	if (strcmp (cp, "-o") == 0) {
	    if (sysout[0]) {
		fprintf (stderr, "too many output files\n");
		exit (1);
	    }
	    if (bflag) {
not_practical: ;
		fprintf (stderr, "-b & -o together is not practical\n");
		exit (1);
	    }
	    argc--, argv++;
	    if ((cp = *argv) == NULL || (*cp == '-' && cp[1] != NULL))
		goto usage;
	    (void) strcpy (sysout, cp);

	    continue;
	}
	if (strcmp (cp, "-r") == 0) {
	    rflag++;
	    continue;
	}
	if (strcmp (cp, "-s") == 0) {
	    sflag++;
	    continue;
	}
	if (strcmp (cp, "-S") == 0) {
	    
	    argc--, argv++;
	    if ((cp = *argv) == NULL || *cp == '-')
		goto usage;

	    for (sectp = sections; sectp -> s_name; sectp++)
		if (strcmp (sectp -> s_name, cp) == 0) {
		    yysection = sectp -> s_mode;
		    break;
		}
	    if (!sectp -> s_name) {
		fprintf (stderr, "unknown section name \"%s\"\n", cp);
		exit (1);
	    }
	    continue;
	}
	if (strcmp (cp, "-b") == 0) {
	    if (bflag) {
		fprintf (stderr, "too many prefixes\n");
		exit (1);
	    }
	    if (sysout[0])
		goto not_practical;
	    argc--, argv++;
	    if ((bflag = *argv) == NULL || *bflag == '-')
		goto usage;
	    continue;
	}

	if (sysin) {
usage: ;
	    fprintf (stderr,
		"usage: pepy [-d] [-h] [-p] [-o module.c] [-r] [-s] [-S section] [-b prefix] module.py\n");
	    exit (1);
	}

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

	if (sysout[0] || bflag)
	    continue;
	if (sp = rindex (cp, '/'))
	    sp++;
	if (sp == NULL || *sp == NULL)
	    sp = cp;
	sp += strlen (cp = sp) - 3;
	if (sp > cp && strcmp (sp, ".py") == 0)
	    (void) sprintf (sysout, "%.*s.c", sp - cp, cp);
	else
	    (void) sprintf (sysout, "%s.c", cp);
    }

    switch (pepydebug = (cp = getenv ("PEPYTEST")) && *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) {
	fprintf (stderr, "unable to read "), perror (sysin);
	exit (1);
    }

    if (pflag)
	exit (pp ());

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

    if (!bflag)
	prologue ();

    initoidtbl ();

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

static prologue ()
{
    char *cp;

    if (cp = index (pepyversion, ')'))
	for (cp++; *cp != ' '; cp++)
	    if (*cp == NULL) {
		cp = NULL;
		break;
	    }
    if (cp == NULL)
	cp = pepyversion + strlen (pepyversion);
    printf ("/* automatically generated by %*.*s, do not edit! */\n\n",
	    cp - pepyversion, cp - pepyversion, pepyversion);
    printf ("#include %s\n\n", mflag ? "\"psap.h\"" : "<isode/psap.h>");
    if (!bflag)
	printf ("static char *pepyid = \"%s\";\n\n", pepyversion);
    if (aflag)
	printf ("#define\tadvise\t%s\n\n", aflag);
    printf ("void\tadvise ();\n");
}
/* \f

   ERRORS */

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

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

    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

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

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

/* \f

 */


#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
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);

    exit (1);
}
#else
/* VARARGS */
pyyerror (yp, fmt)
YP	yp;
char   *fmt;
{
    pyyerror (yp, fmt);
}
#endif

/* \f

 */

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

    return 1;
}

/* \f

 */

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

    if (sflag)
	return;

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

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

	didf = 1;	
    }

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

	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);

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

	if (top)
	    return;
    }

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

/* \f

   PASS1 */

pass1 ()
{
    if (!bflag)
	prologue3 ();
}

static prologue3 ()
{
    printf ("\n/* Generated from module %s", mymodule);
    if (mymoduleid)
	printf (", Object Identifier %s", sprintoid (mymoduleid));
    printf (" */\n");
}
/* \f

 */

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

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

	fprintf (stderr, "%s.%s\n", mod ? mod : mymodule, id);
	print_type (yp, 0);
	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);
}

/* \f

   PASS2 */

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

    if (!sflag)
	(void) fflush (stderr);

    if (bflag) {
	register int    i,
			j;

	i = 2, j = 10;
	for (sy = mysymbols; sy; sy = sy -> sy_next)
	    if (!(sy -> sy_type -> yp_flags & YP_IMPORTED))
		if (++i >= j)
		    bwidth++, j *= 10;
    }
    else
	prologue2 ();

    if (strcmp (mymodule, "UNIV"))
	(void) lookup_module ("UNIV", NULLOID);

    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;

	if (yp -> yp_direction & YP_ENCODER) {
	    if (bflag)
		init_new_file ();
	    yyprefix = sy -> sy_encpref;
	    printf ("\n/* ARGSUSED */\n\n%sint\t%s ",
		    !doexternals && (yp -> yp_flags & YP_EXPORTED) ?
		    "static " : "",
		    modsym (sy -> sy_module,
		    sy -> sy_name, YP_ENCODER));
	    do_type (yp, 1, eval, "(*pe)");
	    printf ("\n    return OK;\n}\n");
	    if (bflag)
		end_file ();
	}
	if (yp -> yp_direction & YP_DECODER) {
	    if (bflag)
		init_new_file ();
	    yyprefix = sy -> sy_decpref;
	    printf ("\n/* ARGSUSED */\n\n%sint\t%s ",
		    !doexternals && (yp -> yp_flags & YP_EXPORTED) ?
		    "static " : "",
		    modsym (sy -> sy_module,
		    sy -> sy_name, YP_DECODER));
	    undo_type (yp, 1, eval, "pe", 0);
	    printf ("\n    return OK;\n}\n");
	    if (bflag)
		end_file ();
	}
	if (yp -> yp_direction & YP_PRINTER) {
	    if (bflag)
		init_new_file ();
	    yyprefix = sy -> sy_prfpref;
	    printf ("\n/* ARGSUSED */\n\n%sint\t%s ",
		    !doexternals && (yp -> yp_flags & YP_EXPORTED) ?
		    "static " : "",
		    modsym (sy -> sy_module,
		    sy -> sy_name, YP_PRINTER));
	    undo_type (yp, 1, eval, "pe", 1);
	    printf ("\n    return OK;\n}\n");
	    if (bflag)
		end_file ();
	}
	if (!bflag && ferror (stdout))
	    myyerror ("write error - %s", sys_errname (errno));
    }

    write_ph_file ();
}

static prologue2 ()
{
    printf("\n#ifndef PEPYPARM\n#define PEPYPARM char *\n");
    printf ("#endif /* PEPYPARM */\n"); /* keep ansi happy ... */
    printf("extern PEPYPARM NullParm;\n");
}

/* \f

 */

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
};

/* \f

   PULLUP */

choice_pullup (yp, partial)
register YP	yp;
int	partial;	/* pullup fully, or just enough? */
{
    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 (partial)
		    continue;
		if ((z = lookup_type (y -> yp_module, y -> yp_identifier))
			== NULLYP
			|| z -> yp_code != YP_CHOICE)
		    continue;

		choice_pullup (z2 = copy_type (z), partial);
		break;

	    case YP_CHOICE:
		choice_pullup (z2 = copy_type (y), partial);
		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;
    }
}

/* \f

 */

tag_pullup (yp, level, arg, whatsit)
register YP	yp;
register int	level;
char   *arg,
       *whatsit;
{
    char   *narg;
    char   *id = yp -> yp_flags & YP_ID ? yp -> yp_id : "member";

    printf ("%*s{\t/* %s TAG PULLUP */\n%*sregister PE %s;\n\n",
	    level * 4, "", whatsit, (level + 1) * 4, "", narg = gensym ());
    level++;

    printf ("%*sif ((%s = prim2set (%s)) == NULLPE) {\n",
	    level * 4, "", narg, arg);
    printf ("%*sadvise (NULLCP, \"%s bad %s: %%s\",\n",
	    (level + 1) * 4, "", id, whatsit);
    printf ("%*spe_error (%s -> pe_errno));\n",
	    (level + 3) * 4, "", arg);
    printf ("%*sreturn NOTOK;\n%*s}\n",
	    (level + 1) * 4, "", level * 4, "");
    printf ("%*sif (%s -> pe_cardinal != 1) {\n",
	    level * 4, "", narg);
    printf ("%*sadvise (NULLCP, \"%s too many elements for tagged %s: %%d\",\n",
	    (level + 1) * 4, "", id, whatsit);
    printf ("%*s%s -> pe_cardinal);\n", (level + 3) * 4, "", narg);
    printf ("%*sreturn NOTOK;\n%*s}\n",
	    (level + 1) * 4, "", level * 4, "");
    printf ("%*s%s = first_member (%s);\n%*s}\n",
	    level * 4, "", arg, narg, (level - 1) * 4, "");
}


tag_pushdown (yp, level, arg, whatsit)
register YP     yp;
register int    level;
char   *arg,
       *whatsit;
{
    char   *narg;

    printf ("%*s{\t/* %s TAG PUSHDOWN */\n%*sPE %s_z;\n",
	    level * 4, "", whatsit, (level + 1) * 4, "", narg = gensym ());
    level++;
    printf ("%*sregister PE *%s = &%s_z;\n\n", level * 4, "", narg, narg);

    printf ("%*sif ((*%s = pe_alloc (PE_CLASS_%s, PE_FORM_CONS, %d)) == NULLPE) {\n",
	    level * 4, "", narg, pe_classlist[yp -> yp_tag -> yt_class],
	    val2int (yp -> yp_tag -> yt_value));
    printf ("%*sadvise (NULLCP, \"%s: out of memory\");\n",
	    (level + 1) * 4, "", whatsit);
    printf ("%*sreturn NOTOK;\n%*s}\n", (level + 1) * 4, "", level * 4, "");
    printf ("%*s(*%s) -> pe_cons = %s;\n", level * 4, "", narg, arg);
    printf ("%*s%s = *%s;\n", level * 4, "", arg, narg);

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

/* \f

   TYPE HANDLING */

tag_type (yp)
register YP	yp;
{
    register struct tuple *t;
    register YT	    yt;
    register YP	    y;

    switch (yp -> yp_code) {
	case YP_IDEFINED:
	    if (yp -> yp_flags & YP_BOUND) {
		if ((y = lookup_binding (yp -> yp_module, yp -> yp_identifier,
			    yp -> yp_bound)) == NULLYP)
		    myyerror ("type \"%s\" isn't defined for binding",
			    yp -> yp_identifier);
		if (!(y -> yp_flags & YP_TAG))
		    myyerror ("type \"%s\" isn't tagged for binding",
			    yp -> yp_identifier);
		yp -> yp_flags |= YP_TAG;
		yp -> yp_tag = copy_tag (y -> yp_tag);
		return;
	    }

	    if (yt = lookup_tag (yp)) {
		yp -> yp_flags |= YP_TAG | YP_IMPLICIT;
		yp -> yp_tag = copy_tag (yt);
		return;
	    }
	    if (!lookup_type (yp -> yp_module, yp -> yp_identifier))
		pyyerror (yp, "don't know how to tag an undefined type");
	    break;

	default:
	    for (t = tuples; t ->t_type != YP_UNDF; t++)
		if (t -> t_type == yp -> yp_code) {
		    yp -> yp_flags |= YP_TAG | YP_IMPLICIT;
		    yp -> yp_tag = new_tag (t -> t_classnum);
		    yp -> yp_tag -> yt_value = new_value (YV_NUMBER);
		    yp -> yp_tag -> yt_value -> yv_number = t -> t_idnum;
		    return;
		}
	    break;
    }

    pyyerror (yp, "don't know how to do a set/choice member that isn't tagged or bound");
}

/* \f

 */

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;
}

/* \f

 */

static YP  lookup_binding (mod, id, binding)
register char  *mod,
	       *id,
	       *binding;
{
    register YP	    yp,
		    y2;

    if ((yp = lookup_type (mod, id)) == NULLYP)
	return NULLYP;

    if (yp -> yp_code != YP_CHOICE)
	myyerror ("type \"%s\" isn't a CHOICE type", id);
    for (y2 = yp -> yp_type; y2; y2 = y2 -> yp_next)
	if ((y2 -> yp_flags & YP_ID)
		&& strcmp (y2 -> yp_id, binding) == 0)
	    return y2;

    myyerror ("type \"%s\" doesn't bind \"%s\"", id, binding);
/* NOTREACHED */
}

/* \f

 */

check_type (type, level, class, form, id, arg)
register char  *type,
	       *class,
	       *form,
	       *id,
	       *arg;
register int	level;
{
    int	    explicit;

    if (level == 1) {
	printf ("%*sif (explicit) {\n", level * 4, ""), level++;
	explicit = 1;
    }
    else
	explicit = 0;

    printf ("%*sif (%s -> pe_class != %s", level * 4, "", arg, class);
    if (form)
	printf ("\n%*s|| %s -> pe_form != %s\n%*s",
		(level + 2) * 4, "", arg, form, (level + 2) * 4 - 1, "");
    printf (" || %s -> pe_id != %s) {\n", arg, id);
    printf ("%*sadvise (NULLCP, \"%s bad class/form/id: %%s/%%d/0x%%x\",\n",
	    (level + 1) * 4, "", type);
    printf ("%*spe_classlist[%s -> pe_class], %s -> pe_form, %s -> pe_id);\n",
	    (level + 3) * 4, "", arg, arg, arg);
    printf ("%*sreturn NOTOK;\n%*s}\n",
	    (level + 1) * 4, "", level * 4, "");

    if (explicit) {
	level--, printf ("%*s}\n", level * 4, "");
	if (form) {
	    printf ("%*selse\n%*sif (%s -> pe_form != %s) {\n",
		    level * 4, "", (level + 1) * 4, "", arg, form);
	    printf ("%*sadvise (NULLCP, \"%s bad form: %%d\", %s -> pe_form);\n",
		    (level + 2) * 4, "", type, arg);
	    printf ("%*sreturn NOTOK;\n%*s}\n",
		    (level + 2) * 4, "", (level + 1) * 4, "");
	}
    }

    printf ("\n");
}

/* \f

 */

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));
}

/* \f

 */

uniqint (yv)
register YV	yv;
{
    register int    i;
    register YV	    y;

    for (; yv; yv = yv -> yv_next) {
	i = val2int (yv);

	for (y = yv -> yv_next; y; y = y -> yv_next)
	    if (i == val2int (y)) {
		warning ("non-unique values in list");
		fprintf (stderr, "\tvalue=%d", i);
		if (yv -> yv_flags & YV_NAMED)
		    fprintf (stderr, " name1=%s", yv -> yv_named);
		if (y -> yv_flags & YV_NAMED)
		    fprintf (stderr, " name2=%s", y -> yv_named);
		fprintf (stderr, "\n");
	    }
    }
}

/* \f

 */

uniqtag (y, z)
register YP	y,
		z;
{
    int     i;
    register int    id;
    register    YT yt;
    register    YP yp;

    for (; y != z; y = y -> yp_next) {
	if ((yt = lookup_tag (y)) == NULLYT)
	    continue;

	id = PE_ID (yt -> yt_class, i = val2int (yt -> yt_value));

	for (yp = y -> yp_next; yp != z; yp = yp -> yp_next) {
	    if ((yt = lookup_tag (yp)) == NULLYT)
		continue;

	    if (id == PE_ID (yt -> yt_class, val2int (yt -> yt_value))) {
		warning ("non-unique tags in list");
		fprintf (stderr, "\ttag=%s/%d", pe_classlist[yt -> yt_class],
			i);
		if (y -> yp_code == YP_IDEFINED)
		    fprintf (stderr, " id1=%s", y -> yp_identifier);
		if (yp -> yp_code == YP_IDEFINED)
		    fprintf (stderr, " id2=%s", yp -> yp_identifier);
		fprintf (stderr, "\n");
	    }
	}
    }
}

/* \f

 */

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_VALIST:
	    yyerror ("need an integer, not a list of values");

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

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

/* \f

   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 (YP_ANY);
	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);
}

/* \f

 */

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

    (void) fclose (fp);
}

/* \f

 */

#ifndef	PEPYPATH
#define	PEPYPATH	""
#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 ("PEPYPATH")) == NULL)
	pepypath = PEPYPATH;
    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;
}

/* \f

   PRETTY-PRINTING */

#define	S0	0
#define	S1	1
#define	S2	2
#define	S3	3
#define S4	4
#define S5	5
#define S6	6
#define S7	7
#define S8	8
#define S9	9

static int  pp () {
    register int    c,
		    s;
    register char  *bp,
		   *wp;
    char    buffer[BUFSIZ];

    for (s = S0, bp = buffer; (c = getchar ()) != EOF;)
	switch (s) {
	    case S0:
		if (c == '%')
		    s = S1;
		else if (c == '<')
		    s = S4;
		else if (c == '[')
		    s = S7;
		else
		    if (isspace (c))
			*bp++ = c;
		    else {
flush: 	;
			if (bp != buffer) {
			    for (wp = buffer; wp < bp; wp++)
				putchar (*wp);
			    bp = buffer;
			}
			putchar (c);
		    }
		break;

	    case S1:
		if (c == '{') {
		    bp = buffer;
		    s = S2;
		    break;
		}
		*bp++ = '%';
		s = S0;
		goto flush;

	    case S2:
		if (c == '%')
		    s = S3;
		break;

	    case S3:
		s = c == '}' ? S0 : S2;
		break;

	    case S4:
		if ( c == '<') {
		    bp = buffer;
		    s = S5;
		    break;
		}
		*bp++ = '<';
		s = S0;
		goto flush;

	    case S5:
		if (c == '>')
		    s = S6;
		break;

	    case S6:
		s = c == '>' ? S0 : S5;
		break;

	    case S7:
		if ( c == '[') {
		    bp = buffer;
		    s = S8;
		    break;
		}
		*bp ++ = '[';
		s = S0;
		goto flush;

	    case S8:
		if (c == ']')
		    s = S9;
		break;

	    case S9:
		s = c == ']' ? S0 : S8;
		break;

	    default:
		printf ("s=%d\n", s);
		break;
	}

    if (bp != buffer)
	for (wp = buffer; wp < bp; wp++)
	    putchar (*wp);

    return 0;
}

/* \f

   DEBUG */

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

    if (yp == NULLYP)
	return;

    fprintf (stderr, "%*scode=0x%x flags=%s direction=0x%x\n", level * 4, "",
	    yp -> yp_code, sprintb (yp -> yp_flags, YPBITS),
	    yp -> yp_direction);
    fprintf (stderr,
	    "%*sintexp=\"%s\" strexp=\"%s\" prfexp=%c 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)
	fprintf (stderr, "%*sparameter type=\"%s\"\n", level * 4, "",
		 yp -> yp_param_type);
    if (yp -> yp_action0)
	fprintf (stderr, "%*saction0 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act0_lineno, yp -> yp_action0);
    if (yp -> yp_action05)
	fprintf (stderr, "%*saction05 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act05_lineno, yp -> yp_action05);
    if (yp -> yp_action1)
	fprintf (stderr, "%*saction1 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act1_lineno, yp -> yp_action1);
    if (yp -> yp_action2)
	fprintf (stderr, "%*saction2 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act2_lineno, yp -> yp_action2);
    if (yp -> yp_action3)
	fprintf (stderr, "%*saction3 at line %d=\"%s\"\n", level * 4, "",
		yp -> yp_act3_lineno, yp -> yp_action3);

    if (yp -> yp_flags & YP_TAG) {
	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) {
	fprintf (stderr, "%*sdefault=0x%x\n", level * 4, "", yp -> yp_default);
	print_value (yp -> yp_default, level + 1);
    }

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

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

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

    switch (yp -> yp_code) {
	case YP_INTLIST:
	case YP_BITLIST:
	    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);
		fprintf (stderr, "%*s----\n", (level + 1) * 4, "");
	    }
	    break;

	case YP_SEQTYPE:
	case YP_SEQLIST:
	case YP_SETTYPE:
	case YP_SETLIST:
	case YP_CHOICE:
	    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);
		fprintf (stderr, "%*s----\n", (level + 1) * 4, "");
	    }
	    break;

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

	default:
	    break;
    }
}

/* \f

 */

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

    if (yv == NULLYV)
	return;

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

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

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

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

    if (yv -> yv_flags & YV_TYPE) {
	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:
	    fprintf (stderr, "%*snumber=0x%x\n", level * 4, "",
		    yv -> yv_number);
	    break;

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

	case YV_IDEFINED:
	    if (yv -> yv_flags & YV_BOUND)
		fprintf (stderr, "%*smodule=\"%s\" identifier=\"%s\"\n",
			level * 4, "", yv -> yv_module, yv -> yv_identifier);
	    else
		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);
		fprintf (stderr, "%*s----\n", (level + 1) * 4, "");
	    }
	    break;

	default:
	    break;
    }
}

/* \f

   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;
}

/* \f

   MODULES */

static 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);
}

/* \f

   TYPES */

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

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

    return yp;
}


YP	add_type (y1, y2)
register YP	y1,
		y2;
{
    register YP	    yp;

    for (yp = y1; yp -> yp_next; yp = yp -> yp_next)
	continue;
    yp -> yp_next = y2;

    return y1;
}

/* \f

 */

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

    if (yp == NULLYP)
	return NULLYP;

    y = new_type (yp -> yp_code);
    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_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_next)
	y -> yp_next = copy_type (yp -> yp_next);

    return y;
}

/* \f

   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 (y1, y2)
register YV	y1,
		y2;
{
    register YV	    yv;

    if (y1 == NULLYV)
	return y2;

    if (y2 == NULLYV)
	return y1;

    for (yv = y1; yv -> yv_next; yv = yv -> yv_next)
	continue;
    yv -> yv_next = y2;

    return y1;
}

/* \f

 */

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;
}

/* \f

   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;
}

/* \f

 */

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;
}

/* \f

 */

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;
}

/* \f

   STRINGS */

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

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

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

/* \f

   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
};

/* \f

 */

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

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

    if (module && strcmp (module, mymodule))
	switch (direct) {
	    case YP_DECODER:
		pref = yydecdflt;
		break;

	    case YP_ENCODER:
		pref = yyencdflt;
		break;

	    case YP_PRINTER:
		pref = yyprfdflt;
		break;
	}

    modsym_aux (pref ? pref : yyprefix, buf1);
    modsym_aux (module ? module : mymodule, buf2);
    modsym_aux (id, buf3);
    (void) sprintf (buffer, "%s_%s_%s", buf1, 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;
}

/* \f

 */

char *gensym () {
    char    buffer[BUFSIZ];
    static int  i = 0;

    (void) sprintf (buffer, "p%d", i++);
    return new_string (buffer);
}

init_new_file ()
{
    static int file_no = 0;
    char	buffer[BUFSIZ];

    (void) sprintf (buffer, "%s-%.*d.c", bflag, bwidth, ++file_no);
    if (freopen (buffer, "w", stdout) == NULL) {
	fprintf (stderr, "unable to write "), perror (buffer);
	exit (1);
    }

    prologue ();
    prologue3 ();

    if (module_actions)
	fputs (module_actions, stdout);

    prologue2 ();
}

end_file ()
{
    (void) fflush (stdout);
    if (ferror (stdout))
	myyerror ("write error - %s", sys_errname (errno));
    
}