xref: /csrg-svn/sys/tahoe/inline/main.c (revision 26405)
124038Ssam /*
224038Ssam  * Copyright (c) 1984 Regents of the University of California.
324038Ssam  * All rights reserved.  The Berkeley software License Agreement
424038Ssam  * specifies the terms and conditions for redistribution.
524038Ssam  */
624038Ssam 
724038Ssam #ifndef lint
824038Ssam char copyright[] =
924038Ssam "@(#) Copyright (c) 1984 Regents of the University of California.\n\
1024038Ssam  All rights reserved.\n";
1125692Ssam #endif
1224038Ssam 
1324038Ssam #ifndef lint
14*26405Ssam static char sccsid[] = "@(#)main.c	1.3 (Berkeley) 02/24/86";
1525692Ssam #endif
1624038Ssam 
1724038Ssam #include <stdio.h>
1824038Ssam #include <ctype.h>
1924038Ssam #include "inline.h"
2024038Ssam 
2124038Ssam /*
2224038Ssam  * These are the pattern tables to be loaded
2324038Ssam  */
2424038Ssam struct pats *inittables[] = {
2524038Ssam 	language_ptab,
2624038Ssam 	libc_ptab,
2724038Ssam 	machine_ptab,
2824038Ssam 	0
2924038Ssam };
3024038Ssam 
3124038Ssam /*
3224038Ssam  * Statistics collection
3324038Ssam  */
3424038Ssam struct stats {
3524038Ssam 	int	attempted;	/* number of expansion attempts */
3624038Ssam 	int	finished;	/* expansions done before end of basic block */
3724038Ssam 	int	lostmodified;	/* mergers inhibited by intervening mod */
3824038Ssam 	int	savedpush;	/* successful push/pop merger */
3924038Ssam } stats;
4024038Ssam 
41*26405Ssam extern	char *strcpy();
42*26405Ssam 
43*26405Ssam char	*whoami;
44*26405Ssam int	lineno = 0;
45*26405Ssam int	dflag;
46*26405Ssam 
4724038Ssam main(argc, argv)
4824038Ssam 	int argc;
4924038Ssam 	char *argv[];
5024038Ssam {
5124038Ssam 	register char *cp, *lp;
5224038Ssam 	register char *bufp;
5324038Ssam 	register struct pats *pp, **php;
5424038Ssam 	struct pats **tablep;
5524038Ssam 	register struct inststoptbl *itp, **ithp;
5624038Ssam 	int size;
5724038Ssam 	extern char *index();
5824038Ssam 
59*26405Ssam 	whoami = argv[0];
6024038Ssam 	if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
6124038Ssam 		dflag++, argc--, argv++;
6224038Ssam 	if (argc > 1)
6324038Ssam 		freopen(argv[1], "r", stdin);
6424038Ssam 	if (argc > 2)
6524038Ssam 		freopen(argv[2], "w", stdout);
6624038Ssam 	/*
6724038Ssam 	 * Set up the hash table for the patterns.
6824038Ssam 	 */
6924038Ssam 	for (tablep = inittables; *tablep; tablep++) {
7024038Ssam 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
7124038Ssam 			php = &patshdr[hash(pp->name, &size)];
7224038Ssam 			pp->size = size;
7324038Ssam 			pp->next = *php;
7424038Ssam 			*php = pp;
7524038Ssam 		}
7624038Ssam 	}
7724038Ssam 	/*
7824038Ssam 	 * Set up the hash table for the instruction stop table.
7924038Ssam 	 */
8024038Ssam 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
8124038Ssam 		ithp = &inststoptblhdr[hash(itp->name, &size)];
8224038Ssam 		itp->size = size;
8324038Ssam 		itp->next = *ithp;
8424038Ssam 		*ithp = itp;
8524038Ssam 	}
8624038Ssam 	/*
8724038Ssam 	 * check each line and replace as appropriate
8824038Ssam 	 */
8924038Ssam 	buftail = bufhead = 0;
9024038Ssam 	bufp = line[0];
9124038Ssam 	while (fgets(bufp, MAXLINELEN, stdin)) {
92*26405Ssam 		lineno++;
9324038Ssam 		lp = index(bufp, LABELCHAR);
9424038Ssam 		if (lp != NULL) {
9524038Ssam 			for (cp = bufp; cp < lp; cp++)
9624038Ssam 				if (!isalnum(*cp))
9724038Ssam 					break;
9824038Ssam 			if (cp == lp) {
9924038Ssam 				bufp = newline();
10024038Ssam 				if (*++lp == '\n') {
10124038Ssam 					emptyqueue();
10224038Ssam 					continue;
10324038Ssam 				}
104*26405Ssam 				(void) strcpy(bufp, lp);
10524038Ssam 				*lp++ = '\n';
10624038Ssam 				*lp = '\0';
10724038Ssam 				emptyqueue();
10824038Ssam 			}
10924038Ssam 		}
11024038Ssam 		for (cp = bufp; isspace(*cp); cp++)
11124038Ssam 			/* void */;
11224038Ssam 		if ((cp = doreplaceon(cp)) == 0) {
11324038Ssam 			bufp = newline();
11424038Ssam 			continue;
11524038Ssam 		}
11624038Ssam 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
11724038Ssam 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
118*26405Ssam 				if (argcounterr(pp->args, countargs(bufp),
119*26405Ssam 				    pp->name)) {
120*26405Ssam 					pp = NULL;
121*26405Ssam 					break;
122*26405Ssam 				}
12324038Ssam 				expand(pp->replace);
12424038Ssam 				bufp = line[bufhead];
12524038Ssam 				break;
12624038Ssam 			}
12724038Ssam 		}
12824038Ssam 		if (!pp) {
12924038Ssam 			emptyqueue();
13024038Ssam 			fputs(bufp, stdout);
13124038Ssam 		}
13224038Ssam 	}
13324038Ssam 	emptyqueue();
13424038Ssam 	if (dflag)
135*26405Ssam 		fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
136*26405Ssam 			whoami,
13724038Ssam 			"attempts", stats.attempted,
13824038Ssam 			"finished", stats.finished,
13924038Ssam 			"inhibited", stats.lostmodified,
14024038Ssam 			"merged", stats.savedpush);
14124038Ssam 	exit(0);
14224038Ssam }
14324038Ssam 
14424038Ssam /*
14524038Ssam  * Integrate an expansion into the assembly stream
14624038Ssam  */
14724038Ssam expand(replace)
14824038Ssam 	char *replace;
14924038Ssam {
15024038Ssam 	register int curptr;
15124038Ssam 	char *nextreplace, *argv[MAXARGS];
15224038Ssam 	int argc, argreg, foundarg, mod = 0, args = 0;
15324038Ssam 	char parsebuf[BUFSIZ];
15424038Ssam 
15524038Ssam 	stats.attempted++;
15624038Ssam 	for (curptr = bufhead; ; ) {
15724038Ssam 		nextreplace = copyline(replace, line[bufhead]);
15824038Ssam 		argc = parseline(line[bufhead], argv, parsebuf);
15924038Ssam 		argreg = nextarg(argc, argv);
16024038Ssam 		if (argreg == -1)
16124038Ssam 			break;
16224038Ssam 		args++;
16324038Ssam 		for (foundarg = 0; curptr != buftail; ) {
16424038Ssam 			curptr = PRED(curptr);
16524038Ssam 			argc = parseline(line[curptr], argv, parsebuf);
16624038Ssam 			if (isendofblock(argc, argv))
16724038Ssam 				break;
16824038Ssam 			if (foundarg = ispusharg(argc, argv))
16924038Ssam 				break;
17024038Ssam 			mod |= 1 << modifies(argc, argv);
17124038Ssam 		}
17224038Ssam 		if (!foundarg)
17324038Ssam 			break;
17424038Ssam 		replace = nextreplace;
17524038Ssam 		if (mod & (1 << argreg)) {
17624038Ssam 			stats.lostmodified++;
17724038Ssam 			if (curptr == buftail) {
17824038Ssam 				(void)newline();
17924038Ssam 				break;
18024038Ssam 			}
18124038Ssam 			(void)newline();
18224038Ssam 		} else {
18324038Ssam 			stats.savedpush++;
18424038Ssam 			rewrite(line[curptr], argc, argv, argreg);
18524038Ssam 			mod |= 1 << argreg;
18624038Ssam 		}
18724038Ssam 	}
18824038Ssam 	if (argreg == -1)
18924038Ssam 		stats.finished++;
19024038Ssam 	emptyqueue();
19124038Ssam 	fputs(replace, stdout);
19224038Ssam 	cleanup(args);
19324038Ssam }
19424038Ssam 
19524038Ssam /*
19624038Ssam  * Parse a line of assembly language into opcode and arguments.
19724038Ssam  */
19824038Ssam parseline(linep, argv, linebuf)
19924038Ssam 	char *linep;
20024038Ssam 	char *argv[];
20124038Ssam 	char *linebuf;
20224038Ssam {
20324038Ssam 	register char *bufp = linebuf, *cp = linep;
20424038Ssam 	register int argc = 0;
20524038Ssam 
20624038Ssam 	for (;;) {
20724038Ssam 		/*
20824038Ssam 		 * skip over white space
20924038Ssam 		 */
21024038Ssam 		while (isspace(*cp))
21124038Ssam 			cp++;
21224038Ssam 		if (*cp == '\0')
21324038Ssam 			return (argc);
21424038Ssam 		/*
21524038Ssam 		 * copy argument
21624038Ssam 		 */
21724038Ssam 		if (argc == MAXARGS - 1) {
21824038Ssam 			fprintf(stderr, "instruction too long->%s", linep);
21924038Ssam 			return (argc);
22024038Ssam 		}
22124038Ssam 		argv[argc++] = bufp;
22224038Ssam 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
22324038Ssam 			*bufp++ = *cp++;
22424038Ssam 		*bufp++ = '\0';
22524038Ssam 		if (*cp == COMMENTCHAR)
22624038Ssam 			return (argc);
22724038Ssam 		if (*cp == ARGSEPCHAR)
22824038Ssam 			cp++;
22924038Ssam 	}
23024038Ssam }
23124038Ssam 
23224038Ssam /*
23324038Ssam  * Check for instructions that end a basic block.
23424038Ssam  */
23524038Ssam isendofblock(argc, argv)
23624038Ssam 	int argc;
23724038Ssam 	char *argv[];
23824038Ssam {
23924038Ssam 	register struct inststoptbl *itp;
24024038Ssam 	int size;
24124038Ssam 
24224038Ssam 	if (argc == 0)
24324038Ssam 		return (0);
24424038Ssam 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
24524038Ssam 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
24624038Ssam 			return (1);
24724038Ssam 	return (0);
24824038Ssam }
24924038Ssam 
25024038Ssam /*
25124038Ssam  * Copy a newline terminated string.
25224038Ssam  * Return pointer to character following last character copied.
25324038Ssam  */
25424038Ssam char *
25524038Ssam copyline(from, to)
25624038Ssam 	register char *from, *to;
25724038Ssam {
25824038Ssam 
25924038Ssam 	while (*from != '\n')
26024038Ssam 		*to++ = *from++;
26124038Ssam 	*to++ = *from++;
26224038Ssam 	*to = '\0';
26324038Ssam 	return (from);
26424038Ssam }
26524038Ssam 
26624038Ssam /*
267*26405Ssam  * Check for a disparity between the number of arguments a function
268*26405Ssam  * is called with and the number which we expect to see.
269*26405Ssam  * If the error is unrecoverable, return 1, otherwise 0.
270*26405Ssam  */
271*26405Ssam argcounterr(args, callargs, name)
272*26405Ssam 	int args, callargs;
273*26405Ssam 	char *name;
274*26405Ssam {
275*26405Ssam 	register char *cp;
276*26405Ssam 	char namebuf[MAXLINELEN];
277*26405Ssam 
278*26405Ssam 	if (args == callargs)
279*26405Ssam 		return (0);
280*26405Ssam 	cp = strcpy(namebuf, name);
281*26405Ssam 	while (*cp != '\0' && *cp != '\n')
282*26405Ssam 		++cp;
283*26405Ssam 	if (*cp == '\n')
284*26405Ssam 		*cp = '\0';
285*26405Ssam 	if (callargs >= 0) {
286*26405Ssam 		fprintf(stderr,
287*26405Ssam 		"%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
288*26405Ssam 			whoami, callargs, args, namebuf, lineno);
289*26405Ssam 		return (1);
290*26405Ssam 	}
291*26405Ssam 	fprintf(stderr,
292*26405Ssam 		"%s: warning: can't verify arg count for '%s' at line %d\n",
293*26405Ssam 		whoami, namebuf, lineno);
294*26405Ssam 	return (0);
295*26405Ssam }
296*26405Ssam 
297*26405Ssam /*
29824038Ssam  * open space for next line in the queue
29924038Ssam  */
30024038Ssam char *
30124038Ssam newline()
30224038Ssam {
30324038Ssam 	bufhead = SUCC(bufhead);
30424038Ssam 	if (bufhead == buftail) {
30524038Ssam 		fputs(line[buftail], stdout);
30624038Ssam 		buftail = SUCC(buftail);
30724038Ssam 	}
30824038Ssam 	return (line[bufhead]);
30924038Ssam }
31024038Ssam 
31124038Ssam /*
31224038Ssam  * empty the queue by printing out all its lines.
31324038Ssam  */
31424038Ssam emptyqueue()
31524038Ssam {
31624038Ssam 	while (buftail != bufhead) {
31724038Ssam 		fputs(line[buftail], stdout);
31824038Ssam 		buftail = SUCC(buftail);
31924038Ssam 	}
32024038Ssam }
32124038Ssam 
32224038Ssam /*
32324038Ssam  * Compute the hash of a string.
32424038Ssam  * Return the hash and the size of the item hashed
32524038Ssam  */
32624038Ssam hash(cp, size)
32724038Ssam 	char *cp;
32824038Ssam 	int *size;
32924038Ssam {
33024038Ssam 	register char *cp1 = cp;
33124038Ssam 	register int hash = 0;
33224038Ssam 
33324038Ssam 	while (*cp1 && *cp1 != '\n')
33424038Ssam 		hash += (int)*cp1++;
33524038Ssam 	*size = cp1 - cp + 1;
33624038Ssam 	hash &= HSHSIZ - 1;
33724038Ssam 	return (hash);
33824038Ssam }
339