|
|
1.1 root 1: /*
2: * Copyright (c) 1984, 1986 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
8: char copyright[] =
9: "@(#) Copyright (c) 1984, 1986 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)main.c 7.1 (Berkeley) 6/5/86";
15: #endif not lint
16:
17: #include <stdio.h>
18: #include <ctype.h>
19: #include "inline.h"
20:
21: /*
22: * These are the pattern tables to be loaded
23: */
24: struct pats *vax_inittables[] = {
25: language_ptab,
26: libc_ptab,
27: vax_libc_ptab,
28: machine_ptab,
29: vax_ptab,
30: 0
31: };
32:
33: struct pats *vaxsubset_inittables[] = {
34: language_ptab,
35: libc_ptab,
36: vaxsubset_libc_ptab,
37: machine_ptab,
38: vaxsubset_ptab,
39: 0
40: };
41:
42: /*
43: * Statistics collection
44: */
45: struct 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;
51:
52: extern char *strcpy();
53:
54: char *whoami;
55: int lineno = 0;
56: int dflag;
57:
58: main(argc, argv)
59: int argc;
60: char *argv[];
61: {
62: register char *cp, *lp;
63: register char *bufp;
64: register struct pats *pp, **php;
65: struct pats **tablep;
66: register struct inststoptbl *itp, **ithp;
67: int size;
68: extern char *index();
69: int subset = 0;
70:
71: whoami = argv[0];
72: argc--;
73: argv++;
74: while (argc > 0 && argv[0][0] == '-') {
75: switch(argv[0][1]) {
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: }
90: if (argc > 0)
91: freopen(argv[0], "r", stdin);
92: if (argc > 1)
93: freopen(argv[1], "w", stdout);
94: /*
95: * Set up the hash table for the patterns.
96: */
97: if (subset)
98: tablep = vaxsubset_inittables;
99: else
100: tablep = vax_inittables;
101: for ( ; *tablep; tablep++) {
102: for (pp = *tablep; pp->name[0] != '\0'; pp++) {
103: php = &patshdr[hash(pp->name, &size)];
104: pp->size = size;
105: pp->next = *php;
106: *php = pp;
107: }
108: }
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: }
118: /*
119: * check each line and replace as appropriate
120: */
121: buftail = bufhead = 0;
122: bufp = line[0];
123: while (fgets(bufp, MAXLINELEN, stdin)) {
124: lineno++;
125: lp = index(bufp, LABELCHAR);
126: if (lp != NULL) {
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: }
136: (void) strcpy(bufp, lp);
137: *lp++ = '\n';
138: *lp = '\0';
139: emptyqueue();
140: }
141: }
142: for (cp = bufp; isspace(*cp); cp++)
143: /* void */;
144: if ((cp = doreplaceon(cp)) == 0) {
145: bufp = newline();
146: continue;
147: }
148: for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
149: if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
150: if (argcounterr(pp->args, countargs(bufp), pp->name)) {
151: pp = NULL;
152: break;
153: }
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();
165: if (dflag)
166: fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
167: whoami,
168: "attempts", stats.attempted,
169: "finished", stats.finished,
170: "inhibited", stats.lostmodified,
171: "merged", stats.savedpush);
172: exit(0);
173: }
174:
175: /*
176: * Integrate an expansion into the assembly stream
177: */
178: expand(replace)
179: char *replace;
180: {
181: register int curptr;
182: char *nextreplace, *argv[MAXARGS];
183: int argc, argreg, foundarg, mod = 0, args = 0;
184: char parsebuf[BUFSIZ];
185:
186: stats.attempted++;
187: for (curptr = bufhead; ; ) {
188: nextreplace = copyline(replace, line[bufhead]);
189: argc = parseline(line[bufhead], argv, parsebuf);
190: argreg = nextarg(argc, argv);
191: if (argreg == -1)
192: break;
193: args++;
194: for (foundarg = 0; curptr != buftail; ) {
195: curptr = PRED(curptr);
196: argc = parseline(line[curptr], argv, parsebuf);
197: if (isendofblock(argc, argv))
198: break;
199: if (foundarg = ispusharg(argc, argv))
200: break;
201: mod |= 1 << modifies(argc, argv);
202: }
203: if (!foundarg)
204: break;
205: replace = nextreplace;
206: if (mod & (1 << argreg)) {
207: stats.lostmodified++;
208: if (curptr == buftail) {
209: (void)newline();
210: break;
211: }
212: (void)newline();
213: } else {
214: stats.savedpush++;
215: rewrite(line[curptr], argc, argv, argreg);
216: mod |= 1 << argreg;
217: }
218: }
219: if (argreg == -1)
220: stats.finished++;
221: emptyqueue();
222: fputs(replace, stdout);
223: cleanup(args);
224: }
225:
226: /*
227: * Parse a line of assembly language into opcode and arguments.
228: */
229: parseline(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;
253: while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
254: *bufp++ = *cp++;
255: *bufp++ = '\0';
256: if (*cp == COMMENTCHAR)
257: return (argc);
258: if (*cp == ARGSEPCHAR)
259: cp++;
260: }
261: }
262:
263: /*
264: * Check for instructions that end a basic block.
265: */
266: isendofblock(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:
281: /*
282: * Copy a newline terminated string.
283: * Return pointer to character following last character copied.
284: */
285: char *
286: copyline(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:
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: */
302: argcounterr(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:
328: /*
329: * open space for next line in the queue
330: */
331: char *
332: newline()
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: */
345: emptyqueue()
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: */
357: hash(cp, size)
358: char *cp;
359: int *size;
360: {
361: register char *cp1 = cp;
362: register int hash = 0;
363:
364: while (*cp1 && *cp1 != '\n')
365: hash += (int)*cp1++;
366: *size = cp1 - cp + 1;
367: hash &= HSHSIZ - 1;
368: return (hash);
369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.