home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / UTILITY / CAWF2.ZIP / EXPAND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-04  |  6.7 KB  |  285 lines

  1. /*
  2.  *    expand.c - macro expansion functions for cawf(1)
  3.  */
  4.  
  5. /*
  6.  *    Copyright (c) 1991 Purdue University Research Foundation,
  7.  *    West Lafayette, Indiana 47907.  All rights reserved.
  8.  *
  9.  *    Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
  10.  *    University Computing Center.  Not derived from licensed software;
  11.  *    derived from awf(1) by Henry Spencer of the University of Toronto.
  12.  *
  13.  *    Permission is granted to anyone to use this software for any
  14.  *    purpose on any computer system, and to alter it and redistribute
  15.  *    it freely, subject to the following restrictions:
  16.  *
  17.  *    1. The author is not responsible for any consequences of use of
  18.  *       this software, even if they arise from flaws in it.
  19.  *
  20.  *    2. The origin of this software must not be misrepresented, either
  21.  *       by explicit claim or by omission.  Credits must appear in the
  22.  *       documentation.
  23.  *
  24.  *    3. Altered versions must be plainly marked as such, and must not
  25.  *       be misrepresented as being the original software.  Credits must
  26.  *       appear in the documentation.
  27.  *
  28.  *    4. This notice may not be removed or altered.
  29.  */
  30.  
  31. #include "cawf.h"
  32. #include <string.h>
  33.  
  34. /*
  35.  * Expand(line) - expand macro or if/ie/el line
  36.  */
  37.  
  38. Expand(line)
  39.     char *line;
  40. {
  41.     char buf[2*MAXLINE];        /* line buffer */
  42.     char cmd[4];                    /* nroff command */
  43.     int cmdl;            /* command length */
  44.     int cmdx;                      /* cmd index in Macrotab[] */
  45.     int cond = 0;            /* conditional statuses */
  46.     int i, j;            /* temporary indexes */
  47.     int iflen;            /* if statement length */
  48.     int invert;            /* inversion status */
  49.     char *lp;            /* line pointer */
  50.     int mx = -1;            /* Macrotab[] index */
  51.     int n1, n2;            /* temporary numbers */
  52.     int nargs = 0;            /* number of arguments */
  53.     int nleft = 0;            /* number of macro lines left */
  54.     int prevcond;            /* previous condition (for else's) */
  55.     int ptr = -1;            /* Macrotxt[] index */
  56.     int quote;            /* quoted string status */
  57.     char *s1, *s2;            /* temporary string pointers */
  58.  
  59.  
  60.     (void) sprintf(buf, ".^= %d %s", NR, Inname);
  61.     Pass2(buf);
  62.  
  63.     for (lp = line; *lp; ) {
  64.         invert = regexec(Pat[1].pat, lp);
  65.         prevcond = cond;
  66.         cond = 0;
  67.         if (regexec(Pat[0].pat, lp) == 0) {
  68.         /*
  69.          * Not conditional: - ! "^\.(i[ef]|el)"
  70.          */
  71.             cond = 1;
  72.             iflen = 0;
  73.         }
  74.  
  75.         else if (regexec(Pat[2].pat, lp)) {
  76.         /*
  77.          * Argument count comparison: - "^\.i[ef] !?\\n\(\.\$[<=>][0-9] "
  78.          */
  79.             iflen = strlen(".if \\n(.$=n ") + invert;
  80.             n1 = (int)(*(lp + iflen - 2) - '0');
  81.             switch (*(lp + iflen - 3)) {
  82.                 case '=':
  83.                     if ((nargs - 1) == n1)
  84.                         cond = 1;
  85.                     break;
  86.                 case '<':
  87.                     if ((nargs - 1) < n1)
  88.                         cond = 1;
  89.                     break;
  90.                 case '>':
  91.                     if ((nargs - 1) > n1)
  92.                         cond = 1;
  93.                     break;
  94.             }
  95.         }
  96.         
  97.         else if (regexec(Pat[3].pat, lp)) {
  98.         /*
  99.          * Argument string comparison: - "^\.i[ef] !?'\\\$[0-9]'[^']*' "
  100.          */
  101.             iflen = strlen(".if '\\$n'") + invert;
  102.             n1 = (int)(*(lp + iflen - 2) - '0');
  103.             if (n1 >= 0 && n1 < nargs)
  104.                 s1 = Args[n1];
  105.             else
  106.                 s1 = "";
  107.             if ((s2 = strchr(lp + iflen, '\'')) != NULL) {
  108.                 n2 = s2 - lp - iflen;
  109.                 if (strncmp(s1, lp + iflen, n2) == 0)
  110.                     cond = 1;
  111.                 iflen += n2 + 2;
  112.             }
  113.         }
  114.         
  115.         else if (regexec(Pat[4].pat, lp)) {
  116.         /*
  117.          * Nroff or troff: - "^\.i[ef] !?[nt] "
  118.          */
  119.             iflen = strlen(".if n ") + invert;
  120.             if (*(lp + iflen - 2) == 'n')
  121.                 cond = 1;
  122.         }
  123.         
  124.         else if (strncmp(lp, ".el ", 4) == 0) {
  125.         /*
  126.          * Else clause: - "^\.el "
  127.          */
  128.             cond = 1 - prevcond;
  129.             iflen = 4;
  130.         }
  131.         
  132.         else {
  133.         /*
  134.          * Unknown conditional:
  135.          */
  136.             cond = 1;
  137.             iflen = 0;
  138.             (void) sprintf(buf, ".tm unknown .if/.ie form: %s", lp);
  139.             lp = buf;
  140.         }
  141.        /*
  142.         * Handle conditional.  If case is true, locate predicate.
  143.         * If predicate is an .i[ef], process it.
  144.         */
  145.         if (invert)
  146.             cond = 1 - cond;
  147.         if (cond && iflen > 0) {
  148.             lp += iflen;
  149.             if (regexec(Pat[15].pat, lp))
  150.                 continue;
  151.         }
  152.         /*
  153.          * Do argument substitution, as necessary.
  154.          */
  155.         if (cond && regexec(Pat[5].pat, lp)) {      /* "\$[0-9]" ??? */
  156.             for (s1 = buf;;) {
  157.                 if ((n1 = Pat[5].pat->startp[0] - lp) > 0) {
  158.                     (void) strncpy(s1, lp, n1);
  159.                     s1 += n1;
  160.                 }
  161.                 *s1 = '\0';
  162.                 lp = Pat[5].pat->endp[0];
  163.                 n1 = (int)(*(lp-1) - '0');
  164.                 if (n1 >= 0 && n1 < nargs) {
  165.                     (void) strcpy(s1, Args[n1]);
  166.                     s1 += strlen(Args[n1]);
  167.                 }
  168.                 if (*lp == '\0')
  169.                     break;
  170.                 if (regexec(Pat[5].pat, lp) == 0) {
  171.                     (void) strcpy(s1, lp);
  172.                     break;
  173.                 }
  174.             }
  175.             lp = buf;
  176.         }
  177.         /*
  178.          * Check for nroff command.
  179.          */
  180.         if (cond) {
  181.             cmdl = 0;
  182.             if (cond && *lp == '.') {
  183.                 if ((*cmd = *(lp+1)) != '\0') {
  184.                     cmdl++;
  185.                     if ((*(cmd+1) = *(lp+2)) == ' ')
  186.                         *(cmd+1) = '\0';
  187.                     else
  188.                         cmdl++;
  189.                 }
  190.             }
  191.             cmd[cmdl] = '\0';
  192.         }
  193.         if (cond == 0)
  194.             i = i;        /* do nothing if condition is false */
  195.         else if (cmdl == 0 || ((cmdx = Findmacro(cmd, 0)) < 0))
  196.             Pass2(lp);
  197.         else if (Sp >= MAXSP) {
  198.             (void) sprintf(buf, " macro nesting > %d", MAXSP);
  199.             Error(WARN, LINE, buf, NULL);
  200.         } else {
  201.         /*
  202.          * Stack macros.
  203.          */
  204.           /*
  205.            * Push stack.
  206.            */
  207.             Sp++;
  208.             Nleftstack[Sp] = nleft;
  209.             Ptrstack[Sp] = ptr;
  210.             Mxstack[Sp] = mx;
  211.             Condstack[Sp] = cond;
  212.             for (i = 10*Sp, j = 0; j < 10; i++, j++) {
  213.                 Argstack[i] = Args[j];
  214.                 Args[j] = NULL;
  215.             }
  216.            /*
  217.             * Start new stack entry.
  218.             */
  219.             mx = cmdx;
  220.             ptr = Macrotab[mx].bx;
  221.             cond = 0;
  222.             nleft = Macrotab[mx].ct;
  223.             Args[0] = Newstr(cmd);
  224.            /*
  225.             * Parse arguments.
  226.             */
  227.             for (s1 = lp + cmdl + 1, nargs = 1; nargs < 10;) {
  228.                 while (*s1 && (*s1 == ' ' || *s1 == '\t'))
  229.                     s1++;
  230.                 if (*s1 == '\0')
  231.                     break;
  232.                 if (*s1 == '"') {
  233.                     s1++;
  234.                     quote = 1;
  235.                 } else
  236.                     quote = 0;
  237.                 for (s2 = buf;;) {
  238.                     if (!quote && (*s1 == ' ' || *s1 == '\t')) {
  239.                     *s2 = '\0';
  240.                     break;
  241.                     }
  242.                     if ((*s2 = *s1) == '\0')
  243.                     break;
  244.                     s1++;
  245.                     if (quote && *s2 == '"') {
  246.                     *s2 = '\0';
  247.                     break;
  248.                     }
  249.                     s2++;
  250.                     }
  251.                 Args[nargs++] = Newstr(buf);
  252.             }
  253.             for (i = nargs; i < 10; i++) {
  254.                 Args[i] = NULL;
  255.             }
  256.         }
  257.         /*
  258.          * Unstack completed macros.
  259.          */
  260.         while (nleft <= 0 && Sp >= 0) {
  261.             nleft = Nleftstack[Sp];
  262.             mx = Mxstack[Sp];
  263.             ptr = Ptrstack[Sp];
  264.             cond = Condstack[Sp];
  265.             for (i = 10*Sp, j = 0, nargs = -1; j < 10; i++, j++) {
  266.                 Free(&Args[j]);
  267.                 if ((Args[j] = Argstack[i]) != NULL)
  268.                     nargs = j;
  269.             }
  270.             Sp--;
  271.             nargs++;
  272.         }
  273.         /*
  274.          * Get next line.
  275.          */
  276.         if (nleft > 0) {
  277.             lp = Macrotxt[ptr++];
  278.             nleft--;
  279.         } else
  280.             lp = "";
  281.     }
  282.     (void) sprintf(buf, ".^# %d %s", NR, Inname);
  283.     Pass2(buf);
  284. }
  285.