1 #ifndef lint 2 static char sccsid[] = "@(#)pc.c 3.26 (Berkeley) 12/28/83"; 3 #endif 4 5 #include <stdio.h> 6 #include <signal.h> 7 #include <sys/wait.h> 8 #include <sys/param.h> 9 10 /* 11 * Pc - front end for Pascal compiler. 12 */ 13 char *pc0 = "/usr/lib/pc0"; 14 char *pc1 = "/lib/f1"; 15 char *pc2 = "/usr/lib/pc2"; 16 char *c2 = "/lib/c2"; 17 char *pc3 = "/usr/lib/pc3"; 18 char *ld = "/bin/ld"; 19 char *as = "/bin/as"; 20 char *lpc = "-lpc"; 21 char *crt0 = "/lib/crt0.o"; 22 char *mcrt0 = "/lib/mcrt0.o"; 23 char *gcrt0 = "/usr/lib/gcrt0.o"; 24 25 char *mktemp(); 26 char *tmpdir = "/tmp"; 27 char tmp0[MAXPATHLEN], tmp1[MAXPATHLEN]; 28 char *tname[2]; 29 char *tfile[2]; 30 31 char *setsuf(), *savestr(); 32 33 int Jflag, Sflag, Oflag, Tlflag, cflag, gflag, pflag, wflag, tflag; 34 int debug; 35 36 #define NARGS 512 37 int ldargx = 3; 38 int pc0argx = 3; 39 char *pc0args[NARGS] = { "pc0", "-o", "XXX" }; 40 char *pc1args[3] = { "pc1", 0, }; 41 char *pc2args[2] = { "pc2", 0 }; 42 char *c2args[4] = { "c2", 0, 0, 0 }; 43 int pc3argx = 1; 44 #define pc3args pc0args 45 #define ldargs pc0args 46 /* char *pc3args[NARGS] = { "pc3", 0 }; */ 47 /* char *ldargs[NARGS] = { "ld", "-X", "/lib/crt0.o", 0, }; */ 48 49 /* as -J -t tmpdir -o objfile srcfile \0 */ 50 int asargx; 51 char *asargs[8] = { "as", 0, }; 52 53 char *mesg[] = { 54 0, 55 "Hangup", 56 "Interrupt", 57 "Quit", 58 "Illegal instruction", 59 "Trace/BPT trap", 60 "IOT trap", 61 "EMT trap", 62 "Floating exception", 63 "Killed", 64 "Bus error", 65 "Segmentation fault", 66 "Bad system call", 67 "Broken pipe", 68 "Alarm clock", 69 "Terminated", 70 "Signal 16", 71 "Stopped (signal)", 72 "Stopped", 73 "Continued", 74 "Child exited", 75 "Stopped (tty input)", 76 "Stopped (tty output)", 77 "Tty input interrupt", 78 "Cputime limit exceeded", 79 "Filesize limit exceeded", 80 "Signal 26", 81 "Signal 27", 82 "Signal 28", 83 "Signal 29", 84 "Signal 30", 85 "Signal 31", 86 "Signal 32" 87 }; 88 89 /* 90 * If the number of .p arguments (np) is 1, and the number of .o arguments 91 * (nxo) is 0, and we successfully create an ``a.out'', then we remove 92 * the one .ps .o file (onepso). 93 */ 94 int np, nxo; 95 char *onepso; 96 int errs; 97 98 int onintr(); 99 100 main(argc, argv) 101 int argc; 102 char **argv; 103 { 104 register char *argp; 105 register int i; 106 int savargx; 107 char *t, c; 108 int j; 109 110 argc--, argv++; 111 if (argc == 0) { 112 execl("/bin/cat", "cat", "/usr/lib/how_pc"); 113 exit(1); 114 } 115 if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 116 signal(SIGINT, onintr); 117 signal(SIGTERM, onintr); 118 } 119 for (i = 0; i < argc; i++) { 120 argp = argv[i]; 121 if (argp[0] != '-') 122 continue; 123 switch (argp[1]) { 124 125 case 'd': 126 if (argp[2] == 0) 127 debug++; 128 continue; 129 case 'i': 130 pc0args[pc0argx++] = "-i"; 131 while (i+1 < argc && argv[i+1][0] != '-' && 132 getsuf(argv[i+1]) != 'p') { 133 pc0args[pc0argx++] = argv[i+1]; 134 i++; 135 } 136 if (i+1 == argc) { 137 fprintf(stderr, "pc: bad -i construction\n"); 138 exit(1); 139 } 140 continue; 141 case 'o': 142 i++; 143 if (i == argc) { 144 fprintf(stderr, "pc: -o must specify file\n"); 145 exit(1); 146 } 147 c = getsuf(argv[i]); 148 if (c == 'o' || c == 'p' || c == 'c') { 149 fprintf(stderr, "pc: -o would overwrite %s\n", 150 argv[i]); 151 exit(1); 152 } 153 continue; 154 case 't': 155 i++; 156 if (i == argc) { 157 fprintf(stderr, "pc: -t but no directory\n"); 158 exit(1); 159 } 160 if (argp[2] != '\0') { 161 fprintf(stderr, "pc: bad -t option\n"); 162 exit(1); 163 } 164 tmpdir = argv[i]; 165 if (tmpdir[0] == '-') { 166 fprintf(stderr, "pc: bad -t option\n"); 167 exit(1); 168 } 169 tflag = 1; 170 continue; 171 case 'O': 172 Oflag = 1; 173 continue; 174 case 'S': 175 Sflag = 1; 176 continue; 177 case 'J': 178 Jflag = 1; 179 continue; 180 case 'T': 181 switch (argp[2]) { 182 183 case '0': 184 pc0 = "/usr/src/ucb/pascal/pc0/a.out"; 185 if (argp[3] != '\0') { 186 pc0 = &argp[3]; 187 } 188 continue; 189 case '1': 190 pc1 = "/usr/src/lib/pcc/fort"; 191 if (argp[3] != '\0') { 192 pc1 = &argp[3]; 193 } 194 continue; 195 case '2': 196 pc2 = "/usr/src/ucb/pascal/utilities/pc2"; 197 if (argp[3] != '\0') { 198 pc2 = &argp[3]; 199 } 200 continue; 201 case '3': 202 pc3 = "/usr/src/ucb/pascal/utilities/pc3"; 203 if (argp[3] != '\0') { 204 pc3 = &argp[3]; 205 } 206 continue; 207 case 'l': 208 Tlflag = 1; 209 lpc = "/usr/src/usr.lib/libpc/libpc"; 210 if (argp[3] != '\0') { 211 lpc = &argp[3]; 212 } 213 continue; 214 } 215 continue; 216 case 'c': 217 cflag = 1; 218 continue; 219 case 'l': 220 if (argp[2]) 221 continue; 222 /* fall into ... */ 223 case 'b': 224 case 's': 225 case 'z': 226 case 'C': 227 pc0args[pc0argx++] = argp; 228 continue; 229 case 'w': 230 wflag = 1; 231 pc0args[pc0argx++] = argp; 232 continue; 233 case 'g': 234 gflag = 1; 235 pc0args[pc0argx++] = argp; 236 continue; 237 case 'p': 238 if (argp[2] == 'g') 239 crt0 = gcrt0; 240 else 241 crt0 = mcrt0; 242 if (!Tlflag) 243 lpc = "-lpc_p"; 244 pflag = 1; 245 continue; 246 } 247 } 248 if (gflag && Oflag) { 249 fprintf(stderr, "pc: warning: -g overrides -O\n"); 250 Oflag = 0; 251 } 252 sprintf(tmp0, "%s/%s", tmpdir, "p0XXXXXX"); 253 tname[0] = mktemp(tmp0); 254 sprintf(tmp1, "%s/%s", tmpdir, "p1XXXXXX"); 255 tname[1] = mktemp(tmp1); 256 savargx = pc0argx; 257 for (i = 0; i < argc; i++) { 258 argp = argv[i]; 259 if (argp[0] == '-') 260 continue; 261 if (suffix(argp) == 's') { 262 asargx = 1; 263 if (Jflag) 264 asargs[asargx++] = "-J"; 265 # ifdef vax 266 if (tflag) { 267 asargs[asargx++] = "-t"; 268 asargs[asargx++] = tmpdir; 269 } 270 # endif vax 271 asargs[asargx++] = argp; 272 asargs[asargx++] = "-o"; 273 tfile[1] = setsuf(argp, 'o'); 274 asargs[asargx++] = tfile[1]; 275 asargs[asargx] = 0; 276 if (dosys(as, asargs, 0, 0)) 277 continue; 278 tfile[1] = 0; 279 continue; 280 } 281 if (suffix(argp) != 'p') 282 continue; 283 tfile[0] = tname[0]; 284 pc0args[2] = tfile[0]; 285 pc0argx = savargx; 286 if (pflag) 287 pc0args[pc0argx++] = "-p"; 288 if (Jflag) 289 pc0args[pc0argx++] = "-J"; 290 pc0args[pc0argx++] = argp; 291 pc0args[pc0argx] = 0; 292 if (dosys(pc0, pc0args, 0, 0)) 293 continue; 294 pc1args[1] = tfile[0]; 295 tfile[1] = tname[1]; 296 if (dosys(pc1, pc1args, 0, tfile[1])) 297 continue; 298 unlink(tfile[0]); 299 tfile[0] = tname[0]; 300 if (Oflag) { 301 if (dosys(c2, c2args, tfile[1], tfile[0])) 302 continue; 303 unlink(tfile[1]); 304 tfile[1] = tfile[0]; 305 tfile[0] = tname[1]; 306 } 307 if (Sflag) 308 tfile[0] = setsuf(argp, 's'); 309 if (dosys(pc2, pc2args, tfile[1], tfile[0])) 310 continue; 311 unlink(tfile[1]); 312 tfile[1] = 0; 313 if (Sflag) { 314 tfile[0] = 0; 315 continue; 316 } 317 asargx = 1; 318 if (Jflag) 319 asargs[asargx++] = "-J"; 320 # ifdef vax 321 if (tflag) { 322 asargs[asargx++] = "-t"; 323 asargs[asargx++] = tmpdir; 324 } 325 # endif vax 326 asargs[asargx++] = tfile[0]; 327 asargs[asargx++] = "-o"; 328 tfile[1] = setsuf(argp, 'o'); 329 asargs[asargx++] = tfile[1]; 330 asargs[asargx] = 0; 331 if (dosys(as, asargs, 0, 0)) 332 continue; 333 tfile[1] = 0; 334 remove(); 335 } 336 if (errs || cflag || Sflag) 337 done(); 338 /* char *pc3args[NARGS] = { "pc3", 0 }; */ 339 pc3args[0] = "pc3"; 340 if (wflag) 341 pc3args[pc3argx++] = "-w"; 342 pc3args[pc3argx++] = "/usr/lib/pcexterns.o"; 343 for (i = 0; i < argc; i++) { 344 argp = argv[i]; 345 if (!strcmp(argp, "-o")) 346 i++; 347 if (argp[0] == '-') 348 continue; 349 switch (getsuf(argp)) { 350 351 case 'o': 352 pc3args[pc3argx++] = argp; 353 nxo++; 354 continue; 355 case 's': 356 case 'p': 357 onepso = pc3args[pc3argx++] = 358 savestr(setsuf(argp, 'o')); 359 np++; 360 continue; 361 } 362 } 363 pc3args[pc3argx] = 0; 364 if (dosys(pc3, pc3args, 0, 0) > 1) 365 done(); 366 errs = 0; 367 /* char *ldargs[NARGS] = { "ld", "-X", "/lib/crt0.o", 0, }; */ 368 ldargs[0] = "ld"; 369 ldargs[1] = "-X"; 370 ldargs[2] = crt0; 371 for (i = 0; i < argc; i++) { 372 argp = argv[i]; 373 if (argp[0] != '-') { 374 switch (getsuf(argp)) { 375 376 case 'p': 377 case 's': 378 ldargs[ldargx] = savestr(setsuf(argp, 'o')); 379 break; 380 default: 381 ldargs[ldargx] = argp; 382 break; 383 } 384 if (getsuf(ldargs[ldargx]) == 'o') 385 for (j = 0; j < ldargx; j++) 386 if (!strcmp(ldargs[j], ldargs[ldargx])) 387 goto duplicate; 388 ldargx++; 389 duplicate: 390 continue; 391 } 392 switch (argp[1]) { 393 394 case 'i': 395 while (i+1 < argc && argv[i+1][0] != '-' && 396 getsuf(argv[i+1]) != 'p') 397 i++; 398 continue; 399 case 'd': 400 if (argp[2] == 0) 401 continue; 402 ldargs[ldargx++] = argp; 403 continue; 404 case 'o': 405 ldargs[ldargx++] = argp; 406 i++; 407 ldargs[ldargx++] = argv[i]; 408 continue; 409 case 'l': 410 if (argp[2]) 411 ldargs[ldargx++] = argp; 412 continue; 413 case 't': 414 i++; 415 continue; 416 case 'c': 417 case 'g': 418 case 'w': 419 case 'p': 420 case 'S': 421 case 'J': 422 case 'T': 423 case 'O': 424 case 'C': 425 case 'b': 426 case 's': 427 case 'z': 428 continue; 429 default: 430 ldargs[ldargx++] = argp; 431 continue; 432 } 433 } 434 ldargs[ldargx++] = lpc; 435 if (gflag) 436 ldargs[ldargx++] = "-lg"; 437 if (pflag) { 438 ldargs[ldargx++] = "-lm_p"; 439 ldargs[ldargx++] = "-lc_p"; 440 } else { 441 ldargs[ldargx++] = "-lm"; 442 ldargs[ldargx++] = "-lc"; 443 } 444 ldargs[ldargx] = 0; 445 if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0) 446 unlink(onepso); 447 done(); 448 } 449 450 dosys(cmd, argv, in, out) 451 char *cmd, **argv, *in, *out; 452 { 453 union wait status; 454 int pid; 455 456 if (debug) { 457 int i; 458 printf("%s:", cmd); 459 for (i = 0; argv[i]; i++) 460 printf(" %s", argv[i]); 461 if (in) 462 printf(" <%s", in); 463 if (out) 464 printf(" >%s", out); 465 printf("\n"); 466 } 467 /* 468 * warning: vfork doesn't work here, because the call to signal() 469 * done by the child process destroys the parent's SIGINT handler. 470 */ 471 pid = fork(); 472 if (pid < 0) { 473 fprintf(stderr, "pc: No more processes\n"); 474 done(); 475 } 476 if (pid == 0) { 477 if (in) { 478 close(0); 479 if (open(in, 0) != 0) { 480 perror(in); 481 exit(1); 482 } 483 } 484 if (out) { 485 close(1); 486 unlink(out); 487 if (creat(out, 0666) != 1) { 488 perror(out); 489 exit(1); 490 } 491 } 492 signal(SIGINT, SIG_DFL); 493 execv(cmd, argv); 494 perror(cmd); 495 exit(1); 496 } 497 while (wait(&status) != pid) 498 ; 499 if (WIFSIGNALED(status)) { 500 if (status.w_termsig != SIGINT) { 501 fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]); 502 if (status.w_coredump) 503 fprintf(stderr, " (core dumped)"); 504 fprintf(stderr, "\n"); 505 } 506 errs = 100; 507 done(); 508 /*NOTREACHED*/ 509 } 510 if (status.w_retcode) { 511 errs = 1; 512 remove(); 513 } 514 return (status.w_retcode); 515 } 516 517 done() 518 { 519 520 remove(); 521 exit(errs); 522 } 523 524 remove() 525 { 526 527 if (tfile[0]) 528 unlink(tfile[0]); 529 if (tfile[1]) 530 unlink(tfile[1]); 531 } 532 533 onintr() 534 { 535 536 errs = 1; 537 done(); 538 } 539 540 getsuf(cp) 541 char *cp; 542 { 543 544 if (*cp == 0) 545 return; 546 while (cp[1]) 547 cp++; 548 if (cp[-1] != '.') 549 return (0); 550 return (*cp); 551 } 552 553 char * 554 setsuf(as, ch) 555 char *as; 556 { 557 register char *s, *s1; 558 559 s = s1 = savestr(as); 560 while (*s) 561 if (*s++ == '/') 562 s1 = s; 563 s[-1] = ch; 564 return (s1); 565 } 566 567 #define NSAVETAB 512 568 char *savetab; 569 int saveleft; 570 571 char * 572 savestr(cp) 573 register char *cp; 574 { 575 register int len; 576 577 len = strlen(cp) + 1; 578 if (len > saveleft) { 579 saveleft = NSAVETAB; 580 if (len > saveleft) 581 saveleft = len; 582 savetab = (char *)malloc(saveleft); 583 if (savetab == 0) { 584 fprintf(stderr, "ran out of memory (savestr)\n"); 585 exit(1); 586 } 587 } 588 strncpy(savetab, cp, len); 589 cp = savetab; 590 savetab += len; 591 return (cp); 592 } 593 594 suffix(cp) 595 char *cp; 596 { 597 598 if (cp[0] == 0 || cp[1] == 0) 599 return (0); 600 while (cp[1]) 601 cp++; 602 if (cp[-1] == '.') 603 return (*cp); 604 return (0); 605 } 606