|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1984 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: */ ! 33: ! 34: #ifndef lint ! 35: char copyright[] = ! 36: "@(#) Copyright (c) 1984 The Regents of the University of California.\n\ ! 37: All rights reserved.\n"; ! 38: #endif /* not lint */ ! 39: ! 40: #ifndef lint ! 41: static char sccsid[] = "@(#)main.c 1.4 (Berkeley) 5/8/91"; ! 42: #endif /* not lint */ ! 43: ! 44: #include <stdio.h> ! 45: #include <ctype.h> ! 46: #include "inline.h" ! 47: ! 48: /* ! 49: * These are the pattern tables to be loaded ! 50: */ ! 51: struct pats *inittables[] = { ! 52: language_ptab, ! 53: libc_ptab, ! 54: machine_ptab, ! 55: 0 ! 56: }; ! 57: ! 58: /* ! 59: * Statistics collection ! 60: */ ! 61: struct stats { ! 62: int attempted; /* number of expansion attempts */ ! 63: int finished; /* expansions done before end of basic block */ ! 64: int lostmodified; /* mergers inhibited by intervening mod */ ! 65: int savedpush; /* successful push/pop merger */ ! 66: } stats; ! 67: ! 68: extern char *strcpy(); ! 69: ! 70: char *whoami; ! 71: int lineno = 0; ! 72: int dflag; ! 73: ! 74: main(argc, argv) ! 75: int argc; ! 76: char *argv[]; ! 77: { ! 78: register char *cp, *lp; ! 79: register char *bufp; ! 80: register struct pats *pp, **php; ! 81: struct pats **tablep; ! 82: register struct inststoptbl *itp, **ithp; ! 83: int size; ! 84: extern char *index(); ! 85: ! 86: whoami = argv[0]; ! 87: if (argc > 1 && bcmp(argv[1], "-d", 3) == 0) ! 88: dflag++, argc--, argv++; ! 89: if (argc > 1) ! 90: freopen(argv[1], "r", stdin); ! 91: if (argc > 2) ! 92: freopen(argv[2], "w", stdout); ! 93: /* ! 94: * Set up the hash table for the patterns. ! 95: */ ! 96: for (tablep = inittables; *tablep; tablep++) { ! 97: for (pp = *tablep; pp->name[0] != '\0'; pp++) { ! 98: php = &patshdr[hash(pp->name, &size)]; ! 99: pp->size = size; ! 100: pp->next = *php; ! 101: *php = pp; ! 102: } ! 103: } ! 104: /* ! 105: * Set up the hash table for the instruction stop table. ! 106: */ ! 107: for (itp = inststoptable; itp->name[0] != '\0'; itp++) { ! 108: ithp = &inststoptblhdr[hash(itp->name, &size)]; ! 109: itp->size = size; ! 110: itp->next = *ithp; ! 111: *ithp = itp; ! 112: } ! 113: /* ! 114: * check each line and replace as appropriate ! 115: */ ! 116: buftail = bufhead = 0; ! 117: bufp = line[0]; ! 118: while (fgets(bufp, MAXLINELEN, stdin)) { ! 119: lineno++; ! 120: lp = index(bufp, LABELCHAR); ! 121: if (lp != NULL) { ! 122: for (cp = bufp; cp < lp; cp++) ! 123: if (!isalnum(*cp)) ! 124: break; ! 125: if (cp == lp) { ! 126: bufp = newline(); ! 127: if (*++lp == '\n') { ! 128: emptyqueue(); ! 129: continue; ! 130: } ! 131: (void) strcpy(bufp, lp); ! 132: *lp++ = '\n'; ! 133: *lp = '\0'; ! 134: emptyqueue(); ! 135: } ! 136: } ! 137: for (cp = bufp; isspace(*cp); cp++) ! 138: /* void */; ! 139: if ((cp = doreplaceon(cp)) == 0) { ! 140: bufp = newline(); ! 141: continue; ! 142: } ! 143: for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) { ! 144: if (pp->size == size && bcmp(pp->name, cp, size) == 0) { ! 145: if (argcounterr(pp->args, countargs(bufp), ! 146: pp->name)) { ! 147: pp = NULL; ! 148: break; ! 149: } ! 150: expand(pp->replace); ! 151: bufp = line[bufhead]; ! 152: break; ! 153: } ! 154: } ! 155: if (!pp) { ! 156: emptyqueue(); ! 157: fputs(bufp, stdout); ! 158: } ! 159: } ! 160: emptyqueue(); ! 161: if (dflag) ! 162: fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n", ! 163: whoami, ! 164: "attempts", stats.attempted, ! 165: "finished", stats.finished, ! 166: "inhibited", stats.lostmodified, ! 167: "merged", stats.savedpush); ! 168: exit(0); ! 169: } ! 170: ! 171: /* ! 172: * Integrate an expansion into the assembly stream ! 173: */ ! 174: expand(replace) ! 175: char *replace; ! 176: { ! 177: register int curptr; ! 178: char *nextreplace, *argv[MAXARGS]; ! 179: int argc, argreg, foundarg, mod = 0, args = 0; ! 180: char parsebuf[BUFSIZ]; ! 181: ! 182: stats.attempted++; ! 183: for (curptr = bufhead; ; ) { ! 184: nextreplace = copyline(replace, line[bufhead]); ! 185: argc = parseline(line[bufhead], argv, parsebuf); ! 186: argreg = nextarg(argc, argv); ! 187: if (argreg == -1) ! 188: break; ! 189: args++; ! 190: for (foundarg = 0; curptr != buftail; ) { ! 191: curptr = PRED(curptr); ! 192: argc = parseline(line[curptr], argv, parsebuf); ! 193: if (isendofblock(argc, argv)) ! 194: break; ! 195: if (foundarg = ispusharg(argc, argv)) ! 196: break; ! 197: mod |= 1 << modifies(argc, argv); ! 198: } ! 199: if (!foundarg) ! 200: break; ! 201: replace = nextreplace; ! 202: if (mod & (1 << argreg)) { ! 203: stats.lostmodified++; ! 204: if (curptr == buftail) { ! 205: (void)newline(); ! 206: break; ! 207: } ! 208: (void)newline(); ! 209: } else { ! 210: stats.savedpush++; ! 211: rewrite(line[curptr], argc, argv, argreg); ! 212: mod |= 1 << argreg; ! 213: } ! 214: } ! 215: if (argreg == -1) ! 216: stats.finished++; ! 217: emptyqueue(); ! 218: fputs(replace, stdout); ! 219: cleanup(args); ! 220: } ! 221: ! 222: /* ! 223: * Parse a line of assembly language into opcode and arguments. ! 224: */ ! 225: parseline(linep, argv, linebuf) ! 226: char *linep; ! 227: char *argv[]; ! 228: char *linebuf; ! 229: { ! 230: register char *bufp = linebuf, *cp = linep; ! 231: register int argc = 0; ! 232: ! 233: for (;;) { ! 234: /* ! 235: * skip over white space ! 236: */ ! 237: while (isspace(*cp)) ! 238: cp++; ! 239: if (*cp == '\0') ! 240: return (argc); ! 241: /* ! 242: * copy argument ! 243: */ ! 244: if (argc == MAXARGS - 1) { ! 245: fprintf(stderr, "instruction too long->%s", linep); ! 246: return (argc); ! 247: } ! 248: argv[argc++] = bufp; ! 249: while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR) ! 250: *bufp++ = *cp++; ! 251: *bufp++ = '\0'; ! 252: if (*cp == COMMENTCHAR) ! 253: return (argc); ! 254: if (*cp == ARGSEPCHAR) ! 255: cp++; ! 256: } ! 257: } ! 258: ! 259: /* ! 260: * Check for instructions that end a basic block. ! 261: */ ! 262: isendofblock(argc, argv) ! 263: int argc; ! 264: char *argv[]; ! 265: { ! 266: register struct inststoptbl *itp; ! 267: int size; ! 268: ! 269: if (argc == 0) ! 270: return (0); ! 271: for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next) ! 272: if (itp->size == size && bcmp(argv[0], itp->name, size) == 0) ! 273: return (1); ! 274: return (0); ! 275: } ! 276: ! 277: /* ! 278: * Copy a newline terminated string. ! 279: * Return pointer to character following last character copied. ! 280: */ ! 281: char * ! 282: copyline(from, to) ! 283: register char *from, *to; ! 284: { ! 285: ! 286: while (*from != '\n') ! 287: *to++ = *from++; ! 288: *to++ = *from++; ! 289: *to = '\0'; ! 290: return (from); ! 291: } ! 292: ! 293: /* ! 294: * Check for a disparity between the number of arguments a function ! 295: * is called with and the number which we expect to see. ! 296: * If the error is unrecoverable, return 1, otherwise 0. ! 297: */ ! 298: argcounterr(args, callargs, name) ! 299: int args, callargs; ! 300: char *name; ! 301: { ! 302: register char *cp; ! 303: char namebuf[MAXLINELEN]; ! 304: ! 305: if (args == callargs) ! 306: return (0); ! 307: cp = strcpy(namebuf, name); ! 308: while (*cp != '\0' && *cp != '\n') ! 309: ++cp; ! 310: if (*cp == '\n') ! 311: *cp = '\0'; ! 312: if (callargs >= 0) { ! 313: fprintf(stderr, ! 314: "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n", ! 315: whoami, callargs, args, namebuf, lineno); ! 316: return (1); ! 317: } ! 318: fprintf(stderr, ! 319: "%s: warning: can't verify arg count for '%s' at line %d\n", ! 320: whoami, namebuf, lineno); ! 321: return (0); ! 322: } ! 323: ! 324: /* ! 325: * open space for next line in the queue ! 326: */ ! 327: char * ! 328: newline() ! 329: { ! 330: bufhead = SUCC(bufhead); ! 331: if (bufhead == buftail) { ! 332: fputs(line[buftail], stdout); ! 333: buftail = SUCC(buftail); ! 334: } ! 335: return (line[bufhead]); ! 336: } ! 337: ! 338: /* ! 339: * empty the queue by printing out all its lines. ! 340: */ ! 341: emptyqueue() ! 342: { ! 343: while (buftail != bufhead) { ! 344: fputs(line[buftail], stdout); ! 345: buftail = SUCC(buftail); ! 346: } ! 347: } ! 348: ! 349: /* ! 350: * Compute the hash of a string. ! 351: * Return the hash and the size of the item hashed ! 352: */ ! 353: hash(cp, size) ! 354: char *cp; ! 355: int *size; ! 356: { ! 357: register char *cp1 = cp; ! 358: register int hash = 0; ! 359: ! 360: while (*cp1 && *cp1 != '\n') ! 361: hash += (int)*cp1++; ! 362: *size = cp1 - cp + 1; ! 363: hash &= HSHSIZ - 1; ! 364: return (hash); ! 365: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.