proc.c

Go to the documentation of this file.
00001 /****************************************************************
00002 Copyright 1990, 1994-6, 2000-2001 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 "names.h"
00026 #include "output.h"
00027 #include "p1defs.h"
00028 
00029 /* round a up to the nearest multiple of b:
00030 
00031    a = b * floor ( (a + (b - 1)) / b )*/
00032 
00033 #undef roundup
00034 #define roundup(a,b)    ( b * ( (a+b-1)/b) )
00035 
00036 #define EXNULL (union Expression *)0
00037 
00038 static void dobss Argdcl((void));
00039 static void docomleng Argdcl((void));
00040 static void docommon Argdcl((void));
00041 static void doentry Argdcl((struct Entrypoint*));
00042 static void epicode Argdcl((void));
00043 static int nextarg Argdcl((int));
00044 static void retval Argdcl((int));
00045 
00046 static char Blank[] = BLANKCOMMON;
00047 
00048  static char *postfix[] = { "g", "h", "i",
00049 #ifdef TYQUAD
00050                                         "j",
00051 #endif
00052                                         "r", "d", "c", "z", "g", "h", "i" };
00053 
00054  chainp new_procs;
00055  int prev_proc, proc_argchanges, proc_protochanges;
00056 
00057  void
00058 #ifdef KR_headers
00059 changedtype(q)
00060         Namep q;
00061 #else
00062 changedtype(Namep q)
00063 #endif
00064 {
00065         char buf[200];
00066         int qtype, type1;
00067         register Extsym *e;
00068         Argtypes *at;
00069 
00070         if (q->vtypewarned)
00071                 return;
00072         q->vtypewarned = 1;
00073         qtype = q->vtype;
00074         e = &extsymtab[q->vardesc.varno];
00075         if (!(at = e->arginfo)) {
00076                 if (!e->exused)
00077                         return;
00078                 }
00079         else if (at->changes & 2 && qtype != TYUNKNOWN && !at->defined)
00080                 proc_protochanges++;
00081         type1 = e->extype;
00082         if (type1 == TYUNKNOWN)
00083                 return;
00084         if (qtype == TYUNKNOWN)
00085                 /* e.g.,
00086                         subroutine foo
00087                         end
00088                         external foo
00089                         call goo(foo)
00090                         end
00091                 */
00092                 return;
00093         sprintf(buf, "%.90s: inconsistent declarations:\n\
00094         here %s%s, previously %s%s.", q->fvarname, ftn_types[qtype],
00095                 qtype == TYSUBR ? "" : " function",
00096                 ftn_types[type1], type1 == TYSUBR ? "" : " function");
00097         warn(buf);
00098         }
00099 
00100  void
00101 #ifdef KR_headers
00102 unamstring(q, s)
00103         register Addrp q;
00104         register char *s;
00105 #else
00106 unamstring(register Addrp q, register char *s)
00107 #endif
00108 {
00109         register int k;
00110         register char *t;
00111 
00112         k = strlen(s);
00113         if (k < IDENT_LEN) {
00114                 q->uname_tag = UNAM_IDENT;
00115                 t = q->user.ident;
00116                 }
00117         else {
00118                 q->uname_tag = UNAM_CHARP;
00119                 q->user.Charp = t = mem(k+1, 0);
00120                 }
00121         strcpy(t, s);
00122         }
00123 
00124  static void
00125 fix_entry_returns(Void) /* for multiple entry points */
00126 {
00127         Addrp a;
00128         int i;
00129         struct Entrypoint *e;
00130         Namep np;
00131 
00132         e = entries = (struct Entrypoint *)revchain((chainp)entries);
00133         allargs = revchain(allargs);
00134         if (!multitype)
00135                 return;
00136 
00137         /* TYLOGICAL should have been turned into TYLONG or TYSHORT by now */
00138 
00139         for(i = TYINT1; i <= TYLOGICAL; i++)
00140                 if (a = xretslot[i])
00141                         sprintf(a->user.ident, "(*ret_val).%s",
00142                                 postfix[i-TYINT1]);
00143 
00144         do {
00145                 np = e->enamep;
00146                 switch(np->vtype) {
00147                         case TYINT1:
00148                         case TYSHORT:
00149                         case TYLONG:
00150 #ifdef TYQUAD
00151                         case TYQUAD:
00152 #endif
00153                         case TYREAL:
00154                         case TYDREAL:
00155                         case TYCOMPLEX:
00156                         case TYDCOMPLEX:
00157                         case TYLOGICAL1:
00158                         case TYLOGICAL2:
00159                         case TYLOGICAL:
00160                                 np->vstg = STGARG;
00161                         }
00162                 }
00163                 while(e = e->entnextp);
00164         }
00165 
00166  static void
00167 #ifdef KR_headers
00168 putentries(outfile)
00169         FILE *outfile;
00170 #else
00171 putentries(FILE *outfile)
00172 #endif
00173         /* put out wrappers for multiple entries */
00174 {
00175         char base[MAXNAMELEN+4];
00176         struct Entrypoint *e;
00177         Namep *A, *Ae, *Ae1, **Alp, *a, **a1, np;
00178         chainp args, lengths;
00179         int i, k, mt, nL, t, type;
00180         extern char *dfltarg[], **dfltproc;
00181 
00182         e = entries;
00183         if (!e->enamep) /* only possible with erroneous input */
00184                 return;
00185         nL = (nallargs + nallchargs) * sizeof(Namep *);
00186         if (!nL)
00187                 nL = 8;
00188         A = (Namep *)ckalloc(nL + nallargs*sizeof(Namep **));
00189         Ae = A + nallargs;
00190         Alp = (Namep **)(Ae1 = Ae + nallchargs);
00191         i = k = 0;
00192         for(a1 = Alp, args = allargs; args; a1++, args = args->nextp) {
00193                 np = (Namep)args->datap;
00194                 if (np->vtype == TYCHAR && np->vclass != CLPROC)
00195                         *a1 = &Ae[i++];
00196                 }
00197 
00198         mt = multitype;
00199         multitype = 0;
00200         sprintf(base, "%s0_", e->enamep->cvarname);
00201         do {
00202                 np = e->enamep;
00203                 lengths = length_comp(e, 0);
00204                 proctype = type = np->vtype;
00205                 if (protofile)
00206                         protowrite(protofile, type, np->cvarname, e, lengths);
00207                 nice_printf(outfile, "\n%s ", c_type_decl(type, 1));
00208                 nice_printf(outfile, "%s", np->cvarname);
00209                 if (!Ansi) {
00210                         listargs(outfile, e, 0, lengths);
00211                         nice_printf(outfile, "\n");
00212                         }
00213                 list_arg_types(outfile, e, lengths, 0, "\n");
00214                 nice_printf(outfile, "{\n");
00215                 frchain(&lengths);
00216                 next_tab(outfile);
00217                 if (mt)
00218                         nice_printf(outfile,
00219                                 "Multitype ret_val;\n%s(%d, &ret_val",
00220                                 base, k); /*)*/
00221                 else if (ISCOMPLEX(type))
00222                         nice_printf(outfile, "%s(%d,%s", base, k,
00223                                 xretslot[type]->user.ident); /*)*/
00224                 else if (type == TYCHAR)
00225                         nice_printf(outfile,
00226                                 "%s(%d, ret_val, ret_val_len", base, k); /*)*/
00227                 else
00228                         nice_printf(outfile, "return %s(%d", base, k); /*)*/
00229                 k++;
00230                 memset((char *)A, 0, nL);
00231                 for(args = e->arglist; args; args = args->nextp) {
00232                         np = (Namep)args->datap;
00233                         A[np->argno] = np;
00234                         if (np->vtype == TYCHAR && np->vclass != CLPROC)
00235                                 *Alp[np->argno] = np;
00236                         }
00237                 args = allargs;
00238                 for(a = A; a < Ae; a++, args = args->nextp) {
00239                         t = ((Namep)args->datap)->vtype;
00240                         nice_printf(outfile, ", %s", (np = *a)
00241                                 ? np->cvarname
00242                                 : ((Namep)args->datap)->vclass == CLPROC
00243                                 ? dfltproc[((Namep)args->datap)->vimpltype
00244                                         ? (Castargs ? TYUNKNOWN : TYSUBR)
00245                                         : t == TYREAL && forcedouble && !Castargs
00246                                         ? TYDREAL : t]
00247                                 : dfltarg[((Namep)args->datap)->vtype]);
00248                         }
00249                 for(; a < Ae1; a++)
00250                         if (np = *a)
00251                                 nice_printf(outfile, ", %s",
00252                                         new_arg_length(np));
00253                         else
00254                                 nice_printf(outfile, ", (ftnint)0");
00255                 nice_printf(outfile, /*(*/ ");\n");
00256                 if (mt) {
00257                         if (type == TYCOMPLEX)
00258                                 nice_printf(outfile,
00259                     "r_v->r = ret_val.c.r; r_v->i = ret_val.c.i;\n");
00260                         else if (type == TYDCOMPLEX)
00261                                 nice_printf(outfile,
00262                     "r_v->r = ret_val.z.r; r_v->i = ret_val.z.i;\n");
00263                         else if (type <= TYLOGICAL)
00264                                 nice_printf(outfile, "return ret_val.%s;\n",
00265                                         postfix[type-TYINT1]);
00266                         }
00267                 nice_printf(outfile, "}\n");
00268                 prev_tab(outfile);
00269                 }
00270                 while(e = e->entnextp);
00271         free((char *)A);
00272         }
00273 
00274  static void
00275 #ifdef KR_headers
00276 entry_goto(outfile)
00277         FILE *outfile;
00278 #else
00279 entry_goto(FILE *outfile)
00280 #endif
00281 {
00282         struct Entrypoint *e = entries;
00283         int k = 0;
00284 
00285         nice_printf(outfile, "switch(n__) {\n");
00286         next_tab(outfile);
00287         while(e = e->entnextp)
00288                 nice_printf(outfile, "case %d: goto %s;\n", ++k,
00289                         user_label((long)(extsymtab - e->entryname - 1)));
00290         nice_printf(outfile, "}\n\n");
00291         prev_tab(outfile);
00292         }
00293 
00294 /* start a new procedure */
00295 
00296  void
00297 newproc(Void)
00298 {
00299         if(parstate != OUTSIDE)
00300         {
00301                 execerr("missing end statement", CNULL);
00302                 endproc();
00303         }
00304 
00305         parstate = INSIDE;
00306         procclass = CLMAIN;     /* default */
00307 }
00308 
00309  static void
00310 zap_changes(Void)
00311 {
00312         register chainp cp;
00313         register Argtypes *at;
00314 
00315         /* arrange to get correct count of prototypes that would
00316            change by running f2c again */
00317 
00318         if (prev_proc && proc_argchanges)
00319                 proc_protochanges++;
00320         prev_proc = proc_argchanges = 0;
00321         for(cp = new_procs; cp; cp = cp->nextp)
00322                 if (at = ((Namep)cp->datap)->arginfo)
00323                         at->changes &= ~1;
00324         frchain(&new_procs);
00325         }
00326 
00327 /* end of procedure. generate variables, epilogs, and prologs */
00328 
00329  void
00330 endproc(Void)
00331 {
00332         struct Labelblock *lp;
00333         Extsym *ext;
00334 
00335         if(parstate < INDATA)
00336                 enddcl();
00337         if(ctlstack >= ctls)
00338                 err("DO loop or BLOCK IF not closed");
00339         for(lp = labeltab ; lp < labtabend ; ++lp)
00340                 if(lp->stateno!=0 && lp->labdefined==NO)
00341                         errstr("missing statement label %s",
00342                                 convic(lp->stateno) );
00343 
00344 /* Save copies of the common variables in extptr -> allextp */
00345 
00346         for (ext = extsymtab; ext < nextext; ext++)
00347                 if (ext -> extstg == STGCOMMON && ext -> extp) {
00348                         extern int usedefsforcommon;
00349 
00350 /* Write out the abbreviations for common block reference */
00351 
00352                         copy_data (ext -> extp);
00353                         if (usedefsforcommon) {
00354                                 wr_abbrevs (c_file, 1, ext -> extp);
00355                                 ext -> used_here = 1;
00356                                 }
00357                         else
00358                                 ext -> extp = CHNULL;
00359 
00360                         }
00361 
00362         if (nentry > 1)
00363                 fix_entry_returns();
00364         epicode();
00365         donmlist();
00366         dobss();
00367         start_formatting ();
00368         if (nentry > 1)
00369                 putentries(c_file);
00370 
00371         zap_changes();
00372         procinit();     /* clean up for next procedure */
00373 }
00374 
00375 
00376 
00377 /* End of declaration section of procedure.  Allocate storage. */
00378 
00379  void
00380 enddcl(Void)
00381 {
00382         register struct Entrypoint *ep;
00383         struct Entrypoint *ep0;
00384         chainp cp;
00385         extern char *err_proc;
00386         static char comblks[] = "common blocks";
00387 
00388         err_proc = comblks;
00389         docommon();
00390 
00391 /* Now the hash table entries for fields of common blocks have STGCOMMON,
00392    vdcldone, voffset, and varno.  And the common blocks themselves have
00393    their full sizes in extleng. */
00394 
00395         err_proc = "equivalences";
00396         doequiv();
00397 
00398         err_proc = comblks;
00399         docomleng();
00400 
00401 /* This implies that entry points in the declarations are buffered in
00402    entries   but not written out */
00403 
00404         err_proc = "entries";
00405         if (ep = ep0 = (struct Entrypoint *)revchain((chainp)entries)) {
00406                 /* entries could be 0 in case of an error */
00407                 do doentry(ep);
00408                         while(ep = ep->entnextp);
00409                 entries = (struct Entrypoint *)revchain((chainp)ep0);
00410                 }
00411 
00412         err_proc = 0;
00413         parstate = INEXEC;
00414         p1put(P1_PROCODE);
00415         freetemps();
00416         if (earlylabs) {
00417                 for(cp = earlylabs = revchain(earlylabs); cp; cp = cp->nextp)
00418                         p1_label((long)cp->datap);
00419                 frchain(&earlylabs);
00420                 }
00421         p1_line_number(lineno); /* for files that start with a MAIN program */
00422                                 /* that starts with an executable statement */
00423 }
00424 
00425 /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
00426 
00427 /* Main program or Block data */
00428 
00429  void
00430 #ifdef KR_headers
00431 startproc(progname, Class)
00432         Extsym *progname;
00433         int Class;
00434 #else
00435 startproc(Extsym *progname, int Class)
00436 #endif
00437 {
00438         register struct Entrypoint *p;
00439 
00440         p = ALLOC(Entrypoint);
00441         if(Class == CLMAIN) {
00442                 puthead(CNULL, CLMAIN);
00443                 if (progname)
00444                     strcpy (main_alias, progname->cextname);
00445         } else {
00446                 if (progname) {
00447                         /* Construct an empty subroutine with this name */
00448                         /* in case the name is needed to force loading */
00449                         /* of this block-data subprogram: the name can */
00450                         /* appear elsewhere in an external statement. */
00451                         entrypt(CLPROC, TYSUBR, (ftnint)0, progname, (chainp)0);
00452                         endproc();
00453                         newproc();
00454                         }
00455                 puthead(CNULL, CLBLOCK);
00456                 }
00457         if(Class == CLMAIN)
00458                 newentry( mkname(" MAIN"), 0 )->extinit = 1;
00459         p->entryname = progname;
00460         entries = p;
00461 
00462         procclass = Class;
00463         fprintf(diagfile, "   %s", (Class==CLMAIN ? "MAIN" : "BLOCK DATA") );
00464         if(progname) {
00465                 fprintf(diagfile, " %s", progname->fextname);
00466                 procname = progname->cextname;
00467                 }
00468         fprintf(diagfile, ":\n");
00469         fflush(diagfile);
00470 }
00471 
00472 /* subroutine or function statement */
00473 
00474  Extsym *
00475 #ifdef KR_headers
00476 newentry(v, substmsg)
00477         register Namep v;
00478         int substmsg;
00479 #else
00480 newentry(register Namep v, int substmsg)
00481 #endif
00482 {
00483         register Extsym *p;
00484         char buf[128], badname[64];
00485         static int nbad = 0;
00486         static char already[] = "external name already used";
00487 
00488         p = mkext(v->fvarname, addunder(v->cvarname));
00489 
00490         if(p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
00491         {
00492                 sprintf(badname, "%s_bad%d", v->fvarname, ++nbad);
00493                 if (substmsg) {
00494                         sprintf(buf,"%s\n\tsubstituting \"%s\"",
00495                                 already, badname);
00496                         dclerr(buf, v);
00497                         }
00498                 else
00499                         dclerr(already, v);
00500                 p = mkext(v->fvarname, badname);
00501         }
00502         v->vstg = STGAUTO;
00503         v->vprocclass = PTHISPROC;
00504         v->vclass = CLPROC;
00505         if (p->extstg == STGEXT)
00506                 prev_proc = 1;
00507         else
00508                 p->extstg = STGEXT;
00509         p->extinit = YES;
00510         v->vardesc.varno = p - extsymtab;
00511         return(p);
00512 }
00513 
00514  void
00515 #ifdef KR_headers
00516 entrypt(Class, type, length, entry, args)
00517         int Class;
00518         int type;
00519         ftnint length;
00520         Extsym *entry;
00521         chainp args;
00522 #else
00523 entrypt(int Class, int type, ftnint length, Extsym *entry, chainp args)
00524 #endif
00525 {
00526         register Namep q;
00527         register struct Entrypoint *p;
00528 
00529         if(Class != CLENTRY)
00530                 puthead( procname = entry->cextname, Class);
00531         else
00532                 fprintf(diagfile, "       entry ");
00533         fprintf(diagfile, "   %s:\n", entry->fextname);
00534         fflush(diagfile);
00535         q = mkname(entry->fextname);
00536         if (type == TYSUBR)
00537                 q->vstg = STGEXT;
00538 
00539         type = lengtype(type, length);
00540         if(Class == CLPROC)
00541         {
00542                 procclass = CLPROC;
00543                 proctype = type;
00544                 procleng = type == TYCHAR ? length : 0;
00545         }
00546 
00547         p = ALLOC(Entrypoint);
00548 
00549         p->entnextp = entries;
00550         entries = p;
00551 
00552         p->entryname = entry;
00553         p->arglist = revchain(args);
00554         p->enamep = q;
00555 
00556         if(Class == CLENTRY)
00557         {
00558                 Class = CLPROC;
00559                 if(proctype == TYSUBR)
00560                         type = TYSUBR;
00561         }
00562 
00563         q->vclass = Class;
00564         q->vprocclass = 0;
00565         settype(q, type, length);
00566         q->vprocclass = PTHISPROC;
00567         /* hold all initial entry points till end of declarations */
00568         if(parstate >= INDATA)
00569                 doentry(p);
00570 }
00571 
00572 /* generate epilogs */
00573 
00574 /* epicode -- write out the proper function return mechanism at the end of
00575    the procedure declaration.  Handles multiple return value types, as
00576    well as cooercion into the proper value */
00577 
00578  LOCAL void
00579 epicode(Void)
00580 {
00581         extern int lastwasbranch;
00582 
00583         if(procclass==CLPROC)
00584         {
00585                 if(proctype==TYSUBR)
00586                 {
00587 
00588 /* Return a zero only when the alternate return mechanism has been
00589    specified in the function header */
00590 
00591                         if ((substars || Ansi) && lastwasbranch != YES)
00592                             p1_subr_ret (ICON(0));
00593                 }
00594                 else if (!multitype && lastwasbranch != YES)
00595                         retval(proctype);
00596         }
00597         else if (procclass == CLMAIN && Ansi && lastwasbranch != YES)
00598                 p1_subr_ret (ICON(0));
00599         lastwasbranch = NO;
00600 }
00601 
00602 
00603 /* generate code to return value of type  t */
00604 
00605  LOCAL void
00606 #ifdef KR_headers
00607 retval(t)
00608         register int t;
00609 #else
00610 retval(register int t)
00611 #endif
00612 {
00613         register Addrp p;
00614 
00615         switch(t)
00616         {
00617         case TYCHAR:
00618         case TYCOMPLEX:
00619         case TYDCOMPLEX:
00620                 break;
00621 
00622         case TYLOGICAL:
00623                 t = tylogical;
00624         case TYINT1:
00625         case TYADDR:
00626         case TYSHORT:
00627         case TYLONG:
00628 #ifdef TYQUAD
00629         case TYQUAD:
00630 #endif
00631         case TYREAL:
00632         case TYDREAL:
00633         case TYLOGICAL1:
00634         case TYLOGICAL2:
00635                 p = (Addrp) cpexpr((expptr)retslot);
00636                 p->vtype = t;
00637                 p1_subr_ret (mkconv (t, fixtype((expptr)p)));
00638                 break;
00639 
00640         default:
00641                 badtype("retval", t);
00642         }
00643 }
00644 
00645 
00646 /* Do parameter adjustments */
00647 
00648  void
00649 #ifdef KR_headers
00650 procode(outfile)
00651         FILE *outfile;
00652 #else
00653 procode(FILE *outfile)
00654 #endif
00655 {
00656         prolog(outfile, allargs);
00657 
00658         if (nentry > 1)
00659                 entry_goto(outfile);
00660         }
00661 
00662  static void
00663 #ifdef KR_headers
00664 bad_dimtype(q) Namep q;
00665 #else
00666 bad_dimtype(Namep q)
00667 #endif
00668 {
00669         errstr("bad dimension type for %.70s", q->fvarname);
00670         }
00671 
00672 /* Finish bound computations now that all variables are declared.
00673  * This used to be in setbound(), but under -u the following incurred
00674  * an erroneous error message:
00675  *      subroutine foo(x,n)
00676  *      real x(n)
00677  *      integer n
00678  */
00679 
00680  static void
00681 #ifdef KR_headers
00682 dim_finish(v)
00683         Namep v;
00684 #else
00685 dim_finish(Namep v)
00686 #endif
00687 {
00688         register struct Dimblock *p;
00689         register expptr q;
00690         register int i, nd;
00691 
00692         p = v->vdim;
00693         v->vdimfinish = 0;
00694         nd = p->ndim;
00695         doin_setbound = 1;
00696         for(i = 0; i < nd; i++)
00697                 if (q = p->dims[i].dimexpr) {
00698                         q = p->dims[i].dimexpr = make_int_expr(putx(fixtype(q)));
00699                         if (!ONEOF(q->headblock.vtype, MSKINT|MSKREAL))
00700                                 bad_dimtype(v);
00701                         }
00702         if (q = p->basexpr)
00703                 p->basexpr = make_int_expr(putx(fixtype(q)));
00704         doin_setbound = 0;
00705         }
00706 
00707  static void
00708 #ifdef KR_headers
00709 duparg(q)
00710         Namep q;
00711 #else
00712 duparg(Namep q)
00713 #endif
00714 { errstr("duplicate argument %.80s", q->fvarname); }
00715 
00716 /*
00717    manipulate argument lists (allocate argument slot positions)
00718  * keep track of return types and labels
00719  */
00720 
00721  LOCAL void
00722 #ifdef KR_headers
00723 doentry(ep)
00724         struct Entrypoint *ep;
00725 #else
00726 doentry(struct Entrypoint *ep)
00727 #endif
00728 {
00729         register int type;
00730         register Namep np;
00731         chainp p, p1;
00732         register Namep q;
00733         Addrp rs;
00734         int it, k;
00735         extern char dflttype[26];
00736         Extsym *entryname = ep->entryname;
00737 
00738         if (++nentry > 1)
00739                 p1_label((long)(extsymtab - entryname - 1));
00740 
00741 /* The main program isn't allowed to have parameters, so any given
00742    parameters are ignored */
00743 
00744         if(procclass == CLMAIN && !ep->arglist || procclass == CLBLOCK)
00745                 return;
00746 
00747         /* Entry points in MAIN are an error, but we process them here */
00748         /* to prevent faults elsewhere. */
00749 
00750 /* So now we're working with something other than CLMAIN or CLBLOCK.
00751    Determine the type of its return value. */
00752 
00753         impldcl( np = mkname(entryname->fextname) );
00754         type = np->vtype;
00755         proc_argchanges = prev_proc && type != entryname->extype;
00756         entryname->extseen = 1;
00757         if(proctype == TYUNKNOWN)
00758                 if( (proctype = type) == TYCHAR)
00759                         procleng = np->vleng ? np->vleng->constblock.Const.ci
00760                                              : (ftnint) (-1);
00761 
00762         if(proctype == TYCHAR)
00763         {
00764                 if(type != TYCHAR)
00765                         err("noncharacter entry of character function");
00766 
00767 /* Functions returning type   char   can only have multiple entries if all
00768    entries return the same length */
00769 
00770                 else if( (np->vleng ? np->vleng->constblock.Const.ci :
00771                     (ftnint) (-1)) != procleng)
00772                         err("mismatched character entry lengths");
00773         }
00774         else if(type == TYCHAR)
00775                 err("character entry of noncharacter function");
00776         else if(type != proctype)
00777                 multitype = YES;
00778         if(rtvlabel[type] == 0)
00779                 rtvlabel[type] = (int)newlabel();
00780         ep->typelabel = rtvlabel[type];
00781 
00782         if(type == TYCHAR)
00783         {
00784                 if(chslot < 0)
00785                 {
00786                         chslot = nextarg(TYADDR);
00787                         chlgslot = nextarg(TYLENG);
00788                 }
00789                 np->vstg = STGARG;
00790 
00791 /* Put a new argument in the function, one which will hold the result of
00792    a character function.  This will have to be named sometime, probably in
00793    mkarg(). */
00794 
00795                 if(procleng < 0) {
00796                         np->vleng = (expptr) mkarg(TYLENG, chlgslot);
00797                         np->vleng->addrblock.uname_tag = UNAM_IDENT;
00798                         strcpy (np -> vleng -> addrblock.user.ident,
00799                                 new_func_length());
00800                         }
00801                 if (!xretslot[TYCHAR]) {
00802                         xretslot[TYCHAR] = rs =
00803                                 autovar(0, type, ISCONST(np->vleng)
00804                                         ? np->vleng : ICON(0), "");
00805                         strcpy(rs->user.ident, "ret_val");
00806                         }
00807         }
00808 
00809 /* Handle a   complex   return type -- declare a new parameter (pointer to
00810    a complex value) */
00811 
00812         else if( ISCOMPLEX(type) ) {
00813                 if (!xretslot[type])
00814                         xretslot[type] =
00815                                 autovar(0, type, EXNULL, " ret_val");
00816                                 /* the blank is for use in out_addr */
00817                 np->vstg = STGARG;
00818                 if(cxslot < 0)
00819                         cxslot = nextarg(TYADDR);
00820                 }
00821         else if (type != TYSUBR) {
00822                 if (type == TYUNKNOWN) {
00823                         dclerr("untyped function", np);
00824                         proctype = type = np->vtype =
00825                                 dflttype[letter(np->fvarname[0])];
00826                         }
00827                 if (!xretslot[type])
00828                         xretslot[type] = retslot =
00829                                 autovar(1, type, EXNULL, " ret_val");
00830                                 /* the blank is for use in out_addr */
00831                 np->vstg = STGAUTO;
00832                 }
00833 
00834         for(p = ep->arglist ; p ; p = p->nextp)
00835                 if(! (( q = (Namep) (p->datap) )->vknownarg) ) {
00836                         q->vknownarg = 1;
00837                         q->vardesc.varno = nextarg(TYADDR);
00838                         allargs = mkchain((char *)q, allargs);
00839                         q->argno = nallargs++;
00840                         }
00841                 else if (nentry == 1)
00842                         duparg(q);
00843                 else for(p1 = ep->arglist ; p1 != p; p1 = p1->nextp)
00844                         if ((Namep)p1->datap == q)
00845                                 duparg(q);
00846 
00847         k = 0;
00848         for(p = ep->arglist ; p ; p = p->nextp) {
00849                 if(! (( q = (Namep) (p->datap) )->vdcldone) )
00850                         {
00851                         impldcl(q);
00852                         q->vdcldone = YES;
00853                         if(q->vtype == TYCHAR)
00854                                 {
00855 
00856 /* If we don't know the length of a char*(*) (i.e. a string), we must add
00857    in this additional length argument. */
00858 
00859                                 ++nallchargs;
00860                                 if (q->vclass == CLPROC)
00861                                         nallchargs--;
00862                                 else if (q->vleng == NULL) {
00863                                         /* character*(*) */
00864                                         q->vleng = (expptr)
00865                                             mkarg(TYLENG, nextarg(TYLENG) );
00866                                         unamstring((Addrp)q->vleng,
00867                                                 new_arg_length(q));
00868                                         }
00869                                 }
00870                         }
00871                 if (q->vdimfinish)
00872                         dim_finish(q);
00873                 if (q->vtype == TYCHAR && q->vclass != CLPROC)
00874                         k++;
00875                 }
00876 
00877         if (entryname->extype != type)
00878                 changedtype(np);
00879 
00880         /* save information for checking consistency of arg lists */
00881 
00882         it = infertypes;
00883         if (entryname->exproto)
00884                 infertypes = 1;
00885         save_argtypes(ep->arglist, &entryname->arginfo, &np->arginfo,
00886                         0, np->fvarname, STGEXT, k, np->vtype, 2);
00887         infertypes = it;
00888 }
00889 
00890 
00891 
00892  LOCAL int
00893 #ifdef KR_headers
00894 nextarg(type)
00895         int type;
00896 #else
00897 nextarg(int type)
00898 #endif
00899 {
00900         type = type;    /* shut up warning */
00901         return(lastargslot++);
00902         }
00903 
00904  LOCAL void
00905 #ifdef KR_headers
00906 dim_check(q)
00907         Namep q;
00908 #else
00909 dim_check(Namep q)
00910 #endif
00911 {
00912         register struct Dimblock *vdim = q->vdim;
00913         register expptr nelt;
00914 
00915         if(!(nelt = vdim->nelt) || !ISCONST(nelt))
00916                 dclerr("adjustable dimension on non-argument", q);
00917         else if (!ONEOF(nelt->headblock.vtype, MSKINT|MSKREAL))
00918                 bad_dimtype(q);
00919         else if (ISINT(nelt->headblock.vtype)
00920                         ? nelt->constblock.Const.ci <= 0
00921                         : nelt->constblock.Const.cd[0] <= 0.)
00922                 dclerr("nonpositive dimension", q);
00923         }
00924 
00925  LOCAL void
00926 dobss(Void)
00927 {
00928         register struct Hashentry *p;
00929         register Namep q;
00930         int qstg, qclass, qtype;
00931         Extsym *e;
00932 
00933         for(p = hashtab ; p<lasthash ; ++p)
00934                 if(q = p->varp)
00935                 {
00936                         qstg = q->vstg;
00937                         qtype = q->vtype;
00938                         qclass = q->vclass;
00939 
00940                         if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
00941                             (qclass==CLVAR && qstg==STGUNKNOWN) ) {
00942                                 if (!(q->vis_assigned | q->vimpldovar))
00943                                         warn1("local variable %s never used",
00944                                                 q->fvarname);
00945                                 }
00946                         else if(qclass==CLVAR && qstg==STGBSS)
00947                         { ; }
00948 
00949 /* Give external procedures the proper storage class */
00950 
00951                         else if(qclass==CLPROC && q->vprocclass==PEXTERNAL
00952                                         && qstg!=STGARG) {
00953                                 e = mkext(q->fvarname,addunder(q->cvarname));
00954                                 e->extstg = STGEXT;
00955                                 q->vardesc.varno = e - extsymtab;
00956                                 if (e->extype != qtype)
00957                                         changedtype(q);
00958                                 }
00959                         if(qclass==CLVAR) {
00960                             if (qstg != STGARG && q->vdim)
00961                                 dim_check(q);
00962                         } /* if qclass == CLVAR */
00963                 }
00964 
00965 }
00966 
00967 
00968  void
00969 donmlist(Void)
00970 {
00971         register struct Hashentry *p;
00972         register Namep q;
00973 
00974         for(p=hashtab; p<lasthash; ++p)
00975                 if( (q = p->varp) && q->vclass==CLNAMELIST)
00976                         namelist(q);
00977 }
00978 
00979 
00980 /* iarrlen -- Returns the size of the array in bytes, or -1 */
00981 
00982  ftnint
00983 #ifdef KR_headers
00984 iarrlen(q)
00985         register Namep q;
00986 #else
00987 iarrlen(register Namep q)
00988 #endif
00989 {
00990         ftnint leng;
00991 
00992         leng = typesize[q->vtype];
00993         if(leng <= 0)
00994                 return(-1);
00995         if(q->vdim)
00996                 if( ISICON(q->vdim->nelt) )
00997                         leng *= q->vdim->nelt->constblock.Const.ci;
00998                 else    return(-1);
00999         if(q->vleng)
01000                 if( ISICON(q->vleng) )
01001                         leng *= q->vleng->constblock.Const.ci;
01002                 else return(-1);
01003         return(leng);
01004 }
01005 
01006  void
01007 #ifdef KR_headers
01008 namelist(np)
01009         Namep np;
01010 #else
01011 namelist(Namep np)
01012 #endif
01013 {
01014         register chainp q;
01015         register Namep v;
01016         int y;
01017 
01018         if (!np->visused)
01019                 return;
01020         y = 0;
01021 
01022         for(q = np->varxptr.namelist ; q ; q = q->nextp)
01023         {
01024                 vardcl( v = (Namep) (q->datap) );
01025                 if( !ONEOF(v->vstg, MSKSTATIC) )
01026                         dclerr("may not appear in namelist", v);
01027                 else {
01028                         v->vnamelist = 1;
01029                         v->visused = 1;
01030                         v->vsave = 1;
01031                         y = 1;
01032                         }
01033         np->visused = y;
01034         }
01035 }
01036 
01037 /* docommon -- called at the end of procedure declarations, before
01038    equivalences and the procedure body */
01039 
01040  LOCAL void
01041 docommon(Void)
01042 {
01043     register Extsym *extptr;
01044     register chainp q, q1;
01045     struct Dimblock *t;
01046     expptr neltp;
01047     register Namep comvar;
01048     ftnint size;
01049     int i, k, pref, type;
01050     extern int type_pref[];
01051 
01052     for(extptr = extsymtab ; extptr<nextext ; ++extptr)
01053         if (extptr->extstg == STGCOMMON && (q = extptr->extp)) {
01054 
01055 /* If a common declaration also had a list of variables ... */
01056 
01057             q = extptr->extp = revchain(q);
01058             pref = 1;
01059             for(k = TYCHAR; q ; q = q->nextp)
01060             {
01061                 comvar = (Namep) (q->datap);
01062 
01063                 if(comvar->vdcldone == NO)
01064                     vardcl(comvar);
01065                 type = comvar->vtype;
01066                 if (pref < type_pref[type])
01067                         pref = type_pref[k = type];
01068                 if(extptr->extleng % typealign[type] != 0) {
01069                     dclerr("common alignment", comvar);
01070                     --nerr; /* don't give bad return code for this */
01071 #if 0
01072                     extptr->extleng = roundup(extptr->extleng, typealign[type]);
01073 #endif
01074                 } /* if extptr -> extleng % */
01075 
01076 /* Set the offset into the common block */
01077 
01078                 comvar->voffset = extptr->extleng;
01079                 comvar->vardesc.varno = extptr - extsymtab;
01080                 if(type == TYCHAR)
01081                         if (comvar->vleng)
01082                                 size = comvar->vleng->constblock.Const.ci;
01083                         else  {
01084                                 dclerr("character*(*) in common", comvar);
01085                                 size = 1;
01086                                 }
01087                 else
01088                         size = typesize[type];
01089                 if(t = comvar->vdim)
01090                     if( (neltp = t->nelt) && ISCONST(neltp) )
01091                         size *= neltp->constblock.Const.ci;
01092                     else
01093                         dclerr("adjustable array in common", comvar);
01094 
01095 /* Adjust the length of the common block so far */
01096 
01097                 extptr->extleng += size;
01098             } /* for */
01099 
01100             extptr->extype = k;
01101 
01102 /* Determine curno and, if new, save this identifier chain */
01103 
01104             q1 = extptr->extp;
01105             for (q = extptr->allextp, i = 0; q; i++, q = q->nextp)
01106                 if (struct_eq((chainp)q->datap, q1))
01107                         break;
01108             if (q)
01109                 extptr->curno = extptr->maxno - i;
01110             else {
01111                 extptr->curno = ++extptr->maxno;
01112                 extptr->allextp = mkchain((char *)extptr->extp,
01113                                                 extptr->allextp);
01114                 }
01115         } /* if extptr -> extstg == STGCOMMON */
01116 
01117 /* Now the hash table entries have STGCOMMON, vdcldone, voffset, and
01118    varno.  And the common block itself has its full size in extleng. */
01119 
01120 } /* docommon */
01121 
01122 
01123 /* copy_data -- copy the Namep entries so they are available even after
01124    the hash table is empty */
01125 
01126  void
01127 #ifdef KR_headers
01128 copy_data(list)
01129         chainp list;
01130 #else
01131 copy_data(chainp list)
01132 #endif
01133 {
01134     for (; list; list = list -> nextp) {
01135         Namep namep = ALLOC (Nameblock);
01136         int size, nd, i;
01137         struct Dimblock *dp;
01138 
01139         cpn(sizeof(struct Nameblock), list->datap, (char *)namep);
01140         namep->fvarname = strcpy(gmem(strlen(namep->fvarname)+1,0),
01141                 namep->fvarname);
01142         namep->cvarname = strcmp(namep->fvarname, namep->cvarname)
01143                 ? strcpy(gmem(strlen(namep->cvarname)+1,0), namep->cvarname)
01144                 : namep->fvarname;
01145         if (namep -> vleng)
01146             namep -> vleng = (expptr) cpexpr (namep -> vleng);
01147         if (namep -> vdim) {
01148             nd = namep -> vdim -> ndim;
01149             size = sizeof(int) + (3 + 2 * nd) * sizeof (expptr);
01150             dp = (struct Dimblock *) ckalloc (size);
01151             cpn(size, (char *)namep->vdim, (char *)dp);
01152             namep -> vdim = dp;
01153             dp->nelt = (expptr)cpexpr(dp->nelt);
01154             for (i = 0; i < nd; i++) {
01155                 dp -> dims[i].dimsize = (expptr) cpexpr (dp -> dims[i].dimsize);
01156             } /* for */
01157         } /* if */
01158         list -> datap = (char *) namep;
01159     } /* for */
01160 } /* copy_data */
01161 
01162 
01163 
01164  LOCAL void
01165 docomleng(Void)
01166 {
01167         register Extsym *p;
01168 
01169         for(p = extsymtab ; p < nextext ; ++p)
01170                 if(p->extstg == STGCOMMON)
01171                 {
01172                         if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
01173                             && strcmp(Blank, p->cextname) )
01174                                 warn1("incompatible lengths for common block %.60s",
01175                                     p->fextname);
01176                         if(p->maxleng < p->extleng)
01177                                 p->maxleng = p->extleng;
01178                         p->extleng = 0;
01179                 }
01180 }
01181 
01182 
01183 /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
01184 
01185  void
01186 #ifdef KR_headers
01187 frtemp(p)
01188         Addrp p;
01189 #else
01190 frtemp(Addrp p)
01191 #endif
01192 {
01193         /* put block on chain of temps to be reclaimed */
01194         holdtemps = mkchain((char *)p, holdtemps);
01195 }
01196 
01197  void
01198 freetemps(Void)
01199 {
01200         register chainp p, p1;
01201         register Addrp q;
01202         register int t;
01203 
01204         p1 = holdtemps;
01205         while(p = p1) {
01206                 q = (Addrp)p->datap;
01207                 t = q->vtype;
01208                 if (t == TYCHAR && q->varleng != 0) {
01209                         /* restore clobbered character string lengths */
01210                         frexpr(q->vleng);
01211                         q->vleng = ICON(q->varleng);
01212                         }
01213                 p1 = p->nextp;
01214                 p->nextp = templist[t];
01215                 templist[t] = p;
01216                 }
01217         holdtemps = 0;
01218         }
01219 
01220 /* allocate an automatic variable slot for each of   nelt   variables */
01221 
01222  Addrp
01223 #ifdef KR_headers
01224 autovar(nelt0, t, lengp, name)
01225         register int nelt0;
01226         register int t;
01227         expptr lengp;
01228         char *name;
01229 #else
01230 autovar(register int nelt0, register int t, expptr lengp, char *name)
01231 #endif
01232 {
01233         ftnint leng;
01234         register Addrp q;
01235         register int nelt = nelt0 > 0 ? nelt0 : 1;
01236         extern char *av_pfix[];
01237 
01238         if(t == TYCHAR)
01239                 if( ISICON(lengp) )
01240                         leng = lengp->constblock.Const.ci;
01241                 else    {
01242                         Fatal("automatic variable of nonconstant length");
01243                 }
01244         else
01245                 leng = typesize[t];
01246 
01247         q = ALLOC(Addrblock);
01248         q->tag = TADDR;
01249         q->vtype = t;
01250         if(t == TYCHAR)
01251         {
01252                 q->vleng = ICON(leng);
01253                 q->varleng = leng;
01254         }
01255         q->vstg = STGAUTO;
01256         q->ntempelt = nelt;
01257         q->isarray = (nelt > 1);
01258         q->memoffset = ICON(0);
01259 
01260         /* kludge for nls so we can have ret_val rather than ret_val_4 */
01261         if (*name == ' ')
01262                 unamstring(q, name);
01263         else {
01264                 q->uname_tag = UNAM_IDENT;
01265                 temp_name(av_pfix[t], ++autonum[t], q->user.ident);
01266                 }
01267         if (nelt0 > 0)
01268                 declare_new_addr (q);
01269         return(q);
01270 }
01271 
01272 
01273 /* Returns a temporary of the appropriate type.  Will reuse existing
01274    temporaries when possible */
01275 
01276  Addrp
01277 #ifdef KR_headers
01278 mktmpn(nelt, type, lengp)
01279         int nelt;
01280         register int type;
01281         expptr lengp;
01282 #else
01283 mktmpn(int nelt, register int type, expptr lengp)
01284 #endif
01285 {
01286         ftnint leng;
01287         chainp p, oldp;
01288         register Addrp q;
01289         extern int krparens;
01290 
01291         if(type==TYUNKNOWN || type==TYERROR)
01292                 badtype("mktmpn", type);
01293 
01294         if(type==TYCHAR)
01295                 if(lengp && ISICON(lengp) )
01296                         leng = lengp->constblock.Const.ci;
01297                 else    {
01298                         err("adjustable length");
01299                         return( (Addrp) errnode() );
01300                 }
01301         else if (type > TYCHAR || type < TYADDR) {
01302                 erri("mktmpn: unexpected type %d", type);
01303                 exit(1);
01304                 }
01305 /*
01306  * if a temporary of appropriate shape is on the templist,
01307  * remove it from the list and return it
01308  */
01309         if (krparens == 2 && ONEOF(type,M(TYREAL)|M(TYCOMPLEX)))
01310                 type++;
01311         for(oldp=CHNULL, p=templist[type];  p  ;  oldp=p, p=p->nextp)
01312         {
01313                 q = (Addrp) (p->datap);
01314                 if(q->ntempelt==nelt &&
01315                     (type!=TYCHAR || q->vleng->constblock.Const.ci==leng) )
01316                 {
01317                         if(oldp)
01318                                 oldp->nextp = p->nextp;
01319                         else
01320                                 templist[type] = p->nextp;
01321                         free( (charptr) p);
01322                         return(q);
01323                 }
01324         }
01325         q = autovar(nelt, type, lengp, "");
01326         return(q);
01327 }
01328 
01329 
01330 
01331 
01332 /* mktmp -- create new local variable; call it something like   name
01333    lengp   is taken directly, not copied */
01334 
01335  Addrp
01336 #ifdef KR_headers
01337 mktmp(type, lengp)
01338         int type;
01339         expptr lengp;
01340 #else
01341 mktmp(int type, expptr lengp)
01342 #endif
01343 {
01344         Addrp rv;
01345         /* arrange for temporaries to be recycled */
01346         /* at the end of this statement... */
01347         rv = mktmpn(1,type,lengp);
01348         frtemp((Addrp)cpexpr((expptr)rv));
01349         return rv;
01350 }
01351 
01352 /* mktmp0 omits frtemp() */
01353  Addrp
01354 #ifdef KR_headers
01355 mktmp0(type, lengp)
01356         int type;
01357         expptr lengp;
01358 #else
01359 mktmp0(int type, expptr lengp)
01360 #endif
01361 {
01362         Addrp rv;
01363         /* arrange for temporaries to be recycled */
01364         /* when this Addrp is freed */
01365         rv = mktmpn(1,type,lengp);
01366         rv->istemp = YES;
01367         return rv;
01368 }
01369 
01370 /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
01371 
01372 /* comblock -- Declare a new common block.  Input parameters name the block;
01373    s   will be NULL if the block is unnamed */
01374 
01375  Extsym *
01376 #ifdef KR_headers
01377 comblock(s)
01378         register char *s;
01379 #else
01380 comblock(register char *s)
01381 #endif
01382 {
01383         Extsym *p;
01384         register char *t;
01385         register int c, i;
01386         char cbuf[256], *s0;
01387 
01388 /* Give the unnamed common block a unique name */
01389 
01390         if(*s == 0)
01391                 p = mkext1(s0 = Blank, Blank);
01392         else {
01393                 s0 = s;
01394                 t = cbuf;
01395                 for(i = 0; c = *t = *s++; t++)
01396                         if (c == '_')
01397                                 i = 1;
01398                 if (i)
01399                         *t++ = '_';
01400                 t[0] = '_';
01401                 t[1] = 0;
01402                 p = mkext1(s0,cbuf);
01403                 }
01404         if(p->extstg == STGUNKNOWN)
01405                 p->extstg = STGCOMMON;
01406         else if(p->extstg != STGCOMMON)
01407         {
01408                 errstr("%.52s cannot be a common block: it is a subprogram.",
01409                         s0);
01410                 return(0);
01411         }
01412 
01413         return( p );
01414 }
01415 
01416 
01417 /* incomm -- add a new variable to a common declaration */
01418 
01419  void
01420 #ifdef KR_headers
01421 incomm(c, v)
01422         Extsym *c;
01423         Namep v;
01424 #else
01425 incomm(Extsym *c, Namep v)
01426 #endif
01427 {
01428         if (!c)
01429                 return;
01430         if(v->vstg != STGUNKNOWN && !v->vimplstg)
01431                 dclerr(v->vstg == STGARG
01432                         ? "dummy arguments cannot be in common"
01433                         : "incompatible common declaration", v);
01434         else
01435         {
01436                 v->vstg = STGCOMMON;
01437                 c->extp = mkchain((char *)v, c->extp);
01438         }
01439 }
01440 
01441 
01442 
01443 
01444 /* settype -- set the type or storage class of a Namep object.  If
01445    v -> vstg == STGUNKNOWN && type < 0,   attempt to reset vstg to be
01446    -type.  This function will not change any earlier definitions in   v,
01447    in will only attempt to fill out more information give the other params */
01448 
01449  void
01450 #ifdef KR_headers
01451 settype(v, type, length)
01452         register Namep v;
01453         register int type;
01454         register ftnint length;
01455 #else
01456 settype(register Namep v, register int type, register ftnint length)
01457 #endif
01458 {
01459         int type1;
01460 
01461         if(type == TYUNKNOWN)
01462                 return;
01463 
01464         if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
01465         {
01466                 v->vtype = TYSUBR;
01467                 frexpr(v->vleng);
01468                 v->vleng = 0;
01469                 v->vimpltype = 0;
01470         }
01471         else if(type < 0)       /* storage class set */
01472         {
01473                 if(v->vstg == STGUNKNOWN)
01474                         v->vstg = - type;
01475                 else if(v->vstg != -type)
01476                         dclerr("incompatible storage declarations", v);
01477         }
01478         else if(v->vtype == TYUNKNOWN
01479                 || v->vtype != type
01480                         && (v->vimpltype || v->vinftype || v->vinfproc))
01481         {
01482                 if( (v->vtype = lengtype(type, length))==TYCHAR )
01483                         if (length>=0)
01484                                 v->vleng = ICON(length);
01485                         else if (parstate >= INDATA)
01486                                 v->vleng = ICON(1);     /* avoid a memory fault */
01487                 v->vimpltype = 0;
01488                 v->vinftype = 0; /* 19960709 */
01489                 v->vinfproc = 0; /* 19960709 */
01490 
01491                 if (v->vclass == CLPROC) {
01492                         if (v->vstg == STGEXT
01493                          && (type1 = extsymtab[v->vardesc.varno].extype)
01494                          &&  type1 != v->vtype)
01495                                 changedtype(v);
01496                         else if (v->vprocclass == PTHISPROC
01497                                         && (parstate >= INDATA
01498                                                 || procclass == CLMAIN)
01499                                         && !xretslot[type]) {
01500                                 xretslot[type] = autovar(ONEOF(type,
01501                                         MSKCOMPLEX|MSKCHAR) ? 0 : 1, type,
01502                                         v->vleng, " ret_val");
01503                                 if (procclass == CLMAIN)
01504                                         errstr(
01505                                 "illegal use of %.60s (main program name)",
01506                                         v->fvarname);
01507                                 /* not completely right, but enough to */
01508                                 /* avoid memory faults; we won't */
01509                                 /* emit any C as we have illegal Fortran */
01510                                 }
01511                         }
01512         }
01513         else if(v->vtype != type && v->vtype != lengtype(type, length)) {
01514  incompat:
01515                 dclerr("incompatible type declarations", v);
01516                 }
01517         else if (type==TYCHAR)
01518                 if (v->vleng && v->vleng->constblock.Const.ci != length)
01519                         goto incompat;
01520                 else if (parstate >= INDATA)
01521                         v->vleng = ICON(1);     /* avoid a memory fault */
01522 }
01523 
01524 
01525 
01526 
01527 
01528 /* lengtype -- returns the proper compiler type, given input of Fortran
01529    type and length specifier */
01530 
01531  int
01532 #ifdef KR_headers
01533 lengtype(type, len)
01534         register int type;
01535         ftnint len;
01536 #else
01537 lengtype(register int type, ftnint len)
01538 #endif
01539 {
01540         register int length = (int)len;
01541         switch(type)
01542         {
01543         case TYREAL:
01544                 if(length == typesize[TYDREAL])
01545                         return(TYDREAL);
01546                 if(length == typesize[TYREAL])
01547                         goto ret;
01548                 break;
01549 
01550         case TYCOMPLEX:
01551                 if(length == typesize[TYDCOMPLEX])
01552                         return(TYDCOMPLEX);
01553                 if(length == typesize[TYCOMPLEX])
01554                         goto ret;
01555                 break;
01556 
01557         case TYINT1:
01558         case TYSHORT:
01559         case TYDREAL:
01560         case TYDCOMPLEX:
01561         case TYCHAR:
01562         case TYLOGICAL1:
01563         case TYLOGICAL2:
01564         case TYUNKNOWN:
01565         case TYSUBR:
01566         case TYERROR:
01567 #ifdef TYQUAD
01568         case TYQUAD:
01569 #endif
01570                 goto ret;
01571 
01572         case TYLOGICAL:
01573                 switch(length) {
01574                         case 0: return tylog;
01575                         case 1: return TYLOGICAL1;
01576                         case 2: return TYLOGICAL2;
01577                         case 4: goto ret;
01578                         }
01579                 break;
01580 
01581         case TYLONG:
01582                 if(length == 0)
01583                         return(tyint);
01584                 if (length == 1)
01585                         return TYINT1;
01586                 if(length == typesize[TYSHORT])
01587                         return(TYSHORT);
01588 #ifdef TYQUAD
01589                 if(length == typesize[TYQUAD] && use_tyquad)
01590                         return(TYQUAD);
01591 #endif
01592                 if(length == typesize[TYLONG])
01593                         goto ret;
01594                 break;
01595         default:
01596                 badtype("lengtype", type);
01597         }
01598 
01599         if(len != 0)
01600                 err("incompatible type-length combination");
01601 
01602 ret:
01603         return(type);
01604 }
01605 
01606 
01607 
01608 
01609 
01610 /* setintr -- Set Intrinsic function */
01611 
01612  void
01613 #ifdef KR_headers
01614 setintr(v)
01615         register Namep v;
01616 #else
01617 setintr(register Namep v)
01618 #endif
01619 {
01620         int k;
01621 
01622         if(k = intrfunct(v->fvarname)) {
01623                 if ((*(struct Intrpacked *)&k).f4)
01624                         if (noextflag)
01625                                 goto unknown;
01626                         else
01627                                 dcomplex_seen++;
01628                 v->vardesc.varno = k;
01629                 }
01630         else {
01631  unknown:
01632                 dclerr("unknown intrinsic function", v);
01633                 return;
01634                 }
01635         if(v->vstg == STGUNKNOWN)
01636                 v->vstg = STGINTR;
01637         else if(v->vstg!=STGINTR)
01638                 dclerr("incompatible use of intrinsic function", v);
01639         if(v->vclass==CLUNKNOWN)
01640                 v->vclass = CLPROC;
01641         if(v->vprocclass == PUNKNOWN)
01642                 v->vprocclass = PINTRINSIC;
01643         else if(v->vprocclass != PINTRINSIC)
01644                 dclerr("invalid intrinsic declaration", v);
01645 }
01646 
01647 
01648 
01649 /* setext -- Set External declaration -- assume that unknowns will become
01650    procedures */
01651 
01652  void
01653 #ifdef KR_headers
01654 setext(v)
01655         register Namep v;
01656 #else
01657 setext(register Namep v)
01658 #endif
01659 {
01660         if(v->vclass == CLUNKNOWN)
01661                 v->vclass = CLPROC;
01662         else if(v->vclass != CLPROC)
01663                 dclerr("invalid external declaration", v);
01664 
01665         if(v->vprocclass == PUNKNOWN)
01666                 v->vprocclass = PEXTERNAL;
01667         else if(v->vprocclass != PEXTERNAL)
01668                 dclerr("invalid external declaration", v);
01669 } /* setext */
01670 
01671 
01672 
01673 
01674 /* create dimensions block for array variable */
01675 
01676  void
01677 #ifdef KR_headers
01678 setbound(v, nd, dims)
01679         register Namep v;
01680         int nd;
01681         struct Dims *dims;
01682 #else
01683 setbound(Namep v, int nd, struct Dims *dims)
01684 #endif
01685 {
01686         expptr q, q0, t;
01687         struct Dimblock *p;
01688         int i;
01689         extern chainp new_vars;
01690         char buf[256];
01691 
01692         if(v->vclass == CLUNKNOWN)
01693                 v->vclass = CLVAR;
01694         else if(v->vclass != CLVAR)
01695         {
01696                 dclerr("only variables may be arrays", v);
01697                 return;
01698         }
01699 
01700         v->vdim = p = (struct Dimblock *)
01701             ckalloc( sizeof(int) + (3+2*nd)*sizeof(expptr) );
01702         p->ndim = nd--;
01703         p->nelt = ICON(1);
01704         doin_setbound = 1;
01705 
01706         if (noextflag)
01707                 for(i = 0; i <= nd; i++)
01708                         if (((q = dims[i].lb) && !ISINT(q->headblock.vtype))
01709                          || ((q = dims[i].ub) && !ISINT(q->headblock.vtype))) {
01710                                 sprintf(buf, "dimension %d of %s is not an integer.",
01711                                         i+1, v->fvarname);
01712                                 errext(buf);
01713                                 break;
01714                                 }
01715 
01716         for(i = 0; i <= nd; i++) {
01717                 if (((q = dims[i].lb) && !ISINT(q->headblock.vtype)))
01718                         dims[i].lb = mkconv(TYINT, q);
01719                 if (((q = dims[i].ub) && !ISINT(q->headblock.vtype)))
01720                         dims[i].ub = mkconv(TYINT, q);
01721                 }
01722 
01723         for(i = 0; i <= nd; ++i)
01724         {
01725                 if( (q = dims[i].ub) == NULL)
01726                 {
01727                         if(i == nd)
01728                         {
01729                                 frexpr(p->nelt);
01730                                 p->nelt = NULL;
01731                         }
01732                         else
01733                                 err("only last bound may be asterisk");
01734                         p->dims[i].dimsize = ICON(1);
01735                         p->dims[i].dimexpr = NULL;
01736                 }
01737                 else
01738                 {
01739 
01740                         if(dims[i].lb)
01741                         {
01742                                 q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
01743                                 q = mkexpr(OPPLUS, q, ICON(1) );
01744                         }
01745                         if( ISCONST(q) )
01746                         {
01747                                 p->dims[i].dimsize = q;
01748                                 p->dims[i].dimexpr = (expptr) PNULL;
01749                         }
01750                         else {
01751                                 sprintf(buf, " %s_dim%d", v->fvarname, i+1);
01752                                 p->dims[i].dimsize = (expptr)
01753                                         autovar(1, tyint, EXNULL, buf);
01754                                 p->dims[i].dimexpr = q;
01755                                 if (i == nd)
01756                                         v->vlastdim = new_vars;
01757                                 v->vdimfinish = 1;
01758                         }
01759                         if(p->nelt)
01760                                 p->nelt = mkexpr(OPSTAR, p->nelt,
01761                                     cpexpr(p->dims[i].dimsize) );
01762                 }
01763         }
01764 
01765         q = dims[nd].lb;
01766         q0 = 0;
01767         if(q == NULL)
01768                 q = q0 = ICON(1);
01769 
01770         for(i = nd-1 ; i>=0 ; --i)
01771         {
01772                 t = dims[i].lb;
01773                 if(t == NULL)
01774                         t = ICON(1);
01775                 if(p->dims[i].dimsize) {
01776                         if (q == q0) {
01777                                 q0 = 0;
01778                                 frexpr(q);
01779                                 q = cpexpr(p->dims[i].dimsize);
01780                                 }
01781                         else
01782                                 q = mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q);
01783                         q = mkexpr(OPPLUS, t, q);
01784                         }
01785         }
01786 
01787         if( ISCONST(q) )
01788         {
01789                 p->baseoffset = q;
01790                 p->basexpr = NULL;
01791         }
01792         else
01793         {
01794                 sprintf(buf, " %s_offset", v->fvarname);
01795                 p->baseoffset = (expptr) autovar(1, tyint, EXNULL, buf);
01796                 p->basexpr = q;
01797                 v->vdimfinish = 1;
01798         }
01799         doin_setbound = 0;
01800 }
01801 
01802 
01803  void
01804 #ifdef KR_headers
01805 wr_abbrevs(outfile, function_head, vars)
01806         FILE *outfile;
01807         int function_head;
01808         chainp vars;
01809 #else
01810 wr_abbrevs(FILE *outfile, int function_head, chainp vars)
01811 #endif
01812 {
01813     for (; vars; vars = vars -> nextp) {
01814         Namep name = (Namep) vars -> datap;
01815         if (!name->visused)
01816                 continue;
01817 
01818         if (function_head)
01819             nice_printf (outfile, "#define ");
01820         else
01821             nice_printf (outfile, "#undef ");
01822         out_name (outfile, name);
01823 
01824         if (function_head) {
01825             Extsym *comm = &extsymtab[name -> vardesc.varno];
01826 
01827             nice_printf (outfile, " (");
01828             extern_out (outfile, comm);
01829             nice_printf (outfile, "%d.", comm->curno);
01830             nice_printf (outfile, "%s)", name->cvarname);
01831         } /* if function_head */
01832         nice_printf (outfile, "\n");
01833     } /* for */
01834 } /* wr_abbrevs */

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