BSD 4_3_Tahoe release
[unix-history] / usr / src / new / X / inline / main.c
CommitLineData
95f51977 1/* Copyright (c) 1984 Regents of the University of California */
3f469da1
SL
2
3#ifndef lint
95f51977
C
4static char sccsid[] = "@(#)main.c 1.6 (Berkeley) 9/20/84";
5#endif not lint
3f469da1
SL
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 */
14struct pats *inittables[] = {
15 language_ptab,
16 libc_ptab,
17 machine_ptab,
18 0
19};
20
21/*
22 * Statistics collection
23 */
24struct 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 */
95f51977 29 int savedmove; /* move to tmp reg eliminated */
3f469da1 30} stats;
95f51977 31int dflag;
3f469da1
SL
32
33main(argc, argv)
34 int argc;
35 char *argv[];
36{
95f51977 37 register char *cp, *lp, *qp;
3f469da1
SL
38 register char *bufp;
39 register struct pats *pp, **php;
40 struct pats **tablep;
41 register struct inststoptbl *itp, **ithp;
42 int size;
43 extern char *index();
44
45 if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
46 dflag++, argc--, argv++;
47 if (argc > 1)
48 freopen(argv[1], "r", stdin);
49 if (argc > 2)
50 freopen(argv[2], "w", stdout);
51 /*
52 * Set up the hash table for the patterns.
53 */
54 for (tablep = inittables; *tablep; tablep++) {
55 for (pp = *tablep; pp->name[0] != '\0'; pp++) {
56 php = &patshdr[hash(pp->name, &size)];
57 pp->size = size;
58 pp->next = *php;
59 *php = pp;
60 }
61 }
62 /*
63 * Set up the hash table for the instruction stop table.
64 */
65 for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
66 ithp = &inststoptblhdr[hash(itp->name, &size)];
67 itp->size = size;
68 itp->next = *ithp;
69 *ithp = itp;
70 }
71 /*
72 * check each line and replace as appropriate
73 */
74 buftail = bufhead = 0;
75 bufp = line[0];
76 while (fgets(bufp, MAXLINELEN, stdin)) {
77 lp = index(bufp, LABELCHAR);
78 if (lp != NULL) {
95f51977
C
79 qp = index(bufp, QUOTECHAR);
80 if (qp == NULL) {
81 bufp = newline();
82 if (*++lp == '\n') {
3f469da1 83 emptyqueue();
95f51977
C
84 continue;
85 }
86 strcpy(bufp, lp);
87 *lp++ = '\n';
88 *lp = '\0';
89 emptyqueue();
3f469da1
SL
90 }
91 }
92 for (cp = bufp; isspace(*cp); cp++)
93 /* void */;
94 if ((cp = doreplaceon(cp)) == 0) {
95 bufp = newline();
96 continue;
97 }
98 for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
99 if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
100 expand(pp->replace);
101 bufp = line[bufhead];
102 break;
103 }
104 }
105 if (!pp) {
106 emptyqueue();
107 fputs(bufp, stdout);
108 }
109 }
110 emptyqueue();
111 if (dflag)
95f51977 112 fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n",
3f469da1
SL
113 "attempts", stats.attempted,
114 "finished", stats.finished,
115 "inhibited", stats.lostmodified,
95f51977
C
116 "merged", stats.savedpush,
117 "nomoves", stats.savedmove);
3f469da1
SL
118 exit(0);
119}
120
121/*
122 * Integrate an expansion into the assembly stream
123 */
124expand(replace)
125 char *replace;
126{
127 register int curptr;
128 char *nextreplace, *argv[MAXARGS];
129 int argc, argreg, foundarg, mod = 0, args = 0;
130 char parsebuf[BUFSIZ];
95f51977
C
131 int argno = 0;
132 int flag;
133 struct oparg oparg[MAXARGS];
3f469da1
SL
134
135 stats.attempted++;
136 for (curptr = bufhead; ; ) {
137 nextreplace = copyline(replace, line[bufhead]);
138 argc = parseline(line[bufhead], argv, parsebuf);
95f51977 139 argreg = nextarg(argc, argv, &flag);
3f469da1
SL
140 if (argreg == -1)
141 break;
142 args++;
143 for (foundarg = 0; curptr != buftail; ) {
144 curptr = PRED(curptr);
145 argc = parseline(line[curptr], argv, parsebuf);
146 if (isendofblock(argc, argv))
147 break;
148 if (foundarg = ispusharg(argc, argv))
149 break;
150 mod |= 1 << modifies(argc, argv);
151 }
152 if (!foundarg)
153 break;
154 replace = nextreplace;
155 if (mod & (1 << argreg)) {
95f51977
C
156 stats.lostmodified++;
157 if (curptr == buftail) {
3f469da1 158 (void)newline();
95f51977
C
159 break;
160 }
161 (void)newline();
3f469da1 162 } else {
95f51977
C
163 if (checkvar(argc, argv, flag, oparg[argno].source, mod)) {
164 line[curptr][0] = '\0';
165 oparg[argno].reg = argreg;
166 argno++;
167 stats.savedmove++;
168 } else {
3f469da1 169 rewrite(line[curptr], argc, argv, argreg);
95f51977 170 stats.savedpush++;
3f469da1 171 mod |= 1 << argreg;
95f51977 172 }
3f469da1
SL
173 }
174 }
175 if (argreg == -1)
176 stats.finished++;
177 emptyqueue();
95f51977 178 output_replace(replace, oparg, argno, stdout);
3f469da1
SL
179 cleanup(args);
180}
181
182/*
183 * Parse a line of assembly language into opcode and arguments.
184 */
185parseline(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 */
222isendofblock(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 */
241char *
242copyline(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 */
256char *
257newline()
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 */
270emptyqueue()
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 */
282hash(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}