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