diff options
Diffstat (limited to 'lcc/etc')
| -rwxr-xr-x | lcc/etc/bprint.c | 475 | ||||
| -rwxr-xr-x | lcc/etc/gcc-solaris.c | 50 | ||||
| -rwxr-xr-x | lcc/etc/irix.c | 64 | ||||
| -rwxr-xr-x | lcc/etc/lcc.c | 793 | ||||
| -rwxr-xr-x | lcc/etc/linux.c | 74 | ||||
| -rwxr-xr-x | lcc/etc/ops.c | 190 | ||||
| -rwxr-xr-x | lcc/etc/osf.c | 53 | ||||
| -rwxr-xr-x | lcc/etc/solaris.c | 50 | ||||
| -rwxr-xr-x | lcc/etc/win32.c | 43 | 
9 files changed, 1792 insertions, 0 deletions
| diff --git a/lcc/etc/bprint.c b/lcc/etc/bprint.c new file mode 100755 index 0000000..856d40b --- /dev/null +++ b/lcc/etc/bprint.c @@ -0,0 +1,475 @@ +#include <assert.h>
 +#include <ctype.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +/* bprint [ -c | -Idir... | -f | -b | -n ] [ file... ]
 + * annotate listings of files with prof.out data
 + */
 +
 +
 +#define NDIRS (sizeof dirs/sizeof dirs[0] - 1)
 +#define NEW(p,a) ((p) = alloc(sizeof *(p)))
 +#define newarray(m,n,a) alloc((m)*(n))
 +#define NELEMS(a) ((int)(sizeof (a)/sizeof ((a)[0])))
 +
 +#define MAXTOKEN 64
 +
 +struct count {			/* count data: */
 +	int x, y;			/* source coordinate */
 +	int count;			/* associated execution count */
 +};
 +
 +char *progname;
 +int number;
 +char *dirs[20];
 +int fcount;
 +
 +struct file {			/* per-file prof.out data: */
 +	struct file *link;		/* link to next file */
 +	char *name;			/* file name */
 +	int size;			/* size of counts[] */
 +	int count;			/* counts[0..count-1] hold valid data */
 +	struct count *counts;		/* count data */
 +	struct func {			/* function data: */
 +		struct func *link;		/* link to next function */
 +		char *name;			/* function name */
 +		struct count count;		/* total number of calls */
 +		struct caller {		/* caller data: */
 +			struct caller *link;	/* link to next caller */
 +			char *name;		/* caller's name */
 +			char *file;		/* call site: file, x, y */
 +			int x, y;
 +			int count;		/* number of calls from this site */
 +		} *callers;
 +	} *funcs;			/* list of functions */
 +} *filelist;
 +FILE *fp;
 +
 +extern int process(char *);
 +extern int findfunc(char *, char *);
 +extern int findcount(char *, int, int);
 +
 +void *alloc(unsigned);
 +char *string(char *);
 +int process(char *);
 +void emitdata(char *);
 +void printfile(struct file *, int);
 +void printfuncs(struct file *, int);
 +
 +/* alloc - allocate n bytes or die */
 +void *alloc(unsigned n) {
 +	void *new = malloc(n);
 +
 +	assert(new);
 +	return new;
 +}
 +
 +/* emitdata - write prof.out data to file */
 +void emitdata(char *file) {
 +	FILE *fp;
 +
 +	if (fp = fopen(file, "w")) {
 +		struct file *p;
 +		for (p = filelist; p; p = p->link) {
 +			int i;
 +			struct func *q;
 +			struct caller *r;
 +			fprintf(fp, "1\n%s\n", p->name);
 +			for (i = 0, q = p->funcs; q; i++, q = q->link)
 +				if (r = q->callers)
 +					for (i--; r; r = r->link)
 +						i++;
 +			fprintf(fp, "%d\n", i);
 +			for (q = p->funcs; q; q = q->link)
 +				if (q->count.count == 0 || !q->callers)
 +					fprintf(fp, "%s 1 %d %d %d ? ? 0 0\n", q->name, q->count.x,
 +						q->count.y, q->count.count);
 +				else
 +					for (r = q->callers; r; r = r->link)
 +						fprintf(fp, "%s 1 %d %d %d %s %s %d %d\n", q->name, q->count.x,
 +							q->count.y, r->count, r->name, r->file, r->x, r->y);
 +			fprintf(fp, "%d\n", p->count);
 +			for (i = 0; i < p->count; i++)
 +				fprintf(fp, "1 %d %d %d\n", p->counts[i].x,
 +					p->counts[i].y, p->counts[i].count);
 +		}
 +		fclose(fp);
 +	} else
 +		fprintf(stderr, "%s: can't create `%s'\n", progname, file);
 +}
 +
 +/* openfile - open name for reading, searching -I directories */
 +FILE *openfile(char *name) {
 +	int i;
 +	FILE *fp;
 +
 +	if (*name != '/')	
 +		for (i = 0; dirs[i]; i++) {
 +			char buf[200];
 +			sprintf(buf, "%s/%s", dirs[i], name);
 +			if (fp = fopen(buf, "r"))
 +				return fp;
 +		}
 +	return fopen(name, "r");
 +}
 +
 +/* printfile - print annotated listing for p */
 +void printfile(struct file *p, int nf) {
 +	int lineno;
 +	FILE *fp;
 +	char *s, buf[512];
 +	struct count *u = p->counts, *r, *uend;
 +
 +	if (u == 0 || p->count <= 0)
 +		return;
 +	uend = &p->counts[p->count];
 +	if ((fp = openfile(p->name)) == NULL) {
 +		fprintf(stderr, "%s: can't open `%s'\n", progname, p->name);
 +		return;
 +	}
 +	if (nf)
 +		printf("%s%s:\n\n", nf == 1 ? "" : "\f", p->name);
 +	for (lineno = 1; fgets(buf, sizeof buf, fp); lineno++) {
 +		if (number)
 +			printf("%d\t", lineno);
 +		while (u < uend && u->y < lineno)
 +			u++;
 +		for (s = buf; *s; ) {
 +			char *t = s + 1;
 +			while (u < uend && u->y == lineno && u->x < s - buf)
 +				u++;
 +			if (isalnum(*s) || *s == '_')
 +				while (isalnum(*t) || *t == '_')
 +					t++;
 +			while (u < uend && u->y == lineno && u->x < t - buf) {
 +				printf("<%d>", u->count);
 +				for (r = u++; u < uend && u->x == r->x && u->y == r->y && u->count == r->count; u++)
 +					;
 +			}
 +			while (s < t)
 +				putchar(*s++);
 +		}
 +		if (*s)
 +			printf("%s", s);
 +	}
 +	fclose(fp);
 +}
 +
 +/* printfuncs - summarize data for functions in p */
 +void printfuncs(struct file *p, int nf) {
 +	struct func *q;
 +
 +	if (nf)
 +		printf("%s:\n", p->name);
 +	for (q = p->funcs; q; q = q->link)
 +		if (fcount <= 1 || q->count.count == 0 || !q->callers)
 +			printf("%d\t%s\n", q->count.count, q->name);
 +		else {
 +			struct caller *r;
 +			for (r = q->callers; r; r = r->link)
 +				printf("%d\t%s\tfrom %s\tin %s:%d.%d\n", r->count, q->name, r->name,
 +					r->file, r->y, r->x + 1);
 +		}
 +		
 +}
 +
 +/* string - save a copy of str, if necessary */
 +char *string(char *str) {
 +	static struct string { struct string *link; char str[1]; } *list;
 +	struct string *p;
 +
 +	for (p = list; p; p = p->link)
 +		if (strcmp(p->str, str) == 0)
 +			return p->str;
 +	p = (struct string *)alloc(strlen(str) + sizeof *p);
 +	strcpy(p->str, str);
 +	p->link = list;
 +	list = p;
 +	return p->str;
 +}
 +/* acaller - add caller and site (file,x,y) to callee's callers list */
 +static void acaller(char *caller, char *file, int x, int y, int count, struct func *callee) {
 +	struct caller *q;
 +
 +	assert(callee);
 +	for (q = callee->callers; q && (caller != q->name
 +		|| file != q->file || x != q->x || y != q->y); q = q->link)
 +		;
 +	if (!q) {
 +		struct caller **r;
 +		NEW(q, PERM);
 +		q->name = caller;
 +		q->file = file;
 +		q->x = x;
 +		q->y = y;
 +		q->count = 0;
 +		for (r = &callee->callers; *r && (strcmp(q->name, (*r)->name) > 0
 +			|| strcmp(q->file, (*r)->file) > 0 || q->y > (*r)->y || q->y > (*r)->y); r = &(*r)->link)
 +			;
 +		q->link = *r;
 +		*r = q;
 +	}
 +	q->count += count;
 +}
 +
 +/* compare - return <0, 0, >0 if a<b, a==b, a>b, resp. */
 +static int compare(struct count *a, struct count *b) {
 +	if (a->y == b->y)
 +		return a->x - b->x;
 +	return a->y - b->y;
 +}
 +
 +/* findfile - return file name's file list entry, or 0 */
 +static struct file *findfile(char *name) {
 +	struct file *p;
 +
 +	for (p = filelist; p; p = p->link)
 +		if (p->name == name)
 +			return p;
 +	return 0;
 +}
 +
 +/* afunction - add function name and its data to file's function list */
 +static struct func *afunction(char *name, char *file, int x, int y, int count) {
 +	struct file *p = findfile(file);
 +	struct func *q;
 +
 +	assert(p);
 +	for (q = p->funcs; q && name != q->name; q = q->link)
 +		;
 +	if (!q) {
 +		struct func **r;
 +		NEW(q, PERM);
 +		q->name = name;
 +		q->count.x = x;
 +		q->count.y = y;
 +		q->count.count = 0;
 +		q->callers = 0;
 +		for (r = &p->funcs; *r && compare(&q->count, &(*r)->count) > 0; r = &(*r)->link)
 +			;
 +		q->link = *r;
 +		*r = q;
 +	}
 +	q->count.count += count;
 +	return q;
 +}
 +
 +/* apoint - append execution point i to file's data */ 
 +static void apoint(int i, char *file, int x, int y, int count) {
 +	struct file *p = findfile(file);
 +
 +	assert(p);
 +	if (i >= p->size) {
 +		int j;
 +		if (p->size == 0) {
 +			p->size = i >= 200 ? 2*i : 200;
 +			p->counts = newarray(p->size, sizeof *p->counts, PERM);
 +		} else {
 +			struct count *new;
 +			p->size = 2*i;
 +			new = newarray(p->size, sizeof *new, PERM);
 +			for (j = 0; j < p->count; j++)
 +				new[j] = p->counts[j];
 +			p->counts = new;
 +		}
 +		for (j = p->count; j < p->size; j++) {
 +			static struct count z;
 +			p->counts[j] = z;
 +		}
 +	}
 +	p->counts[i].x = x;
 +	p->counts[i].y = y;
 +	p->counts[i].count += count;
 +	if (i >= p->count)
 +		p->count = i + 1;
 +}
 +
 +/* findcount - return count associated with (file,x,y) or -1 */
 +int findcount(char *file, int x, int y) {
 +	static struct file *cursor;
 +
 +	if (cursor == 0 || cursor->name != file)
 +		cursor = findfile(file);
 +	if (cursor) {
 +		int l, u;
 +		struct count *c = cursor->counts;
 +		for (l = 0, u = cursor->count - 1; l <= u; ) {
 +			int k = (l + u)/2;
 +			if (c[k].y > y || c[k].y == y && c[k].x > x)
 +				u = k - 1;
 +			else if (c[k].y < y || c[k].y == y && c[k].x < x)
 +				l = k + 1;
 +			else
 +				return c[k].count;
 +		}
 +	}
 +	return -1;
 +}
 +
 +/* findfunc - return count associated with function name in file or -1 */
 +int findfunc(char *name, char *file) {
 +	static struct file *cursor;
 +
 +	if (cursor == 0 || cursor->name != file)
 +		cursor = findfile(file);
 +	if (cursor) {
 +		struct func *p;
 +		for (p = cursor->funcs; p; p = p->link)
 +			if (p->name == name)
 +				return p->count.count;
 +	}
 +	return -1;
 +}
 +
 +/* getd - read a nonnegative number */
 +static int getd(void) {
 +	int c, n = 0;
 +
 +	while ((c = getc(fp)) != EOF && (c == ' ' || c == '\n' || c == '\t'))
 +		;
 +	if (c >= '0' && c <= '9') {
 +		do
 +			n = 10*n + (c - '0');
 +		while ((c = getc(fp)) >= '0' && c <= '9');
 +		return n;
 +	}
 +	return -1;
 +}
 +
 +/* getstr - read a string */
 +static char *getstr(void) {
 +	int c;
 +	char buf[MAXTOKEN], *s = buf;
 +
 +	while ((c = getc(fp)) != EOF && c != ' ' && c != '\n' && c != '\t')
 +		if (s - buf < (int)sizeof buf - 2)
 +			*s++ = c;
 +	*s = 0;
 +	return s == buf ? (char *)0 : string(buf);
 +}
 +
 +/* gather - read prof.out data from fd */
 +static int gather(void) {
 +	int i, nfiles, nfuncs, npoints;
 +	char *files[64];
 +
 +	if ((nfiles = getd()) < 0)
 +		return 0;
 +	assert(nfiles < NELEMS(files));
 +	for (i = 0; i < nfiles; i++) {
 +		if ((files[i] = getstr()) == 0)
 +			return -1;
 +		if (!findfile(files[i])) {
 +			struct file *new;
 +			NEW(new, PERM);
 +			new->name = files[i];
 +			new->size = new->count = 0;
 +			new->counts = 0;
 +			new->funcs = 0;
 +			new->link = filelist;
 +			filelist = new;
 +		}
 +	}
 +	if ((nfuncs = getd()) < 0)
 +		return -1;
 +	for (i = 0; i < nfuncs; i++) {
 +		struct func *q;
 +		char *name, *file;
 +		int f, x, y, count;
 +		if ((name = getstr()) == 0 || (f = getd()) <= 0
 +		|| (x = getd()) < 0 || (y = getd()) < 0 || (count = getd()) < 0)
 +			return -1;
 +		q = afunction(name, files[f-1], x, y, count);
 +		if ((name = getstr()) == 0 || (file = getstr()) == 0
 +		|| (x = getd()) < 0 || (y = getd()) < 0)
 +			return -1;
 +		if (*name != '?')
 +			acaller(name, file, x, y, count, q);
 +	}
 +	if ((npoints = getd()) < 0)
 +		return -1;
 +	for (i = 0; i < npoints; i++) {
 +		int f, x, y, count;
 +		if ((f = getd()) < 0 || (x = getd()) < 0 || (y = getd()) < 0
 +		|| (count = getd()) < 0)
 +			return -1;
 +		if (f)
 +			apoint(i, files[f-1], x, y, count);
 +	}
 +	return 1;
 +}
 +
 +/* process - read prof.out data from file */
 +int process(char *file) {
 +	int more;
 +
 +	if ((fp = fopen(file, "r")) != NULL) {
 +		struct file *p;
 +		while ((more = gather()) > 0)
 +			;
 +		fclose(fp);
 +		if (more < 0)
 +			return more;
 +		for (p = filelist; p; p = p->link)
 +			qsort(p->counts, p->count, sizeof *p->counts,
 +				(int (*)(const void *, const void *))
 +				compare);
 +		
 +		return 1;
 +	}
 +	return 0;
 +}
 +int main(int argc, char *argv[]) {
 +	int i;
 +	struct file *p;
 +	void (*f)(struct file *, int) = printfile;
 +
 +	progname = argv[0];
 +	if ((i = process("prof.out")) <= 0) {
 +		fprintf(stderr, "%s: can't %s `%s'\n", progname,
 +			i == 0 ? "open" : "interpret", "prof.out");
 +		exit(1);
 +	}
 +	for (i = 1; i < argc && *argv[i] == '-'; i++)
 +		if (strcmp(argv[i], "-c") == 0) {
 +			emitdata("prof.out"); 
 +			exit(0);
 +		} else if (strcmp(argv[i], "-b") == 0)
 +			f = printfile;
 +		else if (strcmp(argv[i], "-f") == 0) {
 +			fcount++;
 +			f = printfuncs;
 +		} else if (strcmp(argv[i], "-n") == 0)
 +			number++;
 +		else if (strncmp(argv[i], "-I", 2) == 0) {
 +			int j;
 +			for (j = 0; j < NDIRS && dirs[j]; j++)
 +				;
 +			if (j < NDIRS)
 +				dirs[j] = &argv[i][2];
 +			else
 +				fprintf(stderr, "%s: too many -I options\n", progname);
 +		} else {
 +			fprintf(stderr, "usage: %s [ -c | -b | -n | -f | -Idir... ] [ file... ]\n", progname);
 +			exit(1);
 +		}
 +	for (p = filelist; p; p = p->link)
 +		qsort(p->counts, p->count, sizeof *p->counts,
 +			(int (*)(const void *, const void *))compare);
 +	if (i < argc) {
 +		int nf = i < argc - 1 ? 1 : 0;
 +		for ( ; i < argc; i++, nf ? nf++ : 0)
 +			if (p = findfile(string(argv[i])))
 +				(*f)(p, nf);
 +			else
 +				fprintf(stderr, "%s: no data for `%s'\n", progname, argv[i]);
 +	} else {
 +		int nf = filelist && filelist->link ? 1 : 0;
 +		for (p = filelist; p; p = p->link, nf ? nf++ : 0)
 +			(*f)(p, nf);
 +	}
 +	return 0;
 +}
 +
 diff --git a/lcc/etc/gcc-solaris.c b/lcc/etc/gcc-solaris.c new file mode 100755 index 0000000..c38769c --- /dev/null +++ b/lcc/etc/gcc-solaris.c @@ -0,0 +1,50 @@ +/* SPARCs running Solaris 2.5.1 w/GCC tools
 +   at CS Dept., Princeton University */
 +
 +#include <string.h>
 +
 +
 +#ifndef LCCDIR
 +#define LCCDIR "/usr/local/lib/lcc/"
 +#endif
 +#ifndef GCCDIR
 +#define GCCDIR "/usr/local/gnu/bin/"
 +#endif
 +#ifndef GCCLIB
 +#define GCCLIB "/usr/local/gnu/lib/gcc-lib/sparc-sun-solaris2.5/2.7.2/"
 +#endif
 +
 +char *suffixes[] = { ".c", ".i", ".s", ".o", ".out", 0 };
 +char inputs[256] = "";
 +char *cpp[] = { LCCDIR "cpp",
 +	"-D__STDC__=1", "-Dsparc", "-D__sparc__", "-Dsun", "-D__sun__", "-Dunix",
 +	"$1", "$2", "$3", 0 };
 +char *include[] = { "-I" LCCDIR "include", "-I/usr/local/include",
 +	"-I" GCCLIB "include", "-I/usr/include", 0 };
 +char *com[] = { LCCDIR "rcc", "-target=sparc/solaris",
 +	"$1", "$2", "$3", 0 };
 +char *as[] = { GCCDIR "as", "-f", "-o", "$3", "$1", "$2", 0 };
 +char *ld[] = { GCCDIR "ld", "-o", "$3", "$1",
 +	GCCLIB "crti.o", GCCLIB "crt1.o",
 +	GCCLIB "crtbegin.o", "$2", "", "", "-L" LCCDIR, "-llcc",
 +	"-L" GCCLIB, "-lgcc", "-lm", "-lc", "",
 +	GCCLIB "crtend.o", GCCLIB "crtn.o", 0 };
 +
 +extern char *concat(char *, char *);
 +
 +int option(char *arg) {
 +	if (strncmp(arg, "-lccdir=", 8) == 0) {
 +		cpp[0] = concat(&arg[8], "/cpp");
 +		include[0] = concat("-I", concat(&arg[8], "/include"));
 +		ld[10] = concat("-L", &arg[8]);
 +		com[0] = concat(&arg[8], "/rcc");
 +	} else if (strcmp(arg, "-g") == 0)
 +		;
 +	else if (strcmp(arg, "-pg") == 0) {
 +		ld[8] = GCCLIB "gmon.o";
 +	} else if (strcmp(arg, "-b") == 0)
 +		;
 +	else
 +		return 0;
 +	return 1;
 +}
 diff --git a/lcc/etc/irix.c b/lcc/etc/irix.c new file mode 100755 index 0000000..cc09f1e --- /dev/null +++ b/lcc/etc/irix.c @@ -0,0 +1,64 @@ +/* SGI big endian MIPSes running IRIX 5.2 at CS Dept., Princeton University */
 +
 +#include <string.h>
 +
 +
 +#ifndef LCCDIR
 +#define LCCDIR "/usr/local/lib/lcc/"
 +#endif
 +
 +char *suffixes[] = { ".c", ".i", ".s", ".o", ".out", 0 };
 +char inputs[256] = "";
 +char *cpp[] = { LCCDIR "cpp", "-D__STDC__=1",
 +	"-DLANGUAGE_C",
 +	"-DMIPSEB",
 +	"-DSYSTYPE_SVR4",
 +	"-D_CFE",
 +	"-D_LANGUAGE_C",
 +	"-D_MIPSEB",
 +	"-D_MIPS_FPSET=16",
 +	"-D_MIPS_ISA=_MIPS_ISA_MIPS1",
 +	"-D_MIPS_SIM=_MIPS_SIM_ABI32",
 +	"-D_MIPS_SZINT=32",
 +	"-D_MIPS_SZLONG=32",
 +	"-D_MIPS_SZPTR=32",
 +	"-D_SGI_SOURCE",
 +	"-D_SVR4_SOURCE",
 +	"-D_SYSTYPE_SVR4",
 +	"-D__host_mips",
 +	"-D__mips=1",
 +	"-D__sgi",
 +	"-D__unix",
 +	"-Dhost_mips",
 +	"-Dmips",
 +	"-Dsgi",
 +	"-Dunix",
 +	"$1", "$2", "$3", 0 };
 +char *com[] =  { LCCDIR "rcc", "-target=mips/irix", "$1", "$2", "$3", "", 0 };
 +char *include[] = { "-I" LCCDIR "include", "-I/usr/local/include",
 +	"-I/usr/include", 0 };
 +char *as[] = { "/usr/bin/as", "-o", "$3", "$1", "-nocpp", "-KPIC", "$2", 0 };
 +char *ld[] = { "/usr/bin/ld", "-require_dynamic_link", "_rld_new_interface",
 +	"-elf", "-_SYSTYPE_SVR4", "-Wx,-G", "0", "-g0", "-KPIC", "-dont_warn_unused",
 +	"-o", "$3", "/usr/lib/crt1.o", "-L/usr/local/lib",
 +	"$1", "$2", "", "-L" LCCDIR, "-llcc", "-lc", "-lm", "/usr/lib/crtn.o", 0
 +};
 +
 +extern char *concat(char *, char *);
 +
 +int option(char *arg) {
 +	if (strncmp(arg, "-lccdir=", 8) == 0) {
 +		cpp[0] = concat(&arg[8], "/cpp");
 +		include[0] = concat("-I", concat(&arg[8], "/include"));
 +		com[0] = concat(&arg[8], "/rcc");
 +		ld[17] = concat("-L", &arg[8]);
 +	} else if (strcmp(arg, "-g") == 0)
 +		;
 +	else if (strcmp(arg, "-p") == 0)
 +		ld[12] = "/usr/lib/mcrt1.o";
 +	else if (strcmp(arg, "-b") == 0)
 +		;
 +	else
 +		return 0;
 +	return 1;
 +}
 diff --git a/lcc/etc/lcc.c b/lcc/etc/lcc.c new file mode 100755 index 0000000..c70abbb --- /dev/null +++ b/lcc/etc/lcc.c @@ -0,0 +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;
 +}
 diff --git a/lcc/etc/linux.c b/lcc/etc/linux.c new file mode 100755 index 0000000..58a8b81 --- /dev/null +++ b/lcc/etc/linux.c @@ -0,0 +1,74 @@ +/* x86s running Linux */
 +
 +#include <string.h>
 +
 +static char rcsid[] = "Dummy rcsid";
 +
 +/*
 +TTimo - 10-18-2001
 +our binaries are named q3lcc q3rcc and q3cpp
 +removed hardcoded paths
 +removed __linux__ preprocessor define (confuses the preprocessor, we are doing bytecode!)
 +*/
 +
 +#ifndef LCCDIR
 +#define LCCDIR ""
 +//#define LCCDIR "/usr/local/lib/lcc/"
 +#endif
 +
 +char *suffixes[] = { ".c", ".i", ".asm", ".o", ".out", 0 };
 +char inputs[256] = "";
 +// TTimo experimental: do not compile with the __linux__ define, we are doing bytecode!
 +char *cpp[] = { LCCDIR "q3cpp",
 +	"-U__GNUC__", "-D_POSIX_SOURCE", "-D__STDC__=1", "-D__STRICT_ANSI__",
 +	"-Dunix", "-Di386", "-Dlinux",
 +	"-D__unix__", "-D__i386__", "-D__signed__=signed",
 +	"$1", "$2", "$3", 0 };
 +char *include[] = {"-I" LCCDIR "include", "-I" LCCDIR "gcc/include", "-I/usr/include",
 +		   "-I" SYSTEM "include", 0 };
 +char *com[] = {LCCDIR "q3rcc", "-target=x86/linux", "$1", "$2", "$3", 0 };
 +char *as[] = { "/usr/bin/as", "-o", "$3", "$1", "$2", 0 };
 +// NOTE TTimo I don't think we have any use with the native linkage
 +// our target is always bytecode..
 +char *ld[] = {
 +	/*  0 */ "/usr/bin/ld", "-m", "elf_i386", "-dynamic-linker",
 +	/*  4 */ "/lib/ld-linux.so.2", "-o", "$3",
 +	/*  7 */ "/usr/lib/crt1.o", "/usr/lib/crti.o",
 +	/*  9 */ SYSTEM "crtbegin.o", 
 +                 "$1", "$2",
 +	/* 12 */ "-L" LCCDIR,
 +	/* 13 */ "-llcc",
 +	/* 14 */ "-L" LCCDIR "/gcc", "-lgcc", "-lc", "-lm",
 +	/* 18 */ "",
 +	/* 19 */ SYSTEM "crtend.o", "/usr/lib/crtn.o",
 +	/* 20 */ "-L" SYSTEM,
 +	0 };
 +
 +extern char *concat(char *, char *);
 +
 +int option(char *arg) {
 +  	if (strncmp(arg, "-lccdir=", 8) == 0) {
 +		cpp[0] = concat(&arg[8], "/gcc/cpp");
 +		include[0] = concat("-I", concat(&arg[8], "/include"));
 +		include[1] = concat("-I", concat(&arg[8], "/gcc/include"));
 +		ld[9]  = concat(&arg[8], "/gcc/crtbegin.o");
 +		ld[12] = concat("-L", &arg[8]);
 +		ld[14] = concat("-L", concat(&arg[8], "/gcc"));
 +		ld[19] = concat(&arg[8], "/gcc/crtend.o");
 +		com[0] = concat(&arg[8], "/rcc");
 +	} else if (strcmp(arg, "-p") == 0 || strcmp(arg, "-pg") == 0) {
 +		ld[7] = "/usr/lib/gcrt1.o";
 +		ld[18] = "-lgmon";
 +	} else if (strcmp(arg, "-b") == 0) 
 +		;
 +	else if (strcmp(arg, "-g") == 0)
 +		;
 +	else if (strncmp(arg, "-ld=", 4) == 0)
 +		ld[0] = &arg[4];
 +	else if (strcmp(arg, "-static") == 0) {
 +	        ld[3] = "-static";
 +	        ld[4] = "";
 +	} else
 +		return 0;
 +	return 1;
 +}
 diff --git a/lcc/etc/ops.c b/lcc/etc/ops.c new file mode 100755 index 0000000..dd570b7 --- /dev/null +++ b/lcc/etc/ops.c @@ -0,0 +1,190 @@ +#include "c.h"
 +
 +/* ops [ {csilhfdxp}=n ]...
 + * prints lcc dag operator set for a given set of type sizes.
 + */
 +
 +
 +static char list[] = { 'c', 's', 'i', 'l', 'h', 'f', 'd', 'x', 'p', 0 };
 +static int sizes[] = {  1,   2,   4,   4,   8,   4,   8,  16,   8 };
 +
 +static int doop(int op, int type, const char *sz, const char *opname) {
 +	int count = 0;
 +	static int last;
 +
 +	if (op == LOAD)
 +		return 0;
 +	if (last != 0 && last != op)
 +		printf("\n");
 +	last = op;
 +	if (type == B || type == V) {
 +		printf(" %s=%d", opname, op + type);
 +		count++;
 +	} else {
 +		int i, done = 0;
 +		const char *s;
 +		for (i = 0; sz[i] != '\0' && (s = strchr(list, sz[i])) != NULL; i++) {
 +			int n = sizes[s-list];
 +			if ((done&(1<<n)) == 0) {
 +				printf(" %s%d=%d", opname, n, op + type + sizeop(n));
 +				count++;
 +			}
 +			done |= 1<<n;
 +		}
 +	}
 +	printf("\n");
 +	return count;
 +}
 +
 +int main(int argc, char *argv[]) {
 +	int i, count = 0;
 +
 +	for (i = 1; i < argc; i++) {
 +		char c, *s;
 +		int n;
 +		if (sscanf(argv[i], "%c=%d", &c, &n) == 2
 +		&& n > 0 && (s = strchr(list, c)) != NULL)
 +			sizes[s-list] = n;
 +		else {
 +			fprintf(stderr, "usage: %s [ {csilhfdxp}=n ]...\n", argv[0]);
 +			exit(EXIT_FAILURE);
 +		}
 +	}
 +#define gop(x,n)
 +#define op(x,t,s) count += doop(x,t,#s,#x #t);
 +gop(CNST,1)
 +	op(CNST,F,fdx)
 +	op(CNST,I,csilh)
 +	op(CNST,P,p)
 +	op(CNST,U,csilh)
 +gop(ARG,2)
 +	op(ARG,B,-)
 +	op(ARG,F,fdx)
 +	op(ARG,I,ilh)
 +	op(ARG,P,p)
 +	op(ARG,U,ilh)
 +gop(ASGN,3)
 +	op(ASGN,B,-)
 +	op(ASGN,F,fdx)
 +	op(ASGN,I,csilh)
 +	op(ASGN,P,p)
 +	op(ASGN,U,csilh)
 +gop(INDIR,4)
 +	op(INDIR,B,-)
 +	op(INDIR,F,fdx)
 +	op(INDIR,I,csilh)
 +	op(INDIR,P,p)
 +	op(INDIR,U,csilh)
 +gop(CVF,7)
 +	op(CVF,F,fdx)
 +	op(CVF,I,ilh)
 +gop(CVI,8)
 +	op(CVI,F,fdx)
 +	op(CVI,I,csilh)
 +	op(CVI,U,csilhp)
 +gop(CVP,9)
 +	op(CVP,U,p)
 +gop(CVU,11)
 +	op(CVU,I,csilh)
 +	op(CVU,P,p)
 +	op(CVU,U,csilh)
 +gop(NEG,12)
 +	op(NEG,F,fdx)
 +	op(NEG,I,ilh)
 +gop(CALL,13)
 +	op(CALL,B,-)
 +	op(CALL,F,fdx)
 +	op(CALL,I,ilh)
 +	op(CALL,P,p)
 +	op(CALL,U,ilh)
 +	op(CALL,V,-)
 +gop(RET,15)
 +	op(RET,F,fdx)
 +	op(RET,I,ilh)
 +	op(RET,P,p)
 +	op(RET,U,ilh)
 +	op(RET,V,-)
 +gop(ADDRG,16)
 +	op(ADDRG,P,p)
 +gop(ADDRF,17)
 +	op(ADDRF,P,p)
 +gop(ADDRL,18)
 +	op(ADDRL,P,p)
 +gop(ADD,19)
 +	op(ADD,F,fdx)
 +	op(ADD,I,ilh)
 +	op(ADD,P,p)
 +	op(ADD,U,ilhp)
 +gop(SUB,20)
 +	op(SUB,F,fdx)
 +	op(SUB,I,ilh)
 +	op(SUB,P,p)
 +	op(SUB,U,ilhp)
 +gop(LSH,21)
 +	op(LSH,I,ilh)
 +	op(LSH,U,ilh)
 +gop(MOD,22)
 +	op(MOD,I,ilh)
 +	op(MOD,U,ilh)
 +gop(RSH,23)
 +	op(RSH,I,ilh)
 +	op(RSH,U,ilh)
 +gop(BAND,24)
 +	op(BAND,I,ilh)
 +	op(BAND,U,ilh)
 +gop(BCOM,25)
 +	op(BCOM,I,ilh)
 +	op(BCOM,U,ilh)
 +gop(BOR,26)
 +	op(BOR,I,ilh)
 +	op(BOR,U,ilh)
 +gop(BXOR,27)
 +	op(BXOR,I,ilh)
 +	op(BXOR,U,ilh)
 +gop(DIV,28)
 +	op(DIV,F,fdx)
 +	op(DIV,I,ilh)
 +	op(DIV,U,ilh)
 +gop(MUL,29)
 +	op(MUL,F,fdx)
 +	op(MUL,I,ilh)
 +	op(MUL,U,ilh)
 +gop(EQ,30)
 +	op(EQ,F,fdx)
 +	op(EQ,I,ilh)
 +	op(EQ,U,ilhp)
 +gop(GE,31)
 +	op(GE,F,fdx)
 +	op(GE,I,ilh)
 +	op(GE,U,ilhp)
 +gop(GT,32)
 +	op(GT,F,fdx)
 +	op(GT,I,ilh)
 +	op(GT,U,ilhp)
 +gop(LE,33)
 +	op(LE,F,fdx)
 +	op(LE,I,ilh)
 +	op(LE,U,ilhp)
 +gop(LT,34)
 +	op(LT,F,fdx)
 +	op(LT,I,ilh)
 +	op(LT,U,ilhp)
 +gop(NE,35)
 +	op(NE,F,fdx)
 +	op(NE,I,ilh)
 +	op(NE,U,ilhp)
 +gop(JUMP,36)
 +	op(JUMP,V,-)
 +gop(LABEL,37)
 +	op(LABEL,V,-)
 +gop(LOAD,14)
 +	op(LOAD,B,-)
 +	op(LOAD,F,fdx)
 +	op(LOAD,I,csilh)
 +	op(LOAD,P,p)
 +	op(LOAD,U,csilhp)
 +#undef gop
 +#undef op
 +	fprintf(stderr, "%d operators\n", count);
 +	return EXIT_SUCCESS;
 +}
 diff --git a/lcc/etc/osf.c b/lcc/etc/osf.c new file mode 100755 index 0000000..4c57b09 --- /dev/null +++ b/lcc/etc/osf.c @@ -0,0 +1,53 @@ +/* DEC ALPHAs running OSF/1 V3.2A (Rev. 17) at Princeton University */
 +
 +#include <string.h>
 +
 +
 +#ifndef LCCDIR
 +#define LCCDIR "/usr/local/lib/lcc/"
 +#endif
 +
 +char *suffixes[] = { ".c", ".i", ".s", ".o", ".out", 0 };
 +char inputs[256] = "";
 +char *cpp[] = {
 +	LCCDIR "cpp", "-D__STDC__=1",
 +	"-DLANGUAGE_C", "-D__LANGUAGE_C__",
 + 	"-D_unix", "-D__unix__", "-D_osf", "-D__osf__", "-Dunix",
 +	"-Dalpha", "-D_alpha", "-D__alpha",
 +	"-D__SYSTYPE_BSD",  "-D_SYSTYPE_BSD",
 +	"$1", "$2", "$3", 0 };
 +char *com[] =  { LCCDIR "rcc", "-target=alpha/osf", "$1", "$2", "$3", "", 0 };
 +char *include[] = { "-I" LCCDIR "include", "-I/usr/local/include",
 +	"-I/usr/include", 0 };
 +char *as[] =  { "/bin/as", "-o", "$3", "", "$1", "-nocpp", "$2", 0 };
 +char *ld[] =  { "/usr/bin/ld", "-o", "$3", "/usr/lib/cmplrs/cc/crt0.o",
 +	"$1", "$2", "", "", "-L" LCCDIR, "-llcc", "-lm", "-lc", 0 };
 +
 +extern char *concat(char *, char *);
 +extern int access(const char *, int);
 +
 +int option(char *arg) {
 +	if (strncmp(arg, "-lccdir=", 8) == 0) {
 +		cpp[0] = concat(&arg[8], "/cpp");
 +		include[0] = concat("-I", concat(&arg[8], "/include"));
 +		com[0] = concat(&arg[8], "/rcc");
 +		ld[8] = concat("-L", &arg[8]);
 +	} else if (strcmp(arg, "-g4") == 0
 +	&& access("/u/drh/lib/alpha/rcc", 4) == 0
 +	&& access("/u/drh/book/cdb/alpha/osf/cdbld", 4) == 0) {
 +		com[0] = "/u/drh/lib/alpha/rcc";
 +		com[5] = "-g4";
 +		ld[0] = "/u/drh/book/cdb/alpha/osf/cdbld";
 +		ld[1] = "-o";
 +		ld[2] = "$3";
 +		ld[3] = "$1";
 +		ld[4] = "$2";
 +		ld[5] = 0;
 +	} else if (strcmp(arg, "-g") == 0)
 +		return 1;
 +	else if (strcmp(arg, "-b") == 0)
 +		;
 +	else
 +		return 0;
 +	return 1;
 +}
 diff --git a/lcc/etc/solaris.c b/lcc/etc/solaris.c new file mode 100755 index 0000000..453b101 --- /dev/null +++ b/lcc/etc/solaris.c @@ -0,0 +1,50 @@ +/* SPARCs running Solaris 2.5.1 at CS Dept., Princeton University */
 +
 +#include <string.h>
 +
 +
 +#ifndef LCCDIR
 +#define LCCDIR "/usr/local/lib/lcc/"
 +#endif
 +#ifndef SUNDIR
 +#define SUNDIR "/opt/SUNWspro/SC4.2/lib/"
 +#endif
 +
 +char *suffixes[] = { ".c", ".i", ".s", ".o", ".out", 0 };
 +char inputs[256] = "";
 +char *cpp[] = { LCCDIR "cpp",
 +	"-D__STDC__=1", "-Dsparc", "-D__sparc__", "-Dsun", "-D__sun__", "-Dunix",
 +	"$1", "$2", "$3", 0 };
 +char *include[] = { "-I" LCCDIR "include", "-I/usr/local/include",
 +	"-I/usr/include", 0 };
 +char *com[] = { LCCDIR "rcc", "-target=sparc/solaris",
 +	"$1", "$2", "$3", 0 };
 +char *as[] = { "/usr/ccs/bin/as", "-Qy", "-s", "-o", "$3", "$1", "$2", 0 };
 +char *ld[] = { "/usr/ccs/bin/ld", "-o", "$3", "$1",
 +	SUNDIR "crti.o", SUNDIR "crt1.o",
 +	SUNDIR "values-xa.o", "$2", "",
 +	"-Y", "P," SUNDIR ":/usr/ccs/lib:/usr/lib", "-Qy",
 +	"-L" LCCDIR, "-llcc", "-lm", "-lc", SUNDIR "crtn.o", 0 };
 +
 +extern char *concat(char *, char *);
 +
 +int option(char *arg) {
 +	if (strncmp(arg, "-lccdir=", 8) == 0) {
 +		cpp[0] = concat(&arg[8], "/cpp");
 +		include[0] = concat("-I", concat(&arg[8], "/include"));
 +		ld[12] = concat("-L", &arg[8]);
 +		com[0] = concat(&arg[8], "/rcc");
 +	} else if (strcmp(arg, "-g") == 0)
 +		;
 +	else if (strcmp(arg, "-p") == 0) {
 +		ld[5] = SUNDIR "mcrt1.o";
 +		ld[10] = "P," SUNDIR "libp:/usr/ccs/lib/libp:/usr/lib/libp:"
 +			 SUNDIR ":/usr/ccs/lib:/usr/lib";
 +	} else if (strcmp(arg, "-b") == 0)
 +		;
 +	else if (strncmp(arg, "-ld=", 4) == 0)
 +		ld[0] = &arg[4];
 +	else
 +		return 0;
 +	return 1;
 +}
 diff --git a/lcc/etc/win32.c b/lcc/etc/win32.c new file mode 100755 index 0000000..097fa42 --- /dev/null +++ b/lcc/etc/win32.c @@ -0,0 +1,43 @@ +/* x86s running MS Windows NT 4.0 */
 +
 +#include <string.h>
 +
 +
 +#ifndef LCCDIR
 +// JDC #define LCCDIR "\\progra~1\\lcc\\4.1\\bin\\"
 +//#define LCCDIR "\\quake3\\source\\lcc\\bin\\"	// JDC
 +// TTimo: q3cpp q3rcc & no hardcoded paths
 +#define LCCDIR ""
 +#endif
 +
 +char *suffixes[] = { ".c;.C", ".i;.I", ".asm;.ASM;.s;.S", ".obj;.OBJ", ".exe", 0 };
 +char inputs[256] = "";
 +char *cpp[] = { LCCDIR "q3cpp", "-D__STDC__=1", "-Dwin32", "-D_WIN32", "-D_M_IX86",
 +	"$1", "$2", "$3", 0 };
 +char *include[] = { "-I" LCCDIR "include", 0 };
 +char *com[] = { LCCDIR "q3rcc", "-target=x86/win32", "$1", "$2", "$3", 0 };
 +char *as[] = { "ml", "-nologo", "-c", "-Cp", "-coff", "-Fo$3", "$1", "$2", 0 };
 +char *ld[] = { "link", "-nologo", 
 +	"-align:0x1000", "-subsystem:console", "-entry:mainCRTStartup",
 +	"$2", "-OUT:$3", "$1", LCCDIR "liblcc.lib", "libc.lib", "kernel32.lib", 0 };
 +
 +extern char *concat(char *, char *);
 +extern char *replace(const char *, int, int);
 +
 +int option(char *arg) {
 +	if (strncmp(arg, "-lccdir=", 8) == 0) {
 +		arg = replace(arg + 8, '/', '\\');
 +		if (arg[strlen(arg)-1] == '\\')
 +			arg[strlen(arg)-1] = '\0';
 +		cpp[0] = concat(arg, "\\cpp.exe");
 +		include[0] = concat("-I", concat(arg, "\\include"));
 +		com[0] = concat(arg, "\\rcc.exe");
 +		ld[8] = concat(arg, "\\liblcc.lib");
 +	} else if (strcmp(arg, "-b") == 0)
 +		;
 +	else if (strncmp(arg, "-ld=", 4) == 0)
 +		ld[0] = &arg[4];
 +	else
 +		return 0;
 +	return 1;
 +}
 | 
