xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 15776)
113724Ssam #ifndef lint
2*15776Saoki static	char sccsid[] = "@(#)pc.c	3.26 (Berkeley) 12/28/83";
313724Ssam #endif
45054Smckusic 
5621Sbill #include <stdio.h>
6621Sbill #include <signal.h>
713724Ssam #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 	}
467*15776Saoki 	/*
468*15776Saoki 	 * warning: vfork doesn't work here, because the call to signal()
469*15776Saoki 	 * done by the child process destroys the parent's SIGINT handler.
470*15776Saoki 	 */
471*15776Saoki 	pid = fork();
472621Sbill 	if (pid < 0) {
473621Sbill 		fprintf(stderr, "pc: No more processes\n");
474621Sbill 		done();
475621Sbill 	}
476621Sbill 	if (pid == 0) {
477621Sbill 		if (in) {
478621Sbill 			close(0);
479621Sbill 			if (open(in, 0) != 0) {
480621Sbill 				perror(in);
481621Sbill 				exit(1);
482621Sbill 			}
483621Sbill 		}
484621Sbill 		if (out) {
485621Sbill 			close(1);
486621Sbill 			unlink(out);
487621Sbill 			if (creat(out, 0666) != 1) {
488621Sbill 				perror(out);
489621Sbill 				exit(1);
490621Sbill 			}
491621Sbill 		}
492621Sbill 		signal(SIGINT, SIG_DFL);
493621Sbill 		execv(cmd, argv);
494621Sbill 		perror(cmd);
495621Sbill 		exit(1);
496621Sbill 	}
497621Sbill 	while (wait(&status) != pid)
498621Sbill 		;
499621Sbill 	if (WIFSIGNALED(status)) {
5007766Smckusick 		if (status.w_termsig != SIGINT) {
5017766Smckusick 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
5027766Smckusick 			if (status.w_coredump)
5037766Smckusick 				fprintf(stderr, " (core dumped)");
5047766Smckusick 			fprintf(stderr, "\n");
5057766Smckusick 		}
506621Sbill 		errs = 100;
507621Sbill 		done();
508621Sbill 		/*NOTREACHED*/
509621Sbill 	}
510621Sbill 	if (status.w_retcode) {
511621Sbill 		errs = 1;
512621Sbill 		remove();
513621Sbill 	}
514621Sbill 	return (status.w_retcode);
515621Sbill }
516621Sbill 
517621Sbill done()
518621Sbill {
519621Sbill 
520621Sbill 	remove();
521621Sbill 	exit(errs);
522621Sbill }
523621Sbill 
524621Sbill remove()
525621Sbill {
526621Sbill 
527621Sbill 	if (tfile[0])
528621Sbill 		unlink(tfile[0]);
529621Sbill 	if (tfile[1])
530621Sbill 		unlink(tfile[1]);
531621Sbill }
532621Sbill 
533621Sbill onintr()
534621Sbill {
535621Sbill 
536621Sbill 	errs = 1;
537621Sbill 	done();
538621Sbill }
539621Sbill 
540621Sbill getsuf(cp)
541621Sbill 	char *cp;
542621Sbill {
543621Sbill 
544621Sbill 	if (*cp == 0)
545621Sbill 		return;
546621Sbill 	while (cp[1])
547621Sbill 		cp++;
548621Sbill 	if (cp[-1] != '.')
549621Sbill 		return (0);
550621Sbill 	return (*cp);
551621Sbill }
552621Sbill 
553621Sbill char *
554654Sbill setsuf(as, ch)
555654Sbill 	char *as;
556621Sbill {
557654Sbill 	register char *s, *s1;
558621Sbill 
559654Sbill 	s = s1 = savestr(as);
560654Sbill 	while (*s)
561654Sbill 		if (*s++ == '/')
562654Sbill 			s1 = s;
563654Sbill 	s[-1] = ch;
564654Sbill 	return (s1);
565621Sbill }
566621Sbill 
567621Sbill #define	NSAVETAB	512
568621Sbill char	*savetab;
569621Sbill int	saveleft;
570621Sbill 
571621Sbill char *
572621Sbill savestr(cp)
573621Sbill 	register char *cp;
574621Sbill {
575621Sbill 	register int len;
576621Sbill 
577621Sbill 	len = strlen(cp) + 1;
578621Sbill 	if (len > saveleft) {
579621Sbill 		saveleft = NSAVETAB;
580621Sbill 		if (len > saveleft)
581621Sbill 			saveleft = len;
582621Sbill 		savetab = (char *)malloc(saveleft);
583621Sbill 		if (savetab == 0) {
584621Sbill 			fprintf(stderr, "ran out of memory (savestr)\n");
585621Sbill 			exit(1);
586621Sbill 		}
587621Sbill 	}
588621Sbill 	strncpy(savetab, cp, len);
589621Sbill 	cp = savetab;
590621Sbill 	savetab += len;
591621Sbill 	return (cp);
592621Sbill }
593621Sbill 
594621Sbill suffix(cp)
595621Sbill 	char *cp;
596621Sbill {
597621Sbill 
598621Sbill 	if (cp[0] == 0 || cp[1] == 0)
599621Sbill 		return (0);
600621Sbill 	while (cp[1])
601621Sbill 		cp++;
602621Sbill 	if (cp[-1] == '.')
603621Sbill 		return (*cp);
604621Sbill 	return (0);
605621Sbill }
606