Bell 32V development
[unix-history] / usr / src / cmd / f77 / exec.c
CommitLineData
f2a856a6
TL
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", 0);
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", 0);
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 execerr("endif out of place", 0);
68}
69
70
71
72LOCAL pushctl(code)
73int code;
74{
75register int i;
76
77if(++ctlstack >= lastctl)
78 fatal("nesting too deep");
79ctlstack->ctltype = code;
80for(i = 0 ; i < 4 ; ++i)
81 ctlstack->ctlabels[i] = 0;
82++blklevel;
83}
84
85
86LOCAL popctl()
87{
88if( ctlstack-- < ctls )
89 fatal("control stack empty");
90--blklevel;
91poplab();
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), rp);
153 }
154}
155
156
157
158mkstfunct(lp, rp)
159struct primblock *lp;
160expptr rp;
161{
162register struct primblock *p;
163register struct nameblock *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 : NULL);
178np->vardesc.vstfdesc = mkchain(args , rp );
179
180for( ; args ; args = args->nextp)
181 if( (p = args->datap)->tag!=TPRIM ||
182 p->argsp || p->fcharp || p->lcharp)
183 err("non-variable argument in statement function definition");
184 else
185 {
186 vardcl(args->datap = p->namep);
187 free(p);
188 }
189}
190
191
192
193excall(name, args, nstars, labels)
194struct hashentry *name;
195struct listblock *args;
196int nstars;
197struct labelblock *labels[ ];
198{
199register expptr p;
200
201settype(name, TYSUBR, NULL);
202p = mkfunct( mkprim(name, args, NULL, NULL) );
203p->vtype = p->leftp->vtype = TYINT;
204if(nstars > 0)
205 putcmgo(p, nstars, labels);
206else putexpr(p);
207}
208
209
210
211exstop(stop, p)
212int stop;
213register expptr p;
214{
215char *q;
216int n;
217struct constblock *mkstrcon();
218
219if(p)
220 {
221 if( ! ISCONST(p) )
222 {
223 execerr("pause/stop argument must be constant", 0);
224 frexpr(p);
225 p = mkstrcon(0, 0);
226 }
227 else if( ISINT(p->vtype) )
228 {
229 q = convic(p->const.ci);
230 n = strlen(q);
231 if(n > 0)
232 {
233 p->const.ccp = copyn(n, q);
234 p->vtype = TYCHAR;
235 p->vleng = ICON(n);
236 }
237 else
238 p = mkstrcon(0, 0);
239 }
240 else if(p->vtype != TYCHAR)
241 {
242 execerr("pause/stop argument must be integer or string", 0);
243 p = mkstrcon(0, 0);
244 }
245 }
246else p = mkstrcon(0, 0);
247
248putexpr( call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p) );
249}
250\f
251/* DO LOOP CODE */
252
253#define DOINIT par[0]
254#define DOLIMIT par[1]
255#define DOINCR par[2]
256
257#define VARSTEP 0
258#define POSSTEP 1
259#define NEGSTEP 2
260
261
262exdo(range, spec)
263int range;
264chainp spec;
265{
266register expptr p, q;
267expptr *q1;
268register struct nameblock *np;
269chainp cp;
270register int i;
271int dotype, incsign;
272struct addrblock *dovarp, *dostgp;
273expptr par[3];
274
275pushctl(CTLDO);
276dorange = ctlstack->dolabel = range;
277np = spec->datap;
278ctlstack->donamep = NULL;
279if(np->vdovar)
280 {
281 err1("nested loops with variable %s", varstr(VL,np->varname));
282 ctlstack->donamep = NULL;
283 return;
284 }
285
286dovarp = mklhs( mkprim(np, 0,0,0) );
287if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) )
288 {
289 err("bad type on do variable");
290 return;
291 }
292ctlstack->donamep = np;
293
294np->vdovar = YES;
295if( enregister(np) )
296 {
297 /* stgp points to a storage version, varp to a register version */
298 dostgp = dovarp;
299 dovarp = mklhs( mkprim(np, 0,0,0) );
300 }
301else
302 dostgp = NULL;
303dotype = dovarp->vtype;
304
305for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp)
306 {
307 p = par[i++] = fixtype(cp->datap);
308 if( ! ONEOF(p->vtype, MSKINT|MSKREAL) )
309 {
310 err("bad type on DO parameter");
311 return;
312 }
313 }
314
315frchain(&spec);
316switch(i)
317 {
318 case 0:
319 case 1:
320 err("too few DO parameters");
321 return;
322
323 default:
324 err("too many DO parameters");
325 return;
326
327 case 2:
328 DOINCR = ICON(1);
329
330 case 3:
331 break;
332 }
333
334ctlstack->endlabel = newlabel();
335ctlstack->dobodylabel = newlabel();
336
337if( ISCONST(DOLIMIT) )
338 ctlstack->domax = mkconv(dotype, DOLIMIT);
339else
340 ctlstack->domax = mktemp(dotype, NULL);
341
342if( ISCONST(DOINCR) )
343 {
344 ctlstack->dostep = mkconv(dotype, DOINCR);
345 if( (incsign = conssgn(ctlstack->dostep)) == 0)
346 err("zero DO increment");
347 ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP);
348 }
349else
350 {
351 ctlstack->dostep = mktemp(dotype, NULL);
352 ctlstack->dostepsign = VARSTEP;
353 ctlstack->doposlabel = newlabel();
354 ctlstack->doneglabel = newlabel();
355 }
356
357if( ISCONST(ctlstack->domax) && ISCONST(DOINIT) && ctlstack->dostepsign!=VARSTEP)
358 {
359 puteq(cpexpr(dovarp), cpexpr(DOINIT));
360 if( onetripflag )
361 frexpr(DOINIT);
362 else
363 {
364 q = mkexpr(OPPLUS, ICON(1),
365 mkexpr(OPMINUS, cpexpr(ctlstack->domax), cpexpr(DOINIT)) );
366 if(incsign != conssgn(q))
367 {
368 warn("DO range never executed");
369 putgoto(ctlstack->endlabel);
370 }
371 frexpr(q);
372 }
373 }
374else if(ctlstack->dostepsign!=VARSTEP && !onetripflag)
375 {
376 if( ISCONST(ctlstack->domax) )
377 q = cpexpr(ctlstack->domax);
378 else
379 q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT);
380
381 q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT);
382 q = mkexpr( (ctlstack->dostepsign==POSSTEP ? OPLE : OPGE), q1, q);
383 putif(q, ctlstack->endlabel);
384 }
385else
386 {
387 if(! ISCONST(ctlstack->domax) )
388 puteq( cpexpr(ctlstack->domax), DOLIMIT);
389 q = DOINIT;
390 if( ! onetripflag )
391 q = mkexpr(OPMINUS, q,
392 mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), DOINCR) );
393 puteq( cpexpr(dovarp), q);
394 if(onetripflag && ctlstack->dostepsign==VARSTEP)
395 puteq( cpexpr(ctlstack->dostep), DOINCR);
396 }
397
398if(ctlstack->dostepsign == VARSTEP)
399 {
400 if(onetripflag)
401 putgoto(ctlstack->dobodylabel);
402 else
403 putif( mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)),
404 ctlstack->doneglabel );
405 putlabel(ctlstack->doposlabel);
406 putif( mkexpr(OPLE,
407 mkexpr(OPPLUSEQ, cpexpr(dovarp), cpexpr(ctlstack->dostep)),
408 cpexpr(ctlstack->domax) ),
409 ctlstack->endlabel);
410 }
411putlabel(ctlstack->dobodylabel);
412if(dostgp)
413 puteq(dostgp, cpexpr(dovarp));
414frexpr(dovarp);
415}
416
417
418
419enddo(here)
420int here;
421{
422register struct ctlframe *q;
423register expptr t;
424struct nameblock *np;
425struct addrblock *ap;
426register int i;
427
428while(here == dorange)
429 {
430 if(np = ctlstack->donamep)
431 {
432 t = mkexpr(OPPLUSEQ, mklhs(mkprim(ctlstack->donamep, 0,0,0)),
433 cpexpr(ctlstack->dostep) );
434
435 if(ctlstack->dostepsign == VARSTEP)
436 {
437 putif( mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)), ctlstack->doposlabel);
438 putlabel(ctlstack->doneglabel);
439 putif( mkexpr(OPLT, t, ctlstack->domax), ctlstack->dobodylabel);
440 }
441 else
442 putif( mkexpr( (ctlstack->dostepsign==POSSTEP ? OPGT : OPLT),
443 t, ctlstack->domax),
444 ctlstack->dobodylabel);
445 putlabel(ctlstack->endlabel);
446 if(ap = memversion(np))
447 puteq(ap, mklhs( mkprim(np,0,0,0)) );
448 for(i = 0 ; i < 4 ; ++i)
449 ctlstack->ctlabels[i] = 0;
450 deregister(ctlstack->donamep);
451 ctlstack->donamep->vdovar = NO;
452 frexpr(ctlstack->dostep);
453 }
454
455 popctl();
456 dorange = 0;
457 for(q = ctlstack ; q>=ctls ; --q)
458 if(q->ctltype == CTLDO)
459 {
460 dorange = q->dolabel;
461 break;
462 }
463 }
464}
465\f
466exassign(vname, labelval)
467struct nameblock *vname;
468struct labelblock *labelval;
469{
470struct addrblock *p;
471struct constblock *mkaddcon();
472
473p = mklhs(mkprim(vname,0,0,0));
474if( ! ONEOF(p->vtype, MSKINT|MSKADDR) )
475 err("noninteger assign variable");
476else
477 puteq(p, mkaddcon(labelval->labelno) );
478}
479
480
481
482exarif(expr, neglab, zerlab, poslab)
483expptr expr;
484struct labelblock *neglab, *zerlab, *poslab;
485{
486register int lm, lz, lp;
487
488lm = neglab->labelno;
489lz = zerlab->labelno;
490lp = poslab->labelno;
491expr = fixtype(expr);
492
493if( ! ONEOF(expr->vtype, MSKINT|MSKREAL) )
494 {
495 err("invalid type of arithmetic if expression");
496 frexpr(expr);
497 }
498else
499 {
500 if(lm == lz)
501 exar2(OPLE, expr, lm, lp);
502 else if(lm == lp)
503 exar2(OPNE, expr, lm, lz);
504 else if(lz == lp)
505 exar2(OPGE, expr, lz, lm);
506 else
507 prarif(expr, lm, lz, lp);
508 }
509}
510
511
512
513LOCAL exar2(op, e, l1, l2)
514int op;
515expptr e;
516int l1, l2;
517{
518putif( mkexpr(op, e, ICON(0)), l2);
519putgoto(l1);
520}
521
522
523exreturn(p)
524register expptr p;
525{
526if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
527 {
528 err("alternate return in nonsubroutine");
529 p = 0;
530 }
531
532if(p)
533 {
534 putforce(TYINT, p);
535 putgoto(retlabel);
536 }
537else
538 putgoto(procclass==TYSUBR ? ret0label : retlabel);
539}
540
541
542
543exasgoto(labvar)
544struct hashentry *labvar;
545{
546register struct addrblock *p;
547
548p = mklhs( mkprim(labvar,0,0,0) );
549if( ! ISINT(p->vtype) )
550 err("assigned goto variable must be integer");
551else
552 putbranch(p);
553}