xref: /csrg-svn/sys/vax/inline/main.c (revision 16978)
1 /* Copyright (c) 1984 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)main.c	1.4	(Berkeley)	08/20/84";
5 #endif not lint
6 
7 #include <stdio.h>
8 #include <ctype.h>
9 #include "inline.h"
10 
11 /*
12  * These are the pattern tables to be loaded
13  */
14 struct pats *inittables[] = {
15 	language_ptab,
16 	libc_ptab,
17 	machine_ptab,
18 	0
19 };
20 
21 main(argc, argv)
22 	int argc;
23 	char *argv[];
24 {
25 	register char *cp, *lp;
26 	register char *bufp;
27 	register struct pats *pp, **php;
28 	struct pats **tablep;
29 	register struct inststoptbl *itp, **ithp;
30 	int size;
31 	extern char *index();
32 
33 	if (argc > 1)
34 		freopen(argv[1], "r", stdin);
35 	if (argc > 2)
36 		freopen(argv[2], "w", stdout);
37 	/*
38 	 * Set up the hash table for the patterns.
39 	 */
40 	for (tablep = inittables; *tablep; tablep++) {
41 		for (pp = *tablep; pp->name[0] != '\0'; pp++) {
42 			php = &patshdr[hash(pp->name, &size)];
43 			pp->size = size;
44 			pp->next = *php;
45 			*php = pp;
46 		}
47 	}
48 	/*
49 	 * Set up the hash table for the instruction stop table.
50 	 */
51 	for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
52 		ithp = &inststoptblhdr[hash(itp->name, &size)];
53 		itp->size = size;
54 		itp->next = *ithp;
55 		*ithp = itp;
56 	}
57 	/*
58 	 * check each line and replace as appropriate
59 	 */
60 	buftail = bufhead = 0;
61 	bufp = line[0];
62 	while (fgets(bufp, MAXLINELEN, stdin)) {
63 		lp = index(bufp, LABELCHAR);
64 		if (lp != NULL) {
65 			bufp = newline();
66 			if (*++lp == '\n') {
67 				emptyqueue();
68 				continue;
69 			}
70 			strcpy(bufp, lp);
71 			*lp++ = '\n';
72 			*lp = '\0';
73 			emptyqueue();
74 		}
75 		for (cp = bufp; isspace(*cp); cp++)
76 			/* void */;
77 		if ((cp = doreplaceon(cp)) == 0) {
78 			bufp = newline();
79 			continue;
80 		}
81 		for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
82 			if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
83 				expand(pp->replace);
84 				bufp = line[bufhead];
85 				break;
86 			}
87 		}
88 		if (!pp) {
89 			emptyqueue();
90 			fputs(bufp, stdout);
91 		}
92 	}
93 	emptyqueue();
94 	exit(0);
95 }
96 
97 /*
98  * Integrate an expansion into the assembly stream
99  */
100 expand(replace)
101 	char *replace;
102 {
103 	register int curptr;
104 	char *nextreplace, *argv[MAXARGS];
105 	int argc, argreg, foundarg, mod = 0;
106 	char parsebuf[BUFSIZ];
107 
108 	for (curptr = bufhead; curptr != buftail; ) {
109 		nextreplace = copyline(replace, line[bufhead]);
110 		argc = parseline(line[bufhead], argv, parsebuf);
111 		argreg = nextarg(argc, argv);
112 		if (argreg == -1)
113 			break;
114 		for (foundarg = 0; curptr != buftail; ) {
115 			curptr = PRED(curptr);
116 			argc = parseline(line[curptr], argv, parsebuf);
117 			if (isendofblock(argc, argv))
118 				break;
119 			if (foundarg = ispusharg(argc, argv))
120 				break;
121 			mod |= 1 << modifies(argc, argv);
122 		}
123 		if (!foundarg)
124 			break;
125 		replace = nextreplace;
126 		if (mod & (1 << argreg)) {
127 			if (curptr == buftail) {
128 				(void)newline();
129 				break;
130 			}
131 			(void)newline();
132 		} else {
133 			rewrite(line[curptr], argc, argv, argreg);
134 			mod |= 1 << argreg;
135 		}
136 	}
137 	emptyqueue();
138 	fputs(replace, stdout);
139 }
140 
141 /*
142  * Parse a line of assembly language into opcode and arguments.
143  */
144 parseline(linep, argv, linebuf)
145 	char *linep;
146 	char *argv[];
147 	char *linebuf;
148 {
149 	register char *bufp = linebuf, *cp = linep;
150 	register int argc = 0;
151 
152 	for (;;) {
153 		/*
154 		 * skip over white space
155 		 */
156 		while (isspace(*cp))
157 			cp++;
158 		if (*cp == '\0')
159 			return (argc);
160 		/*
161 		 * copy argument
162 		 */
163 		if (argc == MAXARGS - 1) {
164 			fprintf(stderr, "instruction too long->%s", linep);
165 			return (argc);
166 		}
167 		argv[argc++] = bufp;
168 		while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
169 			*bufp++ = *cp++;
170 		*bufp++ = '\0';
171 		if (*cp == COMMENTCHAR)
172 			return (argc);
173 		if (*cp == ARGSEPCHAR)
174 			cp++;
175 	}
176 }
177 
178 /*
179  * Check for instructions that end a basic block.
180  */
181 isendofblock(argc, argv)
182 	int argc;
183 	char *argv[];
184 {
185 	register struct inststoptbl *itp;
186 	int size;
187 
188 	if (argc == 0)
189 		return (0);
190 	for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
191 		if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
192 			return (1);
193 	return (0);
194 }
195 
196 /*
197  * Copy a newline terminated string.
198  * Return pointer to character following last character copied.
199  */
200 char *
201 copyline(from, to)
202 	register char *from, *to;
203 {
204 
205 	while (*from != '\n')
206 		*to++ = *from++;
207 	*to++ = *from++;
208 	*to = '\0';
209 	return (from);
210 }
211 
212 /*
213  * open space for next line in the queue
214  */
215 char *
216 newline()
217 {
218 	bufhead = SUCC(bufhead);
219 	if (bufhead == buftail) {
220 		fputs(line[buftail], stdout);
221 		buftail = SUCC(buftail);
222 	}
223 	return (line[bufhead]);
224 }
225 
226 /*
227  * empty the queue by printing out all its lines.
228  */
229 emptyqueue()
230 {
231 	while (buftail != bufhead) {
232 		fputs(line[buftail], stdout);
233 		buftail = SUCC(buftail);
234 	}
235 }
236 
237 /*
238  * Compute the hash of a string.
239  * Return the hash and the size of the item hashed
240  */
241 hash(cp, size)
242 	char *cp;
243 	int *size;
244 {
245 	register char *cp1 = cp;
246 	register int hash = 0;
247 
248 	while (*cp1 && *cp1 != '\n')
249 		hash += (int)*cp1++;
250 	*size = cp1 - cp + 1;
251 	hash &= HSHSIZ - 1;
252 	return (hash);
253 }
254