ec_rxstart doesn't eists
[unix-history] / usr / src / sys / tahoe / inline / main.c
CommitLineData
05e3da35
KB
1/*-
2 * Copyright (c) 1984 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
3f469da1
SL
6 */
7
8#ifndef lint
9char copyright[] =
05e3da35 10"@(#) Copyright (c) 1984 The Regents of the University of California.\n\
3f469da1 11 All rights reserved.\n";
05e3da35 12#endif /* not lint */
3f469da1
SL
13
14#ifndef lint
05e3da35
KB
15static char sccsid[] = "@(#)main.c 1.4 (Berkeley) %G%";
16#endif /* not lint */
3f469da1
SL
17
18#include <stdio.h>
19#include <ctype.h>
20#include "inline.h"
21
22/*
23 * These are the pattern tables to be loaded
24 */
25struct pats *inittables[] = {
26 language_ptab,
27 libc_ptab,
28 machine_ptab,
29 0
30};
31
32/*
33 * Statistics collection
34 */
35struct stats {
36 int attempted; /* number of expansion attempts */
37 int finished; /* expansions done before end of basic block */
38 int lostmodified; /* mergers inhibited by intervening mod */
39 int savedpush; /* successful push/pop merger */
40} stats;
23808d85
SL
41
42extern char *strcpy();
43
44char *whoami;
45int lineno = 0;
46int dflag;
3f469da1
SL
47
48main(argc, argv)
49 int argc;
50 char *argv[];
51{
52 register char *cp, *lp;
53 register char *bufp;
54 register struct pats *pp, **php;
55 struct pats **tablep;
56 register struct inststoptbl *itp, **ithp;
57 int size;
58 extern char *index();
59
23808d85 60 whoami = argv[0];
3f469da1
SL
61 if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
62 dflag++, argc--, argv++;
63 if (argc > 1)
64 freopen(argv[1], "r", stdin);
65 if (argc > 2)
66 freopen(argv[2], "w", stdout);
67 /*
68 * Set up the hash table for the patterns.
69 */
70 for (tablep = inittables; *tablep; tablep++) {
71 for (pp = *tablep; pp->name[0] != '\0'; pp++) {
72 php = &patshdr[hash(pp->name, &size)];
73 pp->size = size;
74 pp->next = *php;
75 *php = pp;
76 }
77 }
78 /*
79 * Set up the hash table for the instruction stop table.
80 */
81 for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
82 ithp = &inststoptblhdr[hash(itp->name, &size)];
83 itp->size = size;
84 itp->next = *ithp;
85 *ithp = itp;
86 }
87 /*
88 * check each line and replace as appropriate
89 */
90 buftail = bufhead = 0;
91 bufp = line[0];
92 while (fgets(bufp, MAXLINELEN, stdin)) {
23808d85 93 lineno++;
3f469da1
SL
94 lp = index(bufp, LABELCHAR);
95 if (lp != NULL) {
96 for (cp = bufp; cp < lp; cp++)
97 if (!isalnum(*cp))
98 break;
99 if (cp == lp) {
100 bufp = newline();
101 if (*++lp == '\n') {
102 emptyqueue();
103 continue;
104 }
23808d85 105 (void) strcpy(bufp, lp);
3f469da1
SL
106 *lp++ = '\n';
107 *lp = '\0';
108 emptyqueue();
109 }
110 }
111 for (cp = bufp; isspace(*cp); cp++)
112 /* void */;
113 if ((cp = doreplaceon(cp)) == 0) {
114 bufp = newline();
115 continue;
116 }
117 for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
118 if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
23808d85
SL
119 if (argcounterr(pp->args, countargs(bufp),
120 pp->name)) {
121 pp = NULL;
122 break;
123 }
3f469da1
SL
124 expand(pp->replace);
125 bufp = line[bufhead];
126 break;
127 }
128 }
129 if (!pp) {
130 emptyqueue();
131 fputs(bufp, stdout);
132 }
133 }
134 emptyqueue();
135 if (dflag)
23808d85
SL
136 fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
137 whoami,
3f469da1
SL
138 "attempts", stats.attempted,
139 "finished", stats.finished,
140 "inhibited", stats.lostmodified,
141 "merged", stats.savedpush);
142 exit(0);
143}
144
145/*
146 * Integrate an expansion into the assembly stream
147 */
148expand(replace)
149 char *replace;
150{
151 register int curptr;
152 char *nextreplace, *argv[MAXARGS];
153 int argc, argreg, foundarg, mod = 0, args = 0;
154 char parsebuf[BUFSIZ];
155
156 stats.attempted++;
157 for (curptr = bufhead; ; ) {
158 nextreplace = copyline(replace, line[bufhead]);
159 argc = parseline(line[bufhead], argv, parsebuf);
160 argreg = nextarg(argc, argv);
161 if (argreg == -1)
162 break;
163 args++;
164 for (foundarg = 0; curptr != buftail; ) {
165 curptr = PRED(curptr);
166 argc = parseline(line[curptr], argv, parsebuf);
167 if (isendofblock(argc, argv))
168 break;
169 if (foundarg = ispusharg(argc, argv))
170 break;
171 mod |= 1 << modifies(argc, argv);
172 }
173 if (!foundarg)
174 break;
175 replace = nextreplace;
176 if (mod & (1 << argreg)) {
177 stats.lostmodified++;
178 if (curptr == buftail) {
179 (void)newline();
180 break;
181 }
182 (void)newline();
183 } else {
184 stats.savedpush++;
185 rewrite(line[curptr], argc, argv, argreg);
186 mod |= 1 << argreg;
187 }
188 }
189 if (argreg == -1)
190 stats.finished++;
191 emptyqueue();
192 fputs(replace, stdout);
193 cleanup(args);
194}
195
196/*
197 * Parse a line of assembly language into opcode and arguments.
198 */
199parseline(linep, argv, linebuf)
200 char *linep;
201 char *argv[];
202 char *linebuf;
203{
204 register char *bufp = linebuf, *cp = linep;
205 register int argc = 0;
206
207 for (;;) {
208 /*
209 * skip over white space
210 */
211 while (isspace(*cp))
212 cp++;
213 if (*cp == '\0')
214 return (argc);
215 /*
216 * copy argument
217 */
218 if (argc == MAXARGS - 1) {
219 fprintf(stderr, "instruction too long->%s", linep);
220 return (argc);
221 }
222 argv[argc++] = bufp;
223 while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
224 *bufp++ = *cp++;
225 *bufp++ = '\0';
226 if (*cp == COMMENTCHAR)
227 return (argc);
228 if (*cp == ARGSEPCHAR)
229 cp++;
230 }
231}
232
233/*
234 * Check for instructions that end a basic block.
235 */
236isendofblock(argc, argv)
237 int argc;
238 char *argv[];
239{
240 register struct inststoptbl *itp;
241 int size;
242
243 if (argc == 0)
244 return (0);
245 for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
246 if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
247 return (1);
248 return (0);
249}
250
251/*
252 * Copy a newline terminated string.
253 * Return pointer to character following last character copied.
254 */
255char *
256copyline(from, to)
257 register char *from, *to;
258{
259
260 while (*from != '\n')
261 *to++ = *from++;
262 *to++ = *from++;
263 *to = '\0';
264 return (from);
265}
266
23808d85
SL
267/*
268 * Check for a disparity between the number of arguments a function
269 * is called with and the number which we expect to see.
270 * If the error is unrecoverable, return 1, otherwise 0.
271 */
272argcounterr(args, callargs, name)
273 int args, callargs;
274 char *name;
275{
276 register char *cp;
277 char namebuf[MAXLINELEN];
278
279 if (args == callargs)
280 return (0);
281 cp = strcpy(namebuf, name);
282 while (*cp != '\0' && *cp != '\n')
283 ++cp;
284 if (*cp == '\n')
285 *cp = '\0';
286 if (callargs >= 0) {
287 fprintf(stderr,
288 "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
289 whoami, callargs, args, namebuf, lineno);
290 return (1);
291 }
292 fprintf(stderr,
293 "%s: warning: can't verify arg count for '%s' at line %d\n",
294 whoami, namebuf, lineno);
295 return (0);
296}
297
3f469da1
SL
298/*
299 * open space for next line in the queue
300 */
301char *
302newline()
303{
304 bufhead = SUCC(bufhead);
305 if (bufhead == buftail) {
306 fputs(line[buftail], stdout);
307 buftail = SUCC(buftail);
308 }
309 return (line[bufhead]);
310}
311
312/*
313 * empty the queue by printing out all its lines.
314 */
315emptyqueue()
316{
317 while (buftail != bufhead) {
318 fputs(line[buftail], stdout);
319 buftail = SUCC(buftail);
320 }
321}
322
323/*
324 * Compute the hash of a string.
325 * Return the hash and the size of the item hashed
326 */
327hash(cp, size)
328 char *cp;
329 int *size;
330{
331 register char *cp1 = cp;
332 register int hash = 0;
333
334 while (*cp1 && *cp1 != '\n')
335 hash += (int)*cp1++;
336 *size = cp1 - cp + 1;
337 hash &= HSHSIZ - 1;
338 return (hash);
339}