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