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