Use old gamma.
[unix-history] / usr / src / sys / vax / inline / main.c
CommitLineData
da7c5cc6
KM
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
8char copyright[] =
9"@(#) Copyright (c) 1984 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
2472a393
KM
12
13#ifndef lint
da7c5cc6 14static char sccsid[] = "@(#)main.c 1.8 (Berkeley) %G%";
2472a393
KM
15#endif not lint
16
17#include <stdio.h>
18#include <ctype.h>
ea1f375a 19#include "inline.h"
2472a393 20
b1f9c465
KM
21/*
22 * These are the pattern tables to be loaded
23 */
24struct pats *inittables[] = {
25 language_ptab,
26 libc_ptab,
27 machine_ptab,
28 0
29};
30
1ba0527c
KM
31/*
32 * Statistics collection
33 */
34struct 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;
40int dflag;
41
2472a393
KM
42main(argc, argv)
43 int argc;
44 char *argv[];
45{
2472a393
KM
46 register char *cp, *lp;
47 register char *bufp;
f3002970
KM
48 register struct pats *pp, **php;
49 struct pats **tablep;
50 register struct inststoptbl *itp, **ithp;
2472a393
KM
51 int size;
52 extern char *index();
53
1ba0527c
KM
54 if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
55 dflag++, argc--, argv++;
2472a393
KM
56 if (argc > 1)
57 freopen(argv[1], "r", stdin);
58 if (argc > 2)
59 freopen(argv[2], "w", stdout);
60 /*
f3002970 61 * Set up the hash table for the patterns.
2472a393 62 */
b1f9c465
KM
63 for (tablep = inittables; *tablep; tablep++) {
64 for (pp = *tablep; pp->name[0] != '\0'; pp++) {
f3002970 65 php = &patshdr[hash(pp->name, &size)];
b1f9c465 66 pp->size = size;
f3002970
KM
67 pp->next = *php;
68 *php = pp;
b1f9c465 69 }
2472a393 70 }
f3002970
KM
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 }
2472a393
KM
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) {
8fb09be1
KM
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';
2472a393 100 emptyqueue();
2472a393 101 }
2472a393
KM
102 }
103 for (cp = bufp; isspace(*cp); cp++)
104 /* void */;
105 if ((cp = doreplaceon(cp)) == 0) {
106 bufp = newline();
107 continue;
108 }
f3002970 109 for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
2472a393
KM
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();
1ba0527c
KM
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);
2472a393
KM
128 exit(0);
129}
130
131/*
132 * Integrate an expansion into the assembly stream
133 */
134expand(replace)
135 char *replace;
136{
137 register int curptr;
138 char *nextreplace, *argv[MAXARGS];
86123054 139 int argc, argreg, foundarg, mod = 0, args = 0;
2472a393
KM
140 char parsebuf[BUFSIZ];
141
1ba0527c
KM
142 stats.attempted++;
143 for (curptr = bufhead; ; ) {
2472a393
KM
144 nextreplace = copyline(replace, line[bufhead]);
145 argc = parseline(line[bufhead], argv, parsebuf);
146 argreg = nextarg(argc, argv);
147 if (argreg == -1)
148 break;
86123054 149 args++;
f3002970
KM
150 for (foundarg = 0; curptr != buftail; ) {
151 curptr = PRED(curptr);
2472a393 152 argc = parseline(line[curptr], argv, parsebuf);
f3002970
KM
153 if (isendofblock(argc, argv))
154 break;
155 if (foundarg = ispusharg(argc, argv))
2472a393
KM
156 break;
157 mod |= 1 << modifies(argc, argv);
2472a393 158 }
f3002970 159 if (!foundarg)
2472a393
KM
160 break;
161 replace = nextreplace;
162 if (mod & (1 << argreg)) {
1ba0527c 163 stats.lostmodified++;
f3002970
KM
164 if (curptr == buftail) {
165 (void)newline();
166 break;
167 }
2472a393
KM
168 (void)newline();
169 } else {
1ba0527c 170 stats.savedpush++;
2472a393
KM
171 rewrite(line[curptr], argc, argv, argreg);
172 mod |= 1 << argreg;
173 }
174 }
1ba0527c
KM
175 if (argreg == -1)
176 stats.finished++;
2472a393
KM
177 emptyqueue();
178 fputs(replace, stdout);
86123054 179 cleanup(args);
2472a393
KM
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;
f3002970 209 while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
2472a393
KM
210 *bufp++ = *cp++;
211 *bufp++ = '\0';
212 if (*cp == COMMENTCHAR)
213 return (argc);
f3002970 214 if (*cp == ARGSEPCHAR)
2472a393
KM
215 cp++;
216 }
217}
218
f3002970
KM
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
2472a393
KM
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 */
2472a393
KM
282hash(cp, size)
283 char *cp;
284 int *size;
285{
286 register char *cp1 = cp;
f3002970 287 register int hash = 0;
2472a393 288
2472a393
KM
289 while (*cp1 && *cp1 != '\n')
290 hash += (int)*cp1++;
291 *size = cp1 - cp + 1;
292 hash &= HSHSIZ - 1;
f3002970 293 return (hash);
2472a393 294}