xref: /csrg-svn/sys/tahoe/inline/main.c (revision 24038)
1*24038Ssam /*
2*24038Ssam  * Copyright (c) 1984 Regents of the University of California.
3*24038Ssam  * All rights reserved.  The Berkeley software License Agreement
4*24038Ssam  * specifies the terms and conditions for redistribution.
5*24038Ssam  */
6*24038Ssam 
7*24038Ssam #ifndef lint
8*24038Ssam char copyright[] =
9*24038Ssam "@(#) Copyright (c) 1984 Regents of the University of California.\n\
10*24038Ssam  All rights reserved.\n";
11*24038Ssam #endif not lint
12*24038Ssam 
13*24038Ssam #ifndef lint
14*24038Ssam static char sccsid[] = "@(#)main.c	1.8 (Berkeley) 6/8/85";
15*24038Ssam #endif not lint
16*24038Ssam 
17*24038Ssam #include <stdio.h>
18*24038Ssam #include <ctype.h>
19*24038Ssam #include "inline.h"
20*24038Ssam 
21*24038Ssam /*
22*24038Ssam  * These are the pattern tables to be loaded
23*24038Ssam  */
24*24038Ssam struct pats *inittables[] = {
25*24038Ssam 	language_ptab,
26*24038Ssam 	libc_ptab,
27*24038Ssam 	machine_ptab,
28*24038Ssam 	0
29*24038Ssam };
30*24038Ssam 
31*24038Ssam /*
32*24038Ssam  * Statistics collection
33*24038Ssam  */
34*24038Ssam struct stats {
35*24038Ssam 	int	attempted;	/* number of expansion attempts */
36*24038Ssam 	int	finished;	/* expansions done before end of basic block */
37*24038Ssam 	int	lostmodified;	/* mergers inhibited by intervening mod */
38*24038Ssam 	int	savedpush;	/* successful push/pop merger */
39*24038Ssam } stats;
40*24038Ssam int dflag;
41*24038Ssam 
42*24038Ssam main(argc, argv)
43*24038Ssam 	int argc;
44*24038Ssam 	char *argv[];
45*24038Ssam {
46*24038Ssam 	register char *cp, *lp;
47*24038Ssam 	register char *bufp;
48*24038Ssam 	register struct pats *pp, **php;
49*24038Ssam 	struct pats **tablep;
50*24038Ssam 	register struct inststoptbl *itp, **ithp;
51*24038Ssam 	int size;
52*24038Ssam 	extern char *index();
53*24038Ssam 
54*24038Ssam 	if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
55*24038Ssam 		dflag++, argc--, argv++;
56*24038Ssam 	if (argc > 1)
57*24038Ssam 		freopen(argv[1], "r", stdin);
58*24038Ssam 	if (argc > 2)
59*24038Ssam 		freopen(argv[2], "w", stdout);
60*24038Ssam 	/*
61*24038Ssam 	 * Set up the hash table for the patterns.
62*24038Ssam 	 */
63*24038Ssam 	for (tablep = inittables; *tablep; tablep++) {
64*24038Ssam 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
65*24038Ssam 			php = &patshdr[hash(pp->name, &size)];
66*24038Ssam 			pp->size = size;
67*24038Ssam 			pp->next = *php;
68*24038Ssam 			*php = pp;
69*24038Ssam 		}
70*24038Ssam 	}
71*24038Ssam 	/*
72*24038Ssam 	 * Set up the hash table for the instruction stop table.
73*24038Ssam 	 */
74*24038Ssam 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
75*24038Ssam 		ithp = &inststoptblhdr[hash(itp->name, &size)];
76*24038Ssam 		itp->size = size;
77*24038Ssam 		itp->next = *ithp;
78*24038Ssam 		*ithp = itp;
79*24038Ssam 	}
80*24038Ssam 	/*
81*24038Ssam 	 * check each line and replace as appropriate
82*24038Ssam 	 */
83*24038Ssam 	buftail = bufhead = 0;
84*24038Ssam 	bufp = line[0];
85*24038Ssam 	while (fgets(bufp, MAXLINELEN, stdin)) {
86*24038Ssam 		lp = index(bufp, LABELCHAR);
87*24038Ssam 		if (lp != NULL) {
88*24038Ssam 			for (cp = bufp; cp < lp; cp++)
89*24038Ssam 				if (!isalnum(*cp))
90*24038Ssam 					break;
91*24038Ssam 			if (cp == lp) {
92*24038Ssam 				bufp = newline();
93*24038Ssam 				if (*++lp == '\n') {
94*24038Ssam 					emptyqueue();
95*24038Ssam 					continue;
96*24038Ssam 				}
97*24038Ssam 				strcpy(bufp, lp);
98*24038Ssam 				*lp++ = '\n';
99*24038Ssam 				*lp = '\0';
100*24038Ssam 				emptyqueue();
101*24038Ssam 			}
102*24038Ssam 		}
103*24038Ssam 		for (cp = bufp; isspace(*cp); cp++)
104*24038Ssam 			/* void */;
105*24038Ssam 		if ((cp = doreplaceon(cp)) == 0) {
106*24038Ssam 			bufp = newline();
107*24038Ssam 			continue;
108*24038Ssam 		}
109*24038Ssam 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
110*24038Ssam 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
111*24038Ssam 				expand(pp->replace);
112*24038Ssam 				bufp = line[bufhead];
113*24038Ssam 				break;
114*24038Ssam 			}
115*24038Ssam 		}
116*24038Ssam 		if (!pp) {
117*24038Ssam 			emptyqueue();
118*24038Ssam 			fputs(bufp, stdout);
119*24038Ssam 		}
120*24038Ssam 	}
121*24038Ssam 	emptyqueue();
122*24038Ssam 	if (dflag)
123*24038Ssam 		fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n",
124*24038Ssam 			"attempts", stats.attempted,
125*24038Ssam 			"finished", stats.finished,
126*24038Ssam 			"inhibited", stats.lostmodified,
127*24038Ssam 			"merged", stats.savedpush);
128*24038Ssam 	exit(0);
129*24038Ssam }
130*24038Ssam 
131*24038Ssam /*
132*24038Ssam  * Integrate an expansion into the assembly stream
133*24038Ssam  */
134*24038Ssam expand(replace)
135*24038Ssam 	char *replace;
136*24038Ssam {
137*24038Ssam 	register int curptr;
138*24038Ssam 	char *nextreplace, *argv[MAXARGS];
139*24038Ssam 	int argc, argreg, foundarg, mod = 0, args = 0;
140*24038Ssam 	char parsebuf[BUFSIZ];
141*24038Ssam 
142*24038Ssam 	stats.attempted++;
143*24038Ssam 	for (curptr = bufhead; ; ) {
144*24038Ssam 		nextreplace = copyline(replace, line[bufhead]);
145*24038Ssam 		argc = parseline(line[bufhead], argv, parsebuf);
146*24038Ssam 		argreg = nextarg(argc, argv);
147*24038Ssam 		if (argreg == -1)
148*24038Ssam 			break;
149*24038Ssam 		args++;
150*24038Ssam 		for (foundarg = 0; curptr != buftail; ) {
151*24038Ssam 			curptr = PRED(curptr);
152*24038Ssam 			argc = parseline(line[curptr], argv, parsebuf);
153*24038Ssam 			if (isendofblock(argc, argv))
154*24038Ssam 				break;
155*24038Ssam 			if (foundarg = ispusharg(argc, argv))
156*24038Ssam 				break;
157*24038Ssam 			mod |= 1 << modifies(argc, argv);
158*24038Ssam 		}
159*24038Ssam 		if (!foundarg)
160*24038Ssam 			break;
161*24038Ssam 		replace = nextreplace;
162*24038Ssam 		if (mod & (1 << argreg)) {
163*24038Ssam 			stats.lostmodified++;
164*24038Ssam 			if (curptr == buftail) {
165*24038Ssam 				(void)newline();
166*24038Ssam 				break;
167*24038Ssam 			}
168*24038Ssam 			(void)newline();
169*24038Ssam 		} else {
170*24038Ssam 			stats.savedpush++;
171*24038Ssam 			rewrite(line[curptr], argc, argv, argreg);
172*24038Ssam 			mod |= 1 << argreg;
173*24038Ssam 		}
174*24038Ssam 	}
175*24038Ssam 	if (argreg == -1)
176*24038Ssam 		stats.finished++;
177*24038Ssam 	emptyqueue();
178*24038Ssam 	fputs(replace, stdout);
179*24038Ssam 	cleanup(args);
180*24038Ssam }
181*24038Ssam 
182*24038Ssam /*
183*24038Ssam  * Parse a line of assembly language into opcode and arguments.
184*24038Ssam  */
185*24038Ssam parseline(linep, argv, linebuf)
186*24038Ssam 	char *linep;
187*24038Ssam 	char *argv[];
188*24038Ssam 	char *linebuf;
189*24038Ssam {
190*24038Ssam 	register char *bufp = linebuf, *cp = linep;
191*24038Ssam 	register int argc = 0;
192*24038Ssam 
193*24038Ssam 	for (;;) {
194*24038Ssam 		/*
195*24038Ssam 		 * skip over white space
196*24038Ssam 		 */
197*24038Ssam 		while (isspace(*cp))
198*24038Ssam 			cp++;
199*24038Ssam 		if (*cp == '\0')
200*24038Ssam 			return (argc);
201*24038Ssam 		/*
202*24038Ssam 		 * copy argument
203*24038Ssam 		 */
204*24038Ssam 		if (argc == MAXARGS - 1) {
205*24038Ssam 			fprintf(stderr, "instruction too long->%s", linep);
206*24038Ssam 			return (argc);
207*24038Ssam 		}
208*24038Ssam 		argv[argc++] = bufp;
209*24038Ssam 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
210*24038Ssam 			*bufp++ = *cp++;
211*24038Ssam 		*bufp++ = '\0';
212*24038Ssam 		if (*cp == COMMENTCHAR)
213*24038Ssam 			return (argc);
214*24038Ssam 		if (*cp == ARGSEPCHAR)
215*24038Ssam 			cp++;
216*24038Ssam 	}
217*24038Ssam }
218*24038Ssam 
219*24038Ssam /*
220*24038Ssam  * Check for instructions that end a basic block.
221*24038Ssam  */
222*24038Ssam isendofblock(argc, argv)
223*24038Ssam 	int argc;
224*24038Ssam 	char *argv[];
225*24038Ssam {
226*24038Ssam 	register struct inststoptbl *itp;
227*24038Ssam 	int size;
228*24038Ssam 
229*24038Ssam 	if (argc == 0)
230*24038Ssam 		return (0);
231*24038Ssam 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
232*24038Ssam 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
233*24038Ssam 			return (1);
234*24038Ssam 	return (0);
235*24038Ssam }
236*24038Ssam 
237*24038Ssam /*
238*24038Ssam  * Copy a newline terminated string.
239*24038Ssam  * Return pointer to character following last character copied.
240*24038Ssam  */
241*24038Ssam char *
242*24038Ssam copyline(from, to)
243*24038Ssam 	register char *from, *to;
244*24038Ssam {
245*24038Ssam 
246*24038Ssam 	while (*from != '\n')
247*24038Ssam 		*to++ = *from++;
248*24038Ssam 	*to++ = *from++;
249*24038Ssam 	*to = '\0';
250*24038Ssam 	return (from);
251*24038Ssam }
252*24038Ssam 
253*24038Ssam /*
254*24038Ssam  * open space for next line in the queue
255*24038Ssam  */
256*24038Ssam char *
257*24038Ssam newline()
258*24038Ssam {
259*24038Ssam 	bufhead = SUCC(bufhead);
260*24038Ssam 	if (bufhead == buftail) {
261*24038Ssam 		fputs(line[buftail], stdout);
262*24038Ssam 		buftail = SUCC(buftail);
263*24038Ssam 	}
264*24038Ssam 	return (line[bufhead]);
265*24038Ssam }
266*24038Ssam 
267*24038Ssam /*
268*24038Ssam  * empty the queue by printing out all its lines.
269*24038Ssam  */
270*24038Ssam emptyqueue()
271*24038Ssam {
272*24038Ssam 	while (buftail != bufhead) {
273*24038Ssam 		fputs(line[buftail], stdout);
274*24038Ssam 		buftail = SUCC(buftail);
275*24038Ssam 	}
276*24038Ssam }
277*24038Ssam 
278*24038Ssam /*
279*24038Ssam  * Compute the hash of a string.
280*24038Ssam  * Return the hash and the size of the item hashed
281*24038Ssam  */
282*24038Ssam hash(cp, size)
283*24038Ssam 	char *cp;
284*24038Ssam 	int *size;
285*24038Ssam {
286*24038Ssam 	register char *cp1 = cp;
287*24038Ssam 	register int hash = 0;
288*24038Ssam 
289*24038Ssam 	while (*cp1 && *cp1 != '\n')
290*24038Ssam 		hash += (int)*cp1++;
291*24038Ssam 	*size = cp1 - cp + 1;
292*24038Ssam 	hash &= HSHSIZ - 1;
293*24038Ssam 	return (hash);
294*24038Ssam }
295