xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 13724)
1*13724Ssam #ifndef lint
2*13724Ssam static	char sccsid[] = "@(#)pc.c	3.25 (Berkeley) 07/02/83";
3*13724Ssam #endif
45054Smckusic 
5621Sbill #include <stdio.h>
6621Sbill #include <signal.h>
7*13724Ssam #include <sys/wait.h>
812870Speter #include <sys/param.h>
9621Sbill 
10621Sbill /*
11654Sbill  * Pc - front end for Pascal compiler.
12621Sbill  */
13908Sbill char	*pc0 = "/usr/lib/pc0";
14908Sbill char	*pc1 = "/lib/f1";
15908Sbill char	*pc2 = "/usr/lib/pc2";
16908Sbill char	*c2 = "/lib/c2";
17908Sbill char	*pc3 = "/usr/lib/pc3";
18908Sbill char	*ld = "/bin/ld";
19908Sbill char	*as = "/bin/as";
20621Sbill char	*lpc = "-lpc";
21908Sbill char	*crt0 = "/lib/crt0.o";
22908Sbill char	*mcrt0 = "/lib/mcrt0.o";
235054Smckusic char	*gcrt0 = "/usr/lib/gcrt0.o";
24621Sbill 
25621Sbill char	*mktemp();
2612870Speter char	*tmpdir = "/tmp";
2712870Speter char	tmp0[MAXPATHLEN], tmp1[MAXPATHLEN];
28621Sbill char	*tname[2];
29621Sbill char	*tfile[2];
30621Sbill 
31621Sbill char	*setsuf(), *savestr();
32621Sbill 
3312870Speter int	Jflag, Sflag, Oflag, Tlflag, cflag, gflag, pflag, wflag, tflag;
34621Sbill int	debug;
35621Sbill 
36621Sbill #define	NARGS	512
37621Sbill int	ldargx = 3;
38621Sbill int	pc0argx = 3;
39621Sbill char	*pc0args[NARGS] =	{ "pc0", "-o", "XXX" };
40621Sbill char	*pc1args[3] =		{ "pc1", 0, };
41621Sbill char	*pc2args[2] =		{ "pc2", 0 };
42621Sbill char	*c2args[4] =		{ "c2", 0, 0, 0 };
437596Smckusick int	pc3argx = 1;
44621Sbill #define	pc3args	pc0args
45621Sbill #define	ldargs	pc0args
467596Smckusick /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
47908Sbill /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
4812870Speter 
4912870Speter 				/* as -J -t tmpdir -o objfile srcfile \0 */
50908Sbill int	asargx;
5112870Speter char	*asargs[8] =		{ "as", 0, };
52621Sbill 
537766Smckusick char *mesg[] = {
547766Smckusick 	0,
557766Smckusick 	"Hangup",
567766Smckusick 	"Interrupt",
577766Smckusick 	"Quit",
587766Smckusick 	"Illegal instruction",
597766Smckusick 	"Trace/BPT trap",
607766Smckusick 	"IOT trap",
617766Smckusick 	"EMT trap",
627766Smckusick 	"Floating exception",
637766Smckusick 	"Killed",
647766Smckusick 	"Bus error",
657766Smckusick 	"Segmentation fault",
667766Smckusick 	"Bad system call",
677766Smckusick 	"Broken pipe",
687766Smckusick 	"Alarm clock",
697766Smckusick 	"Terminated",
707766Smckusick 	"Signal 16",
717766Smckusick 	"Stopped (signal)",
727766Smckusick 	"Stopped",
737766Smckusick 	"Continued",
747766Smckusick 	"Child exited",
757766Smckusick 	"Stopped (tty input)",
767766Smckusick 	"Stopped (tty output)",
777766Smckusick 	"Tty input interrupt",
787766Smckusick 	"Cputime limit exceeded",
797766Smckusick 	"Filesize limit exceeded",
807766Smckusick 	"Signal 26",
817766Smckusick 	"Signal 27",
827766Smckusick 	"Signal 28",
837766Smckusick 	"Signal 29",
847766Smckusick 	"Signal 30",
857766Smckusick 	"Signal 31",
867766Smckusick 	"Signal 32"
877766Smckusick };
887766Smckusick 
89621Sbill /*
90621Sbill  * If the number of .p arguments (np) is 1, and the number of .o arguments
91621Sbill  * (nxo) is 0, and we successfully create an ``a.out'', then we remove
92621Sbill  * the one .ps .o file (onepso).
93621Sbill  */
94621Sbill int	np, nxo;
95621Sbill char	*onepso;
96621Sbill int	errs;
97621Sbill 
98621Sbill int	onintr();
99621Sbill 
100621Sbill main(argc, argv)
101621Sbill 	int argc;
102621Sbill 	char **argv;
103621Sbill {
104621Sbill 	register char *argp;
105621Sbill 	register int i;
106621Sbill 	int savargx;
107621Sbill 	char *t, c;
108621Sbill 	int j;
109621Sbill 
110621Sbill 	argc--, argv++;
111621Sbill 	if (argc == 0) {
112621Sbill 		execl("/bin/cat", "cat", "/usr/lib/how_pc");
113621Sbill 		exit(1);
114621Sbill 	}
115621Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
116621Sbill 		signal(SIGINT, onintr);
117621Sbill 		signal(SIGTERM, onintr);
118621Sbill 	}
119621Sbill 	for (i = 0; i < argc; i++) {
120621Sbill 		argp = argv[i];
121621Sbill 		if (argp[0] != '-')
122621Sbill 			continue;
123621Sbill 		switch (argp[1]) {
124621Sbill 
125621Sbill 		case 'd':
126621Sbill 			if (argp[2] == 0)
127621Sbill 				debug++;
128621Sbill 			continue;
129621Sbill 		case 'i':
130621Sbill 			pc0args[pc0argx++] = "-i";
131621Sbill 			while (i+1 < argc && argv[i+1][0] != '-' &&
132621Sbill 			    getsuf(argv[i+1]) != 'p') {
133621Sbill 				pc0args[pc0argx++] = argv[i+1];
134621Sbill 				i++;
135621Sbill 			}
136621Sbill 			if (i+1 == argc) {
137621Sbill 				fprintf(stderr, "pc: bad -i construction\n");
138621Sbill 				exit(1);
139621Sbill 			}
140621Sbill 			continue;
141621Sbill 		case 'o':
142621Sbill 			i++;
143621Sbill 			if (i == argc) {
144621Sbill 				fprintf(stderr, "pc: -o must specify file\n");
145621Sbill 				exit(1);
146621Sbill 			}
147621Sbill 			c = getsuf(argv[i]);
148621Sbill 			if (c == 'o' || c == 'p' || c == 'c') {
149621Sbill 				fprintf(stderr, "pc: -o would overwrite %s\n",
150621Sbill 				    argv[i]);
151621Sbill 				exit(1);
152621Sbill 			}
153621Sbill 			continue;
15412870Speter 		case 't':
15512870Speter 			i++;
15612870Speter 			if (i == argc) {
15712931Speter 				fprintf(stderr, "pc: -t but no directory\n");
15812870Speter 				exit(1);
15912870Speter 			}
16012931Speter 			if (argp[2] != '\0') {
16112931Speter 				fprintf(stderr, "pc: bad -t option\n");
16212931Speter 				exit(1);
16312931Speter 			}
16412870Speter 			tmpdir = argv[i];
16512931Speter 			if (tmpdir[0] == '-') {
16612931Speter 				fprintf(stderr, "pc: bad -t option\n");
16712931Speter 				exit(1);
16812931Speter 			}
16912870Speter 			tflag = 1;
17012870Speter 			continue;
171621Sbill 		case 'O':
172621Sbill 			Oflag = 1;
173621Sbill 			continue;
174621Sbill 		case 'S':
175621Sbill 			Sflag = 1;
176621Sbill 			continue;
177908Sbill 		case 'J':
178908Sbill 			Jflag = 1;
179908Sbill 			continue;
180621Sbill 		case 'T':
181621Sbill 			switch (argp[2]) {
182621Sbill 
183621Sbill 			case '0':
18410721Smckusick 				pc0 = "/usr/src/ucb/pascal/pc0/a.out";
1853862Smckusic 				if (argp[3] != '\0') {
1863862Smckusic 					pc0 = &argp[3];
1873862Smckusic 				}
188621Sbill 				continue;
189621Sbill 			case '1':
1909140Smckusick 				pc1 = "/usr/src/lib/pcc/fort";
1913862Smckusic 				if (argp[3] != '\0') {
1923862Smckusic 					pc1 = &argp[3];
1933862Smckusic 				}
194621Sbill 				continue;
195621Sbill 			case '2':
19610721Smckusick 				pc2 = "/usr/src/ucb/pascal/utilities/pc2";
1973862Smckusic 				if (argp[3] != '\0') {
1983862Smckusic 					pc2 = &argp[3];
1993862Smckusic 				}
200621Sbill 				continue;
201621Sbill 			case '3':
20210721Smckusick 				pc3 = "/usr/src/ucb/pascal/utilities/pc3";
2033862Smckusic 				if (argp[3] != '\0') {
2043862Smckusic 					pc3 = &argp[3];
2053862Smckusic 				}
206621Sbill 				continue;
207621Sbill 			case 'l':
2085054Smckusic 				Tlflag = 1;
2099140Smckusick 				lpc = "/usr/src/usr.lib/libpc/libpc";
2103862Smckusic 				if (argp[3] != '\0') {
2113862Smckusic 					lpc = &argp[3];
2123862Smckusic 				}
213621Sbill 				continue;
214621Sbill 			}
215621Sbill 			continue;
216621Sbill 		case 'c':
217621Sbill 			cflag = 1;
218621Sbill 			continue;
219621Sbill 		case 'l':
220621Sbill 			if (argp[2])
221621Sbill 				continue;
222621Sbill 			/* fall into ... */
223621Sbill 		case 'b':
224621Sbill 		case 's':
225621Sbill 		case 'z':
226621Sbill 		case 'C':
227621Sbill 			pc0args[pc0argx++] = argp;
228621Sbill 			continue;
2297596Smckusick 		case 'w':
2307596Smckusick 			wflag = 1;
2317596Smckusick 			pc0args[pc0argx++] = argp;
2327596Smckusick 			continue;
2337596Smckusick 		case 'g':
2347596Smckusick 			gflag = 1;
2357596Smckusick 			pc0args[pc0argx++] = argp;
2367596Smckusick 			continue;
237621Sbill 		case 'p':
2385054Smckusic 			if (argp[2] == 'g')
2395054Smckusic 				crt0 = gcrt0;
2405054Smckusic 			else
2415054Smckusic 				crt0 = mcrt0;
2425054Smckusic 			if (!Tlflag)
2435054Smckusic 				lpc = "-lpc_p";
2445054Smckusic 			pflag = 1;
245654Sbill 			continue;
246621Sbill 		}
247621Sbill 	}
248621Sbill 	if (gflag && Oflag) {
249621Sbill 		fprintf(stderr, "pc: warning: -g overrides -O\n");
250621Sbill 		Oflag = 0;
251621Sbill 	}
25212870Speter 	sprintf(tmp0, "%s/%s", tmpdir, "p0XXXXXX");
25312870Speter 	tname[0] = mktemp(tmp0);
25412870Speter 	sprintf(tmp1, "%s/%s", tmpdir, "p1XXXXXX");
25512870Speter 	tname[1] = mktemp(tmp1);
256621Sbill 	savargx = pc0argx;
257621Sbill 	for (i = 0; i < argc; i++) {
258621Sbill 		argp = argv[i];
259621Sbill 		if (argp[0] == '-')
260621Sbill 			continue;
2611211Speter 		if (suffix(argp) == 's') {
2621211Speter 			asargx = 1;
2631211Speter 			if (Jflag)
2641211Speter 				asargs[asargx++] = "-J";
26512870Speter #			ifdef vax
26612870Speter 				if (tflag) {
26712870Speter 					asargs[asargx++] = "-t";
26812870Speter 					asargs[asargx++] = tmpdir;
26912870Speter 				}
27012870Speter #			endif vax
2711211Speter 			asargs[asargx++] = argp;
2721211Speter 			asargs[asargx++] = "-o";
2731211Speter 			tfile[1] = setsuf(argp, 'o');
2741211Speter 			asargs[asargx++] = tfile[1];
2751211Speter 			asargs[asargx] = 0;
2761211Speter 			if (dosys(as, asargs, 0, 0))
2771211Speter 				continue;
2781211Speter 			tfile[1] = 0;
2791211Speter 			continue;
2801211Speter 		}
281621Sbill 		if (suffix(argp) != 'p')
282621Sbill 			continue;
283621Sbill 		tfile[0] = tname[0];
284621Sbill 		pc0args[2] = tfile[0];
285621Sbill 		pc0argx = savargx;
286654Sbill 		if (pflag)
287654Sbill 			pc0args[pc0argx++] = "-p";
28812966Smckusick 		if (Jflag)
28912966Smckusick 			pc0args[pc0argx++] = "-J";
290621Sbill 		pc0args[pc0argx++] = argp;
291621Sbill 		pc0args[pc0argx] = 0;
292621Sbill 		if (dosys(pc0, pc0args, 0, 0))
293621Sbill 			continue;
294621Sbill 		pc1args[1] = tfile[0];
295654Sbill 		tfile[1] = tname[1];
296621Sbill 		if (dosys(pc1, pc1args, 0, tfile[1]))
297621Sbill 			continue;
298621Sbill 		unlink(tfile[0]);
2992340Smckusic 		tfile[0] = tname[0];
3002340Smckusic 		if (Oflag) {
3012340Smckusic 			if (dosys(c2, c2args, tfile[1], tfile[0]))
3022340Smckusic 				continue;
3032340Smckusic 			unlink(tfile[1]);
3042340Smckusic 			tfile[1] = tfile[0];
3052340Smckusic 			tfile[0] = tname[1];
3062340Smckusic 		}
3072340Smckusic 		if (Sflag)
308654Sbill 			tfile[0] = setsuf(argp, 's');
309621Sbill 		if (dosys(pc2, pc2args, tfile[1], tfile[0]))
310621Sbill 			continue;
311621Sbill 		unlink(tfile[1]);
312621Sbill 		tfile[1] = 0;
313654Sbill 		if (Sflag) {
314654Sbill 			tfile[0] = 0;
315621Sbill 			continue;
316654Sbill 		}
317908Sbill 		asargx = 1;
318908Sbill 		if (Jflag)
319908Sbill 			asargs[asargx++] = "-J";
32012870Speter #		ifdef vax
32112870Speter 			if (tflag) {
32212870Speter 				asargs[asargx++] = "-t";
32312870Speter 				asargs[asargx++] = tmpdir;
32412870Speter 			}
32512870Speter #		endif vax
326908Sbill 		asargs[asargx++] = tfile[0];
327908Sbill 		asargs[asargx++] = "-o";
328621Sbill 		tfile[1] = setsuf(argp, 'o');
329908Sbill 		asargs[asargx++] = tfile[1];
330908Sbill 		asargs[asargx] = 0;
331621Sbill 		if (dosys(as, asargs, 0, 0))
332621Sbill 			continue;
333621Sbill 		tfile[1] = 0;
334621Sbill 		remove();
335621Sbill 	}
336621Sbill 	if (errs || cflag || Sflag)
337621Sbill 		done();
3387596Smckusick /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
339621Sbill 	pc3args[0] = "pc3";
3407596Smckusick 	if (wflag)
3417596Smckusick 		pc3args[pc3argx++] = "-w";
3427596Smckusick 	pc3args[pc3argx++] = "/usr/lib/pcexterns.o";
343621Sbill 	for (i = 0; i < argc; i++) {
344621Sbill 		argp = argv[i];
345621Sbill 		if (!strcmp(argp, "-o"))
346621Sbill 			i++;
347621Sbill 		if (argp[0] == '-')
348621Sbill 			continue;
349621Sbill 		switch (getsuf(argp)) {
350621Sbill 
351621Sbill 		case 'o':
352621Sbill 			pc3args[pc3argx++] = argp;
353621Sbill 			nxo++;
354621Sbill 			continue;
3551211Speter 		case 's':
356621Sbill 		case 'p':
357621Sbill 			onepso = pc3args[pc3argx++] =
358621Sbill 			    savestr(setsuf(argp, 'o'));
359621Sbill 			np++;
360621Sbill 			continue;
361621Sbill 		}
362621Sbill 	}
363621Sbill 	pc3args[pc3argx] = 0;
3647596Smckusick 	if (dosys(pc3, pc3args, 0, 0) > 1)
365621Sbill 		done();
36610672Speter 	errs = 0;
367908Sbill /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
368621Sbill 	ldargs[0] = "ld";
369621Sbill 	ldargs[1] = "-X";
370654Sbill 	ldargs[2] = crt0;
371621Sbill 	for (i = 0; i < argc; i++) {
372621Sbill 		argp = argv[i];
373621Sbill 		if (argp[0] != '-') {
374621Sbill 			switch (getsuf(argp)) {
375621Sbill 
376621Sbill 			case 'p':
3771211Speter 			case 's':
378621Sbill 				ldargs[ldargx] = savestr(setsuf(argp, 'o'));
379621Sbill 				break;
380621Sbill 			default:
381621Sbill 				ldargs[ldargx] = argp;
382621Sbill 				break;
383621Sbill 			}
384621Sbill 			if (getsuf(ldargs[ldargx]) == 'o')
385621Sbill 			for (j = 0; j < ldargx; j++)
386621Sbill 				if (!strcmp(ldargs[j], ldargs[ldargx]))
387621Sbill 					goto duplicate;
388621Sbill 			ldargx++;
389621Sbill duplicate:
390621Sbill 			continue;
391621Sbill 		}
392621Sbill 		switch (argp[1]) {
393621Sbill 
394621Sbill 		case 'i':
395621Sbill 			while (i+1 < argc && argv[i+1][0] != '-' &&
396621Sbill 			    getsuf(argv[i+1]) != 'p')
397621Sbill 				i++;
398621Sbill 			continue;
399621Sbill 		case 'd':
400621Sbill 			if (argp[2] == 0)
401621Sbill 				continue;
402621Sbill 			ldargs[ldargx++] = argp;
403621Sbill 			continue;
404621Sbill 		case 'o':
405621Sbill 			ldargs[ldargx++] = argp;
406621Sbill 			i++;
407621Sbill 			ldargs[ldargx++] = argv[i];
408621Sbill 			continue;
409621Sbill 		case 'l':
410621Sbill 			if (argp[2])
411621Sbill 				ldargs[ldargx++] = argp;
412621Sbill 			continue;
41312870Speter 		case 't':
41412870Speter 			i++;
41512870Speter 			continue;
416621Sbill 		case 'c':
417621Sbill 		case 'g':
418621Sbill 		case 'w':
419621Sbill 		case 'p':
420621Sbill 		case 'S':
421908Sbill 		case 'J':
422621Sbill 		case 'T':
423621Sbill 		case 'O':
424621Sbill 		case 'C':
425621Sbill 		case 'b':
426621Sbill 		case 's':
427621Sbill 		case 'z':
428621Sbill 			continue;
429621Sbill 		default:
430621Sbill 			ldargs[ldargx++] = argp;
431621Sbill 			continue;
432621Sbill 		}
433621Sbill 	}
434621Sbill 	ldargs[ldargx++] = lpc;
435621Sbill 	if (gflag)
436621Sbill 		ldargs[ldargx++] = "-lg";
4375054Smckusic 	if (pflag) {
4385054Smckusic 		ldargs[ldargx++] = "-lm_p";
4395054Smckusic 		ldargs[ldargx++] = "-lc_p";
4405054Smckusic 	} else {
4415054Smckusic 		ldargs[ldargx++] = "-lm";
4425054Smckusic 		ldargs[ldargx++] = "-lc";
4435054Smckusic 	}
444621Sbill 	ldargs[ldargx] = 0;
445621Sbill 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
446621Sbill 		unlink(onepso);
447621Sbill 	done();
448621Sbill }
449621Sbill 
450621Sbill dosys(cmd, argv, in, out)
451621Sbill 	char *cmd, **argv, *in, *out;
452621Sbill {
453621Sbill 	union wait status;
454621Sbill 	int pid;
455621Sbill 
456621Sbill 	if (debug) {
457621Sbill 		int i;
458621Sbill 		printf("%s:", cmd);
459621Sbill 		for (i = 0; argv[i]; i++)
460621Sbill 			printf(" %s", argv[i]);
461621Sbill 		if (in)
462621Sbill 			printf(" <%s", in);
463621Sbill 		if (out)
464621Sbill 			printf(" >%s", out);
465621Sbill 		printf("\n");
466621Sbill 	}
467621Sbill 	pid = vfork();
468621Sbill 	if (pid < 0) {
469621Sbill 		fprintf(stderr, "pc: No more processes\n");
470621Sbill 		done();
471621Sbill 	}
472621Sbill 	if (pid == 0) {
473621Sbill 		if (in) {
474621Sbill 			close(0);
475621Sbill 			if (open(in, 0) != 0) {
476621Sbill 				perror(in);
477621Sbill 				exit(1);
478621Sbill 			}
479621Sbill 		}
480621Sbill 		if (out) {
481621Sbill 			close(1);
482621Sbill 			unlink(out);
483621Sbill 			if (creat(out, 0666) != 1) {
484621Sbill 				perror(out);
485621Sbill 				exit(1);
486621Sbill 			}
487621Sbill 		}
488621Sbill 		signal(SIGINT, SIG_DFL);
489621Sbill 		execv(cmd, argv);
490621Sbill 		perror(cmd);
491621Sbill 		exit(1);
492621Sbill 	}
493621Sbill 	while (wait(&status) != pid)
494621Sbill 		;
495621Sbill 	if (WIFSIGNALED(status)) {
4967766Smckusick 		if (status.w_termsig != SIGINT) {
4977766Smckusick 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
4987766Smckusick 			if (status.w_coredump)
4997766Smckusick 				fprintf(stderr, " (core dumped)");
5007766Smckusick 			fprintf(stderr, "\n");
5017766Smckusick 		}
502621Sbill 		errs = 100;
503621Sbill 		done();
504621Sbill 		/*NOTREACHED*/
505621Sbill 	}
506621Sbill 	if (status.w_retcode) {
507621Sbill 		errs = 1;
508621Sbill 		remove();
509621Sbill 	}
510621Sbill 	return (status.w_retcode);
511621Sbill }
512621Sbill 
513621Sbill done()
514621Sbill {
515621Sbill 
516621Sbill 	remove();
517621Sbill 	exit(errs);
518621Sbill }
519621Sbill 
520621Sbill remove()
521621Sbill {
522621Sbill 
523621Sbill 	if (tfile[0])
524621Sbill 		unlink(tfile[0]);
525621Sbill 	if (tfile[1])
526621Sbill 		unlink(tfile[1]);
527621Sbill }
528621Sbill 
529621Sbill onintr()
530621Sbill {
531621Sbill 
532621Sbill 	errs = 1;
533621Sbill 	done();
534621Sbill }
535621Sbill 
536621Sbill getsuf(cp)
537621Sbill 	char *cp;
538621Sbill {
539621Sbill 
540621Sbill 	if (*cp == 0)
541621Sbill 		return;
542621Sbill 	while (cp[1])
543621Sbill 		cp++;
544621Sbill 	if (cp[-1] != '.')
545621Sbill 		return (0);
546621Sbill 	return (*cp);
547621Sbill }
548621Sbill 
549621Sbill char *
550654Sbill setsuf(as, ch)
551654Sbill 	char *as;
552621Sbill {
553654Sbill 	register char *s, *s1;
554621Sbill 
555654Sbill 	s = s1 = savestr(as);
556654Sbill 	while (*s)
557654Sbill 		if (*s++ == '/')
558654Sbill 			s1 = s;
559654Sbill 	s[-1] = ch;
560654Sbill 	return (s1);
561621Sbill }
562621Sbill 
563621Sbill #define	NSAVETAB	512
564621Sbill char	*savetab;
565621Sbill int	saveleft;
566621Sbill 
567621Sbill char *
568621Sbill savestr(cp)
569621Sbill 	register char *cp;
570621Sbill {
571621Sbill 	register int len;
572621Sbill 
573621Sbill 	len = strlen(cp) + 1;
574621Sbill 	if (len > saveleft) {
575621Sbill 		saveleft = NSAVETAB;
576621Sbill 		if (len > saveleft)
577621Sbill 			saveleft = len;
578621Sbill 		savetab = (char *)malloc(saveleft);
579621Sbill 		if (savetab == 0) {
580621Sbill 			fprintf(stderr, "ran out of memory (savestr)\n");
581621Sbill 			exit(1);
582621Sbill 		}
583621Sbill 	}
584621Sbill 	strncpy(savetab, cp, len);
585621Sbill 	cp = savetab;
586621Sbill 	savetab += len;
587621Sbill 	return (cp);
588621Sbill }
589621Sbill 
590621Sbill suffix(cp)
591621Sbill 	char *cp;
592621Sbill {
593621Sbill 
594621Sbill 	if (cp[0] == 0 || cp[1] == 0)
595621Sbill 		return (0);
596621Sbill 	while (cp[1])
597621Sbill 		cp++;
598621Sbill 	if (cp[-1] == '.')
599621Sbill 		return (*cp);
600621Sbill 	return (0);
601621Sbill }
602