xref: /csrg-svn/sys/tahoe/inline/main.c (revision 49430)
1*49430Sbostic /*-
2*49430Sbostic  * Copyright (c) 1984 The Regents of the University of California.
3*49430Sbostic  * All rights reserved.
4*49430Sbostic  *
5*49430Sbostic  * %sccs.include.redist.c%
624038Ssam  */
724038Ssam 
824038Ssam #ifndef lint
924038Ssam char copyright[] =
10*49430Sbostic "@(#) Copyright (c) 1984 The Regents of the University of California.\n\
1124038Ssam  All rights reserved.\n";
12*49430Sbostic #endif /* not lint */
1324038Ssam 
1424038Ssam #ifndef lint
15*49430Sbostic static char sccsid[] = "@(#)main.c	1.4 (Berkeley) 05/08/91";
16*49430Sbostic #endif /* not lint */
1724038Ssam 
1824038Ssam #include <stdio.h>
1924038Ssam #include <ctype.h>
2024038Ssam #include "inline.h"
2124038Ssam 
2224038Ssam /*
2324038Ssam  * These are the pattern tables to be loaded
2424038Ssam  */
2524038Ssam struct pats *inittables[] = {
2624038Ssam 	language_ptab,
2724038Ssam 	libc_ptab,
2824038Ssam 	machine_ptab,
2924038Ssam 	0
3024038Ssam };
3124038Ssam 
3224038Ssam /*
3324038Ssam  * Statistics collection
3424038Ssam  */
3524038Ssam struct stats {
3624038Ssam 	int	attempted;	/* number of expansion attempts */
3724038Ssam 	int	finished;	/* expansions done before end of basic block */
3824038Ssam 	int	lostmodified;	/* mergers inhibited by intervening mod */
3924038Ssam 	int	savedpush;	/* successful push/pop merger */
4024038Ssam } stats;
4124038Ssam 
4226405Ssam extern	char *strcpy();
4326405Ssam 
4426405Ssam char	*whoami;
4526405Ssam int	lineno = 0;
4626405Ssam int	dflag;
4726405Ssam 
main(argc,argv)4824038Ssam main(argc, argv)
4924038Ssam 	int argc;
5024038Ssam 	char *argv[];
5124038Ssam {
5224038Ssam 	register char *cp, *lp;
5324038Ssam 	register char *bufp;
5424038Ssam 	register struct pats *pp, **php;
5524038Ssam 	struct pats **tablep;
5624038Ssam 	register struct inststoptbl *itp, **ithp;
5724038Ssam 	int size;
5824038Ssam 	extern char *index();
5924038Ssam 
6026405Ssam 	whoami = argv[0];
6124038Ssam 	if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
6224038Ssam 		dflag++, argc--, argv++;
6324038Ssam 	if (argc > 1)
6424038Ssam 		freopen(argv[1], "r", stdin);
6524038Ssam 	if (argc > 2)
6624038Ssam 		freopen(argv[2], "w", stdout);
6724038Ssam 	/*
6824038Ssam 	 * Set up the hash table for the patterns.
6924038Ssam 	 */
7024038Ssam 	for (tablep = inittables; *tablep; tablep++) {
7124038Ssam 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
7224038Ssam 			php = &patshdr[hash(pp->name, &size)];
7324038Ssam 			pp->size = size;
7424038Ssam 			pp->next = *php;
7524038Ssam 			*php = pp;
7624038Ssam 		}
7724038Ssam 	}
7824038Ssam 	/*
7924038Ssam 	 * Set up the hash table for the instruction stop table.
8024038Ssam 	 */
8124038Ssam 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
8224038Ssam 		ithp = &inststoptblhdr[hash(itp->name, &size)];
8324038Ssam 		itp->size = size;
8424038Ssam 		itp->next = *ithp;
8524038Ssam 		*ithp = itp;
8624038Ssam 	}
8724038Ssam 	/*
8824038Ssam 	 * check each line and replace as appropriate
8924038Ssam 	 */
9024038Ssam 	buftail = bufhead = 0;
9124038Ssam 	bufp = line[0];
9224038Ssam 	while (fgets(bufp, MAXLINELEN, stdin)) {
9326405Ssam 		lineno++;
9424038Ssam 		lp = index(bufp, LABELCHAR);
9524038Ssam 		if (lp != NULL) {
9624038Ssam 			for (cp = bufp; cp < lp; cp++)
9724038Ssam 				if (!isalnum(*cp))
9824038Ssam 					break;
9924038Ssam 			if (cp == lp) {
10024038Ssam 				bufp = newline();
10124038Ssam 				if (*++lp == '\n') {
10224038Ssam 					emptyqueue();
10324038Ssam 					continue;
10424038Ssam 				}
10526405Ssam 				(void) strcpy(bufp, lp);
10624038Ssam 				*lp++ = '\n';
10724038Ssam 				*lp = '\0';
10824038Ssam 				emptyqueue();
10924038Ssam 			}
11024038Ssam 		}
11124038Ssam 		for (cp = bufp; isspace(*cp); cp++)
11224038Ssam 			/* void */;
11324038Ssam 		if ((cp = doreplaceon(cp)) == 0) {
11424038Ssam 			bufp = newline();
11524038Ssam 			continue;
11624038Ssam 		}
11724038Ssam 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
11824038Ssam 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
11926405Ssam 				if (argcounterr(pp->args, countargs(bufp),
12026405Ssam 				    pp->name)) {
12126405Ssam 					pp = NULL;
12226405Ssam 					break;
12326405Ssam 				}
12424038Ssam 				expand(pp->replace);
12524038Ssam 				bufp = line[bufhead];
12624038Ssam 				break;
12724038Ssam 			}
12824038Ssam 		}
12924038Ssam 		if (!pp) {
13024038Ssam 			emptyqueue();
13124038Ssam 			fputs(bufp, stdout);
13224038Ssam 		}
13324038Ssam 	}
13424038Ssam 	emptyqueue();
13524038Ssam 	if (dflag)
13626405Ssam 		fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
13726405Ssam 			whoami,
13824038Ssam 			"attempts", stats.attempted,
13924038Ssam 			"finished", stats.finished,
14024038Ssam 			"inhibited", stats.lostmodified,
14124038Ssam 			"merged", stats.savedpush);
14224038Ssam 	exit(0);
14324038Ssam }
14424038Ssam 
14524038Ssam /*
14624038Ssam  * Integrate an expansion into the assembly stream
14724038Ssam  */
expand(replace)14824038Ssam expand(replace)
14924038Ssam 	char *replace;
15024038Ssam {
15124038Ssam 	register int curptr;
15224038Ssam 	char *nextreplace, *argv[MAXARGS];
15324038Ssam 	int argc, argreg, foundarg, mod = 0, args = 0;
15424038Ssam 	char parsebuf[BUFSIZ];
15524038Ssam 
15624038Ssam 	stats.attempted++;
15724038Ssam 	for (curptr = bufhead; ; ) {
15824038Ssam 		nextreplace = copyline(replace, line[bufhead]);
15924038Ssam 		argc = parseline(line[bufhead], argv, parsebuf);
16024038Ssam 		argreg = nextarg(argc, argv);
16124038Ssam 		if (argreg == -1)
16224038Ssam 			break;
16324038Ssam 		args++;
16424038Ssam 		for (foundarg = 0; curptr != buftail; ) {
16524038Ssam 			curptr = PRED(curptr);
16624038Ssam 			argc = parseline(line[curptr], argv, parsebuf);
16724038Ssam 			if (isendofblock(argc, argv))
16824038Ssam 				break;
16924038Ssam 			if (foundarg = ispusharg(argc, argv))
17024038Ssam 				break;
17124038Ssam 			mod |= 1 << modifies(argc, argv);
17224038Ssam 		}
17324038Ssam 		if (!foundarg)
17424038Ssam 			break;
17524038Ssam 		replace = nextreplace;
17624038Ssam 		if (mod & (1 << argreg)) {
17724038Ssam 			stats.lostmodified++;
17824038Ssam 			if (curptr == buftail) {
17924038Ssam 				(void)newline();
18024038Ssam 				break;
18124038Ssam 			}
18224038Ssam 			(void)newline();
18324038Ssam 		} else {
18424038Ssam 			stats.savedpush++;
18524038Ssam 			rewrite(line[curptr], argc, argv, argreg);
18624038Ssam 			mod |= 1 << argreg;
18724038Ssam 		}
18824038Ssam 	}
18924038Ssam 	if (argreg == -1)
19024038Ssam 		stats.finished++;
19124038Ssam 	emptyqueue();
19224038Ssam 	fputs(replace, stdout);
19324038Ssam 	cleanup(args);
19424038Ssam }
19524038Ssam 
19624038Ssam /*
19724038Ssam  * Parse a line of assembly language into opcode and arguments.
19824038Ssam  */
parseline(linep,argv,linebuf)19924038Ssam parseline(linep, argv, linebuf)
20024038Ssam 	char *linep;
20124038Ssam 	char *argv[];
20224038Ssam 	char *linebuf;
20324038Ssam {
20424038Ssam 	register char *bufp = linebuf, *cp = linep;
20524038Ssam 	register int argc = 0;
20624038Ssam 
20724038Ssam 	for (;;) {
20824038Ssam 		/*
20924038Ssam 		 * skip over white space
21024038Ssam 		 */
21124038Ssam 		while (isspace(*cp))
21224038Ssam 			cp++;
21324038Ssam 		if (*cp == '\0')
21424038Ssam 			return (argc);
21524038Ssam 		/*
21624038Ssam 		 * copy argument
21724038Ssam 		 */
21824038Ssam 		if (argc == MAXARGS - 1) {
21924038Ssam 			fprintf(stderr, "instruction too long->%s", linep);
22024038Ssam 			return (argc);
22124038Ssam 		}
22224038Ssam 		argv[argc++] = bufp;
22324038Ssam 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
22424038Ssam 			*bufp++ = *cp++;
22524038Ssam 		*bufp++ = '\0';
22624038Ssam 		if (*cp == COMMENTCHAR)
22724038Ssam 			return (argc);
22824038Ssam 		if (*cp == ARGSEPCHAR)
22924038Ssam 			cp++;
23024038Ssam 	}
23124038Ssam }
23224038Ssam 
23324038Ssam /*
23424038Ssam  * Check for instructions that end a basic block.
23524038Ssam  */
isendofblock(argc,argv)23624038Ssam isendofblock(argc, argv)
23724038Ssam 	int argc;
23824038Ssam 	char *argv[];
23924038Ssam {
24024038Ssam 	register struct inststoptbl *itp;
24124038Ssam 	int size;
24224038Ssam 
24324038Ssam 	if (argc == 0)
24424038Ssam 		return (0);
24524038Ssam 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
24624038Ssam 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
24724038Ssam 			return (1);
24824038Ssam 	return (0);
24924038Ssam }
25024038Ssam 
25124038Ssam /*
25224038Ssam  * Copy a newline terminated string.
25324038Ssam  * Return pointer to character following last character copied.
25424038Ssam  */
25524038Ssam char *
copyline(from,to)25624038Ssam copyline(from, to)
25724038Ssam 	register char *from, *to;
25824038Ssam {
25924038Ssam 
26024038Ssam 	while (*from != '\n')
26124038Ssam 		*to++ = *from++;
26224038Ssam 	*to++ = *from++;
26324038Ssam 	*to = '\0';
26424038Ssam 	return (from);
26524038Ssam }
26624038Ssam 
26724038Ssam /*
26826405Ssam  * Check for a disparity between the number of arguments a function
26926405Ssam  * is called with and the number which we expect to see.
27026405Ssam  * If the error is unrecoverable, return 1, otherwise 0.
27126405Ssam  */
argcounterr(args,callargs,name)27226405Ssam argcounterr(args, callargs, name)
27326405Ssam 	int args, callargs;
27426405Ssam 	char *name;
27526405Ssam {
27626405Ssam 	register char *cp;
27726405Ssam 	char namebuf[MAXLINELEN];
27826405Ssam 
27926405Ssam 	if (args == callargs)
28026405Ssam 		return (0);
28126405Ssam 	cp = strcpy(namebuf, name);
28226405Ssam 	while (*cp != '\0' && *cp != '\n')
28326405Ssam 		++cp;
28426405Ssam 	if (*cp == '\n')
28526405Ssam 		*cp = '\0';
28626405Ssam 	if (callargs >= 0) {
28726405Ssam 		fprintf(stderr,
28826405Ssam 		"%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
28926405Ssam 			whoami, callargs, args, namebuf, lineno);
29026405Ssam 		return (1);
29126405Ssam 	}
29226405Ssam 	fprintf(stderr,
29326405Ssam 		"%s: warning: can't verify arg count for '%s' at line %d\n",
29426405Ssam 		whoami, namebuf, lineno);
29526405Ssam 	return (0);
29626405Ssam }
29726405Ssam 
29826405Ssam /*
29924038Ssam  * open space for next line in the queue
30024038Ssam  */
30124038Ssam char *
newline()30224038Ssam newline()
30324038Ssam {
30424038Ssam 	bufhead = SUCC(bufhead);
30524038Ssam 	if (bufhead == buftail) {
30624038Ssam 		fputs(line[buftail], stdout);
30724038Ssam 		buftail = SUCC(buftail);
30824038Ssam 	}
30924038Ssam 	return (line[bufhead]);
31024038Ssam }
31124038Ssam 
31224038Ssam /*
31324038Ssam  * empty the queue by printing out all its lines.
31424038Ssam  */
emptyqueue()31524038Ssam emptyqueue()
31624038Ssam {
31724038Ssam 	while (buftail != bufhead) {
31824038Ssam 		fputs(line[buftail], stdout);
31924038Ssam 		buftail = SUCC(buftail);
32024038Ssam 	}
32124038Ssam }
32224038Ssam 
32324038Ssam /*
32424038Ssam  * Compute the hash of a string.
32524038Ssam  * Return the hash and the size of the item hashed
32624038Ssam  */
hash(cp,size)32724038Ssam hash(cp, size)
32824038Ssam 	char *cp;
32924038Ssam 	int *size;
33024038Ssam {
33124038Ssam 	register char *cp1 = cp;
33224038Ssam 	register int hash = 0;
33324038Ssam 
33424038Ssam 	while (*cp1 && *cp1 != '\n')
33524038Ssam 		hash += (int)*cp1++;
33624038Ssam 	*size = cp1 - cp + 1;
33724038Ssam 	hash &= HSHSIZ - 1;
33824038Ssam 	return (hash);
33924038Ssam }
340