xref: /original-bsd/sys/tahoe/inline/main.c (revision 54094f50)
142fa1082Ssam /*
242fa1082Ssam  * Copyright (c) 1984 Regents of the University of California.
342fa1082Ssam  * All rights reserved.  The Berkeley software License Agreement
442fa1082Ssam  * specifies the terms and conditions for redistribution.
542fa1082Ssam  */
642fa1082Ssam 
742fa1082Ssam #ifndef lint
842fa1082Ssam char copyright[] =
942fa1082Ssam "@(#) Copyright (c) 1984 Regents of the University of California.\n\
1042fa1082Ssam  All rights reserved.\n";
11b679c950Ssam #endif
1242fa1082Ssam 
1342fa1082Ssam #ifndef lint
14*54094f50Ssam static char sccsid[] = "@(#)main.c	1.3 (Berkeley) 02/24/86";
15b679c950Ssam #endif
1642fa1082Ssam 
1742fa1082Ssam #include <stdio.h>
1842fa1082Ssam #include <ctype.h>
1942fa1082Ssam #include "inline.h"
2042fa1082Ssam 
2142fa1082Ssam /*
2242fa1082Ssam  * These are the pattern tables to be loaded
2342fa1082Ssam  */
2442fa1082Ssam struct pats *inittables[] = {
2542fa1082Ssam 	language_ptab,
2642fa1082Ssam 	libc_ptab,
2742fa1082Ssam 	machine_ptab,
2842fa1082Ssam 	0
2942fa1082Ssam };
3042fa1082Ssam 
3142fa1082Ssam /*
3242fa1082Ssam  * Statistics collection
3342fa1082Ssam  */
3442fa1082Ssam struct stats {
3542fa1082Ssam 	int	attempted;	/* number of expansion attempts */
3642fa1082Ssam 	int	finished;	/* expansions done before end of basic block */
3742fa1082Ssam 	int	lostmodified;	/* mergers inhibited by intervening mod */
3842fa1082Ssam 	int	savedpush;	/* successful push/pop merger */
3942fa1082Ssam } stats;
40*54094f50Ssam 
41*54094f50Ssam extern	char *strcpy();
42*54094f50Ssam 
43*54094f50Ssam char	*whoami;
44*54094f50Ssam int	lineno = 0;
4542fa1082Ssam int	dflag;
4642fa1082Ssam 
4742fa1082Ssam main(argc, argv)
4842fa1082Ssam 	int argc;
4942fa1082Ssam 	char *argv[];
5042fa1082Ssam {
5142fa1082Ssam 	register char *cp, *lp;
5242fa1082Ssam 	register char *bufp;
5342fa1082Ssam 	register struct pats *pp, **php;
5442fa1082Ssam 	struct pats **tablep;
5542fa1082Ssam 	register struct inststoptbl *itp, **ithp;
5642fa1082Ssam 	int size;
5742fa1082Ssam 	extern char *index();
5842fa1082Ssam 
59*54094f50Ssam 	whoami = argv[0];
6042fa1082Ssam 	if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
6142fa1082Ssam 		dflag++, argc--, argv++;
6242fa1082Ssam 	if (argc > 1)
6342fa1082Ssam 		freopen(argv[1], "r", stdin);
6442fa1082Ssam 	if (argc > 2)
6542fa1082Ssam 		freopen(argv[2], "w", stdout);
6642fa1082Ssam 	/*
6742fa1082Ssam 	 * Set up the hash table for the patterns.
6842fa1082Ssam 	 */
6942fa1082Ssam 	for (tablep = inittables; *tablep; tablep++) {
7042fa1082Ssam 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
7142fa1082Ssam 			php = &patshdr[hash(pp->name, &size)];
7242fa1082Ssam 			pp->size = size;
7342fa1082Ssam 			pp->next = *php;
7442fa1082Ssam 			*php = pp;
7542fa1082Ssam 		}
7642fa1082Ssam 	}
7742fa1082Ssam 	/*
7842fa1082Ssam 	 * Set up the hash table for the instruction stop table.
7942fa1082Ssam 	 */
8042fa1082Ssam 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
8142fa1082Ssam 		ithp = &inststoptblhdr[hash(itp->name, &size)];
8242fa1082Ssam 		itp->size = size;
8342fa1082Ssam 		itp->next = *ithp;
8442fa1082Ssam 		*ithp = itp;
8542fa1082Ssam 	}
8642fa1082Ssam 	/*
8742fa1082Ssam 	 * check each line and replace as appropriate
8842fa1082Ssam 	 */
8942fa1082Ssam 	buftail = bufhead = 0;
9042fa1082Ssam 	bufp = line[0];
9142fa1082Ssam 	while (fgets(bufp, MAXLINELEN, stdin)) {
92*54094f50Ssam 		lineno++;
9342fa1082Ssam 		lp = index(bufp, LABELCHAR);
9442fa1082Ssam 		if (lp != NULL) {
9542fa1082Ssam 			for (cp = bufp; cp < lp; cp++)
9642fa1082Ssam 				if (!isalnum(*cp))
9742fa1082Ssam 					break;
9842fa1082Ssam 			if (cp == lp) {
9942fa1082Ssam 				bufp = newline();
10042fa1082Ssam 				if (*++lp == '\n') {
10142fa1082Ssam 					emptyqueue();
10242fa1082Ssam 					continue;
10342fa1082Ssam 				}
104*54094f50Ssam 				(void) strcpy(bufp, lp);
10542fa1082Ssam 				*lp++ = '\n';
10642fa1082Ssam 				*lp = '\0';
10742fa1082Ssam 				emptyqueue();
10842fa1082Ssam 			}
10942fa1082Ssam 		}
11042fa1082Ssam 		for (cp = bufp; isspace(*cp); cp++)
11142fa1082Ssam 			/* void */;
11242fa1082Ssam 		if ((cp = doreplaceon(cp)) == 0) {
11342fa1082Ssam 			bufp = newline();
11442fa1082Ssam 			continue;
11542fa1082Ssam 		}
11642fa1082Ssam 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
11742fa1082Ssam 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
118*54094f50Ssam 				if (argcounterr(pp->args, countargs(bufp),
119*54094f50Ssam 				    pp->name)) {
120*54094f50Ssam 					pp = NULL;
121*54094f50Ssam 					break;
122*54094f50Ssam 				}
12342fa1082Ssam 				expand(pp->replace);
12442fa1082Ssam 				bufp = line[bufhead];
12542fa1082Ssam 				break;
12642fa1082Ssam 			}
12742fa1082Ssam 		}
12842fa1082Ssam 		if (!pp) {
12942fa1082Ssam 			emptyqueue();
13042fa1082Ssam 			fputs(bufp, stdout);
13142fa1082Ssam 		}
13242fa1082Ssam 	}
13342fa1082Ssam 	emptyqueue();
13442fa1082Ssam 	if (dflag)
135*54094f50Ssam 		fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
136*54094f50Ssam 			whoami,
13742fa1082Ssam 			"attempts", stats.attempted,
13842fa1082Ssam 			"finished", stats.finished,
13942fa1082Ssam 			"inhibited", stats.lostmodified,
14042fa1082Ssam 			"merged", stats.savedpush);
14142fa1082Ssam 	exit(0);
14242fa1082Ssam }
14342fa1082Ssam 
14442fa1082Ssam /*
14542fa1082Ssam  * Integrate an expansion into the assembly stream
14642fa1082Ssam  */
14742fa1082Ssam expand(replace)
14842fa1082Ssam 	char *replace;
14942fa1082Ssam {
15042fa1082Ssam 	register int curptr;
15142fa1082Ssam 	char *nextreplace, *argv[MAXARGS];
15242fa1082Ssam 	int argc, argreg, foundarg, mod = 0, args = 0;
15342fa1082Ssam 	char parsebuf[BUFSIZ];
15442fa1082Ssam 
15542fa1082Ssam 	stats.attempted++;
15642fa1082Ssam 	for (curptr = bufhead; ; ) {
15742fa1082Ssam 		nextreplace = copyline(replace, line[bufhead]);
15842fa1082Ssam 		argc = parseline(line[bufhead], argv, parsebuf);
15942fa1082Ssam 		argreg = nextarg(argc, argv);
16042fa1082Ssam 		if (argreg == -1)
16142fa1082Ssam 			break;
16242fa1082Ssam 		args++;
16342fa1082Ssam 		for (foundarg = 0; curptr != buftail; ) {
16442fa1082Ssam 			curptr = PRED(curptr);
16542fa1082Ssam 			argc = parseline(line[curptr], argv, parsebuf);
16642fa1082Ssam 			if (isendofblock(argc, argv))
16742fa1082Ssam 				break;
16842fa1082Ssam 			if (foundarg = ispusharg(argc, argv))
16942fa1082Ssam 				break;
17042fa1082Ssam 			mod |= 1 << modifies(argc, argv);
17142fa1082Ssam 		}
17242fa1082Ssam 		if (!foundarg)
17342fa1082Ssam 			break;
17442fa1082Ssam 		replace = nextreplace;
17542fa1082Ssam 		if (mod & (1 << argreg)) {
17642fa1082Ssam 			stats.lostmodified++;
17742fa1082Ssam 			if (curptr == buftail) {
17842fa1082Ssam 				(void)newline();
17942fa1082Ssam 				break;
18042fa1082Ssam 			}
18142fa1082Ssam 			(void)newline();
18242fa1082Ssam 		} else {
18342fa1082Ssam 			stats.savedpush++;
18442fa1082Ssam 			rewrite(line[curptr], argc, argv, argreg);
18542fa1082Ssam 			mod |= 1 << argreg;
18642fa1082Ssam 		}
18742fa1082Ssam 	}
18842fa1082Ssam 	if (argreg == -1)
18942fa1082Ssam 		stats.finished++;
19042fa1082Ssam 	emptyqueue();
19142fa1082Ssam 	fputs(replace, stdout);
19242fa1082Ssam 	cleanup(args);
19342fa1082Ssam }
19442fa1082Ssam 
19542fa1082Ssam /*
19642fa1082Ssam  * Parse a line of assembly language into opcode and arguments.
19742fa1082Ssam  */
19842fa1082Ssam parseline(linep, argv, linebuf)
19942fa1082Ssam 	char *linep;
20042fa1082Ssam 	char *argv[];
20142fa1082Ssam 	char *linebuf;
20242fa1082Ssam {
20342fa1082Ssam 	register char *bufp = linebuf, *cp = linep;
20442fa1082Ssam 	register int argc = 0;
20542fa1082Ssam 
20642fa1082Ssam 	for (;;) {
20742fa1082Ssam 		/*
20842fa1082Ssam 		 * skip over white space
20942fa1082Ssam 		 */
21042fa1082Ssam 		while (isspace(*cp))
21142fa1082Ssam 			cp++;
21242fa1082Ssam 		if (*cp == '\0')
21342fa1082Ssam 			return (argc);
21442fa1082Ssam 		/*
21542fa1082Ssam 		 * copy argument
21642fa1082Ssam 		 */
21742fa1082Ssam 		if (argc == MAXARGS - 1) {
21842fa1082Ssam 			fprintf(stderr, "instruction too long->%s", linep);
21942fa1082Ssam 			return (argc);
22042fa1082Ssam 		}
22142fa1082Ssam 		argv[argc++] = bufp;
22242fa1082Ssam 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
22342fa1082Ssam 			*bufp++ = *cp++;
22442fa1082Ssam 		*bufp++ = '\0';
22542fa1082Ssam 		if (*cp == COMMENTCHAR)
22642fa1082Ssam 			return (argc);
22742fa1082Ssam 		if (*cp == ARGSEPCHAR)
22842fa1082Ssam 			cp++;
22942fa1082Ssam 	}
23042fa1082Ssam }
23142fa1082Ssam 
23242fa1082Ssam /*
23342fa1082Ssam  * Check for instructions that end a basic block.
23442fa1082Ssam  */
23542fa1082Ssam isendofblock(argc, argv)
23642fa1082Ssam 	int argc;
23742fa1082Ssam 	char *argv[];
23842fa1082Ssam {
23942fa1082Ssam 	register struct inststoptbl *itp;
24042fa1082Ssam 	int size;
24142fa1082Ssam 
24242fa1082Ssam 	if (argc == 0)
24342fa1082Ssam 		return (0);
24442fa1082Ssam 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
24542fa1082Ssam 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
24642fa1082Ssam 			return (1);
24742fa1082Ssam 	return (0);
24842fa1082Ssam }
24942fa1082Ssam 
25042fa1082Ssam /*
25142fa1082Ssam  * Copy a newline terminated string.
25242fa1082Ssam  * Return pointer to character following last character copied.
25342fa1082Ssam  */
25442fa1082Ssam char *
25542fa1082Ssam copyline(from, to)
25642fa1082Ssam 	register char *from, *to;
25742fa1082Ssam {
25842fa1082Ssam 
25942fa1082Ssam 	while (*from != '\n')
26042fa1082Ssam 		*to++ = *from++;
26142fa1082Ssam 	*to++ = *from++;
26242fa1082Ssam 	*to = '\0';
26342fa1082Ssam 	return (from);
26442fa1082Ssam }
26542fa1082Ssam 
26642fa1082Ssam /*
267*54094f50Ssam  * Check for a disparity between the number of arguments a function
268*54094f50Ssam  * is called with and the number which we expect to see.
269*54094f50Ssam  * If the error is unrecoverable, return 1, otherwise 0.
270*54094f50Ssam  */
271*54094f50Ssam argcounterr(args, callargs, name)
272*54094f50Ssam 	int args, callargs;
273*54094f50Ssam 	char *name;
274*54094f50Ssam {
275*54094f50Ssam 	register char *cp;
276*54094f50Ssam 	char namebuf[MAXLINELEN];
277*54094f50Ssam 
278*54094f50Ssam 	if (args == callargs)
279*54094f50Ssam 		return (0);
280*54094f50Ssam 	cp = strcpy(namebuf, name);
281*54094f50Ssam 	while (*cp != '\0' && *cp != '\n')
282*54094f50Ssam 		++cp;
283*54094f50Ssam 	if (*cp == '\n')
284*54094f50Ssam 		*cp = '\0';
285*54094f50Ssam 	if (callargs >= 0) {
286*54094f50Ssam 		fprintf(stderr,
287*54094f50Ssam 		"%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
288*54094f50Ssam 			whoami, callargs, args, namebuf, lineno);
289*54094f50Ssam 		return (1);
290*54094f50Ssam 	}
291*54094f50Ssam 	fprintf(stderr,
292*54094f50Ssam 		"%s: warning: can't verify arg count for '%s' at line %d\n",
293*54094f50Ssam 		whoami, namebuf, lineno);
294*54094f50Ssam 	return (0);
295*54094f50Ssam }
296*54094f50Ssam 
297*54094f50Ssam /*
29842fa1082Ssam  * open space for next line in the queue
29942fa1082Ssam  */
30042fa1082Ssam char *
30142fa1082Ssam newline()
30242fa1082Ssam {
30342fa1082Ssam 	bufhead = SUCC(bufhead);
30442fa1082Ssam 	if (bufhead == buftail) {
30542fa1082Ssam 		fputs(line[buftail], stdout);
30642fa1082Ssam 		buftail = SUCC(buftail);
30742fa1082Ssam 	}
30842fa1082Ssam 	return (line[bufhead]);
30942fa1082Ssam }
31042fa1082Ssam 
31142fa1082Ssam /*
31242fa1082Ssam  * empty the queue by printing out all its lines.
31342fa1082Ssam  */
31442fa1082Ssam emptyqueue()
31542fa1082Ssam {
31642fa1082Ssam 	while (buftail != bufhead) {
31742fa1082Ssam 		fputs(line[buftail], stdout);
31842fa1082Ssam 		buftail = SUCC(buftail);
31942fa1082Ssam 	}
32042fa1082Ssam }
32142fa1082Ssam 
32242fa1082Ssam /*
32342fa1082Ssam  * Compute the hash of a string.
32442fa1082Ssam  * Return the hash and the size of the item hashed
32542fa1082Ssam  */
32642fa1082Ssam hash(cp, size)
32742fa1082Ssam 	char *cp;
32842fa1082Ssam 	int *size;
32942fa1082Ssam {
33042fa1082Ssam 	register char *cp1 = cp;
33142fa1082Ssam 	register int hash = 0;
33242fa1082Ssam 
33342fa1082Ssam 	while (*cp1 && *cp1 != '\n')
33442fa1082Ssam 		hash += (int)*cp1++;
33542fa1082Ssam 	*size = cp1 - cp + 1;
33642fa1082Ssam 	hash &= HSHSIZ - 1;
33742fa1082Ssam 	return (hash);
33842fa1082Ssam }
339