diff options
Diffstat (limited to 'lcc/etc/lcc.c')
| -rwxr-xr-x | lcc/etc/lcc.c | 1586 | 
1 files changed, 793 insertions, 793 deletions
| diff --git a/lcc/etc/lcc.c b/lcc/etc/lcc.c index c70abbb..a52119b 100755 --- a/lcc/etc/lcc.c +++ b/lcc/etc/lcc.c @@ -1,793 +1,793 @@ -/*
 - * lcc [ option ]... [ file | -llib ]...
 - * front end for the ANSI C compiler
 - */
 -static char rcsid[] = "Id: dummy rcsid";
 -
 -#include <stdio.h>
 -#include <stdarg.h>
 -#include <stdlib.h>
 -#include <string.h>
 -#include <assert.h>
 -#include <ctype.h>
 -#include <signal.h>
 -
 -#ifndef TEMPDIR
 -#define TEMPDIR "/tmp"
 -#endif
 -
 -typedef struct list *List;
 -struct list {		/* circular list nodes: */
 -	char *str;		/* option or file name */
 -	List link;		/* next list element */
 -};
 -
 -static void *alloc(int);
 -static List append(char *,List);
 -extern char *basepath(char *);
 -static int callsys(char *[]);
 -extern char *concat(char *, char *);
 -static int compile(char *, char *);
 -static void compose(char *[], List, List, List);
 -static void error(char *, char *);
 -static char *exists(char *);
 -static char *first(char *);
 -static int filename(char *, char *);
 -static List find(char *, List);
 -static void help(void);
 -static void initinputs(void);
 -static void interrupt(int);
 -static void opt(char *);
 -static List path2list(const char *);
 -extern int main(int, char *[]);
 -extern char *replace(const char *, int, int);
 -static void rm(List);
 -extern char *strsave(const char *);
 -extern char *stringf(const char *, ...);
 -extern int suffix(char *, char *[], int);
 -extern char *tempname(char *);
 -
 -extern int access(char *, int);
 -extern int getpid(void);
 -
 -extern char *cpp[], *include[], *com[], *as[],*ld[], inputs[], *suffixes[];
 -extern int option(char *);
 -
 -static int errcnt;		/* number of errors */
 -static int Eflag;		/* -E specified */
 -static int Sflag;		/* -S specified */
 -static int cflag;		/* -c specified */
 -static int verbose;		/* incremented for each -v */
 -static List llist[2];		/* loader files, flags */
 -static List alist;		/* assembler flags */
 -static List clist;		/* compiler flags */
 -static List plist;		/* preprocessor flags */
 -static List ilist;		/* list of additional includes from LCCINPUTS */
 -static List rmlist;		/* list of files to remove */
 -static char *outfile;		/* ld output file or -[cS] object file */
 -static int ac;			/* argument count */
 -static char **av;		/* argument vector */
 -char *tempdir = TEMPDIR;	/* directory for temporary files */
 -static char *progname;
 -static List lccinputs;		/* list of input directories */
 -
 -main(int argc, char *argv[]) {
 -	int i, j, nf;
 -	
 -	progname = argv[0];
 -	ac = argc + 50;
 -	av = alloc(ac*sizeof(char *));
 -	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 -		signal(SIGINT, interrupt);
 -	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
 -		signal(SIGTERM, interrupt);
 -#ifdef SIGHUP
 -	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 -		signal(SIGHUP, interrupt);
 -#endif
 -	if (getenv("TMP"))
 -		tempdir = getenv("TMP");
 -	else if (getenv("TEMP"))
 -		tempdir = getenv("TEMP");
 -	else if (getenv("TMPDIR"))
 -		tempdir = getenv("TMPDIR");
 -	assert(tempdir);
 -	i = strlen(tempdir);
 -	for (; i > 0 && tempdir[i-1] == '/' || tempdir[i-1] == '\\'; i--)
 -		tempdir[i-1] = '\0';
 -	if (argc <= 1) {
 -		help();
 -		exit(0);
 -	}
 -	plist = append("-D__LCC__", 0);
 -	initinputs();
 -	if (getenv("LCCDIR"))
 -		option(stringf("-lccdir=%s", getenv("LCCDIR")));
 -	for (nf = 0, i = j = 1; i < argc; i++) {
 -		if (strcmp(argv[i], "-o") == 0) {
 -			if (++i < argc) {
 -				if (suffix(argv[i], suffixes, 2) >= 0) {
 -					error("-o would overwrite %s", argv[i]);
 -					exit(8);
 -				}
 -				outfile = argv[i];
 -				continue;
 -			} else {
 -				error("unrecognized option `%s'", argv[i-1]);
 -				exit(8);
 -			}
 -		} else if (strcmp(argv[i], "-target") == 0) {
 -			if (argv[i+1] && *argv[i+1] != '-')
 -				i++;
 -			continue;
 -		} else if (*argv[i] == '-' && argv[i][1] != 'l') {
 -			opt(argv[i]);
 -			continue;
 -		} else if (*argv[i] != '-' && suffix(argv[i], suffixes, 3) >= 0)
 -			nf++;
 -		argv[j++] = argv[i];
 -	}
 -	if ((cflag || Sflag) && outfile && nf != 1) {
 -		fprintf(stderr, "%s: -o %s ignored\n", progname, outfile);
 -		outfile = 0;
 -	}
 -	argv[j] = 0;
 -	for (i = 0; include[i]; i++)
 -		plist = append(include[i], plist);
 -	if (ilist) {
 -		List b = ilist;
 -		do {
 -			b = b->link;
 -			plist = append(b->str, plist);
 -		} while (b != ilist);
 -	}
 -	ilist = 0;
 -	for (i = 1; argv[i]; i++)
 -		if (*argv[i] == '-')
 -			opt(argv[i]);
 -		else {
 -			char *name = exists(argv[i]);
 -			if (name) {
 -				if (strcmp(name, argv[i]) != 0
 -				|| nf > 1 && suffix(name, suffixes, 3) >= 0)
 -					fprintf(stderr, "%s:\n", name);
 -				filename(name, 0);
 -			} else
 -				error("can't find `%s'", argv[i]);
 -		}
 -	if (errcnt == 0 && !Eflag && !Sflag && !cflag && llist[1]) {
 -		compose(ld, llist[0], llist[1],
 -			append(outfile ? outfile : concat("a", first(suffixes[4])), 0));
 -		if (callsys(av))
 -			errcnt++;
 -	}
 -	rm(rmlist);	
 -	return errcnt ? EXIT_FAILURE : EXIT_SUCCESS;
 -}
 -
 -/* alloc - allocate n bytes or die */
 -static void *alloc(int n) {
 -	static char *avail, *limit;
 -	
 -	n = (n + sizeof(char *) - 1)&~(sizeof(char *) - 1);
 -	if (n >= limit - avail) {
 -		avail = malloc(n + 4*1024);
 -		assert(avail);
 -		limit = avail + n + 4*1024;
 -	}
 -	avail += n;
 -	return avail - n;
 -}
 -
 -/* append - append a node with string str onto list, return new list */	
 -static List append(char *str, List list) {
 -	List p = alloc(sizeof *p);
 -
 -	p->str = str;
 -	if (list) {
 -		p->link = list->link;
 -		list->link = p;
 -	} else
 -		p->link = p;
 -	return p;
 -}
 -
 -/* basepath - return base name for name, e.g. /usr/drh/foo.c => foo */
 -char *basepath(char *name) {
 -	char *s, *b, *t = 0;
 -
 -	for (b = s = name; *s; s++)
 -		if (*s == '/' || *s == '\\') {
 -			b = s + 1;
 -			t = 0;
 -		} else if (*s == '.')
 -			t = s;
 -	s = strsave(b);
 -	if (t)
 -		s[t-b] = 0;
 -	return s;
 -}
 -
 -#ifdef WIN32
 -#include <process.h>
 -#else
 -#define _P_WAIT 0
 -extern int fork(void);
 -extern int wait(int *);
 -extern void execv(const char *, char *[]);
 -
 -static int _spawnvp(int mode, const char *cmdname, char *argv[]) {
 -	int pid, n, status;
 -
 -	switch (pid = fork()) {
 -	case -1:
 -		fprintf(stderr, "%s: no more processes\n", progname);
 -		return 100;
 -	case 0:
 -		// TTimo removing hardcoded paths, searching in $PATH
 -		execvp(cmdname, argv);
 -		fprintf(stderr, "%s: ", progname);
 -		perror(cmdname);
 -		fflush(stdout);
 -		exit(100);
 -	}
 -	while ((n = wait(&status)) != pid && n != -1)
 -		;
 -	if (n == -1)
 -		status = -1;
 -	if (status&0377) {
 -		fprintf(stderr, "%s: fatal error in %s\n", progname, cmdname);
 -		status |= 0400;
 -	}
 -	return (status>>8)&0377;
 -}
 -#endif
 -
 -/* callsys - execute the command described by av[0...], return status */
 -static int callsys(char **av) {
 -	int i, status = 0;
 -	static char **argv;
 -	static int argc;
 -
 -	for (i = 0; av[i] != NULL; i++)
 -		;
 -	if (i + 1 > argc) {
 -		argc = i + 1;
 -		if (argv == NULL)
 -			argv = malloc(argc*sizeof *argv);
 -		else
 -			argv = realloc(argv, argc*sizeof *argv);
 -		assert(argv);
 -	}
 -	for (i = 0; status == 0 && av[i] != NULL; ) {
 -		int j = 0;
 -		char *s;
 -		for ( ; av[i] != NULL && (s = strchr(av[i], '\n')) == NULL; i++)
 -			argv[j++] = av[i];
 -		if (s != NULL) {
 -			if (s > av[i])
 -				argv[j++] = stringf("%.*s", s - av[i], av[i]);
 -			if (s[1] != '\0')
 -				av[i] = s + 1;
 -			else
 -				i++;
 -		}
 -		argv[j] = NULL;
 -		if (verbose > 0) {
 -			int k;
 -			fprintf(stderr, "%s", argv[0]);
 -			for (k = 1; argv[k] != NULL; k++)
 -				fprintf(stderr, " %s", argv[k]);
 -			fprintf(stderr, "\n");
 -		}
 -		if (verbose < 2)
 -			status = _spawnvp(_P_WAIT, argv[0], argv);
 -		if (status == -1) {
 -			fprintf(stderr, "%s: ", progname);
 -			perror(argv[0]);
 -		}
 -	}
 -	return status;
 -}
 -
 -/* concat - return concatenation of strings s1 and s2 */
 -char *concat(char *s1, char *s2) {
 -	int n = strlen(s1);
 -	char *s = alloc(n + strlen(s2) + 1);
 -
 -	strcpy(s, s1);
 -	strcpy(s + n, s2);
 -	return s;
 -}
 -
 -/* compile - compile src into dst, return status */
 -static int compile(char *src, char *dst) {
 -	compose(com, clist, append(src, 0), append(dst, 0));
 -	return callsys(av);
 -}
 -
 -/* compose - compose cmd into av substituting a, b, c for $1, $2, $3, resp. */
 -static void compose(char *cmd[], List a, List b, List c) {
 -	int i, j;
 -	List lists[3];
 -
 -	lists[0] = a;
 -	lists[1] = b;
 -	lists[2] = c;
 -	for (i = j = 0; cmd[i]; i++) {
 -		char *s = strchr(cmd[i], '$');
 -		if (s && isdigit(s[1])) {
 -			int k = s[1] - '0';
 -			assert(k >=1 && k <= 3);
 -			if (b = lists[k-1]) {
 -				b = b->link;
 -				av[j] = alloc(strlen(cmd[i]) + strlen(b->str) - 1);
 -				strncpy(av[j], cmd[i], s - cmd[i]);
 -				av[j][s-cmd[i]] = '\0';
 -				strcat(av[j], b->str);
 -				strcat(av[j++], s + 2);
 -				while (b != lists[k-1]) {
 -					b = b->link;
 -					assert(j < ac);
 -					av[j++] = b->str;
 -				};
 -			}
 -		} else if (*cmd[i]) {
 -			assert(j < ac);
 -			av[j++] = cmd[i];
 -		}
 -	}
 -	av[j] = NULL;
 -}
 -
 -/* error - issue error msg according to fmt, bump error count */
 -static void error(char *fmt, char *msg) {
 -	fprintf(stderr, "%s: ", progname);
 -	fprintf(stderr, fmt, msg);
 -	fprintf(stderr, "\n");
 -	errcnt++;
 -}
 -
 -/* exists - if `name' readable return its path name or return null */
 -static char *exists(char *name) {
 -	List b;
 -
 -	if ( (name[0] == '/' || name[0] == '\\' || name[2] == ':')
 -	&& access(name, 4) == 0)
 -		return name;
 -	if (!(name[0] == '/' || name[0] == '\\' || name[2] == ':')
 -	&& (b = lccinputs))		
 -		do {
 -			b = b->link;
 -			if (b->str[0]) {
 -				char buf[1024];
 -				sprintf(buf, "%s/%s", b->str, name);
 -				if (access(buf, 4) == 0)
 -					return strsave(buf);
 -			} else if (access(name, 4) == 0)
 -				return name;
 -		} while (b != lccinputs);
 -	if (verbose > 1)
 -		return name;
 -	return 0;
 -}
 -
 -/* first - return first component in semicolon separated list */
 -static char *first(char *list) {
 -	char *s = strchr(list, ';');
 -
 -	if (s) {
 -		char buf[1024];
 -		strncpy(buf, list, s-list);
 -		buf[s-list] = '\0';
 -		return strsave(buf);
 -	} else
 -		return list;
 -}
 -
 -/* filename - process file name argument `name', return status */
 -static int filename(char *name, char *base) {
 -	int status = 0;
 -	static char *stemp, *itemp;
 -
 -	if (base == 0)
 -		base = basepath(name);
 -	switch (suffix(name, suffixes, 4)) {
 -	case 0:	/* C source files */
 -		compose(cpp, plist, append(name, 0), 0);
 -		if (Eflag) {
 -			status = callsys(av);
 -			break;
 -		}
 -		if (itemp == NULL)
 -			itemp = tempname(first(suffixes[1]));
 -		compose(cpp, plist, append(name, 0), append(itemp, 0));
 -		status = callsys(av);
 -		if (status == 0)
 -			return filename(itemp, base);
 -		break;
 -	case 1:	/* preprocessed source files */
 -		if (Eflag)
 -			break;
 -		if (Sflag)
 -			status = compile(name, outfile ? outfile : concat(base, first(suffixes[2])));
 -		else if ((status = compile(name, stemp?stemp:(stemp=tempname(first(suffixes[2]))))) == 0)
 -			return filename(stemp, base);
 -		break;
 -	case 2:	/* assembly language files */
 -		if (Eflag)
 -			break;
 -		if (!Sflag) {
 -			char *ofile;
 -			if (cflag && outfile)
 -				ofile = outfile;
 -			else if (cflag)
 -				ofile = concat(base, first(suffixes[3]));
 -			else
 -				ofile = tempname(first(suffixes[3]));
 -			compose(as, alist, append(name, 0), append(ofile, 0));
 -			status = callsys(av);
 -			if (!find(ofile, llist[1]))
 -				llist[1] = append(ofile, llist[1]);
 -		}
 -		break;
 -	case 3:	/* object files */
 -		if (!find(name, llist[1]))
 -			llist[1] = append(name, llist[1]);
 -		break;
 -	default:
 -		if (Eflag) {
 -			compose(cpp, plist, append(name, 0), 0);
 -			status = callsys(av);
 -		}
 -		llist[1] = append(name, llist[1]);
 -		break;
 -	}
 -	if (status)
 -		errcnt++;
 -	return status;
 -}
 -
 -/* find - find 1st occurrence of str in list, return list node or 0 */
 -static List find(char *str, List list) {
 -	List b;
 -	
 -	if (b = list)
 -		do {
 -			if (strcmp(str, b->str) == 0)
 -				return b;
 -		} while ((b = b->link) != list);
 -	return 0;
 -}
 -
 -/* help - print help message */
 -static void help(void) {
 -	static char *msgs[] = {
 -"", " [ option | file ]...\n",
 -"	except for -l, options are processed left-to-right before files\n",
 -"	unrecognized options are taken to be linker options\n",
 -"-A	warn about nonANSI usage; 2nd -A warns more\n",
 -"-b	emit expression-level profiling code; see bprint(1)\n",
 -#ifdef sparc
 -"-Bstatic -Bdynamic	specify static or dynamic libraries\n",
 -#endif
 -"-Bdir/	use the compiler named `dir/rcc'\n",
 -"-c	compile only\n",
 -"-dn	set switch statement density to `n'\n",
 -"-Dname -Dname=def	define the preprocessor symbol `name'\n",
 -"-E	run only the preprocessor on the named C programs and unsuffixed files\n",
 -"-g	produce symbol table information for debuggers\n",
 -"-help or -?	print this message\n",
 -"-Idir	add `dir' to the beginning of the list of #include directories\n",	
 -"-lx	search library `x'\n",
 -"-N	do not search the standard directories for #include files\n",
 -"-n	emit code to check for dereferencing zero pointers\n",
 -"-O	is ignored\n",
 -"-o file	leave the output in `file'\n",
 -"-P	print ANSI-style declarations for globals\n",
 -"-p -pg	emit profiling code; see prof(1) and gprof(1)\n",
 -"-S	compile to assembly language\n",
 -#ifdef linux
 -"-static	specify static libraries (default is dynamic)\n",
 -#endif
 -"-t -tname	emit function tracing calls to printf or to `name'\n",
 -"-target name	is ignored\n",
 -"-tempdir=dir	place temporary files in `dir/'", "\n"
 -"-Uname	undefine the preprocessor symbol `name'\n",
 -"-v	show commands as they are executed; 2nd -v suppresses execution\n",
 -"-w	suppress warnings\n",
 -"-Woarg	specify system-specific `arg'\n",
 -"-W[pfal]arg	pass `arg' to the preprocessor, compiler, assembler, or linker\n",
 -	0 };
 -	int i;
 -	char *s;
 -
 -	msgs[0] = progname;
 -	for (i = 0; msgs[i]; i++) {
 -		fprintf(stderr, "%s", msgs[i]);
 -		if (strncmp("-tempdir", msgs[i], 8) == 0 && tempdir)
 -			fprintf(stderr, "; default=%s", tempdir);
 -	}
 -#define xx(v) if (s = getenv(#v)) fprintf(stderr, #v "=%s\n", s)
 -	xx(LCCINPUTS);
 -	xx(LCCDIR);
 -#ifdef WIN32
 -	xx(include);
 -	xx(lib);
 -#endif
 -#undef xx
 -}
 -
 -/* initinputs - if LCCINPUTS or include is defined, use them to initialize various lists */
 -static void initinputs(void) {
 -	char *s = getenv("LCCINPUTS");
 -	List list, b;
 -
 -	if (s == 0 || (s = inputs)[0] == 0)
 -		s = ".";
 -	if (s) {
 -		lccinputs = path2list(s);
 -		if (b = lccinputs)
 -			do {
 -				b = b->link;
 -				if (strcmp(b->str, ".") != 0) {
 -					ilist = append(concat("-I", b->str), ilist);
 -					if (strstr(com[1], "win32") == NULL)
 -						llist[0] = append(concat("-L", b->str), llist[0]);
 -				} else
 -					b->str = "";
 -			} while (b != lccinputs);
 -	}
 -#ifdef WIN32
 -	if (list = b = path2list(getenv("include")))
 -		do {
 -			b = b->link;
 -			ilist = append(stringf("-I\"%s\"", b->str), ilist);
 -		} while (b != list);
 -#endif
 -}
 -
 -/* interrupt - catch interrupt signals */
 -static void interrupt(int n) {
 -	rm(rmlist);
 -	exit(n = 100);
 -}
 -
 -/* opt - process option in arg */
 -static void opt(char *arg) {
 -	switch (arg[1]) {	/* multi-character options */
 -	case 'W':	/* -Wxarg */
 -		if (arg[2] && arg[3])
 -			switch (arg[2]) {
 -			case 'o':
 -				if (option(&arg[3]))
 -					return;
 -				break;
 -			case 'p':
 -				plist = append(&arg[3], plist);
 -				return;
 -			case 'f':
 -				if (strcmp(&arg[3], "-C") || option("-b")) {
 -					clist = append(&arg[3], clist);
 -					return;
 -				}
 -				break; /* and fall thru */
 -			case 'a':
 -				alist = append(&arg[3], alist);
 -				return;
 -			case 'l':
 -				llist[0] = append(&arg[3], llist[0]);
 -				return;
 -			}
 -		fprintf(stderr, "%s: %s ignored\n", progname, arg);
 -		return;
 -	case 'd':	/* -dn */
 -		arg[1] = 's';
 -		clist = append(arg, clist);
 -		return;
 -	case 't':	/* -t -tname -tempdir=dir */
 -		if (strncmp(arg, "-tempdir=", 9) == 0)
 -			tempdir = arg + 9;
 -		else
 -			clist = append(arg, clist);
 -		return;
 -	case 'p':	/* -p -pg */
 -		if (option(arg))
 -			clist = append(arg, clist);
 -		else
 -			fprintf(stderr, "%s: %s ignored\n", progname, arg);
 -		return;
 -	case 'D':	/* -Dname -Dname=def */
 -	case 'U':	/* -Uname */
 -	case 'I':	/* -Idir */
 -		plist = append(arg, plist);
 -		return;
 -	case 'B':	/* -Bdir -Bstatic -Bdynamic */
 -#ifdef sparc
 -		if (strcmp(arg, "-Bstatic") == 0 || strcmp(arg, "-Bdynamic") == 0)
 -			llist[1] = append(arg, llist[1]);
 -		else
 -#endif	
 -		{
 -		static char *path;
 -		if (path)
 -			error("-B overwrites earlier option", 0);
 -		path = arg + 2;
 -		if (strstr(com[1], "win32") != NULL)
 -			com[0] = concat(replace(path, '/', '\\'), concat("rcc", first(suffixes[4])));
 -		else
 -			com[0] = concat(path, "rcc");
 -		if (path[0] == 0)
 -			error("missing directory in -B option", 0);
 -		}
 -		return;
 -	case 'h':
 -		if (strcmp(arg, "-help") == 0) {
 -			static int printed = 0;
 -	case '?':
 -			if (!printed)
 -				help();
 -			printed = 1;
 -			return;
 -		}
 -#ifdef linux
 -	case 's':
 -		if (strcmp(arg,"-static") == 0) {
 -			if (!option(arg))
 -				fprintf(stderr, "%s: %s ignored\n", progname, arg);
 -			return;
 -		}
 -#endif         
 -	}
 -	if (arg[2] == 0)
 -		switch (arg[1]) {	/* single-character options */
 -		case 'S':
 -			Sflag++;
 -			return;
 -		case 'O':
 -			fprintf(stderr, "%s: %s ignored\n", progname, arg);
 -			return;
 -		case 'A': case 'n': case 'w': case 'P':
 -			clist = append(arg, clist);
 -			return;
 -		case 'g': case 'b':
 -			if (option(arg))
 -				clist = append(arg[1] == 'g' ? "-g2" : arg, clist);
 -			else
 -				fprintf(stderr, "%s: %s ignored\n", progname, arg);
 -			return;
 -		case 'G':
 -			if (option(arg)) {
 -				clist = append("-g3", clist);
 -				llist[0] = append("-N", llist[0]);
 -			} else
 -				fprintf(stderr, "%s: %s ignored\n", progname, arg);
 -			return;
 -		case 'E':
 -			Eflag++;
 -			return;
 -		case 'c':
 -			cflag++;
 -			return;
 -		case 'N':
 -			if (strcmp(basepath(cpp[0]), "gcc-cpp") == 0)
 -				plist = append("-nostdinc", plist);
 -			include[0] = 0;
 -			ilist = 0;
 -			return;
 -		case 'v':
 -			if (verbose++ == 0) {
 -				if (strcmp(basepath(cpp[0]), "gcc-cpp") == 0)
 -					plist = append(arg, plist);
 -				clist = append(arg, clist);
 -				fprintf(stderr, "%s %s\n", progname, rcsid);
 -			}
 -			return;
 -		}
 -	if (cflag || Sflag || Eflag)
 -		fprintf(stderr, "%s: %s ignored\n", progname, arg);
 -	else
 -		llist[1] = append(arg, llist[1]);
 -}
 -
 -/* path2list - convert a colon- or semicolon-separated list to a list */
 -static List path2list(const char *path) {
 -	List list = NULL;
 -	char sep = ':';
 -
 -	if (path == NULL)
 -		return NULL;
 -	if (strchr(path, ';'))
 -		sep = ';';
 -	while (*path) {
 -		char *p, buf[512];
 -		if (p = strchr(path, sep)) {
 -			assert(p - path < sizeof buf);
 -			strncpy(buf, path, p - path);
 -			buf[p-path] = '\0';
 -		} else {
 -			assert(strlen(path) < sizeof buf);
 -			strcpy(buf, path);
 -		}
 -		if (!find(buf, list))
 -			list = append(strsave(buf), list);
 -		if (p == 0)
 -			break;
 -		path = p + 1;
 -	}
 -	return list;
 -}
 -
 -/* replace - copy str, then replace occurrences of from with to, return the copy */
 -char *replace(const char *str, int from, int to) {
 -	char *s = strsave(str), *p = s;
 -
 -	for ( ; (p = strchr(p, from)) != NULL; p++)
 -		*p = to;
 -	return s;
 -}
 -
 -/* rm - remove files in list */
 -static void rm(List list) {
 -	if (list) {
 -		List b = list;
 -		if (verbose)
 -			fprintf(stderr, "rm");
 -		do {
 -			if (verbose)
 -				fprintf(stderr, " %s", b->str);
 -			if (verbose < 2)
 -				remove(b->str);
 -		} while ((b = b->link) != list);
 -		if (verbose)
 -			fprintf(stderr, "\n");
 -	}
 -}
 -
 -/* strsave - return a saved copy of string str */
 -char *strsave(const char *str) {
 -	return strcpy(alloc(strlen(str)+1), str);
 -}
 -
 -/* stringf - format and return a string */
 -char *stringf(const char *fmt, ...) {
 -	char buf[1024];
 -	va_list ap;
 -	int n;
 -
 -	va_start(ap, fmt);
 -	n = vsprintf(buf, fmt, ap);
 -	va_end(ap);
 -	return strsave(buf);
 -}
 -
 -/* suffix - if one of tails[0..n-1] holds a proper suffix of name, return its index */
 -int suffix(char *name, char *tails[], int n) {
 -	int i, len = strlen(name);
 -
 -	for (i = 0; i < n; i++) {
 -		char *s = tails[i], *t;
 -		for ( ; t = strchr(s, ';'); s = t + 1) {
 -			int m = t - s;
 -			if (len > m && strncmp(&name[len-m], s, m) == 0)
 -				return i;
 -		}
 -		if (*s) {
 -			int m = strlen(s);
 -			if (len > m && strncmp(&name[len-m], s, m) == 0)
 -				return i;
 -		}
 -	}
 -	return -1;
 -}
 -
 -/* tempname - generate a temporary file name in tempdir with given suffix */
 -char *tempname(char *suffix) {
 -	static int n;
 -	char *name = stringf("%s/lcc%d%d%s", tempdir, getpid(), n++, suffix);
 -
 -	if (strstr(com[1], "win32") != NULL)
 -		name = replace(name, '/', '\\');
 -	rmlist = append(name, rmlist);
 -	return name;
 -}
 +/* + * lcc [ option ]... [ file | -llib ]... + * front end for the ANSI C compiler + */ +static char rcsid[] = "Id: dummy rcsid"; + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> +#include <signal.h> + +#ifndef TEMPDIR +#define TEMPDIR "/tmp" +#endif + +typedef struct list *List; +struct list {		/* circular list nodes: */ +	char *str;		/* option or file name */ +	List link;		/* next list element */ +}; + +static void *alloc(int); +static List append(char *,List); +extern char *basepath(char *); +static int callsys(char *[]); +extern char *concat(char *, char *); +static int compile(char *, char *); +static void compose(char *[], List, List, List); +static void error(char *, char *); +static char *exists(char *); +static char *first(char *); +static int filename(char *, char *); +static List find(char *, List); +static void help(void); +static void initinputs(void); +static void interrupt(int); +static void opt(char *); +static List path2list(const char *); +extern int main(int, char *[]); +extern char *replace(const char *, int, int); +static void rm(List); +extern char *strsave(const char *); +extern char *stringf(const char *, ...); +extern int suffix(char *, char *[], int); +extern char *tempname(char *); + +extern int access(char *, int); +extern int getpid(void); + +extern char *cpp[], *include[], *com[], *as[],*ld[], inputs[], *suffixes[]; +extern int option(char *); + +static int errcnt;		/* number of errors */ +static int Eflag;		/* -E specified */ +static int Sflag;		/* -S specified */ +static int cflag;		/* -c specified */ +static int verbose;		/* incremented for each -v */ +static List llist[2];		/* loader files, flags */ +static List alist;		/* assembler flags */ +static List clist;		/* compiler flags */ +static List plist;		/* preprocessor flags */ +static List ilist;		/* list of additional includes from LCCINPUTS */ +static List rmlist;		/* list of files to remove */ +static char *outfile;		/* ld output file or -[cS] object file */ +static int ac;			/* argument count */ +static char **av;		/* argument vector */ +char *tempdir = TEMPDIR;	/* directory for temporary files */ +static char *progname; +static List lccinputs;		/* list of input directories */ + +main(int argc, char *argv[]) { +	int i, j, nf; +	 +	progname = argv[0]; +	ac = argc + 50; +	av = alloc(ac*sizeof(char *)); +	if (signal(SIGINT, SIG_IGN) != SIG_IGN) +		signal(SIGINT, interrupt); +	if (signal(SIGTERM, SIG_IGN) != SIG_IGN) +		signal(SIGTERM, interrupt); +#ifdef SIGHUP +	if (signal(SIGHUP, SIG_IGN) != SIG_IGN) +		signal(SIGHUP, interrupt); +#endif +	if (getenv("TMP")) +		tempdir = getenv("TMP"); +	else if (getenv("TEMP")) +		tempdir = getenv("TEMP"); +	else if (getenv("TMPDIR")) +		tempdir = getenv("TMPDIR"); +	assert(tempdir); +	i = strlen(tempdir); +	for (; i > 0 && tempdir[i-1] == '/' || tempdir[i-1] == '\\'; i--) +		tempdir[i-1] = '\0'; +	if (argc <= 1) { +		help(); +		exit(0); +	} +	plist = append("-D__LCC__", 0); +	initinputs(); +	if (getenv("LCCDIR")) +		option(stringf("-lccdir=%s", getenv("LCCDIR"))); +	for (nf = 0, i = j = 1; i < argc; i++) { +		if (strcmp(argv[i], "-o") == 0) { +			if (++i < argc) { +				if (suffix(argv[i], suffixes, 2) >= 0) { +					error("-o would overwrite %s", argv[i]); +					exit(8); +				} +				outfile = argv[i]; +				continue; +			} else { +				error("unrecognized option `%s'", argv[i-1]); +				exit(8); +			} +		} else if (strcmp(argv[i], "-target") == 0) { +			if (argv[i+1] && *argv[i+1] != '-') +				i++; +			continue; +		} else if (*argv[i] == '-' && argv[i][1] != 'l') { +			opt(argv[i]); +			continue; +		} else if (*argv[i] != '-' && suffix(argv[i], suffixes, 3) >= 0) +			nf++; +		argv[j++] = argv[i]; +	} +	if ((cflag || Sflag) && outfile && nf != 1) { +		fprintf(stderr, "%s: -o %s ignored\n", progname, outfile); +		outfile = 0; +	} +	argv[j] = 0; +	for (i = 0; include[i]; i++) +		plist = append(include[i], plist); +	if (ilist) { +		List b = ilist; +		do { +			b = b->link; +			plist = append(b->str, plist); +		} while (b != ilist); +	} +	ilist = 0; +	for (i = 1; argv[i]; i++) +		if (*argv[i] == '-') +			opt(argv[i]); +		else { +			char *name = exists(argv[i]); +			if (name) { +				if (strcmp(name, argv[i]) != 0 +				|| nf > 1 && suffix(name, suffixes, 3) >= 0) +					fprintf(stderr, "%s:\n", name); +				filename(name, 0); +			} else +				error("can't find `%s'", argv[i]); +		} +	if (errcnt == 0 && !Eflag && !Sflag && !cflag && llist[1]) { +		compose(ld, llist[0], llist[1], +			append(outfile ? outfile : concat("a", first(suffixes[4])), 0)); +		if (callsys(av)) +			errcnt++; +	} +	rm(rmlist);	 +	return errcnt ? EXIT_FAILURE : EXIT_SUCCESS; +} + +/* alloc - allocate n bytes or die */ +static void *alloc(int n) { +	static char *avail, *limit; +	 +	n = (n + sizeof(char *) - 1)&~(sizeof(char *) - 1); +	if (n >= limit - avail) { +		avail = malloc(n + 4*1024); +		assert(avail); +		limit = avail + n + 4*1024; +	} +	avail += n; +	return avail - n; +} + +/* append - append a node with string str onto list, return new list */	 +static List append(char *str, List list) { +	List p = alloc(sizeof *p); + +	p->str = str; +	if (list) { +		p->link = list->link; +		list->link = p; +	} else +		p->link = p; +	return p; +} + +/* basepath - return base name for name, e.g. /usr/drh/foo.c => foo */ +char *basepath(char *name) { +	char *s, *b, *t = 0; + +	for (b = s = name; *s; s++) +		if (*s == '/' || *s == '\\') { +			b = s + 1; +			t = 0; +		} else if (*s == '.') +			t = s; +	s = strsave(b); +	if (t) +		s[t-b] = 0; +	return s; +} + +#ifdef WIN32 +#include <process.h> +#else +#define _P_WAIT 0 +extern int fork(void); +extern int wait(int *); +extern void execv(const char *, char *[]); + +static int _spawnvp(int mode, const char *cmdname, char *argv[]) { +	int pid, n, status; + +	switch (pid = fork()) { +	case -1: +		fprintf(stderr, "%s: no more processes\n", progname); +		return 100; +	case 0: +		// TTimo removing hardcoded paths, searching in $PATH +		execvp(cmdname, argv); +		fprintf(stderr, "%s: ", progname); +		perror(cmdname); +		fflush(stdout); +		exit(100); +	} +	while ((n = wait(&status)) != pid && n != -1) +		; +	if (n == -1) +		status = -1; +	if (status&0377) { +		fprintf(stderr, "%s: fatal error in %s\n", progname, cmdname); +		status |= 0400; +	} +	return (status>>8)&0377; +} +#endif + +/* callsys - execute the command described by av[0...], return status */ +static int callsys(char **av) { +	int i, status = 0; +	static char **argv; +	static int argc; + +	for (i = 0; av[i] != NULL; i++) +		; +	if (i + 1 > argc) { +		argc = i + 1; +		if (argv == NULL) +			argv = malloc(argc*sizeof *argv); +		else +			argv = realloc(argv, argc*sizeof *argv); +		assert(argv); +	} +	for (i = 0; status == 0 && av[i] != NULL; ) { +		int j = 0; +		char *s; +		for ( ; av[i] != NULL && (s = strchr(av[i], '\n')) == NULL; i++) +			argv[j++] = av[i]; +		if (s != NULL) { +			if (s > av[i]) +				argv[j++] = stringf("%.*s", s - av[i], av[i]); +			if (s[1] != '\0') +				av[i] = s + 1; +			else +				i++; +		} +		argv[j] = NULL; +		if (verbose > 0) { +			int k; +			fprintf(stderr, "%s", argv[0]); +			for (k = 1; argv[k] != NULL; k++) +				fprintf(stderr, " %s", argv[k]); +			fprintf(stderr, "\n"); +		} +		if (verbose < 2) +			status = _spawnvp(_P_WAIT, argv[0], argv); +		if (status == -1) { +			fprintf(stderr, "%s: ", progname); +			perror(argv[0]); +		} +	} +	return status; +} + +/* concat - return concatenation of strings s1 and s2 */ +char *concat(char *s1, char *s2) { +	int n = strlen(s1); +	char *s = alloc(n + strlen(s2) + 1); + +	strcpy(s, s1); +	strcpy(s + n, s2); +	return s; +} + +/* compile - compile src into dst, return status */ +static int compile(char *src, char *dst) { +	compose(com, clist, append(src, 0), append(dst, 0)); +	return callsys(av); +} + +/* compose - compose cmd into av substituting a, b, c for $1, $2, $3, resp. */ +static void compose(char *cmd[], List a, List b, List c) { +	int i, j; +	List lists[3]; + +	lists[0] = a; +	lists[1] = b; +	lists[2] = c; +	for (i = j = 0; cmd[i]; i++) { +		char *s = strchr(cmd[i], '$'); +		if (s && isdigit(s[1])) { +			int k = s[1] - '0'; +			assert(k >=1 && k <= 3); +			if (b = lists[k-1]) { +				b = b->link; +				av[j] = alloc(strlen(cmd[i]) + strlen(b->str) - 1); +				strncpy(av[j], cmd[i], s - cmd[i]); +				av[j][s-cmd[i]] = '\0'; +				strcat(av[j], b->str); +				strcat(av[j++], s + 2); +				while (b != lists[k-1]) { +					b = b->link; +					assert(j < ac); +					av[j++] = b->str; +				}; +			} +		} else if (*cmd[i]) { +			assert(j < ac); +			av[j++] = cmd[i]; +		} +	} +	av[j] = NULL; +} + +/* error - issue error msg according to fmt, bump error count */ +static void error(char *fmt, char *msg) { +	fprintf(stderr, "%s: ", progname); +	fprintf(stderr, fmt, msg); +	fprintf(stderr, "\n"); +	errcnt++; +} + +/* exists - if `name' readable return its path name or return null */ +static char *exists(char *name) { +	List b; + +	if ( (name[0] == '/' || name[0] == '\\' || name[2] == ':') +	&& access(name, 4) == 0) +		return name; +	if (!(name[0] == '/' || name[0] == '\\' || name[2] == ':') +	&& (b = lccinputs))		 +		do { +			b = b->link; +			if (b->str[0]) { +				char buf[1024]; +				sprintf(buf, "%s/%s", b->str, name); +				if (access(buf, 4) == 0) +					return strsave(buf); +			} else if (access(name, 4) == 0) +				return name; +		} while (b != lccinputs); +	if (verbose > 1) +		return name; +	return 0; +} + +/* first - return first component in semicolon separated list */ +static char *first(char *list) { +	char *s = strchr(list, ';'); + +	if (s) { +		char buf[1024]; +		strncpy(buf, list, s-list); +		buf[s-list] = '\0'; +		return strsave(buf); +	} else +		return list; +} + +/* filename - process file name argument `name', return status */ +static int filename(char *name, char *base) { +	int status = 0; +	static char *stemp, *itemp; + +	if (base == 0) +		base = basepath(name); +	switch (suffix(name, suffixes, 4)) { +	case 0:	/* C source files */ +		compose(cpp, plist, append(name, 0), 0); +		if (Eflag) { +			status = callsys(av); +			break; +		} +		if (itemp == NULL) +			itemp = tempname(first(suffixes[1])); +		compose(cpp, plist, append(name, 0), append(itemp, 0)); +		status = callsys(av); +		if (status == 0) +			return filename(itemp, base); +		break; +	case 1:	/* preprocessed source files */ +		if (Eflag) +			break; +		if (Sflag) +			status = compile(name, outfile ? outfile : concat(base, first(suffixes[2]))); +		else if ((status = compile(name, stemp?stemp:(stemp=tempname(first(suffixes[2]))))) == 0) +			return filename(stemp, base); +		break; +	case 2:	/* assembly language files */ +		if (Eflag) +			break; +		if (!Sflag) { +			char *ofile; +			if (cflag && outfile) +				ofile = outfile; +			else if (cflag) +				ofile = concat(base, first(suffixes[3])); +			else +				ofile = tempname(first(suffixes[3])); +			compose(as, alist, append(name, 0), append(ofile, 0)); +			status = callsys(av); +			if (!find(ofile, llist[1])) +				llist[1] = append(ofile, llist[1]); +		} +		break; +	case 3:	/* object files */ +		if (!find(name, llist[1])) +			llist[1] = append(name, llist[1]); +		break; +	default: +		if (Eflag) { +			compose(cpp, plist, append(name, 0), 0); +			status = callsys(av); +		} +		llist[1] = append(name, llist[1]); +		break; +	} +	if (status) +		errcnt++; +	return status; +} + +/* find - find 1st occurrence of str in list, return list node or 0 */ +static List find(char *str, List list) { +	List b; +	 +	if (b = list) +		do { +			if (strcmp(str, b->str) == 0) +				return b; +		} while ((b = b->link) != list); +	return 0; +} + +/* help - print help message */ +static void help(void) { +	static char *msgs[] = { +"", " [ option | file ]...\n", +"	except for -l, options are processed left-to-right before files\n", +"	unrecognized options are taken to be linker options\n", +"-A	warn about nonANSI usage; 2nd -A warns more\n", +"-b	emit expression-level profiling code; see bprint(1)\n", +#ifdef sparc +"-Bstatic -Bdynamic	specify static or dynamic libraries\n", +#endif +"-Bdir/	use the compiler named `dir/rcc'\n", +"-c	compile only\n", +"-dn	set switch statement density to `n'\n", +"-Dname -Dname=def	define the preprocessor symbol `name'\n", +"-E	run only the preprocessor on the named C programs and unsuffixed files\n", +"-g	produce symbol table information for debuggers\n", +"-help or -?	print this message\n", +"-Idir	add `dir' to the beginning of the list of #include directories\n",	 +"-lx	search library `x'\n", +"-N	do not search the standard directories for #include files\n", +"-n	emit code to check for dereferencing zero pointers\n", +"-O	is ignored\n", +"-o file	leave the output in `file'\n", +"-P	print ANSI-style declarations for globals\n", +"-p -pg	emit profiling code; see prof(1) and gprof(1)\n", +"-S	compile to assembly language\n", +#ifdef linux +"-static	specify static libraries (default is dynamic)\n", +#endif +"-t -tname	emit function tracing calls to printf or to `name'\n", +"-target name	is ignored\n", +"-tempdir=dir	place temporary files in `dir/'", "\n" +"-Uname	undefine the preprocessor symbol `name'\n", +"-v	show commands as they are executed; 2nd -v suppresses execution\n", +"-w	suppress warnings\n", +"-Woarg	specify system-specific `arg'\n", +"-W[pfal]arg	pass `arg' to the preprocessor, compiler, assembler, or linker\n", +	0 }; +	int i; +	char *s; + +	msgs[0] = progname; +	for (i = 0; msgs[i]; i++) { +		fprintf(stderr, "%s", msgs[i]); +		if (strncmp("-tempdir", msgs[i], 8) == 0 && tempdir) +			fprintf(stderr, "; default=%s", tempdir); +	} +#define xx(v) if (s = getenv(#v)) fprintf(stderr, #v "=%s\n", s) +	xx(LCCINPUTS); +	xx(LCCDIR); +#ifdef WIN32 +	xx(include); +	xx(lib); +#endif +#undef xx +} + +/* initinputs - if LCCINPUTS or include is defined, use them to initialize various lists */ +static void initinputs(void) { +	char *s = getenv("LCCINPUTS"); +	List list, b; + +	if (s == 0 || (s = inputs)[0] == 0) +		s = "."; +	if (s) { +		lccinputs = path2list(s); +		if (b = lccinputs) +			do { +				b = b->link; +				if (strcmp(b->str, ".") != 0) { +					ilist = append(concat("-I", b->str), ilist); +					if (strstr(com[1], "win32") == NULL) +						llist[0] = append(concat("-L", b->str), llist[0]); +				} else +					b->str = ""; +			} while (b != lccinputs); +	} +#ifdef WIN32 +	if (list = b = path2list(getenv("include"))) +		do { +			b = b->link; +			ilist = append(stringf("-I\"%s\"", b->str), ilist); +		} while (b != list); +#endif +} + +/* interrupt - catch interrupt signals */ +static void interrupt(int n) { +	rm(rmlist); +	exit(n = 100); +} + +/* opt - process option in arg */ +static void opt(char *arg) { +	switch (arg[1]) {	/* multi-character options */ +	case 'W':	/* -Wxarg */ +		if (arg[2] && arg[3]) +			switch (arg[2]) { +			case 'o': +				if (option(&arg[3])) +					return; +				break; +			case 'p': +				plist = append(&arg[3], plist); +				return; +			case 'f': +				if (strcmp(&arg[3], "-C") || option("-b")) { +					clist = append(&arg[3], clist); +					return; +				} +				break; /* and fall thru */ +			case 'a': +				alist = append(&arg[3], alist); +				return; +			case 'l': +				llist[0] = append(&arg[3], llist[0]); +				return; +			} +		fprintf(stderr, "%s: %s ignored\n", progname, arg); +		return; +	case 'd':	/* -dn */ +		arg[1] = 's'; +		clist = append(arg, clist); +		return; +	case 't':	/* -t -tname -tempdir=dir */ +		if (strncmp(arg, "-tempdir=", 9) == 0) +			tempdir = arg + 9; +		else +			clist = append(arg, clist); +		return; +	case 'p':	/* -p -pg */ +		if (option(arg)) +			clist = append(arg, clist); +		else +			fprintf(stderr, "%s: %s ignored\n", progname, arg); +		return; +	case 'D':	/* -Dname -Dname=def */ +	case 'U':	/* -Uname */ +	case 'I':	/* -Idir */ +		plist = append(arg, plist); +		return; +	case 'B':	/* -Bdir -Bstatic -Bdynamic */ +#ifdef sparc +		if (strcmp(arg, "-Bstatic") == 0 || strcmp(arg, "-Bdynamic") == 0) +			llist[1] = append(arg, llist[1]); +		else +#endif	 +		{ +		static char *path; +		if (path) +			error("-B overwrites earlier option", 0); +		path = arg + 2; +		if (strstr(com[1], "win32") != NULL) +			com[0] = concat(replace(path, '/', '\\'), concat("rcc", first(suffixes[4]))); +		else +			com[0] = concat(path, "rcc"); +		if (path[0] == 0) +			error("missing directory in -B option", 0); +		} +		return; +	case 'h': +		if (strcmp(arg, "-help") == 0) { +			static int printed = 0; +	case '?': +			if (!printed) +				help(); +			printed = 1; +			return; +		} +#ifdef linux +	case 's': +		if (strcmp(arg,"-static") == 0) { +			if (!option(arg)) +				fprintf(stderr, "%s: %s ignored\n", progname, arg); +			return; +		} +#endif          +	} +	if (arg[2] == 0) +		switch (arg[1]) {	/* single-character options */ +		case 'S': +			Sflag++; +			return; +		case 'O': +			fprintf(stderr, "%s: %s ignored\n", progname, arg); +			return; +		case 'A': case 'n': case 'w': case 'P': +			clist = append(arg, clist); +			return; +		case 'g': case 'b': +			if (option(arg)) +				clist = append(arg[1] == 'g' ? "-g2" : arg, clist); +			else +				fprintf(stderr, "%s: %s ignored\n", progname, arg); +			return; +		case 'G': +			if (option(arg)) { +				clist = append("-g3", clist); +				llist[0] = append("-N", llist[0]); +			} else +				fprintf(stderr, "%s: %s ignored\n", progname, arg); +			return; +		case 'E': +			Eflag++; +			return; +		case 'c': +			cflag++; +			return; +		case 'N': +			if (strcmp(basepath(cpp[0]), "gcc-cpp") == 0) +				plist = append("-nostdinc", plist); +			include[0] = 0; +			ilist = 0; +			return; +		case 'v': +			if (verbose++ == 0) { +				if (strcmp(basepath(cpp[0]), "gcc-cpp") == 0) +					plist = append(arg, plist); +				clist = append(arg, clist); +				fprintf(stderr, "%s %s\n", progname, rcsid); +			} +			return; +		} +	if (cflag || Sflag || Eflag) +		fprintf(stderr, "%s: %s ignored\n", progname, arg); +	else +		llist[1] = append(arg, llist[1]); +} + +/* path2list - convert a colon- or semicolon-separated list to a list */ +static List path2list(const char *path) { +	List list = NULL; +	char sep = ':'; + +	if (path == NULL) +		return NULL; +	if (strchr(path, ';')) +		sep = ';'; +	while (*path) { +		char *p, buf[512]; +		if (p = strchr(path, sep)) { +			assert(p - path < sizeof buf); +			strncpy(buf, path, p - path); +			buf[p-path] = '\0'; +		} else { +			assert(strlen(path) < sizeof buf); +			strcpy(buf, path); +		} +		if (!find(buf, list)) +			list = append(strsave(buf), list); +		if (p == 0) +			break; +		path = p + 1; +	} +	return list; +} + +/* replace - copy str, then replace occurrences of from with to, return the copy */ +char *replace(const char *str, int from, int to) { +	char *s = strsave(str), *p = s; + +	for ( ; (p = strchr(p, from)) != NULL; p++) +		*p = to; +	return s; +} + +/* rm - remove files in list */ +static void rm(List list) { +	if (list) { +		List b = list; +		if (verbose) +			fprintf(stderr, "rm"); +		do { +			if (verbose) +				fprintf(stderr, " %s", b->str); +			if (verbose < 2) +				remove(b->str); +		} while ((b = b->link) != list); +		if (verbose) +			fprintf(stderr, "\n"); +	} +} + +/* strsave - return a saved copy of string str */ +char *strsave(const char *str) { +	return strcpy(alloc(strlen(str)+1), str); +} + +/* stringf - format and return a string */ +char *stringf(const char *fmt, ...) { +	char buf[1024]; +	va_list ap; +	int n; + +	va_start(ap, fmt); +	n = vsprintf(buf, fmt, ap); +	va_end(ap); +	return strsave(buf); +} + +/* suffix - if one of tails[0..n-1] holds a proper suffix of name, return its index */ +int suffix(char *name, char *tails[], int n) { +	int i, len = strlen(name); + +	for (i = 0; i < n; i++) { +		char *s = tails[i], *t; +		for ( ; t = strchr(s, ';'); s = t + 1) { +			int m = t - s; +			if (len > m && strncmp(&name[len-m], s, m) == 0) +				return i; +		} +		if (*s) { +			int m = strlen(s); +			if (len > m && strncmp(&name[len-m], s, m) == 0) +				return i; +		} +	} +	return -1; +} + +/* tempname - generate a temporary file name in tempdir with given suffix */ +char *tempname(char *suffix) { +	static int n; +	char *name = stringf("%s/lcc%d%d%s", tempdir, getpid(), n++, suffix); + +	if (strstr(com[1], "win32") != NULL) +		name = replace(name, '/', '\\'); +	rmlist = append(name, rmlist); +	return name; +} | 
