minor fixes
[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
8049a9ac 14static char sccsid[] = "@(#)main.c 1.11 (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 */
7a971c52 24struct pats *vax_inittables[] = {
b1f9c465
KM
25 language_ptab,
26 libc_ptab,
7a971c52 27 vax_libc_ptab,
b1f9c465 28 machine_ptab,
7a971c52
MK
29 vax_ptab,
30 0
31};
32
33struct pats *vaxsubset_inittables[] = {
34 language_ptab,
35 libc_ptab,
36 vaxsubset_libc_ptab,
37 machine_ptab,
38 vaxsubset_ptab,
b1f9c465
KM
39 0
40};
41
1ba0527c
KM
42/*
43 * Statistics collection
44 */
45struct 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;
1e4dba2b
KM
51
52extern char *strcpy();
53
54char *whoami;
55int lineno = 0;
1ba0527c
KM
56int dflag;
57
2472a393
KM
58main(argc, argv)
59 int argc;
60 char *argv[];
61{
2472a393
KM
62 register char *cp, *lp;
63 register char *bufp;
f3002970
KM
64 register struct pats *pp, **php;
65 struct pats **tablep;
66 register struct inststoptbl *itp, **ithp;
2472a393
KM
67 int size;
68 extern char *index();
7a971c52 69 int subset = 0;
2472a393 70
1e4dba2b 71 whoami = argv[0];
8049a9ac
JB
72 while (argc > 1 && argv[1][0] == '-') {
73 switch(argv[1][1]) {
7a971c52
MK
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 }
2472a393
KM
88 if (argc > 1)
89 freopen(argv[1], "r", stdin);
90 if (argc > 2)
91 freopen(argv[2], "w", stdout);
92 /*
f3002970 93 * Set up the hash table for the patterns.
2472a393 94 */
7a971c52
MK
95 if (subset)
96 tablep = vaxsubset_inittables;
97 else
98 tablep = vax_inittables;
99 for ( ; *tablep; tablep++) {
b1f9c465 100 for (pp = *tablep; pp->name[0] != '\0'; pp++) {
f3002970 101 php = &patshdr[hash(pp->name, &size)];
b1f9c465 102 pp->size = size;
f3002970
KM
103 pp->next = *php;
104 *php = pp;
b1f9c465 105 }
2472a393 106 }
f3002970
KM
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 }
2472a393
KM
116 /*
117 * check each line and replace as appropriate
118 */
119 buftail = bufhead = 0;
120 bufp = line[0];
121 while (fgets(bufp, MAXLINELEN, stdin)) {
1e4dba2b 122 lineno++;
2472a393
KM
123 lp = index(bufp, LABELCHAR);
124 if (lp != NULL) {
8fb09be1
KM
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 }
1e4dba2b 134 (void) strcpy(bufp, lp);
8fb09be1
KM
135 *lp++ = '\n';
136 *lp = '\0';
2472a393 137 emptyqueue();
2472a393 138 }
2472a393
KM
139 }
140 for (cp = bufp; isspace(*cp); cp++)
141 /* void */;
142 if ((cp = doreplaceon(cp)) == 0) {
143 bufp = newline();
144 continue;
145 }
f3002970 146 for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
2472a393 147 if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
1e4dba2b
KM
148 if (argcounterr(pp->args, countargs(bufp), pp->name)) {
149 pp = NULL;
150 break;
151 }
2472a393
KM
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();
1ba0527c 163 if (dflag)
1e4dba2b
KM
164 fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
165 whoami,
1ba0527c
KM
166 "attempts", stats.attempted,
167 "finished", stats.finished,
168 "inhibited", stats.lostmodified,
169 "merged", stats.savedpush);
2472a393
KM
170 exit(0);
171}
172
173/*
174 * Integrate an expansion into the assembly stream
175 */
176expand(replace)
177 char *replace;
178{
179 register int curptr;
180 char *nextreplace, *argv[MAXARGS];
86123054 181 int argc, argreg, foundarg, mod = 0, args = 0;
2472a393
KM
182 char parsebuf[BUFSIZ];
183
1ba0527c
KM
184 stats.attempted++;
185 for (curptr = bufhead; ; ) {
2472a393
KM
186 nextreplace = copyline(replace, line[bufhead]);
187 argc = parseline(line[bufhead], argv, parsebuf);
188 argreg = nextarg(argc, argv);
189 if (argreg == -1)
190 break;
86123054 191 args++;
f3002970
KM
192 for (foundarg = 0; curptr != buftail; ) {
193 curptr = PRED(curptr);
2472a393 194 argc = parseline(line[curptr], argv, parsebuf);
f3002970
KM
195 if (isendofblock(argc, argv))
196 break;
197 if (foundarg = ispusharg(argc, argv))
2472a393
KM
198 break;
199 mod |= 1 << modifies(argc, argv);
2472a393 200 }
f3002970 201 if (!foundarg)
2472a393
KM
202 break;
203 replace = nextreplace;
204 if (mod & (1 << argreg)) {
1ba0527c 205 stats.lostmodified++;
f3002970
KM
206 if (curptr == buftail) {
207 (void)newline();
208 break;
209 }
2472a393
KM
210 (void)newline();
211 } else {
1ba0527c 212 stats.savedpush++;
2472a393
KM
213 rewrite(line[curptr], argc, argv, argreg);
214 mod |= 1 << argreg;
215 }
216 }
1ba0527c
KM
217 if (argreg == -1)
218 stats.finished++;
2472a393
KM
219 emptyqueue();
220 fputs(replace, stdout);
86123054 221 cleanup(args);
2472a393
KM
222}
223
224/*
225 * Parse a line of assembly language into opcode and arguments.
226 */
227parseline(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;
f3002970 251 while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
2472a393
KM
252 *bufp++ = *cp++;
253 *bufp++ = '\0';
254 if (*cp == COMMENTCHAR)
255 return (argc);
f3002970 256 if (*cp == ARGSEPCHAR)
2472a393
KM
257 cp++;
258 }
259}
260
f3002970
KM
261/*
262 * Check for instructions that end a basic block.
263 */
264isendofblock(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
2472a393
KM
279/*
280 * Copy a newline terminated string.
281 * Return pointer to character following last character copied.
282 */
283char *
284copyline(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
1e4dba2b
KM
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 */
300argcounterr(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
2472a393
KM
326/*
327 * open space for next line in the queue
328 */
329char *
330newline()
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 */
343emptyqueue()
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 */
2472a393
KM
355hash(cp, size)
356 char *cp;
357 int *size;
358{
359 register char *cp1 = cp;
f3002970 360 register int hash = 0;
2472a393 361
2472a393
KM
362 while (*cp1 && *cp1 != '\n')
363 hash += (int)*cp1++;
364 *size = cp1 - cp + 1;
365 hash &= HSHSIZ - 1;
f3002970 366 return (hash);
2472a393 367}