home *** CD-ROM | disk | FTP | other *** search
- /*-
- * Copyright (c) 1980 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[] = "@(#)pclval.c 5.2 (Berkeley) 4/16/91";
- #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.
- */
- bool
- nilfnil( 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
-