xref: /csrg-svn/sys/vax/inline/main.c (revision 16980)
1 /* Copyright (c) 1984 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)main.c	1.5	(Berkeley)	08/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;
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 		for (foundarg = 0; curptr != buftail; ) {
135 			curptr = PRED(curptr);
136 			argc = parseline(line[curptr], argv, parsebuf);
137 			if (isendofblock(argc, argv))
138 				break;
139 			if (foundarg = ispusharg(argc, argv))
140 				break;
141 			mod |= 1 << modifies(argc, argv);
142 		}
143 		if (!foundarg)
144 			break;
145 		replace = nextreplace;
146 		if (mod & (1 << argreg)) {
147 			stats.lostmodified++;
148 			if (curptr == buftail) {
149 				(void)newline();
150 				break;
151 			}
152 			(void)newline();
153 		} else {
154 			stats.savedpush++;
155 			rewrite(line[curptr], argc, argv, argreg);
156 			mod |= 1 << argreg;
157 		}
158 	}
159 	if (argreg == -1)
160 		stats.finished++;
161 	emptyqueue();
162 	fputs(replace, stdout);
163 }
164 
165 /*
166  * Parse a line of assembly language into opcode and arguments.
167  */
168 parseline(linep, argv, linebuf)
169 	char *linep;
170 	char *argv[];
171 	char *linebuf;
172 {
173 	register char *bufp = linebuf, *cp = linep;
174 	register int argc = 0;
175 
176 	for (;;) {
177 		/*
178 		 * skip over white space
179 		 */
180 		while (isspace(*cp))
181 			cp++;
182 		if (*cp == '\0')
183 			return (argc);
184 		/*
185 		 * copy argument
186 		 */
187 		if (argc == MAXARGS - 1) {
188 			fprintf(stderr, "instruction too long->%s", linep);
189 			return (argc);
190 		}
191 		argv[argc++] = bufp;
192 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
193 			*bufp++ = *cp++;
194 		*bufp++ = '\0';
195 		if (*cp == COMMENTCHAR)
196 			return (argc);
197 		if (*cp == ARGSEPCHAR)
198 			cp++;
199 	}
200 }
201 
202 /*
203  * Check for instructions that end a basic block.
204  */
205 isendofblock(argc, argv)
206 	int argc;
207 	char *argv[];
208 {
209 	register struct inststoptbl *itp;
210 	int size;
211 
212 	if (argc == 0)
213 		return (0);
214 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
215 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
216 			return (1);
217 	return (0);
218 }
219 
220 /*
221  * Copy a newline terminated string.
222  * Return pointer to character following last character copied.
223  */
224 char *
225 copyline(from, to)
226 	register char *from, *to;
227 {
228 
229 	while (*from != '\n')
230 		*to++ = *from++;
231 	*to++ = *from++;
232 	*to = '\0';
233 	return (from);
234 }
235 
236 /*
237  * open space for next line in the queue
238  */
239 char *
240 newline()
241 {
242 	bufhead = SUCC(bufhead);
243 	if (bufhead == buftail) {
244 		fputs(line[buftail], stdout);
245 		buftail = SUCC(buftail);
246 	}
247 	return (line[bufhead]);
248 }
249 
250 /*
251  * empty the queue by printing out all its lines.
252  */
253 emptyqueue()
254 {
255 	while (buftail != bufhead) {
256 		fputs(line[buftail], stdout);
257 		buftail = SUCC(buftail);
258 	}
259 }
260 
261 /*
262  * Compute the hash of a string.
263  * Return the hash and the size of the item hashed
264  */
265 hash(cp, size)
266 	char *cp;
267 	int *size;
268 {
269 	register char *cp1 = cp;
270 	register int hash = 0;
271 
272 	while (*cp1 && *cp1 != '\n')
273 		hash += (int)*cp1++;
274 	*size = cp1 - cp + 1;
275 	hash &= HSHSIZ - 1;
276 	return (hash);
277 }
278