home *** CD-ROM | disk | FTP | other *** search
- /*-
- * Copyright (c) 1984, 1986 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
- #ifndef lint
- char copyright[] =
- "@(#) Copyright (c) 1984, 1986 The Regents of the University of California.\n\
- All rights reserved.\n";
- #endif /* not lint */
-
- #ifndef lint
- static char sccsid[] = "@(#)main.c 7.2 (Berkeley) 5/8/91";
- #endif /* not lint */
-
- #include <stdio.h>
- #include <ctype.h>
- #include "inline.h"
-
- /*
- * These are the pattern tables to be loaded
- */
- struct pats *vax_inittables[] = {
- language_ptab,
- libc_ptab,
- vax_libc_ptab,
- machine_ptab,
- vax_ptab,
- 0
- };
-
- struct pats *vaxsubset_inittables[] = {
- language_ptab,
- libc_ptab,
- vaxsubset_libc_ptab,
- machine_ptab,
- vaxsubset_ptab,
- 0
- };
-
- /*
- * Statistics collection
- */
- struct stats {
- int attempted; /* number of expansion attempts */
- int finished; /* expansions done before end of basic block */
- int lostmodified; /* mergers inhibited by intervening mod */
- int savedpush; /* successful push/pop merger */
- } stats;
-
- extern char *strcpy();
-
- char *whoami;
- int lineno = 0;
- int dflag;
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- register char *cp, *lp;
- register char *bufp;
- register struct pats *pp, **php;
- struct pats **tablep;
- register struct inststoptbl *itp, **ithp;
- int size;
- extern char *index();
- int subset = 0;
-
- whoami = argv[0];
- argc--;
- argv++;
- while (argc > 0 && argv[0][0] == '-') {
- switch(argv[0][1]) {
-
- case 's':
- subset++;
- break;
-
- case 'd':
- dflag++;
- break;
-
- default:
- break;
- }
- argc--, argv++;
- }
- if (argc > 0)
- freopen(argv[0], "r", stdin);
- if (argc > 1)
- freopen(argv[1], "w", stdout);
- /*
- * Set up the hash table for the patterns.
- */
- if (subset)
- tablep = vaxsubset_inittables;
- else
- tablep = vax_inittables;
- for ( ; *tablep; tablep++) {
- for (pp = *tablep; pp->name[0] != '\0'; pp++) {
- php = &patshdr[hash(pp->name, &size)];
- pp->size = size;
- pp->next = *php;
- *php = pp;
- }
- }
- /*
- * Set up the hash table for the instruction stop table.
- */
- for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
- ithp = &inststoptblhdr[hash(itp->name, &size)];
- itp->size = size;
- itp->next = *ithp;
- *ithp = itp;
- }
- /*
- * check each line and replace as appropriate
- */
- buftail = bufhead = 0;
- bufp = line[0];
- while (fgets(bufp, MAXLINELEN, stdin)) {
- lineno++;
- lp = index(bufp, LABELCHAR);
- if (lp != NULL) {
- for (cp = bufp; cp < lp; cp++)
- if (!isalnum(*cp))
- break;
- if (cp == lp) {
- bufp = newline();
- if (*++lp == '\n') {
- emptyqueue();
- continue;
- }
- (void) strcpy(bufp, lp);
- *lp++ = '\n';
- *lp = '\0';
- emptyqueue();
- }
- }
- for (cp = bufp; isspace(*cp); cp++)
- /* void */;
- if ((cp = doreplaceon(cp)) == 0) {
- bufp = newline();
- continue;
- }
- for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
- if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
- if (argcounterr(pp->args, countargs(bufp), pp->name)) {
- pp = NULL;
- break;
- }
- expand(pp->replace);
- bufp = line[bufhead];
- break;
- }
- }
- if (!pp) {
- emptyqueue();
- fputs(bufp, stdout);
- }
- }
- emptyqueue();
- if (dflag)
- fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
- whoami,
- "attempts", stats.attempted,
- "finished", stats.finished,
- "inhibited", stats.lostmodified,
- "merged", stats.savedpush);
- exit(0);
- }
-
- /*
- * Integrate an expansion into the assembly stream
- */
- expand(replace)
- char *replace;
- {
- register int curptr;
- char *nextreplace, *argv[MAXARGS];
- int argc, argreg, foundarg, mod = 0, args = 0;
- char parsebuf[BUFSIZ];
-
- stats.attempted++;
- for (curptr = bufhead; ; ) {
- nextreplace = copyline(replace, line[bufhead]);
- argc = parseline(line[bufhead], argv, parsebuf);
- argreg = nextarg(argc, argv);
- if (argreg == -1)
- break;
- args++;
- for (foundarg = 0; curptr != buftail; ) {
- curptr = PRED(curptr);
- argc = parseline(line[curptr], argv, parsebuf);
- if (isendofblock(argc, argv))
- break;
- if (foundarg = ispusharg(argc, argv))
- break;
- mod |= 1 << modifies(argc, argv);
- }
- if (!foundarg)
- break;
- replace = nextreplace;
- if (mod & (1 << argreg)) {
- stats.lostmodified++;
- if (curptr == buftail) {
- (void)newline();
- break;
- }
- (void)newline();
- } else {
- stats.savedpush++;
- rewrite(line[curptr], argc, argv, argreg);
- mod |= 1 << argreg;
- }
- }
- if (argreg == -1)
- stats.finished++;
- emptyqueue();
- fputs(replace, stdout);
- cleanup(args);
- }
-
- /*
- * Parse a line of assembly language into opcode and arguments.
- */
- parseline(linep, argv, linebuf)
- char *linep;
- char *argv[];
- char *linebuf;
- {
- register char *bufp = linebuf, *cp = linep;
- register int argc = 0;
-
- for (;;) {
- /*
- * skip over white space
- */
- while (isspace(*cp))
- cp++;
- if (*cp == '\0')
- return (argc);
- /*
- * copy argument
- */
- if (argc == MAXARGS - 1) {
- fprintf(stderr, "instruction too long->%s", linep);
- return (argc);
- }
- argv[argc++] = bufp;
- while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
- *bufp++ = *cp++;
- *bufp++ = '\0';
- if (*cp == COMMENTCHAR)
- return (argc);
- if (*cp == ARGSEPCHAR)
- cp++;
- }
- }
-
- /*
- * Check for instructions that end a basic block.
- */
- isendofblock(argc, argv)
- int argc;
- char *argv[];
- {
- register struct inststoptbl *itp;
- int size;
-
- if (argc == 0)
- return (0);
- for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
- if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
- return (1);
- return (0);
- }
-
- /*
- * Copy a newline terminated string.
- * Return pointer to character following last character copied.
- */
- char *
- copyline(from, to)
- register char *from, *to;
- {
-
- while (*from != '\n')
- *to++ = *from++;
- *to++ = *from++;
- *to = '\0';
- return (from);
- }
-
- /*
- * Check for a disparity between the number of arguments a function
- * is called with and the number which we expect to see.
- * If the error is unrecoverable, return 1, otherwise 0.
- */
- argcounterr(args, callargs, name)
- int args, callargs;
- char *name;
- {
- register char *cp;
- char namebuf[MAXLINELEN];
-
- if (args == callargs)
- return (0);
- cp = strcpy(namebuf, name);
- while (*cp != '\0' && *cp != '\n')
- ++cp;
- if (*cp == '\n')
- *cp = '\0';
- if (callargs >= 0) {
- fprintf(stderr,
- "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
- whoami, callargs, args, namebuf, lineno);
- return (1);
- }
- fprintf(stderr,
- "%s: warning: can't verify arg count for '%s' at line %d\n",
- whoami, namebuf, lineno);
- return (0);
- }
-
- /*
- * open space for next line in the queue
- */
- char *
- newline()
- {
- bufhead = SUCC(bufhead);
- if (bufhead == buftail) {
- fputs(line[buftail], stdout);
- buftail = SUCC(buftail);
- }
- return (line[bufhead]);
- }
-
- /*
- * empty the queue by printing out all its lines.
- */
- emptyqueue()
- {
- while (buftail != bufhead) {
- fputs(line[buftail], stdout);
- buftail = SUCC(buftail);
- }
- }
-
- /*
- * Compute the hash of a string.
- * Return the hash and the size of the item hashed
- */
- hash(cp, size)
- char *cp;
- int *size;
- {
- register char *cp1 = cp;
- register int hash = 0;
-
- while (*cp1 && *cp1 != '\n')
- hash += (int)*cp1++;
- *size = cp1 - cp + 1;
- hash &= HSHSIZ - 1;
- return (hash);
- }
-