]> Zhao Yanbai Git Server - minix.git/blob - commands/cawf/expand.c
886c549246aeb9a7e779bbb941707b81417f787f
[minix.git] / commands / cawf / expand.c
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
33 /*
34 * Expand(line) - expand macro or if/ie/el line
35 */
36
37 void
38 Expand(line)
39 unsigned char *line;
40 {
41 unsigned char buf[2*MAXLINE]; /* line buffer */
42 unsigned 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 unsigned 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 char op; /* comparison operator */
55 int prevcond; /* previous condition (for else's) */
56 int ptr = -1; /* Macrotxt[] index */
57 int quote; /* quoted string status */
58 unsigned char *s1, *s2; /* temporary string pointers */
59
60
61 (void) sprintf((char *)buf, ".^= %d %s", NR, (char *)Inname);
62 Pass2(buf);
63
64 for (lp = line; *lp; ) {
65 invert = regexec(Pat[1].pat, lp);
66 prevcond = cond;
67 cond = 0;
68 if (regexec(Pat[0].pat, lp) == 0) {
69 /*
70 * Not conditional: - ! "^[.'](i[ef]|el)"
71 */
72 cond = 1;
73 iflen = 0;
74 }
75
76 else if (regexec(Pat[2].pat, lp)) {
77 /*
78 * Argument count comparison: -
79 * "^[.']i[ef] !?\\n\(\.\$(>|>=|=|<|<=)[0-9] "
80 */
81 iflen = strlen(".if \\n(.$=n ") + invert;
82 s1 = lp + iflen - 3;
83 op = *s1++;
84 if (*s1 == '=' && (op == '>' || op == '<')) {
85 s1++;
86 op = (op == '>') ? 'G' : 'L';
87 }
88 n1 = (int)(*s1 - '0');
89 switch (op) {
90 case '=':
91 if ((nargs - 1) == n1)
92 cond = 1;
93 break;
94 case '<':
95 if ((nargs - 1) < n1)
96 cond = 1;
97 break;
98 case '>':
99 if ((nargs - 1) > n1)
100 cond = 1;
101 break;
102 case 'G': /* >= */
103 if ((nargs - 1) >= n1)
104 cond = 1;
105 break;
106 case 'L': /* <= */
107 if ((nargs - 1) <= n1)
108 cond = 1;
109 }
110 }
111
112 else if (regexec(Pat[3].pat, lp)) {
113 /*
114 * Argument string comparison: - "^[.']i[ef] !?'\\\$[0-9]'[^']*' "
115 */
116 iflen = strlen(".if '\\$n'") + invert;
117 n1 = (int)(*(lp + iflen - 2) - '0');
118 if (n1 >= 0 && n1 < nargs)
119 s1 = Args[n1];
120 else
121 s1 = (unsigned char *)"";
122 if ((s2 = (unsigned char *)strchr((char *)lp
123 + iflen, '\''))
124 != NULL) {
125 n2 = s2 - lp - iflen;
126 if (strncmp((char *)s1, (char *)lp + iflen, n2)
127 == 0)
128 cond = 1;
129 iflen += n2 + 2;
130 }
131 }
132
133 else if (regexec(Pat[4].pat, lp)) {
134 /*
135 * Nroff or troff: - "^[.']i[ef] !?[nt] "
136 */
137 iflen = strlen(".if n ") + invert;
138 if (*(lp + iflen - 2) == 'n')
139 cond = 1;
140 }
141
142 else if ((*lp == '.' || *lp == '\'')
143 && strncmp((char *)lp+1, "el ", 3) == 0) {
144 /*
145 * Else clause: - "^[.']el "
146 */
147 cond = 1 - prevcond;
148 iflen = 4;
149 }
150
151 else {
152 /*
153 * Unknown conditional:
154 */
155 cond = 1;
156 iflen = 0;
157 (void) sprintf((char *)buf,
158 ".tm unknown .if/.ie form: %s", (char *)lp);
159 lp = buf;
160 }
161 /*
162 * Handle conditional. If case is true, locate predicate.
163 * If predicate is an .i[ef], process it.
164 */
165 if (invert)
166 cond = 1 - cond;
167 if (cond && iflen > 0) {
168 lp += iflen;
169 if (regexec(Pat[15].pat, lp))
170 continue;
171 }
172 /*
173 * Do argument substitution, as necessary.
174 */
175 if (cond && regexec(Pat[5].pat, lp)) { /* "\$[0-9]" ??? */
176 for (s1 = buf;;) {
177 if ((n1 = Pat[5].pat->startp[0] - lp) > 0) {
178 (void) strncpy((char *)s1, (char *)lp,
179 n1);
180 s1 += n1;
181 }
182 *s1 = '\0';
183 lp = Pat[5].pat->endp[0];
184 n1 = (int)(*(lp-1) - '0');
185 if (n1 >= 0 && n1 < nargs) {
186 (void) strcpy((char *)s1,
187 (char *)Args[n1]);
188 s1 += strlen((char *)Args[n1]);
189 }
190 if (*lp == '\0')
191 break;
192 if (regexec(Pat[5].pat, lp) == 0) {
193 (void) strcpy((char *)s1, (char *)lp);
194 break;
195 }
196 }
197 lp = buf;
198 }
199 /*
200 * Check for nroff command.
201 */
202 if (cond) {
203 cmdl = 0;
204 if (cond && (*lp == '.' || *lp == '\'')) {
205 if ((*cmd = *(lp+1)) != '\0') {
206 cmdl++;
207 if ((*(cmd+1) = *(lp+2)) == ' ')
208 *(cmd+1) = '\0';
209 else
210 cmdl++;
211 }
212 }
213 cmd[cmdl] = '\0';
214 }
215 if (cond == 0)
216 i = i; /* do nothing if condition is false */
217 else if (cmdl == 0 || ((cmdx = Findmacro(cmd, 0)) < 0))
218 Pass2(lp);
219 else if (Sp >= MAXSP) {
220 (void) sprintf((char *)buf, " macro nesting > %d",
221 MAXSP);
222 Error(WARN, LINE, (char *)buf, NULL);
223 } else {
224 /*
225 * Stack macros.
226 */
227 /*
228 * Push stack.
229 */
230 Sp++;
231 Nleftstack[Sp] = nleft;
232 Ptrstack[Sp] = ptr;
233 Mxstack[Sp] = mx;
234 Condstack[Sp] = cond;
235 for (i = 10*Sp, j = 0; j < 10; i++, j++) {
236 Argstack[i] = Args[j];
237 Args[j] = NULL;
238 }
239 /*
240 * Start new stack entry.
241 */
242 mx = cmdx;
243 ptr = Macrotab[mx].bx;
244 cond = 0;
245 nleft = Macrotab[mx].ct;
246 Args[0] = Newstr(cmd);
247 /*
248 * Parse arguments.
249 */
250 for (s1 = lp + cmdl + 1, nargs = 1; nargs < 10;) {
251 while (*s1 && (*s1 == ' ' || *s1 == '\t'))
252 s1++;
253 if (*s1 == '\0')
254 break;
255 if (*s1 == '"') {
256 s1++;
257 quote = 1;
258 } else
259 quote = 0;
260 for (s2 = buf;;) {
261 if (!quote && (*s1 == ' ' || *s1 == '\t')) {
262 *s2 = '\0';
263 break;
264 }
265 if ((*s2 = *s1) == '\0')
266 break;
267 s1++;
268 if (quote && *s2 == '"') {
269 *s2 = '\0';
270 break;
271 }
272 s2++;
273 }
274 if (buf[0])
275 Args[nargs++] = Newstr(buf);
276 }
277 for (i = nargs; i < 10; i++) {
278 Args[i] = NULL;
279 }
280 }
281 /*
282 * Unstack completed macros.
283 */
284 while (nleft <= 0 && Sp >= 0) {
285 nleft = Nleftstack[Sp];
286 mx = Mxstack[Sp];
287 ptr = Ptrstack[Sp];
288 cond = Condstack[Sp];
289 for (i = 10*Sp, j = 0, nargs = -1; j < 10; i++, j++) {
290 Free(&Args[j]);
291 if ((Args[j] = Argstack[i]) != NULL)
292 nargs = j;
293 }
294 Sp--;
295 nargs++;
296 }
297 /*
298 * Get next line.
299 */
300 if (nleft > 0) {
301 lp = Macrotxt[ptr++];
302 nleft--;
303 } else
304 lp = (unsigned char *)"";
305 }
306 (void) sprintf((char *)buf, ".^# %d %s", NR, (char *)Inname);
307 Pass2(buf);
308 }