/* Copyright (c) 1979 Regents of the University of California */
static char sccsid
[] = "@(#)conv.c 1.2 3/8/81";
* Convert a p1 into a p2.
* Mostly used for different
* length integers and "to real" conversions.
if (p1
== NIL
|| p2
== NIL
)
switch (width(p1
) - width(p2
)) {
* p1 and p2 are compatible
* types for an assignment like
* context, i.e. value parameters,
* indicies for 'in', etc.
if (c2
== TINT
&& divflg
== 0 && t
!= NIL
) {
c1
= classify(rvalue(t
, NLNIL
, RREQ
));
error("Type clash: real is incompatible with integer");
cerror("This resulted because you used '/' which always returns real rather");
cerror("than 'div' which divides integers and returns integers");
if (scalar(p1
) != scalar(p2
)) {
derror("Type clash: non-identical scalar types");
if (width(p1
) != width(p2
)) {
derror("Type clash: unequal length strings");
derror("Type clash: files not allowed in this context");
derror("Type clash: non-identical %s types", clnames
[c1
]);
if (p1
->nl_flags
& NFILES
) {
derror("Type clash: %ss with file components not allowed in this context", clnames
[c1
]);
derror("Type clash: %s is incompatible with %s", clnames
[c1
], clnames
[c2
]);
* Rangechk generates code to
* check if the type p on top
* of the stack is in range for
* assignment to a variable
* When op is 1 we are checking length
* 4 numbers against length 2 bounds,
* and adding it to the opcode forces
* generation of appropriate tests.
op
= wq
!= wrp
&& (wq
== 4 || wrp
== 4);
put(3, O_RANG2
+op
, ( short ) rp
->range
[0],
put(3, O_RANG4
+op
, rp
->range
[0], rp
->range
[1] );
put(3, O_RANG2
+op
,( short ) rp
->range
[0],
put(3, O_RANG4
+op
,rp
->range
[0],
if (rp
!= nl
+T2INT
&& rp
!= nl
+T4INT
)
put(3, O_RANG2
+op
,( short ) rp
->range
[0],
* Range whose lower bounds are
* zero can be treated as scalars.
put(2, O_RSNG2
+op
, ( short ) rp
->range
[1]);
put( 2 , O_RSNG4
+op
, rp
->range
[1]);
* what i want to do is make this and some other stuff
* arguments to a function call, which will do the rangecheck,
* and return the value of the current expression, or abort
* if the rangecheck fails.
* probably i need one rangecheck routine to return each c-type
* also, i haven't figured out what the `other stuff' is.
putprintf( "# call rangecheck" , 0 );
* if type p requires a range check,
* then put out the name of the checking function
* for the beginning of a function call which is completed by postcheck.
* (name1 is for a full check; name2 assumes a lower bound of zero)
precheck( p
, name1
, name2
)
if ( p
-> class == TYPE
) {
putleaf( P2ICON
, 0 , 0 , ADDTYPE( P2FTN
| P2INT
, P2PTR
)
, p
-> range
[0] != 0 ? name1
: name2
);
* how could a scalar ever be out of range?
* if type p requires a range check,
* then put out the rest of the arguments of to the checking function
* a call to which was started by precheck.
* the first argument is what is being rangechecked (put out by rvalue),
* the second argument is the lower bound of the range,
* the third argument is the upper bound of the range.
if ( p
-> class == TYPE
) {
if (p
-> range
[0] != 0 ) {
putleaf( P2ICON
, p
-> range
[0] , 0 , P2INT
, 0 );
putop( P2LISTOP
, P2INT
);
putleaf( P2ICON
, p
-> range
[1] , 0 , P2INT
, 0 );
putop( P2LISTOP
, P2INT
);
newfp
[0] = dub
[0] & 0100000;
exp
= ((dub
[0] >> 7) & 0377) - 0200;
newfp
[0] |= (mant
>> 17) & 077777;
newfp
[1] |= (((int) (mant
>> 1)) & 0177400) | (exp
<< 1);