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