4.4BSD/usr/src/usr.bin/pascal/src/yyid.c

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

/*-
 * Copyright (c) 1980, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
static char sccsid[] = "@(#)yyid.c	8.1 (Berkeley) 6/6/93";
#endif /* not lint */

#include "whoami.h"
#include <0.h>
#include "tree_ty.h"	/* must be included for yy.h */
#include "yy.h"

#ifdef PI
extern	union semstack *yypv;
/*
 * Determine whether the identifier whose name
 * is "cp" can possibly be a kind, which is a
 * namelist class.  We look through the symbol
 * table for the first instance of cp as a non-field,
 * and at all instances of cp as a field.
 * If any of these are ok, we return true, else false.
 * It would be much better to handle with's correctly,
 * even to just know whether we are in a with at all.
 *
 * Note that we don't disallow constants on the lhs of assignment.
 */
identis(cp, kind)
	register char *cp;
	int kind;
{
	register struct nl *p;
	int i;

	/*
	 * Cp is NIL when error recovery inserts it.
	 */
	if (cp == NIL)
		return (1);

	/*
	 * Record kind we want for possible later use by yyrecover
	 */
	yyidwant = kind;
	yyidhave = NIL;
	i = ( (int) cp ) & 077;
	for (p = disptab[i]; p != NIL; p = p->nl_next)
		if (p->symbol == cp) {
			if (yyidok(p, kind))
				goto gotit;
			if (p->class != FIELD && p->class != BADUSE)
				break;
		}
	if (p != NIL)
		for (p = p->nl_next; p != NIL; p = p->nl_next)
			if (p->symbol == cp && p->class == FIELD && yyidok(p, kind))
				goto gotit;
	return (0);
gotit:
	if (p->class == BADUSE && !Recovery) {
		yybadref(p, OY.Yyeline);
		yypv[0].i_entry = NIL;
	}
	return (1);
}

/*
 * A bad reference to the identifier cp on line
 * line and use implying the addition of kindmask
 * to the mask of kind information.
 */
struct nl *
yybaduse(cp, line, kindmask)
	register char *cp;
	int line, kindmask;
{
	register struct nl *p, *oldp;
	int i;

	i = ( (int) cp ) & 077;
	for (p = disptab[i]; p != NIL; p = p->nl_next)
		if (p->symbol == cp)
			break;
	oldp = p;
	if (p == NIL || p->class != BADUSE)
		p = enter(defnl(cp, BADUSE, NLNIL, 0));
	p->value[NL_KINDS] |= kindmask;
	yybadref(p, line);
	return (oldp);
}

    /*
     *	ud is initialized so that esavestr will allocate
     *	sizeof ( struct udinfo ) bytes for the 'real' struct udinfo
     */
struct	udinfo ud = { ~0 , (struct udinfo *) ~0 , 0};
/*
 * Record a reference to an undefined identifier,
 * or one which is improperly used.
 */
yybadref(p, line)
	register struct nl *p;
	int line;
{
	register struct udinfo *udp;

	if (p->chain != NIL && ((struct udinfo *) p->chain)->ud_line == line)
		return;
	udp = (struct udinfo *) esavestr((char *) &ud);
	udp->ud_line = line;
	udp->ud_next = (struct udinfo *) p->chain;
	p->chain = (struct nl *) udp;
}

#define	varkinds	((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \
			|(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \
			|(1<<FFUNC)|(1<<PROC)|(1<<FPROC))
/*
 * Is the symbol in the p entry of the namelist
 * even possibly a kind kind?  If not, update
 * what we have based on this encounter.
 */
yyidok(p, kind)
	register struct nl *p;
	int kind;
{

	if (p->class == BADUSE) {
		if (kind == VAR)
			return (p->value[0] & varkinds);
		return (p->value[0] & (1 << kind));
	}
	if (yyidok1(p, kind))
		return (1);
	if (yyidhave != NIL)
		yyidhave = IMPROPER;
	else
		yyidhave = p->class;
	return (0);
}

yyidok1(p, kind)
	register struct nl *p;
	int kind;
{

	switch (kind) {
		default:
		case FUNC:
			return (   p -> class == FUNC
				|| p -> class == FVAR
				|| p -> class == FFUNC );
		case PROC:
			return ( p -> class == PROC || p -> class == FPROC );
		case CONST:
		case TYPE:
		case FIELD:
			return (p->class == kind);
		case VAR:
			return (p->class == CONST || yyisvar(p, NIL));
		case ARRAY:
		case RECORD:
			return (yyisvar(p, kind));
		case PTRFILE:
			return (yyisvar(p, PTR) || yyisvar(p, FILET));
	}
}

yyisvar(p, varclass)
	register struct nl *p;
	int varclass;
{

	switch (p->class) {
		case FIELD:
		case VAR:
		case REF:
		case FVAR:
		/*
		 * We would prefer to return
		 * parameterless functions only.
		 */
		case FUNC:
		case FFUNC:
			return (varclass == NIL || (p->type != NIL && p->type->class == varclass));
		case PROC:
		case FPROC:
			return ( varclass == NIL );
	}
	return (0);
}
#endif
#ifdef PXP
#ifndef DEBUG
identis()
{

	return (1);
}
#endif
#ifdef DEBUG
extern	char *classes[];

char	kindchars[]	"UCTVAQRDPF";
/*
 * Fake routine "identis" for pxp when testing error recovery.
 * Looks at letters in variable names to answer questions
 * about attributes.  Mapping is
 *	C	const_id
 *	T	type_id
 *	V	var_id		also if any of AQRDF
 *	A	array_id
 *	Q	ptr_id
 *	R	record_id
 *	D	field_id	D for "dot"
 *	P	proc_id
 *	F	func_id
 */
identis(cp, kind)
	register char *cp;
	int kind;
{
	register char *dp;
	char kindch;

	/*
	 * Don't do anything unless -T
	 */
	if (!typetest)
		return (1);

	/*
	 * Inserted symbols are always correct
	 */
	if (cp == NIL)
		return (1);
	/*
	 * Set up the names for error messages
	 */
	yyidwant = classes[kind];
	for (dp = kindchars; *dp; dp++)
		if (any(cp, *dp)) {
			yyidhave = classes[dp - kindchars];
			break;
		}

	/*
	 * U in the name means undefined
	 */
	if (any(cp, 'U'))
		return (0);

	kindch = kindchars[kind];
	if (kindch == 'V')
		for (dp = "AQRDF"; *dp; dp++)
			if (any(cp, *dp))
				return (1);
	return (any(cp, kindch));
}
#endif
#endif