xref: /netbsd/external/bsd/pcc/dist/pcc/f77/fcom/exec.c (revision 3eb51a41)
1 /*	Id: exec.c,v 1.14 2008/05/11 15:28:03 ragge Exp 	*/
2 /*	$NetBSD: exec.c,v 1.1.1.2 2010/06/03 18:57:46 plunky Exp $	*/
3 /*
4  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * Redistributions of source code and documentation must retain the above
11  * copyright notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * All advertising materials mentioning features or use of this software
16  * must display the following acknowledgement:
17  * 	This product includes software developed or owned by Caldera
18  *	International, Inc.
19  * Neither the name of Caldera International, Inc. nor the names of other
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 #include <string.h>
37 
38 #include "defines.h"
39 #include "defs.h"
40 
41 /*   Logical IF codes
42 */
43 LOCAL void exar2(int, bigptr, int, int);
44 LOCAL void pushctl(int code);
45 LOCAL void popctl(void);
46 LOCAL void poplab(void);
47 LOCAL void mkstfunct(struct bigblock *, bigptr);
48 
49 void
exif(p)50 exif(p)
51 bigptr p;
52 {
53 pushctl(CTLIF);
54 ctlstack->elselabel = newlabel();
55 putif(p, ctlstack->elselabel);
56 }
57 
58 
59 void
exelif(p)60 exelif(p)
61 bigptr p;
62 {
63 if(ctlstack->ctltype == CTLIF)
64 	{
65 	if(ctlstack->endlabel == 0)
66 		ctlstack->endlabel = newlabel();
67 	putgoto(ctlstack->endlabel);
68 	putlabel(ctlstack->elselabel);
69 	ctlstack->elselabel = newlabel();
70 	putif(p, ctlstack->elselabel);
71 	}
72 
73 else	execerr("elseif out of place", 0);
74 }
75 
76 
77 
78 
79 void
exelse()80 exelse()
81 {
82 if(ctlstack->ctltype==CTLIF)
83 	{
84 	if(ctlstack->endlabel == 0)
85 		ctlstack->endlabel = newlabel();
86 	putgoto( ctlstack->endlabel );
87 	putlabel(ctlstack->elselabel);
88 	ctlstack->ctltype = CTLELSE;
89 	}
90 
91 else	execerr("else out of place", 0);
92 }
93 
94 void
exendif()95 exendif()
96 {
97 if(ctlstack->ctltype == CTLIF)
98 	{
99 	putlabel(ctlstack->elselabel);
100 	if(ctlstack->endlabel)
101 		putlabel(ctlstack->endlabel);
102 	popctl();
103 	}
104 else if(ctlstack->ctltype == CTLELSE)
105 	{
106 	putlabel(ctlstack->endlabel);
107 	popctl();
108 	}
109 
110 else	execerr("endif out of place", 0);
111 }
112 
113 
114 
115 LOCAL void
pushctl(code)116 pushctl(code)
117 int code;
118 {
119 register int i;
120 
121 if(++ctlstack >= lastctl)
122 	fatal("nesting too deep");
123 ctlstack->ctltype = code;
124 for(i = 0 ; i < 4 ; ++i)
125 	ctlstack->ctlabels[i] = 0;
126 ++blklevel;
127 }
128 
129 
130 LOCAL void
popctl()131 popctl()
132 {
133 if( ctlstack-- < ctls )
134 	fatal("control stack empty");
135 --blklevel;
136 poplab();
137 }
138 
139 
140 
141 LOCAL void
poplab()142 poplab()
143 {
144 register struct labelblock  *lp;
145 
146 for(lp = labeltab ; lp < highlabtab ; ++lp)
147 	if(lp->labdefined)
148 		{
149 		/* mark all labels in inner blocks unreachable */
150 		if(lp->blklevel > blklevel)
151 			lp->labinacc = YES;
152 		}
153 	else if(lp->blklevel > blklevel)
154 		{
155 		/* move all labels referred to in inner blocks out a level */
156 		lp->blklevel = blklevel;
157 		}
158 }
159 
160 
161 
162 /*  BRANCHING CODE
163 */
164 void
exgoto(lab)165 exgoto(lab)
166 struct labelblock *lab;
167 {
168 putgoto(lab->labelno);
169 }
170 
171 
172 
173 
174 /*
175  * Found an assignment expression.
176  */
177 void
exequals(struct bigblock * lp,bigptr rp)178 exequals(struct bigblock *lp, bigptr rp)
179 {
180 	if(lp->tag != TPRIM) {
181 		err("assignment to a non-variable");
182 		frexpr(lp);
183 		frexpr(rp);
184 	} else if(lp->b_prim.namep->vclass!=CLVAR && lp->b_prim.argsp) {
185 		if(parstate >= INEXEC)
186 			err("statement function amid executables");
187 		else
188 			mkstfunct(lp, rp);
189 	} else {
190 		if(parstate < INDATA)
191 			enddcl();
192 		puteq(mklhs(lp), rp);
193 	}
194 }
195 
196 /*
197  * Create a statement function; e.g. like "f(i)=i*i"
198  */
199 void
mkstfunct(struct bigblock * lp,bigptr rp)200 mkstfunct(struct bigblock *lp, bigptr rp)
201 {
202 	struct bigblock *p;
203 	struct bigblock *np;
204 	chainp args;
205 
206 	np = lp->b_prim.namep;
207 	if(np->vclass == CLUNKNOWN)
208 		np->vclass = CLPROC;
209 	else {
210 		dclerr("redeclaration of statement function", np);
211 		return;
212 	}
213 
214 	np->b_name.vprocclass = PSTFUNCT;
215 	np->vstg = STGSTFUNCT;
216 	impldcl(np);
217 	args = (lp->b_prim.argsp ? lp->b_prim.argsp->b_list.listp : NULL);
218 	np->b_name.vardesc.vstfdesc = mkchain((void *)args, (void *)rp);
219 
220 	for( ; args ; args = args->chain.nextp)
221 		if( (p = args->chain.datap)->tag!=TPRIM ||
222 		    p->b_prim.argsp || p->b_prim.fcharp || p->b_prim.lcharp)
223 			err("non-variable argument in statement function definition");
224 		else {
225 			vardcl(args->chain.datap = p->b_prim.namep);
226 			ckfree(p);
227 		}
228 }
229 
230 
231 void
excall(name,args,nstars,labels)232 excall(name, args, nstars, labels)
233 struct bigblock *name;
234 struct bigblock *args;
235 int nstars;
236 struct labelblock *labels[ ];
237 {
238 register bigptr p;
239 
240 settype(name, TYSUBR, 0);
241 p = mkfunct( mkprim(name, args, NULL, NULL) );
242 p->vtype = p->b_expr.leftp->vtype = TYINT;
243 if(nstars > 0)
244 	putcmgo(p, nstars, labels);
245 else putexpr(p);
246 }
247 
248 
249 void
exstop(stop,p)250 exstop(stop, p)
251 int stop;
252 register bigptr p;
253 {
254 char *q;
255 int n;
256 
257 if(p)
258 	{
259 	if( ! ISCONST(p) )
260 		{
261 		execerr("pause/stop argument must be constant", 0);
262 		frexpr(p);
263 		p = mkstrcon(0, 0);
264 		}
265 	else if( ISINT(p->vtype) )
266 		{
267 		q = convic(p->b_const.fconst.ci);
268 		n = strlen(q);
269 		if(n > 0)
270 			{
271 			p->b_const.fconst.ccp = copyn(n, q);
272 			p->vtype = TYCHAR;
273 			p->vleng = MKICON(n);
274 			}
275 		else
276 			p = mkstrcon(0, 0);
277 		}
278 	else if(p->vtype != TYCHAR)
279 		{
280 		execerr("pause/stop argument must be integer or string", 0);
281 		p = mkstrcon(0, 0);
282 		}
283 	}
284 else	p = mkstrcon(0, 0);
285 
286 putexpr( call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p) );
287 }
288 
289 /* DO LOOP CODE */
290 
291 #define DOINIT	par[0]
292 #define DOLIMIT	par[1]
293 #define DOINCR	par[2]
294 
295 #define VARSTEP	0
296 #define POSSTEP	1
297 #define NEGSTEP	2
298 
299 void
exdo(range,spec)300 exdo(range, spec)
301 int range;
302 chainp spec;
303 {
304 register bigptr p, q;
305 bigptr q1;
306 register struct bigblock *np;
307 chainp cp;
308 register int i;
309 int dotype, incsign = 0; /* XXX gcc */
310 struct bigblock *dovarp, *dostgp;
311 bigptr par[3];
312 
313 pushctl(CTLDO);
314 dorange = ctlstack->dolabel = range;
315 np = spec->chain.datap;
316 ctlstack->donamep = NULL;
317 if(np->b_name.vdovar)
318 	{
319 	err1("nested loops with variable %s", varstr(VL,np->b_name.varname));
320 	ctlstack->donamep = NULL;
321 	return;
322 	}
323 
324 dovarp = mklhs( mkprim(np, 0,0,0) );
325 if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) )
326 	{
327 	err("bad type on do variable");
328 	return;
329 	}
330 ctlstack->donamep = np;
331 
332 np->b_name.vdovar = YES;
333 if( enregister(np) )
334 	{
335 	/* stgp points to a storage version, varp to a register version */
336 	dostgp = dovarp;
337 	dovarp = mklhs( mkprim(np, 0,0,0) );
338 	}
339 else
340 	dostgp = NULL;
341 dotype = dovarp->vtype;
342 
343 for(i=0 , cp = spec->chain.nextp ; cp!=NULL && i<3 ; cp = cp->chain.nextp)
344 	{
345 	p = par[i++] = fixtype(cp->chain.datap);
346 	if( ! ONEOF(p->vtype, MSKINT|MSKREAL) )
347 		{
348 		err("bad type on DO parameter");
349 		return;
350 		}
351 	}
352 
353 frchain(&spec);
354 switch(i)
355 	{
356 	case 0:
357 	case 1:
358 		err("too few DO parameters");
359 		return;
360 
361 	default:
362 		err("too many DO parameters");
363 		return;
364 
365 	case 2:
366 		DOINCR = MKICON(1);
367 
368 	case 3:
369 		break;
370 	}
371 
372 ctlstack->endlabel = newlabel();
373 ctlstack->dobodylabel = newlabel();
374 
375 if( ISCONST(DOLIMIT) )
376 	ctlstack->domax = mkconv(dotype, DOLIMIT);
377 else
378 	ctlstack->domax = fmktemp(dotype, NULL);
379 
380 if( ISCONST(DOINCR) )
381 	{
382 	ctlstack->dostep = mkconv(dotype, DOINCR);
383 	if( (incsign = conssgn(ctlstack->dostep)) == 0)
384 		err("zero DO increment");
385 	ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP);
386 	}
387 else
388 	{
389 	ctlstack->dostep = fmktemp(dotype, NULL);
390 	ctlstack->dostepsign = VARSTEP;
391 	ctlstack->doposlabel = newlabel();
392 	ctlstack->doneglabel = newlabel();
393 	}
394 
395 if( ISCONST(ctlstack->domax) && ISCONST(DOINIT) && ctlstack->dostepsign!=VARSTEP)
396 	{
397 	puteq(cpexpr(dovarp), cpexpr(DOINIT));
398 	if( onetripflag )
399 		frexpr(DOINIT);
400 	else
401 		{
402 		q = mkexpr(OPPLUS, MKICON(1),
403 			mkexpr(OPMINUS, cpexpr(ctlstack->domax), cpexpr(DOINIT)) );
404 		if(incsign != conssgn(q))
405 			{
406 			warn("DO range never executed");
407 			putgoto(ctlstack->endlabel);
408 			}
409 		frexpr(q);
410 		}
411 	}
412 else if(ctlstack->dostepsign!=VARSTEP && !onetripflag)
413 	{
414 	if( ISCONST(ctlstack->domax) )
415 		q = cpexpr(ctlstack->domax);
416 	else
417 		q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT);
418 
419 	q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT);
420 	q = mkexpr( (ctlstack->dostepsign==POSSTEP ? OPLE : OPGE), q1, q);
421 	putif(q, ctlstack->endlabel);
422 	}
423 else
424 	{
425 	if(! ISCONST(ctlstack->domax) )
426 		puteq( cpexpr(ctlstack->domax), DOLIMIT);
427 	q = DOINIT;
428 	if( ! onetripflag )
429 		q = mkexpr(OPMINUS, q,
430 			mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), DOINCR) );
431 	puteq( cpexpr(dovarp), q);
432 	if(onetripflag && ctlstack->dostepsign==VARSTEP)
433 		puteq( cpexpr(ctlstack->dostep), DOINCR);
434 	}
435 
436 if(ctlstack->dostepsign == VARSTEP)
437 	{
438 	if(onetripflag)
439 		putgoto(ctlstack->dobodylabel);
440 	else
441 		putif( mkexpr(OPGE, cpexpr(ctlstack->dostep), MKICON(0)),
442 			ctlstack->doneglabel );
443 	putlabel(ctlstack->doposlabel);
444 
445 	p = cpexpr(dovarp);
446 	putif( mkexpr(OPLE, mkexpr(OPASSIGN, p,
447 	    mkexpr(OPPLUS, cpexpr(dovarp), cpexpr(ctlstack->dostep))),
448 	    cpexpr(ctlstack->domax)), ctlstack->endlabel);
449 	}
450 putlabel(ctlstack->dobodylabel);
451 if(dostgp)
452 	puteq(dostgp, cpexpr(dovarp));
453 frexpr(dovarp);
454 }
455 
456 /*
457  * Reached the end of a DO statement.
458  */
459 void
enddo(int here)460 enddo(int here)
461 {
462 	register struct ctlframe *q;
463 	register bigptr t;
464 	struct bigblock *np;
465 	struct bigblock *ap;
466 	register int i;
467 
468 	while(here == dorange) {
469 		if((np = ctlstack->donamep)) {
470 
471 			t = mklhs(mkprim(ctlstack->donamep, 0,0 ,0));
472 			t = mkexpr(OPASSIGN, cpexpr(t),
473 			    mkexpr(OPPLUS, t, cpexpr(ctlstack->dostep)));
474 
475 			if(ctlstack->dostepsign == VARSTEP) {
476 				putif( mkexpr(OPLE, cpexpr(ctlstack->dostep),
477 				    MKICON(0)), ctlstack->doposlabel);
478 				putlabel(ctlstack->doneglabel);
479 				putif( mkexpr(OPLT, t, ctlstack->domax),
480 				    ctlstack->dobodylabel);
481 			} else
482 				putif( mkexpr( (ctlstack->dostepsign==POSSTEP ?
483 					OPGT : OPLT), t, ctlstack->domax),
484 					ctlstack->dobodylabel);
485 			putlabel(ctlstack->endlabel);
486 			if((ap = memversion(np)))
487 				puteq(ap, mklhs( mkprim(np,0,0,0)) );
488 			for(i = 0 ; i < 4 ; ++i)
489 				ctlstack->ctlabels[i] = 0;
490 			deregister(ctlstack->donamep);
491 			ctlstack->donamep->b_name.vdovar = NO;
492 			frexpr(ctlstack->dostep);
493 		}
494 
495 		popctl();
496 		dorange = 0;
497 		for(q = ctlstack ; q>=ctls ; --q)
498 			if(q->ctltype == CTLDO) {
499 				dorange = q->dolabel;
500 				break;
501 			}
502 	}
503 }
504 
505 void
exassign(vname,labelval)506 exassign(vname, labelval)
507 struct bigblock *vname;
508 struct labelblock *labelval;
509 {
510 struct bigblock *p;
511 
512 p = mklhs(mkprim(vname,0,0,0));
513 if( ! ONEOF(p->vtype, MSKINT|MSKADDR) )
514 	err("noninteger assign variable");
515 else
516 	puteq(p, mkaddcon(labelval->labelno) );
517 }
518 
519 
520 void
exarif(expr,neglab,zerlab,poslab)521 exarif(expr, neglab, zerlab, poslab)
522 bigptr expr;
523 struct labelblock *neglab, *zerlab, *poslab;
524 {
525 register int lm, lz, lp;
526 
527 lm = neglab->labelno;
528 lz = zerlab->labelno;
529 lp = poslab->labelno;
530 expr = fixtype(expr);
531 
532 if( ! ONEOF(expr->vtype, MSKINT|MSKREAL) )
533 	{
534 	err("invalid type of arithmetic if expression");
535 	frexpr(expr);
536 	}
537 else
538 	{
539 	if(lm == lz)
540 		exar2(OPLE, expr, lm, lp);
541 	else if(lm == lp)
542 		exar2(OPNE, expr, lm, lz);
543 	else if(lz == lp)
544 		exar2(OPGE, expr, lz, lm);
545 	else
546 		prarif(expr, lm, lz, lp);
547 	}
548 }
549 
550 
551 
exar2(op,e,l1,l2)552 LOCAL void exar2(op, e, l1, l2)
553 int op;
554 bigptr e;
555 int l1, l2;
556 {
557 putif( mkexpr(op, e, MKICON(0)), l2);
558 putgoto(l1);
559 }
560 
561 void
exreturn(p)562 exreturn(p)
563 register bigptr p;
564 {
565 if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
566 	{
567 	err("alternate return in nonsubroutine");
568 	p = 0;
569 	}
570 
571 if(p)
572 	{
573 	putforce(TYINT, p);
574 	putgoto(retlabel);
575 	}
576 else
577 	putgoto(procclass==TYSUBR ? ret0label : retlabel);
578 }
579 
580 
581 void
exasgoto(labvar)582 exasgoto(labvar)
583 bigptr labvar;
584 {
585 register struct bigblock *p;
586 
587 p = mklhs( mkprim(labvar,0,0,0) );
588 if( ! ISINT(p->vtype) )
589 	err("assigned goto variable must be integer");
590 else
591 	putbranch(p);
592 }
593