home *** CD-ROM | disk | FTP | other *** search
- /*
- * expand.c - macro expansion functions for cawf(1)
- */
-
- /*
- * Copyright (c) 1991 Purdue University Research Foundation,
- * West Lafayette, Indiana 47907. All rights reserved.
- *
- * Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue
- * University Computing Center. Not derived from licensed software;
- * derived from awf(1) by Henry Spencer of the University of Toronto.
- *
- * Permission is granted to anyone to use this software for any
- * purpose on any computer system, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The author is not responsible for any consequences of use of
- * this software, even if they arise from flaws in it.
- *
- * 2. The origin of this software must not be misrepresented, either
- * by explicit claim or by omission. Credits must appear in the
- * documentation.
- *
- * 3. Altered versions must be plainly marked as such, and must not
- * be misrepresented as being the original software. Credits must
- * appear in the documentation.
- *
- * 4. This notice may not be removed or altered.
- */
-
- #include "cawf.h"
-
- /*
- * Expand(line) - expand macro or if/ie/el line
- */
-
- void
- Expand(line)
- unsigned char *line;
- {
- unsigned char buf[2*MAXLINE]; /* line buffer */
- unsigned char cmd[4]; /* nroff command */
- int cmdl; /* command length */
- int cmdx; /* cmd index in Macrotab[] */
- int cond = 0; /* conditional statuses */
- int i, j; /* temporary indexes */
- int iflen; /* if statement length */
- int invert; /* inversion status */
- unsigned char *lp; /* line pointer */
- int mx = -1; /* Macrotab[] index */
- int n1, n2; /* temporary numbers */
- int nargs = 0; /* number of arguments */
- int nleft = 0; /* number of macro lines left */
- char op; /* comparison operator */
- int prevcond; /* previous condition (for else's) */
- int ptr = -1; /* Macrotxt[] index */
- int quote; /* quoted string status */
- unsigned char *s1, *s2; /* temporary string pointers */
-
-
- (void) sprintf((char *)buf, ".^= %d %s", NR, (char *)Inname);
- Pass2(buf);
-
- for (lp = line; *lp; ) {
- invert = regexec(Pat[1].pat, lp);
- prevcond = cond;
- cond = 0;
- if (regexec(Pat[0].pat, lp) == 0) {
- /*
- * Not conditional: - ! "^[.'](i[ef]|el)"
- */
- cond = 1;
- iflen = 0;
- }
-
- else if (regexec(Pat[2].pat, lp)) {
- /*
- * Argument count comparison: -
- * "^[.']i[ef] !?\\n\(\.\$(>|>=|=|<|<=)[0-9] "
- */
- iflen = strlen(".if \\n(.$=n ") + invert;
- s1 = lp + iflen - 3;
- op = *s1++;
- if (*s1 == '=' && (op == '>' || op == '<')) {
- s1++;
- op = (op == '>') ? 'G' : 'L';
- }
- n1 = (int)(*s1 - '0');
- switch (op) {
- case '=':
- if ((nargs - 1) == n1)
- cond = 1;
- break;
- case '<':
- if ((nargs - 1) < n1)
- cond = 1;
- break;
- case '>':
- if ((nargs - 1) > n1)
- cond = 1;
- break;
- case 'G': /* >= */
- if ((nargs - 1) >= n1)
- cond = 1;
- break;
- case 'L': /* <= */
- if ((nargs - 1) <= n1)
- cond = 1;
- }
- }
-
- else if (regexec(Pat[3].pat, lp)) {
- /*
- * Argument string comparison: - "^[.']i[ef] !?'\\\$[0-9]'[^']*' "
- */
- iflen = strlen(".if '\\$n'") + invert;
- n1 = (int)(*(lp + iflen - 2) - '0');
- if (n1 >= 0 && n1 < nargs)
- s1 = Args[n1];
- else
- s1 = (unsigned char *)"";
- if ((s2 = (unsigned char *)strchr((char *)lp
- + iflen, '\''))
- != NULL) {
- n2 = s2 - lp - iflen;
- if (strncmp((char *)s1, (char *)lp + iflen, n2)
- == 0)
- cond = 1;
- iflen += n2 + 2;
- }
- }
-
- else if (regexec(Pat[4].pat, lp)) {
- /*
- * Nroff or troff: - "^[.']i[ef] !?[nt] "
- */
- iflen = strlen(".if n ") + invert;
- if (*(lp + iflen - 2) == 'n')
- cond = 1;
- }
-
- else if ((*lp == '.' || *lp == '\'')
- && strncmp((char *)lp+1, "el ", 3) == 0) {
- /*
- * Else clause: - "^[.']el "
- */
- cond = 1 - prevcond;
- iflen = 4;
- }
-
- else {
- /*
- * Unknown conditional:
- */
- cond = 1;
- iflen = 0;
- (void) sprintf((char *)buf,
- ".tm unknown .if/.ie form: %s", (char *)lp);
- lp = buf;
- }
- /*
- * Handle conditional. If case is true, locate predicate.
- * If predicate is an .i[ef], process it.
- */
- if (invert)
- cond = 1 - cond;
- if (cond && iflen > 0) {
- lp += iflen;
- if (regexec(Pat[15].pat, lp))
- continue;
- }
- /*
- * Do argument substitution, as necessary.
- */
- if (cond && regexec(Pat[5].pat, lp)) { /* "\$[0-9]" ??? */
- for (s1 = buf;;) {
- if ((n1 = Pat[5].pat->startp[0] - lp) > 0) {
- (void) strncpy((char *)s1, (char *)lp,
- n1);
- s1 += n1;
- }
- *s1 = '\0';
- lp = Pat[5].pat->endp[0];
- n1 = (int)(*(lp-1) - '0');
- if (n1 >= 0 && n1 < nargs) {
- (void) strcpy((char *)s1,
- (char *)Args[n1]);
- s1 += strlen((char *)Args[n1]);
- }
- if (*lp == '\0')
- break;
- if (regexec(Pat[5].pat, lp) == 0) {
- (void) strcpy((char *)s1, (char *)lp);
- break;
- }
- }
- lp = buf;
- }
- /*
- * Check for nroff command.
- */
- if (cond) {
- cmdl = 0;
- if (cond && (*lp == '.' || *lp == '\'')) {
- if ((*cmd = *(lp+1)) != '\0') {
- cmdl++;
- if ((*(cmd+1) = *(lp+2)) == ' ')
- *(cmd+1) = '\0';
- else
- cmdl++;
- }
- }
- cmd[cmdl] = '\0';
- }
- if (cond == 0) {
- /* do nothing if condition is false */
- } else if (cmdl == 0 || ((cmdx = Findmacro(cmd, 0)) < 0))
- Pass2(lp);
- else if (Sp >= MAXSP) {
- (void) sprintf((char *)buf, " macro nesting > %d",
- MAXSP);
- Error(WARN, LINE, (char *)buf, NULL);
- } else {
- /*
- * Stack macros.
- */
- /*
- * Push stack.
- */
- Sp++;
- Nleftstack[Sp] = nleft;
- Ptrstack[Sp] = ptr;
- Mxstack[Sp] = mx;
- Condstack[Sp] = cond;
- for (i = 10*Sp, j = 0; j < 10; i++, j++) {
- Argstack[i] = Args[j];
- Args[j] = NULL;
- }
- /*
- * Start new stack entry.
- */
- mx = cmdx;
- ptr = Macrotab[mx].bx;
- cond = 0;
- nleft = Macrotab[mx].ct;
- Args[0] = Newstr(cmd);
- /*
- * Parse arguments.
- */
- for (s1 = lp + cmdl + 1, nargs = 1; nargs < 10;) {
- while (*s1 && (*s1 == ' ' || *s1 == '\t'))
- s1++;
- if (*s1 == '\0')
- break;
- if (*s1 == '"') {
- s1++;
- quote = 1;
- } else
- quote = 0;
- for (s2 = buf;;) {
- if (!quote && (*s1 == ' ' || *s1 == '\t')) {
- *s2 = '\0';
- break;
- }
- if ((*s2 = *s1) == '\0')
- break;
- s1++;
- if (quote && *s2 == '"') {
- *s2 = '\0';
- break;
- }
- s2++;
- }
- if (buf[0])
- Args[nargs++] = Newstr(buf);
- }
- for (i = nargs; i < 10; i++) {
- Args[i] = NULL;
- }
- }
- /*
- * Unstack completed macros.
- */
- while (nleft <= 0 && Sp >= 0) {
- nleft = Nleftstack[Sp];
- mx = Mxstack[Sp];
- ptr = Ptrstack[Sp];
- cond = Condstack[Sp];
- for (i = 10*Sp, j = 0, nargs = -1; j < 10; i++, j++) {
- Free(&Args[j]);
- if ((Args[j] = Argstack[i]) != NULL)
- nargs = j;
- }
- Sp--;
- nargs++;
- }
- /*
- * Get next line.
- */
- if (nleft > 0) {
- lp = Macrotxt[ptr++];
- nleft--;
- } else
- lp = (unsigned char *)"";
- }
- (void) sprintf((char *)buf, ".^# %d %s", NR, (char *)Inname);
- Pass2(buf);
- }
-