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