1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: static char sccsid[] = "@(#)misc.c 5.2 (Berkeley) 1/7/86"; 9: #endif not lint 10: 11: /* 12: * misc.c 13: * 14: * Miscellaneous routines for the f77 compiler, 4.2 BSD. 15: * 16: * University of Utah CS Dept modification history: 17: * 18: * $Log: misc.c,v $ 19: * Revision 5.2 85/12/18 00:35:08 donn 20: * Prevent core dumps for peculiar statement numbers. 21: * 22: * Revision 5.1 85/08/10 03:48:29 donn 23: * 4.3 alpha 24: * 25: * Revision 3.1 84/10/13 01:53:26 donn 26: * Installed Jerry Berkman's version; added UofU comment header. 27: * 28: */ 29: 30: #include "defs.h" 31: 32: 33: 34: cpn(n, a, b) 35: register int n; 36: register char *a, *b; 37: { 38: while(--n >= 0) 39: *b++ = *a++; 40: } 41: 42: 43: 44: eqn(n, a, b) 45: register int n; 46: register char *a, *b; 47: { 48: while(--n >= 0) 49: if(*a++ != *b++) 50: return(NO); 51: return(YES); 52: } 53: 54: 55: 56: 57: 58: 59: 60: cmpstr(a, b, la, lb) /* compare two strings */ 61: register char *a, *b; 62: ftnint la, lb; 63: { 64: register char *aend, *bend; 65: aend = a + la; 66: bend = b + lb; 67: 68: 69: if(la <= lb) 70: { 71: while(a < aend) 72: if(*a != *b) 73: return( *a - *b ); 74: else 75: { ++a; ++b; } 76: 77: while(b < bend) 78: if(*b != ' ') 79: return(' ' - *b); 80: else 81: ++b; 82: } 83: 84: else 85: { 86: while(b < bend) 87: if(*a != *b) 88: return( *a - *b ); 89: else 90: { ++a; ++b; } 91: while(a < aend) 92: if(*a != ' ') 93: return(*a - ' '); 94: else 95: ++a; 96: } 97: return(0); 98: } 99: 100: 101: 102: 103: 104: chainp hookup(x,y) 105: register chainp x, y; 106: { 107: register chainp p; 108: 109: if(x == NULL) 110: return(y); 111: 112: for(p = x ; p->nextp ; p = p->nextp) 113: ; 114: p->nextp = y; 115: return(x); 116: } 117: 118: 119: 120: struct Listblock *mklist(p) 121: chainp p; 122: { 123: register struct Listblock *q; 124: 125: q = ALLOC(Listblock); 126: q->tag = TLIST; 127: q->listp = p; 128: return(q); 129: } 130: 131: 132: chainp mkchain(p,q) 133: register tagptr p; 134: register chainp q; 135: { 136: register chainp r; 137: 138: if(chains) 139: { 140: r = chains; 141: chains = chains->nextp; 142: } 143: else 144: r = ALLOC(Chain); 145: 146: r->datap = p; 147: r->nextp = q; 148: return(r); 149: } 150: 151: 152: 153: char * varstr(n, s) 154: register int n; 155: register char *s; 156: { 157: register int i; 158: static char name[XL+1]; 159: 160: for(i=0; i<n && *s!=' ' && *s!='\0' ; ++i) 161: name[i] = *s++; 162: 163: name[i] = '\0'; 164: 165: return( name ); 166: } 167: 168: 169: 170: 171: char * varunder(n, s) 172: register int n; 173: register char *s; 174: { 175: register int i; 176: static char name[XL+1]; 177: 178: for(i=0; i<n && *s!=' ' && *s!='\0' ; ++i) 179: name[i] = *s++; 180: 181: #if TARGET != GCOS 182: name[i++] = '_'; 183: #endif 184: 185: name[i] = '\0'; 186: 187: return( name ); 188: } 189: 190: 191: 192: 193: 194: char * nounder(n, s) 195: register int n; 196: register char *s; 197: { 198: register int i; 199: static char name[XL+1]; 200: 201: for(i=0; i<n && *s!=' ' && *s!='\0' ; ++s) 202: if(*s != '_') 203: name[i++] = *s; 204: 205: name[i] = '\0'; 206: 207: return( name ); 208: } 209: 210: 211: 212: char *copyn(n, s) 213: register int n; 214: register char *s; 215: { 216: register char *p, *q; 217: 218: p = q = (char *) ckalloc(n); 219: while(--n >= 0) 220: *q++ = *s++; 221: return(p); 222: } 223: 224: 225: 226: char *copys(s) 227: char *s; 228: { 229: return( copyn( strlen(s)+1 , s) ); 230: } 231: 232: 233: 234: ftnint convci(n, s) 235: register int n; 236: register char *s; 237: { 238: ftnint sum; 239: ftnint digval; 240: sum = 0; 241: while(n-- > 0) 242: { 243: if (sum > MAXINT/10 ) { 244: err("integer constant too large"); 245: return(sum); 246: } 247: sum *= 10; 248: digval = *s++ - '0'; 249: #if (TARGET != VAX) 250: sum += digval; 251: #endif 252: #if (TARGET == VAX) 253: if ( MAXINT - sum >= digval ) { 254: sum += digval; 255: } else { 256: /* KLUDGE. On VAXs, MININT is (-MAXINT)-1 , i.e., there 257: is one more neg. integer than pos. integer. The 258: following code returns MININT whenever (MAXINT+1) 259: is seen. On VAXs, such statements as: i = MININT 260: work, although this generates garbage for 261: such statements as: i = MPLUS1 where MPLUS1 is MAXINT+1 262: or: i = 5 - 2147483647/2 . 263: The only excuse for this kludge is it keeps all legal 264: programs running and flags most illegal constants, unlike 265: the previous version which flaged nothing outside data stmts! 266: */ 267: if ( n == 0 && MAXINT - sum + 1 == digval ) { 268: warn("minimum negative integer compiled - possibly bad code"); 269: sum = MININT; 270: } else { 271: err("integer constant too large"); 272: return(sum); 273: } 274: } 275: #endif 276: } 277: return(sum); 278: } 279: 280: char *convic(n) 281: ftnint n; 282: { 283: static char s[20]; 284: register char *t; 285: 286: s[19] = '\0'; 287: t = s+19; 288: 289: do { 290: *--t = '0' + n%10; 291: n /= 10; 292: } while(n > 0); 293: 294: return(t); 295: } 296: 297: 298: 299: double convcd(n, s) 300: int n; 301: register char *s; 302: { 303: double atof(); 304: char v[100]; 305: register char *t; 306: if(n > 90) 307: { 308: err("too many digits in floating constant"); 309: n = 90; 310: } 311: for(t = v ; n-- > 0 ; s++) 312: *t++ = (*s=='d' ? 'e' : *s); 313: *t = '\0'; 314: return( atof(v) ); 315: } 316: 317: 318: 319: Namep mkname(l, s) 320: int l; 321: register char *s; 322: { 323: struct Hashentry *hp; 324: int hash; 325: register Namep q; 326: register int i; 327: char n[VL]; 328: 329: hash = 0; 330: for(i = 0 ; i<l && *s!='\0' ; ++i) 331: { 332: hash += *s; 333: n[i] = *s++; 334: } 335: hash %= maxhash; 336: while( i < VL ) 337: n[i++] = ' '; 338: 339: hp = hashtab + hash; 340: while(q = hp->varp) 341: if( hash==hp->hashval && eqn(VL,n,q->varname) ) 342: return(q); 343: else if(++hp >= lasthash) 344: hp = hashtab; 345: 346: if(++nintnames >= maxhash-1) 347: many("names", 'n'); 348: hp->varp = q = ALLOC(Nameblock); 349: hp->hashval = hash; 350: q->tag = TNAME; 351: cpn(VL, n, q->varname); 352: return(q); 353: } 354: 355: 356: 357: struct Labelblock *mklabel(l) 358: ftnint l; 359: { 360: register struct Labelblock *lp; 361: 362: if(l <= 0 || l > 99999 ) { 363: errstr("illegal label %d", l); 364: l = 0; 365: } 366: 367: for(lp = labeltab ; lp < highlabtab ; ++lp) 368: if(lp->stateno == l) 369: return(lp); 370: 371: if(++highlabtab > labtabend) 372: many("statement numbers", 's'); 373: 374: lp->stateno = l; 375: lp->labelno = newlabel(); 376: lp->blklevel = 0; 377: lp->labused = NO; 378: lp->labdefined = NO; 379: lp->labinacc = NO; 380: lp->labtype = LABUNKNOWN; 381: return(lp); 382: } 383: 384: 385: newlabel() 386: { 387: return( ++lastlabno ); 388: } 389: 390: 391: /* this label appears in a branch context */ 392: 393: struct Labelblock *execlab(stateno) 394: ftnint stateno; 395: { 396: register struct Labelblock *lp; 397: 398: if(lp = mklabel(stateno)) 399: { 400: if(lp->labinacc) 401: warn1("illegal branch to inner block, statement %s", 402: convic(stateno) ); 403: else if(lp->labdefined == NO) 404: lp->blklevel = blklevel; 405: lp->labused = YES; 406: if(lp->labtype == LABFORMAT) 407: err("may not branch to a format"); 408: else 409: lp->labtype = LABEXEC; 410: } 411: 412: return(lp); 413: } 414: 415: 416: 417: 418: 419: /* find or put a name in the external symbol table */ 420: 421: struct Extsym *mkext(s) 422: char *s; 423: { 424: int i; 425: register char *t; 426: char n[XL]; 427: struct Extsym *p; 428: 429: i = 0; 430: t = n; 431: while(i<XL && *s) 432: *t++ = *s++; 433: while(t < n+XL) 434: *t++ = ' '; 435: 436: for(p = extsymtab ; p<nextext ; ++p) 437: if(eqn(XL, n, p->extname)) 438: return( p ); 439: 440: if(nextext >= lastext) 441: many("external symbols", 'x'); 442: 443: cpn(XL, n, nextext->extname); 444: nextext->extstg = STGUNKNOWN; 445: nextext->extsave = NO; 446: nextext->extp = 0; 447: nextext->extleng = 0; 448: nextext->maxleng = 0; 449: nextext->extinit = NO; 450: return( nextext++ ); 451: } 452: 453: 454: 455: 456: 457: 458: 459: 460: Addrp builtin(t, s) 461: int t; 462: char *s; 463: { 464: register struct Extsym *p; 465: register Addrp q; 466: 467: p = mkext(s); 468: if(p->extstg == STGUNKNOWN) 469: p->extstg = STGEXT; 470: else if(p->extstg != STGEXT) 471: { 472: errstr("improper use of builtin %s", s); 473: return(0); 474: } 475: 476: q = ALLOC(Addrblock); 477: q->tag = TADDR; 478: q->vtype = t; 479: q->vclass = CLPROC; 480: q->vstg = STGEXT; 481: q->memno = p - extsymtab; 482: return(q); 483: } 484: 485: 486: 487: frchain(p) 488: register chainp *p; 489: { 490: register chainp q; 491: 492: if(p==0 || *p==0) 493: return; 494: 495: for(q = *p; q->nextp ; q = q->nextp) 496: ; 497: q->nextp = chains; 498: chains = *p; 499: *p = 0; 500: } 501: 502: 503: tagptr cpblock(n,p) 504: register int n; 505: register char * p; 506: { 507: register char *q; 508: ptr q0; 509: 510: q0 = ckalloc(n); 511: q = (char *) q0; 512: while(n-- > 0) 513: *q++ = *p++; 514: return( (tagptr) q0); 515: } 516: 517: 518: 519: max(a,b) 520: int a,b; 521: { 522: return( a>b ? a : b); 523: } 524: 525: 526: ftnint lmax(a, b) 527: ftnint a, b; 528: { 529: return( a>b ? a : b); 530: } 531: 532: ftnint lmin(a, b) 533: ftnint a, b; 534: { 535: return(a < b ? a : b); 536: } 537: 538: 539: 540: 541: maxtype(t1, t2) 542: int t1, t2; 543: { 544: int t; 545: 546: t = max(t1, t2); 547: if(t==TYCOMPLEX && (t1==TYDREAL || t2==TYDREAL) ) 548: t = TYDCOMPLEX; 549: return(t); 550: } 551: 552: 553: 554: /* return log base 2 of n if n a power of 2; otherwise -1 */ 555: #if FAMILY == PCC 556: log2(n) 557: ftnint n; 558: { 559: int k; 560: 561: /* trick based on binary representation */ 562: 563: if(n<=0 || (n & (n-1))!=0) 564: return(-1); 565: 566: for(k = 0 ; n >>= 1 ; ++k) 567: ; 568: return(k); 569: } 570: #endif 571: 572: 573: 574: frrpl() 575: { 576: struct Rplblock *rp; 577: 578: while(rpllist) 579: { 580: rp = rpllist->rplnextp; 581: free( (charptr) rpllist); 582: rpllist = rp; 583: } 584: } 585: 586: 587: 588: expptr callk(type, name, args) 589: int type; 590: char *name; 591: chainp args; 592: { 593: register expptr p; 594: 595: p = mkexpr(OPCALL, builtin(type,name), args); 596: p->exprblock.vtype = type; 597: return(p); 598: } 599: 600: 601: 602: expptr call4(type, name, arg1, arg2, arg3, arg4) 603: int type; 604: char *name; 605: expptr arg1, arg2, arg3, arg4; 606: { 607: struct Listblock *args; 608: args = mklist( mkchain(arg1, mkchain(arg2, mkchain(arg3, 609: mkchain(arg4, CHNULL)) ) ) ); 610: return( callk(type, name, args) ); 611: } 612: 613: 614: 615: 616: expptr call3(type, name, arg1, arg2, arg3) 617: int type; 618: char *name; 619: expptr arg1, arg2, arg3; 620: { 621: struct Listblock *args; 622: args = mklist( mkchain(arg1, mkchain(arg2, mkchain(arg3, CHNULL) ) ) ); 623: return( callk(type, name, args) ); 624: } 625: 626: 627: 628: 629: 630: expptr call2(type, name, arg1, arg2) 631: int type; 632: char *name; 633: expptr arg1, arg2; 634: { 635: struct Listblock *args; 636: 637: args = mklist( mkchain(arg1, mkchain(arg2, CHNULL) ) ); 638: return( callk(type,name, args) ); 639: } 640: 641: 642: 643: 644: expptr call1(type, name, arg) 645: int type; 646: char *name; 647: expptr arg; 648: { 649: return( callk(type,name, mklist(mkchain(arg,CHNULL)) )); 650: } 651: 652: 653: expptr call0(type, name) 654: int type; 655: char *name; 656: { 657: return( callk(type, name, PNULL) ); 658: } 659: 660: 661: 662: struct Impldoblock *mkiodo(dospec, list) 663: chainp dospec, list; 664: { 665: register struct Impldoblock *q; 666: 667: q = ALLOC(Impldoblock); 668: q->tag = TIMPLDO; 669: q->impdospec = dospec; 670: q->datalist = list; 671: return(q); 672: } 673: 674: 675: 676: 677: ptr ckalloc(n) 678: register int n; 679: { 680: register ptr p; 681: ptr calloc(); 682: 683: if( p = calloc(1, (unsigned) n) ) 684: return(p); 685: 686: fatal("out of memory"); 687: /* NOTREACHED */ 688: } 689: 690: 691: 692: 693: 694: isaddr(p) 695: register expptr p; 696: { 697: if(p->tag == TADDR) 698: return(YES); 699: if(p->tag == TEXPR) 700: switch(p->exprblock.opcode) 701: { 702: case OPCOMMA: 703: return( isaddr(p->exprblock.rightp) ); 704: 705: case OPASSIGN: 706: case OPPLUSEQ: 707: return( isaddr(p->exprblock.leftp) ); 708: } 709: return(NO); 710: } 711: 712: 713: 714: 715: isstatic(p) 716: register expptr p; 717: { 718: if(p->headblock.vleng && !ISCONST(p->headblock.vleng)) 719: return(NO); 720: 721: switch(p->tag) 722: { 723: case TCONST: 724: return(YES); 725: 726: case TADDR: 727: if(ONEOF(p->addrblock.vstg,MSKSTATIC) && 728: ISCONST(p->addrblock.memoffset)) 729: return(YES); 730: 731: default: 732: return(NO); 733: } 734: } 735: 736: 737: 738: addressable(p) 739: register expptr p; 740: { 741: switch(p->tag) 742: { 743: case TCONST: 744: return(YES); 745: 746: case TADDR: 747: return( addressable(p->addrblock.memoffset) ); 748: 749: default: 750: return(NO); 751: } 752: } 753: 754: 755: 756: hextoi(c) 757: register int c; 758: { 759: register char *p; 760: static char p0[17] = "0123456789abcdef"; 761: 762: for(p = p0 ; *p ; ++p) 763: if(*p == c) 764: return( p-p0 ); 765: return(16); 766: }