1 /* Copyright (c) 1984 Regents of the University of California */ 2 3 #ifndef lint 4 static char sccsid[] = "@(#)main.c 1.7 (Berkeley) 03/20/85"; 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 for (cp = bufp; cp < lp; cp++) 79 if (!isalnum(*cp)) 80 break; 81 if (cp == lp) { 82 bufp = newline(); 83 if (*++lp == '\n') { 84 emptyqueue(); 85 continue; 86 } 87 strcpy(bufp, lp); 88 *lp++ = '\n'; 89 *lp = '\0'; 90 emptyqueue(); 91 } 92 } 93 for (cp = bufp; isspace(*cp); cp++) 94 /* void */; 95 if ((cp = doreplaceon(cp)) == 0) { 96 bufp = newline(); 97 continue; 98 } 99 for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) { 100 if (pp->size == size && bcmp(pp->name, cp, size) == 0) { 101 expand(pp->replace); 102 bufp = line[bufhead]; 103 break; 104 } 105 } 106 if (!pp) { 107 emptyqueue(); 108 fputs(bufp, stdout); 109 } 110 } 111 emptyqueue(); 112 if (dflag) 113 fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n", 114 "attempts", stats.attempted, 115 "finished", stats.finished, 116 "inhibited", stats.lostmodified, 117 "merged", stats.savedpush); 118 exit(0); 119 } 120 121 /* 122 * Integrate an expansion into the assembly stream 123 */ 124 expand(replace) 125 char *replace; 126 { 127 register int curptr; 128 char *nextreplace, *argv[MAXARGS]; 129 int argc, argreg, foundarg, mod = 0, args = 0; 130 char parsebuf[BUFSIZ]; 131 132 stats.attempted++; 133 for (curptr = bufhead; ; ) { 134 nextreplace = copyline(replace, line[bufhead]); 135 argc = parseline(line[bufhead], argv, parsebuf); 136 argreg = nextarg(argc, argv); 137 if (argreg == -1) 138 break; 139 args++; 140 for (foundarg = 0; curptr != buftail; ) { 141 curptr = PRED(curptr); 142 argc = parseline(line[curptr], argv, parsebuf); 143 if (isendofblock(argc, argv)) 144 break; 145 if (foundarg = ispusharg(argc, argv)) 146 break; 147 mod |= 1 << modifies(argc, argv); 148 } 149 if (!foundarg) 150 break; 151 replace = nextreplace; 152 if (mod & (1 << argreg)) { 153 stats.lostmodified++; 154 if (curptr == buftail) { 155 (void)newline(); 156 break; 157 } 158 (void)newline(); 159 } else { 160 stats.savedpush++; 161 rewrite(line[curptr], argc, argv, argreg); 162 mod |= 1 << argreg; 163 } 164 } 165 if (argreg == -1) 166 stats.finished++; 167 emptyqueue(); 168 fputs(replace, stdout); 169 cleanup(args); 170 } 171 172 /* 173 * Parse a line of assembly language into opcode and arguments. 174 */ 175 parseline(linep, argv, linebuf) 176 char *linep; 177 char *argv[]; 178 char *linebuf; 179 { 180 register char *bufp = linebuf, *cp = linep; 181 register int argc = 0; 182 183 for (;;) { 184 /* 185 * skip over white space 186 */ 187 while (isspace(*cp)) 188 cp++; 189 if (*cp == '\0') 190 return (argc); 191 /* 192 * copy argument 193 */ 194 if (argc == MAXARGS - 1) { 195 fprintf(stderr, "instruction too long->%s", linep); 196 return (argc); 197 } 198 argv[argc++] = bufp; 199 while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR) 200 *bufp++ = *cp++; 201 *bufp++ = '\0'; 202 if (*cp == COMMENTCHAR) 203 return (argc); 204 if (*cp == ARGSEPCHAR) 205 cp++; 206 } 207 } 208 209 /* 210 * Check for instructions that end a basic block. 211 */ 212 isendofblock(argc, argv) 213 int argc; 214 char *argv[]; 215 { 216 register struct inststoptbl *itp; 217 int size; 218 219 if (argc == 0) 220 return (0); 221 for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next) 222 if (itp->size == size && bcmp(argv[0], itp->name, size) == 0) 223 return (1); 224 return (0); 225 } 226 227 /* 228 * Copy a newline terminated string. 229 * Return pointer to character following last character copied. 230 */ 231 char * 232 copyline(from, to) 233 register char *from, *to; 234 { 235 236 while (*from != '\n') 237 *to++ = *from++; 238 *to++ = *from++; 239 *to = '\0'; 240 return (from); 241 } 242 243 /* 244 * open space for next line in the queue 245 */ 246 char * 247 newline() 248 { 249 bufhead = SUCC(bufhead); 250 if (bufhead == buftail) { 251 fputs(line[buftail], stdout); 252 buftail = SUCC(buftail); 253 } 254 return (line[bufhead]); 255 } 256 257 /* 258 * empty the queue by printing out all its lines. 259 */ 260 emptyqueue() 261 { 262 while (buftail != bufhead) { 263 fputs(line[buftail], stdout); 264 buftail = SUCC(buftail); 265 } 266 } 267 268 /* 269 * Compute the hash of a string. 270 * Return the hash and the size of the item hashed 271 */ 272 hash(cp, size) 273 char *cp; 274 int *size; 275 { 276 register char *cp1 = cp; 277 register int hash = 0; 278 279 while (*cp1 && *cp1 != '\n') 280 hash += (int)*cp1++; 281 *size = cp1 - cp + 1; 282 hash &= HSHSIZ - 1; 283 return (hash); 284 } 285