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