1/* Id: misc.c,v 1.17 2009/02/11 15:58:55 ragge Exp */ 2/* $NetBSD$ */ 3/* 4 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * Redistributions of source code and documentation must retain the above 11 * copyright notice, this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed or owned by Caldera 18 * International, Inc. 19 * Neither the name of Caldera International, Inc. nor the names of other 20 * contributors may be used to endorse or promote products derived from 21 * this software without specific prior written permission. 22 * 23 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 24 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE 28 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, 32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37#include <string.h> 38 39#include "defines.h" 40#include "defs.h" 41 42int max(int, int); 43 44void 45cpn(n, a, b) 46register int n; 47register char *a, *b; 48{ 49while(--n >= 0) 50 *b++ = *a++; 51} 52 53 54int 55eqn(n, a, b) 56register int n; 57register char *a, *b; 58{ 59while(--n >= 0) 60 if(*a++ != *b++) 61 return(NO); 62return(YES); 63} 64 65 66 67 68 69 70int 71cmpstr(a, b, la, lb) /* compare two strings */ 72register char *a, *b; 73ftnint la, lb; 74{ 75register char *aend, *bend; 76aend = a + la; 77bend = b + lb; 78 79 80if(la <= lb) 81 { 82 while(a < aend) 83 if(*a != *b) 84 return( *a - *b ); 85 else 86 { ++a; ++b; } 87 88 while(b < bend) 89 if(*b != ' ') 90 return(' ' - *b); 91 else 92 ++b; 93 } 94 95else 96 { 97 while(b < bend) 98 if(*a != *b) 99 return( *a - *b ); 100 else 101 { ++a; ++b; } 102 while(a < aend) 103 if(*a != ' ') 104 return(*a - ' '); 105 else 106 ++a; 107 } 108return(0); 109} 110 111 112 113 114 115chainp hookup(x,y) 116register chainp x, y; 117{ 118register chainp p; 119 120if(x == NULL) 121 return(y); 122 123for(p = x ; p->chain.nextp ; p = p->chain.nextp) 124 ; 125p->chain.nextp = y; 126return(x); 127} 128 129 130 131struct bigblock *mklist(p) 132chainp p; 133{ 134register struct bigblock *q; 135 136q = BALLO(); 137q->tag = TLIST; 138q->b_list.listp = p; 139return(q); 140} 141 142 143chainp 144mkchain(bigptr p, chainp q) 145{ 146 chainp r; 147 148 if(chains) { 149 r = chains; 150 chains = chains->chain.nextp; 151 } else 152 r = ALLOC(chain); 153 154 r->chain.datap = p; 155 r->chain.nextp = q; 156 return(r); 157} 158 159 160 161char * varstr(n, s) 162register int n; 163register char *s; 164{ 165register int i; 166static char name[XL+1]; 167 168for(i=0; i<n && *s!=' ' && *s!='\0' ; ++i) 169 name[i] = *s++; 170 171name[i] = '\0'; 172 173return( name ); 174} 175 176 177 178 179char * varunder(n, s) 180register int n; 181register char *s; 182{ 183register int i; 184static char name[XL+1]; 185 186for(i=0; i<n && *s!=' ' && *s!='\0' ; ++i) 187 name[i] = *s++; 188 189name[i] = '\0'; 190 191return( name ); 192} 193 194 195 196 197 198char * nounder(n, s) 199register int n; 200register char *s; 201{ 202register int i; 203static char name[XL+1]; 204 205for(i=0; i<n && *s!=' ' && *s!='\0' ; ++s) 206 if(*s != '_') 207 name[i++] = *s; 208 209name[i] = '\0'; 210 211return( name ); 212} 213 214/* 215 * Save a block on heap. 216 */ 217char * 218copyn(int n, char *s) 219{ 220 char *p, *q; 221 222 p = q = ckalloc(n); 223 while(--n >= 0) 224 *q++ = *s++; 225 return(p); 226} 227 228/* 229 * Save a string on heap. 230 */ 231char * 232copys(char *s) 233{ 234 return(copyn(strlen(s)+1 , s)); 235} 236 237/* 238 * convert a string to an int. 239 */ 240ftnint 241convci(int n, char *s) 242{ 243 ftnint sum; 244 sum = 0; 245 while(n-- > 0) 246 sum = 10*sum + (*s++ - '0'); 247 return(sum); 248} 249 250char *convic(n) 251ftnint n; 252{ 253static char s[20]; 254register char *t; 255 256s[19] = '\0'; 257t = s+19; 258 259do { 260 *--t = '0' + n%10; 261 n /= 10; 262 } while(n > 0); 263 264return(t); 265} 266 267 268 269double convcd(n, s) 270int n; 271register char *s; 272{ 273char v[100]; 274register char *t; 275if(n > 90) 276 { 277 err("too many digits in floating constant"); 278 n = 90; 279 } 280for(t = v ; n-- > 0 ; s++) 281 *t++ = (*s=='d' ? 'e' : *s); 282*t = '\0'; 283return( atof(v) ); 284} 285 286 287 288struct bigblock *mkname(l, s) 289int l; 290register char *s; 291{ 292struct hashentry *hp; 293int hash; 294register struct bigblock *q; 295register int i; 296char n[VL]; 297 298hash = 0; 299for(i = 0 ; i<l && *s!='\0' ; ++i) 300 { 301 hash += *s; 302 n[i] = *s++; 303 } 304hash %= MAXHASH; 305while( i < VL ) 306 n[i++] = ' '; 307 308hp = hashtab + hash; 309while((q = hp->varp)) 310 if( hash==hp->hashval && eqn(VL,n,q->b_name.varname) ) 311 return(q); 312 else if(++hp >= lasthash) 313 hp = hashtab; 314 315if(++nintnames >= MAXHASH-1) 316 fatal("hash table full"); 317hp->varp = q = BALLO(); 318hp->hashval = hash; 319q->tag = TNAME; 320cpn(VL, n, q->b_name.varname); 321return(q); 322} 323 324 325 326struct labelblock *mklabel(l) 327ftnint l; 328{ 329register struct labelblock *lp; 330 331if(l == 0) 332 return(0); 333 334for(lp = labeltab ; lp < highlabtab ; ++lp) 335 if(lp->stateno == l) 336 return(lp); 337 338if(++highlabtab >= labtabend) 339 fatal("too many statement numbers"); 340 341lp->stateno = l; 342lp->labelno = newlabel(); 343lp->blklevel = 0; 344lp->labused = NO; 345lp->labdefined = NO; 346lp->labinacc = NO; 347lp->labtype = LABUNKNOWN; 348return(lp); 349} 350 351int 352newlabel() 353{ 354return( lastlabno++ ); 355} 356 357 358/* find or put a name in the external symbol table */ 359 360struct extsym *mkext(s) 361char *s; 362{ 363int i; 364register char *t; 365char n[XL]; 366struct extsym *p; 367 368i = 0; 369t = n; 370while(i<XL && *s) 371 *t++ = *s++; 372while(t < n+XL) 373 *t++ = ' '; 374 375for(p = extsymtab ; p<nextext ; ++p) 376 if(eqn(XL, n, p->extname)) 377 return( p ); 378 379if(nextext >= lastext) 380 fatal("too many external symbols"); 381 382cpn(XL, n, nextext->extname); 383nextext->extstg = STGUNKNOWN; 384nextext->extsave = NO; 385nextext->extp = 0; 386nextext->extleng = 0; 387nextext->maxleng = 0; 388nextext->extinit = NO; 389return( nextext++ ); 390} 391 392 393 394 395 396 397 398 399struct bigblock *builtin(t, s) 400int t; 401char *s; 402{ 403register struct extsym *p; 404register struct bigblock *q; 405 406p = mkext(s); 407if(p->extstg == STGUNKNOWN) 408 p->extstg = STGEXT; 409else if(p->extstg != STGEXT) 410 { 411 err1("improper use of builtin %s", s); 412 return(0); 413 } 414 415q = BALLO(); 416q->tag = TADDR; 417q->vtype = t; 418q->vclass = CLPROC; 419q->vstg = STGEXT; 420q->b_addr.memno = p - extsymtab; 421return(q); 422} 423 424 425void 426frchain(p) 427register chainp *p; 428{ 429register chainp q; 430 431if(p==0 || *p==0) 432 return; 433 434for(q = *p; q->chain.nextp ; q = q->chain.nextp) 435 ; 436q->chain.nextp = chains; 437chains = *p; 438*p = 0; 439} 440 441 442ptr cpblock(n,p) 443register int n; 444register void * p; 445{ 446register char *q, *r = p; 447ptr q0; 448 449q = q0 = ckalloc(n); 450while(n-- > 0) 451 *q++ = *r++; 452return(q0); 453} 454 455 456int 457max(a,b) 458int a,b; 459{ 460return( a>b ? a : b); 461} 462 463 464ftnint lmax(a, b) 465ftnint a, b; 466{ 467return( a>b ? a : b); 468} 469 470ftnint lmin(a, b) 471ftnint a, b; 472{ 473return(a < b ? a : b); 474} 475 476 477 478int 479maxtype(t1, t2) 480int t1, t2; 481{ 482int t; 483 484t = max(t1, t2); 485if(t==TYCOMPLEX && (t1==TYDREAL || t2==TYDREAL) ) 486 t = TYDCOMPLEX; 487return(t); 488} 489 490 491 492/* return log base 2 of n if n a power of 2; otherwise -1 */ 493int 494flog2(n) 495ftnint n; 496{ 497int k; 498 499/* trick based on binary representation */ 500 501if(n<=0 || (n & (n-1))!=0) 502 return(-1); 503 504for(k = 0 ; n >>= 1 ; ++k) 505 ; 506return(k); 507} 508 509 510void 511frrpl() 512{ 513chainp rp; 514 515while(rpllist) 516 { 517 rp = rpllist->rplblock.nextp; 518 ckfree(rpllist); 519 rpllist = rp; 520 } 521} 522 523void 524popstack(p) 525register chainp *p; 526{ 527register chainp q; 528 529if(p==NULL || *p==NULL) 530 fatal("popstack: stack empty"); 531q = (*p)->chain.nextp; 532ckfree(*p); 533*p = q; 534} 535 536 537 538struct bigblock * 539callk(type, name, args) 540int type; 541char *name; 542bigptr args; 543{ 544register struct bigblock *p; 545 546p = mkexpr(OPCALL, builtin(type,name), args); 547p->vtype = type; 548return(p); 549} 550 551 552 553struct bigblock * 554call4(type, name, arg1, arg2, arg3, arg4) 555int type; 556char *name; 557bigptr arg1, arg2, arg3, arg4; 558{ 559struct bigblock *args; 560args = mklist( mkchain(arg1, mkchain(arg2, mkchain(arg3, mkchain(arg4, NULL)) ) ) ); 561return( callk(type, name, args) ); 562} 563 564 565 566 567struct bigblock *call3(type, name, arg1, arg2, arg3) 568int type; 569char *name; 570bigptr arg1, arg2, arg3; 571{ 572struct bigblock *args; 573args = mklist( mkchain(arg1, mkchain(arg2, mkchain(arg3, NULL) ) ) ); 574return( callk(type, name, args) ); 575} 576 577 578 579 580 581struct bigblock * 582call2(type, name, arg1, arg2) 583int type; 584char *name; 585bigptr arg1, arg2; 586{ 587bigptr args; 588 589args = mklist( mkchain(arg1, mkchain(arg2, NULL) ) ); 590return( callk(type,name, args) ); 591} 592 593 594 595 596struct bigblock *call1(type, name, arg) 597int type; 598char *name; 599bigptr arg; 600{ 601return( callk(type,name, mklist(mkchain(arg,0)) )); 602} 603 604 605struct bigblock *call0(type, name) 606int type; 607char *name; 608{ 609return( callk(type, name, NULL) ); 610} 611 612 613 614struct bigblock * 615mkiodo(dospec, list) 616chainp dospec, list; 617{ 618register struct bigblock *q; 619 620q = BALLO(); 621q->tag = TIMPLDO; 622q->b_impldo.varnp = (struct bigblock *)dospec; 623q->b_impldo.datalist = list; 624return(q); 625} 626 627 628 629 630ptr 631ckalloc(int n) 632{ 633 ptr p; 634 635 if ((p = calloc(1, (unsigned) n)) == NULL) 636 fatal("out of memory"); 637#ifdef PCC_DEBUG 638 if (mflag) 639 printf("ckalloc: sz %d ptr %p\n", n, p); 640#endif 641 return(p); 642} 643 644void 645ckfree(void *p) 646{ 647#ifdef PCC_DEBUG 648 if (mflag) 649 printf("ckfree: ptr %p\n", p); 650#endif 651 free(p); 652} 653 654#if 0 655int 656isaddr(p) 657register bigptr p; 658{ 659if(p->tag == TADDR) 660 return(YES); 661if(p->tag == TEXPR) 662 switch(p->b_expr.opcode) 663 { 664 case OPCOMMA: 665 return( isaddr(p->b_expr.rightp) ); 666 667 case OPASSIGN: 668 case OPPLUSEQ: 669 return( isaddr(p->b_expr.leftp) ); 670 } 671return(NO); 672} 673#endif 674 675/* 676 * Return YES if not an expression. 677 */ 678int 679addressable(bigptr p) 680{ 681 switch(p->tag) { 682 case TCONST: 683 return(YES); 684 685 case TADDR: 686 return( addressable(p->b_addr.memoffset) ); 687 688 default: 689 return(NO); 690 } 691} 692 693 694int 695hextoi(c) 696register int c; 697{ 698register char *p; 699static char p0[17] = "0123456789abcdef"; 700 701for(p = p0 ; *p ; ++p) 702 if(*p == c) 703 return( p-p0 ); 704return(16); 705} 706