⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pclval.c

📁 早期freebsd实现
💻 C
字号:
/*- * 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 lintstatic char sccsid[] = "@(#)pclval.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include "whoami.h"#include "0.h"#include "tree.h"#include "opcode.h"#include "objfmt.h"#include "tree_ty.h"#ifdef PC	/*	 *	and the rest of the file	 */#   include	"pc.h"#   include	<pcc.h>extern	int flagwas;/* * pclvalue computes the address * of a qualified name and * leaves it on the stack. * for pc, it can be asked for either an lvalue or an rvalue. * the semantics are the same, only the code is different. * for putting out calls to check for nil and fnil, * we have to traverse the list of qualifications twice: * once to put out the calls and once to put out the address to be checked. */struct nl *pclvalue( var , modflag , required )	struct tnode	*var;	int	modflag;	int	required;{	register struct nl	*p;	register struct tnode 	*c, *co;	int			f, o;	struct tnode		l_node, tr;	VAR_NODE		*v_node;	LIST_NODE		*tr_ptr;	struct nl		*firstp, *lastp;	char			*firstsymbol;	char			firstextra_flags;	int			firstbn;	int			s;	if ( var == TR_NIL ) {		return NLNIL;	}	if ( nowexp( var ) ) {		return NLNIL;	}	if ( var->tag != T_VAR ) {		error("Variable required");	/* Pass mesgs down from pt of call ? */		return NLNIL;	}	v_node = &(var->var_node);	firstp = p = lookup( v_node->cptr );	if ( p == NLNIL ) {		return NLNIL;	}	firstsymbol = p -> symbol;	firstbn = bn;	firstextra_flags = p -> extra_flags;	c = v_node->qual;	if ( ( modflag & NOUSE ) && ! lptr( c ) ) {		p -> nl_flags = flagwas;	}	if ( modflag & MOD ) {		p -> nl_flags |= NMOD;	}	/*	 * Only possibilities for p -> class here	 * are the named classes, i.e. CONST, TYPE	 * VAR, PROC, FUNC, REF, or a WITHPTR.	 */	 tr_ptr = &(l_node.list_node);	if ( p -> class == WITHPTR ) {		/*		 * Construct the tree implied by		 * the with statement		 */	    l_node.tag = T_LISTPP;	    tr_ptr->list = &(tr);	    tr_ptr->next = v_node->qual;	    tr.tag = T_FIELD;	    tr.field_node.id_ptr = v_node->cptr;	    c = &(l_node);	}	    /*	     *	this not only puts out the names of functions to call	     *	but also does all the semantic checking of the qualifications.	     */	if ( ! nilfnil( p , c , modflag , firstp , v_node->cptr ) ) {	    return NLNIL;	}	switch (p -> class) {		case WITHPTR:		case REF:			/*			 * Obtain the indirect word			 * of the WITHPTR or REF			 * as the base of our lvalue			 */			putRV( firstsymbol , firstbn , p -> value[ 0 ] ,				firstextra_flags , p2type( p ) );			firstsymbol = 0;			f = 0;		/* have an lv on stack */			o = 0;			break;		case VAR:			if (p->type->class != CRANGE) {				f = 1;		/* no lv on stack yet */				o = p -> value[0];			} else {				error("Conformant array bound %s found where variable required", p->symbol);				return(NIL);			}			break;		default:			error("%s %s found where variable required", classes[p -> class], p -> symbol);			return (NLNIL);	}	/*	 * Loop and handle each	 * qualification on the name	 */	if ( c == NIL &&	    ( modflag & ASGN ) &&	    ( p -> value[ NL_FORV ] & FORVAR ) ) {		error("Can't modify the for variable %s in the range of the loop", p -> symbol);		return (NLNIL);	}	s = 0;	for ( ; c != TR_NIL ; c = c->list_node.next ) {		co = c->list_node.list;		if ( co == TR_NIL ) {			return NLNIL;		}		lastp = p;		p = p -> type;		if ( p == NLNIL ) {			return NLNIL;		}		/*		 * If we haven't seen enough subscripts, and the next		 * qualification isn't array reference, then it's an error.		 */		if (s && co->tag != T_ARY) {			error("Too few subscripts (%d given, %d required)",				s, p->value[0]);		}		switch ( co->tag ) {			case T_PTR:				/*				 * Pointer qualification.				 */				if ( f ) {					putLV( firstsymbol , firstbn , o ,					    firstextra_flags , p2type( p ) );					firstsymbol = 0;				} else {					if (o) {					    putleaf( PCC_ICON , o , 0 , PCCT_INT						    , (char *) 0 );					    putop( PCC_PLUS , PCCTM_PTR | PCCT_CHAR );					}				}				    /*				     * Pointer cannot be				     * nil and file cannot				     * be at end-of-file.				     * the appropriate function name is 				     * already out there from nilfnil.				     */				if ( p -> class == PTR ) {					/*					 * this is the indirection from					 * the address of the pointer 					 * to the pointer itself.					 * kirk sez:					 * fnil doesn't want this.					 * and does it itself for files					 * since only it knows where the					 * actual window is.					 * but i have to do this for					 * regular pointers.					 */				    putop( PCCOM_UNARY PCC_MUL , p2type( p ) );				    if ( opt( 't' ) ) {					putop( PCC_CALL , PCCT_INT );				    }				} else {				    putop( PCC_CALL , PCCT_INT );				}				f = o = 0;				continue;			case T_ARGL:			case T_ARY:				if ( f ) {					putLV( firstsymbol , firstbn , o ,					    firstextra_flags , p2type( p ) );					firstsymbol = 0;				} else {					if (o) {					    putleaf( PCC_ICON , o , 0 , PCCT_INT						    , (char *) 0 );					    putop( PCC_PLUS , PCCT_INT );					}				}				s = arycod( p , co->ary_node.expr_list, s);				if (s == p->value[0]) {					s = 0;				} else {					p = lastp;				}				f = o = 0;				continue;			case T_FIELD:				/*				 * Field names are just				 * an offset with some 				 * semantic checking.				 */				p = reclook(p, co->field_node.id_ptr);				o += p -> value[0];				continue;			default:				panic("lval2");		}	}	if (s) {		error("Too few subscripts (%d given, %d required)",			s, p->type->value[0]);		return NLNIL;	}	if (f) {		if ( required == LREQ ) {		    putLV( firstsymbol , firstbn , o ,			    firstextra_flags , p2type( p -> type ) );		} else {		    putRV( firstsymbol , firstbn , o ,			    firstextra_flags , p2type( p -> type ) );		}	} else {		if (o) {		    putleaf( PCC_ICON , o , 0 , PCCT_INT , (char *) 0 );		    putop( PCC_PLUS , PCCT_INT );		}		if ( required == RREQ ) {		    putop( PCCOM_UNARY PCC_MUL , p2type( p -> type ) );		}	}	return ( p -> type );}    /*     *	this recursively follows done a list of qualifications     *	and puts out the beginnings of calls to fnil for files     *	or nil for pointers (if checking is on) on the way back.     *	this returns true or false.     */boolnilfnil( p , c , modflag , firstp , r2 )    struct nl	 *p;    struct tnode *c;    int		modflag;    struct nl	*firstp;    char	*r2;		/* no, not r2-d2 */    {	struct tnode 	*co;	struct nl	*lastp;	int		t;	static int	s = 0;	if ( c == TR_NIL ) {	    return TRUE;	}	co = ( c->list_node.list );	if ( co == TR_NIL ) {		return FALSE;	}	lastp = p;	p = p -> type;	if ( p == NLNIL ) {		return FALSE;	}	switch ( co->tag ) {	    case T_PTR:		    /*		     * Pointer qualification.		     */		    lastp -> nl_flags |= NUSED;		    if ( p -> class != PTR && p -> class != FILET) {			    error("^ allowed only on files and pointers, not on %ss", nameof(p));			    goto bad;		    }		    break;	    case T_ARGL:		    if ( p -> class != ARRAY ) {			    if ( lastp == firstp ) {				    error("%s is a %s, not a function", r2, classes[firstp -> class]);			    } else {				    error("Illegal function qualificiation");			    }			    return FALSE;		    }		    recovered();		    error("Pascal uses [] for subscripting, not ()");		    /* and fall through */	    case T_ARY:		    if ( p -> class != ARRAY ) {			    error("Subscripting allowed only on arrays, not on %ss", nameof(p));			    goto bad;		    }		    codeoff();		    s = arycod( p , co->ary_node.expr_list , s );		    codeon();		    switch ( s ) {			    case 0:				    return FALSE;			    case -1:				    goto bad;		    }		    if (s == p->value[0]) {			    s = 0;		    } else {			    p = lastp;		    }		    break;	    case T_FIELD:		    /*		     * Field names are just		     * an offset with some 		     * semantic checking.		     */		    if ( p -> class != RECORD ) {			    error(". allowed only on records, not on %ss", nameof(p));			    goto bad;		    }		    if ( co->field_node.id_ptr == NIL ) {			    return FALSE;		    }		    p = reclook( p , co->field_node.id_ptr );		    if ( p == NIL ) {			    error("%s is not a field in this record", co->field_node.id_ptr);			    goto bad;		    }		    if ( modflag & MOD ) {			    p -> nl_flags |= NMOD;		    }		    if ((modflag & NOUSE) == 0 || lptr(c->field_node.other )) {			    p -> nl_flags |= NUSED;		    }		    break;	    default:		    panic("nilfnil");	}	    /*	     *	recursive call, check the rest of the qualifications.	     */	if ( ! nilfnil( p , c->list_node.next , modflag , firstp , r2 ) ) {	    return FALSE;	}	    /*	     *	the point of all this.	     */	if ( co->tag == T_PTR ) {	    if ( p -> class == PTR ) {		    if ( opt( 't' ) ) {			putleaf( PCC_ICON , 0 , 0			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )			    , "_NIL" );		    }	    } else {		    putleaf( PCC_ICON , 0 , 0			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )			, "_FNIL" );	    }	}	return TRUE;bad:	cerror("Error occurred on qualification of %s", r2);	return FALSE;    }#endif PC

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -