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