123350Smckusick /* 223350Smckusick * Copyright (c) 1984 Regents of the University of California. 323350Smckusick * All rights reserved. The Berkeley software License Agreement 423350Smckusick * specifies the terms and conditions for redistribution. 523350Smckusick */ 616962Smckusick 716962Smckusick #ifndef lint 823350Smckusick char copyright[] = 923350Smckusick "@(#) Copyright (c) 1984 Regents of the University of California.\n\ 1023350Smckusick All rights reserved.\n"; 1116962Smckusick #endif not lint 1216962Smckusick 1323350Smckusick #ifndef lint 14*27899Skarels static char sccsid[] = "@(#)main.c 1.12 (Berkeley) 05/08/86"; 1523350Smckusick #endif not lint 1623350Smckusick 1716962Smckusick #include <stdio.h> 1816962Smckusick #include <ctype.h> 1916963Smckusick #include "inline.h" 2016962Smckusick 2116975Smckusick /* 2216975Smckusick * These are the pattern tables to be loaded 2316975Smckusick */ 2427462Skarels struct pats *vax_inittables[] = { 2516975Smckusick language_ptab, 2616975Smckusick libc_ptab, 2727462Skarels vax_libc_ptab, 2816975Smckusick machine_ptab, 2927462Skarels vax_ptab, 3016975Smckusick 0 3116975Smckusick }; 3216975Smckusick 3327462Skarels struct pats *vaxsubset_inittables[] = { 3427462Skarels language_ptab, 3527462Skarels libc_ptab, 3627462Skarels vaxsubset_libc_ptab, 3727462Skarels machine_ptab, 3827462Skarels vaxsubset_ptab, 3927462Skarels 0 4027462Skarels }; 4127462Skarels 4216980Smckusick /* 4316980Smckusick * Statistics collection 4416980Smckusick */ 4516980Smckusick struct stats { 4616980Smckusick int attempted; /* number of expansion attempts */ 4716980Smckusick int finished; /* expansions done before end of basic block */ 4816980Smckusick int lostmodified; /* mergers inhibited by intervening mod */ 4916980Smckusick int savedpush; /* successful push/pop merger */ 5016980Smckusick } stats; 5124395Smckusick 5224395Smckusick extern char *strcpy(); 5324395Smckusick 5424395Smckusick char *whoami; 5524395Smckusick int lineno = 0; 5616980Smckusick int dflag; 5716980Smckusick 5816962Smckusick main(argc, argv) 5916962Smckusick int argc; 6016962Smckusick char *argv[]; 6116962Smckusick { 6216962Smckusick register char *cp, *lp; 6316962Smckusick register char *bufp; 6416978Smckusick register struct pats *pp, **php; 6516978Smckusick struct pats **tablep; 6616978Smckusick register struct inststoptbl *itp, **ithp; 6716962Smckusick int size; 6816962Smckusick extern char *index(); 6927462Skarels int subset = 0; 7016962Smckusick 7124395Smckusick whoami = argv[0]; 72*27899Skarels argc--; 73*27899Skarels argv++; 74*27899Skarels while (argc > 0 && argv[0][0] == '-') { 75*27899Skarels switch(argv[0][1]) { 7627462Skarels 7727462Skarels case 's': 7827462Skarels subset++; 7927462Skarels break; 8027462Skarels 8127462Skarels case 'd': 8227462Skarels dflag++; 8327462Skarels break; 8427462Skarels 8527462Skarels default: 8627462Skarels break; 8727462Skarels } 8827462Skarels argc--, argv++; 8927462Skarels } 90*27899Skarels if (argc > 0) 91*27899Skarels freopen(argv[0], "r", stdin); 9216962Smckusick if (argc > 1) 93*27899Skarels freopen(argv[1], "w", stdout); 9416962Smckusick /* 9516978Smckusick * Set up the hash table for the patterns. 9616962Smckusick */ 9727462Skarels if (subset) 9827462Skarels tablep = vaxsubset_inittables; 9927462Skarels else 10027462Skarels tablep = vax_inittables; 10127462Skarels for ( ; *tablep; tablep++) { 10216975Smckusick for (pp = *tablep; pp->name[0] != '\0'; pp++) { 10316978Smckusick php = &patshdr[hash(pp->name, &size)]; 10416975Smckusick pp->size = size; 10516978Smckusick pp->next = *php; 10616978Smckusick *php = pp; 10716975Smckusick } 10816962Smckusick } 10916962Smckusick /* 11016978Smckusick * Set up the hash table for the instruction stop table. 11116978Smckusick */ 11216978Smckusick for (itp = inststoptable; itp->name[0] != '\0'; itp++) { 11316978Smckusick ithp = &inststoptblhdr[hash(itp->name, &size)]; 11416978Smckusick itp->size = size; 11516978Smckusick itp->next = *ithp; 11616978Smckusick *ithp = itp; 11716978Smckusick } 11816978Smckusick /* 11916962Smckusick * check each line and replace as appropriate 12016962Smckusick */ 12116962Smckusick buftail = bufhead = 0; 12216962Smckusick bufp = line[0]; 12316962Smckusick while (fgets(bufp, MAXLINELEN, stdin)) { 12424395Smckusick lineno++; 12516962Smckusick lp = index(bufp, LABELCHAR); 12616962Smckusick if (lp != NULL) { 12718448Smckusick for (cp = bufp; cp < lp; cp++) 12818448Smckusick if (!isalnum(*cp)) 12918448Smckusick break; 13018448Smckusick if (cp == lp) { 13118448Smckusick bufp = newline(); 13218448Smckusick if (*++lp == '\n') { 13318448Smckusick emptyqueue(); 13418448Smckusick continue; 13518448Smckusick } 13624395Smckusick (void) strcpy(bufp, lp); 13718448Smckusick *lp++ = '\n'; 13818448Smckusick *lp = '\0'; 13916962Smckusick emptyqueue(); 14016962Smckusick } 14116962Smckusick } 14216962Smckusick for (cp = bufp; isspace(*cp); cp++) 14316962Smckusick /* void */; 14416962Smckusick if ((cp = doreplaceon(cp)) == 0) { 14516962Smckusick bufp = newline(); 14616962Smckusick continue; 14716962Smckusick } 14816978Smckusick for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) { 14916962Smckusick if (pp->size == size && bcmp(pp->name, cp, size) == 0) { 15024395Smckusick if (argcounterr(pp->args, countargs(bufp), pp->name)) { 15124395Smckusick pp = NULL; 15224395Smckusick break; 15324395Smckusick } 15416962Smckusick expand(pp->replace); 15516962Smckusick bufp = line[bufhead]; 15616962Smckusick break; 15716962Smckusick } 15816962Smckusick } 15916962Smckusick if (!pp) { 16016962Smckusick emptyqueue(); 16116962Smckusick fputs(bufp, stdout); 16216962Smckusick } 16316962Smckusick } 16416962Smckusick emptyqueue(); 16516980Smckusick if (dflag) 16624395Smckusick fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n", 16724395Smckusick whoami, 16816980Smckusick "attempts", stats.attempted, 16916980Smckusick "finished", stats.finished, 17016980Smckusick "inhibited", stats.lostmodified, 17116980Smckusick "merged", stats.savedpush); 17216962Smckusick exit(0); 17316962Smckusick } 17416962Smckusick 17516962Smckusick /* 17616962Smckusick * Integrate an expansion into the assembly stream 17716962Smckusick */ 17816962Smckusick expand(replace) 17916962Smckusick char *replace; 18016962Smckusick { 18116962Smckusick register int curptr; 18216962Smckusick char *nextreplace, *argv[MAXARGS]; 18317202Smckusick int argc, argreg, foundarg, mod = 0, args = 0; 18416962Smckusick char parsebuf[BUFSIZ]; 18516962Smckusick 18616980Smckusick stats.attempted++; 18716980Smckusick for (curptr = bufhead; ; ) { 18816962Smckusick nextreplace = copyline(replace, line[bufhead]); 18916962Smckusick argc = parseline(line[bufhead], argv, parsebuf); 19016962Smckusick argreg = nextarg(argc, argv); 19116962Smckusick if (argreg == -1) 19216962Smckusick break; 19317202Smckusick args++; 19416978Smckusick for (foundarg = 0; curptr != buftail; ) { 19516978Smckusick curptr = PRED(curptr); 19616962Smckusick argc = parseline(line[curptr], argv, parsebuf); 19716978Smckusick if (isendofblock(argc, argv)) 19816962Smckusick break; 19916978Smckusick if (foundarg = ispusharg(argc, argv)) 20016978Smckusick break; 20116962Smckusick mod |= 1 << modifies(argc, argv); 20216962Smckusick } 20316978Smckusick if (!foundarg) 20416962Smckusick break; 20516962Smckusick replace = nextreplace; 20616962Smckusick if (mod & (1 << argreg)) { 20716980Smckusick stats.lostmodified++; 20816978Smckusick if (curptr == buftail) { 20916978Smckusick (void)newline(); 21016978Smckusick break; 21116978Smckusick } 21216962Smckusick (void)newline(); 21316962Smckusick } else { 21416980Smckusick stats.savedpush++; 21516962Smckusick rewrite(line[curptr], argc, argv, argreg); 21616962Smckusick mod |= 1 << argreg; 21716962Smckusick } 21816962Smckusick } 21916980Smckusick if (argreg == -1) 22016980Smckusick stats.finished++; 22116962Smckusick emptyqueue(); 22216962Smckusick fputs(replace, stdout); 22317202Smckusick cleanup(args); 22416962Smckusick } 22516962Smckusick 22616962Smckusick /* 22716962Smckusick * Parse a line of assembly language into opcode and arguments. 22816962Smckusick */ 22916962Smckusick parseline(linep, argv, linebuf) 23016962Smckusick char *linep; 23116962Smckusick char *argv[]; 23216962Smckusick char *linebuf; 23316962Smckusick { 23416962Smckusick register char *bufp = linebuf, *cp = linep; 23516962Smckusick register int argc = 0; 23616962Smckusick 23716962Smckusick for (;;) { 23816962Smckusick /* 23916962Smckusick * skip over white space 24016962Smckusick */ 24116962Smckusick while (isspace(*cp)) 24216962Smckusick cp++; 24316962Smckusick if (*cp == '\0') 24416962Smckusick return (argc); 24516962Smckusick /* 24616962Smckusick * copy argument 24716962Smckusick */ 24816962Smckusick if (argc == MAXARGS - 1) { 24916962Smckusick fprintf(stderr, "instruction too long->%s", linep); 25016962Smckusick return (argc); 25116962Smckusick } 25216962Smckusick argv[argc++] = bufp; 25316978Smckusick while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR) 25416962Smckusick *bufp++ = *cp++; 25516962Smckusick *bufp++ = '\0'; 25616962Smckusick if (*cp == COMMENTCHAR) 25716962Smckusick return (argc); 25816978Smckusick if (*cp == ARGSEPCHAR) 25916962Smckusick cp++; 26016962Smckusick } 26116962Smckusick } 26216962Smckusick 26316962Smckusick /* 26416978Smckusick * Check for instructions that end a basic block. 26516978Smckusick */ 26616978Smckusick isendofblock(argc, argv) 26716978Smckusick int argc; 26816978Smckusick char *argv[]; 26916978Smckusick { 27016978Smckusick register struct inststoptbl *itp; 27116978Smckusick int size; 27216978Smckusick 27316978Smckusick if (argc == 0) 27416978Smckusick return (0); 27516978Smckusick for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next) 27616978Smckusick if (itp->size == size && bcmp(argv[0], itp->name, size) == 0) 27716978Smckusick return (1); 27816978Smckusick return (0); 27916978Smckusick } 28016978Smckusick 28116978Smckusick /* 28216962Smckusick * Copy a newline terminated string. 28316962Smckusick * Return pointer to character following last character copied. 28416962Smckusick */ 28516962Smckusick char * 28616962Smckusick copyline(from, to) 28716962Smckusick register char *from, *to; 28816962Smckusick { 28916962Smckusick 29016962Smckusick while (*from != '\n') 29116962Smckusick *to++ = *from++; 29216962Smckusick *to++ = *from++; 29316962Smckusick *to = '\0'; 29416962Smckusick return (from); 29516962Smckusick } 29616962Smckusick 29716962Smckusick /* 29824395Smckusick * Check for a disparity between the number of arguments a function 29924395Smckusick * is called with and the number which we expect to see. 30024395Smckusick * If the error is unrecoverable, return 1, otherwise 0. 30124395Smckusick */ 30224395Smckusick argcounterr(args, callargs, name) 30324395Smckusick int args, callargs; 30424395Smckusick char *name; 30524395Smckusick { 30624395Smckusick register char *cp; 30724395Smckusick char namebuf[MAXLINELEN]; 30824395Smckusick 30924395Smckusick if (args == callargs) 31024395Smckusick return (0); 31124395Smckusick cp = strcpy(namebuf, name); 31224395Smckusick while (*cp != '\0' && *cp != '\n') 31324395Smckusick ++cp; 31424395Smckusick if (*cp == '\n') 31524395Smckusick *cp = '\0'; 31624395Smckusick if (callargs >= 0) { 31724395Smckusick fprintf(stderr, 31824395Smckusick "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n", 31924395Smckusick whoami, callargs, args, namebuf, lineno); 32024395Smckusick return (1); 32124395Smckusick } 32224395Smckusick fprintf(stderr, 32324395Smckusick "%s: warning: can't verify arg count for '%s' at line %d\n", 32424395Smckusick whoami, namebuf, lineno); 32524395Smckusick return (0); 32624395Smckusick } 32724395Smckusick 32824395Smckusick /* 32916962Smckusick * open space for next line in the queue 33016962Smckusick */ 33116962Smckusick char * 33216962Smckusick newline() 33316962Smckusick { 33416962Smckusick bufhead = SUCC(bufhead); 33516962Smckusick if (bufhead == buftail) { 33616962Smckusick fputs(line[buftail], stdout); 33716962Smckusick buftail = SUCC(buftail); 33816962Smckusick } 33916962Smckusick return (line[bufhead]); 34016962Smckusick } 34116962Smckusick 34216962Smckusick /* 34316962Smckusick * empty the queue by printing out all its lines. 34416962Smckusick */ 34516962Smckusick emptyqueue() 34616962Smckusick { 34716962Smckusick while (buftail != bufhead) { 34816962Smckusick fputs(line[buftail], stdout); 34916962Smckusick buftail = SUCC(buftail); 35016962Smckusick } 35116962Smckusick } 35216962Smckusick 35316962Smckusick /* 35416962Smckusick * Compute the hash of a string. 35516962Smckusick * Return the hash and the size of the item hashed 35616962Smckusick */ 35716962Smckusick hash(cp, size) 35816962Smckusick char *cp; 35916962Smckusick int *size; 36016962Smckusick { 36116962Smckusick register char *cp1 = cp; 36216978Smckusick register int hash = 0; 36316962Smckusick 36416962Smckusick while (*cp1 && *cp1 != '\n') 36516962Smckusick hash += (int)*cp1++; 36616962Smckusick *size = cp1 - cp + 1; 36716962Smckusick hash &= HSHSIZ - 1; 36816978Smckusick return (hash); 36916962Smckusick } 370