xref: /csrg-svn/sys/vax/inline/main.c (revision 27462)
123350Smckusick /*
223350Smckusick  * Copyright (c) 1984 Regents of the University of California.
323350Smckusick  * All rights reserved.  The Berkeley software License Agreement
423350Smckusick  * specifies the terms and conditions for redistribution.
523350Smckusick  */
616962Smckusick 
716962Smckusick #ifndef lint
823350Smckusick char copyright[] =
923350Smckusick "@(#) Copyright (c) 1984 Regents of the University of California.\n\
1023350Smckusick  All rights reserved.\n";
1116962Smckusick #endif not lint
1216962Smckusick 
1323350Smckusick #ifndef lint
14*27462Skarels static char sccsid[] = "@(#)main.c	1.10 (Berkeley) 04/27/86";
1523350Smckusick #endif not lint
1623350Smckusick 
1716962Smckusick #include <stdio.h>
1816962Smckusick #include <ctype.h>
1916963Smckusick #include "inline.h"
2016962Smckusick 
2116975Smckusick /*
2216975Smckusick  * These are the pattern tables to be loaded
2316975Smckusick  */
24*27462Skarels struct pats *vax_inittables[] = {
2516975Smckusick 	language_ptab,
2616975Smckusick 	libc_ptab,
27*27462Skarels 	vax_libc_ptab,
2816975Smckusick 	machine_ptab,
29*27462Skarels 	vax_ptab,
3016975Smckusick 	0
3116975Smckusick };
3216975Smckusick 
33*27462Skarels struct pats *vaxsubset_inittables[] = {
34*27462Skarels 	language_ptab,
35*27462Skarels 	libc_ptab,
36*27462Skarels 	vaxsubset_libc_ptab,
37*27462Skarels 	machine_ptab,
38*27462Skarels 	vaxsubset_ptab,
39*27462Skarels 	0
40*27462Skarels };
41*27462Skarels 
4216980Smckusick /*
4316980Smckusick  * Statistics collection
4416980Smckusick  */
4516980Smckusick struct stats {
4616980Smckusick 	int	attempted;	/* number of expansion attempts */
4716980Smckusick 	int	finished;	/* expansions done before end of basic block */
4816980Smckusick 	int	lostmodified;	/* mergers inhibited by intervening mod */
4916980Smckusick 	int	savedpush;	/* successful push/pop merger */
5016980Smckusick } stats;
5124395Smckusick 
5224395Smckusick extern char *strcpy();
5324395Smckusick 
5424395Smckusick char *whoami;
5524395Smckusick int lineno = 0;
5616980Smckusick int dflag;
5716980Smckusick 
5816962Smckusick main(argc, argv)
5916962Smckusick 	int argc;
6016962Smckusick 	char *argv[];
6116962Smckusick {
6216962Smckusick 	register char *cp, *lp;
6316962Smckusick 	register char *bufp;
6416978Smckusick 	register struct pats *pp, **php;
6516978Smckusick 	struct pats **tablep;
6616978Smckusick 	register struct inststoptbl *itp, **ithp;
6716962Smckusick 	int size;
6816962Smckusick 	extern char *index();
69*27462Skarels 	int subset = 0;
7016962Smckusick 
7124395Smckusick 	whoami = argv[0];
72*27462Skarels 	while (argc > 0 && argv[0][0] == '-') {
73*27462Skarels 		switch(argv[0][1]) {
74*27462Skarels 
75*27462Skarels 		case 's':
76*27462Skarels 			subset++;
77*27462Skarels 			break;
78*27462Skarels 
79*27462Skarels 		case 'd':
80*27462Skarels 			dflag++;
81*27462Skarels 			break;
82*27462Skarels 
83*27462Skarels 		default:
84*27462Skarels 			break;
85*27462Skarels 		}
86*27462Skarels 		argc--, argv++;
87*27462Skarels 	}
8816962Smckusick 	if (argc > 1)
8916962Smckusick 		freopen(argv[1], "r", stdin);
9016962Smckusick 	if (argc > 2)
9116962Smckusick 		freopen(argv[2], "w", stdout);
9216962Smckusick 	/*
9316978Smckusick 	 * Set up the hash table for the patterns.
9416962Smckusick 	 */
95*27462Skarels 	if (subset)
96*27462Skarels 		tablep = vaxsubset_inittables;
97*27462Skarels 	else
98*27462Skarels 		tablep = vax_inittables;
99*27462Skarels 	for ( ; *tablep; tablep++) {
10016975Smckusick 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
10116978Smckusick 			php = &patshdr[hash(pp->name, &size)];
10216975Smckusick 			pp->size = size;
10316978Smckusick 			pp->next = *php;
10416978Smckusick 			*php = pp;
10516975Smckusick 		}
10616962Smckusick 	}
10716962Smckusick 	/*
10816978Smckusick 	 * Set up the hash table for the instruction stop table.
10916978Smckusick 	 */
11016978Smckusick 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
11116978Smckusick 		ithp = &inststoptblhdr[hash(itp->name, &size)];
11216978Smckusick 		itp->size = size;
11316978Smckusick 		itp->next = *ithp;
11416978Smckusick 		*ithp = itp;
11516978Smckusick 	}
11616978Smckusick 	/*
11716962Smckusick 	 * check each line and replace as appropriate
11816962Smckusick 	 */
11916962Smckusick 	buftail = bufhead = 0;
12016962Smckusick 	bufp = line[0];
12116962Smckusick 	while (fgets(bufp, MAXLINELEN, stdin)) {
12224395Smckusick 		lineno++;
12316962Smckusick 		lp = index(bufp, LABELCHAR);
12416962Smckusick 		if (lp != NULL) {
12518448Smckusick 			for (cp = bufp; cp < lp; cp++)
12618448Smckusick 				if (!isalnum(*cp))
12718448Smckusick 					break;
12818448Smckusick 			if (cp == lp) {
12918448Smckusick 				bufp = newline();
13018448Smckusick 				if (*++lp == '\n') {
13118448Smckusick 					emptyqueue();
13218448Smckusick 					continue;
13318448Smckusick 				}
13424395Smckusick 				(void) strcpy(bufp, lp);
13518448Smckusick 				*lp++ = '\n';
13618448Smckusick 				*lp = '\0';
13716962Smckusick 				emptyqueue();
13816962Smckusick 			}
13916962Smckusick 		}
14016962Smckusick 		for (cp = bufp; isspace(*cp); cp++)
14116962Smckusick 			/* void */;
14216962Smckusick 		if ((cp = doreplaceon(cp)) == 0) {
14316962Smckusick 			bufp = newline();
14416962Smckusick 			continue;
14516962Smckusick 		}
14616978Smckusick 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
14716962Smckusick 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
14824395Smckusick 				if (argcounterr(pp->args, countargs(bufp), pp->name)) {
14924395Smckusick 					pp = NULL;
15024395Smckusick 					break;
15124395Smckusick 				}
15216962Smckusick 				expand(pp->replace);
15316962Smckusick 				bufp = line[bufhead];
15416962Smckusick 				break;
15516962Smckusick 			}
15616962Smckusick 		}
15716962Smckusick 		if (!pp) {
15816962Smckusick 			emptyqueue();
15916962Smckusick 			fputs(bufp, stdout);
16016962Smckusick 		}
16116962Smckusick 	}
16216962Smckusick 	emptyqueue();
16316980Smckusick 	if (dflag)
16424395Smckusick 		fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
16524395Smckusick 			whoami,
16616980Smckusick 			"attempts", stats.attempted,
16716980Smckusick 			"finished", stats.finished,
16816980Smckusick 			"inhibited", stats.lostmodified,
16916980Smckusick 			"merged", stats.savedpush);
17016962Smckusick 	exit(0);
17116962Smckusick }
17216962Smckusick 
17316962Smckusick /*
17416962Smckusick  * Integrate an expansion into the assembly stream
17516962Smckusick  */
17616962Smckusick expand(replace)
17716962Smckusick 	char *replace;
17816962Smckusick {
17916962Smckusick 	register int curptr;
18016962Smckusick 	char *nextreplace, *argv[MAXARGS];
18117202Smckusick 	int argc, argreg, foundarg, mod = 0, args = 0;
18216962Smckusick 	char parsebuf[BUFSIZ];
18316962Smckusick 
18416980Smckusick 	stats.attempted++;
18516980Smckusick 	for (curptr = bufhead; ; ) {
18616962Smckusick 		nextreplace = copyline(replace, line[bufhead]);
18716962Smckusick 		argc = parseline(line[bufhead], argv, parsebuf);
18816962Smckusick 		argreg = nextarg(argc, argv);
18916962Smckusick 		if (argreg == -1)
19016962Smckusick 			break;
19117202Smckusick 		args++;
19216978Smckusick 		for (foundarg = 0; curptr != buftail; ) {
19316978Smckusick 			curptr = PRED(curptr);
19416962Smckusick 			argc = parseline(line[curptr], argv, parsebuf);
19516978Smckusick 			if (isendofblock(argc, argv))
19616962Smckusick 				break;
19716978Smckusick 			if (foundarg = ispusharg(argc, argv))
19816978Smckusick 				break;
19916962Smckusick 			mod |= 1 << modifies(argc, argv);
20016962Smckusick 		}
20116978Smckusick 		if (!foundarg)
20216962Smckusick 			break;
20316962Smckusick 		replace = nextreplace;
20416962Smckusick 		if (mod & (1 << argreg)) {
20516980Smckusick 			stats.lostmodified++;
20616978Smckusick 			if (curptr == buftail) {
20716978Smckusick 				(void)newline();
20816978Smckusick 				break;
20916978Smckusick 			}
21016962Smckusick 			(void)newline();
21116962Smckusick 		} else {
21216980Smckusick 			stats.savedpush++;
21316962Smckusick 			rewrite(line[curptr], argc, argv, argreg);
21416962Smckusick 			mod |= 1 << argreg;
21516962Smckusick 		}
21616962Smckusick 	}
21716980Smckusick 	if (argreg == -1)
21816980Smckusick 		stats.finished++;
21916962Smckusick 	emptyqueue();
22016962Smckusick 	fputs(replace, stdout);
22117202Smckusick 	cleanup(args);
22216962Smckusick }
22316962Smckusick 
22416962Smckusick /*
22516962Smckusick  * Parse a line of assembly language into opcode and arguments.
22616962Smckusick  */
22716962Smckusick parseline(linep, argv, linebuf)
22816962Smckusick 	char *linep;
22916962Smckusick 	char *argv[];
23016962Smckusick 	char *linebuf;
23116962Smckusick {
23216962Smckusick 	register char *bufp = linebuf, *cp = linep;
23316962Smckusick 	register int argc = 0;
23416962Smckusick 
23516962Smckusick 	for (;;) {
23616962Smckusick 		/*
23716962Smckusick 		 * skip over white space
23816962Smckusick 		 */
23916962Smckusick 		while (isspace(*cp))
24016962Smckusick 			cp++;
24116962Smckusick 		if (*cp == '\0')
24216962Smckusick 			return (argc);
24316962Smckusick 		/*
24416962Smckusick 		 * copy argument
24516962Smckusick 		 */
24616962Smckusick 		if (argc == MAXARGS - 1) {
24716962Smckusick 			fprintf(stderr, "instruction too long->%s", linep);
24816962Smckusick 			return (argc);
24916962Smckusick 		}
25016962Smckusick 		argv[argc++] = bufp;
25116978Smckusick 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
25216962Smckusick 			*bufp++ = *cp++;
25316962Smckusick 		*bufp++ = '\0';
25416962Smckusick 		if (*cp == COMMENTCHAR)
25516962Smckusick 			return (argc);
25616978Smckusick 		if (*cp == ARGSEPCHAR)
25716962Smckusick 			cp++;
25816962Smckusick 	}
25916962Smckusick }
26016962Smckusick 
26116962Smckusick /*
26216978Smckusick  * Check for instructions that end a basic block.
26316978Smckusick  */
26416978Smckusick isendofblock(argc, argv)
26516978Smckusick 	int argc;
26616978Smckusick 	char *argv[];
26716978Smckusick {
26816978Smckusick 	register struct inststoptbl *itp;
26916978Smckusick 	int size;
27016978Smckusick 
27116978Smckusick 	if (argc == 0)
27216978Smckusick 		return (0);
27316978Smckusick 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
27416978Smckusick 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
27516978Smckusick 			return (1);
27616978Smckusick 	return (0);
27716978Smckusick }
27816978Smckusick 
27916978Smckusick /*
28016962Smckusick  * Copy a newline terminated string.
28116962Smckusick  * Return pointer to character following last character copied.
28216962Smckusick  */
28316962Smckusick char *
28416962Smckusick copyline(from, to)
28516962Smckusick 	register char *from, *to;
28616962Smckusick {
28716962Smckusick 
28816962Smckusick 	while (*from != '\n')
28916962Smckusick 		*to++ = *from++;
29016962Smckusick 	*to++ = *from++;
29116962Smckusick 	*to = '\0';
29216962Smckusick 	return (from);
29316962Smckusick }
29416962Smckusick 
29516962Smckusick /*
29624395Smckusick  * Check for a disparity between the number of arguments a function
29724395Smckusick  * is called with and the number which we expect to see.
29824395Smckusick  * If the error is unrecoverable, return 1, otherwise 0.
29924395Smckusick  */
30024395Smckusick argcounterr(args, callargs, name)
30124395Smckusick 	int args, callargs;
30224395Smckusick 	char *name;
30324395Smckusick {
30424395Smckusick 	register char *cp;
30524395Smckusick 	char namebuf[MAXLINELEN];
30624395Smckusick 
30724395Smckusick 	if (args == callargs)
30824395Smckusick 		return (0);
30924395Smckusick 	cp = strcpy(namebuf, name);
31024395Smckusick 	while (*cp != '\0' && *cp != '\n')
31124395Smckusick 		++cp;
31224395Smckusick 	if (*cp == '\n')
31324395Smckusick 		*cp = '\0';
31424395Smckusick 	if (callargs >= 0) {
31524395Smckusick 		fprintf(stderr,
31624395Smckusick 		"%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
31724395Smckusick 			whoami, callargs, args, namebuf, lineno);
31824395Smckusick 		return (1);
31924395Smckusick 	}
32024395Smckusick 	fprintf(stderr,
32124395Smckusick 		"%s: warning: can't verify arg count for '%s' at line %d\n",
32224395Smckusick 		whoami, namebuf, lineno);
32324395Smckusick 	return (0);
32424395Smckusick }
32524395Smckusick 
32624395Smckusick /*
32716962Smckusick  * open space for next line in the queue
32816962Smckusick  */
32916962Smckusick char *
33016962Smckusick newline()
33116962Smckusick {
33216962Smckusick 	bufhead = SUCC(bufhead);
33316962Smckusick 	if (bufhead == buftail) {
33416962Smckusick 		fputs(line[buftail], stdout);
33516962Smckusick 		buftail = SUCC(buftail);
33616962Smckusick 	}
33716962Smckusick 	return (line[bufhead]);
33816962Smckusick }
33916962Smckusick 
34016962Smckusick /*
34116962Smckusick  * empty the queue by printing out all its lines.
34216962Smckusick  */
34316962Smckusick emptyqueue()
34416962Smckusick {
34516962Smckusick 	while (buftail != bufhead) {
34616962Smckusick 		fputs(line[buftail], stdout);
34716962Smckusick 		buftail = SUCC(buftail);
34816962Smckusick 	}
34916962Smckusick }
35016962Smckusick 
35116962Smckusick /*
35216962Smckusick  * Compute the hash of a string.
35316962Smckusick  * Return the hash and the size of the item hashed
35416962Smckusick  */
35516962Smckusick hash(cp, size)
35616962Smckusick 	char *cp;
35716962Smckusick 	int *size;
35816962Smckusick {
35916962Smckusick 	register char *cp1 = cp;
36016978Smckusick 	register int hash = 0;
36116962Smckusick 
36216962Smckusick 	while (*cp1 && *cp1 != '\n')
36316962Smckusick 		hash += (int)*cp1++;
36416962Smckusick 	*size = cp1 - cp + 1;
36516962Smckusick 	hash &= HSHSIZ - 1;
36616978Smckusick 	return (hash);
36716962Smckusick }
368