* Copyright (c) 1980 The Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)lval.c 5.3 (Berkeley) %G%";
* Lvalue 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.
lvalue(var
, modflag
, required
)
struct nl
*firstp
, *lastp
;
register struct tnode
*c
, *co
;
* Note that the local optimizations
* done here for offsets would more
* appropriately be done in put.
struct tnode tr
; /* T_FIELD */
error("Variable required"); /* Pass mesgs down from pt of call ? */
* pc requires a whole different control flow
return pclvalue( var
, modflag
, required
);
* pi uses the rest of the function
firstp
= p
= lookup(var
->var_node
.cptr
);
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.
* Construct the tree implied by
/* the cast has got to go but until the node is figured
tr_ptr
->list_node
.list
= (&tr
);
tr_ptr
->list_node
.next
= var
->var_node
.qual
;
tr
.field_node
.id_ptr
= var
->var_node
.cptr
;
c
= tr_ptr
; /* c is a ptr to a tnode */
* mung var->fields to say which field this T_VAR is
/* problem! reclook returns struct nl* */
var
->var_node
.fields
= reclook( p
-> type
,
* Obtain the indirect word
* as the base of our lvalue
(void) put(2, PTR_RV
| bn
<< 8+INDX
, (int)p
->value
[0] );
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
if (c
== TR_NIL
&& (modflag
&ASGN
) && ( p
->value
[NL_FORV
] & FORVAR
) ) {
error("Can't modify the for variable %s in the range of the loop", p
->symbol
);
s
= 0; /* subscripts seen */
for (; c
!= TR_NIL
; c
= c
->list_node
.next
) {
co
= c
->list_node
.list
; /* co is a ptr to a tnode */
* 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)",
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 == FILET
&& bn
!= 0)
(void) put(2, O_LV
| bn
<<8+INDX
, o
);
* 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
* This is further complicated by
* the fact that global variables
* are referenced through pointers
* on the stack. Thus an RV on a
* global variable is the same as
* an LV of a non-global one ?!?
(void) put(2, PTR_RV
| bn
<<8+INDX
, o
);
if (p
->class != FILET
|| bn
== 0)
(void) put(1, p
->class == FILET
? O_FNIL
: O_NIL
);
error("%s is a %s, not a function", var
->var_node
.cptr
, classes
[firstp
->class]);
error("Illegal function qualificiation");
error("Pascal uses [] for subscripting, not ()");
error("Subscripting allowed only on arrays, not on %ss", nameof(p
));
* referenced through pointers
(void) put(2, PTR_RV
| bn
<<8+INDX
, o
);
(void) put(2, O_LV
| bn
<<8+INDX
, o
);
switch(s
= arycod(p
,co
->ary_node
.expr_list
,s
)) {
* This is the number of subscripts seen
if (p
->class != RECORD
) {
error(". allowed only on records, not on %ss", nameof(p
));
/* must define the field node!! */
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
);
* mung co[3] to indicate which field
co
->field_node
.nl_entry
= p
;
if ((modflag
& NOUSE
) == 0 ||
lptr(c
->list_node
.next
)) {
/* figure out what kind of node c is !! */
error("Too few subscripts (%d given, %d required)",
* global variables are referenced through
(void) put(2, PTR_RV
| bn
<<8+INDX
, o
);
(void) put(2, O_LV
| bn
<<8+INDX
, o
);
cerror("Error occurred on qualification of %s", var
->var_node
.cptr
);
register struct tnode
*c
;
register struct tnode
*co
;
for (; c
!= TR_NIL
; c
= c
->list_node
.next
) {
* subscripts already seen
register struct nl
*p
, *ap
;
int i
, d
; /* v, v1; these aren't used */
for (i
= 1; i
<= n
; i
++) {
for (i
= n
+1; i
<= d
; i
++) {
if ((p
->class != CRANGE
) &&
(constsub
= constval(el
->list_node
.list
))) {
if (sub
< p
->range
[0] || sub
> p
->range
[1]) {
error("Subscript value of %D is out of range", (char *) sub
);
precheck( p
, "_SUBSC" , "_SUBSCZ" );
ap
= rvalue(el
->list_node
.list
, NLNIL
, RREQ
);
sconv(p2type(ap
),PCCT_INT
);
if (incompat(ap
, p
->type
, el
->list_node
.list
)) {
cerror("Array index type incompatible with declared index type");
cerror("Error occurred on index number %d", (char *) i
);
if (p
->class == CRANGE
) {
(void) put(2, w
<= 2 ? O_CON2
: O_CON4
, sub
);
(void) gen(NIL
, T_ADD
, sizeof(char *), w
);
if (p
->class == CRANGE
) {
} else if (opt('t') == 0) {
(void) put(2, (width(ap
) != 4 ? O_INX2P2
: O_INX4P2
) | (w
& ~1) << 7, ( short ) p
->range
[0]);
if (p
->class == CRANGE
) {
put(1, width(ap
) != 4 ? O_VINX42
: O_VINX4
);
put(1, width(ap
) != 4 ? O_VINX2
: O_VINX24
);
put(4, width(ap
) != 4 ? O_INX2
: O_INX4
, w
,
(short)p
->range
[0], (short)(p
->range
[1]));
* subtract off the lower bound
putleaf( PCC_ICON
, (int) sub
, 0 , PCCT_INT
, (char *) 0 );
putop(PCC_PLUS
, PCCM_ADDTYPE(p2type(np
->type
), PCCTM_PTR
));
if (p
->class == CRANGE
) {
* if conformant array, subtract off lower bound
putRV(ap
->symbol
, (ap
->nl_block
& 037), ap
->value
[0],
ap
->extra_flags
, p2type( ap
) );
putop( PCC_MINUS
, PCCT_INT
);
* and multiply by the width of the elements
putRV( 0 , (ap
->nl_block
& 037), ap
->value
[0],
ap
->extra_flags
, p2type( ap
) );
putop( PCC_MUL
, PCCT_INT
);
if ( p
-> range
[ 0 ] != 0 ) {
putleaf( PCC_ICON
, (int) p
-> range
[0] , 0 , PCCT_INT
, (char *) 0 );
putop( PCC_MINUS
, PCCT_INT
);
* multiply by the width of the elements
putleaf( PCC_ICON
, w
, 0 , PCCT_INT
, (char *) 0 );
putop( PCC_MUL
, PCCT_INT
);
* and add it to the base address
putop( PCC_PLUS
, PCCM_ADDTYPE( p2type( np
-> type
) , PCCTM_PTR
) );
if (np
->type
->class != ARRAY
) {
error("Too many subscripts (%d given, %d required)", (char *) (i
-1), (char *) d
);
return(arycod(np
->type
, el
, d
));
* Put out the conformant array bounds (lower bound, upper bound or width)
* for conformant array type ctype.
* The value of i determines which is being put
* i = 0: lower bound, i=1: upper bound, i=2: width
switch(width(ctype
->type
)) {
put(2, O_RV1
| (ctype
->nl_block
& 037) << 8+INDX
,
(int)ctype
->nptr
[i
]->value
[0]);
put(2, O_RV2
| (ctype
->nl_block
& 037) << 8+INDX
,
(int)ctype
->nptr
[i
]->value
[0]);
put(2, O_RV4
| (ctype
->nl_block
& 037) << 8+INDX
,
(int)ctype
->nptr
[i
]->value
[0]);