xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 12931)
1*12931Speter static	char sccsid[] = "@(#)pc.c 3.23 06/06/83";
25054Smckusic 
3621Sbill #include <stdio.h>
4621Sbill #include <signal.h>
5621Sbill #include <wait.h>
612870Speter #include <sys/param.h>
7621Sbill 
8621Sbill /*
9654Sbill  * Pc - front end for Pascal compiler.
10621Sbill  */
11908Sbill char	*pc0 = "/usr/lib/pc0";
12908Sbill char	*pc1 = "/lib/f1";
13908Sbill char	*pc2 = "/usr/lib/pc2";
14908Sbill char	*c2 = "/lib/c2";
15908Sbill char	*pc3 = "/usr/lib/pc3";
16908Sbill char	*ld = "/bin/ld";
17908Sbill char	*as = "/bin/as";
18621Sbill char	*lpc = "-lpc";
19908Sbill char	*crt0 = "/lib/crt0.o";
20908Sbill char	*mcrt0 = "/lib/mcrt0.o";
215054Smckusic char	*gcrt0 = "/usr/lib/gcrt0.o";
22621Sbill 
23621Sbill char	*mktemp();
2412870Speter char	*tmpdir = "/tmp";
2512870Speter char	tmp0[MAXPATHLEN], tmp1[MAXPATHLEN];
26621Sbill char	*tname[2];
27621Sbill char	*tfile[2];
28621Sbill 
29621Sbill char	*setsuf(), *savestr();
30621Sbill 
3112870Speter int	Jflag, Sflag, Oflag, Tlflag, cflag, gflag, pflag, wflag, tflag;
32621Sbill int	debug;
33621Sbill 
34621Sbill #define	NARGS	512
35621Sbill int	ldargx = 3;
36621Sbill int	pc0argx = 3;
37621Sbill char	*pc0args[NARGS] =	{ "pc0", "-o", "XXX" };
38621Sbill char	*pc1args[3] =		{ "pc1", 0, };
39621Sbill char	*pc2args[2] =		{ "pc2", 0 };
40621Sbill char	*c2args[4] =		{ "c2", 0, 0, 0 };
417596Smckusick int	pc3argx = 1;
42621Sbill #define	pc3args	pc0args
43621Sbill #define	ldargs	pc0args
447596Smckusick /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
45908Sbill /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
4612870Speter 
4712870Speter 				/* as -J -t tmpdir -o objfile srcfile \0 */
48908Sbill int	asargx;
4912870Speter char	*asargs[8] =		{ "as", 0, };
50621Sbill 
517766Smckusick char *mesg[] = {
527766Smckusick 	0,
537766Smckusick 	"Hangup",
547766Smckusick 	"Interrupt",
557766Smckusick 	"Quit",
567766Smckusick 	"Illegal instruction",
577766Smckusick 	"Trace/BPT trap",
587766Smckusick 	"IOT trap",
597766Smckusick 	"EMT trap",
607766Smckusick 	"Floating exception",
617766Smckusick 	"Killed",
627766Smckusick 	"Bus error",
637766Smckusick 	"Segmentation fault",
647766Smckusick 	"Bad system call",
657766Smckusick 	"Broken pipe",
667766Smckusick 	"Alarm clock",
677766Smckusick 	"Terminated",
687766Smckusick 	"Signal 16",
697766Smckusick 	"Stopped (signal)",
707766Smckusick 	"Stopped",
717766Smckusick 	"Continued",
727766Smckusick 	"Child exited",
737766Smckusick 	"Stopped (tty input)",
747766Smckusick 	"Stopped (tty output)",
757766Smckusick 	"Tty input interrupt",
767766Smckusick 	"Cputime limit exceeded",
777766Smckusick 	"Filesize limit exceeded",
787766Smckusick 	"Signal 26",
797766Smckusick 	"Signal 27",
807766Smckusick 	"Signal 28",
817766Smckusick 	"Signal 29",
827766Smckusick 	"Signal 30",
837766Smckusick 	"Signal 31",
847766Smckusick 	"Signal 32"
857766Smckusick };
867766Smckusick 
87621Sbill /*
88621Sbill  * If the number of .p arguments (np) is 1, and the number of .o arguments
89621Sbill  * (nxo) is 0, and we successfully create an ``a.out'', then we remove
90621Sbill  * the one .ps .o file (onepso).
91621Sbill  */
92621Sbill int	np, nxo;
93621Sbill char	*onepso;
94621Sbill int	errs;
95621Sbill 
96621Sbill int	onintr();
97621Sbill 
98621Sbill main(argc, argv)
99621Sbill 	int argc;
100621Sbill 	char **argv;
101621Sbill {
102621Sbill 	register char *argp;
103621Sbill 	register int i;
104621Sbill 	int savargx;
105621Sbill 	char *t, c;
106621Sbill 	int j;
107621Sbill 
108621Sbill 	argc--, argv++;
109621Sbill 	if (argc == 0) {
110621Sbill 		execl("/bin/cat", "cat", "/usr/lib/how_pc");
111621Sbill 		exit(1);
112621Sbill 	}
113621Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
114621Sbill 		signal(SIGINT, onintr);
115621Sbill 		signal(SIGTERM, onintr);
116621Sbill 	}
117621Sbill 	for (i = 0; i < argc; i++) {
118621Sbill 		argp = argv[i];
119621Sbill 		if (argp[0] != '-')
120621Sbill 			continue;
121621Sbill 		switch (argp[1]) {
122621Sbill 
123621Sbill 		case 'd':
124621Sbill 			if (argp[2] == 0)
125621Sbill 				debug++;
126621Sbill 			continue;
127621Sbill 		case 'i':
128621Sbill 			pc0args[pc0argx++] = "-i";
129621Sbill 			while (i+1 < argc && argv[i+1][0] != '-' &&
130621Sbill 			    getsuf(argv[i+1]) != 'p') {
131621Sbill 				pc0args[pc0argx++] = argv[i+1];
132621Sbill 				i++;
133621Sbill 			}
134621Sbill 			if (i+1 == argc) {
135621Sbill 				fprintf(stderr, "pc: bad -i construction\n");
136621Sbill 				exit(1);
137621Sbill 			}
138621Sbill 			continue;
139621Sbill 		case 'o':
140621Sbill 			i++;
141621Sbill 			if (i == argc) {
142621Sbill 				fprintf(stderr, "pc: -o must specify file\n");
143621Sbill 				exit(1);
144621Sbill 			}
145621Sbill 			c = getsuf(argv[i]);
146621Sbill 			if (c == 'o' || c == 'p' || c == 'c') {
147621Sbill 				fprintf(stderr, "pc: -o would overwrite %s\n",
148621Sbill 				    argv[i]);
149621Sbill 				exit(1);
150621Sbill 			}
151621Sbill 			continue;
15212870Speter 		case 't':
15312870Speter 			i++;
15412870Speter 			if (i == argc) {
155*12931Speter 				fprintf(stderr, "pc: -t but no directory\n");
15612870Speter 				exit(1);
15712870Speter 			}
158*12931Speter 			if (argp[2] != '\0') {
159*12931Speter 				fprintf(stderr, "pc: bad -t option\n");
160*12931Speter 				exit(1);
161*12931Speter 			}
16212870Speter 			tmpdir = argv[i];
163*12931Speter 			if (tmpdir[0] == '-') {
164*12931Speter 				fprintf(stderr, "pc: bad -t option\n");
165*12931Speter 				exit(1);
166*12931Speter 			}
16712870Speter 			tflag = 1;
16812870Speter 			continue;
169621Sbill 		case 'O':
170621Sbill 			Oflag = 1;
171621Sbill 			continue;
172621Sbill 		case 'S':
173621Sbill 			Sflag = 1;
174621Sbill 			continue;
175908Sbill 		case 'J':
176908Sbill 			Jflag = 1;
177908Sbill 			continue;
178621Sbill 		case 'T':
179621Sbill 			switch (argp[2]) {
180621Sbill 
181621Sbill 			case '0':
18210721Smckusick 				pc0 = "/usr/src/ucb/pascal/pc0/a.out";
1833862Smckusic 				if (argp[3] != '\0') {
1843862Smckusic 					pc0 = &argp[3];
1853862Smckusic 				}
186621Sbill 				continue;
187621Sbill 			case '1':
1889140Smckusick 				pc1 = "/usr/src/lib/pcc/fort";
1893862Smckusic 				if (argp[3] != '\0') {
1903862Smckusic 					pc1 = &argp[3];
1913862Smckusic 				}
192621Sbill 				continue;
193621Sbill 			case '2':
19410721Smckusick 				pc2 = "/usr/src/ucb/pascal/utilities/pc2";
1953862Smckusic 				if (argp[3] != '\0') {
1963862Smckusic 					pc2 = &argp[3];
1973862Smckusic 				}
198621Sbill 				continue;
199621Sbill 			case '3':
20010721Smckusick 				pc3 = "/usr/src/ucb/pascal/utilities/pc3";
2013862Smckusic 				if (argp[3] != '\0') {
2023862Smckusic 					pc3 = &argp[3];
2033862Smckusic 				}
204621Sbill 				continue;
205621Sbill 			case 'l':
2065054Smckusic 				Tlflag = 1;
2079140Smckusick 				lpc = "/usr/src/usr.lib/libpc/libpc";
2083862Smckusic 				if (argp[3] != '\0') {
2093862Smckusic 					lpc = &argp[3];
2103862Smckusic 				}
211621Sbill 				continue;
212621Sbill 			}
213621Sbill 			continue;
214621Sbill 		case 'c':
215621Sbill 			cflag = 1;
216621Sbill 			continue;
217621Sbill 		case 'l':
218621Sbill 			if (argp[2])
219621Sbill 				continue;
220621Sbill 			/* fall into ... */
221621Sbill 		case 'b':
222621Sbill 		case 's':
223621Sbill 		case 'z':
224621Sbill 		case 'C':
225621Sbill 			pc0args[pc0argx++] = argp;
226621Sbill 			continue;
2277596Smckusick 		case 'w':
2287596Smckusick 			wflag = 1;
2297596Smckusick 			pc0args[pc0argx++] = argp;
2307596Smckusick 			continue;
2317596Smckusick 		case 'g':
2327596Smckusick 			gflag = 1;
2337596Smckusick 			pc0args[pc0argx++] = argp;
2347596Smckusick 			continue;
235621Sbill 		case 'p':
2365054Smckusic 			if (argp[2] == 'g')
2375054Smckusic 				crt0 = gcrt0;
2385054Smckusic 			else
2395054Smckusic 				crt0 = mcrt0;
2405054Smckusic 			if (!Tlflag)
2415054Smckusic 				lpc = "-lpc_p";
2425054Smckusic 			pflag = 1;
243654Sbill 			continue;
244621Sbill 		}
245621Sbill 	}
246621Sbill 	if (gflag && Oflag) {
247621Sbill 		fprintf(stderr, "pc: warning: -g overrides -O\n");
248621Sbill 		Oflag = 0;
249621Sbill 	}
25012870Speter 	sprintf(tmp0, "%s/%s", tmpdir, "p0XXXXXX");
25112870Speter 	tname[0] = mktemp(tmp0);
25212870Speter 	sprintf(tmp1, "%s/%s", tmpdir, "p1XXXXXX");
25312870Speter 	tname[1] = mktemp(tmp1);
254621Sbill 	savargx = pc0argx;
255621Sbill 	for (i = 0; i < argc; i++) {
256621Sbill 		argp = argv[i];
257621Sbill 		if (argp[0] == '-')
258621Sbill 			continue;
2591211Speter 		if (suffix(argp) == 's') {
2601211Speter 			asargx = 1;
2611211Speter 			if (Jflag)
2621211Speter 				asargs[asargx++] = "-J";
26312870Speter #			ifdef vax
26412870Speter 				if (tflag) {
26512870Speter 					asargs[asargx++] = "-t";
26612870Speter 					asargs[asargx++] = tmpdir;
26712870Speter 				}
26812870Speter #			endif vax
2691211Speter 			asargs[asargx++] = argp;
2701211Speter 			asargs[asargx++] = "-o";
2711211Speter 			tfile[1] = setsuf(argp, 'o');
2721211Speter 			asargs[asargx++] = tfile[1];
2731211Speter 			asargs[asargx] = 0;
2741211Speter 			if (dosys(as, asargs, 0, 0))
2751211Speter 				continue;
2761211Speter 			tfile[1] = 0;
2771211Speter 			continue;
2781211Speter 		}
279621Sbill 		if (suffix(argp) != 'p')
280621Sbill 			continue;
281621Sbill 		tfile[0] = tname[0];
282621Sbill 		pc0args[2] = tfile[0];
283621Sbill 		pc0argx = savargx;
284654Sbill 		if (pflag)
285654Sbill 			pc0args[pc0argx++] = "-p";
286621Sbill 		pc0args[pc0argx++] = argp;
287621Sbill 		pc0args[pc0argx] = 0;
288621Sbill 		if (dosys(pc0, pc0args, 0, 0))
289621Sbill 			continue;
290621Sbill 		pc1args[1] = tfile[0];
291654Sbill 		tfile[1] = tname[1];
292621Sbill 		if (dosys(pc1, pc1args, 0, tfile[1]))
293621Sbill 			continue;
294621Sbill 		unlink(tfile[0]);
2952340Smckusic 		tfile[0] = tname[0];
2962340Smckusic 		if (Oflag) {
2972340Smckusic 			if (dosys(c2, c2args, tfile[1], tfile[0]))
2982340Smckusic 				continue;
2992340Smckusic 			unlink(tfile[1]);
3002340Smckusic 			tfile[1] = tfile[0];
3012340Smckusic 			tfile[0] = tname[1];
3022340Smckusic 		}
3032340Smckusic 		if (Sflag)
304654Sbill 			tfile[0] = setsuf(argp, 's');
305621Sbill 		if (dosys(pc2, pc2args, tfile[1], tfile[0]))
306621Sbill 			continue;
307621Sbill 		unlink(tfile[1]);
308621Sbill 		tfile[1] = 0;
309654Sbill 		if (Sflag) {
310654Sbill 			tfile[0] = 0;
311621Sbill 			continue;
312654Sbill 		}
313908Sbill 		asargx = 1;
314908Sbill 		if (Jflag)
315908Sbill 			asargs[asargx++] = "-J";
31612870Speter #		ifdef vax
31712870Speter 			if (tflag) {
31812870Speter 				asargs[asargx++] = "-t";
31912870Speter 				asargs[asargx++] = tmpdir;
32012870Speter 			}
32112870Speter #		endif vax
322908Sbill 		asargs[asargx++] = tfile[0];
323908Sbill 		asargs[asargx++] = "-o";
324621Sbill 		tfile[1] = setsuf(argp, 'o');
325908Sbill 		asargs[asargx++] = tfile[1];
326908Sbill 		asargs[asargx] = 0;
327621Sbill 		if (dosys(as, asargs, 0, 0))
328621Sbill 			continue;
329621Sbill 		tfile[1] = 0;
330621Sbill 		remove();
331621Sbill 	}
332621Sbill 	if (errs || cflag || Sflag)
333621Sbill 		done();
3347596Smckusick /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
335621Sbill 	pc3args[0] = "pc3";
3367596Smckusick 	if (wflag)
3377596Smckusick 		pc3args[pc3argx++] = "-w";
3387596Smckusick 	pc3args[pc3argx++] = "/usr/lib/pcexterns.o";
339621Sbill 	for (i = 0; i < argc; i++) {
340621Sbill 		argp = argv[i];
341621Sbill 		if (!strcmp(argp, "-o"))
342621Sbill 			i++;
343621Sbill 		if (argp[0] == '-')
344621Sbill 			continue;
345621Sbill 		switch (getsuf(argp)) {
346621Sbill 
347621Sbill 		case 'o':
348621Sbill 			pc3args[pc3argx++] = argp;
349621Sbill 			nxo++;
350621Sbill 			continue;
3511211Speter 		case 's':
352621Sbill 		case 'p':
353621Sbill 			onepso = pc3args[pc3argx++] =
354621Sbill 			    savestr(setsuf(argp, 'o'));
355621Sbill 			np++;
356621Sbill 			continue;
357621Sbill 		}
358621Sbill 	}
359621Sbill 	pc3args[pc3argx] = 0;
3607596Smckusick 	if (dosys(pc3, pc3args, 0, 0) > 1)
361621Sbill 		done();
36210672Speter 	errs = 0;
363908Sbill /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
364621Sbill 	ldargs[0] = "ld";
365621Sbill 	ldargs[1] = "-X";
366654Sbill 	ldargs[2] = crt0;
367621Sbill 	for (i = 0; i < argc; i++) {
368621Sbill 		argp = argv[i];
369621Sbill 		if (argp[0] != '-') {
370621Sbill 			switch (getsuf(argp)) {
371621Sbill 
372621Sbill 			case 'p':
3731211Speter 			case 's':
374621Sbill 				ldargs[ldargx] = savestr(setsuf(argp, 'o'));
375621Sbill 				break;
376621Sbill 			default:
377621Sbill 				ldargs[ldargx] = argp;
378621Sbill 				break;
379621Sbill 			}
380621Sbill 			if (getsuf(ldargs[ldargx]) == 'o')
381621Sbill 			for (j = 0; j < ldargx; j++)
382621Sbill 				if (!strcmp(ldargs[j], ldargs[ldargx]))
383621Sbill 					goto duplicate;
384621Sbill 			ldargx++;
385621Sbill duplicate:
386621Sbill 			continue;
387621Sbill 		}
388621Sbill 		switch (argp[1]) {
389621Sbill 
390621Sbill 		case 'i':
391621Sbill 			while (i+1 < argc && argv[i+1][0] != '-' &&
392621Sbill 			    getsuf(argv[i+1]) != 'p')
393621Sbill 				i++;
394621Sbill 			continue;
395621Sbill 		case 'd':
396621Sbill 			if (argp[2] == 0)
397621Sbill 				continue;
398621Sbill 			ldargs[ldargx++] = argp;
399621Sbill 			continue;
400621Sbill 		case 'o':
401621Sbill 			ldargs[ldargx++] = argp;
402621Sbill 			i++;
403621Sbill 			ldargs[ldargx++] = argv[i];
404621Sbill 			continue;
405621Sbill 		case 'l':
406621Sbill 			if (argp[2])
407621Sbill 				ldargs[ldargx++] = argp;
408621Sbill 			continue;
40912870Speter 		case 't':
41012870Speter 			i++;
41112870Speter 			continue;
412621Sbill 		case 'c':
413621Sbill 		case 'g':
414621Sbill 		case 'w':
415621Sbill 		case 'p':
416621Sbill 		case 'S':
417908Sbill 		case 'J':
418621Sbill 		case 'T':
419621Sbill 		case 'O':
420621Sbill 		case 'C':
421621Sbill 		case 'b':
422621Sbill 		case 's':
423621Sbill 		case 'z':
424621Sbill 			continue;
425621Sbill 		default:
426621Sbill 			ldargs[ldargx++] = argp;
427621Sbill 			continue;
428621Sbill 		}
429621Sbill 	}
430621Sbill 	ldargs[ldargx++] = lpc;
431621Sbill 	if (gflag)
432621Sbill 		ldargs[ldargx++] = "-lg";
4335054Smckusic 	if (pflag) {
4345054Smckusic 		ldargs[ldargx++] = "-lm_p";
4355054Smckusic 		ldargs[ldargx++] = "-lc_p";
4365054Smckusic 	} else {
4375054Smckusic 		ldargs[ldargx++] = "-lm";
4385054Smckusic 		ldargs[ldargx++] = "-lc";
4395054Smckusic 	}
440621Sbill 	ldargs[ldargx] = 0;
441621Sbill 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
442621Sbill 		unlink(onepso);
443621Sbill 	done();
444621Sbill }
445621Sbill 
446621Sbill dosys(cmd, argv, in, out)
447621Sbill 	char *cmd, **argv, *in, *out;
448621Sbill {
449621Sbill 	union wait status;
450621Sbill 	int pid;
451621Sbill 
452621Sbill 	if (debug) {
453621Sbill 		int i;
454621Sbill 		printf("%s:", cmd);
455621Sbill 		for (i = 0; argv[i]; i++)
456621Sbill 			printf(" %s", argv[i]);
457621Sbill 		if (in)
458621Sbill 			printf(" <%s", in);
459621Sbill 		if (out)
460621Sbill 			printf(" >%s", out);
461621Sbill 		printf("\n");
462621Sbill 	}
463621Sbill 	pid = vfork();
464621Sbill 	if (pid < 0) {
465621Sbill 		fprintf(stderr, "pc: No more processes\n");
466621Sbill 		done();
467621Sbill 	}
468621Sbill 	if (pid == 0) {
469621Sbill 		if (in) {
470621Sbill 			close(0);
471621Sbill 			if (open(in, 0) != 0) {
472621Sbill 				perror(in);
473621Sbill 				exit(1);
474621Sbill 			}
475621Sbill 		}
476621Sbill 		if (out) {
477621Sbill 			close(1);
478621Sbill 			unlink(out);
479621Sbill 			if (creat(out, 0666) != 1) {
480621Sbill 				perror(out);
481621Sbill 				exit(1);
482621Sbill 			}
483621Sbill 		}
484621Sbill 		signal(SIGINT, SIG_DFL);
485621Sbill 		execv(cmd, argv);
486621Sbill 		perror(cmd);
487621Sbill 		exit(1);
488621Sbill 	}
489621Sbill 	while (wait(&status) != pid)
490621Sbill 		;
491621Sbill 	if (WIFSIGNALED(status)) {
4927766Smckusick 		if (status.w_termsig != SIGINT) {
4937766Smckusick 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
4947766Smckusick 			if (status.w_coredump)
4957766Smckusick 				fprintf(stderr, " (core dumped)");
4967766Smckusick 			fprintf(stderr, "\n");
4977766Smckusick 		}
498621Sbill 		errs = 100;
499621Sbill 		done();
500621Sbill 		/*NOTREACHED*/
501621Sbill 	}
502621Sbill 	if (status.w_retcode) {
503621Sbill 		errs = 1;
504621Sbill 		remove();
505621Sbill 	}
506621Sbill 	return (status.w_retcode);
507621Sbill }
508621Sbill 
509621Sbill done()
510621Sbill {
511621Sbill 
512621Sbill 	remove();
513621Sbill 	exit(errs);
514621Sbill }
515621Sbill 
516621Sbill remove()
517621Sbill {
518621Sbill 
519621Sbill 	if (tfile[0])
520621Sbill 		unlink(tfile[0]);
521621Sbill 	if (tfile[1])
522621Sbill 		unlink(tfile[1]);
523621Sbill }
524621Sbill 
525621Sbill onintr()
526621Sbill {
527621Sbill 
528621Sbill 	errs = 1;
529621Sbill 	done();
530621Sbill }
531621Sbill 
532621Sbill getsuf(cp)
533621Sbill 	char *cp;
534621Sbill {
535621Sbill 
536621Sbill 	if (*cp == 0)
537621Sbill 		return;
538621Sbill 	while (cp[1])
539621Sbill 		cp++;
540621Sbill 	if (cp[-1] != '.')
541621Sbill 		return (0);
542621Sbill 	return (*cp);
543621Sbill }
544621Sbill 
545621Sbill char *
546654Sbill setsuf(as, ch)
547654Sbill 	char *as;
548621Sbill {
549654Sbill 	register char *s, *s1;
550621Sbill 
551654Sbill 	s = s1 = savestr(as);
552654Sbill 	while (*s)
553654Sbill 		if (*s++ == '/')
554654Sbill 			s1 = s;
555654Sbill 	s[-1] = ch;
556654Sbill 	return (s1);
557621Sbill }
558621Sbill 
559621Sbill #define	NSAVETAB	512
560621Sbill char	*savetab;
561621Sbill int	saveleft;
562621Sbill 
563621Sbill char *
564621Sbill savestr(cp)
565621Sbill 	register char *cp;
566621Sbill {
567621Sbill 	register int len;
568621Sbill 
569621Sbill 	len = strlen(cp) + 1;
570621Sbill 	if (len > saveleft) {
571621Sbill 		saveleft = NSAVETAB;
572621Sbill 		if (len > saveleft)
573621Sbill 			saveleft = len;
574621Sbill 		savetab = (char *)malloc(saveleft);
575621Sbill 		if (savetab == 0) {
576621Sbill 			fprintf(stderr, "ran out of memory (savestr)\n");
577621Sbill 			exit(1);
578621Sbill 		}
579621Sbill 	}
580621Sbill 	strncpy(savetab, cp, len);
581621Sbill 	cp = savetab;
582621Sbill 	savetab += len;
583621Sbill 	return (cp);
584621Sbill }
585621Sbill 
586621Sbill suffix(cp)
587621Sbill 	char *cp;
588621Sbill {
589621Sbill 
590621Sbill 	if (cp[0] == 0 || cp[1] == 0)
591621Sbill 		return (0);
592621Sbill 	while (cp[1])
593621Sbill 		cp++;
594621Sbill 	if (cp[-1] == '.')
595621Sbill 		return (*cp);
596621Sbill 	return (0);
597621Sbill }
598