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