xref: /csrg-svn/sys/vax/inline/main.c (revision 27899)
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*27899Skarels static char sccsid[] = "@(#)main.c	1.12 (Berkeley) 05/08/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  */
2427462Skarels struct pats *vax_inittables[] = {
2516975Smckusick 	language_ptab,
2616975Smckusick 	libc_ptab,
2727462Skarels 	vax_libc_ptab,
2816975Smckusick 	machine_ptab,
2927462Skarels 	vax_ptab,
3016975Smckusick 	0
3116975Smckusick };
3216975Smckusick 
3327462Skarels struct pats *vaxsubset_inittables[] = {
3427462Skarels 	language_ptab,
3527462Skarels 	libc_ptab,
3627462Skarels 	vaxsubset_libc_ptab,
3727462Skarels 	machine_ptab,
3827462Skarels 	vaxsubset_ptab,
3927462Skarels 	0
4027462Skarels };
4127462Skarels 
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();
6927462Skarels 	int subset = 0;
7016962Smckusick 
7124395Smckusick 	whoami = argv[0];
72*27899Skarels 	argc--;
73*27899Skarels 	argv++;
74*27899Skarels 	while (argc > 0 && argv[0][0] == '-') {
75*27899Skarels 		switch(argv[0][1]) {
7627462Skarels 
7727462Skarels 		case 's':
7827462Skarels 			subset++;
7927462Skarels 			break;
8027462Skarels 
8127462Skarels 		case 'd':
8227462Skarels 			dflag++;
8327462Skarels 			break;
8427462Skarels 
8527462Skarels 		default:
8627462Skarels 			break;
8727462Skarels 		}
8827462Skarels 		argc--, argv++;
8927462Skarels 	}
90*27899Skarels 	if (argc > 0)
91*27899Skarels 		freopen(argv[0], "r", stdin);
9216962Smckusick 	if (argc > 1)
93*27899Skarels 		freopen(argv[1], "w", stdout);
9416962Smckusick 	/*
9516978Smckusick 	 * Set up the hash table for the patterns.
9616962Smckusick 	 */
9727462Skarels 	if (subset)
9827462Skarels 		tablep = vaxsubset_inittables;
9927462Skarels 	else
10027462Skarels 		tablep = vax_inittables;
10127462Skarels 	for ( ; *tablep; tablep++) {
10216975Smckusick 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
10316978Smckusick 			php = &patshdr[hash(pp->name, &size)];
10416975Smckusick 			pp->size = size;
10516978Smckusick 			pp->next = *php;
10616978Smckusick 			*php = pp;
10716975Smckusick 		}
10816962Smckusick 	}
10916962Smckusick 	/*
11016978Smckusick 	 * Set up the hash table for the instruction stop table.
11116978Smckusick 	 */
11216978Smckusick 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
11316978Smckusick 		ithp = &inststoptblhdr[hash(itp->name, &size)];
11416978Smckusick 		itp->size = size;
11516978Smckusick 		itp->next = *ithp;
11616978Smckusick 		*ithp = itp;
11716978Smckusick 	}
11816978Smckusick 	/*
11916962Smckusick 	 * check each line and replace as appropriate
12016962Smckusick 	 */
12116962Smckusick 	buftail = bufhead = 0;
12216962Smckusick 	bufp = line[0];
12316962Smckusick 	while (fgets(bufp, MAXLINELEN, stdin)) {
12424395Smckusick 		lineno++;
12516962Smckusick 		lp = index(bufp, LABELCHAR);
12616962Smckusick 		if (lp != NULL) {
12718448Smckusick 			for (cp = bufp; cp < lp; cp++)
12818448Smckusick 				if (!isalnum(*cp))
12918448Smckusick 					break;
13018448Smckusick 			if (cp == lp) {
13118448Smckusick 				bufp = newline();
13218448Smckusick 				if (*++lp == '\n') {
13318448Smckusick 					emptyqueue();
13418448Smckusick 					continue;
13518448Smckusick 				}
13624395Smckusick 				(void) strcpy(bufp, lp);
13718448Smckusick 				*lp++ = '\n';
13818448Smckusick 				*lp = '\0';
13916962Smckusick 				emptyqueue();
14016962Smckusick 			}
14116962Smckusick 		}
14216962Smckusick 		for (cp = bufp; isspace(*cp); cp++)
14316962Smckusick 			/* void */;
14416962Smckusick 		if ((cp = doreplaceon(cp)) == 0) {
14516962Smckusick 			bufp = newline();
14616962Smckusick 			continue;
14716962Smckusick 		}
14816978Smckusick 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
14916962Smckusick 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
15024395Smckusick 				if (argcounterr(pp->args, countargs(bufp), pp->name)) {
15124395Smckusick 					pp = NULL;
15224395Smckusick 					break;
15324395Smckusick 				}
15416962Smckusick 				expand(pp->replace);
15516962Smckusick 				bufp = line[bufhead];
15616962Smckusick 				break;
15716962Smckusick 			}
15816962Smckusick 		}
15916962Smckusick 		if (!pp) {
16016962Smckusick 			emptyqueue();
16116962Smckusick 			fputs(bufp, stdout);
16216962Smckusick 		}
16316962Smckusick 	}
16416962Smckusick 	emptyqueue();
16516980Smckusick 	if (dflag)
16624395Smckusick 		fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
16724395Smckusick 			whoami,
16816980Smckusick 			"attempts", stats.attempted,
16916980Smckusick 			"finished", stats.finished,
17016980Smckusick 			"inhibited", stats.lostmodified,
17116980Smckusick 			"merged", stats.savedpush);
17216962Smckusick 	exit(0);
17316962Smckusick }
17416962Smckusick 
17516962Smckusick /*
17616962Smckusick  * Integrate an expansion into the assembly stream
17716962Smckusick  */
17816962Smckusick expand(replace)
17916962Smckusick 	char *replace;
18016962Smckusick {
18116962Smckusick 	register int curptr;
18216962Smckusick 	char *nextreplace, *argv[MAXARGS];
18317202Smckusick 	int argc, argreg, foundarg, mod = 0, args = 0;
18416962Smckusick 	char parsebuf[BUFSIZ];
18516962Smckusick 
18616980Smckusick 	stats.attempted++;
18716980Smckusick 	for (curptr = bufhead; ; ) {
18816962Smckusick 		nextreplace = copyline(replace, line[bufhead]);
18916962Smckusick 		argc = parseline(line[bufhead], argv, parsebuf);
19016962Smckusick 		argreg = nextarg(argc, argv);
19116962Smckusick 		if (argreg == -1)
19216962Smckusick 			break;
19317202Smckusick 		args++;
19416978Smckusick 		for (foundarg = 0; curptr != buftail; ) {
19516978Smckusick 			curptr = PRED(curptr);
19616962Smckusick 			argc = parseline(line[curptr], argv, parsebuf);
19716978Smckusick 			if (isendofblock(argc, argv))
19816962Smckusick 				break;
19916978Smckusick 			if (foundarg = ispusharg(argc, argv))
20016978Smckusick 				break;
20116962Smckusick 			mod |= 1 << modifies(argc, argv);
20216962Smckusick 		}
20316978Smckusick 		if (!foundarg)
20416962Smckusick 			break;
20516962Smckusick 		replace = nextreplace;
20616962Smckusick 		if (mod & (1 << argreg)) {
20716980Smckusick 			stats.lostmodified++;
20816978Smckusick 			if (curptr == buftail) {
20916978Smckusick 				(void)newline();
21016978Smckusick 				break;
21116978Smckusick 			}
21216962Smckusick 			(void)newline();
21316962Smckusick 		} else {
21416980Smckusick 			stats.savedpush++;
21516962Smckusick 			rewrite(line[curptr], argc, argv, argreg);
21616962Smckusick 			mod |= 1 << argreg;
21716962Smckusick 		}
21816962Smckusick 	}
21916980Smckusick 	if (argreg == -1)
22016980Smckusick 		stats.finished++;
22116962Smckusick 	emptyqueue();
22216962Smckusick 	fputs(replace, stdout);
22317202Smckusick 	cleanup(args);
22416962Smckusick }
22516962Smckusick 
22616962Smckusick /*
22716962Smckusick  * Parse a line of assembly language into opcode and arguments.
22816962Smckusick  */
22916962Smckusick parseline(linep, argv, linebuf)
23016962Smckusick 	char *linep;
23116962Smckusick 	char *argv[];
23216962Smckusick 	char *linebuf;
23316962Smckusick {
23416962Smckusick 	register char *bufp = linebuf, *cp = linep;
23516962Smckusick 	register int argc = 0;
23616962Smckusick 
23716962Smckusick 	for (;;) {
23816962Smckusick 		/*
23916962Smckusick 		 * skip over white space
24016962Smckusick 		 */
24116962Smckusick 		while (isspace(*cp))
24216962Smckusick 			cp++;
24316962Smckusick 		if (*cp == '\0')
24416962Smckusick 			return (argc);
24516962Smckusick 		/*
24616962Smckusick 		 * copy argument
24716962Smckusick 		 */
24816962Smckusick 		if (argc == MAXARGS - 1) {
24916962Smckusick 			fprintf(stderr, "instruction too long->%s", linep);
25016962Smckusick 			return (argc);
25116962Smckusick 		}
25216962Smckusick 		argv[argc++] = bufp;
25316978Smckusick 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
25416962Smckusick 			*bufp++ = *cp++;
25516962Smckusick 		*bufp++ = '\0';
25616962Smckusick 		if (*cp == COMMENTCHAR)
25716962Smckusick 			return (argc);
25816978Smckusick 		if (*cp == ARGSEPCHAR)
25916962Smckusick 			cp++;
26016962Smckusick 	}
26116962Smckusick }
26216962Smckusick 
26316962Smckusick /*
26416978Smckusick  * Check for instructions that end a basic block.
26516978Smckusick  */
26616978Smckusick isendofblock(argc, argv)
26716978Smckusick 	int argc;
26816978Smckusick 	char *argv[];
26916978Smckusick {
27016978Smckusick 	register struct inststoptbl *itp;
27116978Smckusick 	int size;
27216978Smckusick 
27316978Smckusick 	if (argc == 0)
27416978Smckusick 		return (0);
27516978Smckusick 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
27616978Smckusick 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
27716978Smckusick 			return (1);
27816978Smckusick 	return (0);
27916978Smckusick }
28016978Smckusick 
28116978Smckusick /*
28216962Smckusick  * Copy a newline terminated string.
28316962Smckusick  * Return pointer to character following last character copied.
28416962Smckusick  */
28516962Smckusick char *
28616962Smckusick copyline(from, to)
28716962Smckusick 	register char *from, *to;
28816962Smckusick {
28916962Smckusick 
29016962Smckusick 	while (*from != '\n')
29116962Smckusick 		*to++ = *from++;
29216962Smckusick 	*to++ = *from++;
29316962Smckusick 	*to = '\0';
29416962Smckusick 	return (from);
29516962Smckusick }
29616962Smckusick 
29716962Smckusick /*
29824395Smckusick  * Check for a disparity between the number of arguments a function
29924395Smckusick  * is called with and the number which we expect to see.
30024395Smckusick  * If the error is unrecoverable, return 1, otherwise 0.
30124395Smckusick  */
30224395Smckusick argcounterr(args, callargs, name)
30324395Smckusick 	int args, callargs;
30424395Smckusick 	char *name;
30524395Smckusick {
30624395Smckusick 	register char *cp;
30724395Smckusick 	char namebuf[MAXLINELEN];
30824395Smckusick 
30924395Smckusick 	if (args == callargs)
31024395Smckusick 		return (0);
31124395Smckusick 	cp = strcpy(namebuf, name);
31224395Smckusick 	while (*cp != '\0' && *cp != '\n')
31324395Smckusick 		++cp;
31424395Smckusick 	if (*cp == '\n')
31524395Smckusick 		*cp = '\0';
31624395Smckusick 	if (callargs >= 0) {
31724395Smckusick 		fprintf(stderr,
31824395Smckusick 		"%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
31924395Smckusick 			whoami, callargs, args, namebuf, lineno);
32024395Smckusick 		return (1);
32124395Smckusick 	}
32224395Smckusick 	fprintf(stderr,
32324395Smckusick 		"%s: warning: can't verify arg count for '%s' at line %d\n",
32424395Smckusick 		whoami, namebuf, lineno);
32524395Smckusick 	return (0);
32624395Smckusick }
32724395Smckusick 
32824395Smckusick /*
32916962Smckusick  * open space for next line in the queue
33016962Smckusick  */
33116962Smckusick char *
33216962Smckusick newline()
33316962Smckusick {
33416962Smckusick 	bufhead = SUCC(bufhead);
33516962Smckusick 	if (bufhead == buftail) {
33616962Smckusick 		fputs(line[buftail], stdout);
33716962Smckusick 		buftail = SUCC(buftail);
33816962Smckusick 	}
33916962Smckusick 	return (line[bufhead]);
34016962Smckusick }
34116962Smckusick 
34216962Smckusick /*
34316962Smckusick  * empty the queue by printing out all its lines.
34416962Smckusick  */
34516962Smckusick emptyqueue()
34616962Smckusick {
34716962Smckusick 	while (buftail != bufhead) {
34816962Smckusick 		fputs(line[buftail], stdout);
34916962Smckusick 		buftail = SUCC(buftail);
35016962Smckusick 	}
35116962Smckusick }
35216962Smckusick 
35316962Smckusick /*
35416962Smckusick  * Compute the hash of a string.
35516962Smckusick  * Return the hash and the size of the item hashed
35616962Smckusick  */
35716962Smckusick hash(cp, size)
35816962Smckusick 	char *cp;
35916962Smckusick 	int *size;
36016962Smckusick {
36116962Smckusick 	register char *cp1 = cp;
36216978Smckusick 	register int hash = 0;
36316962Smckusick 
36416962Smckusick 	while (*cp1 && *cp1 != '\n')
36516962Smckusick 		hash += (int)*cp1++;
36616962Smckusick 	*size = cp1 - cp + 1;
36716962Smckusick 	hash &= HSHSIZ - 1;
36816978Smckusick 	return (hash);
36916962Smckusick }
370