home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / tahoe / inline / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  8.3 KB  |  366 lines

  1. /*-
  2.  * Copyright (c) 1984 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1984 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)main.c    1.4 (Berkeley) 5/8/91";
  42. #endif /* not lint */
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include "inline.h"
  47.  
  48. /*
  49.  * These are the pattern tables to be loaded
  50.  */
  51. struct pats *inittables[] = {
  52.     language_ptab,
  53.     libc_ptab,
  54.     machine_ptab,
  55.     0
  56. };
  57.  
  58. /*
  59.  * Statistics collection
  60.  */
  61. struct stats {
  62.     int    attempted;    /* number of expansion attempts */
  63.     int    finished;    /* expansions done before end of basic block */
  64.     int    lostmodified;    /* mergers inhibited by intervening mod */
  65.     int    savedpush;    /* successful push/pop merger */
  66. } stats;
  67.  
  68. extern    char *strcpy();
  69.  
  70. char    *whoami;
  71. int    lineno = 0;
  72. int    dflag;
  73.  
  74. main(argc, argv)
  75.     int argc;
  76.     char *argv[];
  77. {
  78.     register char *cp, *lp;
  79.     register char *bufp;
  80.     register struct pats *pp, **php;
  81.     struct pats **tablep;
  82.     register struct inststoptbl *itp, **ithp;
  83.     int size;
  84.     extern char *index();
  85.  
  86.     whoami = argv[0];
  87.     if (argc > 1 && bcmp(argv[1], "-d", 3) == 0)
  88.         dflag++, argc--, argv++;
  89.     if (argc > 1)
  90.         freopen(argv[1], "r", stdin);
  91.     if (argc > 2)
  92.         freopen(argv[2], "w", stdout);
  93.     /*
  94.      * Set up the hash table for the patterns.
  95.      */
  96.     for (tablep = inittables; *tablep; tablep++) {
  97.         for (pp = *tablep; pp->name[0] != '\0'; pp++) {
  98.             php = &patshdr[hash(pp->name, &size)];
  99.             pp->size = size;
  100.             pp->next = *php;
  101.             *php = pp;
  102.         }
  103.     }
  104.     /*
  105.      * Set up the hash table for the instruction stop table.
  106.      */
  107.     for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
  108.         ithp = &inststoptblhdr[hash(itp->name, &size)];
  109.         itp->size = size;
  110.         itp->next = *ithp;
  111.         *ithp = itp;
  112.     }
  113.     /*
  114.      * check each line and replace as appropriate
  115.      */
  116.     buftail = bufhead = 0;
  117.     bufp = line[0];
  118.     while (fgets(bufp, MAXLINELEN, stdin)) {
  119.         lineno++;
  120.         lp = index(bufp, LABELCHAR);
  121.         if (lp != NULL) {
  122.             for (cp = bufp; cp < lp; cp++)
  123.                 if (!isalnum(*cp))
  124.                     break;
  125.             if (cp == lp) {
  126.                 bufp = newline();
  127.                 if (*++lp == '\n') {
  128.                     emptyqueue();
  129.                     continue;
  130.                 }
  131.                 (void) strcpy(bufp, lp);
  132.                 *lp++ = '\n';
  133.                 *lp = '\0';
  134.                 emptyqueue();
  135.             }
  136.         }
  137.         for (cp = bufp; isspace(*cp); cp++)
  138.             /* void */;
  139.         if ((cp = doreplaceon(cp)) == 0) {
  140.             bufp = newline();
  141.             continue;
  142.         }
  143.         for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
  144.             if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
  145.                 if (argcounterr(pp->args, countargs(bufp),
  146.                     pp->name)) {
  147.                     pp = NULL;
  148.                     break;
  149.                 }
  150.                 expand(pp->replace);
  151.                 bufp = line[bufhead];
  152.                 break;
  153.             }
  154.         }
  155.         if (!pp) {
  156.             emptyqueue();
  157.             fputs(bufp, stdout);
  158.         }
  159.     }
  160.     emptyqueue();
  161.     if (dflag)
  162.         fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
  163.             whoami,
  164.             "attempts", stats.attempted,
  165.             "finished", stats.finished,
  166.             "inhibited", stats.lostmodified,
  167.             "merged", stats.savedpush);
  168.     exit(0);
  169. }
  170.  
  171. /*
  172.  * Integrate an expansion into the assembly stream
  173.  */
  174. expand(replace)
  175.     char *replace;
  176. {
  177.     register int curptr;
  178.     char *nextreplace, *argv[MAXARGS];
  179.     int argc, argreg, foundarg, mod = 0, args = 0;
  180.     char parsebuf[BUFSIZ];
  181.  
  182.     stats.attempted++;
  183.     for (curptr = bufhead; ; ) {
  184.         nextreplace = copyline(replace, line[bufhead]);
  185.         argc = parseline(line[bufhead], argv, parsebuf);
  186.         argreg = nextarg(argc, argv);
  187.         if (argreg == -1)
  188.             break;
  189.         args++;
  190.         for (foundarg = 0; curptr != buftail; ) {
  191.             curptr = PRED(curptr);
  192.             argc = parseline(line[curptr], argv, parsebuf);
  193.             if (isendofblock(argc, argv))
  194.                 break;
  195.             if (foundarg = ispusharg(argc, argv))
  196.                 break;
  197.             mod |= 1 << modifies(argc, argv);
  198.         }
  199.         if (!foundarg)
  200.             break;
  201.         replace = nextreplace;
  202.         if (mod & (1 << argreg)) {
  203.             stats.lostmodified++;
  204.             if (curptr == buftail) {
  205.                 (void)newline();
  206.                 break;
  207.             }
  208.             (void)newline();
  209.         } else {
  210.             stats.savedpush++;
  211.             rewrite(line[curptr], argc, argv, argreg);
  212.             mod |= 1 << argreg;
  213.         }
  214.     }
  215.     if (argreg == -1)
  216.         stats.finished++;
  217.     emptyqueue();
  218.     fputs(replace, stdout);
  219.     cleanup(args);
  220. }
  221.  
  222. /*
  223.  * Parse a line of assembly language into opcode and arguments.
  224.  */
  225. parseline(linep, argv, linebuf)
  226.     char *linep;
  227.     char *argv[];
  228.     char *linebuf;
  229. {
  230.     register char *bufp = linebuf, *cp = linep;
  231.     register int argc = 0;
  232.  
  233.     for (;;) {
  234.         /*
  235.          * skip over white space
  236.          */
  237.         while (isspace(*cp))
  238.             cp++;
  239.         if (*cp == '\0')
  240.             return (argc);
  241.         /*
  242.          * copy argument
  243.          */
  244.         if (argc == MAXARGS - 1) {
  245.             fprintf(stderr, "instruction too long->%s", linep);
  246.             return (argc);
  247.         }
  248.         argv[argc++] = bufp;
  249.         while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
  250.             *bufp++ = *cp++;
  251.         *bufp++ = '\0';
  252.         if (*cp == COMMENTCHAR)
  253.             return (argc);
  254.         if (*cp == ARGSEPCHAR)
  255.             cp++;
  256.     }
  257. }
  258.  
  259. /*
  260.  * Check for instructions that end a basic block.
  261.  */
  262. isendofblock(argc, argv)
  263.     int argc;
  264.     char *argv[];
  265. {
  266.     register struct inststoptbl *itp;
  267.     int size;
  268.  
  269.     if (argc == 0)
  270.         return (0);
  271.     for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
  272.         if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
  273.             return (1);
  274.     return (0);
  275. }
  276.  
  277. /*
  278.  * Copy a newline terminated string.
  279.  * Return pointer to character following last character copied.
  280.  */
  281. char *
  282. copyline(from, to)
  283.     register char *from, *to;
  284. {
  285.  
  286.     while (*from != '\n')
  287.         *to++ = *from++;
  288.     *to++ = *from++;
  289.     *to = '\0';
  290.     return (from);
  291. }
  292.  
  293. /*
  294.  * Check for a disparity between the number of arguments a function
  295.  * is called with and the number which we expect to see.
  296.  * If the error is unrecoverable, return 1, otherwise 0.
  297.  */
  298. argcounterr(args, callargs, name)
  299.     int args, callargs;
  300.     char *name;
  301. {
  302.     register char *cp;
  303.     char namebuf[MAXLINELEN];
  304.  
  305.     if (args == callargs)
  306.         return (0);
  307.     cp = strcpy(namebuf, name);
  308.     while (*cp != '\0' && *cp != '\n')
  309.         ++cp;
  310.     if (*cp == '\n')
  311.         *cp = '\0';
  312.     if (callargs >= 0) {
  313.         fprintf(stderr,
  314.         "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
  315.             whoami, callargs, args, namebuf, lineno);
  316.         return (1);
  317.     }
  318.     fprintf(stderr,
  319.         "%s: warning: can't verify arg count for '%s' at line %d\n",
  320.         whoami, namebuf, lineno);
  321.     return (0);
  322. }
  323.  
  324. /*
  325.  * open space for next line in the queue
  326.  */
  327. char *
  328. newline()
  329. {
  330.     bufhead = SUCC(bufhead);
  331.     if (bufhead == buftail) {
  332.         fputs(line[buftail], stdout);
  333.         buftail = SUCC(buftail);
  334.     }
  335.     return (line[bufhead]);
  336. }
  337.  
  338. /*
  339.  * empty the queue by printing out all its lines.
  340.  */
  341. emptyqueue()
  342. {
  343.     while (buftail != bufhead) {
  344.         fputs(line[buftail], stdout);
  345.         buftail = SUCC(buftail);
  346.     }
  347. }
  348.  
  349. /*
  350.  * Compute the hash of a string.
  351.  * Return the hash and the size of the item hashed
  352.  */
  353. hash(cp, size)
  354.     char *cp;
  355.     int *size;
  356. {
  357.     register char *cp1 = cp;
  358.     register int hash = 0;
  359.  
  360.     while (*cp1 && *cp1 != '\n')
  361.         hash += (int)*cp1++;
  362.     *size = cp1 - cp + 1;
  363.     hash &= HSHSIZ - 1;
  364.     return (hash);
  365. }
  366.