xref: /csrg-svn/sys/vax/inline/main.c (revision 17202)
116962Smckusick /* Copyright (c) 1984 Regents of the University of California */
216962Smckusick 
316962Smckusick #ifndef lint
4*17202Smckusick static char sccsid[] = "@(#)main.c	1.6	(Berkeley)	09/20/84";
516962Smckusick #endif not lint
616962Smckusick 
716962Smckusick #include <stdio.h>
816962Smckusick #include <ctype.h>
916963Smckusick #include "inline.h"
1016962Smckusick 
1116975Smckusick /*
1216975Smckusick  * These are the pattern tables to be loaded
1316975Smckusick  */
1416975Smckusick struct pats *inittables[] = {
1516975Smckusick 	language_ptab,
1616975Smckusick 	libc_ptab,
1716975Smckusick 	machine_ptab,
1816975Smckusick 	0
1916975Smckusick };
2016975Smckusick 
2116980Smckusick /*
2216980Smckusick  * Statistics collection
2316980Smckusick  */
2416980Smckusick struct stats {
2516980Smckusick 	int	attempted;	/* number of expansion attempts */
2616980Smckusick 	int	finished;	/* expansions done before end of basic block */
2716980Smckusick 	int	lostmodified;	/* mergers inhibited by intervening mod */
2816980Smckusick 	int	savedpush;	/* successful push/pop merger */
2916980Smckusick } stats;
3016980Smckusick int dflag;
3116980Smckusick 
3216962Smckusick main(argc, argv)
3316962Smckusick 	int argc;
3416962Smckusick 	char *argv[];
3516962Smckusick {
3616962Smckusick 	register char *cp, *lp;
3716962Smckusick 	register char *bufp;
3816978Smckusick 	register struct pats *pp, **php;
3916978Smckusick 	struct pats **tablep;
4016978Smckusick 	register struct inststoptbl *itp, **ithp;
4116962Smckusick 	int size;
4216962Smckusick 	extern char *index();
4316962Smckusick 
4416980Smckusick 	if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
4516980Smckusick 		dflag++, argc--, argv++;
4616962Smckusick 	if (argc > 1)
4716962Smckusick 		freopen(argv[1], "r", stdin);
4816962Smckusick 	if (argc > 2)
4916962Smckusick 		freopen(argv[2], "w", stdout);
5016962Smckusick 	/*
5116978Smckusick 	 * Set up the hash table for the patterns.
5216962Smckusick 	 */
5316975Smckusick 	for (tablep = inittables; *tablep; tablep++) {
5416975Smckusick 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
5516978Smckusick 			php = &patshdr[hash(pp->name, &size)];
5616975Smckusick 			pp->size = size;
5716978Smckusick 			pp->next = *php;
5816978Smckusick 			*php = pp;
5916975Smckusick 		}
6016962Smckusick 	}
6116962Smckusick 	/*
6216978Smckusick 	 * Set up the hash table for the instruction stop table.
6316978Smckusick 	 */
6416978Smckusick 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
6516978Smckusick 		ithp = &inststoptblhdr[hash(itp->name, &size)];
6616978Smckusick 		itp->size = size;
6716978Smckusick 		itp->next = *ithp;
6816978Smckusick 		*ithp = itp;
6916978Smckusick 	}
7016978Smckusick 	/*
7116962Smckusick 	 * check each line and replace as appropriate
7216962Smckusick 	 */
7316962Smckusick 	buftail = bufhead = 0;
7416962Smckusick 	bufp = line[0];
7516962Smckusick 	while (fgets(bufp, MAXLINELEN, stdin)) {
7616962Smckusick 		lp = index(bufp, LABELCHAR);
7716962Smckusick 		if (lp != NULL) {
7816962Smckusick 			bufp = newline();
7916962Smckusick 			if (*++lp == '\n') {
8016962Smckusick 				emptyqueue();
8116962Smckusick 				continue;
8216962Smckusick 			}
8316962Smckusick 			strcpy(bufp, lp);
8416962Smckusick 			*lp++ = '\n';
8516962Smckusick 			*lp = '\0';
8616962Smckusick 			emptyqueue();
8716962Smckusick 		}
8816962Smckusick 		for (cp = bufp; isspace(*cp); cp++)
8916962Smckusick 			/* void */;
9016962Smckusick 		if ((cp = doreplaceon(cp)) == 0) {
9116962Smckusick 			bufp = newline();
9216962Smckusick 			continue;
9316962Smckusick 		}
9416978Smckusick 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
9516962Smckusick 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
9616962Smckusick 				expand(pp->replace);
9716962Smckusick 				bufp = line[bufhead];
9816962Smckusick 				break;
9916962Smckusick 			}
10016962Smckusick 		}
10116962Smckusick 		if (!pp) {
10216962Smckusick 			emptyqueue();
10316962Smckusick 			fputs(bufp, stdout);
10416962Smckusick 		}
10516962Smckusick 	}
10616962Smckusick 	emptyqueue();
10716980Smckusick 	if (dflag)
10816980Smckusick 		fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n",
10916980Smckusick 			"attempts", stats.attempted,
11016980Smckusick 			"finished", stats.finished,
11116980Smckusick 			"inhibited", stats.lostmodified,
11216980Smckusick 			"merged", stats.savedpush);
11316962Smckusick 	exit(0);
11416962Smckusick }
11516962Smckusick 
11616962Smckusick /*
11716962Smckusick  * Integrate an expansion into the assembly stream
11816962Smckusick  */
11916962Smckusick expand(replace)
12016962Smckusick 	char *replace;
12116962Smckusick {
12216962Smckusick 	register int curptr;
12316962Smckusick 	char *nextreplace, *argv[MAXARGS];
124*17202Smckusick 	int argc, argreg, foundarg, mod = 0, args = 0;
12516962Smckusick 	char parsebuf[BUFSIZ];
12616962Smckusick 
12716980Smckusick 	stats.attempted++;
12816980Smckusick 	for (curptr = bufhead; ; ) {
12916962Smckusick 		nextreplace = copyline(replace, line[bufhead]);
13016962Smckusick 		argc = parseline(line[bufhead], argv, parsebuf);
13116962Smckusick 		argreg = nextarg(argc, argv);
13216962Smckusick 		if (argreg == -1)
13316962Smckusick 			break;
134*17202Smckusick 		args++;
13516978Smckusick 		for (foundarg = 0; curptr != buftail; ) {
13616978Smckusick 			curptr = PRED(curptr);
13716962Smckusick 			argc = parseline(line[curptr], argv, parsebuf);
13816978Smckusick 			if (isendofblock(argc, argv))
13916962Smckusick 				break;
14016978Smckusick 			if (foundarg = ispusharg(argc, argv))
14116978Smckusick 				break;
14216962Smckusick 			mod |= 1 << modifies(argc, argv);
14316962Smckusick 		}
14416978Smckusick 		if (!foundarg)
14516962Smckusick 			break;
14616962Smckusick 		replace = nextreplace;
14716962Smckusick 		if (mod & (1 << argreg)) {
14816980Smckusick 			stats.lostmodified++;
14916978Smckusick 			if (curptr == buftail) {
15016978Smckusick 				(void)newline();
15116978Smckusick 				break;
15216978Smckusick 			}
15316962Smckusick 			(void)newline();
15416962Smckusick 		} else {
15516980Smckusick 			stats.savedpush++;
15616962Smckusick 			rewrite(line[curptr], argc, argv, argreg);
15716962Smckusick 			mod |= 1 << argreg;
15816962Smckusick 		}
15916962Smckusick 	}
16016980Smckusick 	if (argreg == -1)
16116980Smckusick 		stats.finished++;
16216962Smckusick 	emptyqueue();
16316962Smckusick 	fputs(replace, stdout);
164*17202Smckusick 	cleanup(args);
16516962Smckusick }
16616962Smckusick 
16716962Smckusick /*
16816962Smckusick  * Parse a line of assembly language into opcode and arguments.
16916962Smckusick  */
17016962Smckusick parseline(linep, argv, linebuf)
17116962Smckusick 	char *linep;
17216962Smckusick 	char *argv[];
17316962Smckusick 	char *linebuf;
17416962Smckusick {
17516962Smckusick 	register char *bufp = linebuf, *cp = linep;
17616962Smckusick 	register int argc = 0;
17716962Smckusick 
17816962Smckusick 	for (;;) {
17916962Smckusick 		/*
18016962Smckusick 		 * skip over white space
18116962Smckusick 		 */
18216962Smckusick 		while (isspace(*cp))
18316962Smckusick 			cp++;
18416962Smckusick 		if (*cp == '\0')
18516962Smckusick 			return (argc);
18616962Smckusick 		/*
18716962Smckusick 		 * copy argument
18816962Smckusick 		 */
18916962Smckusick 		if (argc == MAXARGS - 1) {
19016962Smckusick 			fprintf(stderr, "instruction too long->%s", linep);
19116962Smckusick 			return (argc);
19216962Smckusick 		}
19316962Smckusick 		argv[argc++] = bufp;
19416978Smckusick 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
19516962Smckusick 			*bufp++ = *cp++;
19616962Smckusick 		*bufp++ = '\0';
19716962Smckusick 		if (*cp == COMMENTCHAR)
19816962Smckusick 			return (argc);
19916978Smckusick 		if (*cp == ARGSEPCHAR)
20016962Smckusick 			cp++;
20116962Smckusick 	}
20216962Smckusick }
20316962Smckusick 
20416962Smckusick /*
20516978Smckusick  * Check for instructions that end a basic block.
20616978Smckusick  */
20716978Smckusick isendofblock(argc, argv)
20816978Smckusick 	int argc;
20916978Smckusick 	char *argv[];
21016978Smckusick {
21116978Smckusick 	register struct inststoptbl *itp;
21216978Smckusick 	int size;
21316978Smckusick 
21416978Smckusick 	if (argc == 0)
21516978Smckusick 		return (0);
21616978Smckusick 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
21716978Smckusick 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
21816978Smckusick 			return (1);
21916978Smckusick 	return (0);
22016978Smckusick }
22116978Smckusick 
22216978Smckusick /*
22316962Smckusick  * Copy a newline terminated string.
22416962Smckusick  * Return pointer to character following last character copied.
22516962Smckusick  */
22616962Smckusick char *
22716962Smckusick copyline(from, to)
22816962Smckusick 	register char *from, *to;
22916962Smckusick {
23016962Smckusick 
23116962Smckusick 	while (*from != '\n')
23216962Smckusick 		*to++ = *from++;
23316962Smckusick 	*to++ = *from++;
23416962Smckusick 	*to = '\0';
23516962Smckusick 	return (from);
23616962Smckusick }
23716962Smckusick 
23816962Smckusick /*
23916962Smckusick  * open space for next line in the queue
24016962Smckusick  */
24116962Smckusick char *
24216962Smckusick newline()
24316962Smckusick {
24416962Smckusick 	bufhead = SUCC(bufhead);
24516962Smckusick 	if (bufhead == buftail) {
24616962Smckusick 		fputs(line[buftail], stdout);
24716962Smckusick 		buftail = SUCC(buftail);
24816962Smckusick 	}
24916962Smckusick 	return (line[bufhead]);
25016962Smckusick }
25116962Smckusick 
25216962Smckusick /*
25316962Smckusick  * empty the queue by printing out all its lines.
25416962Smckusick  */
25516962Smckusick emptyqueue()
25616962Smckusick {
25716962Smckusick 	while (buftail != bufhead) {
25816962Smckusick 		fputs(line[buftail], stdout);
25916962Smckusick 		buftail = SUCC(buftail);
26016962Smckusick 	}
26116962Smckusick }
26216962Smckusick 
26316962Smckusick /*
26416962Smckusick  * Compute the hash of a string.
26516962Smckusick  * Return the hash and the size of the item hashed
26616962Smckusick  */
26716962Smckusick hash(cp, size)
26816962Smckusick 	char *cp;
26916962Smckusick 	int *size;
27016962Smckusick {
27116962Smckusick 	register char *cp1 = cp;
27216978Smckusick 	register int hash = 0;
27316962Smckusick 
27416962Smckusick 	while (*cp1 && *cp1 != '\n')
27516962Smckusick 		hash += (int)*cp1++;
27616962Smckusick 	*size = cp1 - cp + 1;
27716962Smckusick 	hash &= HSHSIZ - 1;
27816978Smckusick 	return (hash);
27916962Smckusick }
280