Commit | Line | Data |
---|---|---|
0b02dad2 DS |
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 | |
87338294 | 8 | static char sccsid[] = "@(#)f77.c 5.3 (Berkeley) %G%"; |
0b02dad2 DS |
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 $ | |
87338294 DS |
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 | * | |
c466b5d7 DS |
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 | * | |
0b02dad2 DS |
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; | |
0b02dad2 DS |
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; | |
0b02dad2 DS |
163 | static flag fortonly = NO; |
164 | static flag macroflag = NO; | |
165 | static flag sdbflag = NO; | |
166 | static flag namesflag = YES; | |
167 | ||
87338294 DS |
168 | #if TARGET == PDP11 |
169 | static flag nofloating = NO; | |
170 | #endif | |
171 | ||
0b02dad2 DS |
172 | static int ncpp; |
173 | ||
174 | \f | |
175 | main(argc, argv) | |
176 | int argc; | |
177 | char **argv; | |
178 | { | |
87338294 DS |
179 | register int i, n; |
180 | int c, status; | |
0b02dad2 DS |
181 | char *setdoto(), *lastchar(), *lastfield(), *copys(), *argvtos(); |
182 | ptr ckalloc(); | |
87338294 | 183 | char *strcat(); |
0b02dad2 DS |
184 | register char *s; |
185 | char fortfile[20], *t; | |
87338294 | 186 | char *buff; |
0b02dad2 DS |
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 | ||
87338294 DS |
214 | for (i = 0, n = 50; i < argc; ++i) |
215 | n += strlen(argv[i]) + 1; | |
216 | buff = (char *) ckalloc(n); | |
217 | ||
0b02dad2 DS |
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 | ||
c466b5d7 | 246 | #ifdef ONLY66 |
0b02dad2 DS |
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 | } | |
c466b5d7 | 257 | #endif |
0b02dad2 DS |
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': | |
87338294 | 311 | (void) strcat(cflags, " -S"); |
0b02dad2 DS |
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 | } | |
87338294 | 347 | (void) strcat(cflags," -g"); |
0b02dad2 DS |
348 | sdbflag = YES; |
349 | goto copyfflag; | |
350 | ||
351 | case 'p': | |
352 | profileflag = YES; | |
87338294 | 353 | (void) strcat(cflags," -p"); |
0b02dad2 DS |
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 | ||
c466b5d7 DS |
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 | ||
0b02dad2 DS |
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; | |
87338294 | 450 | (void) setrlimit(RLIMIT_CORE, &r); |
0b02dad2 DS |
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 | \f | |
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); | |
87338294 DS |
764 | if( sys(buff) ) |
765 | fatal("can't rename optimizer output file"); | |
0b02dad2 DS |
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 | |
87338294 DS |
790 | if( sys(buff) ) |
791 | fatal("can't concatenate assembly files"); | |
0b02dad2 DS |
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); | |
87338294 DS |
811 | if( sys(buff) ) |
812 | fatal("can't concatenate assembly files"); | |
0b02dad2 DS |
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 | } | |
87338294 DS |
880 | if( await(waitpid) ) |
881 | erred = YES; | |
0b02dad2 DS |
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 | \f | |
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) | |
87338294 DS |
963 | if(freopen(inname, "r", stdin) == NULL) |
964 | fatalstr("Cannot open %s", inname); | |
0b02dad2 | 965 | if(outname) |
87338294 DS |
966 | if(freopen(outname, (append ? "a" : "w"), stdout) == NULL) |
967 | fatalstr("Cannot open %s", outname); | |
0b02dad2 DS |
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) | |
87338294 | 1032 | (void) signal(SIGINT,k); |
0b02dad2 | 1033 | if(sigqvalue == 0) |
87338294 | 1034 | (void) signal(SIGQUIT,k); |
0b02dad2 | 1035 | if(sighvalue == 0) |
87338294 | 1036 | (void) signal(SIGHUP,k); |
0b02dad2 | 1037 | if(sigtvalue == 0) |
87338294 | 1038 | (void) signal(SIGTERM,k); |
0b02dad2 DS |
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 | \f | |
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; | |
87338294 | 1127 | extern char *index(); |
0b02dad2 DS |
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 | { | |
87338294 DS |
1290 | ptr p; |
1291 | extern char *calloc(); | |
0b02dad2 | 1292 | |
87338294 | 1293 | if( p = (ptr) calloc(1, (unsigned) n) ) |
0b02dad2 DS |
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 |