* Copyright (c) 1980 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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
static char sccsid
[] = "@(#)pclval.c 5.2 (Berkeley) 4/16/91";
* and the rest of the file
* 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.
pclvalue( var
, modflag
, required
)
register struct tnode
*c
, *co
;
struct nl
*firstp
, *lastp
;
if ( var
->tag
!= T_VAR
) {
error("Variable required"); /* Pass mesgs down from pt of call ? */
v_node
= &(var
->var_node
);
firstp
= p
= lookup( v_node
->cptr
);
firstsymbol
= p
-> symbol
;
firstextra_flags
= p
-> extra_flags
;
if ( ( modflag
& NOUSE
) && ! lptr( c
) ) {
* 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
tr_ptr
->next
= v_node
->qual
;
tr
.field_node
.id_ptr
= v_node
->cptr
;
* 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
) ) {
* Obtain the indirect word
* as the base of our lvalue
putRV( firstsymbol
, firstbn
, p
-> value
[ 0 ] ,
firstextra_flags
, p2type( p
) );
f
= 0; /* have an lv on stack */
if (p
->type
->class != CRANGE
) {
f
= 1; /* no lv on stack yet */
error("Conformant array bound %s found where variable required", p
->symbol
);
error("%s %s found where variable required", classes
[p
-> class], p
-> symbol
);
* qualification on the name
( p
-> value
[ NL_FORV
] & FORVAR
) ) {
error("Can't modify the for variable %s in the range of the loop", p
-> symbol
);
for ( ; c
!= TR_NIL
; c
= c
->list_node
.next
) {
* 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)",
putLV( firstsymbol
, firstbn
, o
,
firstextra_flags
, p2type( p
) );
putleaf( PCC_ICON
, o
, 0 , PCCT_INT
putop( PCC_PLUS
, PCCTM_PTR
| PCCT_CHAR
);
* the appropriate function name is
* already out there from nilfnil.
if ( p
-> class == PTR
) {
* this is the indirection from
* the address of the pointer
* fnil doesn't want this.
* and does it itself for files
* since only it knows where the
* but i have to do this for
putop( PCCOM_UNARY PCC_MUL
, p2type( p
) );
putop( PCC_CALL
, PCCT_INT
);
putop( PCC_CALL
, PCCT_INT
);
putLV( firstsymbol
, firstbn
, o
,
firstextra_flags
, p2type( p
) );
putleaf( PCC_ICON
, o
, 0 , PCCT_INT
putop( PCC_PLUS
, PCCT_INT
);
s
= arycod( p
, co
->ary_node
.expr_list
, s
);
p
= reclook(p
, co
->field_node
.id_ptr
);
error("Too few subscripts (%d given, %d required)",
if ( required
== LREQ
) {
putLV( firstsymbol
, firstbn
, o
,
firstextra_flags
, p2type( p
-> type
) );
putRV( firstsymbol
, firstbn
, o
,
firstextra_flags
, p2type( p
-> type
) );
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
) );
* 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.
nilfnil( p
, c
, modflag
, firstp
, r2
)
char *r2
; /* no, not r2-d2 */
co
= ( c
->list_node
.list
);
lastp
-> nl_flags
|= NUSED
;
if ( p
-> class != PTR
&& p
-> class != FILET
) {
error("^ allowed only on files and pointers, not on %ss", nameof(p
));
if ( p
-> class != ARRAY
) {
error("%s is a %s, not a function", r2
, classes
[firstp
-> class]);
error("Illegal function qualificiation");
error("Pascal uses [] for subscripting, not ()");
if ( p
-> class != ARRAY
) {
error("Subscripting allowed only on arrays, not on %ss", nameof(p
));
s
= arycod( p
, co
->ary_node
.expr_list
, s
);
if ( p
-> class != RECORD
) {
error(". allowed only on records, not on %ss", nameof(p
));
if ( co
->field_node
.id_ptr
== NIL
) {
p
= reclook( p
, co
->field_node
.id_ptr
);
error("%s is not a field in this record", co
->field_node
.id_ptr
);
if ((modflag
& NOUSE
) == 0 || lptr(c
->field_node
.other
)) {
* recursive call, check the rest of the qualifications.
if ( ! nilfnil( p
, c
->list_node
.next
, modflag
, firstp
, r2
) ) {
if ( co
->tag
== T_PTR
) {
if ( p
-> class == PTR
) {
putleaf( PCC_ICON
, 0 , 0
, PCCM_ADDTYPE( PCCTM_FTN
| PCCT_INT
, PCCTM_PTR
)
putleaf( PCC_ICON
, 0 , 0
, PCCM_ADDTYPE( PCCTM_FTN
| PCCT_INT
, PCCTM_PTR
)
cerror("Error occurred on qualification of %s", r2
);