1 /* $Id: exec.c,v 1.14 2008/05/11 15:28:03 ragge Exp $ */
3 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * Redistributions of source code and documentation must retain the above
10 * copyright notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed or owned by Caldera
18 * Neither the name of Caldera International, Inc. nor the names of other
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
22 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
23 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
27 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
42 LOCAL
void exar2(int, bigptr
, int, int);
43 LOCAL
void pushctl(int code
);
44 LOCAL
void popctl(void);
45 LOCAL
void poplab(void);
46 LOCAL
void mkstfunct(struct bigblock
*, bigptr
);
53 ctlstack
->elselabel
= newlabel();
54 putif(p
, ctlstack
->elselabel
);
62 if(ctlstack
->ctltype
== CTLIF
)
64 if(ctlstack
->endlabel
== 0)
65 ctlstack
->endlabel
= newlabel();
66 putgoto(ctlstack
->endlabel
);
67 putlabel(ctlstack
->elselabel
);
68 ctlstack
->elselabel
= newlabel();
69 putif(p
, ctlstack
->elselabel
);
72 else execerr("elseif out of place", 0);
81 if(ctlstack
->ctltype
==CTLIF
)
83 if(ctlstack
->endlabel
== 0)
84 ctlstack
->endlabel
= newlabel();
85 putgoto( ctlstack
->endlabel
);
86 putlabel(ctlstack
->elselabel
);
87 ctlstack
->ctltype
= CTLELSE
;
90 else execerr("else out of place", 0);
96 if(ctlstack
->ctltype
== CTLIF
)
98 putlabel(ctlstack
->elselabel
);
99 if(ctlstack
->endlabel
)
100 putlabel(ctlstack
->endlabel
);
103 else if(ctlstack
->ctltype
== CTLELSE
)
105 putlabel(ctlstack
->endlabel
);
109 else execerr("endif out of place", 0);
120 if(++ctlstack
>= lastctl
)
121 fatal("nesting too deep");
122 ctlstack
->ctltype
= code
;
123 for(i
= 0 ; i
< 4 ; ++i
)
124 ctlstack
->ctlabels
[i
] = 0;
132 if( ctlstack
-- < ctls
)
133 fatal("control stack empty");
143 register struct labelblock
*lp
;
145 for(lp
= labeltab
; lp
< highlabtab
; ++lp
)
148 /* mark all labels in inner blocks unreachable */
149 if(lp
->blklevel
> blklevel
)
152 else if(lp
->blklevel
> blklevel
)
154 /* move all labels referred to in inner blocks out a level */
155 lp
->blklevel
= blklevel
;
165 struct labelblock
*lab
;
167 putgoto(lab
->labelno
);
174 * Found an assignment expression.
177 exequals(struct bigblock
*lp
, bigptr rp
)
179 if(lp
->tag
!= TPRIM
) {
180 err("assignment to a non-variable");
183 } else if(lp
->b_prim
.namep
->vclass
!=CLVAR
&& lp
->b_prim
.argsp
) {
184 if(parstate
>= INEXEC
)
185 err("statement function amid executables");
189 if(parstate
< INDATA
)
191 puteq(mklhs(lp
), rp
);
196 * Create a statement function; e.g. like "f(i)=i*i"
199 mkstfunct(struct bigblock
*lp
, bigptr rp
)
205 np
= lp
->b_prim
.namep
;
206 if(np
->vclass
== CLUNKNOWN
)
209 dclerr("redeclaration of statement function", np
);
213 np
->b_name
.vprocclass
= PSTFUNCT
;
214 np
->vstg
= STGSTFUNCT
;
216 args
= (lp
->b_prim
.argsp
? lp
->b_prim
.argsp
->b_list
.listp
: NULL
);
217 np
->b_name
.vardesc
.vstfdesc
= mkchain((void *)args
, (void *)rp
);
219 for( ; args
; args
= args
->chain
.nextp
)
220 if( (p
= args
->chain
.datap
)->tag
!=TPRIM
||
221 p
->b_prim
.argsp
|| p
->b_prim
.fcharp
|| p
->b_prim
.lcharp
)
222 err("non-variable argument in statement function definition");
224 vardcl(args
->chain
.datap
= p
->b_prim
.namep
);
231 excall(name
, args
, nstars
, labels
)
232 struct bigblock
*name
;
233 struct bigblock
*args
;
235 struct labelblock
*labels
[ ];
239 settype(name
, TYSUBR
, 0);
240 p
= mkfunct( mkprim(name
, args
, NULL
, NULL
) );
241 p
->vtype
= p
->b_expr
.leftp
->vtype
= TYINT
;
243 putcmgo(p
, nstars
, labels
);
260 execerr("pause/stop argument must be constant", 0);
264 else if( ISINT(p
->vtype
) )
266 q
= convic(p
->b_const
.fconst
.ci
);
270 p
->b_const
.fconst
.ccp
= copyn(n
, q
);
272 p
->vleng
= MKICON(n
);
277 else if(p
->vtype
!= TYCHAR
)
279 execerr("pause/stop argument must be integer or string", 0);
283 else p
= mkstrcon(0, 0);
285 putexpr( call1(TYSUBR
, (stop
? "s_stop" : "s_paus"), p
) );
290 #define DOINIT par[0]
291 #define DOLIMIT par[1]
292 #define DOINCR par[2]
303 register bigptr p
, q
;
305 register struct bigblock
*np
;
308 int dotype
, incsign
= 0; /* XXX gcc */
309 struct bigblock
*dovarp
, *dostgp
;
313 dorange
= ctlstack
->dolabel
= range
;
314 np
= spec
->chain
.datap
;
315 ctlstack
->donamep
= NULL
;
316 if(np
->b_name
.vdovar
)
318 err1("nested loops with variable %s", varstr(VL
,np
->b_name
.varname
));
319 ctlstack
->donamep
= NULL
;
323 dovarp
= mklhs( mkprim(np
, 0,0,0) );
324 if( ! ONEOF(dovarp
->vtype
, MSKINT
|MSKREAL
) )
326 err("bad type on do variable");
329 ctlstack
->donamep
= np
;
331 np
->b_name
.vdovar
= YES
;
334 /* stgp points to a storage version, varp to a register version */
336 dovarp
= mklhs( mkprim(np
, 0,0,0) );
340 dotype
= dovarp
->vtype
;
342 for(i
=0 , cp
= spec
->chain
.nextp
; cp
!=NULL
&& i
<3 ; cp
= cp
->chain
.nextp
)
344 p
= par
[i
++] = fixtype(cp
->chain
.datap
);
345 if( ! ONEOF(p
->vtype
, MSKINT
|MSKREAL
) )
347 err("bad type on DO parameter");
357 err("too few DO parameters");
361 err("too many DO parameters");
371 ctlstack
->endlabel
= newlabel();
372 ctlstack
->dobodylabel
= newlabel();
374 if( ISCONST(DOLIMIT
) )
375 ctlstack
->domax
= mkconv(dotype
, DOLIMIT
);
377 ctlstack
->domax
= fmktemp(dotype
, NULL
);
379 if( ISCONST(DOINCR
) )
381 ctlstack
->dostep
= mkconv(dotype
, DOINCR
);
382 if( (incsign
= conssgn(ctlstack
->dostep
)) == 0)
383 err("zero DO increment");
384 ctlstack
->dostepsign
= (incsign
> 0 ? POSSTEP
: NEGSTEP
);
388 ctlstack
->dostep
= fmktemp(dotype
, NULL
);
389 ctlstack
->dostepsign
= VARSTEP
;
390 ctlstack
->doposlabel
= newlabel();
391 ctlstack
->doneglabel
= newlabel();
394 if( ISCONST(ctlstack
->domax
) && ISCONST(DOINIT
) && ctlstack
->dostepsign
!=VARSTEP
)
396 puteq(cpexpr(dovarp
), cpexpr(DOINIT
));
401 q
= mkexpr(OPPLUS
, MKICON(1),
402 mkexpr(OPMINUS
, cpexpr(ctlstack
->domax
), cpexpr(DOINIT
)) );
403 if(incsign
!= conssgn(q
))
405 warn("DO range never executed");
406 putgoto(ctlstack
->endlabel
);
411 else if(ctlstack
->dostepsign
!=VARSTEP
&& !onetripflag
)
413 if( ISCONST(ctlstack
->domax
) )
414 q
= cpexpr(ctlstack
->domax
);
416 q
= mkexpr(OPASSIGN
, cpexpr(ctlstack
->domax
), DOLIMIT
);
418 q1
= mkexpr(OPASSIGN
, cpexpr(dovarp
), DOINIT
);
419 q
= mkexpr( (ctlstack
->dostepsign
==POSSTEP
? OPLE
: OPGE
), q1
, q
);
420 putif(q
, ctlstack
->endlabel
);
424 if(! ISCONST(ctlstack
->domax
) )
425 puteq( cpexpr(ctlstack
->domax
), DOLIMIT
);
428 q
= mkexpr(OPMINUS
, q
,
429 mkexpr(OPASSIGN
, cpexpr(ctlstack
->dostep
), DOINCR
) );
430 puteq( cpexpr(dovarp
), q
);
431 if(onetripflag
&& ctlstack
->dostepsign
==VARSTEP
)
432 puteq( cpexpr(ctlstack
->dostep
), DOINCR
);
435 if(ctlstack
->dostepsign
== VARSTEP
)
438 putgoto(ctlstack
->dobodylabel
);
440 putif( mkexpr(OPGE
, cpexpr(ctlstack
->dostep
), MKICON(0)),
441 ctlstack
->doneglabel
);
442 putlabel(ctlstack
->doposlabel
);
445 putif( mkexpr(OPLE
, mkexpr(OPASSIGN
, p
,
446 mkexpr(OPPLUS
, cpexpr(dovarp
), cpexpr(ctlstack
->dostep
))),
447 cpexpr(ctlstack
->domax
)), ctlstack
->endlabel
);
449 putlabel(ctlstack
->dobodylabel
);
451 puteq(dostgp
, cpexpr(dovarp
));
456 * Reached the end of a DO statement.
461 register struct ctlframe
*q
;
467 while(here
== dorange
) {
468 if((np
= ctlstack
->donamep
)) {
470 t
= mklhs(mkprim(ctlstack
->donamep
, 0,0 ,0));
471 t
= mkexpr(OPASSIGN
, cpexpr(t
),
472 mkexpr(OPPLUS
, t
, cpexpr(ctlstack
->dostep
)));
474 if(ctlstack
->dostepsign
== VARSTEP
) {
475 putif( mkexpr(OPLE
, cpexpr(ctlstack
->dostep
),
476 MKICON(0)), ctlstack
->doposlabel
);
477 putlabel(ctlstack
->doneglabel
);
478 putif( mkexpr(OPLT
, t
, ctlstack
->domax
),
479 ctlstack
->dobodylabel
);
481 putif( mkexpr( (ctlstack
->dostepsign
==POSSTEP
?
482 OPGT
: OPLT
), t
, ctlstack
->domax
),
483 ctlstack
->dobodylabel
);
484 putlabel(ctlstack
->endlabel
);
485 if((ap
= memversion(np
)))
486 puteq(ap
, mklhs( mkprim(np
,0,0,0)) );
487 for(i
= 0 ; i
< 4 ; ++i
)
488 ctlstack
->ctlabels
[i
] = 0;
489 deregister(ctlstack
->donamep
);
490 ctlstack
->donamep
->b_name
.vdovar
= NO
;
491 frexpr(ctlstack
->dostep
);
496 for(q
= ctlstack
; q
>=ctls
; --q
)
497 if(q
->ctltype
== CTLDO
) {
498 dorange
= q
->dolabel
;
505 exassign(vname
, labelval
)
506 struct bigblock
*vname
;
507 struct labelblock
*labelval
;
511 p
= mklhs(mkprim(vname
,0,0,0));
512 if( ! ONEOF(p
->vtype
, MSKINT
|MSKADDR
) )
513 err("noninteger assign variable");
515 puteq(p
, mkaddcon(labelval
->labelno
) );
520 exarif(expr
, neglab
, zerlab
, poslab
)
522 struct labelblock
*neglab
, *zerlab
, *poslab
;
524 register int lm
, lz
, lp
;
526 lm
= neglab
->labelno
;
527 lz
= zerlab
->labelno
;
528 lp
= poslab
->labelno
;
529 expr
= fixtype(expr
);
531 if( ! ONEOF(expr
->vtype
, MSKINT
|MSKREAL
) )
533 err("invalid type of arithmetic if expression");
539 exar2(OPLE
, expr
, lm
, lp
);
541 exar2(OPNE
, expr
, lm
, lz
);
543 exar2(OPGE
, expr
, lz
, lm
);
545 prarif(expr
, lm
, lz
, lp
);
551 LOCAL
void exar2(op
, e
, l1
, l2
)
556 putif( mkexpr(op
, e
, MKICON(0)), l2
);
564 if(p
&& (proctype
!=TYSUBR
|| procclass
!=CLPROC
) )
566 err("alternate return in nonsubroutine");
576 putgoto(procclass
==TYSUBR
? ret0label
: retlabel
);
584 register struct bigblock
*p
;
586 p
= mklhs( mkprim(labvar
,0,0,0) );
587 if( ! ISINT(p
->vtype
) )
588 err("assigned goto variable must be integer");