|
|
1.1 ! root 1: /**************************************************************** ! 2: Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore. ! 3: ! 4: Permission to use, copy, modify, and distribute this software ! 5: and its documentation for any purpose and without fee is hereby ! 6: granted, provided that the above copyright notice appear in all ! 7: copies and that both that the copyright notice and this ! 8: permission notice and warranty disclaimer appear in supporting ! 9: documentation, and that the names of AT&T Bell Laboratories or ! 10: Bellcore or any of their entities not be used in advertising or ! 11: publicity pertaining to distribution of the software without ! 12: specific, written prior permission. ! 13: ! 14: AT&T and Bellcore disclaim all warranties with regard to this ! 15: software, including all implied warranties of merchantability ! 16: and fitness. In no event shall AT&T or Bellcore be liable for ! 17: any special, indirect or consequential damages or any damages ! 18: whatsoever resulting from loss of use, data or profits, whether ! 19: in an action of contract, negligence or other tortious action, ! 20: arising out of or in connection with the use or performance of ! 21: this software. ! 22: ****************************************************************/ ! 23: ! 24: #include "defs.h" ! 25: #include "names.h" ! 26: #include "output.h" ! 27: #include "p1defs.h" ! 28: ! 29: #define EXNULL (union Expression *)0 ! 30: ! 31: LOCAL dobss(), docomleng(), docommon(), doentry(), ! 32: epicode(), nextarg(), retval(); ! 33: ! 34: static char Blank[] = BLANKCOMMON; ! 35: ! 36: static char *postfix[] = { "g", "h", "i", ! 37: #ifdef TYQUAD ! 38: "j", ! 39: #endif ! 40: "r", "d", "c", "z", "g", "h", "i" }; ! 41: ! 42: chainp new_procs; ! 43: int prev_proc, proc_argchanges, proc_protochanges; ! 44: ! 45: void ! 46: changedtype(q) ! 47: Namep q; ! 48: { ! 49: char buf[200]; ! 50: int qtype, type1; ! 51: register Extsym *e; ! 52: Argtypes *at; ! 53: ! 54: if (q->vtypewarned) ! 55: return; ! 56: q->vtypewarned = 1; ! 57: qtype = q->vtype; ! 58: e = &extsymtab[q->vardesc.varno]; ! 59: if (!(at = e->arginfo)) { ! 60: if (!e->exused) ! 61: return; ! 62: } ! 63: else if (at->changes & 2 && qtype != TYUNKNOWN && !at->defined) ! 64: proc_protochanges++; ! 65: type1 = e->extype; ! 66: if (type1 == TYUNKNOWN) ! 67: return; ! 68: if (qtype == TYUNKNOWN) ! 69: /* e.g., ! 70: subroutine foo ! 71: end ! 72: external foo ! 73: call goo(foo) ! 74: end ! 75: */ ! 76: return; ! 77: sprintf(buf, "%.90s: inconsistent declarations:\n\ ! 78: here %s%s, previously %s%s.", q->fvarname, ftn_types[qtype], ! 79: qtype == TYSUBR ? "" : " function", ! 80: ftn_types[type1], type1 == TYSUBR ? "" : " function"); ! 81: warn(buf); ! 82: } ! 83: ! 84: void ! 85: unamstring(q, s) ! 86: register Addrp q; ! 87: register char *s; ! 88: { ! 89: register int k; ! 90: register char *t; ! 91: ! 92: k = strlen(s); ! 93: if (k < IDENT_LEN) { ! 94: q->uname_tag = UNAM_IDENT; ! 95: t = q->user.ident; ! 96: } ! 97: else { ! 98: q->uname_tag = UNAM_CHARP; ! 99: q->user.Charp = t = mem(k+1, 0); ! 100: } ! 101: strcpy(t, s); ! 102: } ! 103: ! 104: static void ! 105: fix_entry_returns() /* for multiple entry points */ ! 106: { ! 107: Addrp a; ! 108: int i; ! 109: struct Entrypoint *e; ! 110: Namep np; ! 111: ! 112: e = entries = (struct Entrypoint *)revchain((chainp)entries); ! 113: allargs = revchain(allargs); ! 114: if (!multitype) ! 115: return; ! 116: ! 117: /* TYLOGICAL should have been turned into TYLONG or TYSHORT by now */ ! 118: ! 119: for(i = TYINT1; i <= TYLOGICAL; i++) ! 120: if (a = xretslot[i]) ! 121: sprintf(a->user.ident, "(*ret_val).%s", ! 122: postfix[i-TYINT1]); ! 123: ! 124: do { ! 125: np = e->enamep; ! 126: switch(np->vtype) { ! 127: case TYINT1: ! 128: case TYSHORT: ! 129: case TYLONG: ! 130: #ifdef TYQUAD ! 131: case TYQUAD: ! 132: #endif ! 133: case TYREAL: ! 134: case TYDREAL: ! 135: case TYCOMPLEX: ! 136: case TYDCOMPLEX: ! 137: case TYLOGICAL1: ! 138: case TYLOGICAL2: ! 139: case TYLOGICAL: ! 140: np->vstg = STGARG; ! 141: } ! 142: } ! 143: while(e = e->entnextp); ! 144: } ! 145: ! 146: static void ! 147: putentries(outfile) /* put out wrappers for multiple entries */ ! 148: FILE *outfile; ! 149: { ! 150: char base[IDENT_LEN]; ! 151: struct Entrypoint *e; ! 152: Namep *A, *Ae, *Ae1, **Alp, *a, **a1, np; ! 153: chainp args, lengths, length_comp(); ! 154: void listargs(), list_arg_types(); ! 155: int i, k, mt, nL, type; ! 156: extern char *dfltarg[], **dfltproc; ! 157: ! 158: e = entries; ! 159: if (!e->enamep) /* only possible with erroneous input */ ! 160: return; ! 161: nL = (nallargs + nallchargs) * sizeof(Namep *); ! 162: A = (Namep *)ckalloc(nL + nallargs*sizeof(Namep **)); ! 163: Ae = A + nallargs; ! 164: Alp = (Namep **)(Ae1 = Ae + nallchargs); ! 165: i = k = 0; ! 166: for(a1 = Alp, args = allargs; args; a1++, args = args->nextp) { ! 167: np = (Namep)args->datap; ! 168: if (np->vtype == TYCHAR && np->vclass != CLPROC) ! 169: *a1 = &Ae[i++]; ! 170: } ! 171: ! 172: mt = multitype; ! 173: multitype = 0; ! 174: sprintf(base, "%s0_", e->enamep->cvarname); ! 175: do { ! 176: np = e->enamep; ! 177: lengths = length_comp(e, 0); ! 178: proctype = type = np->vtype; ! 179: if (protofile) ! 180: protowrite(protofile, type, np->cvarname, e, lengths); ! 181: nice_printf(outfile, "\n%s ", c_type_decl(type, 1)); ! 182: nice_printf(outfile, "%s", np->cvarname); ! 183: if (!Ansi) { ! 184: listargs(outfile, e, 0, lengths); ! 185: nice_printf(outfile, "\n"); ! 186: } ! 187: list_arg_types(outfile, e, lengths, 0, "\n"); ! 188: nice_printf(outfile, "{\n"); ! 189: frchain(&lengths); ! 190: next_tab(outfile); ! 191: if (mt) ! 192: nice_printf(outfile, ! 193: "Multitype ret_val;\n%s(%d, &ret_val", ! 194: base, k); /*)*/ ! 195: else if (ISCOMPLEX(type)) ! 196: nice_printf(outfile, "%s(%d,%s", base, k, ! 197: xretslot[type]->user.ident); /*)*/ ! 198: else if (type == TYCHAR) ! 199: nice_printf(outfile, ! 200: "%s(%d, ret_val, ret_val_len", base, k); /*)*/ ! 201: else ! 202: nice_printf(outfile, "return %s(%d", base, k); /*)*/ ! 203: k++; ! 204: memset((char *)A, 0, nL); ! 205: for(args = e->arglist; args; args = args->nextp) { ! 206: np = (Namep)args->datap; ! 207: A[np->argno] = np; ! 208: if (np->vtype == TYCHAR && np->vclass != CLPROC) ! 209: *Alp[np->argno] = np; ! 210: } ! 211: args = allargs; ! 212: for(a = A; a < Ae; a++, args = args->nextp) ! 213: nice_printf(outfile, ", %s", (np = *a) ! 214: ? np->cvarname ! 215: : ((Namep)args->datap)->vclass == CLPROC ! 216: ? dfltproc[((Namep)args->datap)->vtype] ! 217: : dfltarg[((Namep)args->datap)->vtype]); ! 218: for(; a < Ae1; a++) ! 219: if (np = *a) ! 220: nice_printf(outfile, ", %s_len", np->fvarname); ! 221: else ! 222: nice_printf(outfile, ", (ftnint)0"); ! 223: nice_printf(outfile, /*(*/ ");\n"); ! 224: if (mt) { ! 225: if (type == TYCOMPLEX) ! 226: nice_printf(outfile, ! 227: "r_v->r = ret_val.c.r; r_v->i = ret_val.c.i;\nreturn 0;\n"); ! 228: else if (type == TYDCOMPLEX) ! 229: nice_printf(outfile, ! 230: "r_v->r = ret_val.z.r; r_v->i = ret_val.z.i;\nreturn 0;\n"); ! 231: else nice_printf(outfile, "return ret_val.%s;\n", ! 232: postfix[type-TYINT1]); ! 233: } ! 234: nice_printf(outfile, "}\n"); ! 235: prev_tab(outfile); ! 236: } ! 237: while(e = e->entnextp); ! 238: free((char *)A); ! 239: } ! 240: ! 241: static void ! 242: entry_goto(outfile) ! 243: FILEP outfile; ! 244: { ! 245: struct Entrypoint *e = entries; ! 246: int k = 0; ! 247: ! 248: nice_printf(outfile, "switch(n__) {\n"); ! 249: next_tab(outfile); ! 250: while(e = e->entnextp) ! 251: nice_printf(outfile, "case %d: goto %s;\n", ++k, ! 252: user_label((long)(extsymtab - e->entryname - 1))); ! 253: nice_printf(outfile, "}\n\n"); ! 254: prev_tab(outfile); ! 255: } ! 256: ! 257: /* start a new procedure */ ! 258: ! 259: newproc() ! 260: { ! 261: if(parstate != OUTSIDE) ! 262: { ! 263: execerr("missing end statement", CNULL); ! 264: endproc(); ! 265: } ! 266: ! 267: parstate = INSIDE; ! 268: procclass = CLMAIN; /* default */ ! 269: } ! 270: ! 271: static void ! 272: zap_changes() ! 273: { ! 274: register chainp cp; ! 275: register Argtypes *at; ! 276: ! 277: /* arrange to get correct count of prototypes that would ! 278: change by running f2c again */ ! 279: ! 280: if (prev_proc && proc_argchanges) ! 281: proc_protochanges++; ! 282: prev_proc = proc_argchanges = 0; ! 283: for(cp = new_procs; cp; cp = cp->nextp) ! 284: if (at = ((Namep)cp->datap)->arginfo) ! 285: at->changes &= ~1; ! 286: frchain(&new_procs); ! 287: } ! 288: ! 289: /* end of procedure. generate variables, epilogs, and prologs */ ! 290: ! 291: endproc() ! 292: { ! 293: struct Labelblock *lp; ! 294: Extsym *ext; ! 295: ! 296: if(parstate < INDATA) ! 297: enddcl(); ! 298: if(ctlstack >= ctls) ! 299: err("DO loop or BLOCK IF not closed"); ! 300: for(lp = labeltab ; lp < labtabend ; ++lp) ! 301: if(lp->stateno!=0 && lp->labdefined==NO) ! 302: errstr("missing statement label %s", ! 303: convic(lp->stateno) ); ! 304: ! 305: /* Save copies of the common variables in extptr -> allextp */ ! 306: ! 307: for (ext = extsymtab; ext < nextext; ext++) ! 308: if (ext -> extstg == STGCOMMON && ext -> extp) { ! 309: extern int usedefsforcommon; ! 310: ! 311: /* Write out the abbreviations for common block reference */ ! 312: ! 313: copy_data (ext -> extp); ! 314: if (usedefsforcommon) { ! 315: wr_abbrevs (c_file, 1, ext -> extp); ! 316: ext -> used_here = 1; ! 317: } ! 318: else ! 319: ext -> extp = CHNULL; ! 320: ! 321: } ! 322: ! 323: if (nentry > 1) ! 324: fix_entry_returns(); ! 325: epicode(); ! 326: donmlist(); ! 327: dobss(); ! 328: start_formatting (); ! 329: if (nentry > 1) ! 330: putentries(c_file); ! 331: ! 332: zap_changes(); ! 333: procinit(); /* clean up for next procedure */ ! 334: } ! 335: ! 336: ! 337: ! 338: /* End of declaration section of procedure. Allocate storage. */ ! 339: ! 340: enddcl() ! 341: { ! 342: register struct Entrypoint *ep; ! 343: struct Entrypoint *ep0; ! 344: extern void freetemps(); ! 345: chainp cp; ! 346: extern char *err_proc; ! 347: static char comblks[] = "common blocks"; ! 348: ! 349: err_proc = comblks; ! 350: docommon(); ! 351: ! 352: /* Now the hash table entries for fields of common blocks have STGCOMMON, ! 353: vdcldone, voffset, and varno. And the common blocks themselves have ! 354: their full sizes in extleng. */ ! 355: ! 356: err_proc = "equivalences"; ! 357: doequiv(); ! 358: ! 359: err_proc = comblks; ! 360: docomleng(); ! 361: ! 362: /* This implies that entry points in the declarations are buffered in ! 363: entries but not written out */ ! 364: ! 365: err_proc = "entries"; ! 366: if (ep = ep0 = (struct Entrypoint *)revchain((chainp)entries)) { ! 367: /* entries could be 0 in case of an error */ ! 368: do doentry(ep); ! 369: while(ep = ep->entnextp); ! 370: entries = (struct Entrypoint *)revchain((chainp)ep0); ! 371: } ! 372: ! 373: err_proc = 0; ! 374: parstate = INEXEC; ! 375: p1put(P1_PROCODE); ! 376: freetemps(); ! 377: if (earlylabs) { ! 378: for(cp = earlylabs = revchain(earlylabs); cp; cp = cp->nextp) ! 379: p1_label((long)cp->datap); ! 380: frchain(&earlylabs); ! 381: } ! 382: } ! 383: ! 384: /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */ ! 385: ! 386: /* Main program or Block data */ ! 387: ! 388: startproc(progname, class) ! 389: Extsym * progname; ! 390: int class; ! 391: { ! 392: register struct Entrypoint *p; ! 393: ! 394: p = ALLOC(Entrypoint); ! 395: if(class == CLMAIN) { ! 396: puthead(CNULL, CLMAIN); ! 397: if (progname) ! 398: strcpy (main_alias, progname->cextname); ! 399: } else ! 400: puthead(CNULL, CLBLOCK); ! 401: if(class == CLMAIN) ! 402: newentry( mkname(" MAIN"), 0 )->extinit = 1; ! 403: p->entryname = progname; ! 404: entries = p; ! 405: ! 406: procclass = class; ! 407: fprintf(diagfile, " %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") ); ! 408: if(progname) { ! 409: fprintf(diagfile, " %s", progname->fextname); ! 410: procname = progname->cextname; ! 411: } ! 412: fprintf(diagfile, ":\n"); ! 413: fflush(diagfile); ! 414: } ! 415: ! 416: /* subroutine or function statement */ ! 417: ! 418: Extsym *newentry(v, substmsg) ! 419: register Namep v; ! 420: int substmsg; ! 421: { ! 422: register Extsym *p; ! 423: char buf[128], badname[64]; ! 424: static int nbad = 0; ! 425: static char already[] = "external name already used"; ! 426: ! 427: p = mkext(v->fvarname, addunder(v->cvarname)); ! 428: ! 429: if(p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) ) ! 430: { ! 431: sprintf(badname, "%s_bad%d", v->fvarname, ++nbad); ! 432: if (substmsg) { ! 433: sprintf(buf,"%s\n\tsubstituting \"%s\"", ! 434: already, badname); ! 435: dclerr(buf, v); ! 436: } ! 437: else ! 438: dclerr(already, v); ! 439: p = mkext(v->fvarname, badname); ! 440: } ! 441: v->vstg = STGAUTO; ! 442: v->vprocclass = PTHISPROC; ! 443: v->vclass = CLPROC; ! 444: if (p->extstg == STGEXT) ! 445: prev_proc = 1; ! 446: else ! 447: p->extstg = STGEXT; ! 448: p->extinit = YES; ! 449: v->vardesc.varno = p - extsymtab; ! 450: return(p); ! 451: } ! 452: ! 453: ! 454: entrypt(class, type, length, entry, args) ! 455: int class, type; ! 456: ftnint length; ! 457: Extsym *entry; ! 458: chainp args; ! 459: { ! 460: register Namep q; ! 461: register struct Entrypoint *p; ! 462: ! 463: if(class != CLENTRY) ! 464: puthead( procname = entry->cextname, class); ! 465: else ! 466: fprintf(diagfile, " entry "); ! 467: fprintf(diagfile, " %s:\n", entry->fextname); ! 468: fflush(diagfile); ! 469: q = mkname(entry->fextname); ! 470: if (type == TYSUBR) ! 471: q->vstg = STGEXT; ! 472: ! 473: type = lengtype(type, length); ! 474: if(class == CLPROC) ! 475: { ! 476: procclass = CLPROC; ! 477: proctype = type; ! 478: procleng = type == TYCHAR ? length : 0; ! 479: } ! 480: ! 481: p = ALLOC(Entrypoint); ! 482: ! 483: p->entnextp = entries; ! 484: entries = p; ! 485: ! 486: p->entryname = entry; ! 487: p->arglist = revchain(args); ! 488: p->enamep = q; ! 489: ! 490: if(class == CLENTRY) ! 491: { ! 492: class = CLPROC; ! 493: if(proctype == TYSUBR) ! 494: type = TYSUBR; ! 495: } ! 496: ! 497: q->vclass = class; ! 498: q->vprocclass = 0; ! 499: settype(q, type, length); ! 500: q->vprocclass = PTHISPROC; ! 501: /* hold all initial entry points till end of declarations */ ! 502: if(parstate >= INDATA) ! 503: doentry(p); ! 504: } ! 505: ! 506: /* generate epilogs */ ! 507: ! 508: /* epicode -- write out the proper function return mechanism at the end of ! 509: the procedure declaration. Handles multiple return value types, as ! 510: well as cooercion into the proper value */ ! 511: ! 512: LOCAL epicode() ! 513: { ! 514: extern int lastwasbranch; ! 515: ! 516: if(procclass==CLPROC) ! 517: { ! 518: if(proctype==TYSUBR) ! 519: { ! 520: ! 521: /* Return a zero only when the alternate return mechanism has been ! 522: specified in the function header */ ! 523: ! 524: if ((substars || Ansi) && lastwasbranch != YES) ! 525: p1_subr_ret (ICON(0)); ! 526: } ! 527: else if (!multitype && lastwasbranch != YES) ! 528: retval(proctype); ! 529: } ! 530: else if (procclass == CLMAIN && Ansi && lastwasbranch != YES) ! 531: p1_subr_ret (ICON(0)); ! 532: lastwasbranch = NO; ! 533: } ! 534: ! 535: ! 536: /* generate code to return value of type t */ ! 537: ! 538: LOCAL retval(t) ! 539: register int t; ! 540: { ! 541: register Addrp p; ! 542: ! 543: switch(t) ! 544: { ! 545: case TYCHAR: ! 546: case TYCOMPLEX: ! 547: case TYDCOMPLEX: ! 548: break; ! 549: ! 550: case TYLOGICAL: ! 551: t = tylogical; ! 552: case TYINT1: ! 553: case TYADDR: ! 554: case TYSHORT: ! 555: case TYLONG: ! 556: #ifdef TYQUAD ! 557: case TYQUAD: ! 558: #endif ! 559: case TYREAL: ! 560: case TYDREAL: ! 561: case TYLOGICAL1: ! 562: case TYLOGICAL2: ! 563: p = (Addrp) cpexpr((expptr)retslot); ! 564: p->vtype = t; ! 565: p1_subr_ret (mkconv (t, fixtype((expptr)p))); ! 566: break; ! 567: ! 568: default: ! 569: badtype("retval", t); ! 570: } ! 571: } ! 572: ! 573: ! 574: /* Do parameter adjustments */ ! 575: ! 576: procode(outfile) ! 577: FILE *outfile; ! 578: { ! 579: prolog(outfile, allargs); ! 580: ! 581: if (nentry > 1) ! 582: entry_goto(outfile); ! 583: } ! 584: ! 585: /* Finish bound computations now that all variables are declared. ! 586: * This used to be in setbound(), but under -u the following incurred ! 587: * an erroneous error message: ! 588: * subroutine foo(x,n) ! 589: * real x(n) ! 590: * integer n ! 591: */ ! 592: ! 593: static void ! 594: dim_finish(v) ! 595: Namep v; ! 596: { ! 597: register struct Dimblock *p; ! 598: register expptr q; ! 599: register int i, nd; ! 600: extern expptr make_int_expr(); ! 601: ! 602: p = v->vdim; ! 603: v->vdimfinish = 0; ! 604: nd = p->ndim; ! 605: doin_setbound = 1; ! 606: for(i = 0; i < nd; i++) ! 607: if (q = p->dims[i].dimexpr) { ! 608: q = p->dims[i].dimexpr = make_int_expr(putx(fixtype(q))); ! 609: if (!ONEOF(q->headblock.vtype, MSKINT|MSKREAL)) ! 610: errstr("bad dimension type for %.70s", ! 611: v->fvarname); ! 612: } ! 613: if (q = p->basexpr) ! 614: p->basexpr = make_int_expr(putx(fixtype(q))); ! 615: doin_setbound = 0; ! 616: } ! 617: ! 618: static void ! 619: duparg(q) ! 620: Namep q; ! 621: { errstr("duplicate argument %.80s", q->fvarname); } ! 622: ! 623: /* ! 624: manipulate argument lists (allocate argument slot positions) ! 625: * keep track of return types and labels ! 626: */ ! 627: ! 628: LOCAL doentry(ep) ! 629: struct Entrypoint *ep; ! 630: { ! 631: register int type; ! 632: register Namep np; ! 633: chainp p, p1; ! 634: register Namep q; ! 635: Addrp mkarg(), rs; ! 636: int it, k; ! 637: extern char dflttype[26]; ! 638: Extsym *entryname = ep->entryname; ! 639: ! 640: if (++nentry > 1) ! 641: p1_label((long)(extsymtab - entryname - 1)); ! 642: ! 643: /* The main program isn't allowed to have parameters, so any given ! 644: parameters are ignored */ ! 645: ! 646: if(procclass == CLMAIN || procclass == CLBLOCK) ! 647: return; ! 648: ! 649: /* So now we're working with something other than CLMAIN or CLBLOCK. ! 650: Determine the type of its return value. */ ! 651: ! 652: impldcl( np = mkname(entryname->fextname) ); ! 653: type = np->vtype; ! 654: proc_argchanges = prev_proc && type != entryname->extype; ! 655: entryname->extseen = 1; ! 656: if(proctype == TYUNKNOWN) ! 657: if( (proctype = type) == TYCHAR) ! 658: procleng = np->vleng ? np->vleng->constblock.Const.ci ! 659: : (ftnint) (-1); ! 660: ! 661: if(proctype == TYCHAR) ! 662: { ! 663: if(type != TYCHAR) ! 664: err("noncharacter entry of character function"); ! 665: ! 666: /* Functions returning type char can only have multiple entries if all ! 667: entries return the same length */ ! 668: ! 669: else if( (np->vleng ? np->vleng->constblock.Const.ci : ! 670: (ftnint) (-1)) != procleng) ! 671: err("mismatched character entry lengths"); ! 672: } ! 673: else if(type == TYCHAR) ! 674: err("character entry of noncharacter function"); ! 675: else if(type != proctype) ! 676: multitype = YES; ! 677: if(rtvlabel[type] == 0) ! 678: rtvlabel[type] = newlabel(); ! 679: ep->typelabel = rtvlabel[type]; ! 680: ! 681: if(type == TYCHAR) ! 682: { ! 683: if(chslot < 0) ! 684: { ! 685: chslot = nextarg(TYADDR); ! 686: chlgslot = nextarg(TYLENG); ! 687: } ! 688: np->vstg = STGARG; ! 689: ! 690: /* Put a new argument in the function, one which will hold the result of ! 691: a character function. This will have to be named sometime, probably in ! 692: mkarg(). */ ! 693: ! 694: if(procleng < 0) { ! 695: np->vleng = (expptr) mkarg(TYLENG, chlgslot); ! 696: np->vleng->addrblock.uname_tag = UNAM_IDENT; ! 697: strcpy (np -> vleng -> addrblock.user.ident, ! 698: new_func_length()); ! 699: } ! 700: if (!xretslot[TYCHAR]) { ! 701: xretslot[TYCHAR] = rs = ! 702: autovar(0, type, ISCONST(np->vleng) ! 703: ? np->vleng : ICON(0), ""); ! 704: strcpy(rs->user.ident, "ret_val"); ! 705: } ! 706: } ! 707: ! 708: /* Handle a complex return type -- declare a new parameter (pointer to ! 709: a complex value) */ ! 710: ! 711: else if( ISCOMPLEX(type) ) { ! 712: if (!xretslot[type]) ! 713: xretslot[type] = ! 714: autovar(0, type, EXNULL, " ret_val"); ! 715: /* the blank is for use in out_addr */ ! 716: np->vstg = STGARG; ! 717: if(cxslot < 0) ! 718: cxslot = nextarg(TYADDR); ! 719: } ! 720: else if (type != TYSUBR) { ! 721: if (type == TYUNKNOWN) { ! 722: dclerr("untyped function", np); ! 723: proctype = type = np->vtype = ! 724: dflttype[letter(np->fvarname[0])]; ! 725: } ! 726: if (!xretslot[type]) ! 727: xretslot[type] = retslot = ! 728: autovar(1, type, EXNULL, " ret_val"); ! 729: /* the blank is for use in out_addr */ ! 730: np->vstg = STGAUTO; ! 731: } ! 732: ! 733: for(p = ep->arglist ; p ; p = p->nextp) ! 734: if(! (( q = (Namep) (p->datap) )->vknownarg) ) { ! 735: q->vknownarg = 1; ! 736: q->vardesc.varno = nextarg(TYADDR); ! 737: allargs = mkchain((char *)q, allargs); ! 738: q->argno = nallargs++; ! 739: } ! 740: else if (nentry == 1) ! 741: duparg(q); ! 742: else for(p1 = ep->arglist ; p1 != p; p1 = p1->nextp) ! 743: if ((Namep)p1->datap == q) ! 744: duparg(q); ! 745: ! 746: k = 0; ! 747: for(p = ep->arglist ; p ; p = p->nextp) { ! 748: if(! (( q = (Namep) (p->datap) )->vdcldone) ) ! 749: { ! 750: impldcl(q); ! 751: q->vdcldone = YES; ! 752: if(q->vtype == TYCHAR) ! 753: { ! 754: ! 755: /* If we don't know the length of a char*(*) (i.e. a string), we must add ! 756: in this additional length argument. */ ! 757: ! 758: ++nallchargs; ! 759: if (q->vclass == CLPROC) ! 760: nallchargs--; ! 761: else if (q->vleng == NULL) { ! 762: /* character*(*) */ ! 763: q->vleng = (expptr) ! 764: mkarg(TYLENG, nextarg(TYLENG) ); ! 765: unamstring((Addrp)q->vleng, ! 766: new_arg_length(q)); ! 767: } ! 768: } ! 769: } ! 770: if (q->vdimfinish) ! 771: dim_finish(q); ! 772: if (q->vtype == TYCHAR && q->vclass != CLPROC) ! 773: k++; ! 774: } ! 775: ! 776: if (entryname->extype != type) ! 777: changedtype(np); ! 778: ! 779: /* save information for checking consistency of arg lists */ ! 780: ! 781: it = infertypes; ! 782: if (entryname->exproto) ! 783: infertypes = 1; ! 784: save_argtypes(ep->arglist, &entryname->arginfo, &np->arginfo, ! 785: 0, np->fvarname, STGEXT, k, np->vtype, 2); ! 786: infertypes = it; ! 787: } ! 788: ! 789: ! 790: ! 791: LOCAL nextarg(type) ! 792: int type; ! 793: { ! 794: int k; ! 795: k = lastargslot; ! 796: lastargslot += typesize[type]; ! 797: return(k); ! 798: } ! 799: ! 800: LOCAL ! 801: dim_check(q) ! 802: Namep q; ! 803: { ! 804: register struct Dimblock *vdim = q->vdim; ! 805: ! 806: if(!vdim->nelt || !ISICON(vdim->nelt)) ! 807: dclerr("adjustable dimension on non-argument", q); ! 808: else if (vdim->nelt->constblock.Const.ci <= 0) ! 809: dclerr("nonpositive dimension", q); ! 810: } ! 811: ! 812: LOCAL dobss() ! 813: { ! 814: register struct Hashentry *p; ! 815: register Namep q; ! 816: int qstg, qclass, qtype; ! 817: Extsym *e; ! 818: ! 819: for(p = hashtab ; p<lasthash ; ++p) ! 820: if(q = p->varp) ! 821: { ! 822: qstg = q->vstg; ! 823: qtype = q->vtype; ! 824: qclass = q->vclass; ! 825: ! 826: if( (qclass==CLUNKNOWN && qstg!=STGARG) || ! 827: (qclass==CLVAR && qstg==STGUNKNOWN) ) { ! 828: if (!(q->vis_assigned | q->vimpldovar)) ! 829: warn1("local variable %s never used", ! 830: q->fvarname); ! 831: } ! 832: else if(qclass==CLVAR && qstg==STGBSS) ! 833: { ; } ! 834: ! 835: /* Give external procedures the proper storage class */ ! 836: ! 837: else if(qclass==CLPROC && q->vprocclass==PEXTERNAL ! 838: && qstg!=STGARG) { ! 839: e = mkext(q->fvarname,addunder(q->cvarname)); ! 840: e->extstg = STGEXT; ! 841: q->vardesc.varno = e - extsymtab; ! 842: if (e->extype != qtype) ! 843: changedtype(q); ! 844: } ! 845: if(qclass==CLVAR) { ! 846: if (qstg != STGARG && q->vdim) ! 847: dim_check(q); ! 848: } /* if qclass == CLVAR */ ! 849: } ! 850: ! 851: } ! 852: ! 853: ! 854: ! 855: donmlist() ! 856: { ! 857: register struct Hashentry *p; ! 858: register Namep q; ! 859: ! 860: for(p=hashtab; p<lasthash; ++p) ! 861: if( (q = p->varp) && q->vclass==CLNAMELIST) ! 862: namelist(q); ! 863: } ! 864: ! 865: ! 866: /* iarrlen -- Returns the size of the array in bytes, or -1 */ ! 867: ! 868: ftnint iarrlen(q) ! 869: register Namep q; ! 870: { ! 871: ftnint leng; ! 872: ! 873: leng = typesize[q->vtype]; ! 874: if(leng <= 0) ! 875: return(-1); ! 876: if(q->vdim) ! 877: if( ISICON(q->vdim->nelt) ) ! 878: leng *= q->vdim->nelt->constblock.Const.ci; ! 879: else return(-1); ! 880: if(q->vleng) ! 881: if( ISICON(q->vleng) ) ! 882: leng *= q->vleng->constblock.Const.ci; ! 883: else return(-1); ! 884: return(leng); ! 885: } ! 886: ! 887: namelist(np) ! 888: Namep np; ! 889: { ! 890: register chainp q; ! 891: register Namep v; ! 892: int y; ! 893: ! 894: if (!np->visused) ! 895: return; ! 896: y = 0; ! 897: ! 898: for(q = np->varxptr.namelist ; q ; q = q->nextp) ! 899: { ! 900: vardcl( v = (Namep) (q->datap) ); ! 901: if( !ONEOF(v->vstg, MSKSTATIC) ) ! 902: dclerr("may not appear in namelist", v); ! 903: else { ! 904: v->vnamelist = 1; ! 905: v->visused = 1; ! 906: v->vsave = 1; ! 907: y = 1; ! 908: } ! 909: np->visused = y; ! 910: } ! 911: } ! 912: ! 913: /* docommon -- called at the end of procedure declarations, before ! 914: equivalences and the procedure body */ ! 915: ! 916: LOCAL docommon() ! 917: { ! 918: register Extsym *extptr; ! 919: register chainp q, q1; ! 920: struct Dimblock *t; ! 921: expptr neltp; ! 922: register Namep comvar; ! 923: ftnint size; ! 924: int i, k, pref, type; ! 925: extern int type_pref[]; ! 926: ! 927: for(extptr = extsymtab ; extptr<nextext ; ++extptr) ! 928: if (extptr->extstg == STGCOMMON && (q = extptr->extp)) { ! 929: ! 930: /* If a common declaration also had a list of variables ... */ ! 931: ! 932: q = extptr->extp = revchain(q); ! 933: pref = 1; ! 934: for(k = TYCHAR; q ; q = q->nextp) ! 935: { ! 936: comvar = (Namep) (q->datap); ! 937: ! 938: if(comvar->vdcldone == NO) ! 939: vardcl(comvar); ! 940: type = comvar->vtype; ! 941: if (pref < type_pref[type]) ! 942: pref = type_pref[k = type]; ! 943: if(extptr->extleng % typealign[type] != 0) { ! 944: dclerr("common alignment", comvar); ! 945: --nerr; /* don't give bad return code for this */ ! 946: #if 0 ! 947: extptr->extleng = roundup(extptr->extleng, typealign[type]); ! 948: #endif ! 949: } /* if extptr -> extleng % */ ! 950: ! 951: /* Set the offset into the common block */ ! 952: ! 953: comvar->voffset = extptr->extleng; ! 954: comvar->vardesc.varno = extptr - extsymtab; ! 955: if(type == TYCHAR) ! 956: size = comvar->vleng->constblock.Const.ci; ! 957: else ! 958: size = typesize[type]; ! 959: if(t = comvar->vdim) ! 960: if( (neltp = t->nelt) && ISCONST(neltp) ) ! 961: size *= neltp->constblock.Const.ci; ! 962: else ! 963: dclerr("adjustable array in common", comvar); ! 964: ! 965: /* Adjust the length of the common block so far */ ! 966: ! 967: extptr->extleng += size; ! 968: } /* for */ ! 969: ! 970: extptr->extype = k; ! 971: ! 972: /* Determine curno and, if new, save this identifier chain */ ! 973: ! 974: q1 = extptr->extp; ! 975: for (q = extptr->allextp, i = 0; q; i++, q = q->nextp) ! 976: if (struct_eq((chainp)q->datap, q1)) ! 977: break; ! 978: if (q) ! 979: extptr->curno = extptr->maxno - i; ! 980: else { ! 981: extptr->curno = ++extptr->maxno; ! 982: extptr->allextp = mkchain((char *)extptr->extp, ! 983: extptr->allextp); ! 984: } ! 985: } /* if extptr -> extstg == STGCOMMON */ ! 986: ! 987: /* Now the hash table entries have STGCOMMON, vdcldone, voffset, and ! 988: varno. And the common block itself has its full size in extleng. */ ! 989: ! 990: } /* docommon */ ! 991: ! 992: ! 993: /* copy_data -- copy the Namep entries so they are available even after ! 994: the hash table is empty */ ! 995: ! 996: copy_data (list) ! 997: chainp list; ! 998: { ! 999: for (; list; list = list -> nextp) { ! 1000: Namep namep = ALLOC (Nameblock); ! 1001: int size, nd, i; ! 1002: struct Dimblock *dp; ! 1003: ! 1004: cpn(sizeof(struct Nameblock), list->datap, (char *)namep); ! 1005: namep->fvarname = strcpy(gmem(strlen(namep->fvarname)+1,0), ! 1006: namep->fvarname); ! 1007: namep->cvarname = strcmp(namep->fvarname, namep->cvarname) ! 1008: ? strcpy(gmem(strlen(namep->cvarname)+1,0), namep->cvarname) ! 1009: : namep->fvarname; ! 1010: if (namep -> vleng) ! 1011: namep -> vleng = (expptr) cpexpr (namep -> vleng); ! 1012: if (namep -> vdim) { ! 1013: nd = namep -> vdim -> ndim; ! 1014: size = sizeof(int) + (3 + 2 * nd) * sizeof (expptr); ! 1015: dp = (struct Dimblock *) ckalloc (size); ! 1016: cpn(size, (char *)namep->vdim, (char *)dp); ! 1017: namep -> vdim = dp; ! 1018: dp->nelt = (expptr)cpexpr(dp->nelt); ! 1019: for (i = 0; i < nd; i++) { ! 1020: dp -> dims[i].dimsize = (expptr) cpexpr (dp -> dims[i].dimsize); ! 1021: } /* for */ ! 1022: } /* if */ ! 1023: list -> datap = (char *) namep; ! 1024: } /* for */ ! 1025: } /* copy_data */ ! 1026: ! 1027: ! 1028: ! 1029: LOCAL docomleng() ! 1030: { ! 1031: register Extsym *p; ! 1032: ! 1033: for(p = extsymtab ; p < nextext ; ++p) ! 1034: if(p->extstg == STGCOMMON) ! 1035: { ! 1036: if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng ! 1037: && strcmp(Blank, p->cextname) ) ! 1038: warn1("incompatible lengths for common block %.60s", ! 1039: p->fextname); ! 1040: if(p->maxleng < p->extleng) ! 1041: p->maxleng = p->extleng; ! 1042: p->extleng = 0; ! 1043: } ! 1044: } ! 1045: ! 1046: ! 1047: /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */ ! 1048: ! 1049: frtemp(p) ! 1050: Addrp p; ! 1051: { ! 1052: /* put block on chain of temps to be reclaimed */ ! 1053: holdtemps = mkchain((char *)p, holdtemps); ! 1054: } ! 1055: ! 1056: void ! 1057: freetemps() ! 1058: { ! 1059: register chainp p, p1; ! 1060: register Addrp q; ! 1061: register int t; ! 1062: ! 1063: p1 = holdtemps; ! 1064: while(p = p1) { ! 1065: q = (Addrp)p->datap; ! 1066: t = q->vtype; ! 1067: if (t == TYCHAR && q->varleng != 0) { ! 1068: /* restore clobbered character string lengths */ ! 1069: frexpr(q->vleng); ! 1070: q->vleng = ICON(q->varleng); ! 1071: } ! 1072: p1 = p->nextp; ! 1073: p->nextp = templist[t]; ! 1074: templist[t] = p; ! 1075: } ! 1076: holdtemps = 0; ! 1077: } ! 1078: ! 1079: /* allocate an automatic variable slot for each of nelt variables */ ! 1080: ! 1081: Addrp autovar(nelt0, t, lengp, name) ! 1082: register int nelt0, t; ! 1083: expptr lengp; ! 1084: char *name; ! 1085: { ! 1086: ftnint leng; ! 1087: register Addrp q; ! 1088: char *temp_name (); ! 1089: register int nelt = nelt0 > 0 ? nelt0 : 1; ! 1090: extern char *av_pfix[]; ! 1091: ! 1092: if(t == TYCHAR) ! 1093: if( ISICON(lengp) ) ! 1094: leng = lengp->constblock.Const.ci; ! 1095: else { ! 1096: Fatal("automatic variable of nonconstant length"); ! 1097: } ! 1098: else ! 1099: leng = typesize[t]; ! 1100: ! 1101: q = ALLOC(Addrblock); ! 1102: q->tag = TADDR; ! 1103: q->vtype = t; ! 1104: if(t == TYCHAR) ! 1105: { ! 1106: q->vleng = ICON(leng); ! 1107: q->varleng = leng; ! 1108: } ! 1109: q->vstg = STGAUTO; ! 1110: q->ntempelt = nelt; ! 1111: q->isarray = (nelt > 1); ! 1112: q->memoffset = ICON(0); ! 1113: ! 1114: /* kludge for nls so we can have ret_val rather than ret_val_4 */ ! 1115: if (*name == ' ') ! 1116: unamstring(q, name); ! 1117: else { ! 1118: q->uname_tag = UNAM_IDENT; ! 1119: temp_name(av_pfix[t], ++autonum[t], q->user.ident); ! 1120: } ! 1121: if (nelt0 > 0) ! 1122: declare_new_addr (q); ! 1123: return(q); ! 1124: } ! 1125: ! 1126: ! 1127: /* Returns a temporary of the appropriate type. Will reuse existing ! 1128: temporaries when possible */ ! 1129: ! 1130: Addrp mktmpn(nelt, type, lengp) ! 1131: int nelt; ! 1132: register int type; ! 1133: expptr lengp; ! 1134: { ! 1135: ftnint leng; ! 1136: chainp p, oldp; ! 1137: register Addrp q; ! 1138: ! 1139: if(type==TYUNKNOWN || type==TYERROR) ! 1140: badtype("mktmpn", type); ! 1141: ! 1142: if(type==TYCHAR) ! 1143: if(lengp && ISICON(lengp) ) ! 1144: leng = lengp->constblock.Const.ci; ! 1145: else { ! 1146: err("adjustable length"); ! 1147: return( (Addrp) errnode() ); ! 1148: } ! 1149: else if (type > TYCHAR || type < TYADDR) { ! 1150: erri("mktmpn: unexpected type %d", type); ! 1151: exit(1); ! 1152: } ! 1153: /* ! 1154: * if a temporary of appropriate shape is on the templist, ! 1155: * remove it from the list and return it ! 1156: */ ! 1157: for(oldp=CHNULL, p=templist[type]; p ; oldp=p, p=p->nextp) ! 1158: { ! 1159: q = (Addrp) (p->datap); ! 1160: if(q->ntempelt==nelt && ! 1161: (type!=TYCHAR || q->vleng->constblock.Const.ci==leng) ) ! 1162: { ! 1163: if(oldp) ! 1164: oldp->nextp = p->nextp; ! 1165: else ! 1166: templist[type] = p->nextp; ! 1167: free( (charptr) p); ! 1168: return(q); ! 1169: } ! 1170: } ! 1171: q = autovar(nelt, type, lengp, ""); ! 1172: return(q); ! 1173: } ! 1174: ! 1175: ! 1176: ! 1177: ! 1178: /* mktmp -- create new local variable; call it something like name ! 1179: lengp is taken directly, not copied */ ! 1180: ! 1181: Addrp mktmp(type, lengp) ! 1182: int type; ! 1183: expptr lengp; ! 1184: { ! 1185: Addrp rv; ! 1186: /* arrange for temporaries to be recycled */ ! 1187: /* at the end of this statement... */ ! 1188: rv = mktmpn(1,type,lengp); ! 1189: frtemp((Addrp)cpexpr((expptr)rv)); ! 1190: return rv; ! 1191: } ! 1192: ! 1193: /* mktmp0 omits frtemp() */ ! 1194: Addrp mktmp0(type, lengp) ! 1195: int type; ! 1196: expptr lengp; ! 1197: { ! 1198: Addrp rv; ! 1199: /* arrange for temporaries to be recycled */ ! 1200: /* when this Addrp is freed */ ! 1201: rv = mktmpn(1,type,lengp); ! 1202: rv->istemp = YES; ! 1203: return rv; ! 1204: } ! 1205: ! 1206: /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ ! 1207: ! 1208: /* comblock -- Declare a new common block. Input parameters name the block; ! 1209: s will be NULL if the block is unnamed */ ! 1210: ! 1211: Extsym *comblock(s) ! 1212: register char *s; ! 1213: { ! 1214: Extsym *p; ! 1215: register char *t; ! 1216: register int c, i; ! 1217: char cbuf[256], *s0; ! 1218: ! 1219: /* Give the unnamed common block a unique name */ ! 1220: ! 1221: if(*s == 0) ! 1222: p = mkext(Blank,Blank); ! 1223: else { ! 1224: s0 = s; ! 1225: t = cbuf; ! 1226: for(i = 0; c = *t = *s++; t++) ! 1227: if (c == '_') ! 1228: i = 1; ! 1229: if (i) ! 1230: *t++ = '_'; ! 1231: t[0] = '_'; ! 1232: t[1] = 0; ! 1233: p = mkext(s0,cbuf); ! 1234: } ! 1235: if(p->extstg == STGUNKNOWN) ! 1236: p->extstg = STGCOMMON; ! 1237: else if(p->extstg != STGCOMMON) ! 1238: { ! 1239: errstr("%.68s cannot be a common block name", s); ! 1240: return(0); ! 1241: } ! 1242: ! 1243: return( p ); ! 1244: } ! 1245: ! 1246: ! 1247: /* incomm -- add a new variable to a common declaration */ ! 1248: ! 1249: incomm(c, v) ! 1250: Extsym *c; ! 1251: Namep v; ! 1252: { ! 1253: if (!c) ! 1254: return; ! 1255: if(v->vstg != STGUNKNOWN && !v->vimplstg) ! 1256: dclerr(v->vstg == STGARG ! 1257: ? "dummy arguments cannot be in common" ! 1258: : "incompatible common declaration", v); ! 1259: else ! 1260: { ! 1261: v->vstg = STGCOMMON; ! 1262: c->extp = mkchain((char *)v, c->extp); ! 1263: } ! 1264: } ! 1265: ! 1266: ! 1267: ! 1268: ! 1269: /* settype -- set the type or storage class of a Namep object. If ! 1270: v -> vstg == STGUNKNOWN && type < 0, attempt to reset vstg to be ! 1271: -type. This function will not change any earlier definitions in v, ! 1272: in will only attempt to fill out more information give the other params */ ! 1273: ! 1274: settype(v, type, length) ! 1275: register Namep v; ! 1276: register int type; ! 1277: register ftnint length; ! 1278: { ! 1279: int type1; ! 1280: ! 1281: if(type == TYUNKNOWN) ! 1282: return; ! 1283: ! 1284: if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG) ! 1285: { ! 1286: v->vtype = TYSUBR; ! 1287: frexpr(v->vleng); ! 1288: v->vleng = 0; ! 1289: v->vimpltype = 0; ! 1290: } ! 1291: else if(type < 0) /* storage class set */ ! 1292: { ! 1293: if(v->vstg == STGUNKNOWN) ! 1294: v->vstg = - type; ! 1295: else if(v->vstg != -type) ! 1296: dclerr("incompatible storage declarations", v); ! 1297: } ! 1298: else if(v->vtype == TYUNKNOWN || v->vimpltype && v->vtype != type) ! 1299: { ! 1300: if( (v->vtype = lengtype(type, length))==TYCHAR ) ! 1301: if (length>=0) ! 1302: v->vleng = ICON(length); ! 1303: else if (parstate >= INDATA) ! 1304: v->vleng = ICON(1); /* avoid a memory fault */ ! 1305: v->vimpltype = 0; ! 1306: ! 1307: if (v->vclass == CLPROC) { ! 1308: if (v->vstg == STGEXT ! 1309: && (type1 = extsymtab[v->vardesc.varno].extype) ! 1310: && type1 != v->vtype) ! 1311: changedtype(v); ! 1312: else if (v->vprocclass == PTHISPROC ! 1313: && (parstate >= INDATA ! 1314: || procclass == CLMAIN) ! 1315: && !xretslot[type]) { ! 1316: xretslot[type] = autovar(ONEOF(type, ! 1317: MSKCOMPLEX|MSKCHAR) ? 0 : 1, type, ! 1318: v->vleng, " ret_val"); ! 1319: if (procclass == CLMAIN) ! 1320: errstr( ! 1321: "illegal use of %.60s (main program name)", ! 1322: v->fvarname); ! 1323: /* not completely right, but enough to */ ! 1324: /* avoid memory faults; we won't */ ! 1325: /* emit any C as we have illegal Fortran */ ! 1326: } ! 1327: } ! 1328: } ! 1329: else if(v->vtype!=type) { ! 1330: incompat: ! 1331: dclerr("incompatible type declarations", v); ! 1332: } ! 1333: else if (type==TYCHAR) ! 1334: if (v->vleng && v->vleng->constblock.Const.ci != length) ! 1335: goto incompat; ! 1336: else if (parstate >= INDATA) ! 1337: v->vleng = ICON(1); /* avoid a memory fault */ ! 1338: } ! 1339: ! 1340: ! 1341: ! 1342: ! 1343: ! 1344: /* lengtype -- returns the proper compiler type, given input of Fortran ! 1345: type and length specifier */ ! 1346: ! 1347: lengtype(type, len) ! 1348: register int type; ! 1349: ftnint len; ! 1350: { ! 1351: register int length = (int)len; ! 1352: switch(type) ! 1353: { ! 1354: case TYREAL: ! 1355: if(length == typesize[TYDREAL]) ! 1356: return(TYDREAL); ! 1357: if(length == typesize[TYREAL]) ! 1358: goto ret; ! 1359: break; ! 1360: ! 1361: case TYCOMPLEX: ! 1362: if(length == typesize[TYDCOMPLEX]) ! 1363: return(TYDCOMPLEX); ! 1364: if(length == typesize[TYCOMPLEX]) ! 1365: goto ret; ! 1366: break; ! 1367: ! 1368: case TYINT1: ! 1369: case TYSHORT: ! 1370: case TYDREAL: ! 1371: case TYDCOMPLEX: ! 1372: case TYCHAR: ! 1373: case TYLOGICAL1: ! 1374: case TYLOGICAL2: ! 1375: case TYUNKNOWN: ! 1376: case TYSUBR: ! 1377: case TYERROR: ! 1378: #ifdef TYQUAD ! 1379: case TYQUAD: ! 1380: #endif ! 1381: goto ret; ! 1382: ! 1383: case TYLOGICAL: ! 1384: switch(length) { ! 1385: case 0: return tylog; ! 1386: case 1: return TYLOGICAL1; ! 1387: case 2: return TYLOGICAL2; ! 1388: case 4: goto ret; ! 1389: } ! 1390: #if 0 /*!!??!!*/ ! 1391: if(length == typesize[TYLOGICAL]) ! 1392: goto ret; ! 1393: #endif ! 1394: break; ! 1395: ! 1396: case TYLONG: ! 1397: if(length == 0) ! 1398: return(tyint); ! 1399: if (length == 1) ! 1400: return TYINT1; ! 1401: if(length == typesize[TYSHORT]) ! 1402: return(TYSHORT); ! 1403: #ifdef TYQUAD ! 1404: if(length == typesize[TYQUAD] && use_tyquad) ! 1405: return(TYQUAD); ! 1406: #endif ! 1407: if(length == typesize[TYLONG]) ! 1408: goto ret; ! 1409: break; ! 1410: default: ! 1411: badtype("lengtype", type); ! 1412: } ! 1413: ! 1414: if(len != 0) ! 1415: err("incompatible type-length combination"); ! 1416: ! 1417: ret: ! 1418: return(type); ! 1419: } ! 1420: ! 1421: ! 1422: ! 1423: ! 1424: ! 1425: /* setintr -- Set Intrinsic function */ ! 1426: ! 1427: setintr(v) ! 1428: register Namep v; ! 1429: { ! 1430: int k; ! 1431: ! 1432: if(v->vstg == STGUNKNOWN) ! 1433: v->vstg = STGINTR; ! 1434: else if(v->vstg!=STGINTR) ! 1435: dclerr("incompatible use of intrinsic function", v); ! 1436: if(v->vclass==CLUNKNOWN) ! 1437: v->vclass = CLPROC; ! 1438: if(v->vprocclass == PUNKNOWN) ! 1439: v->vprocclass = PINTRINSIC; ! 1440: else if(v->vprocclass != PINTRINSIC) ! 1441: dclerr("invalid intrinsic declaration", v); ! 1442: if(k = intrfunct(v->fvarname)) { ! 1443: if ((*(struct Intrpacked *)&k).f4) ! 1444: if (noextflag) ! 1445: goto unknown; ! 1446: else ! 1447: dcomplex_seen++; ! 1448: v->vardesc.varno = k; ! 1449: } ! 1450: else { ! 1451: unknown: ! 1452: dclerr("unknown intrinsic function", v); ! 1453: } ! 1454: } ! 1455: ! 1456: ! 1457: ! 1458: /* setext -- Set External declaration -- assume that unknowns will become ! 1459: procedures */ ! 1460: ! 1461: setext(v) ! 1462: register Namep v; ! 1463: { ! 1464: if(v->vclass == CLUNKNOWN) ! 1465: v->vclass = CLPROC; ! 1466: else if(v->vclass != CLPROC) ! 1467: dclerr("invalid external declaration", v); ! 1468: ! 1469: if(v->vprocclass == PUNKNOWN) ! 1470: v->vprocclass = PEXTERNAL; ! 1471: else if(v->vprocclass != PEXTERNAL) ! 1472: dclerr("invalid external declaration", v); ! 1473: } /* setext */ ! 1474: ! 1475: ! 1476: ! 1477: ! 1478: /* create dimensions block for array variable */ ! 1479: ! 1480: setbound(v, nd, dims) ! 1481: register Namep v; ! 1482: int nd; ! 1483: struct Dims dims[ ]; ! 1484: { ! 1485: register expptr q, t; ! 1486: register struct Dimblock *p; ! 1487: int i; ! 1488: extern chainp new_vars; ! 1489: char buf[256]; ! 1490: ! 1491: if(v->vclass == CLUNKNOWN) ! 1492: v->vclass = CLVAR; ! 1493: else if(v->vclass != CLVAR) ! 1494: { ! 1495: dclerr("only variables may be arrays", v); ! 1496: return; ! 1497: } ! 1498: ! 1499: v->vdim = p = (struct Dimblock *) ! 1500: ckalloc( sizeof(int) + (3+2*nd)*sizeof(expptr) ); ! 1501: p->ndim = nd--; ! 1502: p->nelt = ICON(1); ! 1503: doin_setbound = 1; ! 1504: ! 1505: for(i = 0; i <= nd; ++i) ! 1506: { ! 1507: if( (q = dims[i].ub) == NULL) ! 1508: { ! 1509: if(i == nd) ! 1510: { ! 1511: frexpr(p->nelt); ! 1512: p->nelt = NULL; ! 1513: } ! 1514: else ! 1515: err("only last bound may be asterisk"); ! 1516: p->dims[i].dimsize = ICON(1); ! 1517: ; ! 1518: p->dims[i].dimexpr = NULL; ! 1519: } ! 1520: else ! 1521: { ! 1522: ! 1523: if(dims[i].lb) ! 1524: { ! 1525: q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb)); ! 1526: q = mkexpr(OPPLUS, q, ICON(1) ); ! 1527: } ! 1528: if( ISCONST(q) ) ! 1529: { ! 1530: p->dims[i].dimsize = q; ! 1531: p->dims[i].dimexpr = (expptr) PNULL; ! 1532: } ! 1533: else { ! 1534: sprintf(buf, " %s_dim%d", v->fvarname, i+1); ! 1535: p->dims[i].dimsize = (expptr) ! 1536: autovar(1, tyint, EXNULL, buf); ! 1537: p->dims[i].dimexpr = q; ! 1538: if (i == nd) ! 1539: v->vlastdim = new_vars; ! 1540: v->vdimfinish = 1; ! 1541: } ! 1542: if(p->nelt) ! 1543: p->nelt = mkexpr(OPSTAR, p->nelt, ! 1544: cpexpr(p->dims[i].dimsize) ); ! 1545: } ! 1546: } ! 1547: ! 1548: q = dims[nd].lb; ! 1549: if(q == NULL) ! 1550: q = ICON(1); ! 1551: ! 1552: for(i = nd-1 ; i>=0 ; --i) ! 1553: { ! 1554: t = dims[i].lb; ! 1555: if(t == NULL) ! 1556: t = ICON(1); ! 1557: if(p->dims[i].dimsize) ! 1558: q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) ); ! 1559: } ! 1560: ! 1561: if( ISCONST(q) ) ! 1562: { ! 1563: p->baseoffset = q; ! 1564: p->basexpr = NULL; ! 1565: } ! 1566: else ! 1567: { ! 1568: sprintf(buf, " %s_offset", v->fvarname); ! 1569: p->baseoffset = (expptr) autovar(1, tyint, EXNULL, buf); ! 1570: p->basexpr = q; ! 1571: v->vdimfinish = 1; ! 1572: } ! 1573: doin_setbound = 0; ! 1574: } ! 1575: ! 1576: ! 1577: ! 1578: wr_abbrevs (outfile, function_head, vars) ! 1579: FILE *outfile; ! 1580: int function_head; ! 1581: chainp vars; ! 1582: { ! 1583: for (; vars; vars = vars -> nextp) { ! 1584: Namep name = (Namep) vars -> datap; ! 1585: if (!name->visused) ! 1586: continue; ! 1587: ! 1588: if (function_head) ! 1589: nice_printf (outfile, "#define "); ! 1590: else ! 1591: nice_printf (outfile, "#undef "); ! 1592: out_name (outfile, name); ! 1593: ! 1594: if (function_head) { ! 1595: Extsym *comm = &extsymtab[name -> vardesc.varno]; ! 1596: ! 1597: nice_printf (outfile, " ("); ! 1598: extern_out (outfile, comm); ! 1599: nice_printf (outfile, "%d.", comm->curno); ! 1600: nice_printf (outfile, "%s)", name->cvarname); ! 1601: } /* if function_head */ ! 1602: nice_printf (outfile, "\n"); ! 1603: } /* for */ ! 1604: } /* wr_abbrevs */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.