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[] = "@(#)f77.c 5.4 (Berkeley) 01/03/88"; 9 #endif 10 11 /* 12 * f77.c 13 * 14 * Driver program for the 4.2 BSD f77 compiler. 15 * 16 * University of Utah CS Dept modification history: 17 * 18 * $Log: f77.c,v $ 19 * Revision 5.4 85/12/17 19:12:14 donn 20 * Dynamically allocate buffer; add lint fixes. 21 * 22 * Revision 5.3 85/11/25 00:00:02 donn 23 * 4.3 beta 24 * 25 * Revision 5.2 85/08/10 05:16:14 donn 26 * Ifdeffed 66 code, added -r8 flag. From Jerry Berkman. 27 * 28 * Revision 5.1 85/08/10 03:32:12 donn 29 * 4.3 alpha 30 * 31 * Revision 1.14 85/03/01 00:07:57 donn 32 * Portability fix from Ralph Campbell. 33 * 34 * Revision 1.13 85/02/12 19:31:47 donn 35 * Use CATNAME to get the name of a concatenation command instead of 36 * explicitly running 'cat' -- you can get the wrong 'cat' the old way! 37 * 38 * Revision 1.12 85/01/14 06:42:30 donn 39 * Changed to call the peephole optimizer with the '-f' flag, so that 40 * floating point moves are translated to integer moves. 41 * 42 * Revision 1.11 85/01/14 04:38:59 donn 43 * Jerry's change to pass -O to f1 so it knows whether the peephole optimizer 44 * will be run. This is necessary in order to handle movf/movl translation. 45 * 46 * Revision 1.10 85/01/14 03:59:12 donn 47 * Added Jerry Berkman's fix for the '-q' flag. 48 * 49 * Revision 1.9 84/11/09 01:51:26 donn 50 * Cosmetic change to stupid() suggested by John McCarthy at Memorial 51 * University, St. Johns. 52 * 53 * Revision 1.8 84/09/14 16:02:34 donn 54 * Added changes to notice when people do 'f77 -c foo.f -o bar.o' and tell 55 * them why it doesn't do what they think it does. 56 * 57 * Revision 1.7 84/08/24 21:08:31 donn 58 * Added call to setrlimit() to prevent core dumps when not debugging. 59 * Reorganized the include file arrangment somewhat. 60 * 61 * Revision 1.6 84/08/24 20:20:24 donn 62 * Changed stupidity check on Jerry Berkman's suggestion -- now it balks if 63 * the load file exists and has a sensitive suffix. 64 * 65 * Revision 1.5 84/08/15 18:56:44 donn 66 * Added test for -O combined with -g, suggested by Raleigh Romine. To keep 67 * things simple, if both are specified then the second in the list is thrown 68 * out and the user is warned. 69 * 70 * Revision 1.4 84/08/05 21:33:15 donn 71 * Added stupidity check -- f77 won't load on a file that it's asked to 72 * compile as well. 73 * 74 * Revision 1.3 84/08/04 22:58:24 donn 75 * Improved error reporting -- we now explain why we died and what we did. 76 * Only works on 4.2. Added at the instigation of Jerry Berkman. 77 * 78 * Revision 1.2 84/07/28 13:11:24 donn 79 * Added Ralph Campbell's changes to reduce offsets to data. 80 * 81 */ 82 83 char *xxxvers = "\n@(#) F77 DRIVER, VERSION 4.2, 1984 JULY 28\n"; 84 #include <stdio.h> 85 #include <sys/types.h> 86 #include <sys/stat.h> 87 #include <ctype.h> 88 #include <signal.h> 89 90 #ifdef SIGPROF 91 /* 92 * Some 4.2 BSD capabilities. 93 */ 94 #include <sys/time.h> 95 #include <sys/resource.h> 96 #define NOCORE 1 97 #include <sys/wait.h> 98 #define PSIGNAL 1 99 #endif 100 101 #include "defines.h" 102 #include "machdefs.h" 103 #include "drivedefs.h" 104 #include "version.h" 105 106 static FILEP diagfile = {stderr} ; 107 static int pid; 108 static int sigivalue = 0; 109 static int sigqvalue = 0; 110 static int sighvalue = 0; 111 static int sigtvalue = 0; 112 113 static char *pass1name = PASS1NAME ; 114 static char *pass2name = PASS2NAME ; 115 static char *pass2opt = PASS2OPT ; 116 static char *asmname = ASMNAME ; 117 static char *ldname = LDNAME ; 118 static char *footname = FOOTNAME; 119 static char *proffoot = PROFFOOT; 120 static char *macroname = "m4"; 121 static char *shellname = "/bin/sh"; 122 static char *cppname = "/lib/cpp"; 123 static char *aoutname = "a.out" ; 124 static char *temppref = TEMPPREF; 125 126 static char *infname; 127 static char textfname[44]; 128 static char asmfname[44]; 129 static char asmpass2[44]; 130 static char initfname[44]; 131 static char sortfname[44]; 132 static char prepfname[44]; 133 static char objfdefault[44]; 134 static char optzfname[44]; 135 static char setfname[44]; 136 137 static char fflags[50] = "-"; 138 static char f2flags[50]; 139 static char cflags[50] = "-c"; 140 #if TARGET == GCOS 141 static char eflags[30] = "system=gcos "; 142 #else 143 static char eflags[30] = "system=unix "; 144 #endif 145 static char rflags[30] = ""; 146 static char lflag[3] = "-x"; 147 static char *fflagp = fflags+1; 148 static char *f2flagp = f2flags; 149 static char *eflagp = eflags+12; 150 static char *rflagp = rflags; 151 static char *cppflags = ""; 152 static char **cppargs; 153 static char **loadargs; 154 static char **loadp; 155 156 static flag erred = NO; 157 static flag loadflag = YES; 158 static flag saveasmflag = NO; 159 static flag profileflag = NO; 160 static flag optimflag = NO; 161 static flag debugflag = NO; 162 static flag verbose = NO; 163 static flag fortonly = NO; 164 static flag macroflag = NO; 165 static flag sdbflag = NO; 166 static flag namesflag = YES; 167 168 #if TARGET == PDP11 169 static flag nofloating = NO; 170 #endif 171 172 static int ncpp; 173 174 175 main(argc, argv) 176 int argc; 177 char **argv; 178 { 179 register int i, n; 180 int c, status; 181 char *setdoto(), *lastchar(), *lastfield(), *copys(), *argvtos(); 182 ptr ckalloc(); 183 char *strcat(); 184 register char *s; 185 char fortfile[20], *t; 186 char *buff; 187 int intrupt(); 188 int new_aoutname = NO; 189 190 sigivalue = signal(SIGINT, SIG_IGN) == SIG_IGN; 191 sigqvalue = signal(SIGQUIT,SIG_IGN) == SIG_IGN; 192 sighvalue = signal(SIGHUP, SIG_IGN) == SIG_IGN; 193 sigtvalue = signal(SIGTERM,SIG_IGN) == SIG_IGN; 194 enbint(intrupt); 195 196 pid = getpid(); 197 crfnames(); 198 199 cppargs = (char **) ckalloc( argc * sizeof(*cppargs) ); 200 loadargs = (char **) ckalloc( (argc+20) * sizeof(*loadargs) ); 201 loadargs[1] = "-X"; 202 loadargs[2] = "-u"; 203 #if HERE==PDP11 || HERE==VAX 204 loadargs[3] = "_MAIN_"; 205 #endif 206 #if HERE == INTERDATA 207 loadargs[3] = "main"; 208 #endif 209 loadp = loadargs + 4; 210 211 --argc; 212 ++argv; 213 214 for (i = 0, n = 50; i < argc; ++i) 215 n += strlen(argv[i]) + 1; 216 buff = (char *) ckalloc(n); 217 218 while(argc>0 && argv[0][0]=='-' && argv[0][1]!='\0') 219 { 220 for(s = argv[0]+1 ; *s ; ++s) switch(*s) 221 { 222 case 'T': /* use special passes */ 223 switch(*++s) 224 { 225 case '1': 226 pass1name = s+1; goto endfor; 227 case '2': 228 pass2name = s+1; goto endfor; 229 case 'p': 230 pass2opt = s+1; goto endfor; 231 case 'a': 232 asmname = s+1; goto endfor; 233 case 'l': 234 ldname = s+1; goto endfor; 235 case 'F': 236 footname = s+1; goto endfor; 237 case 'm': 238 macroname = s+1; goto endfor; 239 case 't': 240 temppref = s+1; goto endfor; 241 default: 242 fatali("bad option -T%c", *s); 243 } 244 break; 245 246 #ifdef ONLY66 247 case '6': 248 if(s[1]=='6') 249 { 250 *fflagp++ = *s++; 251 goto copyfflag; 252 } 253 else { 254 fprintf(diagfile, "invalid flag 6%c\n", s[1]); 255 done(1); 256 } 257 #endif 258 259 case 'w': 260 if(s[1]=='6' && s[2]=='6') 261 { 262 *fflagp++ = *s++; 263 *fflagp++ = *s++; 264 } 265 266 copyfflag: 267 case 'u': 268 case 'U': 269 case '1': 270 case 'C': 271 *fflagp++ = *s; 272 break; 273 274 case 'O': 275 if(sdbflag) 276 { 277 fprintf(diagfile, "-O and -g are incompatible; -O ignored\n"); 278 break; 279 } 280 optimflag = YES; 281 *f2flagp++ = '-'; 282 *f2flagp++ = 'O'; 283 *f2flagp++ = ' '; 284 #if TARGET == INTERDATA 285 *loadp++ = "-r"; 286 *loadp++ = "-d"; 287 #endif 288 *fflagp++ = 'O'; 289 break; 290 291 case 'N': 292 *fflagp++ = 'N'; 293 if( oneof(*++s, "qxscn") ) 294 *fflagp++ = *s++; 295 else { 296 fprintf(diagfile, "invalid flag -N%c\n", *s); 297 done(1); 298 } 299 while( isdigit(*s) ) 300 *fflagp++ = *s++; 301 *fflagp++ = 'X'; 302 goto endfor; 303 304 case 'm': 305 if(s[1] == '4') 306 ++s; 307 macroflag = YES; 308 break; 309 310 case 'S': 311 (void) strcat(cflags, " -S"); 312 saveasmflag = YES; 313 314 case 'c': 315 if( new_aoutname == YES ){ 316 fprintf(diagfile, "-c prevents loading, -o %s ignored\n", aoutname); 317 new_aoutname = NO; 318 } 319 loadflag = NO; 320 break; 321 322 case 'v': 323 verbose = YES; 324 fprintf(diagfile,"\nBerkeley F77, version %s\n", 325 VERSIONNUMBER); 326 break; 327 328 case 'd': 329 debugflag = YES; 330 *fflagp++ = 'd'; 331 s++; 332 while( isdigit(*s) || *s == ',' ) 333 *fflagp++ = *s++; 334 *fflagp++ = 'X'; 335 goto endfor; 336 337 case 'M': 338 *loadp++ = "-M"; 339 break; 340 341 case 'g': 342 if(optimflag) 343 { 344 fprintf(diagfile, "-g and -O are incompatible; -g ignored\n"); 345 break; 346 } 347 (void) strcat(cflags," -g"); 348 sdbflag = YES; 349 goto copyfflag; 350 351 case 'p': 352 profileflag = YES; 353 (void) strcat(cflags," -p"); 354 *fflagp++ = 'p'; 355 if(s[1] == 'g') 356 { 357 proffoot = GPRFFOOT; 358 s++; 359 } 360 break; 361 362 case 'q': 363 namesflag = NO; 364 *fflagp++ = *s; 365 break; 366 367 case 'o': 368 if( ! strcmp(s, "onetrip") ) 369 { 370 *fflagp++ = '1'; 371 goto endfor; 372 } 373 new_aoutname = YES; 374 aoutname = *++argv; 375 --argc; 376 if( loadflag == NO ){ 377 fprintf(diagfile, "-c prevents loading, -o %s ignored\n", aoutname); 378 new_aoutname = NO; 379 } 380 break; 381 382 #if TARGET == PDP11 383 case 'f': 384 nofloating = YES; 385 pass2name = NOFLPASS2; 386 break; 387 #endif 388 389 case 'F': 390 fortonly = YES; 391 loadflag = NO; 392 break; 393 case 'D': 394 case 'I': 395 cppargs[ncpp++] = *argv; 396 goto endfor; 397 398 case 'i': 399 if((s[1]=='2' || s[1]=='4') && s[2] == '\0') 400 { 401 *fflagp++ = *s++; 402 goto copyfflag; 403 } 404 fprintf(diagfile, "invalid flag -i%c\n", s[1]); 405 done(1); 406 407 case 'r': /* -r8 - double the precision */ 408 if(s[1] == '8' && s[2] == '\0') 409 { 410 s++; 411 goto copyfflag; 412 } 413 else 414 { 415 *loadp++ = "-r"; 416 break; 417 } 418 419 case 'l': /* letter ell--library */ 420 s[-1] = '-'; 421 *loadp++ = s-1; 422 goto endfor; 423 424 case 'E': /* EFL flag argument */ 425 while( *eflagp++ = *++s) 426 ; 427 *eflagp++ = ' '; 428 goto endfor; 429 case 'R': 430 while( *rflagp++ = *++s ) 431 ; 432 *rflagp++ = ' '; 433 goto endfor; 434 default: 435 lflag[1] = *s; 436 *loadp++ = copys(lflag); 437 break; 438 } 439 endfor: 440 --argc; 441 ++argv; 442 } 443 444 #ifdef NOCORE 445 if(!debugflag) 446 { 447 struct rlimit r; 448 449 r.rlim_cur = r.rlim_max = 0; 450 (void) setrlimit(RLIMIT_CORE, &r); 451 } 452 #endif NOCORE 453 454 *fflagp = '\0'; 455 456 if (ncpp > 0) 457 cppflags = argvtos (ncpp,cppargs); 458 459 loadargs[0] = ldname; 460 #if TARGET == PDP11 461 if(nofloating) 462 *loadp++ = (profileflag ? NOFLPROF : NOFLFOOT); 463 else 464 #endif 465 *loadp++ = (profileflag ? proffoot : footname); 466 467 for(i = 0 ; i<argc ; ++i) 468 switch(c = dotchar(infname = argv[i]) ) 469 { 470 case 'r': /* Ratfor file */ 471 case 'e': /* EFL file */ 472 if( unreadable(argv[i]) ) 473 { 474 erred = YES; 475 break; 476 } 477 s = fortfile; 478 t = lastfield(argv[i]); 479 while( *s++ = *t++) 480 ; 481 s[-2] = 'f'; 482 483 if(macroflag) 484 { 485 sprintf(buff, "%s %s >%s", macroname, infname, prepfname); 486 if( sys(buff) ) 487 { 488 rmf(prepfname); 489 erred = YES; 490 break; 491 } 492 infname = prepfname; 493 } 494 495 if(c == 'e') 496 sprintf(buff, "efl %s %s >%s", eflags, infname, fortfile); 497 else 498 sprintf(buff, "ratfor %s %s >%s", rflags, infname, fortfile); 499 status = sys(buff); 500 if(macroflag) 501 rmf(infname); 502 if(status) 503 { 504 erred = YES; 505 rmf(fortfile); 506 break; 507 } 508 509 if( ! fortonly ) 510 { 511 infname = argv[i] = lastfield(argv[i]); 512 *lastchar(infname) = 'f'; 513 514 if( dofort(argv[i]) ) 515 erred = YES; 516 else { 517 if( nodup(t = setdoto(argv[i])) ) 518 *loadp++ = t; 519 rmf(fortfile); 520 } 521 } 522 break; 523 524 case 'F': /* C preprocessor -> Fortran file */ 525 if( unreadable(argv[i]) ) 526 { 527 erred = YES; 528 break; 529 } 530 s = fortfile; 531 t = lastfield(argv[i]); 532 while( *s++ = *t++) 533 ; 534 s[-2] = 'f'; 535 sprintf(buff,"%s %s %s >%s", cppname, cppflags, infname, fortfile); 536 status = sys(buff); 537 if(status) 538 { 539 erred = YES; 540 rmf(fortfile); 541 break; 542 } 543 544 if( ! fortonly ) 545 { 546 infname = argv[i] = lastfield(argv[i]); 547 *lastchar(infname) = 'f'; 548 549 if ( dofort(argv[i]) ) 550 erred = YES; 551 else { 552 if (nodup(t = setdoto(argv[i])) ) 553 *loadp++ = t; 554 rmf(fortfile); 555 } 556 } 557 break; 558 559 case 'f': /* Fortran file */ 560 if( unreadable(argv[i]) ) 561 erred = YES; 562 else if( dofort(argv[i]) ) 563 erred = YES; 564 else if( nodup(t=setdoto(argv[i])) ) 565 *loadp++ = t; 566 break; 567 568 case 'c': /* C file */ 569 case 's': /* Assembler file */ 570 if( unreadable(argv[i]) ) 571 { 572 erred = YES; 573 break; 574 } 575 #if HERE==PDP11 || HERE==VAX 576 if( namesflag == YES ) 577 fprintf(diagfile, "%s:\n", argv[i]); 578 #endif 579 sprintf(buff, "cc %s %s", cflags, argv[i] ); 580 if( sys(buff) ) 581 erred = YES; 582 else 583 if( nodup(t = setdoto(argv[i])) ) 584 *loadp++ = t; 585 break; 586 587 case 'o': 588 if( nodup(argv[i]) ) 589 *loadp++ = argv[i]; 590 break; 591 592 default: 593 if( ! strcmp(argv[i], "-o") ) { 594 aoutname = argv[++i]; 595 new_aoutname = YES; 596 if( loadflag == NO ){ 597 fprintf(diagfile, "-c prevents loading, -o %s ignored\n", aoutname); 598 new_aoutname = NO; 599 } 600 } else 601 *loadp++ = argv[i]; 602 break; 603 } 604 605 if( loadflag && stupid(aoutname) ) 606 erred = YES; 607 if(loadflag && !erred) 608 doload(loadargs, loadp); 609 done(erred); 610 } 611 612 613 614 /* 615 * argvtos() copies a list of arguments contained in an array of character 616 * strings to a single dynamically allocated string. Each argument is 617 * separated by one blank space. Returns a pointer to the string or null 618 * if out of memory. 619 */ 620 #define SBUFINCR 1024 621 #define SBUFMAX 10240 622 623 char * 624 argvtos(argc, argv) 625 char **argv; 626 int argc; 627 { 628 register char *s; /* string pointer */ 629 register int i; /* string buffer pointer */ 630 char *malloc(); /* memory allocator */ 631 char *realloc(); /* increase size of storage */ 632 char *sbuf; /* string buffer */ 633 int nbytes; /* bytes of memory required */ 634 int nu; /* no. of SBUFINCR units required */ 635 int sbufsize; /* current size of sbuf */ 636 int strlen(); /* string length */ 637 638 sbufsize = SBUFINCR; 639 if ((sbuf = malloc((unsigned)sbufsize)) == NULL) 640 { 641 fatal("out of memory (argvtos)"); 642 /* NOTREACHED */ 643 } 644 645 for (i = 0; argc-- > 0; ++argv) 646 { 647 if ((nbytes = (i+strlen(*argv)+1-sbufsize)) > 0) 648 { 649 nu = (nbytes+SBUFINCR-1)/SBUFINCR; 650 sbufsize += nu * SBUFINCR; 651 if (sbufsize > SBUFMAX) 652 { 653 fatal("argument length exceeded (argvtos)"); 654 /* NOTREACHED */ 655 } 656 if ((sbuf = realloc(sbuf, (unsigned)sbufsize)) == NULL) 657 { 658 fatal("out of memory (argvtos)"); 659 /* NOTREACHED */ 660 } 661 } 662 for (s = *argv; *s != '\0'; i++, s++) 663 sbuf[i] = *s; 664 sbuf[i++] = ' '; 665 } 666 sbuf[--i] = '\0'; 667 return(sbuf); 668 } 669 670 dofort(s) 671 char *s; 672 { 673 int retcode; 674 char buff[200]; 675 676 infname = s; 677 sprintf(buff, "%s %s %s %s %s %s", 678 pass1name, fflags, s, asmfname, initfname, textfname); 679 switch( sys(buff) ) 680 { 681 case 1: 682 goto error; 683 case 0: 684 break; 685 default: 686 goto comperror; 687 } 688 689 if( dopass2() ) 690 goto comperror; 691 doasm(s); 692 retcode = 0; 693 694 ret: 695 rmf(asmfname); 696 rmf(initfname); 697 rmf(textfname); 698 return(retcode); 699 700 error: 701 fprintf(diagfile, "\nError. No assembly.\n"); 702 retcode = 1; 703 goto ret; 704 705 comperror: 706 fprintf(diagfile, "\ncompiler error.\n"); 707 retcode = 2; 708 goto ret; 709 } 710 711 712 713 714 dopass2() 715 { 716 char buff[100]; 717 718 if(verbose) 719 fprintf(diagfile, "PASS2."); 720 721 #if FAMILY==DMR 722 sprintf(buff, "%s %s - %s", pass2name, textfname, asmpass2); 723 return( sys(buff) ); 724 #endif 725 726 727 #if FAMILY == PCC 728 # if TARGET==INTERDATA 729 sprintf(buff, "%s -A%s <%s >%s", pass2name, setfname, textfname, asmpass2); 730 # else 731 sprintf(buff, "%s %s %s >%s", 732 pass2name, f2flags, textfname, asmpass2); 733 # endif 734 return( sys(buff) ); 735 #endif 736 } 737 738 739 740 741 doasm(s) 742 char *s; 743 { 744 register char *lastc; 745 char *obj; 746 char buff[200]; 747 char *lastchar(), *setdoto(); 748 749 if(*s == '\0') 750 s = objfdefault; 751 lastc = lastchar(s); 752 obj = setdoto(s); 753 754 #if TARGET==PDP11 || TARGET==VAX 755 # ifdef PASS2OPT 756 if(optimflag) 757 { 758 sprintf(buff, "%s -f %s %s", pass2opt, asmpass2, optzfname); 759 if( sys(buff) ) 760 rmf(optzfname); 761 else 762 { 763 sprintf(buff,"mv %s %s", optzfname, asmpass2); 764 if( sys(buff) ) 765 fatal("can't rename optimizer output file"); 766 } 767 } 768 # endif 769 #endif 770 771 if(saveasmflag) 772 { 773 *lastc = 's'; 774 #if TARGET == INTERDATA 775 sprintf(buff, "%s %s %s %s %s >%s", CATNAME, asmfname, initfname, 776 setfname, asmpass2, obj); 777 #else 778 #if TARGET == VAX 779 if (sdbflag) 780 sprintf(buff, "%s %s %s %s >%s", 781 CATNAME, asmfname, asmpass2, initfname, obj); 782 else 783 sprintf(buff, "%s %s %s %s >%s", 784 CATNAME, asmfname, initfname, asmpass2, obj); 785 #else 786 sprintf(buff, "%s %s %s %s >%s", 787 CATNAME, asmfname, initfname, asmpass2, obj); 788 #endif 789 #endif 790 if( sys(buff) ) 791 fatal("can't concatenate assembly files"); 792 *lastc = 'o'; 793 } 794 else 795 { 796 if(verbose) 797 fprintf(diagfile, " ASM."); 798 #if TARGET == INTERDATA 799 sprintf(buff, "%s -o %s %s %s %s %s", asmname, obj, asmfname, 800 initfname, setfname, asmpass2); 801 #endif 802 803 #if TARGET == VAX 804 /* vax assembler currently accepts only one input file */ 805 if (sdbflag) 806 sprintf(buff, "%s %s %s >>%s", 807 CATNAME, asmpass2, initfname, asmfname); 808 else 809 sprintf(buff, "%s %s %s >>%s", 810 CATNAME, initfname, asmpass2, asmfname); 811 if( sys(buff) ) 812 fatal("can't concatenate assembly files"); 813 #ifdef UCBVAXASM 814 sprintf(buff, "%s -J -o %s %s", asmname, obj, asmfname); 815 #else 816 sprintf(buff, "%s -o %s %s", asmname, obj, asmfname); 817 #endif 818 #endif 819 820 #if TARGET == PDP11 821 sprintf(buff, "%s -u -o %s %s %s", asmname, obj, asmfname, asmpass2); 822 #endif 823 824 #if TARGET!=INTERDATA && TARGET!=PDP11 && TARGET!=VAX 825 sprintf(buff, "%s -o %s %s %s", asmname, obj, asmfname, asmpass2); 826 #endif 827 828 if( sys(buff) ) 829 fatal("assembler error"); 830 if(verbose) 831 fprintf(diagfile, "\n"); 832 #if HERE==PDP11 && TARGET!=PDP11 833 rmf(obj); 834 #endif 835 } 836 837 rmf(asmpass2); 838 } 839 840 841 842 doload(v0, v) 843 register char *v0[], *v[]; 844 { 845 char **p; 846 int waitpid; 847 848 if(sdbflag) 849 *v++ = "-lg"; 850 if (profileflag) 851 { 852 for(p = p_liblist ; *p ; *v++ = *p++) 853 ; 854 } 855 else { 856 for(p = liblist ; *p ; *v++ = *p++) 857 ; 858 } 859 860 *v++ = "-o"; 861 *v++ = aoutname; 862 *v = NULL; 863 864 if(verbose) 865 fprintf(diagfile, "LOAD."); 866 if(debugflag) 867 { 868 for(p = v0 ; p<v ; ++p) 869 fprintf(diagfile, "%s ", *p); 870 fprintf(diagfile, "\n"); 871 } 872 873 #if HERE==PDP11 || HERE==INTERDATA || HERE==VAX 874 if( (waitpid = fork()) == 0) 875 { 876 enbint(SIG_DFL); 877 execv(ldname, v0); 878 fatalstr("couldn't load %s", ldname); 879 } 880 if( await(waitpid) ) 881 erred = YES; 882 #endif 883 884 #if HERE==INTERDATA 885 if(optimflag) 886 { 887 char buff1[100], buff2[100]; 888 sprintf(buff1, "nopt %s -o junk.%d", aoutname, pid); 889 sprintf(buff2, "mv junk.%d %s", pid, aoutname); 890 if( sys(buff1) || sys(buff2) ) 891 err("bad optimization"); 892 } 893 #endif 894 895 if(verbose) 896 fprintf(diagfile, "\n"); 897 } 898 899 /* Process control and Shell-simulating routines */ 900 901 sys(str) 902 char *str; 903 { 904 register char *s, *t; 905 char *argv[100], path[100]; 906 char *inname, *outname; 907 int append; 908 int waitpid; 909 int argc; 910 911 912 if(debugflag) 913 fprintf(diagfile, "%s\n", str); 914 inname = NULL; 915 outname = NULL; 916 argv[0] = shellname; 917 argc = 1; 918 919 t = str; 920 while( isspace(*t) ) 921 ++t; 922 while(*t) 923 { 924 if(*t == '<') 925 inname = t+1; 926 else if(*t == '>') 927 { 928 if(t[1] == '>') 929 { 930 append = YES; 931 outname = t+2; 932 } 933 else { 934 append = NO; 935 outname = t+1; 936 } 937 } 938 else 939 argv[argc++] = t; 940 while( !isspace(*t) && *t!='\0' ) 941 ++t; 942 if(*t) 943 { 944 *t++ = '\0'; 945 while( isspace(*t) ) 946 ++t; 947 } 948 } 949 950 if(argc == 1) /* no command */ 951 return(-1); 952 argv[argc] = 0; 953 954 s = path; 955 t = "/usr/bin/"; 956 while(*t) 957 *s++ = *t++; 958 for(t = argv[1] ; *s++ = *t++ ; ) 959 ; 960 if((waitpid = fork()) == 0) 961 { 962 if(inname) 963 if(freopen(inname, "r", stdin) == NULL) 964 fatalstr("Cannot open %s", inname); 965 if(outname) 966 if(freopen(outname, (append ? "a" : "w"), stdout) == NULL) 967 fatalstr("Cannot open %s", outname); 968 enbint(SIG_DFL); 969 970 texec(path+9, argv); /* command */ 971 texec(path+4, argv); /* /bin/command */ 972 texec(path , argv); /* /usr/bin/command */ 973 974 fatalstr("Cannot load %s",path+9); 975 } 976 977 return( await(waitpid) ); 978 } 979 980 981 982 983 984 #include "errno.h" 985 986 /* modified version from the Shell */ 987 texec(f, av) 988 char *f; 989 char **av; 990 { 991 extern int errno; 992 993 execv(f, av+1); 994 995 if (errno==ENOEXEC) 996 { 997 av[1] = f; 998 execv(shellname, av); 999 fatal("No shell!"); 1000 } 1001 if (errno==ENOMEM) 1002 fatalstr("%s: too large", f); 1003 } 1004 1005 1006 1007 1008 1009 1010 done(k) 1011 int k; 1012 { 1013 static int recurs = NO; 1014 1015 if(recurs == NO) 1016 { 1017 recurs = YES; 1018 rmfiles(); 1019 } 1020 exit(k); 1021 } 1022 1023 1024 1025 1026 1027 1028 enbint(k) 1029 int (*k)(); 1030 { 1031 if(sigivalue == 0) 1032 (void) signal(SIGINT,k); 1033 if(sigqvalue == 0) 1034 (void) signal(SIGQUIT,k); 1035 if(sighvalue == 0) 1036 (void) signal(SIGHUP,k); 1037 if(sigtvalue == 0) 1038 (void) signal(SIGTERM,k); 1039 } 1040 1041 1042 1043 1044 intrupt() 1045 { 1046 done(2); 1047 } 1048 1049 1050 #ifdef PSIGNAL 1051 /* 1052 * Fancy 4.2 BSD signal printing stuff. 1053 */ 1054 char harmless[NSIG] = { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 }; 1055 #endif 1056 1057 1058 await(waitpid) 1059 int waitpid; 1060 { 1061 1062 #ifdef PSIGNAL 1063 extern char *sys_siglist[]; 1064 union wait status; 1065 #else PSIGNAL 1066 int status; 1067 #endif PSIGNAL 1068 1069 int w; 1070 1071 enbint(SIG_IGN); 1072 while ( (w = wait(&status)) != waitpid) 1073 if(w == -1) 1074 fatal("bad wait code"); 1075 enbint(intrupt); 1076 1077 #ifdef PSIGNAL 1078 if(status.w_termsig) 1079 { 1080 debugflag = 0; /* Prevent us from dumping core ourselves */ 1081 if(status.w_termsig != SIGINT && status.w_termsig < NSIG) 1082 fprintf(diagfile, "%s%s\n", sys_siglist[status.w_termsig], 1083 status.w_coredump ? " -- core dumped" : ""); 1084 if(status.w_termsig < NSIG && ! harmless[status.w_termsig]) 1085 fatal("see a system manager"); 1086 else 1087 done(3); 1088 } 1089 return(status.w_retcode); 1090 #else PSIGNAL 1091 if(status & 0377) 1092 { 1093 if(status != SIGINT) 1094 fprintf(diagfile, "Termination code %d\n", status); 1095 done(3); 1096 } 1097 return(status>>8); 1098 #endif PSIGNAL 1099 } 1100 1101 /* File Name and File Manipulation Routines */ 1102 1103 unreadable(s) 1104 register char *s; 1105 { 1106 register FILE *fp; 1107 1108 if(fp = fopen(s, "r")) 1109 { 1110 fclose(fp); 1111 return(NO); 1112 } 1113 1114 else 1115 { 1116 fprintf(diagfile, "Error: Cannot read file %s\n", s); 1117 return(YES); 1118 } 1119 } 1120 1121 1122 1123 stupid(s) 1124 char *s; 1125 { 1126 char c; 1127 extern char *index(); 1128 1129 if( (c = dotchar(s)) 1130 && index("focsreF", c) 1131 && access(s, 0) == 0 ) 1132 { 1133 fprintf(diagfile, "Loading on %s would destroy it\n", s); 1134 return(YES); 1135 } 1136 return(NO); 1137 } 1138 1139 1140 1141 clf(p) 1142 FILEP *p; 1143 { 1144 if(p!=NULL && *p!=NULL && *p!=stdout) 1145 { 1146 if(ferror(*p)) 1147 fatal("writing error"); 1148 fclose(*p); 1149 } 1150 *p = NULL; 1151 } 1152 1153 rmfiles() 1154 { 1155 rmf(textfname); 1156 rmf(asmfname); 1157 rmf(initfname); 1158 rmf(asmpass2); 1159 #if TARGET == INTERDATA 1160 rmf(setfname); 1161 #endif 1162 } 1163 1164 1165 1166 1167 1168 1169 1170 1171 /* return -1 if file does not exist, 0 if it is of zero length 1172 and 1 if of positive length 1173 */ 1174 content(filename) 1175 char *filename; 1176 { 1177 #ifdef VERSION6 1178 struct stat 1179 { 1180 char cjunk[9]; 1181 char size0; 1182 int size1; 1183 int ijunk[12]; 1184 } buf; 1185 #else 1186 struct stat buf; 1187 #endif 1188 1189 if(stat(filename,&buf) < 0) 1190 return(-1); 1191 #ifdef VERSION6 1192 return(buf.size0 || buf.size1); 1193 #else 1194 return( buf.st_size > 0 ); 1195 #endif 1196 } 1197 1198 1199 1200 1201 crfnames() 1202 { 1203 fname(textfname, "x"); 1204 fname(asmfname, "s"); 1205 fname(asmpass2, "a"); 1206 fname(initfname, "d"); 1207 fname(sortfname, "S"); 1208 fname(objfdefault, "o"); 1209 fname(prepfname, "p"); 1210 fname(optzfname, "z"); 1211 fname(setfname, "A"); 1212 } 1213 1214 1215 1216 1217 rmf(fn) 1218 register char *fn; 1219 { 1220 /* if(!debugflag && fn!=NULL && *fn!='\0') */ 1221 1222 if(fn!=NULL && *fn!='\0') 1223 unlink(fn); 1224 } 1225 1226 1227 1228 1229 1230 LOCAL fname(name, suff) 1231 char *name, *suff; 1232 { 1233 sprintf(name, "/tmp/%s%d.%s", temppref, pid, suff); 1234 } 1235 1236 1237 1238 1239 dotchar(s) 1240 register char *s; 1241 { 1242 for( ; *s ; ++s) 1243 if(s[0]=='.' && s[1]!='\0' && s[2]=='\0') 1244 return( s[1] ); 1245 return(NO); 1246 } 1247 1248 1249 1250 char *lastfield(s) 1251 register char *s; 1252 { 1253 register char *t; 1254 for(t = s; *s ; ++s) 1255 if(*s == '/') 1256 t = s+1; 1257 return(t); 1258 } 1259 1260 1261 1262 char *lastchar(s) 1263 register char *s; 1264 { 1265 while(*s) 1266 ++s; 1267 return(s-1); 1268 } 1269 1270 char *setdoto(s) 1271 register char *s; 1272 { 1273 *lastchar(s) = 'o'; 1274 return( lastfield(s) ); 1275 } 1276 1277 1278 1279 badfile(s) 1280 char *s; 1281 { 1282 fatalstr("cannot open intermediate file %s", s); 1283 } 1284 1285 1286 1287 ptr ckalloc(n) 1288 int n; 1289 { 1290 ptr p; 1291 extern char *calloc(); 1292 1293 if( p = (ptr) calloc(1, (unsigned) n) ) 1294 return(p); 1295 1296 fatal("out of memory"); 1297 /* NOTREACHED */ 1298 } 1299 1300 1301 1302 1303 1304 char *copyn(n, s) 1305 register int n; 1306 register char *s; 1307 { 1308 register char *p, *q; 1309 1310 p = q = (char *) ckalloc(n); 1311 while(n-- > 0) 1312 *q++ = *s++; 1313 return(p); 1314 } 1315 1316 1317 1318 char *copys(s) 1319 char *s; 1320 { 1321 return( copyn( strlen(s)+1 , s) ); 1322 } 1323 1324 1325 1326 1327 1328 oneof(c,s) 1329 register c; 1330 register char *s; 1331 { 1332 while( *s ) 1333 if(*s++ == c) 1334 return(YES); 1335 return(NO); 1336 } 1337 1338 1339 1340 nodup(s) 1341 char *s; 1342 { 1343 register char **p; 1344 1345 for(p = loadargs ; p < loadp ; ++p) 1346 if( !strcmp(*p, s) ) 1347 return(NO); 1348 1349 return(YES); 1350 } 1351 1352 1353 1354 static fatal(t) 1355 char *t; 1356 { 1357 fprintf(diagfile, "Compiler error in file %s: %s\n", infname, t); 1358 if(debugflag) 1359 abort(); 1360 done(1); 1361 exit(1); 1362 } 1363 1364 1365 1366 1367 static fatali(t,d) 1368 char *t; 1369 int d; 1370 { 1371 char buff[100]; 1372 sprintf(buff, t, d); 1373 fatal(buff); 1374 } 1375 1376 1377 1378 1379 static fatalstr(t, s) 1380 char *t, *s; 1381 { 1382 char buff[100]; 1383 sprintf(buff, t, s); 1384 fatal(buff); 1385 } 1386 err(s) 1387 char *s; 1388 { 1389 fprintf(diagfile, "Error in file %s: %s\n", infname, s); 1390 } 1391 1392