xref: /csrg-svn/sys/vax/inline/main.c (revision 27462)
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.10 (Berkeley) 04/27/86";
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 *vax_inittables[] = {
25 	language_ptab,
26 	libc_ptab,
27 	vax_libc_ptab,
28 	machine_ptab,
29 	vax_ptab,
30 	0
31 };
32 
33 struct pats *vaxsubset_inittables[] = {
34 	language_ptab,
35 	libc_ptab,
36 	vaxsubset_libc_ptab,
37 	machine_ptab,
38 	vaxsubset_ptab,
39 	0
40 };
41 
42 /*
43  * Statistics collection
44  */
45 struct stats {
46 	int	attempted;	/* number of expansion attempts */
47 	int	finished;	/* expansions done before end of basic block */
48 	int	lostmodified;	/* mergers inhibited by intervening mod */
49 	int	savedpush;	/* successful push/pop merger */
50 } stats;
51 
52 extern char *strcpy();
53 
54 char *whoami;
55 int lineno = 0;
56 int dflag;
57 
58 main(argc, argv)
59 	int argc;
60 	char *argv[];
61 {
62 	register char *cp, *lp;
63 	register char *bufp;
64 	register struct pats *pp, **php;
65 	struct pats **tablep;
66 	register struct inststoptbl *itp, **ithp;
67 	int size;
68 	extern char *index();
69 	int subset = 0;
70 
71 	whoami = argv[0];
72 	while (argc > 0 && argv[0][0] == '-') {
73 		switch(argv[0][1]) {
74 
75 		case 's':
76 			subset++;
77 			break;
78 
79 		case 'd':
80 			dflag++;
81 			break;
82 
83 		default:
84 			break;
85 		}
86 		argc--, argv++;
87 	}
88 	if (argc > 1)
89 		freopen(argv[1], "r", stdin);
90 	if (argc > 2)
91 		freopen(argv[2], "w", stdout);
92 	/*
93 	 * Set up the hash table for the patterns.
94 	 */
95 	if (subset)
96 		tablep = vaxsubset_inittables;
97 	else
98 		tablep = vax_inittables;
99 	for ( ; *tablep; tablep++) {
100 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
101 			php = &patshdr[hash(pp->name, &size)];
102 			pp->size = size;
103 			pp->next = *php;
104 			*php = pp;
105 		}
106 	}
107 	/*
108 	 * Set up the hash table for the instruction stop table.
109 	 */
110 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
111 		ithp = &inststoptblhdr[hash(itp->name, &size)];
112 		itp->size = size;
113 		itp->next = *ithp;
114 		*ithp = itp;
115 	}
116 	/*
117 	 * check each line and replace as appropriate
118 	 */
119 	buftail = bufhead = 0;
120 	bufp = line[0];
121 	while (fgets(bufp, MAXLINELEN, stdin)) {
122 		lineno++;
123 		lp = index(bufp, LABELCHAR);
124 		if (lp != NULL) {
125 			for (cp = bufp; cp < lp; cp++)
126 				if (!isalnum(*cp))
127 					break;
128 			if (cp == lp) {
129 				bufp = newline();
130 				if (*++lp == '\n') {
131 					emptyqueue();
132 					continue;
133 				}
134 				(void) strcpy(bufp, lp);
135 				*lp++ = '\n';
136 				*lp = '\0';
137 				emptyqueue();
138 			}
139 		}
140 		for (cp = bufp; isspace(*cp); cp++)
141 			/* void */;
142 		if ((cp = doreplaceon(cp)) == 0) {
143 			bufp = newline();
144 			continue;
145 		}
146 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
147 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
148 				if (argcounterr(pp->args, countargs(bufp), pp->name)) {
149 					pp = NULL;
150 					break;
151 				}
152 				expand(pp->replace);
153 				bufp = line[bufhead];
154 				break;
155 			}
156 		}
157 		if (!pp) {
158 			emptyqueue();
159 			fputs(bufp, stdout);
160 		}
161 	}
162 	emptyqueue();
163 	if (dflag)
164 		fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
165 			whoami,
166 			"attempts", stats.attempted,
167 			"finished", stats.finished,
168 			"inhibited", stats.lostmodified,
169 			"merged", stats.savedpush);
170 	exit(0);
171 }
172 
173 /*
174  * Integrate an expansion into the assembly stream
175  */
176 expand(replace)
177 	char *replace;
178 {
179 	register int curptr;
180 	char *nextreplace, *argv[MAXARGS];
181 	int argc, argreg, foundarg, mod = 0, args = 0;
182 	char parsebuf[BUFSIZ];
183 
184 	stats.attempted++;
185 	for (curptr = bufhead; ; ) {
186 		nextreplace = copyline(replace, line[bufhead]);
187 		argc = parseline(line[bufhead], argv, parsebuf);
188 		argreg = nextarg(argc, argv);
189 		if (argreg == -1)
190 			break;
191 		args++;
192 		for (foundarg = 0; curptr != buftail; ) {
193 			curptr = PRED(curptr);
194 			argc = parseline(line[curptr], argv, parsebuf);
195 			if (isendofblock(argc, argv))
196 				break;
197 			if (foundarg = ispusharg(argc, argv))
198 				break;
199 			mod |= 1 << modifies(argc, argv);
200 		}
201 		if (!foundarg)
202 			break;
203 		replace = nextreplace;
204 		if (mod & (1 << argreg)) {
205 			stats.lostmodified++;
206 			if (curptr == buftail) {
207 				(void)newline();
208 				break;
209 			}
210 			(void)newline();
211 		} else {
212 			stats.savedpush++;
213 			rewrite(line[curptr], argc, argv, argreg);
214 			mod |= 1 << argreg;
215 		}
216 	}
217 	if (argreg == -1)
218 		stats.finished++;
219 	emptyqueue();
220 	fputs(replace, stdout);
221 	cleanup(args);
222 }
223 
224 /*
225  * Parse a line of assembly language into opcode and arguments.
226  */
227 parseline(linep, argv, linebuf)
228 	char *linep;
229 	char *argv[];
230 	char *linebuf;
231 {
232 	register char *bufp = linebuf, *cp = linep;
233 	register int argc = 0;
234 
235 	for (;;) {
236 		/*
237 		 * skip over white space
238 		 */
239 		while (isspace(*cp))
240 			cp++;
241 		if (*cp == '\0')
242 			return (argc);
243 		/*
244 		 * copy argument
245 		 */
246 		if (argc == MAXARGS - 1) {
247 			fprintf(stderr, "instruction too long->%s", linep);
248 			return (argc);
249 		}
250 		argv[argc++] = bufp;
251 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
252 			*bufp++ = *cp++;
253 		*bufp++ = '\0';
254 		if (*cp == COMMENTCHAR)
255 			return (argc);
256 		if (*cp == ARGSEPCHAR)
257 			cp++;
258 	}
259 }
260 
261 /*
262  * Check for instructions that end a basic block.
263  */
264 isendofblock(argc, argv)
265 	int argc;
266 	char *argv[];
267 {
268 	register struct inststoptbl *itp;
269 	int size;
270 
271 	if (argc == 0)
272 		return (0);
273 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
274 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
275 			return (1);
276 	return (0);
277 }
278 
279 /*
280  * Copy a newline terminated string.
281  * Return pointer to character following last character copied.
282  */
283 char *
284 copyline(from, to)
285 	register char *from, *to;
286 {
287 
288 	while (*from != '\n')
289 		*to++ = *from++;
290 	*to++ = *from++;
291 	*to = '\0';
292 	return (from);
293 }
294 
295 /*
296  * Check for a disparity between the number of arguments a function
297  * is called with and the number which we expect to see.
298  * If the error is unrecoverable, return 1, otherwise 0.
299  */
300 argcounterr(args, callargs, name)
301 	int args, callargs;
302 	char *name;
303 {
304 	register char *cp;
305 	char namebuf[MAXLINELEN];
306 
307 	if (args == callargs)
308 		return (0);
309 	cp = strcpy(namebuf, name);
310 	while (*cp != '\0' && *cp != '\n')
311 		++cp;
312 	if (*cp == '\n')
313 		*cp = '\0';
314 	if (callargs >= 0) {
315 		fprintf(stderr,
316 		"%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
317 			whoami, callargs, args, namebuf, lineno);
318 		return (1);
319 	}
320 	fprintf(stderr,
321 		"%s: warning: can't verify arg count for '%s' at line %d\n",
322 		whoami, namebuf, lineno);
323 	return (0);
324 }
325 
326 /*
327  * open space for next line in the queue
328  */
329 char *
330 newline()
331 {
332 	bufhead = SUCC(bufhead);
333 	if (bufhead == buftail) {
334 		fputs(line[buftail], stdout);
335 		buftail = SUCC(buftail);
336 	}
337 	return (line[bufhead]);
338 }
339 
340 /*
341  * empty the queue by printing out all its lines.
342  */
343 emptyqueue()
344 {
345 	while (buftail != bufhead) {
346 		fputs(line[buftail], stdout);
347 		buftail = SUCC(buftail);
348 	}
349 }
350 
351 /*
352  * Compute the hash of a string.
353  * Return the hash and the size of the item hashed
354  */
355 hash(cp, size)
356 	char *cp;
357 	int *size;
358 {
359 	register char *cp1 = cp;
360 	register int hash = 0;
361 
362 	while (*cp1 && *cp1 != '\n')
363 		hash += (int)*cp1++;
364 	*size = cp1 - cp + 1;
365 	hash &= HSHSIZ - 1;
366 	return (hash);
367 }
368