xref: /csrg-svn/sys/vax/inline/main.c (revision 49438)
1*49438Sbostic /*-
2*49438Sbostic  * Copyright (c) 1984, 1986 The Regents of the University of California.
3*49438Sbostic  * All rights reserved.
4*49438Sbostic  *
5*49438Sbostic  * %sccs.include.redist.c%
623350Smckusick  */
716962Smckusick 
816962Smckusick #ifndef lint
923350Smckusick char copyright[] =
10*49438Sbostic "@(#) Copyright (c) 1984, 1986 The Regents of the University of California.\n\
1123350Smckusick  All rights reserved.\n";
12*49438Sbostic #endif /* not lint */
1316962Smckusick 
1423350Smckusick #ifndef lint
15*49438Sbostic static char sccsid[] = "@(#)main.c	7.2 (Berkeley) 05/08/91";
16*49438Sbostic #endif /* not lint */
1723350Smckusick 
1816962Smckusick #include <stdio.h>
1916962Smckusick #include <ctype.h>
2016963Smckusick #include "inline.h"
2116962Smckusick 
2216975Smckusick /*
2316975Smckusick  * These are the pattern tables to be loaded
2416975Smckusick  */
2527462Skarels struct pats *vax_inittables[] = {
2616975Smckusick 	language_ptab,
2716975Smckusick 	libc_ptab,
2827462Skarels 	vax_libc_ptab,
2916975Smckusick 	machine_ptab,
3027462Skarels 	vax_ptab,
3116975Smckusick 	0
3216975Smckusick };
3316975Smckusick 
3427462Skarels struct pats *vaxsubset_inittables[] = {
3527462Skarels 	language_ptab,
3627462Skarels 	libc_ptab,
3727462Skarels 	vaxsubset_libc_ptab,
3827462Skarels 	machine_ptab,
3927462Skarels 	vaxsubset_ptab,
4027462Skarels 	0
4127462Skarels };
4227462Skarels 
4316980Smckusick /*
4416980Smckusick  * Statistics collection
4516980Smckusick  */
4616980Smckusick struct stats {
4716980Smckusick 	int	attempted;	/* number of expansion attempts */
4816980Smckusick 	int	finished;	/* expansions done before end of basic block */
4916980Smckusick 	int	lostmodified;	/* mergers inhibited by intervening mod */
5016980Smckusick 	int	savedpush;	/* successful push/pop merger */
5116980Smckusick } stats;
5224395Smckusick 
5324395Smckusick extern char *strcpy();
5424395Smckusick 
5524395Smckusick char *whoami;
5624395Smckusick int lineno = 0;
5716980Smckusick int dflag;
5816980Smckusick 
main(argc,argv)5916962Smckusick main(argc, argv)
6016962Smckusick 	int argc;
6116962Smckusick 	char *argv[];
6216962Smckusick {
6316962Smckusick 	register char *cp, *lp;
6416962Smckusick 	register char *bufp;
6516978Smckusick 	register struct pats *pp, **php;
6616978Smckusick 	struct pats **tablep;
6716978Smckusick 	register struct inststoptbl *itp, **ithp;
6816962Smckusick 	int size;
6916962Smckusick 	extern char *index();
7027462Skarels 	int subset = 0;
7116962Smckusick 
7224395Smckusick 	whoami = argv[0];
7327899Skarels 	argc--;
7427899Skarels 	argv++;
7527899Skarels 	while (argc > 0 && argv[0][0] == '-') {
7627899Skarels 		switch(argv[0][1]) {
7727462Skarels 
7827462Skarels 		case 's':
7927462Skarels 			subset++;
8027462Skarels 			break;
8127462Skarels 
8227462Skarels 		case 'd':
8327462Skarels 			dflag++;
8427462Skarels 			break;
8527462Skarels 
8627462Skarels 		default:
8727462Skarels 			break;
8827462Skarels 		}
8927462Skarels 		argc--, argv++;
9027462Skarels 	}
9127899Skarels 	if (argc > 0)
9227899Skarels 		freopen(argv[0], "r", stdin);
9316962Smckusick 	if (argc > 1)
9427899Skarels 		freopen(argv[1], "w", stdout);
9516962Smckusick 	/*
9616978Smckusick 	 * Set up the hash table for the patterns.
9716962Smckusick 	 */
9827462Skarels 	if (subset)
9927462Skarels 		tablep = vaxsubset_inittables;
10027462Skarels 	else
10127462Skarels 		tablep = vax_inittables;
10227462Skarels 	for ( ; *tablep; tablep++) {
10316975Smckusick 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
10416978Smckusick 			php = &patshdr[hash(pp->name, &size)];
10516975Smckusick 			pp->size = size;
10616978Smckusick 			pp->next = *php;
10716978Smckusick 			*php = pp;
10816975Smckusick 		}
10916962Smckusick 	}
11016962Smckusick 	/*
11116978Smckusick 	 * Set up the hash table for the instruction stop table.
11216978Smckusick 	 */
11316978Smckusick 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
11416978Smckusick 		ithp = &inststoptblhdr[hash(itp->name, &size)];
11516978Smckusick 		itp->size = size;
11616978Smckusick 		itp->next = *ithp;
11716978Smckusick 		*ithp = itp;
11816978Smckusick 	}
11916978Smckusick 	/*
12016962Smckusick 	 * check each line and replace as appropriate
12116962Smckusick 	 */
12216962Smckusick 	buftail = bufhead = 0;
12316962Smckusick 	bufp = line[0];
12416962Smckusick 	while (fgets(bufp, MAXLINELEN, stdin)) {
12524395Smckusick 		lineno++;
12616962Smckusick 		lp = index(bufp, LABELCHAR);
12716962Smckusick 		if (lp != NULL) {
12818448Smckusick 			for (cp = bufp; cp < lp; cp++)
12918448Smckusick 				if (!isalnum(*cp))
13018448Smckusick 					break;
13118448Smckusick 			if (cp == lp) {
13218448Smckusick 				bufp = newline();
13318448Smckusick 				if (*++lp == '\n') {
13418448Smckusick 					emptyqueue();
13518448Smckusick 					continue;
13618448Smckusick 				}
13724395Smckusick 				(void) strcpy(bufp, lp);
13818448Smckusick 				*lp++ = '\n';
13918448Smckusick 				*lp = '\0';
14016962Smckusick 				emptyqueue();
14116962Smckusick 			}
14216962Smckusick 		}
14316962Smckusick 		for (cp = bufp; isspace(*cp); cp++)
14416962Smckusick 			/* void */;
14516962Smckusick 		if ((cp = doreplaceon(cp)) == 0) {
14616962Smckusick 			bufp = newline();
14716962Smckusick 			continue;
14816962Smckusick 		}
14916978Smckusick 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
15016962Smckusick 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
15124395Smckusick 				if (argcounterr(pp->args, countargs(bufp), pp->name)) {
15224395Smckusick 					pp = NULL;
15324395Smckusick 					break;
15424395Smckusick 				}
15516962Smckusick 				expand(pp->replace);
15616962Smckusick 				bufp = line[bufhead];
15716962Smckusick 				break;
15816962Smckusick 			}
15916962Smckusick 		}
16016962Smckusick 		if (!pp) {
16116962Smckusick 			emptyqueue();
16216962Smckusick 			fputs(bufp, stdout);
16316962Smckusick 		}
16416962Smckusick 	}
16516962Smckusick 	emptyqueue();
16616980Smckusick 	if (dflag)
16724395Smckusick 		fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
16824395Smckusick 			whoami,
16916980Smckusick 			"attempts", stats.attempted,
17016980Smckusick 			"finished", stats.finished,
17116980Smckusick 			"inhibited", stats.lostmodified,
17216980Smckusick 			"merged", stats.savedpush);
17316962Smckusick 	exit(0);
17416962Smckusick }
17516962Smckusick 
17616962Smckusick /*
17716962Smckusick  * Integrate an expansion into the assembly stream
17816962Smckusick  */
expand(replace)17916962Smckusick expand(replace)
18016962Smckusick 	char *replace;
18116962Smckusick {
18216962Smckusick 	register int curptr;
18316962Smckusick 	char *nextreplace, *argv[MAXARGS];
18417202Smckusick 	int argc, argreg, foundarg, mod = 0, args = 0;
18516962Smckusick 	char parsebuf[BUFSIZ];
18616962Smckusick 
18716980Smckusick 	stats.attempted++;
18816980Smckusick 	for (curptr = bufhead; ; ) {
18916962Smckusick 		nextreplace = copyline(replace, line[bufhead]);
19016962Smckusick 		argc = parseline(line[bufhead], argv, parsebuf);
19116962Smckusick 		argreg = nextarg(argc, argv);
19216962Smckusick 		if (argreg == -1)
19316962Smckusick 			break;
19417202Smckusick 		args++;
19516978Smckusick 		for (foundarg = 0; curptr != buftail; ) {
19616978Smckusick 			curptr = PRED(curptr);
19716962Smckusick 			argc = parseline(line[curptr], argv, parsebuf);
19816978Smckusick 			if (isendofblock(argc, argv))
19916962Smckusick 				break;
20016978Smckusick 			if (foundarg = ispusharg(argc, argv))
20116978Smckusick 				break;
20216962Smckusick 			mod |= 1 << modifies(argc, argv);
20316962Smckusick 		}
20416978Smckusick 		if (!foundarg)
20516962Smckusick 			break;
20616962Smckusick 		replace = nextreplace;
20716962Smckusick 		if (mod & (1 << argreg)) {
20816980Smckusick 			stats.lostmodified++;
20916978Smckusick 			if (curptr == buftail) {
21016978Smckusick 				(void)newline();
21116978Smckusick 				break;
21216978Smckusick 			}
21316962Smckusick 			(void)newline();
21416962Smckusick 		} else {
21516980Smckusick 			stats.savedpush++;
21616962Smckusick 			rewrite(line[curptr], argc, argv, argreg);
21716962Smckusick 			mod |= 1 << argreg;
21816962Smckusick 		}
21916962Smckusick 	}
22016980Smckusick 	if (argreg == -1)
22116980Smckusick 		stats.finished++;
22216962Smckusick 	emptyqueue();
22316962Smckusick 	fputs(replace, stdout);
22417202Smckusick 	cleanup(args);
22516962Smckusick }
22616962Smckusick 
22716962Smckusick /*
22816962Smckusick  * Parse a line of assembly language into opcode and arguments.
22916962Smckusick  */
parseline(linep,argv,linebuf)23016962Smckusick parseline(linep, argv, linebuf)
23116962Smckusick 	char *linep;
23216962Smckusick 	char *argv[];
23316962Smckusick 	char *linebuf;
23416962Smckusick {
23516962Smckusick 	register char *bufp = linebuf, *cp = linep;
23616962Smckusick 	register int argc = 0;
23716962Smckusick 
23816962Smckusick 	for (;;) {
23916962Smckusick 		/*
24016962Smckusick 		 * skip over white space
24116962Smckusick 		 */
24216962Smckusick 		while (isspace(*cp))
24316962Smckusick 			cp++;
24416962Smckusick 		if (*cp == '\0')
24516962Smckusick 			return (argc);
24616962Smckusick 		/*
24716962Smckusick 		 * copy argument
24816962Smckusick 		 */
24916962Smckusick 		if (argc == MAXARGS - 1) {
25016962Smckusick 			fprintf(stderr, "instruction too long->%s", linep);
25116962Smckusick 			return (argc);
25216962Smckusick 		}
25316962Smckusick 		argv[argc++] = bufp;
25416978Smckusick 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
25516962Smckusick 			*bufp++ = *cp++;
25616962Smckusick 		*bufp++ = '\0';
25716962Smckusick 		if (*cp == COMMENTCHAR)
25816962Smckusick 			return (argc);
25916978Smckusick 		if (*cp == ARGSEPCHAR)
26016962Smckusick 			cp++;
26116962Smckusick 	}
26216962Smckusick }
26316962Smckusick 
26416962Smckusick /*
26516978Smckusick  * Check for instructions that end a basic block.
26616978Smckusick  */
isendofblock(argc,argv)26716978Smckusick isendofblock(argc, argv)
26816978Smckusick 	int argc;
26916978Smckusick 	char *argv[];
27016978Smckusick {
27116978Smckusick 	register struct inststoptbl *itp;
27216978Smckusick 	int size;
27316978Smckusick 
27416978Smckusick 	if (argc == 0)
27516978Smckusick 		return (0);
27616978Smckusick 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
27716978Smckusick 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
27816978Smckusick 			return (1);
27916978Smckusick 	return (0);
28016978Smckusick }
28116978Smckusick 
28216978Smckusick /*
28316962Smckusick  * Copy a newline terminated string.
28416962Smckusick  * Return pointer to character following last character copied.
28516962Smckusick  */
28616962Smckusick char *
copyline(from,to)28716962Smckusick copyline(from, to)
28816962Smckusick 	register char *from, *to;
28916962Smckusick {
29016962Smckusick 
29116962Smckusick 	while (*from != '\n')
29216962Smckusick 		*to++ = *from++;
29316962Smckusick 	*to++ = *from++;
29416962Smckusick 	*to = '\0';
29516962Smckusick 	return (from);
29616962Smckusick }
29716962Smckusick 
29816962Smckusick /*
29924395Smckusick  * Check for a disparity between the number of arguments a function
30024395Smckusick  * is called with and the number which we expect to see.
30124395Smckusick  * If the error is unrecoverable, return 1, otherwise 0.
30224395Smckusick  */
argcounterr(args,callargs,name)30324395Smckusick argcounterr(args, callargs, name)
30424395Smckusick 	int args, callargs;
30524395Smckusick 	char *name;
30624395Smckusick {
30724395Smckusick 	register char *cp;
30824395Smckusick 	char namebuf[MAXLINELEN];
30924395Smckusick 
31024395Smckusick 	if (args == callargs)
31124395Smckusick 		return (0);
31224395Smckusick 	cp = strcpy(namebuf, name);
31324395Smckusick 	while (*cp != '\0' && *cp != '\n')
31424395Smckusick 		++cp;
31524395Smckusick 	if (*cp == '\n')
31624395Smckusick 		*cp = '\0';
31724395Smckusick 	if (callargs >= 0) {
31824395Smckusick 		fprintf(stderr,
31924395Smckusick 		"%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
32024395Smckusick 			whoami, callargs, args, namebuf, lineno);
32124395Smckusick 		return (1);
32224395Smckusick 	}
32324395Smckusick 	fprintf(stderr,
32424395Smckusick 		"%s: warning: can't verify arg count for '%s' at line %d\n",
32524395Smckusick 		whoami, namebuf, lineno);
32624395Smckusick 	return (0);
32724395Smckusick }
32824395Smckusick 
32924395Smckusick /*
33016962Smckusick  * open space for next line in the queue
33116962Smckusick  */
33216962Smckusick char *
newline()33316962Smckusick newline()
33416962Smckusick {
33516962Smckusick 	bufhead = SUCC(bufhead);
33616962Smckusick 	if (bufhead == buftail) {
33716962Smckusick 		fputs(line[buftail], stdout);
33816962Smckusick 		buftail = SUCC(buftail);
33916962Smckusick 	}
34016962Smckusick 	return (line[bufhead]);
34116962Smckusick }
34216962Smckusick 
34316962Smckusick /*
34416962Smckusick  * empty the queue by printing out all its lines.
34516962Smckusick  */
emptyqueue()34616962Smckusick emptyqueue()
34716962Smckusick {
34816962Smckusick 	while (buftail != bufhead) {
34916962Smckusick 		fputs(line[buftail], stdout);
35016962Smckusick 		buftail = SUCC(buftail);
35116962Smckusick 	}
35216962Smckusick }
35316962Smckusick 
35416962Smckusick /*
35516962Smckusick  * Compute the hash of a string.
35616962Smckusick  * Return the hash and the size of the item hashed
35716962Smckusick  */
hash(cp,size)35816962Smckusick hash(cp, size)
35916962Smckusick 	char *cp;
36016962Smckusick 	int *size;
36116962Smckusick {
36216962Smckusick 	register char *cp1 = cp;
36316978Smckusick 	register int hash = 0;
36416962Smckusick 
36516962Smckusick 	while (*cp1 && *cp1 != '\n')
36616962Smckusick 		hash += (int)*cp1++;
36716962Smckusick 	*size = cp1 - cp + 1;
36816962Smckusick 	hash &= HSHSIZ - 1;
36916978Smckusick 	return (hash);
37016962Smckusick }
371