source: mainline/uspace/app/pcc/f77/fcom/exec.c@ 7eaeec1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7eaeec1 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 11.8 KB
Line 
1/* $Id: exec.c,v 1.14 2008/05/11 15:28:03 ragge Exp $ */
2/*
3 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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
17 * International, Inc.
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.
21 *
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.
34 */
35#include <string.h>
36
37#include "defines.h"
38#include "defs.h"
39
40/* Logical IF codes
41*/
42LOCAL void exar2(int, bigptr, int, int);
43LOCAL void pushctl(int code);
44LOCAL void popctl(void);
45LOCAL void poplab(void);
46LOCAL void mkstfunct(struct bigblock *, bigptr);
47
48void
49exif(p)
50bigptr p;
51{
52pushctl(CTLIF);
53ctlstack->elselabel = newlabel();
54putif(p, ctlstack->elselabel);
55}
56
57
58void
59exelif(p)
60bigptr p;
61{
62if(ctlstack->ctltype == CTLIF)
63 {
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);
70 }
71
72else execerr("elseif out of place", 0);
73}
74
75
76
77
78void
79exelse()
80{
81if(ctlstack->ctltype==CTLIF)
82 {
83 if(ctlstack->endlabel == 0)
84 ctlstack->endlabel = newlabel();
85 putgoto( ctlstack->endlabel );
86 putlabel(ctlstack->elselabel);
87 ctlstack->ctltype = CTLELSE;
88 }
89
90else execerr("else out of place", 0);
91}
92
93void
94exendif()
95{
96if(ctlstack->ctltype == CTLIF)
97 {
98 putlabel(ctlstack->elselabel);
99 if(ctlstack->endlabel)
100 putlabel(ctlstack->endlabel);
101 popctl();
102 }
103else if(ctlstack->ctltype == CTLELSE)
104 {
105 putlabel(ctlstack->endlabel);
106 popctl();
107 }
108
109else execerr("endif out of place", 0);
110}
111
112
113
114LOCAL void
115pushctl(code)
116int code;
117{
118register int i;
119
120if(++ctlstack >= lastctl)
121 fatal("nesting too deep");
122ctlstack->ctltype = code;
123for(i = 0 ; i < 4 ; ++i)
124 ctlstack->ctlabels[i] = 0;
125++blklevel;
126}
127
128
129LOCAL void
130popctl()
131{
132if( ctlstack-- < ctls )
133 fatal("control stack empty");
134--blklevel;
135poplab();
136}
137
138
139
140LOCAL void
141poplab()
142{
143register struct labelblock *lp;
144
145for(lp = labeltab ; lp < highlabtab ; ++lp)
146 if(lp->labdefined)
147 {
148 /* mark all labels in inner blocks unreachable */
149 if(lp->blklevel > blklevel)
150 lp->labinacc = YES;
151 }
152 else if(lp->blklevel > blklevel)
153 {
154 /* move all labels referred to in inner blocks out a level */
155 lp->blklevel = blklevel;
156 }
157}
158
159
160
161
162/* BRANCHING CODE
163*/
164void
165exgoto(lab)
166struct labelblock *lab;
167{
168putgoto(lab->labelno);
169}
170
171
172
173
174/*
175 * Found an assignment expression.
176 */
177void
178exequals(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 */
199void
200mkstfunct(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
231void
232excall(name, args, nstars, labels)
233struct bigblock *name;
234struct bigblock *args;
235int nstars;
236struct labelblock *labels[ ];
237{
238register bigptr p;
239
240settype(name, TYSUBR, 0);
241p = mkfunct( mkprim(name, args, NULL, NULL) );
242p->vtype = p->b_expr.leftp->vtype = TYINT;
243if(nstars > 0)
244 putcmgo(p, nstars, labels);
245else putexpr(p);
246}
247
248
249void
250exstop(stop, p)
251int stop;
252register bigptr p;
253{
254char *q;
255int n;
256
257if(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 }
284else p = mkstrcon(0, 0);
285
286putexpr( call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p) );
287}
288
289
290/* DO LOOP CODE */
291
292#define DOINIT par[0]
293#define DOLIMIT par[1]
294#define DOINCR par[2]
295
296#define VARSTEP 0
297#define POSSTEP 1
298#define NEGSTEP 2
299
300void
301exdo(range, spec)
302int range;
303chainp spec;
304{
305register bigptr p, q;
306bigptr q1;
307register struct bigblock *np;
308chainp cp;
309register int i;
310int dotype, incsign = 0; /* XXX gcc */
311struct bigblock *dovarp, *dostgp;
312bigptr par[3];
313
314pushctl(CTLDO);
315dorange = ctlstack->dolabel = range;
316np = spec->chain.datap;
317ctlstack->donamep = NULL;
318if(np->b_name.vdovar)
319 {
320 err1("nested loops with variable %s", varstr(VL,np->b_name.varname));
321 ctlstack->donamep = NULL;
322 return;
323 }
324
325dovarp = mklhs( mkprim(np, 0,0,0) );
326if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) )
327 {
328 err("bad type on do variable");
329 return;
330 }
331ctlstack->donamep = np;
332
333np->b_name.vdovar = YES;
334if( enregister(np) )
335 {
336 /* stgp points to a storage version, varp to a register version */
337 dostgp = dovarp;
338 dovarp = mklhs( mkprim(np, 0,0,0) );
339 }
340else
341 dostgp = NULL;
342dotype = dovarp->vtype;
343
344for(i=0 , cp = spec->chain.nextp ; cp!=NULL && i<3 ; cp = cp->chain.nextp)
345 {
346 p = par[i++] = fixtype(cp->chain.datap);
347 if( ! ONEOF(p->vtype, MSKINT|MSKREAL) )
348 {
349 err("bad type on DO parameter");
350 return;
351 }
352 }
353
354frchain(&spec);
355switch(i)
356 {
357 case 0:
358 case 1:
359 err("too few DO parameters");
360 return;
361
362 default:
363 err("too many DO parameters");
364 return;
365
366 case 2:
367 DOINCR = MKICON(1);
368
369 case 3:
370 break;
371 }
372
373ctlstack->endlabel = newlabel();
374ctlstack->dobodylabel = newlabel();
375
376if( ISCONST(DOLIMIT) )
377 ctlstack->domax = mkconv(dotype, DOLIMIT);
378else
379 ctlstack->domax = fmktemp(dotype, NULL);
380
381if( ISCONST(DOINCR) )
382 {
383 ctlstack->dostep = mkconv(dotype, DOINCR);
384 if( (incsign = conssgn(ctlstack->dostep)) == 0)
385 err("zero DO increment");
386 ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP);
387 }
388else
389 {
390 ctlstack->dostep = fmktemp(dotype, NULL);
391 ctlstack->dostepsign = VARSTEP;
392 ctlstack->doposlabel = newlabel();
393 ctlstack->doneglabel = newlabel();
394 }
395
396if( ISCONST(ctlstack->domax) && ISCONST(DOINIT) && ctlstack->dostepsign!=VARSTEP)
397 {
398 puteq(cpexpr(dovarp), cpexpr(DOINIT));
399 if( onetripflag )
400 frexpr(DOINIT);
401 else
402 {
403 q = mkexpr(OPPLUS, MKICON(1),
404 mkexpr(OPMINUS, cpexpr(ctlstack->domax), cpexpr(DOINIT)) );
405 if(incsign != conssgn(q))
406 {
407 warn("DO range never executed");
408 putgoto(ctlstack->endlabel);
409 }
410 frexpr(q);
411 }
412 }
413else if(ctlstack->dostepsign!=VARSTEP && !onetripflag)
414 {
415 if( ISCONST(ctlstack->domax) )
416 q = cpexpr(ctlstack->domax);
417 else
418 q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT);
419
420 q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT);
421 q = mkexpr( (ctlstack->dostepsign==POSSTEP ? OPLE : OPGE), q1, q);
422 putif(q, ctlstack->endlabel);
423 }
424else
425 {
426 if(! ISCONST(ctlstack->domax) )
427 puteq( cpexpr(ctlstack->domax), DOLIMIT);
428 q = DOINIT;
429 if( ! onetripflag )
430 q = mkexpr(OPMINUS, q,
431 mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), DOINCR) );
432 puteq( cpexpr(dovarp), q);
433 if(onetripflag && ctlstack->dostepsign==VARSTEP)
434 puteq( cpexpr(ctlstack->dostep), DOINCR);
435 }
436
437if(ctlstack->dostepsign == VARSTEP)
438 {
439 if(onetripflag)
440 putgoto(ctlstack->dobodylabel);
441 else
442 putif( mkexpr(OPGE, cpexpr(ctlstack->dostep), MKICON(0)),
443 ctlstack->doneglabel );
444 putlabel(ctlstack->doposlabel);
445
446 p = cpexpr(dovarp);
447 putif( mkexpr(OPLE, mkexpr(OPASSIGN, p,
448 mkexpr(OPPLUS, cpexpr(dovarp), cpexpr(ctlstack->dostep))),
449 cpexpr(ctlstack->domax)), ctlstack->endlabel);
450 }
451putlabel(ctlstack->dobodylabel);
452if(dostgp)
453 puteq(dostgp, cpexpr(dovarp));
454frexpr(dovarp);
455}
456
457/*
458 * Reached the end of a DO statement.
459 */
460void
461enddo(int here)
462{
463 register struct ctlframe *q;
464 register bigptr t;
465 struct bigblock *np;
466 struct bigblock *ap;
467 register int i;
468
469 while(here == dorange) {
470 if((np = ctlstack->donamep)) {
471
472 t = mklhs(mkprim(ctlstack->donamep, 0,0 ,0));
473 t = mkexpr(OPASSIGN, cpexpr(t),
474 mkexpr(OPPLUS, t, cpexpr(ctlstack->dostep)));
475
476 if(ctlstack->dostepsign == VARSTEP) {
477 putif( mkexpr(OPLE, cpexpr(ctlstack->dostep),
478 MKICON(0)), ctlstack->doposlabel);
479 putlabel(ctlstack->doneglabel);
480 putif( mkexpr(OPLT, t, ctlstack->domax),
481 ctlstack->dobodylabel);
482 } else
483 putif( mkexpr( (ctlstack->dostepsign==POSSTEP ?
484 OPGT : OPLT), t, ctlstack->domax),
485 ctlstack->dobodylabel);
486 putlabel(ctlstack->endlabel);
487 if((ap = memversion(np)))
488 puteq(ap, mklhs( mkprim(np,0,0,0)) );
489 for(i = 0 ; i < 4 ; ++i)
490 ctlstack->ctlabels[i] = 0;
491 deregister(ctlstack->donamep);
492 ctlstack->donamep->b_name.vdovar = NO;
493 frexpr(ctlstack->dostep);
494 }
495
496 popctl();
497 dorange = 0;
498 for(q = ctlstack ; q>=ctls ; --q)
499 if(q->ctltype == CTLDO) {
500 dorange = q->dolabel;
501 break;
502 }
503 }
504}
505
506void
507exassign(vname, labelval)
508struct bigblock *vname;
509struct labelblock *labelval;
510{
511struct bigblock *p;
512
513p = mklhs(mkprim(vname,0,0,0));
514if( ! ONEOF(p->vtype, MSKINT|MSKADDR) )
515 err("noninteger assign variable");
516else
517 puteq(p, mkaddcon(labelval->labelno) );
518}
519
520
521void
522exarif(expr, neglab, zerlab, poslab)
523bigptr expr;
524struct labelblock *neglab, *zerlab, *poslab;
525{
526register int lm, lz, lp;
527
528lm = neglab->labelno;
529lz = zerlab->labelno;
530lp = poslab->labelno;
531expr = fixtype(expr);
532
533if( ! ONEOF(expr->vtype, MSKINT|MSKREAL) )
534 {
535 err("invalid type of arithmetic if expression");
536 frexpr(expr);
537 }
538else
539 {
540 if(lm == lz)
541 exar2(OPLE, expr, lm, lp);
542 else if(lm == lp)
543 exar2(OPNE, expr, lm, lz);
544 else if(lz == lp)
545 exar2(OPGE, expr, lz, lm);
546 else
547 prarif(expr, lm, lz, lp);
548 }
549}
550
551
552
553LOCAL void exar2(op, e, l1, l2)
554int op;
555bigptr e;
556int l1, l2;
557{
558putif( mkexpr(op, e, MKICON(0)), l2);
559putgoto(l1);
560}
561
562void
563exreturn(p)
564register bigptr p;
565{
566if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
567 {
568 err("alternate return in nonsubroutine");
569 p = 0;
570 }
571
572if(p)
573 {
574 putforce(TYINT, p);
575 putgoto(retlabel);
576 }
577else
578 putgoto(procclass==TYSUBR ? ret0label : retlabel);
579}
580
581
582void
583exasgoto(labvar)
584bigptr labvar;
585{
586register struct bigblock *p;
587
588p = mklhs( mkprim(labvar,0,0,0) );
589if( ! ISINT(p->vtype) )
590 err("assigned goto variable must be integer");
591else
592 putbranch(p);
593}
Note: See TracBrowser for help on using the repository browser.