|
|
1.1 root 1: /*-
2: * Copyright (c) 1984, 1986 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: */
33:
34: #ifndef lint
35: char copyright[] =
36: "@(#) Copyright (c) 1984, 1986 The Regents of the University of California.\n\
37: All rights reserved.\n";
38: #endif /* not lint */
39:
40: #ifndef lint
41: static char sccsid[] = "@(#)main.c 7.2 (Berkeley) 5/8/91";
42: #endif /* not lint */
43:
44: #include <stdio.h>
45: #include <ctype.h>
46: #include "inline.h"
47:
48: /*
49: * These are the pattern tables to be loaded
50: */
51: struct pats *vax_inittables[] = {
52: language_ptab,
53: libc_ptab,
54: vax_libc_ptab,
55: machine_ptab,
56: vax_ptab,
57: 0
58: };
59:
60: struct pats *vaxsubset_inittables[] = {
61: language_ptab,
62: libc_ptab,
63: vaxsubset_libc_ptab,
64: machine_ptab,
65: vaxsubset_ptab,
66: 0
67: };
68:
69: /*
70: * Statistics collection
71: */
72: struct stats {
73: int attempted; /* number of expansion attempts */
74: int finished; /* expansions done before end of basic block */
75: int lostmodified; /* mergers inhibited by intervening mod */
76: int savedpush; /* successful push/pop merger */
77: } stats;
78:
79: extern char *strcpy();
80:
81: char *whoami;
82: int lineno = 0;
83: int dflag;
84:
85: main(argc, argv)
86: int argc;
87: char *argv[];
88: {
89: register char *cp, *lp;
90: register char *bufp;
91: register struct pats *pp, **php;
92: struct pats **tablep;
93: register struct inststoptbl *itp, **ithp;
94: int size;
95: extern char *index();
96: int subset = 0;
97:
98: whoami = argv[0];
99: argc--;
100: argv++;
101: while (argc > 0 && argv[0][0] == '-') {
102: switch(argv[0][1]) {
103:
104: case 's':
105: subset++;
106: break;
107:
108: case 'd':
109: dflag++;
110: break;
111:
112: default:
113: break;
114: }
115: argc--, argv++;
116: }
117: if (argc > 0)
118: freopen(argv[0], "r", stdin);
119: if (argc > 1)
120: freopen(argv[1], "w", stdout);
121: /*
122: * Set up the hash table for the patterns.
123: */
124: if (subset)
125: tablep = vaxsubset_inittables;
126: else
127: tablep = vax_inittables;
128: for ( ; *tablep; tablep++) {
129: for (pp = *tablep; pp->name[0] != '\0'; pp++) {
130: php = &patshdr[hash(pp->name, &size)];
131: pp->size = size;
132: pp->next = *php;
133: *php = pp;
134: }
135: }
136: /*
137: * Set up the hash table for the instruction stop table.
138: */
139: for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
140: ithp = &inststoptblhdr[hash(itp->name, &size)];
141: itp->size = size;
142: itp->next = *ithp;
143: *ithp = itp;
144: }
145: /*
146: * check each line and replace as appropriate
147: */
148: buftail = bufhead = 0;
149: bufp = line[0];
150: while (fgets(bufp, MAXLINELEN, stdin)) {
151: lineno++;
152: lp = index(bufp, LABELCHAR);
153: if (lp != NULL) {
154: for (cp = bufp; cp < lp; cp++)
155: if (!isalnum(*cp))
156: break;
157: if (cp == lp) {
158: bufp = newline();
159: if (*++lp == '\n') {
160: emptyqueue();
161: continue;
162: }
163: (void) strcpy(bufp, lp);
164: *lp++ = '\n';
165: *lp = '\0';
166: emptyqueue();
167: }
168: }
169: for (cp = bufp; isspace(*cp); cp++)
170: /* void */;
171: if ((cp = doreplaceon(cp)) == 0) {
172: bufp = newline();
173: continue;
174: }
175: for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
176: if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
177: if (argcounterr(pp->args, countargs(bufp), pp->name)) {
178: pp = NULL;
179: break;
180: }
181: expand(pp->replace);
182: bufp = line[bufhead];
183: break;
184: }
185: }
186: if (!pp) {
187: emptyqueue();
188: fputs(bufp, stdout);
189: }
190: }
191: emptyqueue();
192: if (dflag)
193: fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
194: whoami,
195: "attempts", stats.attempted,
196: "finished", stats.finished,
197: "inhibited", stats.lostmodified,
198: "merged", stats.savedpush);
199: exit(0);
200: }
201:
202: /*
203: * Integrate an expansion into the assembly stream
204: */
205: expand(replace)
206: char *replace;
207: {
208: register int curptr;
209: char *nextreplace, *argv[MAXARGS];
210: int argc, argreg, foundarg, mod = 0, args = 0;
211: char parsebuf[BUFSIZ];
212:
213: stats.attempted++;
214: for (curptr = bufhead; ; ) {
215: nextreplace = copyline(replace, line[bufhead]);
216: argc = parseline(line[bufhead], argv, parsebuf);
217: argreg = nextarg(argc, argv);
218: if (argreg == -1)
219: break;
220: args++;
221: for (foundarg = 0; curptr != buftail; ) {
222: curptr = PRED(curptr);
223: argc = parseline(line[curptr], argv, parsebuf);
224: if (isendofblock(argc, argv))
225: break;
226: if (foundarg = ispusharg(argc, argv))
227: break;
228: mod |= 1 << modifies(argc, argv);
229: }
230: if (!foundarg)
231: break;
232: replace = nextreplace;
233: if (mod & (1 << argreg)) {
234: stats.lostmodified++;
235: if (curptr == buftail) {
236: (void)newline();
237: break;
238: }
239: (void)newline();
240: } else {
241: stats.savedpush++;
242: rewrite(line[curptr], argc, argv, argreg);
243: mod |= 1 << argreg;
244: }
245: }
246: if (argreg == -1)
247: stats.finished++;
248: emptyqueue();
249: fputs(replace, stdout);
250: cleanup(args);
251: }
252:
253: /*
254: * Parse a line of assembly language into opcode and arguments.
255: */
256: parseline(linep, argv, linebuf)
257: char *linep;
258: char *argv[];
259: char *linebuf;
260: {
261: register char *bufp = linebuf, *cp = linep;
262: register int argc = 0;
263:
264: for (;;) {
265: /*
266: * skip over white space
267: */
268: while (isspace(*cp))
269: cp++;
270: if (*cp == '\0')
271: return (argc);
272: /*
273: * copy argument
274: */
275: if (argc == MAXARGS - 1) {
276: fprintf(stderr, "instruction too long->%s", linep);
277: return (argc);
278: }
279: argv[argc++] = bufp;
280: while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
281: *bufp++ = *cp++;
282: *bufp++ = '\0';
283: if (*cp == COMMENTCHAR)
284: return (argc);
285: if (*cp == ARGSEPCHAR)
286: cp++;
287: }
288: }
289:
290: /*
291: * Check for instructions that end a basic block.
292: */
293: isendofblock(argc, argv)
294: int argc;
295: char *argv[];
296: {
297: register struct inststoptbl *itp;
298: int size;
299:
300: if (argc == 0)
301: return (0);
302: for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
303: if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
304: return (1);
305: return (0);
306: }
307:
308: /*
309: * Copy a newline terminated string.
310: * Return pointer to character following last character copied.
311: */
312: char *
313: copyline(from, to)
314: register char *from, *to;
315: {
316:
317: while (*from != '\n')
318: *to++ = *from++;
319: *to++ = *from++;
320: *to = '\0';
321: return (from);
322: }
323:
324: /*
325: * Check for a disparity between the number of arguments a function
326: * is called with and the number which we expect to see.
327: * If the error is unrecoverable, return 1, otherwise 0.
328: */
329: argcounterr(args, callargs, name)
330: int args, callargs;
331: char *name;
332: {
333: register char *cp;
334: char namebuf[MAXLINELEN];
335:
336: if (args == callargs)
337: return (0);
338: cp = strcpy(namebuf, name);
339: while (*cp != '\0' && *cp != '\n')
340: ++cp;
341: if (*cp == '\n')
342: *cp = '\0';
343: if (callargs >= 0) {
344: fprintf(stderr,
345: "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
346: whoami, callargs, args, namebuf, lineno);
347: return (1);
348: }
349: fprintf(stderr,
350: "%s: warning: can't verify arg count for '%s' at line %d\n",
351: whoami, namebuf, lineno);
352: return (0);
353: }
354:
355: /*
356: * open space for next line in the queue
357: */
358: char *
359: newline()
360: {
361: bufhead = SUCC(bufhead);
362: if (bufhead == buftail) {
363: fputs(line[buftail], stdout);
364: buftail = SUCC(buftail);
365: }
366: return (line[bufhead]);
367: }
368:
369: /*
370: * empty the queue by printing out all its lines.
371: */
372: emptyqueue()
373: {
374: while (buftail != bufhead) {
375: fputs(line[buftail], stdout);
376: buftail = SUCC(buftail);
377: }
378: }
379:
380: /*
381: * Compute the hash of a string.
382: * Return the hash and the size of the item hashed
383: */
384: hash(cp, size)
385: char *cp;
386: int *size;
387: {
388: register char *cp1 = cp;
389: register int hash = 0;
390:
391: while (*cp1 && *cp1 != '\n')
392: hash += (int)*cp1++;
393: *size = cp1 - cp + 1;
394: hash &= HSHSIZ - 1;
395: return (hash);
396: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.