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 | */
|
---|
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);
|
---|
47 |
|
---|
48 | void
|
---|
49 | exif(p)
|
---|
50 | bigptr p;
|
---|
51 | {
|
---|
52 | pushctl(CTLIF);
|
---|
53 | ctlstack->elselabel = newlabel();
|
---|
54 | putif(p, ctlstack->elselabel);
|
---|
55 | }
|
---|
56 |
|
---|
57 |
|
---|
58 | void
|
---|
59 | exelif(p)
|
---|
60 | bigptr p;
|
---|
61 | {
|
---|
62 | if(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 |
|
---|
72 | else execerr("elseif out of place", 0);
|
---|
73 | }
|
---|
74 |
|
---|
75 |
|
---|
76 |
|
---|
77 |
|
---|
78 | void
|
---|
79 | exelse()
|
---|
80 | {
|
---|
81 | if(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 |
|
---|
90 | else execerr("else out of place", 0);
|
---|
91 | }
|
---|
92 |
|
---|
93 | void
|
---|
94 | exendif()
|
---|
95 | {
|
---|
96 | if(ctlstack->ctltype == CTLIF)
|
---|
97 | {
|
---|
98 | putlabel(ctlstack->elselabel);
|
---|
99 | if(ctlstack->endlabel)
|
---|
100 | putlabel(ctlstack->endlabel);
|
---|
101 | popctl();
|
---|
102 | }
|
---|
103 | else if(ctlstack->ctltype == CTLELSE)
|
---|
104 | {
|
---|
105 | putlabel(ctlstack->endlabel);
|
---|
106 | popctl();
|
---|
107 | }
|
---|
108 |
|
---|
109 | else execerr("endif out of place", 0);
|
---|
110 | }
|
---|
111 |
|
---|
112 |
|
---|
113 |
|
---|
114 | LOCAL void
|
---|
115 | pushctl(code)
|
---|
116 | int code;
|
---|
117 | {
|
---|
118 | register int i;
|
---|
119 |
|
---|
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;
|
---|
125 | ++blklevel;
|
---|
126 | }
|
---|
127 |
|
---|
128 |
|
---|
129 | LOCAL void
|
---|
130 | popctl()
|
---|
131 | {
|
---|
132 | if( ctlstack-- < ctls )
|
---|
133 | fatal("control stack empty");
|
---|
134 | --blklevel;
|
---|
135 | poplab();
|
---|
136 | }
|
---|
137 |
|
---|
138 |
|
---|
139 |
|
---|
140 | LOCAL void
|
---|
141 | poplab()
|
---|
142 | {
|
---|
143 | register struct labelblock *lp;
|
---|
144 |
|
---|
145 | for(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 | */
|
---|
164 | void
|
---|
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
|
---|
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
|
---|
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
|
---|
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
|
---|
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 |
|
---|
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 |
|
---|
300 | void
|
---|
301 | exdo(range, spec)
|
---|
302 | int range;
|
---|
303 | chainp spec;
|
---|
304 | {
|
---|
305 | register bigptr p, q;
|
---|
306 | bigptr q1;
|
---|
307 | register struct bigblock *np;
|
---|
308 | chainp cp;
|
---|
309 | register int i;
|
---|
310 | int dotype, incsign = 0; /* XXX gcc */
|
---|
311 | struct bigblock *dovarp, *dostgp;
|
---|
312 | bigptr par[3];
|
---|
313 |
|
---|
314 | pushctl(CTLDO);
|
---|
315 | dorange = ctlstack->dolabel = range;
|
---|
316 | np = spec->chain.datap;
|
---|
317 | ctlstack->donamep = NULL;
|
---|
318 | if(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 |
|
---|
325 | dovarp = mklhs( mkprim(np, 0,0,0) );
|
---|
326 | if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) )
|
---|
327 | {
|
---|
328 | err("bad type on do variable");
|
---|
329 | return;
|
---|
330 | }
|
---|
331 | ctlstack->donamep = np;
|
---|
332 |
|
---|
333 | np->b_name.vdovar = YES;
|
---|
334 | if( 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 | }
|
---|
340 | else
|
---|
341 | dostgp = NULL;
|
---|
342 | dotype = dovarp->vtype;
|
---|
343 |
|
---|
344 | for(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 |
|
---|
354 | frchain(&spec);
|
---|
355 | switch(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 |
|
---|
373 | ctlstack->endlabel = newlabel();
|
---|
374 | ctlstack->dobodylabel = newlabel();
|
---|
375 |
|
---|
376 | if( ISCONST(DOLIMIT) )
|
---|
377 | ctlstack->domax = mkconv(dotype, DOLIMIT);
|
---|
378 | else
|
---|
379 | ctlstack->domax = fmktemp(dotype, NULL);
|
---|
380 |
|
---|
381 | if( 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 | }
|
---|
388 | else
|
---|
389 | {
|
---|
390 | ctlstack->dostep = fmktemp(dotype, NULL);
|
---|
391 | ctlstack->dostepsign = VARSTEP;
|
---|
392 | ctlstack->doposlabel = newlabel();
|
---|
393 | ctlstack->doneglabel = newlabel();
|
---|
394 | }
|
---|
395 |
|
---|
396 | if( 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 | }
|
---|
413 | else 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 | }
|
---|
424 | else
|
---|
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 |
|
---|
437 | if(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 | }
|
---|
451 | putlabel(ctlstack->dobodylabel);
|
---|
452 | if(dostgp)
|
---|
453 | puteq(dostgp, cpexpr(dovarp));
|
---|
454 | frexpr(dovarp);
|
---|
455 | }
|
---|
456 |
|
---|
457 | /*
|
---|
458 | * Reached the end of a DO statement.
|
---|
459 | */
|
---|
460 | void
|
---|
461 | enddo(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 |
|
---|
506 | void
|
---|
507 | exassign(vname, labelval)
|
---|
508 | struct bigblock *vname;
|
---|
509 | struct labelblock *labelval;
|
---|
510 | {
|
---|
511 | struct bigblock *p;
|
---|
512 |
|
---|
513 | p = mklhs(mkprim(vname,0,0,0));
|
---|
514 | if( ! ONEOF(p->vtype, MSKINT|MSKADDR) )
|
---|
515 | err("noninteger assign variable");
|
---|
516 | else
|
---|
517 | puteq(p, mkaddcon(labelval->labelno) );
|
---|
518 | }
|
---|
519 |
|
---|
520 |
|
---|
521 | void
|
---|
522 | exarif(expr, neglab, zerlab, poslab)
|
---|
523 | bigptr expr;
|
---|
524 | struct labelblock *neglab, *zerlab, *poslab;
|
---|
525 | {
|
---|
526 | register int lm, lz, lp;
|
---|
527 |
|
---|
528 | lm = neglab->labelno;
|
---|
529 | lz = zerlab->labelno;
|
---|
530 | lp = poslab->labelno;
|
---|
531 | expr = fixtype(expr);
|
---|
532 |
|
---|
533 | if( ! ONEOF(expr->vtype, MSKINT|MSKREAL) )
|
---|
534 | {
|
---|
535 | err("invalid type of arithmetic if expression");
|
---|
536 | frexpr(expr);
|
---|
537 | }
|
---|
538 | else
|
---|
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 |
|
---|
553 | LOCAL void exar2(op, e, l1, l2)
|
---|
554 | int op;
|
---|
555 | bigptr e;
|
---|
556 | int l1, l2;
|
---|
557 | {
|
---|
558 | putif( mkexpr(op, e, MKICON(0)), l2);
|
---|
559 | putgoto(l1);
|
---|
560 | }
|
---|
561 |
|
---|
562 | void
|
---|
563 | exreturn(p)
|
---|
564 | register bigptr p;
|
---|
565 | {
|
---|
566 | if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
|
---|
567 | {
|
---|
568 | err("alternate return in nonsubroutine");
|
---|
569 | p = 0;
|
---|
570 | }
|
---|
571 |
|
---|
572 | if(p)
|
---|
573 | {
|
---|
574 | putforce(TYINT, p);
|
---|
575 | putgoto(retlabel);
|
---|
576 | }
|
---|
577 | else
|
---|
578 | putgoto(procclass==TYSUBR ? ret0label : retlabel);
|
---|
579 | }
|
---|
580 |
|
---|
581 |
|
---|
582 | void
|
---|
583 | exasgoto(labvar)
|
---|
584 | bigptr labvar;
|
---|
585 | {
|
---|
586 | register struct bigblock *p;
|
---|
587 |
|
---|
588 | p = mklhs( mkprim(labvar,0,0,0) );
|
---|
589 | if( ! ISINT(p->vtype) )
|
---|
590 | err("assigned goto variable must be integer");
|
---|
591 | else
|
---|
592 | putbranch(p);
|
---|
593 | }
|
---|