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