* Called from tree, this routine takes the top 1, 2, or 3
* operands on the expression stack, makes a new node with
* the operator op, and puts it on the stack.
* Essentially all the work is in inserting
* appropriate conversions.
register struct tnode
*p1
, *p2
;
int dope
, leftc
, cvn
, pcvn
;
p2
= chkfun(disarray(*--cp
));
* sizeof gets turned into a number here.
if ((t1
&XTYPE
)==FUNC
|| (t1
&XTYPE
)==ARRAY
)
error("Disallowed conversion");
if (t1
==UNSIGN
&& t2
==CHAR
) {
p2
= block(AND
,INT
,NULL
,NULL
,p2
,cblock(0377));
/* no-conversion operators */
error("Illegal conditional");
*cp
++ = block(op
, t
, NULL
, NULL
, p1
, p2
);
error("Call of non-function");
*cp
++ = block(CALL
,decref(t1
),p1
->subsp
,p1
->strp
,p1
,p2
);
error("Illegal indirection");
*cp
++ = block(STAR
, decref(t1
), p1
->subsp
, p1
->strp
, p1
);
if (p1
->op
==NAME
|| p1
->op
==STAR
) {
*cp
++ = block(op
,incref(t1
),p1
->subsp
,p1
->strp
,p1
);
if (p1
->op
==CALL
&& t1
==STRUCT
) {
* In a->b, a is given the type ptr-to-structure element;
* then the offset is added in without conversion;
* then * is tacked on to access the member.
if (p2
->op
!=NAME
|| p2
->tr1
->hclass
!=MOS
) {
error("Illegal structure ref");
if (t2
==INT
&& p2
->tr1
->hflag
&FFIELD
)
*cp
++ = block(PLUS
,t
,p2
->subsp
,p2
->strp
,p1
,cblock(p2
->tr1
->hoffset
));
if (p2
->tr1
->hflag
&FFIELD
)
*cp
++ = block(FSEL
,UNSIGN
,NULL
,NULL
,*--cp
,p2
->tr1
->hstrp
);
*cp
++ = block(op
,t1
,p1
->subsp
,p1
->strp
,p1
);
if (t1
==STRUCT
|| t2
==STRUCT
) {
if (t1
!=t2
|| p1
->strp
!= p2
->strp
)
error("Incompatible structures");
cvn
= cvtab
[lintyp(t1
)][lintyp(t2
)];
if ((t
==INT
||t
==CHAR
) && (t1
==UNSIGN
||t2
==UNSIGN
))
if (dope
&ASSGOP
|| op
==CAST
) {
if (op
==ASSIGN
|| op
==CAST
) {
} else if (op
==COLON
|| op
==MAX
|| op
==MIN
) {
if (op
!=COLON
&& (t1
>=PTR
|| t2
>=PTR
))
if (op
>=LESSEQ
&& (t1
>=PTR
||t2
>=PTR
||(t1
==UNSIGN
||t2
==UNSIGN
)
&& (t
==INT
||t
==CHAR
||t
==UNSIGN
)))
if (cvn
==ITP
|| cvn
==PTI
)
if (t1
!=t2
|| t1
!=(PTR
+CHAR
))
if (cvn
==XX
|| (cvn
==PTI
&&t1
!=t2
))
error("Illegal conversion");
p1
= convert(p1
, t
, cvn
, t2
);
p2
= convert(p2
, t
, cvn
, t1
);
if (t
!=DOUBLE
&& (t
!=INT
|| p2
->type
!=CHAR
)) {
if (t
==INT
&& p1
->type
==CHAR
)
p2
= block(ITOC
, INT
, NULL
, NULL
, p2
);
if (fold(op
, p1
, p2
)==0) {
*cp
++ = block(op
, t
, p3
->subsp
, p3
->strp
, p1
, p2
);
if (pcvn
&& t1
!=(PTR
+CHAR
)) {
*cp
++ = convert(p1
, 0, PTI
, plength(p1
->tr1
));
* Generate the appropriate conversion operator.
error("Illegal conversion");
return(block(op
, t
, NULL
, NULL
, p
, cblock(len
)));
return(block(op
, t
, NULL
, NULL
, p
));
* Traverse an expression tree, adjust things
* so the types of things in it are consistent
* with the view that its top node has
* Used with structure references.
struct tnode
*ap
, *anewp
;
register struct tnode
*p
, *newp
;
* A mention of a function name is turned into
* a pointer to that function.
register struct tnode
*p
;
if (((t
= p
->type
)&XTYPE
)==FUNC
&& p
->op
!=ETYPE
)
return(block(AMPER
,incref(t
),p
->subsp
,p
->strp
,p
));
* A mention of an array is turned into
* a pointer to the base of the array.
register struct tnode
*p
;
/* check array & not MOS and not typer */
if (((t
= p
->type
)&XTYPE
)!=ARRAY
|| p
->op
==NAME
&&p
->tr1
->hclass
==MOS
* make sure that p is a ptr to a node
* with type int or char or 'okt.'
* okt might be nonexistent or 'long'
if ((t
=p
->type
)!=INT
&& t
<PTR
&& t
!=CHAR
&& t
!=UNSIGN
&& t
!=okt
)
error("Illegal type of operand");
*'linearize' a type for looking up in the
error(s
, p1
, p2
, p3
, p4
, p5
, p6
)
fprintf(stderr
, "%s:", filename
);
fprintf(stderr
, "%d: ", line
);
fprintf(stderr
, s
, p1
, p2
, p3
, p4
, p5
, p6
);
* Generate a node in an expression tree,
* setting the operator, type, dimen/struct table ptrs,
block(op
, t
, subs
, str
, p1
,p2
)
register struct tnode
*p
;
register struct hshtab
*ds
;
return(block(NAME
, ds
->htype
, ds
->hsubsp
, ds
->hstrp
, ds
));
* Generate a block for a constant
register struct cnode
*p
;
* A block for a float or long constant
register struct fnode
*p
;
* Assign a block for use in the
if ((curbase
=+ n
) >= coremax
) {
* Check that a tree can be used as an lvalue.
register struct tnode
*p
;
if (p
->op
!=NAME
&& p
->op
!=STAR
)
error("Lvalue required");
* reduce some forms of `constant op constant'
* to a constant. More of this is done in the next pass
* but this is used to allow constant expressions
* to be used in switches and array bounds.
register struct tnode
*p1
;
unsignf
= p1
->type
==UNSIGN
;
if (ap2
->tr1
->op
==CON
&& ap2
->tr2
->op
==CON
) {
p1
->value
= p1
->value
? ap2
->tr1
->value
: ap2
->tr2
->value
;
unsignf
|= ap2
->type
==UNSIGN
;
* Compile an expression expected to have constant value,
* for example an array bound or a case value.
register struct tnode
*t
;
error("Constant required");