xref: /original-bsd/usr.bin/f77/f77.vax/f77.c (revision bdd86a84)
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