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