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

  1. /*-
  2.  * Copyright (c) 1984, 1986 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, 1986 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    7.2 (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 *vax_inittables[] = {
  52.     language_ptab,
  53.     libc_ptab,
  54.     vax_libc_ptab,
  55.     machine_ptab,
  56.     vax_ptab,
  57.     0
  58. };
  59.  
  60. struct pats *vaxsubset_inittables[] = {
  61.     language_ptab,
  62.     libc_ptab,
  63.     vaxsubset_libc_ptab,
  64.     machine_ptab,
  65.     vaxsubset_ptab,
  66.     0
  67. };
  68.  
  69. /*
  70.  * Statistics collection
  71.  */
  72. struct stats {
  73.     int    attempted;    /* number of expansion attempts */
  74.     int    finished;    /* expansions done before end of basic block */
  75.     int    lostmodified;    /* mergers inhibited by intervening mod */
  76.     int    savedpush;    /* successful push/pop merger */
  77. } stats;
  78.  
  79. extern char *strcpy();
  80.  
  81. char *whoami;
  82. int lineno = 0;
  83. int dflag;
  84.  
  85. main(argc, argv)
  86.     int argc;
  87.     char *argv[];
  88. {
  89.     register char *cp, *lp;
  90.     register char *bufp;
  91.     register struct pats *pp, **php;
  92.     struct pats **tablep;
  93.     register struct inststoptbl *itp, **ithp;
  94.     int size;
  95.     extern char *index();
  96.     int subset = 0;
  97.  
  98.     whoami = argv[0];
  99.     argc--;
  100.     argv++;
  101.     while (argc > 0 && argv[0][0] == '-') {
  102.         switch(argv[0][1]) {
  103.  
  104.         case 's':
  105.             subset++;
  106.             break;
  107.  
  108.         case 'd':
  109.             dflag++;
  110.             break;
  111.  
  112.         default:
  113.             break;
  114.         }
  115.         argc--, argv++;
  116.     }
  117.     if (argc > 0)
  118.         freopen(argv[0], "r", stdin);
  119.     if (argc > 1)
  120.         freopen(argv[1], "w", stdout);
  121.     /*
  122.      * Set up the hash table for the patterns.
  123.      */
  124.     if (subset)
  125.         tablep = vaxsubset_inittables;
  126.     else
  127.         tablep = vax_inittables;
  128.     for ( ; *tablep; tablep++) {
  129.         for (pp = *tablep; pp->name[0] != '\0'; pp++) {
  130.             php = &patshdr[hash(pp->name, &size)];
  131.             pp->size = size;
  132.             pp->next = *php;
  133.             *php = pp;
  134.         }
  135.     }
  136.     /*
  137.      * Set up the hash table for the instruction stop table.
  138.      */
  139.     for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
  140.         ithp = &inststoptblhdr[hash(itp->name, &size)];
  141.         itp->size = size;
  142.         itp->next = *ithp;
  143.         *ithp = itp;
  144.     }
  145.     /*
  146.      * check each line and replace as appropriate
  147.      */
  148.     buftail = bufhead = 0;
  149.     bufp = line[0];
  150.     while (fgets(bufp, MAXLINELEN, stdin)) {
  151.         lineno++;
  152.         lp = index(bufp, LABELCHAR);
  153.         if (lp != NULL) {
  154.             for (cp = bufp; cp < lp; cp++)
  155.                 if (!isalnum(*cp))
  156.                     break;
  157.             if (cp == lp) {
  158.                 bufp = newline();
  159.                 if (*++lp == '\n') {
  160.                     emptyqueue();
  161.                     continue;
  162.                 }
  163.                 (void) strcpy(bufp, lp);
  164.                 *lp++ = '\n';
  165.                 *lp = '\0';
  166.                 emptyqueue();
  167.             }
  168.         }
  169.         for (cp = bufp; isspace(*cp); cp++)
  170.             /* void */;
  171.         if ((cp = doreplaceon(cp)) == 0) {
  172.             bufp = newline();
  173.             continue;
  174.         }
  175.         for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
  176.             if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
  177.                 if (argcounterr(pp->args, countargs(bufp), pp->name)) {
  178.                     pp = NULL;
  179.                     break;
  180.                 }
  181.                 expand(pp->replace);
  182.                 bufp = line[bufhead];
  183.                 break;
  184.             }
  185.         }
  186.         if (!pp) {
  187.             emptyqueue();
  188.             fputs(bufp, stdout);
  189.         }
  190.     }
  191.     emptyqueue();
  192.     if (dflag)
  193.         fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
  194.             whoami,
  195.             "attempts", stats.attempted,
  196.             "finished", stats.finished,
  197.             "inhibited", stats.lostmodified,
  198.             "merged", stats.savedpush);
  199.     exit(0);
  200. }
  201.  
  202. /*
  203.  * Integrate an expansion into the assembly stream
  204.  */
  205. expand(replace)
  206.     char *replace;
  207. {
  208.     register int curptr;
  209.     char *nextreplace, *argv[MAXARGS];
  210.     int argc, argreg, foundarg, mod = 0, args = 0;
  211.     char parsebuf[BUFSIZ];
  212.  
  213.     stats.attempted++;
  214.     for (curptr = bufhead; ; ) {
  215.         nextreplace = copyline(replace, line[bufhead]);
  216.         argc = parseline(line[bufhead], argv, parsebuf);
  217.         argreg = nextarg(argc, argv);
  218.         if (argreg == -1)
  219.             break;
  220.         args++;
  221.         for (foundarg = 0; curptr != buftail; ) {
  222.             curptr = PRED(curptr);
  223.             argc = parseline(line[curptr], argv, parsebuf);
  224.             if (isendofblock(argc, argv))
  225.                 break;
  226.             if (foundarg = ispusharg(argc, argv))
  227.                 break;
  228.             mod |= 1 << modifies(argc, argv);
  229.         }
  230.         if (!foundarg)
  231.             break;
  232.         replace = nextreplace;
  233.         if (mod & (1 << argreg)) {
  234.             stats.lostmodified++;
  235.             if (curptr == buftail) {
  236.                 (void)newline();
  237.                 break;
  238.             }
  239.             (void)newline();
  240.         } else {
  241.             stats.savedpush++;
  242.             rewrite(line[curptr], argc, argv, argreg);
  243.             mod |= 1 << argreg;
  244.         }
  245.     }
  246.     if (argreg == -1)
  247.         stats.finished++;
  248.     emptyqueue();
  249.     fputs(replace, stdout);
  250.     cleanup(args);
  251. }
  252.  
  253. /*
  254.  * Parse a line of assembly language into opcode and arguments.
  255.  */
  256. parseline(linep, argv, linebuf)
  257.     char *linep;
  258.     char *argv[];
  259.     char *linebuf;
  260. {
  261.     register char *bufp = linebuf, *cp = linep;
  262.     register int argc = 0;
  263.  
  264.     for (;;) {
  265.         /*
  266.          * skip over white space
  267.          */
  268.         while (isspace(*cp))
  269.             cp++;
  270.         if (*cp == '\0')
  271.             return (argc);
  272.         /*
  273.          * copy argument
  274.          */
  275.         if (argc == MAXARGS - 1) {
  276.             fprintf(stderr, "instruction too long->%s", linep);
  277.             return (argc);
  278.         }
  279.         argv[argc++] = bufp;
  280.         while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
  281.             *bufp++ = *cp++;
  282.         *bufp++ = '\0';
  283.         if (*cp == COMMENTCHAR)
  284.             return (argc);
  285.         if (*cp == ARGSEPCHAR)
  286.             cp++;
  287.     }
  288. }
  289.  
  290. /*
  291.  * Check for instructions that end a basic block.
  292.  */
  293. isendofblock(argc, argv)
  294.     int argc;
  295.     char *argv[];
  296. {
  297.     register struct inststoptbl *itp;
  298.     int size;
  299.  
  300.     if (argc == 0)
  301.         return (0);
  302.     for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
  303.         if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
  304.             return (1);
  305.     return (0);
  306. }
  307.  
  308. /*
  309.  * Copy a newline terminated string.
  310.  * Return pointer to character following last character copied.
  311.  */
  312. char *
  313. copyline(from, to)
  314.     register char *from, *to;
  315. {
  316.  
  317.     while (*from != '\n')
  318.         *to++ = *from++;
  319.     *to++ = *from++;
  320.     *to = '\0';
  321.     return (from);
  322. }
  323.  
  324. /*
  325.  * Check for a disparity between the number of arguments a function
  326.  * is called with and the number which we expect to see.
  327.  * If the error is unrecoverable, return 1, otherwise 0.
  328.  */
  329. argcounterr(args, callargs, name)
  330.     int args, callargs;
  331.     char *name;
  332. {
  333.     register char *cp;
  334.     char namebuf[MAXLINELEN];
  335.  
  336.     if (args == callargs)
  337.         return (0);
  338.     cp = strcpy(namebuf, name);
  339.     while (*cp != '\0' && *cp != '\n')
  340.         ++cp;
  341.     if (*cp == '\n')
  342.         *cp = '\0';
  343.     if (callargs >= 0) {
  344.         fprintf(stderr,
  345.         "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
  346.             whoami, callargs, args, namebuf, lineno);
  347.         return (1);
  348.     }
  349.     fprintf(stderr,
  350.         "%s: warning: can't verify arg count for '%s' at line %d\n",
  351.         whoami, namebuf, lineno);
  352.     return (0);
  353. }
  354.  
  355. /*
  356.  * open space for next line in the queue
  357.  */
  358. char *
  359. newline()
  360. {
  361.     bufhead = SUCC(bufhead);
  362.     if (bufhead == buftail) {
  363.         fputs(line[buftail], stdout);
  364.         buftail = SUCC(buftail);
  365.     }
  366.     return (line[bufhead]);
  367. }
  368.  
  369. /*
  370.  * empty the queue by printing out all its lines.
  371.  */
  372. emptyqueue()
  373. {
  374.     while (buftail != bufhead) {
  375.         fputs(line[buftail], stdout);
  376.         buftail = SUCC(buftail);
  377.     }
  378. }
  379.  
  380. /*
  381.  * Compute the hash of a string.
  382.  * Return the hash and the size of the item hashed
  383.  */
  384. hash(cp, size)
  385.     char *cp;
  386.     int *size;
  387. {
  388.     register char *cp1 = cp;
  389.     register int hash = 0;
  390.  
  391.     while (*cp1 && *cp1 != '\n')
  392.         hash += (int)*cp1++;
  393.     *size = cp1 - cp + 1;
  394.     hash &= HSHSIZ - 1;
  395.     return (hash);
  396. }
  397.