|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.