|
|
1.1 root 1: /*-
2: * Copyright (c) 1984 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 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 1.4 (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 *inittables[] = {
52: language_ptab,
53: libc_ptab,
54: machine_ptab,
55: 0
56: };
57:
58: /*
59: * Statistics collection
60: */
61: struct stats {
62: int attempted; /* number of expansion attempts */
63: int finished; /* expansions done before end of basic block */
64: int lostmodified; /* mergers inhibited by intervening mod */
65: int savedpush; /* successful push/pop merger */
66: } stats;
67:
68: extern char *strcpy();
69:
70: char *whoami;
71: int lineno = 0;
72: int dflag;
73:
74: main(argc, argv)
75: int argc;
76: char *argv[];
77: {
78: register char *cp, *lp;
79: register char *bufp;
80: register struct pats *pp, **php;
81: struct pats **tablep;
82: register struct inststoptbl *itp, **ithp;
83: int size;
84: extern char *index();
85:
86: whoami = argv[0];
87: if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
88: dflag++, argc--, argv++;
89: if (argc > 1)
90: freopen(argv[1], "r", stdin);
91: if (argc > 2)
92: freopen(argv[2], "w", stdout);
93: /*
94: * Set up the hash table for the patterns.
95: */
96: for (tablep = inittables; *tablep; tablep++) {
97: for (pp = *tablep; pp->name[0] != '\0'; pp++) {
98: php = &patshdr[hash(pp->name, &size)];
99: pp->size = size;
100: pp->next = *php;
101: *php = pp;
102: }
103: }
104: /*
105: * Set up the hash table for the instruction stop table.
106: */
107: for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
108: ithp = &inststoptblhdr[hash(itp->name, &size)];
109: itp->size = size;
110: itp->next = *ithp;
111: *ithp = itp;
112: }
113: /*
114: * check each line and replace as appropriate
115: */
116: buftail = bufhead = 0;
117: bufp = line[0];
118: while (fgets(bufp, MAXLINELEN, stdin)) {
119: lineno++;
120: lp = index(bufp, LABELCHAR);
121: if (lp != NULL) {
122: for (cp = bufp; cp < lp; cp++)
123: if (!isalnum(*cp))
124: break;
125: if (cp == lp) {
126: bufp = newline();
127: if (*++lp == '\n') {
128: emptyqueue();
129: continue;
130: }
131: (void) strcpy(bufp, lp);
132: *lp++ = '\n';
133: *lp = '\0';
134: emptyqueue();
135: }
136: }
137: for (cp = bufp; isspace(*cp); cp++)
138: /* void */;
139: if ((cp = doreplaceon(cp)) == 0) {
140: bufp = newline();
141: continue;
142: }
143: for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
144: if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
145: if (argcounterr(pp->args, countargs(bufp),
146: pp->name)) {
147: pp = NULL;
148: break;
149: }
150: expand(pp->replace);
151: bufp = line[bufhead];
152: break;
153: }
154: }
155: if (!pp) {
156: emptyqueue();
157: fputs(bufp, stdout);
158: }
159: }
160: emptyqueue();
161: if (dflag)
162: fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
163: whoami,
164: "attempts", stats.attempted,
165: "finished", stats.finished,
166: "inhibited", stats.lostmodified,
167: "merged", stats.savedpush);
168: exit(0);
169: }
170:
171: /*
172: * Integrate an expansion into the assembly stream
173: */
174: expand(replace)
175: char *replace;
176: {
177: register int curptr;
178: char *nextreplace, *argv[MAXARGS];
179: int argc, argreg, foundarg, mod = 0, args = 0;
180: char parsebuf[BUFSIZ];
181:
182: stats.attempted++;
183: for (curptr = bufhead; ; ) {
184: nextreplace = copyline(replace, line[bufhead]);
185: argc = parseline(line[bufhead], argv, parsebuf);
186: argreg = nextarg(argc, argv);
187: if (argreg == -1)
188: break;
189: args++;
190: for (foundarg = 0; curptr != buftail; ) {
191: curptr = PRED(curptr);
192: argc = parseline(line[curptr], argv, parsebuf);
193: if (isendofblock(argc, argv))
194: break;
195: if (foundarg = ispusharg(argc, argv))
196: break;
197: mod |= 1 << modifies(argc, argv);
198: }
199: if (!foundarg)
200: break;
201: replace = nextreplace;
202: if (mod & (1 << argreg)) {
203: stats.lostmodified++;
204: if (curptr == buftail) {
205: (void)newline();
206: break;
207: }
208: (void)newline();
209: } else {
210: stats.savedpush++;
211: rewrite(line[curptr], argc, argv, argreg);
212: mod |= 1 << argreg;
213: }
214: }
215: if (argreg == -1)
216: stats.finished++;
217: emptyqueue();
218: fputs(replace, stdout);
219: cleanup(args);
220: }
221:
222: /*
223: * Parse a line of assembly language into opcode and arguments.
224: */
225: parseline(linep, argv, linebuf)
226: char *linep;
227: char *argv[];
228: char *linebuf;
229: {
230: register char *bufp = linebuf, *cp = linep;
231: register int argc = 0;
232:
233: for (;;) {
234: /*
235: * skip over white space
236: */
237: while (isspace(*cp))
238: cp++;
239: if (*cp == '\0')
240: return (argc);
241: /*
242: * copy argument
243: */
244: if (argc == MAXARGS - 1) {
245: fprintf(stderr, "instruction too long->%s", linep);
246: return (argc);
247: }
248: argv[argc++] = bufp;
249: while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
250: *bufp++ = *cp++;
251: *bufp++ = '\0';
252: if (*cp == COMMENTCHAR)
253: return (argc);
254: if (*cp == ARGSEPCHAR)
255: cp++;
256: }
257: }
258:
259: /*
260: * Check for instructions that end a basic block.
261: */
262: isendofblock(argc, argv)
263: int argc;
264: char *argv[];
265: {
266: register struct inststoptbl *itp;
267: int size;
268:
269: if (argc == 0)
270: return (0);
271: for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
272: if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
273: return (1);
274: return (0);
275: }
276:
277: /*
278: * Copy a newline terminated string.
279: * Return pointer to character following last character copied.
280: */
281: char *
282: copyline(from, to)
283: register char *from, *to;
284: {
285:
286: while (*from != '\n')
287: *to++ = *from++;
288: *to++ = *from++;
289: *to = '\0';
290: return (from);
291: }
292:
293: /*
294: * Check for a disparity between the number of arguments a function
295: * is called with and the number which we expect to see.
296: * If the error is unrecoverable, return 1, otherwise 0.
297: */
298: argcounterr(args, callargs, name)
299: int args, callargs;
300: char *name;
301: {
302: register char *cp;
303: char namebuf[MAXLINELEN];
304:
305: if (args == callargs)
306: return (0);
307: cp = strcpy(namebuf, name);
308: while (*cp != '\0' && *cp != '\n')
309: ++cp;
310: if (*cp == '\n')
311: *cp = '\0';
312: if (callargs >= 0) {
313: fprintf(stderr,
314: "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
315: whoami, callargs, args, namebuf, lineno);
316: return (1);
317: }
318: fprintf(stderr,
319: "%s: warning: can't verify arg count for '%s' at line %d\n",
320: whoami, namebuf, lineno);
321: return (0);
322: }
323:
324: /*
325: * open space for next line in the queue
326: */
327: char *
328: newline()
329: {
330: bufhead = SUCC(bufhead);
331: if (bufhead == buftail) {
332: fputs(line[buftail], stdout);
333: buftail = SUCC(buftail);
334: }
335: return (line[bufhead]);
336: }
337:
338: /*
339: * empty the queue by printing out all its lines.
340: */
341: emptyqueue()
342: {
343: while (buftail != bufhead) {
344: fputs(line[buftail], stdout);
345: buftail = SUCC(buftail);
346: }
347: }
348:
349: /*
350: * Compute the hash of a string.
351: * Return the hash and the size of the item hashed
352: */
353: hash(cp, size)
354: char *cp;
355: int *size;
356: {
357: register char *cp1 = cp;
358: register int hash = 0;
359:
360: while (*cp1 && *cp1 != '\n')
361: hash += (int)*cp1++;
362: *size = cp1 - cp + 1;
363: hash &= HSHSIZ - 1;
364: return (hash);
365: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.