xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 31043)
122260Sdist /*
222260Sdist  * Copyright (c) 1980 Regents of the University of California.
322260Sdist  * All rights reserved.  The Berkeley software License Agreement
422260Sdist  * specifies the terms and conditions for redistribution.
522260Sdist  */
622260Sdist 
713724Ssam #ifndef lint
822260Sdist char copyright[] =
922260Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1022260Sdist  All rights reserved.\n";
1122260Sdist #endif not lint
125054Smckusic 
1322260Sdist #ifndef lint
14*31043Ssam static char sccsid[] = "@(#)pc.c	5.3 (Berkeley) 05/08/87";
1522260Sdist #endif not lint
1622260Sdist 
17621Sbill #include <stdio.h>
18621Sbill #include <signal.h>
19*31043Ssam #include <sys/param.h>
2013724Ssam #include <sys/wait.h>
21621Sbill 
22621Sbill /*
23654Sbill  * Pc - front end for Pascal compiler.
24621Sbill  */
25908Sbill char	*pc0 = "/usr/lib/pc0";
26908Sbill char	*pc1 = "/lib/f1";
27908Sbill char	*pc2 = "/usr/lib/pc2";
28908Sbill char	*c2 = "/lib/c2";
29908Sbill char	*pc3 = "/usr/lib/pc3";
30908Sbill char	*ld = "/bin/ld";
31908Sbill char	*as = "/bin/as";
32621Sbill char	*lpc = "-lpc";
33908Sbill char	*crt0 = "/lib/crt0.o";
34908Sbill char	*mcrt0 = "/lib/mcrt0.o";
355054Smckusic char	*gcrt0 = "/usr/lib/gcrt0.o";
36621Sbill 
37621Sbill char	*mktemp();
3812870Speter char	*tmpdir = "/tmp";
3912870Speter char	tmp0[MAXPATHLEN], tmp1[MAXPATHLEN];
40621Sbill char	*tname[2];
41621Sbill char	*tfile[2];
42621Sbill 
43621Sbill char	*setsuf(), *savestr();
44621Sbill 
4512870Speter int	Jflag, Sflag, Oflag, Tlflag, cflag, gflag, pflag, wflag, tflag;
46621Sbill int	debug;
47621Sbill 
48621Sbill #define	NARGS	512
49621Sbill int	ldargx = 3;
50621Sbill int	pc0argx = 3;
51621Sbill char	*pc0args[NARGS] =	{ "pc0", "-o", "XXX" };
52621Sbill char	*pc1args[3] =		{ "pc1", 0, };
53621Sbill char	*pc2args[2] =		{ "pc2", 0 };
54621Sbill char	*c2args[4] =		{ "c2", 0, 0, 0 };
557596Smckusick int	pc3argx = 1;
56621Sbill #define	pc3args	pc0args
57621Sbill #define	ldargs	pc0args
587596Smckusick /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
59908Sbill /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
6012870Speter 
6112870Speter 				/* as -J -t tmpdir -o objfile srcfile \0 */
62908Sbill int	asargx;
6312870Speter char	*asargs[8] =		{ "as", 0, };
64621Sbill 
657766Smckusick char *mesg[] = {
667766Smckusick 	0,
677766Smckusick 	"Hangup",
687766Smckusick 	"Interrupt",
697766Smckusick 	"Quit",
707766Smckusick 	"Illegal instruction",
717766Smckusick 	"Trace/BPT trap",
727766Smckusick 	"IOT trap",
737766Smckusick 	"EMT trap",
747766Smckusick 	"Floating exception",
757766Smckusick 	"Killed",
767766Smckusick 	"Bus error",
777766Smckusick 	"Segmentation fault",
787766Smckusick 	"Bad system call",
797766Smckusick 	"Broken pipe",
807766Smckusick 	"Alarm clock",
817766Smckusick 	"Terminated",
827766Smckusick 	"Signal 16",
837766Smckusick 	"Stopped (signal)",
847766Smckusick 	"Stopped",
857766Smckusick 	"Continued",
867766Smckusick 	"Child exited",
877766Smckusick 	"Stopped (tty input)",
887766Smckusick 	"Stopped (tty output)",
897766Smckusick 	"Tty input interrupt",
907766Smckusick 	"Cputime limit exceeded",
917766Smckusick 	"Filesize limit exceeded",
927766Smckusick 	"Signal 26",
937766Smckusick 	"Signal 27",
947766Smckusick 	"Signal 28",
957766Smckusick 	"Signal 29",
967766Smckusick 	"Signal 30",
977766Smckusick 	"Signal 31",
987766Smckusick 	"Signal 32"
997766Smckusick };
1007766Smckusick 
101621Sbill /*
102621Sbill  * If the number of .p arguments (np) is 1, and the number of .o arguments
103621Sbill  * (nxo) is 0, and we successfully create an ``a.out'', then we remove
104621Sbill  * the one .ps .o file (onepso).
105621Sbill  */
106621Sbill int	np, nxo;
107621Sbill char	*onepso;
108621Sbill int	errs;
109621Sbill 
110621Sbill int	onintr();
111621Sbill 
112621Sbill main(argc, argv)
113621Sbill 	int argc;
114621Sbill 	char **argv;
115621Sbill {
116621Sbill 	register char *argp;
117621Sbill 	register int i;
118621Sbill 	int savargx;
119621Sbill 	char *t, c;
120621Sbill 	int j;
121621Sbill 
122621Sbill 	argc--, argv++;
123621Sbill 	if (argc == 0) {
124621Sbill 		execl("/bin/cat", "cat", "/usr/lib/how_pc");
125621Sbill 		exit(1);
126621Sbill 	}
127621Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
128621Sbill 		signal(SIGINT, onintr);
129621Sbill 		signal(SIGTERM, onintr);
130621Sbill 	}
131621Sbill 	for (i = 0; i < argc; i++) {
132621Sbill 		argp = argv[i];
133621Sbill 		if (argp[0] != '-')
134621Sbill 			continue;
135621Sbill 		switch (argp[1]) {
136621Sbill 
137621Sbill 		case 'd':
138621Sbill 			if (argp[2] == 0)
139621Sbill 				debug++;
140621Sbill 			continue;
141621Sbill 		case 'i':
142621Sbill 			pc0args[pc0argx++] = "-i";
143621Sbill 			while (i+1 < argc && argv[i+1][0] != '-' &&
144621Sbill 			    getsuf(argv[i+1]) != 'p') {
145621Sbill 				pc0args[pc0argx++] = argv[i+1];
146621Sbill 				i++;
147621Sbill 			}
148621Sbill 			if (i+1 == argc) {
149621Sbill 				fprintf(stderr, "pc: bad -i construction\n");
150621Sbill 				exit(1);
151621Sbill 			}
152621Sbill 			continue;
153621Sbill 		case 'o':
154621Sbill 			i++;
155621Sbill 			if (i == argc) {
156621Sbill 				fprintf(stderr, "pc: -o must specify file\n");
157621Sbill 				exit(1);
158621Sbill 			}
159621Sbill 			c = getsuf(argv[i]);
160621Sbill 			if (c == 'o' || c == 'p' || c == 'c') {
161621Sbill 				fprintf(stderr, "pc: -o would overwrite %s\n",
162621Sbill 				    argv[i]);
163621Sbill 				exit(1);
164621Sbill 			}
165621Sbill 			continue;
16612870Speter 		case 't':
16712870Speter 			i++;
16812870Speter 			if (i == argc) {
16912931Speter 				fprintf(stderr, "pc: -t but no directory\n");
17012870Speter 				exit(1);
17112870Speter 			}
17212931Speter 			if (argp[2] != '\0') {
17312931Speter 				fprintf(stderr, "pc: bad -t option\n");
17412931Speter 				exit(1);
17512931Speter 			}
17612870Speter 			tmpdir = argv[i];
17712931Speter 			if (tmpdir[0] == '-') {
17812931Speter 				fprintf(stderr, "pc: bad -t option\n");
17912931Speter 				exit(1);
18012931Speter 			}
18112870Speter 			tflag = 1;
18212870Speter 			continue;
183621Sbill 		case 'O':
184621Sbill 			Oflag = 1;
185621Sbill 			continue;
186621Sbill 		case 'S':
187621Sbill 			Sflag = 1;
188621Sbill 			continue;
189908Sbill 		case 'J':
190908Sbill 			Jflag = 1;
191908Sbill 			continue;
192621Sbill 		case 'T':
193621Sbill 			switch (argp[2]) {
194621Sbill 
195621Sbill 			case '0':
19610721Smckusick 				pc0 = "/usr/src/ucb/pascal/pc0/a.out";
1973862Smckusic 				if (argp[3] != '\0') {
1983862Smckusic 					pc0 = &argp[3];
1993862Smckusic 				}
200621Sbill 				continue;
201621Sbill 			case '1':
2029140Smckusick 				pc1 = "/usr/src/lib/pcc/fort";
2033862Smckusic 				if (argp[3] != '\0') {
2043862Smckusic 					pc1 = &argp[3];
2053862Smckusic 				}
206621Sbill 				continue;
207621Sbill 			case '2':
20810721Smckusick 				pc2 = "/usr/src/ucb/pascal/utilities/pc2";
2093862Smckusic 				if (argp[3] != '\0') {
2103862Smckusic 					pc2 = &argp[3];
2113862Smckusic 				}
212621Sbill 				continue;
213621Sbill 			case '3':
21410721Smckusick 				pc3 = "/usr/src/ucb/pascal/utilities/pc3";
2153862Smckusic 				if (argp[3] != '\0') {
2163862Smckusic 					pc3 = &argp[3];
2173862Smckusic 				}
218621Sbill 				continue;
219621Sbill 			case 'l':
2205054Smckusic 				Tlflag = 1;
2219140Smckusick 				lpc = "/usr/src/usr.lib/libpc/libpc";
2223862Smckusic 				if (argp[3] != '\0') {
2233862Smckusic 					lpc = &argp[3];
2243862Smckusic 				}
225621Sbill 				continue;
226621Sbill 			}
227621Sbill 			continue;
228621Sbill 		case 'c':
229621Sbill 			cflag = 1;
230621Sbill 			continue;
231621Sbill 		case 'l':
232621Sbill 			if (argp[2])
233621Sbill 				continue;
234621Sbill 			/* fall into ... */
235621Sbill 		case 'b':
236621Sbill 		case 's':
237621Sbill 		case 'z':
238621Sbill 		case 'C':
239621Sbill 			pc0args[pc0argx++] = argp;
240621Sbill 			continue;
2417596Smckusick 		case 'w':
2427596Smckusick 			wflag = 1;
2437596Smckusick 			pc0args[pc0argx++] = argp;
2447596Smckusick 			continue;
2457596Smckusick 		case 'g':
2467596Smckusick 			gflag = 1;
2477596Smckusick 			pc0args[pc0argx++] = argp;
2487596Smckusick 			continue;
249621Sbill 		case 'p':
2505054Smckusic 			if (argp[2] == 'g')
2515054Smckusic 				crt0 = gcrt0;
2525054Smckusic 			else
2535054Smckusic 				crt0 = mcrt0;
2545054Smckusic 			if (!Tlflag)
2555054Smckusic 				lpc = "-lpc_p";
2565054Smckusic 			pflag = 1;
257654Sbill 			continue;
258621Sbill 		}
259621Sbill 	}
260621Sbill 	if (gflag && Oflag) {
261621Sbill 		fprintf(stderr, "pc: warning: -g overrides -O\n");
262621Sbill 		Oflag = 0;
263621Sbill 	}
26412870Speter 	sprintf(tmp0, "%s/%s", tmpdir, "p0XXXXXX");
26512870Speter 	tname[0] = mktemp(tmp0);
26612870Speter 	sprintf(tmp1, "%s/%s", tmpdir, "p1XXXXXX");
26712870Speter 	tname[1] = mktemp(tmp1);
268621Sbill 	savargx = pc0argx;
269621Sbill 	for (i = 0; i < argc; i++) {
270621Sbill 		argp = argv[i];
271621Sbill 		if (argp[0] == '-')
272621Sbill 			continue;
2731211Speter 		if (suffix(argp) == 's') {
2741211Speter 			asargx = 1;
2751211Speter 			if (Jflag)
2761211Speter 				asargs[asargx++] = "-J";
27730092Smckusick #			if defined(vax) || defined(tahoe)
27812870Speter 				if (tflag) {
27912870Speter 					asargs[asargx++] = "-t";
28012870Speter 					asargs[asargx++] = tmpdir;
28112870Speter 				}
28230092Smckusick #			endif vax || tahoe
2831211Speter 			asargs[asargx++] = argp;
2841211Speter 			asargs[asargx++] = "-o";
2851211Speter 			tfile[1] = setsuf(argp, 'o');
2861211Speter 			asargs[asargx++] = tfile[1];
2871211Speter 			asargs[asargx] = 0;
2881211Speter 			if (dosys(as, asargs, 0, 0))
2891211Speter 				continue;
2901211Speter 			tfile[1] = 0;
2911211Speter 			continue;
2921211Speter 		}
293621Sbill 		if (suffix(argp) != 'p')
294621Sbill 			continue;
295621Sbill 		tfile[0] = tname[0];
296621Sbill 		pc0args[2] = tfile[0];
297621Sbill 		pc0argx = savargx;
298654Sbill 		if (pflag)
299654Sbill 			pc0args[pc0argx++] = "-p";
30012966Smckusick 		if (Jflag)
30112966Smckusick 			pc0args[pc0argx++] = "-J";
302621Sbill 		pc0args[pc0argx++] = argp;
303621Sbill 		pc0args[pc0argx] = 0;
304621Sbill 		if (dosys(pc0, pc0args, 0, 0))
305621Sbill 			continue;
306621Sbill 		pc1args[1] = tfile[0];
307654Sbill 		tfile[1] = tname[1];
308621Sbill 		if (dosys(pc1, pc1args, 0, tfile[1]))
309621Sbill 			continue;
310621Sbill 		unlink(tfile[0]);
3112340Smckusic 		tfile[0] = tname[0];
3122340Smckusic 		if (Oflag) {
3132340Smckusic 			if (dosys(c2, c2args, tfile[1], tfile[0]))
3142340Smckusic 				continue;
3152340Smckusic 			unlink(tfile[1]);
3162340Smckusic 			tfile[1] = tfile[0];
3172340Smckusic 			tfile[0] = tname[1];
3182340Smckusic 		}
3192340Smckusic 		if (Sflag)
320654Sbill 			tfile[0] = setsuf(argp, 's');
321621Sbill 		if (dosys(pc2, pc2args, tfile[1], tfile[0]))
322621Sbill 			continue;
323621Sbill 		unlink(tfile[1]);
324621Sbill 		tfile[1] = 0;
325654Sbill 		if (Sflag) {
326654Sbill 			tfile[0] = 0;
327621Sbill 			continue;
328654Sbill 		}
329908Sbill 		asargx = 1;
330908Sbill 		if (Jflag)
331908Sbill 			asargs[asargx++] = "-J";
33230092Smckusick #		if defined(vax) || defined(tahoe)
33312870Speter 			if (tflag) {
33412870Speter 				asargs[asargx++] = "-t";
33512870Speter 				asargs[asargx++] = tmpdir;
33612870Speter 			}
33730092Smckusick #		endif vax || tahoe
338908Sbill 		asargs[asargx++] = tfile[0];
339908Sbill 		asargs[asargx++] = "-o";
340621Sbill 		tfile[1] = setsuf(argp, 'o');
341908Sbill 		asargs[asargx++] = tfile[1];
342908Sbill 		asargs[asargx] = 0;
343621Sbill 		if (dosys(as, asargs, 0, 0))
344621Sbill 			continue;
345621Sbill 		tfile[1] = 0;
346621Sbill 		remove();
347621Sbill 	}
348621Sbill 	if (errs || cflag || Sflag)
349621Sbill 		done();
3507596Smckusick /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
351621Sbill 	pc3args[0] = "pc3";
3527596Smckusick 	if (wflag)
3537596Smckusick 		pc3args[pc3argx++] = "-w";
3547596Smckusick 	pc3args[pc3argx++] = "/usr/lib/pcexterns.o";
355621Sbill 	for (i = 0; i < argc; i++) {
356621Sbill 		argp = argv[i];
357621Sbill 		if (!strcmp(argp, "-o"))
358621Sbill 			i++;
359621Sbill 		if (argp[0] == '-')
360621Sbill 			continue;
361621Sbill 		switch (getsuf(argp)) {
362621Sbill 
363621Sbill 		case 'o':
364621Sbill 			pc3args[pc3argx++] = argp;
365621Sbill 			nxo++;
366621Sbill 			continue;
3671211Speter 		case 's':
368621Sbill 		case 'p':
369621Sbill 			onepso = pc3args[pc3argx++] =
370621Sbill 			    savestr(setsuf(argp, 'o'));
371621Sbill 			np++;
372621Sbill 			continue;
373621Sbill 		}
374621Sbill 	}
375621Sbill 	pc3args[pc3argx] = 0;
3767596Smckusick 	if (dosys(pc3, pc3args, 0, 0) > 1)
377621Sbill 		done();
37810672Speter 	errs = 0;
379908Sbill /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
380621Sbill 	ldargs[0] = "ld";
381621Sbill 	ldargs[1] = "-X";
382654Sbill 	ldargs[2] = crt0;
383621Sbill 	for (i = 0; i < argc; i++) {
384621Sbill 		argp = argv[i];
385621Sbill 		if (argp[0] != '-') {
386621Sbill 			switch (getsuf(argp)) {
387621Sbill 
388621Sbill 			case 'p':
3891211Speter 			case 's':
390621Sbill 				ldargs[ldargx] = savestr(setsuf(argp, 'o'));
391621Sbill 				break;
392621Sbill 			default:
393621Sbill 				ldargs[ldargx] = argp;
394621Sbill 				break;
395621Sbill 			}
396621Sbill 			if (getsuf(ldargs[ldargx]) == 'o')
397621Sbill 			for (j = 0; j < ldargx; j++)
398621Sbill 				if (!strcmp(ldargs[j], ldargs[ldargx]))
399621Sbill 					goto duplicate;
400621Sbill 			ldargx++;
401621Sbill duplicate:
402621Sbill 			continue;
403621Sbill 		}
404621Sbill 		switch (argp[1]) {
405621Sbill 
406621Sbill 		case 'i':
407621Sbill 			while (i+1 < argc && argv[i+1][0] != '-' &&
408621Sbill 			    getsuf(argv[i+1]) != 'p')
409621Sbill 				i++;
410621Sbill 			continue;
411621Sbill 		case 'd':
412621Sbill 			if (argp[2] == 0)
413621Sbill 				continue;
414621Sbill 			ldargs[ldargx++] = argp;
415621Sbill 			continue;
416621Sbill 		case 'o':
417621Sbill 			ldargs[ldargx++] = argp;
418621Sbill 			i++;
419621Sbill 			ldargs[ldargx++] = argv[i];
420621Sbill 			continue;
421621Sbill 		case 'l':
422621Sbill 			if (argp[2])
423621Sbill 				ldargs[ldargx++] = argp;
424621Sbill 			continue;
42512870Speter 		case 't':
42612870Speter 			i++;
42712870Speter 			continue;
428621Sbill 		case 'c':
429621Sbill 		case 'g':
430621Sbill 		case 'w':
431621Sbill 		case 'p':
432621Sbill 		case 'S':
433908Sbill 		case 'J':
434621Sbill 		case 'T':
435621Sbill 		case 'O':
436621Sbill 		case 'C':
437621Sbill 		case 'b':
438621Sbill 		case 's':
439621Sbill 		case 'z':
440621Sbill 			continue;
441621Sbill 		default:
442621Sbill 			ldargs[ldargx++] = argp;
443621Sbill 			continue;
444621Sbill 		}
445621Sbill 	}
446621Sbill 	ldargs[ldargx++] = lpc;
447621Sbill 	if (gflag)
448621Sbill 		ldargs[ldargx++] = "-lg";
4495054Smckusic 	if (pflag) {
4505054Smckusic 		ldargs[ldargx++] = "-lm_p";
4515054Smckusic 		ldargs[ldargx++] = "-lc_p";
4525054Smckusic 	} else {
4535054Smckusic 		ldargs[ldargx++] = "-lm";
4545054Smckusic 		ldargs[ldargx++] = "-lc";
4555054Smckusic 	}
456621Sbill 	ldargs[ldargx] = 0;
457621Sbill 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
458621Sbill 		unlink(onepso);
459621Sbill 	done();
460621Sbill }
461621Sbill 
462621Sbill dosys(cmd, argv, in, out)
463621Sbill 	char *cmd, **argv, *in, *out;
464621Sbill {
465621Sbill 	union wait status;
466621Sbill 	int pid;
467621Sbill 
468621Sbill 	if (debug) {
469621Sbill 		int i;
470621Sbill 		printf("%s:", cmd);
471621Sbill 		for (i = 0; argv[i]; i++)
472621Sbill 			printf(" %s", argv[i]);
473621Sbill 		if (in)
474621Sbill 			printf(" <%s", in);
475621Sbill 		if (out)
476621Sbill 			printf(" >%s", out);
477621Sbill 		printf("\n");
478621Sbill 	}
47915776Saoki 	/*
48015776Saoki 	 * warning: vfork doesn't work here, because the call to signal()
48115776Saoki 	 * done by the child process destroys the parent's SIGINT handler.
48215776Saoki 	 */
48315776Saoki 	pid = fork();
484621Sbill 	if (pid < 0) {
485621Sbill 		fprintf(stderr, "pc: No more processes\n");
486621Sbill 		done();
487621Sbill 	}
488621Sbill 	if (pid == 0) {
489621Sbill 		if (in) {
490621Sbill 			close(0);
491621Sbill 			if (open(in, 0) != 0) {
492621Sbill 				perror(in);
493621Sbill 				exit(1);
494621Sbill 			}
495621Sbill 		}
496621Sbill 		if (out) {
497621Sbill 			close(1);
498621Sbill 			unlink(out);
499621Sbill 			if (creat(out, 0666) != 1) {
500621Sbill 				perror(out);
501621Sbill 				exit(1);
502621Sbill 			}
503621Sbill 		}
504621Sbill 		signal(SIGINT, SIG_DFL);
505621Sbill 		execv(cmd, argv);
506621Sbill 		perror(cmd);
507621Sbill 		exit(1);
508621Sbill 	}
509621Sbill 	while (wait(&status) != pid)
510621Sbill 		;
511621Sbill 	if (WIFSIGNALED(status)) {
5127766Smckusick 		if (status.w_termsig != SIGINT) {
5137766Smckusick 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
5147766Smckusick 			if (status.w_coredump)
5157766Smckusick 				fprintf(stderr, " (core dumped)");
5167766Smckusick 			fprintf(stderr, "\n");
5177766Smckusick 		}
518621Sbill 		errs = 100;
519621Sbill 		done();
520621Sbill 		/*NOTREACHED*/
521621Sbill 	}
522621Sbill 	if (status.w_retcode) {
523621Sbill 		errs = 1;
524621Sbill 		remove();
525621Sbill 	}
526621Sbill 	return (status.w_retcode);
527621Sbill }
528621Sbill 
529621Sbill done()
530621Sbill {
531621Sbill 
532621Sbill 	remove();
533621Sbill 	exit(errs);
534621Sbill }
535621Sbill 
536621Sbill remove()
537621Sbill {
538621Sbill 
539621Sbill 	if (tfile[0])
540621Sbill 		unlink(tfile[0]);
541621Sbill 	if (tfile[1])
542621Sbill 		unlink(tfile[1]);
543621Sbill }
544621Sbill 
545621Sbill onintr()
546621Sbill {
547621Sbill 
548621Sbill 	errs = 1;
549621Sbill 	done();
550621Sbill }
551621Sbill 
552621Sbill getsuf(cp)
553621Sbill 	char *cp;
554621Sbill {
555621Sbill 
556621Sbill 	if (*cp == 0)
557621Sbill 		return;
558621Sbill 	while (cp[1])
559621Sbill 		cp++;
560621Sbill 	if (cp[-1] != '.')
561621Sbill 		return (0);
562621Sbill 	return (*cp);
563621Sbill }
564621Sbill 
565621Sbill char *
566654Sbill setsuf(as, ch)
567654Sbill 	char *as;
568621Sbill {
569654Sbill 	register char *s, *s1;
570621Sbill 
571654Sbill 	s = s1 = savestr(as);
572654Sbill 	while (*s)
573654Sbill 		if (*s++ == '/')
574654Sbill 			s1 = s;
575654Sbill 	s[-1] = ch;
576654Sbill 	return (s1);
577621Sbill }
578621Sbill 
579621Sbill #define	NSAVETAB	512
580621Sbill char	*savetab;
581621Sbill int	saveleft;
582621Sbill 
583621Sbill char *
584621Sbill savestr(cp)
585621Sbill 	register char *cp;
586621Sbill {
587621Sbill 	register int len;
588621Sbill 
589621Sbill 	len = strlen(cp) + 1;
590621Sbill 	if (len > saveleft) {
591621Sbill 		saveleft = NSAVETAB;
592621Sbill 		if (len > saveleft)
593621Sbill 			saveleft = len;
594621Sbill 		savetab = (char *)malloc(saveleft);
595621Sbill 		if (savetab == 0) {
596621Sbill 			fprintf(stderr, "ran out of memory (savestr)\n");
597621Sbill 			exit(1);
598621Sbill 		}
599621Sbill 	}
600621Sbill 	strncpy(savetab, cp, len);
601621Sbill 	cp = savetab;
602621Sbill 	savetab += len;
603621Sbill 	return (cp);
604621Sbill }
605621Sbill 
606621Sbill suffix(cp)
607621Sbill 	char *cp;
608621Sbill {
609621Sbill 
610621Sbill 	if (cp[0] == 0 || cp[1] == 0)
611621Sbill 		return (0);
612621Sbill 	while (cp[1])
613621Sbill 		cp++;
614621Sbill 	if (cp[-1] == '.')
615621Sbill 		return (*cp);
616621Sbill 	return (0);
617621Sbill }
618