xref: /csrg-svn/sys/vax/inline/main.c (revision 23350)
1*23350Smckusick /*
2*23350Smckusick  * Copyright (c) 1984 Regents of the University of California.
3*23350Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*23350Smckusick  * specifies the terms and conditions for redistribution.
5*23350Smckusick  */
616962Smckusick 
716962Smckusick #ifndef lint
8*23350Smckusick char copyright[] =
9*23350Smckusick "@(#) Copyright (c) 1984 Regents of the University of California.\n\
10*23350Smckusick  All rights reserved.\n";
1116962Smckusick #endif not lint
1216962Smckusick 
13*23350Smckusick #ifndef lint
14*23350Smckusick static char sccsid[] = "@(#)main.c	1.8 (Berkeley) 06/08/85";
15*23350Smckusick #endif not lint
16*23350Smckusick 
1716962Smckusick #include <stdio.h>
1816962Smckusick #include <ctype.h>
1916963Smckusick #include "inline.h"
2016962Smckusick 
2116975Smckusick /*
2216975Smckusick  * These are the pattern tables to be loaded
2316975Smckusick  */
2416975Smckusick struct pats *inittables[] = {
2516975Smckusick 	language_ptab,
2616975Smckusick 	libc_ptab,
2716975Smckusick 	machine_ptab,
2816975Smckusick 	0
2916975Smckusick };
3016975Smckusick 
3116980Smckusick /*
3216980Smckusick  * Statistics collection
3316980Smckusick  */
3416980Smckusick struct stats {
3516980Smckusick 	int	attempted;	/* number of expansion attempts */
3616980Smckusick 	int	finished;	/* expansions done before end of basic block */
3716980Smckusick 	int	lostmodified;	/* mergers inhibited by intervening mod */
3816980Smckusick 	int	savedpush;	/* successful push/pop merger */
3916980Smckusick } stats;
4016980Smckusick int dflag;
4116980Smckusick 
4216962Smckusick main(argc, argv)
4316962Smckusick 	int argc;
4416962Smckusick 	char *argv[];
4516962Smckusick {
4616962Smckusick 	register char *cp, *lp;
4716962Smckusick 	register char *bufp;
4816978Smckusick 	register struct pats *pp, **php;
4916978Smckusick 	struct pats **tablep;
5016978Smckusick 	register struct inststoptbl *itp, **ithp;
5116962Smckusick 	int size;
5216962Smckusick 	extern char *index();
5316962Smckusick 
5416980Smckusick 	if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
5516980Smckusick 		dflag++, argc--, argv++;
5616962Smckusick 	if (argc > 1)
5716962Smckusick 		freopen(argv[1], "r", stdin);
5816962Smckusick 	if (argc > 2)
5916962Smckusick 		freopen(argv[2], "w", stdout);
6016962Smckusick 	/*
6116978Smckusick 	 * Set up the hash table for the patterns.
6216962Smckusick 	 */
6316975Smckusick 	for (tablep = inittables; *tablep; tablep++) {
6416975Smckusick 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
6516978Smckusick 			php = &patshdr[hash(pp->name, &size)];
6616975Smckusick 			pp->size = size;
6716978Smckusick 			pp->next = *php;
6816978Smckusick 			*php = pp;
6916975Smckusick 		}
7016962Smckusick 	}
7116962Smckusick 	/*
7216978Smckusick 	 * Set up the hash table for the instruction stop table.
7316978Smckusick 	 */
7416978Smckusick 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
7516978Smckusick 		ithp = &inststoptblhdr[hash(itp->name, &size)];
7616978Smckusick 		itp->size = size;
7716978Smckusick 		itp->next = *ithp;
7816978Smckusick 		*ithp = itp;
7916978Smckusick 	}
8016978Smckusick 	/*
8116962Smckusick 	 * check each line and replace as appropriate
8216962Smckusick 	 */
8316962Smckusick 	buftail = bufhead = 0;
8416962Smckusick 	bufp = line[0];
8516962Smckusick 	while (fgets(bufp, MAXLINELEN, stdin)) {
8616962Smckusick 		lp = index(bufp, LABELCHAR);
8716962Smckusick 		if (lp != NULL) {
8818448Smckusick 			for (cp = bufp; cp < lp; cp++)
8918448Smckusick 				if (!isalnum(*cp))
9018448Smckusick 					break;
9118448Smckusick 			if (cp == lp) {
9218448Smckusick 				bufp = newline();
9318448Smckusick 				if (*++lp == '\n') {
9418448Smckusick 					emptyqueue();
9518448Smckusick 					continue;
9618448Smckusick 				}
9718448Smckusick 				strcpy(bufp, lp);
9818448Smckusick 				*lp++ = '\n';
9918448Smckusick 				*lp = '\0';
10016962Smckusick 				emptyqueue();
10116962Smckusick 			}
10216962Smckusick 		}
10316962Smckusick 		for (cp = bufp; isspace(*cp); cp++)
10416962Smckusick 			/* void */;
10516962Smckusick 		if ((cp = doreplaceon(cp)) == 0) {
10616962Smckusick 			bufp = newline();
10716962Smckusick 			continue;
10816962Smckusick 		}
10916978Smckusick 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
11016962Smckusick 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
11116962Smckusick 				expand(pp->replace);
11216962Smckusick 				bufp = line[bufhead];
11316962Smckusick 				break;
11416962Smckusick 			}
11516962Smckusick 		}
11616962Smckusick 		if (!pp) {
11716962Smckusick 			emptyqueue();
11816962Smckusick 			fputs(bufp, stdout);
11916962Smckusick 		}
12016962Smckusick 	}
12116962Smckusick 	emptyqueue();
12216980Smckusick 	if (dflag)
12316980Smckusick 		fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n",
12416980Smckusick 			"attempts", stats.attempted,
12516980Smckusick 			"finished", stats.finished,
12616980Smckusick 			"inhibited", stats.lostmodified,
12716980Smckusick 			"merged", stats.savedpush);
12816962Smckusick 	exit(0);
12916962Smckusick }
13016962Smckusick 
13116962Smckusick /*
13216962Smckusick  * Integrate an expansion into the assembly stream
13316962Smckusick  */
13416962Smckusick expand(replace)
13516962Smckusick 	char *replace;
13616962Smckusick {
13716962Smckusick 	register int curptr;
13816962Smckusick 	char *nextreplace, *argv[MAXARGS];
13917202Smckusick 	int argc, argreg, foundarg, mod = 0, args = 0;
14016962Smckusick 	char parsebuf[BUFSIZ];
14116962Smckusick 
14216980Smckusick 	stats.attempted++;
14316980Smckusick 	for (curptr = bufhead; ; ) {
14416962Smckusick 		nextreplace = copyline(replace, line[bufhead]);
14516962Smckusick 		argc = parseline(line[bufhead], argv, parsebuf);
14616962Smckusick 		argreg = nextarg(argc, argv);
14716962Smckusick 		if (argreg == -1)
14816962Smckusick 			break;
14917202Smckusick 		args++;
15016978Smckusick 		for (foundarg = 0; curptr != buftail; ) {
15116978Smckusick 			curptr = PRED(curptr);
15216962Smckusick 			argc = parseline(line[curptr], argv, parsebuf);
15316978Smckusick 			if (isendofblock(argc, argv))
15416962Smckusick 				break;
15516978Smckusick 			if (foundarg = ispusharg(argc, argv))
15616978Smckusick 				break;
15716962Smckusick 			mod |= 1 << modifies(argc, argv);
15816962Smckusick 		}
15916978Smckusick 		if (!foundarg)
16016962Smckusick 			break;
16116962Smckusick 		replace = nextreplace;
16216962Smckusick 		if (mod & (1 << argreg)) {
16316980Smckusick 			stats.lostmodified++;
16416978Smckusick 			if (curptr == buftail) {
16516978Smckusick 				(void)newline();
16616978Smckusick 				break;
16716978Smckusick 			}
16816962Smckusick 			(void)newline();
16916962Smckusick 		} else {
17016980Smckusick 			stats.savedpush++;
17116962Smckusick 			rewrite(line[curptr], argc, argv, argreg);
17216962Smckusick 			mod |= 1 << argreg;
17316962Smckusick 		}
17416962Smckusick 	}
17516980Smckusick 	if (argreg == -1)
17616980Smckusick 		stats.finished++;
17716962Smckusick 	emptyqueue();
17816962Smckusick 	fputs(replace, stdout);
17917202Smckusick 	cleanup(args);
18016962Smckusick }
18116962Smckusick 
18216962Smckusick /*
18316962Smckusick  * Parse a line of assembly language into opcode and arguments.
18416962Smckusick  */
18516962Smckusick parseline(linep, argv, linebuf)
18616962Smckusick 	char *linep;
18716962Smckusick 	char *argv[];
18816962Smckusick 	char *linebuf;
18916962Smckusick {
19016962Smckusick 	register char *bufp = linebuf, *cp = linep;
19116962Smckusick 	register int argc = 0;
19216962Smckusick 
19316962Smckusick 	for (;;) {
19416962Smckusick 		/*
19516962Smckusick 		 * skip over white space
19616962Smckusick 		 */
19716962Smckusick 		while (isspace(*cp))
19816962Smckusick 			cp++;
19916962Smckusick 		if (*cp == '\0')
20016962Smckusick 			return (argc);
20116962Smckusick 		/*
20216962Smckusick 		 * copy argument
20316962Smckusick 		 */
20416962Smckusick 		if (argc == MAXARGS - 1) {
20516962Smckusick 			fprintf(stderr, "instruction too long->%s", linep);
20616962Smckusick 			return (argc);
20716962Smckusick 		}
20816962Smckusick 		argv[argc++] = bufp;
20916978Smckusick 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
21016962Smckusick 			*bufp++ = *cp++;
21116962Smckusick 		*bufp++ = '\0';
21216962Smckusick 		if (*cp == COMMENTCHAR)
21316962Smckusick 			return (argc);
21416978Smckusick 		if (*cp == ARGSEPCHAR)
21516962Smckusick 			cp++;
21616962Smckusick 	}
21716962Smckusick }
21816962Smckusick 
21916962Smckusick /*
22016978Smckusick  * Check for instructions that end a basic block.
22116978Smckusick  */
22216978Smckusick isendofblock(argc, argv)
22316978Smckusick 	int argc;
22416978Smckusick 	char *argv[];
22516978Smckusick {
22616978Smckusick 	register struct inststoptbl *itp;
22716978Smckusick 	int size;
22816978Smckusick 
22916978Smckusick 	if (argc == 0)
23016978Smckusick 		return (0);
23116978Smckusick 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
23216978Smckusick 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
23316978Smckusick 			return (1);
23416978Smckusick 	return (0);
23516978Smckusick }
23616978Smckusick 
23716978Smckusick /*
23816962Smckusick  * Copy a newline terminated string.
23916962Smckusick  * Return pointer to character following last character copied.
24016962Smckusick  */
24116962Smckusick char *
24216962Smckusick copyline(from, to)
24316962Smckusick 	register char *from, *to;
24416962Smckusick {
24516962Smckusick 
24616962Smckusick 	while (*from != '\n')
24716962Smckusick 		*to++ = *from++;
24816962Smckusick 	*to++ = *from++;
24916962Smckusick 	*to = '\0';
25016962Smckusick 	return (from);
25116962Smckusick }
25216962Smckusick 
25316962Smckusick /*
25416962Smckusick  * open space for next line in the queue
25516962Smckusick  */
25616962Smckusick char *
25716962Smckusick newline()
25816962Smckusick {
25916962Smckusick 	bufhead = SUCC(bufhead);
26016962Smckusick 	if (bufhead == buftail) {
26116962Smckusick 		fputs(line[buftail], stdout);
26216962Smckusick 		buftail = SUCC(buftail);
26316962Smckusick 	}
26416962Smckusick 	return (line[bufhead]);
26516962Smckusick }
26616962Smckusick 
26716962Smckusick /*
26816962Smckusick  * empty the queue by printing out all its lines.
26916962Smckusick  */
27016962Smckusick emptyqueue()
27116962Smckusick {
27216962Smckusick 	while (buftail != bufhead) {
27316962Smckusick 		fputs(line[buftail], stdout);
27416962Smckusick 		buftail = SUCC(buftail);
27516962Smckusick 	}
27616962Smckusick }
27716962Smckusick 
27816962Smckusick /*
27916962Smckusick  * Compute the hash of a string.
28016962Smckusick  * Return the hash and the size of the item hashed
28116962Smckusick  */
28216962Smckusick hash(cp, size)
28316962Smckusick 	char *cp;
28416962Smckusick 	int *size;
28516962Smckusick {
28616962Smckusick 	register char *cp1 = cp;
28716978Smckusick 	register int hash = 0;
28816962Smckusick 
28916962Smckusick 	while (*cp1 && *cp1 != '\n')
29016962Smckusick 		hash += (int)*cp1++;
29116962Smckusick 	*size = cp1 - cp + 1;
29216962Smckusick 	hash &= HSHSIZ - 1;
29316978Smckusick 	return (hash);
29416962Smckusick }
295