1*23350Smckusick /* 2*23350Smckusick * Copyright (c) 1984 Regents of the University of California. 3*23350Smckusick * All rights reserved. The Berkeley software License Agreement 4*23350Smckusick * specifies the terms and conditions for redistribution. 5*23350Smckusick */ 616962Smckusick 716962Smckusick #ifndef lint 8*23350Smckusick char copyright[] = 9*23350Smckusick "@(#) Copyright (c) 1984 Regents of the University of California.\n\ 10*23350Smckusick All rights reserved.\n"; 1116962Smckusick #endif not lint 1216962Smckusick 13*23350Smckusick #ifndef lint 14*23350Smckusick static char sccsid[] = "@(#)main.c 1.8 (Berkeley) 06/08/85"; 15*23350Smckusick #endif not lint 16*23350Smckusick 1716962Smckusick #include <stdio.h> 1816962Smckusick #include <ctype.h> 1916963Smckusick #include "inline.h" 2016962Smckusick 2116975Smckusick /* 2216975Smckusick * These are the pattern tables to be loaded 2316975Smckusick */ 2416975Smckusick struct pats *inittables[] = { 2516975Smckusick language_ptab, 2616975Smckusick libc_ptab, 2716975Smckusick machine_ptab, 2816975Smckusick 0 2916975Smckusick }; 3016975Smckusick 3116980Smckusick /* 3216980Smckusick * Statistics collection 3316980Smckusick */ 3416980Smckusick struct stats { 3516980Smckusick int attempted; /* number of expansion attempts */ 3616980Smckusick int finished; /* expansions done before end of basic block */ 3716980Smckusick int lostmodified; /* mergers inhibited by intervening mod */ 3816980Smckusick int savedpush; /* successful push/pop merger */ 3916980Smckusick } stats; 4016980Smckusick int dflag; 4116980Smckusick 4216962Smckusick main(argc, argv) 4316962Smckusick int argc; 4416962Smckusick char *argv[]; 4516962Smckusick { 4616962Smckusick register char *cp, *lp; 4716962Smckusick register char *bufp; 4816978Smckusick register struct pats *pp, **php; 4916978Smckusick struct pats **tablep; 5016978Smckusick register struct inststoptbl *itp, **ithp; 5116962Smckusick int size; 5216962Smckusick extern char *index(); 5316962Smckusick 5416980Smckusick if (argc > 1 && bcmp(argv[1], "-d", 3) == 0) 5516980Smckusick dflag++, argc--, argv++; 5616962Smckusick if (argc > 1) 5716962Smckusick freopen(argv[1], "r", stdin); 5816962Smckusick if (argc > 2) 5916962Smckusick freopen(argv[2], "w", stdout); 6016962Smckusick /* 6116978Smckusick * Set up the hash table for the patterns. 6216962Smckusick */ 6316975Smckusick for (tablep = inittables; *tablep; tablep++) { 6416975Smckusick for (pp = *tablep; pp->name[0] != '\0'; pp++) { 6516978Smckusick php = &patshdr[hash(pp->name, &size)]; 6616975Smckusick pp->size = size; 6716978Smckusick pp->next = *php; 6816978Smckusick *php = pp; 6916975Smckusick } 7016962Smckusick } 7116962Smckusick /* 7216978Smckusick * Set up the hash table for the instruction stop table. 7316978Smckusick */ 7416978Smckusick for (itp = inststoptable; itp->name[0] != '\0'; itp++) { 7516978Smckusick ithp = &inststoptblhdr[hash(itp->name, &size)]; 7616978Smckusick itp->size = size; 7716978Smckusick itp->next = *ithp; 7816978Smckusick *ithp = itp; 7916978Smckusick } 8016978Smckusick /* 8116962Smckusick * check each line and replace as appropriate 8216962Smckusick */ 8316962Smckusick buftail = bufhead = 0; 8416962Smckusick bufp = line[0]; 8516962Smckusick while (fgets(bufp, MAXLINELEN, stdin)) { 8616962Smckusick lp = index(bufp, LABELCHAR); 8716962Smckusick if (lp != NULL) { 8818448Smckusick for (cp = bufp; cp < lp; cp++) 8918448Smckusick if (!isalnum(*cp)) 9018448Smckusick break; 9118448Smckusick if (cp == lp) { 9218448Smckusick bufp = newline(); 9318448Smckusick if (*++lp == '\n') { 9418448Smckusick emptyqueue(); 9518448Smckusick continue; 9618448Smckusick } 9718448Smckusick strcpy(bufp, lp); 9818448Smckusick *lp++ = '\n'; 9918448Smckusick *lp = '\0'; 10016962Smckusick emptyqueue(); 10116962Smckusick } 10216962Smckusick } 10316962Smckusick for (cp = bufp; isspace(*cp); cp++) 10416962Smckusick /* void */; 10516962Smckusick if ((cp = doreplaceon(cp)) == 0) { 10616962Smckusick bufp = newline(); 10716962Smckusick continue; 10816962Smckusick } 10916978Smckusick for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) { 11016962Smckusick if (pp->size == size && bcmp(pp->name, cp, size) == 0) { 11116962Smckusick expand(pp->replace); 11216962Smckusick bufp = line[bufhead]; 11316962Smckusick break; 11416962Smckusick } 11516962Smckusick } 11616962Smckusick if (!pp) { 11716962Smckusick emptyqueue(); 11816962Smckusick fputs(bufp, stdout); 11916962Smckusick } 12016962Smckusick } 12116962Smckusick emptyqueue(); 12216980Smckusick if (dflag) 12316980Smckusick fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n", 12416980Smckusick "attempts", stats.attempted, 12516980Smckusick "finished", stats.finished, 12616980Smckusick "inhibited", stats.lostmodified, 12716980Smckusick "merged", stats.savedpush); 12816962Smckusick exit(0); 12916962Smckusick } 13016962Smckusick 13116962Smckusick /* 13216962Smckusick * Integrate an expansion into the assembly stream 13316962Smckusick */ 13416962Smckusick expand(replace) 13516962Smckusick char *replace; 13616962Smckusick { 13716962Smckusick register int curptr; 13816962Smckusick char *nextreplace, *argv[MAXARGS]; 13917202Smckusick int argc, argreg, foundarg, mod = 0, args = 0; 14016962Smckusick char parsebuf[BUFSIZ]; 14116962Smckusick 14216980Smckusick stats.attempted++; 14316980Smckusick for (curptr = bufhead; ; ) { 14416962Smckusick nextreplace = copyline(replace, line[bufhead]); 14516962Smckusick argc = parseline(line[bufhead], argv, parsebuf); 14616962Smckusick argreg = nextarg(argc, argv); 14716962Smckusick if (argreg == -1) 14816962Smckusick break; 14917202Smckusick args++; 15016978Smckusick for (foundarg = 0; curptr != buftail; ) { 15116978Smckusick curptr = PRED(curptr); 15216962Smckusick argc = parseline(line[curptr], argv, parsebuf); 15316978Smckusick if (isendofblock(argc, argv)) 15416962Smckusick break; 15516978Smckusick if (foundarg = ispusharg(argc, argv)) 15616978Smckusick break; 15716962Smckusick mod |= 1 << modifies(argc, argv); 15816962Smckusick } 15916978Smckusick if (!foundarg) 16016962Smckusick break; 16116962Smckusick replace = nextreplace; 16216962Smckusick if (mod & (1 << argreg)) { 16316980Smckusick stats.lostmodified++; 16416978Smckusick if (curptr == buftail) { 16516978Smckusick (void)newline(); 16616978Smckusick break; 16716978Smckusick } 16816962Smckusick (void)newline(); 16916962Smckusick } else { 17016980Smckusick stats.savedpush++; 17116962Smckusick rewrite(line[curptr], argc, argv, argreg); 17216962Smckusick mod |= 1 << argreg; 17316962Smckusick } 17416962Smckusick } 17516980Smckusick if (argreg == -1) 17616980Smckusick stats.finished++; 17716962Smckusick emptyqueue(); 17816962Smckusick fputs(replace, stdout); 17917202Smckusick cleanup(args); 18016962Smckusick } 18116962Smckusick 18216962Smckusick /* 18316962Smckusick * Parse a line of assembly language into opcode and arguments. 18416962Smckusick */ 18516962Smckusick parseline(linep, argv, linebuf) 18616962Smckusick char *linep; 18716962Smckusick char *argv[]; 18816962Smckusick char *linebuf; 18916962Smckusick { 19016962Smckusick register char *bufp = linebuf, *cp = linep; 19116962Smckusick register int argc = 0; 19216962Smckusick 19316962Smckusick for (;;) { 19416962Smckusick /* 19516962Smckusick * skip over white space 19616962Smckusick */ 19716962Smckusick while (isspace(*cp)) 19816962Smckusick cp++; 19916962Smckusick if (*cp == '\0') 20016962Smckusick return (argc); 20116962Smckusick /* 20216962Smckusick * copy argument 20316962Smckusick */ 20416962Smckusick if (argc == MAXARGS - 1) { 20516962Smckusick fprintf(stderr, "instruction too long->%s", linep); 20616962Smckusick return (argc); 20716962Smckusick } 20816962Smckusick argv[argc++] = bufp; 20916978Smckusick while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR) 21016962Smckusick *bufp++ = *cp++; 21116962Smckusick *bufp++ = '\0'; 21216962Smckusick if (*cp == COMMENTCHAR) 21316962Smckusick return (argc); 21416978Smckusick if (*cp == ARGSEPCHAR) 21516962Smckusick cp++; 21616962Smckusick } 21716962Smckusick } 21816962Smckusick 21916962Smckusick /* 22016978Smckusick * Check for instructions that end a basic block. 22116978Smckusick */ 22216978Smckusick isendofblock(argc, argv) 22316978Smckusick int argc; 22416978Smckusick char *argv[]; 22516978Smckusick { 22616978Smckusick register struct inststoptbl *itp; 22716978Smckusick int size; 22816978Smckusick 22916978Smckusick if (argc == 0) 23016978Smckusick return (0); 23116978Smckusick for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next) 23216978Smckusick if (itp->size == size && bcmp(argv[0], itp->name, size) == 0) 23316978Smckusick return (1); 23416978Smckusick return (0); 23516978Smckusick } 23616978Smckusick 23716978Smckusick /* 23816962Smckusick * Copy a newline terminated string. 23916962Smckusick * Return pointer to character following last character copied. 24016962Smckusick */ 24116962Smckusick char * 24216962Smckusick copyline(from, to) 24316962Smckusick register char *from, *to; 24416962Smckusick { 24516962Smckusick 24616962Smckusick while (*from != '\n') 24716962Smckusick *to++ = *from++; 24816962Smckusick *to++ = *from++; 24916962Smckusick *to = '\0'; 25016962Smckusick return (from); 25116962Smckusick } 25216962Smckusick 25316962Smckusick /* 25416962Smckusick * open space for next line in the queue 25516962Smckusick */ 25616962Smckusick char * 25716962Smckusick newline() 25816962Smckusick { 25916962Smckusick bufhead = SUCC(bufhead); 26016962Smckusick if (bufhead == buftail) { 26116962Smckusick fputs(line[buftail], stdout); 26216962Smckusick buftail = SUCC(buftail); 26316962Smckusick } 26416962Smckusick return (line[bufhead]); 26516962Smckusick } 26616962Smckusick 26716962Smckusick /* 26816962Smckusick * empty the queue by printing out all its lines. 26916962Smckusick */ 27016962Smckusick emptyqueue() 27116962Smckusick { 27216962Smckusick while (buftail != bufhead) { 27316962Smckusick fputs(line[buftail], stdout); 27416962Smckusick buftail = SUCC(buftail); 27516962Smckusick } 27616962Smckusick } 27716962Smckusick 27816962Smckusick /* 27916962Smckusick * Compute the hash of a string. 28016962Smckusick * Return the hash and the size of the item hashed 28116962Smckusick */ 28216962Smckusick hash(cp, size) 28316962Smckusick char *cp; 28416962Smckusick int *size; 28516962Smckusick { 28616962Smckusick register char *cp1 = cp; 28716978Smckusick register int hash = 0; 28816962Smckusick 28916962Smckusick while (*cp1 && *cp1 != '\n') 29016962Smckusick hash += (int)*cp1++; 29116962Smckusick *size = cp1 - cp + 1; 29216962Smckusick hash &= HSHSIZ - 1; 29316978Smckusick return (hash); 29416962Smckusick } 295