exec.c

Go to the documentation of this file.
00001 /****************************************************************
00002 Copyright 1990, 1993 - 1996, 2000 by AT&T, Lucent Technologies and Bellcore.
00003 
00004 Permission to use, copy, modify, and distribute this software
00005 and its documentation for any purpose and without fee is hereby
00006 granted, provided that the above copyright notice appear in all
00007 copies and that both that the copyright notice and this
00008 permission notice and warranty disclaimer appear in supporting
00009 documentation, and that the names of AT&T, Bell Laboratories,
00010 Lucent or Bellcore or any of their entities not be used in
00011 advertising or publicity pertaining to distribution of the
00012 software without specific, written prior permission.
00013 
00014 AT&T, Lucent and Bellcore disclaim all warranties with regard to
00015 this software, including all implied warranties of
00016 merchantability and fitness.  In no event shall AT&T, Lucent or
00017 Bellcore be liable for any special, indirect or consequential
00018 damages or any damages whatsoever resulting from loss of use,
00019 data or profits, whether in an action of contract, negligence or
00020 other tortious action, arising out of or in connection with the
00021 use or performance of this software.
00022 ****************************************************************/
00023 
00024 #include "defs.h"
00025 #include "p1defs.h"
00026 #include "names.h"
00027 
00028 static void exar2 Argdcl((int, tagptr, struct Labelblock*, struct Labelblock*));
00029 static void popctl Argdcl((void));
00030 static void pushctl Argdcl((int));
00031 
00032 /*   Logical IF codes
00033 */
00034 
00035  void
00036 #ifdef KR_headers
00037 exif(p)
00038         expptr p;
00039 #else
00040 exif(expptr p)
00041 #endif
00042 {
00043     pushctl(CTLIF);
00044     putif(p, 0);        /* 0 => if, not elseif */
00045 }
00046 
00047 
00048  void
00049 #ifdef KR_headers
00050 exelif(p)
00051         expptr p;
00052 #else
00053 exelif(expptr p)
00054 #endif
00055 {
00056     if (ctlstack->ctltype == CTLIF || ctlstack->ctltype == CTLIFX)
00057         putif(p, 1);    /* 1 ==> elseif */
00058     else
00059         execerr("elseif out of place", CNULL);
00060 }
00061 
00062 
00063 
00064 
00065  void
00066 exelse(Void)
00067 {
00068         register struct Ctlframe *c;
00069 
00070         for(c = ctlstack; c->ctltype == CTLIFX; --c);
00071         if(c->ctltype == CTLIF) {
00072                 p1_else ();
00073                 c->ctltype = CTLELSE;
00074                 }
00075         else
00076                 execerr("else out of place", CNULL);
00077         }
00078 
00079  void
00080 #ifdef KR_headers
00081 exendif()
00082 #else
00083 exendif()
00084 #endif
00085 {
00086         while(ctlstack->ctltype == CTLIFX) {
00087                 popctl();
00088                 p1else_end();
00089                 }
00090         if(ctlstack->ctltype == CTLIF) {
00091                 popctl();
00092                 p1_endif ();
00093                 }
00094         else if(ctlstack->ctltype == CTLELSE) {
00095                 popctl();
00096                 p1else_end ();
00097                 }
00098         else
00099                 execerr("endif out of place", CNULL);
00100         }
00101 
00102 
00103  void
00104 #ifdef KR_headers
00105 new_endif()
00106 #else
00107 new_endif()
00108 #endif
00109 {
00110         if (ctlstack->ctltype == CTLIF || ctlstack->ctltype == CTLIFX)
00111                 pushctl(CTLIFX);
00112         else
00113                 err("new_endif bug");
00114         }
00115 
00116 /* pushctl -- Start a new control construct, initialize the labels (to
00117    zero) */
00118 
00119  LOCAL void
00120 #ifdef KR_headers
00121 pushctl(code)
00122         int code;
00123 #else
00124 pushctl(int code)
00125 #endif
00126 {
00127         register int i;
00128 
00129         if(++ctlstack >= lastctl)
00130                 many("loops or if-then-elses", 'c', maxctl);
00131         ctlstack->ctltype = code;
00132         for(i = 0 ; i < 4 ; ++i)
00133                 ctlstack->ctlabels[i] = 0;
00134         ctlstack->dowhile = 0;
00135         ctlstack->domax = ctlstack->dostep = 0; /* in case of errors */
00136         ++blklevel;
00137 }
00138 
00139 
00140  LOCAL void
00141 popctl(Void)
00142 {
00143         if( ctlstack-- < ctls )
00144                 Fatal("control stack empty");
00145         --blklevel;
00146 }
00147 
00148 
00149 
00150 /* poplab -- update the flags in   labeltab   */
00151 
00152  LOCAL void
00153 poplab(Void)
00154 {
00155         register struct Labelblock  *lp;
00156 
00157         for(lp = labeltab ; lp < highlabtab ; ++lp)
00158                 if(lp->labdefined)
00159                 {
00160                         /* mark all labels in inner blocks unreachable */
00161                         if(lp->blklevel > (unsigned int)(blklevel))
00162                                 lp->labinacc = YES;
00163                 }
00164                 else if(lp->blklevel > (unsigned int)(blklevel))
00165                 {
00166                         /* move all labels referred to in inner blocks out a level */
00167                         lp->blklevel = blklevel;
00168                 }
00169 }
00170 
00171 
00172 /*  BRANCHING CODE
00173 */
00174  void
00175 #ifdef KR_headers
00176 exgoto(lab)
00177         struct Labelblock *lab;
00178 #else
00179 exgoto(struct Labelblock *lab)
00180 #endif
00181 {
00182         lab->labused = 1;
00183         p1_goto (lab -> stateno);
00184 }
00185 
00186 
00187  static expptr
00188 #ifdef KR_headers
00189 cktype1(p) expptr p;
00190 #else
00191 cktype1(expptr p)
00192 #endif
00193 {
00194         /* Do things omitted because we might have been parsing a */
00195         /* statement function...  Check types and fold constants. */
00196 
00197         chainp c;
00198         tagptr t;
00199 
00200         if(p == 0)
00201                 return(0);
00202 
00203         switch(p->tag) {
00204           case TCONST:
00205           case TADDR:
00206           case TERROR:
00207                 break;
00208 
00209 /* This case means that   fixexpr   can't call   fixtype   with any expr,
00210    only a subexpr of its parameter. */
00211 
00212           case TEXPR:
00213                 t = mkexpr(p->exprblock.opcode, cktype1(p->exprblock.leftp),
00214                                 cktype1(p->exprblock.rightp));
00215                 free((charptr)p);
00216                 p = (expptr) t;
00217                 break;
00218 
00219           case TLIST:
00220                 for(c = p->listblock.listp; c; c = c->nextp)
00221                         c->datap = (char*)cktype1((expptr)c->datap);
00222                 break;
00223 
00224           case TPRIM:
00225                 p->primblock.argsp = (struct Listblock*)
00226                         cktype1((expptr)p->primblock.argsp);
00227                 p->primblock.fcharp = cktype1(p->primblock.fcharp);
00228                 p->primblock.lcharp = cktype1(p->primblock.lcharp);
00229                 break;
00230 
00231           default:
00232                 badtag("cktype1", p->tag);
00233           }
00234         return p;
00235         }
00236 
00237 
00238  void
00239 #ifdef KR_headers
00240 exequals(lp, rp)
00241         register struct Primblock *lp;
00242         register expptr rp;
00243 #else
00244 exequals(register struct Primblock *lp, register expptr rp)
00245 #endif
00246 {
00247         if(lp->tag != TPRIM)
00248         {
00249                 err("assignment to a non-variable");
00250                 frexpr((expptr)lp);
00251                 frexpr(rp);
00252         }
00253         else if(lp->namep->vclass!=CLVAR && lp->argsp)
00254         {
00255                 if(parstate >= INEXEC)
00256                         errstr("statement function %.62s amid executables.",
00257                                 lp->namep->fvarname);
00258                 mkstfunct(lp, rp);
00259         }
00260         else if (lp->vtype == TYSUBR)
00261                 err("illegal use of subroutine name");
00262         else
00263         {
00264                 expptr new_lp, new_rp;
00265 
00266                 if(parstate < INDATA) {
00267                         enddcl();
00268                         lp = (struct Primblock *)cktype1((expptr)lp);
00269                         rp = cktype1(rp);
00270                         }
00271                 new_lp = mklhs (lp, keepsubs);
00272                 new_rp = fixtype (rp);
00273                 puteq(new_lp, new_rp);
00274         }
00275 }
00276 
00277 
00278 
00279 /* Make Statement Function */
00280 
00281 long laststfcn = -1, thisstno;
00282 int doing_stmtfcn;
00283 
00284  void
00285 #ifdef KR_headers
00286 mkstfunct(lp, rp)
00287         struct Primblock *lp;
00288         expptr rp;
00289 #else
00290 mkstfunct(struct Primblock *lp, expptr rp)
00291 #endif
00292 {
00293         register struct Primblock *p;
00294         register Namep np;
00295         chainp args;
00296 
00297         laststfcn = thisstno;
00298         np = lp->namep;
00299         if(np->vclass == CLUNKNOWN)
00300                 np->vclass = CLPROC;
00301         else
00302         {
00303                 dclerr("redeclaration of statement function", np);
00304                 return;
00305         }
00306         np->vprocclass = PSTFUNCT;
00307         np->vstg = STGSTFUNCT;
00308 
00309 /* Set the type of the function */
00310 
00311         impldcl(np);
00312         if (np->vtype == TYCHAR && !np->vleng)
00313                 err("character statement function with length (*)");
00314         args = (lp->argsp ? lp->argsp->listp : CHNULL);
00315         np->varxptr.vstfdesc = mkchain((char *)args, (chainp)rp);
00316 
00317         for(doing_stmtfcn = 1 ; args ; args = args->nextp)
00318 
00319 /* It is an error for the formal parameters to have arguments or
00320    subscripts */
00321 
00322                 if( ((tagptr)(args->datap))->tag!=TPRIM ||
00323                     (p = (struct Primblock *)(args->datap) )->argsp ||
00324                     p->fcharp || p->lcharp ) {
00325                         err("non-variable argument in statement function definition");
00326                         args->datap = 0;
00327                         }
00328                 else
00329                 {
00330 
00331 /* Replace the name on the left-hand side */
00332 
00333                         args->datap = (char *)p->namep;
00334                         vardcl(p -> namep);
00335                         free((char *)p);
00336                 }
00337         doing_stmtfcn = 0;
00338 }
00339 
00340  static void
00341 #ifdef KR_headers
00342 mixed_type(np)
00343         Namep np;
00344 #else
00345 mixed_type(Namep np)
00346 #endif
00347 {
00348         char buf[128];
00349         sprintf(buf, "%s function %.90s invoked as subroutine",
00350                 ftn_types[np->vtype], np->fvarname);
00351         warn(buf);
00352         }
00353 
00354  void
00355 #ifdef KR_headers
00356 excall(name, args, nstars, labels)
00357         Namep name;
00358         struct Listblock *args;
00359         int nstars;
00360         struct Labelblock **labels;
00361 #else
00362 excall(Namep name, struct Listblock *args, int nstars, struct Labelblock **labels)
00363 #endif
00364 {
00365         register expptr p;
00366 
00367         if (name->vtype != TYSUBR) {
00368                 if (name->vinfproc && !name->vcalled) {
00369                         name->vtype = TYSUBR;
00370                         frexpr(name->vleng);
00371                         name->vleng = 0;
00372                         }
00373                 else if (!name->vimpltype && name->vtype != TYUNKNOWN)
00374                         mixed_type(name);
00375                 else
00376                         settype(name, TYSUBR, (ftnint)0);
00377                 }
00378         p = mkfunct( mkprim(name, args, CHNULL) );
00379         if (p->tag == TERROR)
00380                 return;
00381 
00382 /* Subroutines and their identifiers acquire the type INT */
00383 
00384         p->exprblock.vtype = p->exprblock.leftp->headblock.vtype = TYINT;
00385 
00386 /* Handle the alternate return mechanism */
00387 
00388         if(nstars > 0)
00389                 putcmgo(putx(fixtype(p)), nstars, labels);
00390         else
00391                 putexpr(p);
00392 }
00393 
00394 
00395  void
00396 #ifdef KR_headers
00397 exstop(stop, p)
00398         int stop;
00399         register expptr p;
00400 #else
00401 exstop(int stop, register expptr p)
00402 #endif
00403 {
00404         char *str;
00405         int n;
00406 
00407         if(p)
00408         {
00409                 if( ! ISCONST(p) )
00410                 {
00411                         execerr("pause/stop argument must be constant", CNULL);
00412                         frexpr(p);
00413                         p = mkstrcon(0, CNULL);
00414                 }
00415                 else if( ISINT(p->constblock.vtype) )
00416                 {
00417                         str = convic(p->constblock.Const.ci);
00418                         n = strlen(str);
00419                         if(n > 0)
00420                         {
00421                                 p->constblock.Const.ccp = copyn(n, str);
00422                                 p->constblock.Const.ccp1.blanks = 0;
00423                                 p->constblock.vtype = TYCHAR;
00424                                 p->constblock.vleng = (expptr) ICON(n);
00425                         }
00426                         else
00427                                 p = (expptr) mkstrcon(0, CNULL);
00428                 }
00429                 else if(p->constblock.vtype != TYCHAR)
00430                 {
00431                         execerr("pause/stop argument must be integer or string", CNULL);
00432                         p = (expptr) mkstrcon(0, CNULL);
00433                 }
00434         }
00435         else    p = (expptr) mkstrcon(0, CNULL);
00436 
00437     {
00438         expptr subr_call;
00439 
00440         subr_call = call1(TYSUBR, (char*)(stop ? "s_stop" : "s_paus"), p);
00441         putexpr( subr_call );
00442     }
00443 }
00444 
00445 /* DO LOOP CODE */
00446 
00447 #define DOINIT  par[0]
00448 #define DOLIMIT par[1]
00449 #define DOINCR  par[2]
00450 
00451 
00452 /* Macros for   ctlstack -> dostepsign   */
00453 
00454 #define VARSTEP 0
00455 #define POSSTEP 1
00456 #define NEGSTEP 2
00457 
00458 
00459 /* exdo -- generate DO loop code.  In the case of a variable increment,
00460    positive increment tests are placed above the body, negative increment
00461    tests are placed below (see   enddo()   ) */
00462 
00463  void
00464 #ifdef KR_headers
00465 exdo(range, loopname, spec)
00466         int range;
00467         Namep loopname;
00468         chainp spec;
00469 #else
00470 exdo(int range, Namep loopname, chainp spec)
00471 #endif
00472                         /* range = end label */
00473                         /* input spec must have at least 2 exprs */
00474 {
00475         register expptr p;
00476         register Namep np;
00477         chainp cp;              /* loops over the fields in   spec */
00478         register int i;
00479         int dotype;             /* type of the index variable */
00480         int incsign;            /* sign of the increment, if it's constant
00481                                    */
00482         Addrp dovarp;           /* loop index variable */
00483         expptr doinit;          /* constant or register for init param */
00484         expptr par[3];          /* local specification parameters */
00485 
00486         expptr init, test, inc; /* Expressions in the resulting FOR loop */
00487 
00488 
00489         test = ENULL;
00490 
00491         pushctl(CTLDO);
00492         dorange = ctlstack->dolabel = range;
00493         ctlstack->loopname = loopname;
00494 
00495 /* Declare the loop index */
00496 
00497         np = (Namep)spec->datap;
00498         ctlstack->donamep = NULL;
00499         if (!np) { /* do while */
00500                 ctlstack->dowhile = 1;
00501 #if 0
00502                 if (loopname) {
00503                         if (loopname->vtype == TYUNKNOWN) {
00504                                 loopname->vdcldone = 1;
00505                                 loopname->vclass = CLLABEL;
00506                                 loopname->vprocclass = PLABEL;
00507                                 loopname->vtype = TYLABEL;
00508                                 }
00509                         if (loopname->vtype == TYLABEL)
00510                                 if (loopname->vdovar)
00511                                         dclerr("already in use as a loop name",
00512                                                 loopname);
00513                                 else
00514                                         loopname->vdovar = 1;
00515                         else
00516                                 dclerr("already declared; cannot be a loop name",
00517                                         loopname);
00518                         }
00519 #endif
00520                 putwhile((expptr)spec->nextp);
00521                 NOEXT("do while");
00522                 spec->nextp = 0;
00523                 frchain(&spec);
00524                 return;
00525                 }
00526         if(np->vdovar)
00527         {
00528                 errstr("nested loops with variable %s", np->fvarname);
00529                 ctlstack->donamep = NULL;
00530                 return;
00531         }
00532 
00533 /* Create a memory-resident version of the index variable */
00534 
00535         dovarp = mkplace(np);
00536         if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) )
00537         {
00538                 err("bad type on do variable");
00539                 return;
00540         }
00541         ctlstack->donamep = np;
00542 
00543         np->vdovar = YES;
00544 
00545 /* Now   dovarp   points to the index to be used within the loop,   dostgp
00546    points to the one which may need to be stored */
00547 
00548         dotype = dovarp->vtype;
00549 
00550 /* Count the input specifications and type-check each one independently;
00551    this just eliminates non-numeric values from the specification */
00552 
00553         for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp)
00554         {
00555                 p = par[i++] = fixtype((tagptr)cp->datap);
00556                 if( ! ONEOF(p->headblock.vtype, MSKINT|MSKREAL) )
00557                 {
00558                         err("bad type on DO parameter");
00559                         return;
00560                 }
00561         }
00562 
00563         frchain(&spec);
00564         switch(i)
00565         {
00566         case 0:
00567         case 1:
00568                 err("too few DO parameters");
00569                 return;
00570 
00571         default:
00572                 err("too many DO parameters");
00573                 return;
00574 
00575         case 2:
00576                 DOINCR = (expptr) ICON(1);
00577 
00578         case 3:
00579                 break;
00580         }
00581 
00582 
00583 /* Now all of the local specification fields are set, but their types are
00584    not yet consistent */
00585 
00586 /* Declare the loop initialization value, casting it properly and declaring a
00587    register if need be */
00588 
00589         ctlstack->doinit = 0;
00590         if (ISCONST (DOINIT) || !onetripflag)
00591 /* putx added 6-29-89 (mwm), not sure if fixtype is required, but I doubt it
00592    since mkconv is called just before */
00593                 doinit = putx (mkconv (dotype, DOINIT));
00594         else  {
00595             if (onetripflag)
00596                 ctlstack->doinit = doinit = (expptr) mktmp0(dotype, ENULL);
00597             else
00598                 doinit = (expptr) mktmp(dotype, ENULL);
00599             puteq (cpexpr (doinit), DOINIT);
00600         } /* else */
00601 
00602 /* Declare the loop ending value, casting it to the type of the index
00603    variable */
00604 
00605         if( ISCONST(DOLIMIT) )
00606                 ctlstack->domax = mkconv(dotype, DOLIMIT);
00607         else {
00608                 ctlstack->domax = (expptr) mktmp0(dotype, ENULL);
00609                 puteq (cpexpr (ctlstack -> domax), DOLIMIT);
00610         } /* else */
00611 
00612 /* Declare the loop increment value, casting it to the type of the index
00613    variable */
00614 
00615         if( ISCONST(DOINCR) )
00616         {
00617                 ctlstack->dostep = mkconv(dotype, DOINCR);
00618                 if( (incsign = conssgn(ctlstack->dostep)) == 0)
00619                         err("zero DO increment");
00620                 ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP);
00621         }
00622         else
00623         {
00624                 ctlstack->dostep = (expptr) mktmp0(dotype, ENULL);
00625                 ctlstack->dostepsign = VARSTEP;
00626                 puteq (cpexpr (ctlstack -> dostep), DOINCR);
00627         }
00628 
00629 /* All data is now properly typed and in the   ctlstack,   except for the
00630    initial value.  Assignments of temps have been generated already */
00631 
00632         switch (ctlstack -> dostepsign) {
00633             case VARSTEP:
00634                 test = mkexpr (OPQUEST, mkexpr (OPLT,
00635                         cpexpr (ctlstack -> dostep), ICON(0)),
00636                         mkexpr (OPCOLON,
00637                             mkexpr (OPGE, cpexpr((expptr)dovarp),
00638                                     cpexpr (ctlstack -> domax)),
00639                             mkexpr (OPLE, cpexpr((expptr)dovarp),
00640                                     cpexpr (ctlstack -> domax))));
00641                 break;
00642             case POSSTEP:
00643                 test = mkexpr (OPLE, cpexpr((expptr)dovarp),
00644                         cpexpr (ctlstack -> domax));
00645                 break;
00646             case NEGSTEP:
00647                 test = mkexpr (OPGE, cpexpr((expptr)dovarp),
00648                         cpexpr (ctlstack -> domax));
00649                 break;
00650             default:
00651                 erri ("exdo:  bad dostepsign '%d'", ctlstack -> dostepsign);
00652                 break;
00653         } /* switch (ctlstack -> dostepsign) */
00654 
00655         if (onetripflag)
00656             test = mkexpr (OPOR, test,
00657                     mkexpr (OPEQ, cpexpr((expptr)dovarp), cpexpr (doinit)));
00658         init = mkexpr (OPASSIGN, cpexpr((expptr)dovarp),
00659                         ctlstack->doinit ? cpexpr(doinit) : doinit);
00660         inc = mkexpr (OPPLUSEQ, (expptr)dovarp, cpexpr (ctlstack -> dostep));
00661 
00662         if (!onetripflag && ISCONST (ctlstack -> domax) && ISCONST (doinit)
00663                 && ctlstack -> dostepsign != VARSTEP) {
00664             expptr tester;
00665 
00666             tester = mkexpr (OPMINUS, cpexpr (doinit),
00667                     cpexpr (ctlstack -> domax));
00668             if (incsign == conssgn (tester))
00669                 warn ("DO range never executed");
00670             frexpr (tester);
00671         } /* if !onetripflag && */
00672 
00673         p1_for (init, test, inc);
00674 }
00675 
00676  void
00677 #ifdef KR_headers
00678 exenddo(np)
00679         Namep np;
00680 #else
00681 exenddo(Namep np)
00682 #endif
00683 {
00684         Namep np1;
00685         int here;
00686         struct Ctlframe *cf;
00687 
00688         if( ctlstack < ctls )
00689                 goto misplaced;
00690         here = ctlstack->dolabel;
00691         if (ctlstack->ctltype != CTLDO
00692         || here >= 0 && (!thislabel || thislabel->labelno != here)) {
00693  misplaced:
00694                 err("misplaced ENDDO");
00695                 return;
00696                 }
00697         if (np != ctlstack->loopname) {
00698                 if (np1 = ctlstack->loopname)
00699                         errstr("expected \"enddo %s\"", np1->fvarname);
00700                 else
00701                         err("expected unnamed ENDDO");
00702                 for(cf = ctls; cf < ctlstack; cf++)
00703                         if (cf->ctltype == CTLDO && cf->loopname == np) {
00704                                 here = cf->dolabel;
00705                                 break;
00706                                 }
00707                 }
00708         enddo(here);
00709         }
00710 
00711  void
00712 #ifdef KR_headers
00713 enddo(here)
00714         int here;
00715 #else
00716 enddo(int here)
00717 #endif
00718 {
00719         register struct Ctlframe *q;
00720         Namep np;                       /* name of the current DO index */
00721         Addrp ap;
00722         register int i;
00723         register expptr e;
00724 
00725 /* Many DO's can end at the same statement, so keep looping over all
00726    nested indicies */
00727 
00728         while(here == dorange)
00729         {
00730                 if(np = ctlstack->donamep)
00731                         {
00732                         p1for_end ();
00733 
00734 /* Now we're done with all of the tests, and the loop has terminated.
00735    Store the index value back in long-term memory */
00736 
00737                         if(ap = memversion(np))
00738                                 puteq((expptr)ap, (expptr)mkplace(np));
00739                         for(i = 0 ; i < 4 ; ++i)
00740                                 ctlstack->ctlabels[i] = 0;
00741                         deregister(ctlstack->donamep);
00742                         ctlstack->donamep->vdovar = NO;
00743                         /* ctlstack->dostep and ctlstack->domax can be zero */
00744                         /* with sufficiently bizarre (erroneous) syntax */
00745                         if (e = ctlstack->dostep)
00746                                 if (e->tag == TADDR && e->addrblock.istemp)
00747                                         frtemp((Addrp)e);
00748                                 else
00749                                         frexpr(e);
00750                         if (e = ctlstack->domax)
00751                                 if (e->tag == TADDR && e->addrblock.istemp)
00752                                         frtemp((Addrp)e);
00753                                 else
00754                                         frexpr(e);
00755                         if (e = ctlstack->doinit)
00756                                 frtemp((Addrp)e);
00757                         }
00758                 else if (ctlstack->dowhile)
00759                         p1for_end ();
00760 
00761 /* Set   dorange   to the closing label of the next most enclosing DO loop
00762    */
00763 
00764                 popctl();
00765                 poplab();
00766                 dorange = 0;
00767                 for(q = ctlstack ; q>=ctls ; --q)
00768                         if(q->ctltype == CTLDO)
00769                         {
00770                                 dorange = q->dolabel;
00771                                 break;
00772                         }
00773         }
00774 }
00775 
00776  void
00777 #ifdef KR_headers
00778 exassign(vname, labelval)
00779         register Namep vname;
00780         struct Labelblock *labelval;
00781 #else
00782 exassign(register Namep vname, struct Labelblock *labelval)
00783 #endif
00784 {
00785         Addrp p;
00786         register Addrp q;
00787         char *fs;
00788         register chainp cp, cpprev;
00789         register ftnint k, stno;
00790 
00791         p = mkplace(vname);
00792         if( ! ONEOF(p->vtype, MSKINT|MSKADDR) ) {
00793                 err("noninteger assign variable");
00794                 return;
00795                 }
00796 
00797         /* If the label hasn't been defined, then we do things twice:
00798          * once for an executable stmt label, once for a format
00799          */
00800 
00801         /* code for executable label... */
00802 
00803 /* Now store the assigned value in a list associated with this variable.
00804    This will be used later to generate a switch() statement in the C output */
00805 
00806         fs = labelval->fmtstring;
00807         if (!labelval->labdefined || !fs) {
00808 
00809                 if (vname -> vis_assigned == 0) {
00810                         vname -> varxptr.assigned_values = CHNULL;
00811                         vname -> vis_assigned = 1;
00812                         }
00813 
00814                 /* don't duplicate labels... */
00815 
00816                 stno = labelval->stateno;
00817                 cpprev = 0;
00818                 for(k = 0, cp = vname->varxptr.assigned_values;
00819                                 cp; cpprev = cp, cp = cp->nextp, k++)
00820                         if ((ftnint)cp->datap == stno)
00821                                 break;
00822                 if (!cp) {
00823                         cp = mkchain((char *)stno, CHNULL);
00824                         if (cpprev)
00825                                 cpprev->nextp = cp;
00826                         else
00827                                 vname->varxptr.assigned_values = cp;
00828                         labelval->labused = 1;
00829                         }
00830                 putout(mkexpr(OPASSIGN, (expptr)p, mkintcon(k)));
00831                 }
00832 
00833         /* Code for FORMAT label... */
00834 
00835         if (!labelval->labdefined || fs) {
00836 
00837                 labelval->fmtlabused = 1;
00838                 p = ALLOC(Addrblock);
00839                 p->tag = TADDR;
00840                 p->vtype = TYCHAR;
00841                 p->vstg = STGAUTO;
00842                 p->memoffset = ICON(0);
00843                 fmtname(vname, p);
00844                 q = ALLOC(Addrblock);
00845                 q->tag = TADDR;
00846                 q->vtype = TYCHAR;
00847                 q->vstg = STGAUTO;
00848                 q->ntempelt = 1;
00849                 q->memoffset = ICON(0);
00850                 q->uname_tag = UNAM_IDENT;
00851                 sprintf(q->user.ident, "fmt_%ld", labelval->stateno);
00852                 putout(mkexpr(OPASSIGN, (expptr)p, (expptr)q));
00853                 }
00854 
00855 } /* exassign */
00856 
00857 
00858  void
00859 #ifdef KR_headers
00860 exarif(expr, neglab, zerlab, poslab)
00861         expptr expr;
00862         struct Labelblock *neglab;
00863         struct Labelblock *zerlab;
00864         struct Labelblock *poslab;
00865 #else
00866 exarif(expptr expr, struct Labelblock *neglab, struct Labelblock *zerlab, struct Labelblock *poslab)
00867 #endif
00868 {
00869     ftnint lm, lz, lp;
00870 
00871     lm = neglab->stateno;
00872     lz = zerlab->stateno;
00873     lp = poslab->stateno;
00874     expr = fixtype(expr);
00875 
00876     if( ! ONEOF(expr->headblock.vtype, MSKINT|MSKREAL) )
00877     {
00878         err("invalid type of arithmetic if expression");
00879         frexpr(expr);
00880     }
00881     else
00882     {
00883         if (lm == lz && lz == lp)
00884             exgoto (neglab);
00885         else if(lm == lz)
00886             exar2(OPLE, expr, neglab, poslab);
00887         else if(lm == lp)
00888             exar2(OPNE, expr, neglab, zerlab);
00889         else if(lz == lp)
00890             exar2(OPGE, expr, zerlab, neglab);
00891         else {
00892             expptr t;
00893 
00894             if (!addressable (expr)) {
00895                 t = (expptr) mktmp(expr -> headblock.vtype, ENULL);
00896                 expr = mkexpr (OPASSIGN, cpexpr (t), expr);
00897             } else
00898                 t = (expptr) cpexpr (expr);
00899 
00900             p1_if(putx(fixtype(mkexpr (OPLT, expr, ICON (0)))));
00901             exgoto(neglab);
00902             p1_elif (mkexpr (OPEQ, t, ICON (0)));
00903             exgoto(zerlab);
00904             p1_else ();
00905             exgoto(poslab);
00906             p1else_end ();
00907         } /* else */
00908     }
00909 }
00910 
00911 
00912 
00913 /* exar2 -- Do arithmetic IF for only 2 distinct labels;   if !(e.op.0)
00914    goto l2 else goto l1.  If this seems backwards, that's because it is,
00915    in order to make the 1 pass algorithm work. */
00916 
00917  LOCAL void
00918 #ifdef KR_headers
00919 exar2(op, e, l1, l2)
00920         int op;
00921         expptr e;
00922         struct Labelblock *l1;
00923         struct Labelblock *l2;
00924 #else
00925 exar2(int op, expptr e, struct Labelblock *l1, struct Labelblock *l2)
00926 #endif
00927 {
00928         expptr comp;
00929 
00930         comp = mkexpr (op, e, ICON (0));
00931         p1_if(putx(fixtype(comp)));
00932         exgoto(l1);
00933         p1_else ();
00934         exgoto(l2);
00935         p1else_end ();
00936 }
00937 
00938 
00939 /* exreturn -- return the value in   p  from a SUBROUTINE call -- used to
00940    implement the alternate return mechanism */
00941 
00942  void
00943 #ifdef KR_headers
00944 exreturn(p)
00945         register expptr p;
00946 #else
00947 exreturn(register expptr p)
00948 #endif
00949 {
00950         if(procclass != CLPROC)
00951                 warn("RETURN statement in main or block data");
00952         if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
00953         {
00954                 err("alternate return in nonsubroutine");
00955                 p = 0;
00956         }
00957 
00958         if (p || proctype == TYSUBR) {
00959                 if (p == ENULL) p = ICON (0);
00960                 p = mkconv (TYLONG, fixtype (p));
00961                 p1_subr_ret (p);
00962         } /* if p || proctype == TYSUBR */
00963         else
00964             p1_subr_ret((expptr)retslot);
00965 }
00966 
00967 
00968  void
00969 #ifdef KR_headers
00970 exasgoto(labvar)
00971         Namep labvar;
00972 #else
00973 exasgoto(Namep labvar)
00974 #endif
00975 {
00976         register Addrp p;
00977 
00978         p = mkplace(labvar);
00979         if( ! ISINT(p->vtype) )
00980                 err("assigned goto variable must be integer");
00981         else {
00982                 p1_asgoto (p);
00983         } /* else */
00984 }

Generated on Sun Mar 4 15:03:44 2007 for Scilab [trunk] by  doxygen 1.5.1