BSD 4 release
[unix-history] / usr / src / cmd / f77 / exec.c
CommitLineData
853979d9
BJ
1#include "defs"
2
3/* Logical IF codes
4*/
5
6
7exif(p)
8expptr p;
9{
10pushctl(CTLIF);
11ctlstack->elselabel = newlabel();
12putif(p, ctlstack->elselabel);
13}
14
15
16
17exelif(p)
18expptr p;
19{
20if(ctlstack->ctltype == CTLIF)
21 {
22 if(ctlstack->endlabel == 0)
23 ctlstack->endlabel = newlabel();
24 putgoto(ctlstack->endlabel);
25 putlabel(ctlstack->elselabel);
26 ctlstack->elselabel = newlabel();
27 putif(p, ctlstack->elselabel);
28 }
29
30else execerr("elseif out of place", CNULL);
31}
32
33
34
35
36
37exelse()
38{
39if(ctlstack->ctltype==CTLIF)
40 {
41 if(ctlstack->endlabel == 0)
42 ctlstack->endlabel = newlabel();
43 putgoto( ctlstack->endlabel );
44 putlabel(ctlstack->elselabel);
45 ctlstack->ctltype = CTLELSE;
46 }
47
48else execerr("else out of place", CNULL);
49}
50
51
52exendif()
53{
54if(ctlstack->ctltype == CTLIF)
55 {
56 putlabel(ctlstack->elselabel);
57 if(ctlstack->endlabel)
58 putlabel(ctlstack->endlabel);
59 popctl();
60 }
61else if(ctlstack->ctltype == CTLELSE)
62 {
63 putlabel(ctlstack->endlabel);
64 popctl();
65 }
66
67else
68 execerr("endif out of place", CNULL);
69}
70
71
72
73LOCAL pushctl(code)
74int code;
75{
76register int i;
77
78if(++ctlstack >= lastctl)
79 many("loops or if-then-elses", 'c');
80ctlstack->ctltype = code;
81for(i = 0 ; i < 4 ; ++i)
82 ctlstack->ctlabels[i] = 0;
83++blklevel;
84}
85
86
87LOCAL popctl()
88{
89if( ctlstack-- < ctls )
90 fatal("control stack empty");
91--blklevel;
92}
93
94
95
96LOCAL poplab()
97{
98register struct Labelblock *lp;
99
100for(lp = labeltab ; lp < highlabtab ; ++lp)
101 if(lp->labdefined)
102 {
103 /* mark all labels in inner blocks unreachable */
104 if(lp->blklevel > blklevel)
105 lp->labinacc = YES;
106 }
107 else if(lp->blklevel > blklevel)
108 {
109 /* move all labels referred to in inner blocks out a level */
110 lp->blklevel = blklevel;
111 }
112}
113\f
114
115
116/* BRANCHING CODE
117*/
118
119exgoto(lab)
120struct Labelblock *lab;
121{
122putgoto(lab->labelno);
123}
124
125
126
127
128
129
130
131exequals(lp, rp)
132register struct Primblock *lp;
133register expptr rp;
134{
135if(lp->tag != TPRIM)
136 {
137 err("assignment to a non-variable");
138 frexpr(lp);
139 frexpr(rp);
140 }
141else if(lp->namep->vclass!=CLVAR && lp->argsp)
142 {
143 if(parstate >= INEXEC)
144 err("statement function amid executables");
145 else
146 mkstfunct(lp, rp);
147 }
148else
149 {
150 if(parstate < INDATA)
151 enddcl();
152 puteq(mklhs(lp), fixtype(rp));
153 }
154}
155
156
157
158mkstfunct(lp, rp)
159struct Primblock *lp;
160expptr rp;
161{
162register struct Primblock *p;
163register Namep np;
164chainp args;
165
166np = lp->namep;
167if(np->vclass == CLUNKNOWN)
168 np->vclass = CLPROC;
169else
170 {
171 dclerr("redeclaration of statement function", np);
172 return;
173 }
174np->vprocclass = PSTFUNCT;
175np->vstg = STGSTFUNCT;
176impldcl(np);
177args = (lp->argsp ? lp->argsp->listp : CHNULL);
178np->varxptr.vstfdesc = mkchain(args , rp );
179
180for( ; args ; args = args->nextp)
181 if( args->datap->tag!=TPRIM ||
182 (p = (struct Primblock *) (args->datap) )->argsp ||
183 p->fcharp || p->lcharp )
184 err("non-variable argument in statement function definition");
185 else
186 {
187 args->datap = (tagptr) (p->namep);
188 vardcl(p->namep);
189 free(p);
190 }
191}
192
193
194
195excall(name, args, nstars, labels)
196Namep name;
197struct Listblock *args;
198int nstars;
199struct Labelblock *labels[ ];
200{
201register expptr p;
202
203settype(name, TYSUBR, ENULL);
204p = mkfunct( mkprim(name, args, CHNULL) );
205p->exprblock.vtype = p->exprblock.leftp->headblock.vtype = TYINT;
206if(nstars > 0)
207 putcmgo(p, nstars, labels);
208else putexpr(p);
209}
210
211
212
213exstop(stop, p)
214int stop;
215register expptr p;
216{
217char *q;
218int n;
219expptr mkstrcon();
220
221if(p)
222 {
223 if( ! ISCONST(p) )
224 {
225 execerr("pause/stop argument must be constant", CNULL);
226 frexpr(p);
227 p = mkstrcon(0, CNULL);
228 }
229 else if( ISINT(p->constblock.vtype) )
230 {
231 q = convic(p->constblock.const.ci);
232 n = strlen(q);
233 if(n > 0)
234 {
235 p->constblock.const.ccp = copyn(n, q);
236 p->constblock.vtype = TYCHAR;
237 p->constblock.vleng = (expptr) ICON(n);
238 }
239 else
240 p = (expptr) mkstrcon(0, CNULL);
241 }
242 else if(p->constblock.vtype != TYCHAR)
243 {
244 execerr("pause/stop argument must be integer or string", CNULL);
245 p = (expptr) mkstrcon(0, CNULL);
246 }
247 }
248else p = (expptr) mkstrcon(0, CNULL);
249
250putexpr( call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p) );
251}
252\f
253/* DO LOOP CODE */
254
255#define DOINIT par[0]
256#define DOLIMIT par[1]
257#define DOINCR par[2]
258
259#define VARSTEP 0
260#define POSSTEP 1
261#define NEGSTEP 2
262
263
264exdo(range, spec)
265int range;
266chainp spec;
267{
268register expptr p, q;
269expptr q1;
270register Namep np;
271chainp cp;
272register int i;
273int dotype, incsign;
274Addrp dovarp, dostgp;
275expptr par[3];
276
277pushctl(CTLDO);
278dorange = ctlstack->dolabel = range;
279np = (Namep) (spec->datap);
280ctlstack->donamep = NULL;
281if(np->vdovar)
282 {
283 errstr("nested loops with variable %s", varstr(VL,np->varname));
284 ctlstack->donamep = NULL;
285 return;
286 }
287
288dovarp = mkplace(np);
289if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) )
290 {
291 err("bad type on do variable");
292 return;
293 }
294ctlstack->donamep = np;
295
296np->vdovar = YES;
297if( enregister(np) )
298 {
299 /* stgp points to a storage version, varp to a register version */
300 dostgp = dovarp;
301 dovarp = mkplace(np);
302 }
303else
304 dostgp = NULL;
305dotype = dovarp->vtype;
306
307for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp)
308 {
309 p = par[i++] = fixtype(cp->datap);
310 if( ! ONEOF(p->headblock.vtype, MSKINT|MSKREAL) )
311 {
312 err("bad type on DO parameter");
313 return;
314 }
315 }
316
317frchain(&spec);
318switch(i)
319 {
320 case 0:
321 case 1:
322 err("too few DO parameters");
323 return;
324
325 default:
326 err("too many DO parameters");
327 return;
328
329 case 2:
330 DOINCR = (expptr) ICON(1);
331
332 case 3:
333 break;
334 }
335
336ctlstack->endlabel = newlabel();
337ctlstack->dobodylabel = newlabel();
338
339if( ISCONST(DOLIMIT) )
340 ctlstack->domax = mkconv(dotype, DOLIMIT);
341else
342 ctlstack->domax = (expptr) mktemp(dotype, PNULL);
343
344if( ISCONST(DOINCR) )
345 {
346 ctlstack->dostep = mkconv(dotype, DOINCR);
347 if( (incsign = conssgn(ctlstack->dostep)) == 0)
348 err("zero DO increment");
349 ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP);
350 }
351else
352 {
353 ctlstack->dostep = (expptr) mktemp(dotype, PNULL);
354 ctlstack->dostepsign = VARSTEP;
355 ctlstack->doposlabel = newlabel();
356 ctlstack->doneglabel = newlabel();
357 }
358
359if( ISCONST(ctlstack->domax) && ISCONST(DOINIT) && ctlstack->dostepsign!=VARSTEP)
360 {
361 puteq(cpexpr(dovarp), cpexpr(DOINIT));
362 if( onetripflag )
363 frexpr(DOINIT);
364 else
365 {
366 q = mkexpr(OPPLUS, ICON(1),
367 mkexpr(OPMINUS, cpexpr(ctlstack->domax), cpexpr(DOINIT)) );
368 if(incsign != conssgn(q))
369 {
370 warn("DO range never executed");
371 putgoto(ctlstack->endlabel);
372 }
373 frexpr(q);
374 }
375 }
376else if(ctlstack->dostepsign!=VARSTEP && !onetripflag)
377 {
378 if( ISCONST(ctlstack->domax) )
379 q = (expptr) cpexpr(ctlstack->domax);
380 else
381 q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT);
382
383 q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT);
384 q = mkexpr( (ctlstack->dostepsign==POSSTEP ? OPLE : OPGE), q1, q);
385 putif(q, ctlstack->endlabel);
386 }
387else
388 {
389 if(! ISCONST(ctlstack->domax) )
390 puteq( cpexpr(ctlstack->domax), DOLIMIT);
391 q = DOINIT;
392 if( ! onetripflag )
393 q = mkexpr(OPMINUS, q,
394 mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), DOINCR) );
395 puteq( cpexpr(dovarp), q);
396 if(onetripflag && ctlstack->dostepsign==VARSTEP)
397 puteq( cpexpr(ctlstack->dostep), DOINCR);
398 }
399
400if(ctlstack->dostepsign == VARSTEP)
401 {
402 if(onetripflag)
403 putgoto(ctlstack->dobodylabel);
404 else
405 putif( mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)),
406 ctlstack->doneglabel );
407 putlabel(ctlstack->doposlabel);
408 putif( mkexpr(OPLE,
409 mkexpr(OPPLUSEQ, cpexpr(dovarp), cpexpr(ctlstack->dostep)),
410 cpexpr(ctlstack->domax) ),
411 ctlstack->endlabel);
412 }
413putlabel(ctlstack->dobodylabel);
414if(dostgp)
415 puteq(dostgp, cpexpr(dovarp));
416frexpr(dovarp);
417}
418
419
420
421enddo(here)
422int here;
423{
424register struct Ctlframe *q;
425register expptr t;
426Namep np;
427Addrp ap;
428register int i;
429
430while(here == dorange)
431 {
432 if(np = ctlstack->donamep)
433 {
434 t = mkexpr(OPPLUSEQ, mkplace(ctlstack->donamep),
435 cpexpr(ctlstack->dostep) );
436
437 if(ctlstack->dostepsign == VARSTEP)
438 {
439 putif( mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)), ctlstack->doposlabel);
440 putlabel(ctlstack->doneglabel);
441 putif( mkexpr(OPLT, t, ctlstack->domax), ctlstack->dobodylabel);
442 }
443 else
444 putif( mkexpr( (ctlstack->dostepsign==POSSTEP ? OPGT : OPLT),
445 t, ctlstack->domax),
446 ctlstack->dobodylabel);
447 putlabel(ctlstack->endlabel);
448 if(ap = memversion(np))
449 puteq(ap, mkplace(np));
450 for(i = 0 ; i < 4 ; ++i)
451 ctlstack->ctlabels[i] = 0;
452 deregister(ctlstack->donamep);
453 ctlstack->donamep->vdovar = NO;
454 frexpr(ctlstack->dostep);
455 }
456
457 popctl();
458 poplab();
459 dorange = 0;
460 for(q = ctlstack ; q>=ctls ; --q)
461 if(q->ctltype == CTLDO)
462 {
463 dorange = q->dolabel;
464 break;
465 }
466 }
467}
468\f
469exassign(vname, labelval)
470Namep vname;
471struct Labelblock *labelval;
472{
473Addrp p;
474expptr mkaddcon();
475
476p = mkplace(vname);
477if( ! ONEOF(p->vtype, MSKINT|MSKADDR) )
478 err("noninteger assign variable");
479else
480 puteq(p, mkaddcon(labelval->labelno) );
481}
482
483
484
485exarif(expr, neglab, zerlab, poslab)
486expptr expr;
487struct Labelblock *neglab, *zerlab, *poslab;
488{
489register int lm, lz, lp;
490
491lm = neglab->labelno;
492lz = zerlab->labelno;
493lp = poslab->labelno;
494expr = fixtype(expr);
495
496if( ! ONEOF(expr->headblock.vtype, MSKINT|MSKREAL) )
497 {
498 err("invalid type of arithmetic if expression");
499 frexpr(expr);
500 }
501else
502 {
503 if(lm == lz)
504 exar2(OPLE, expr, lm, lp);
505 else if(lm == lp)
506 exar2(OPNE, expr, lm, lz);
507 else if(lz == lp)
508 exar2(OPGE, expr, lz, lm);
509 else
510 prarif(expr, lm, lz, lp);
511 }
512}
513
514
515
516LOCAL exar2(op, e, l1, l2)
517int op;
518expptr e;
519int l1, l2;
520{
521putif( mkexpr(op, e, ICON(0)), l2);
522putgoto(l1);
523}
524
525
526exreturn(p)
527register expptr p;
528{
529if(procclass != CLPROC)
530 warn("RETURN statement in main or block data");
531if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
532 {
533 err("alternate return in nonsubroutine");
534 p = 0;
535 }
536
537if(p)
538 {
539 putforce(TYINT, p);
540 putgoto(retlabel);
541 }
542else
543 putgoto(proctype==TYSUBR ? ret0label : retlabel);
544}
545
546
547
548exasgoto(labvar)
549struct Hashentry *labvar;
550{
551register Addrp p;
552
553p = mkplace(labvar);
554if( ! ISINT(p->vtype) )
555 err("assigned goto variable must be integer");
556else
557 putbranch(p);
558}