386BSD 0.1 development
[unix-history] / usr / src / usr.bin / m4 / eval.c
CommitLineData
88bb73f0
WJ
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ozan Yigit.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char sccsid[] = "@(#)eval.c 5.4 (Berkeley) 2/26/91";
39#endif /* not lint */
40
41/*
42 * eval.c
43 * Facility: m4 macro processor
44 * by: oz
45 */
46
47#include <unistd.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include "mdef.h"
52#include "extr.h"
53
54extern ndptr lookup();
55
56/*
57 * eval - evaluate built-in macros.
58 * argc - number of elements in argv.
59 * argv - element vector :
60 * argv[0] = definition of a user
61 * macro or nil if built-in.
62 * argv[1] = name of the macro or
63 * built-in.
64 * argv[2] = parameters to user-defined
65 * . macro or built-in.
66 * .
67 *
68 * Note that the minimum value for argc is 3. A call in the form
69 * of macro-or-builtin() will result in:
70 * argv[0] = nullstr
71 * argv[1] = macro-or-builtin
72 * argv[2] = nullstr
73 *
74 */
75
76eval (argv, argc, td)
77register char *argv[];
78register int argc;
79register int td;
80{
81 register int c, n;
82 static int sysval;
83
84#ifdef DEBUG
85 printf("argc = %d\n", argc);
86 for (n = 0; n < argc; n++)
87 printf("argv[%d] = %s\n", n, argv[n]);
88#endif
89 /*
90 * if argc == 3 and argv[2] is null,
91 * then we have macro-or-builtin() type call.
92 * We adjust argc to avoid further checking..
93 *
94 */
95 if (argc == 3 && !*(argv[2]))
96 argc--;
97
98 switch (td & ~STATIC) {
99
100 case DEFITYPE:
101 if (argc > 2)
102 dodefine(argv[2], (argc > 3) ? argv[3] : null);
103 break;
104
105 case PUSDTYPE:
106 if (argc > 2)
107 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
108 break;
109
110 case DUMPTYPE:
111 dodump(argv, argc);
112 break;
113
114 case EXPRTYPE:
115 /*
116 * doexpr - evaluate arithmetic expression
117 *
118 */
119 if (argc > 2)
120 pbnum(expr(argv[2]));
121 break;
122
123 case IFELTYPE:
124 if (argc > 4)
125 doifelse(argv, argc);
126 break;
127
128 case IFDFTYPE:
129 /*
130 * doifdef - select one of two alternatives based
131 * on the existence of another definition
132 */
133 if (argc > 3) {
134 if (lookup(argv[2]) != nil)
135 pbstr(argv[3]);
136 else if (argc > 4)
137 pbstr(argv[4]);
138 }
139 break;
140
141 case LENGTYPE:
142 /*
143 * dolen - find the length of the argument
144 *
145 */
146 if (argc > 2)
147 pbnum((argc > 2) ? strlen(argv[2]) : 0);
148 break;
149
150 case INCRTYPE:
151 /*
152 * doincr - increment the value of the argument
153 *
154 */
155 if (argc > 2)
156 pbnum(atoi(argv[2]) + 1);
157 break;
158
159 case DECRTYPE:
160 /*
161 * dodecr - decrement the value of the argument
162 *
163 */
164 if (argc > 2)
165 pbnum(atoi(argv[2]) - 1);
166 break;
167
168 case SYSCTYPE:
169 /*
170 * dosys - execute system command
171 *
172 */
173 if (argc > 2)
174 sysval = system(argv[2]);
175 break;
176
177 case SYSVTYPE:
178 /*
179 * dosysval - return value of the last system call.
180 *
181 */
182 pbnum(sysval);
183 break;
184
185 case INCLTYPE:
186 if (argc > 2)
187 if (!doincl(argv[2])) {
188 fprintf(stderr,"m4: %s: ",argv[2]);
189 error("cannot open for read.");
190 }
191 break;
192
193 case SINCTYPE:
194 if (argc > 2)
195 (void) doincl(argv[2]);
196 break;
197#ifdef EXTENDED
198 case PASTTYPE:
199 if (argc > 2)
200 if (!dopaste(argv[2])) {
201 fprintf(stderr,"m4: %s: ",argv[2]);
202 error("cannot open for read.");
203 }
204 break;
205
206 case SPASTYPE:
207 if (argc > 2)
208 (void) dopaste(argv[2]);
209 break;
210#endif
211 case CHNQTYPE:
212 dochq(argv, argc);
213 break;
214
215 case CHNCTYPE:
216 dochc(argv, argc);
217 break;
218
219 case SUBSTYPE:
220 /*
221 * dosub - select substring
222 *
223 */
224 if (argc > 3)
225 dosub(argv,argc);
226 break;
227
228 case SHIFTYPE:
229 /*
230 * doshift - push back all arguments except the
231 * first one (i.e. skip argv[2])
232 */
233 if (argc > 3) {
234 for (n = argc-1; n > 3; n--) {
235 putback(rquote);
236 pbstr(argv[n]);
237 putback(lquote);
238 putback(',');
239 }
240 putback(rquote);
241 pbstr(argv[3]);
242 putback(lquote);
243 }
244 break;
245
246 case DIVRTYPE:
247 if (argc > 2 && (n = atoi(argv[2])) != 0)
248 dodiv(n);
249 else {
250 active = stdout;
251 oindex = 0;
252 }
253 break;
254
255 case UNDVTYPE:
256 doundiv(argv, argc);
257 break;
258
259 case DIVNTYPE:
260 /*
261 * dodivnum - return the number of current
262 * output diversion
263 *
264 */
265 pbnum(oindex);
266 break;
267
268 case UNDFTYPE:
269 /*
270 * doundefine - undefine a previously defined
271 * macro(s) or m4 keyword(s).
272 */
273 if (argc > 2)
274 for (n = 2; n < argc; n++)
275 remhash(argv[n], ALL);
276 break;
277
278 case POPDTYPE:
279 /*
280 * dopopdef - remove the topmost definitions of
281 * macro(s) or m4 keyword(s).
282 */
283 if (argc > 2)
284 for (n = 2; n < argc; n++)
285 remhash(argv[n], TOP);
286 break;
287
288 case MKTMTYPE:
289 /*
290 * dotemp - create a temporary file
291 *
292 */
293 if (argc > 2)
294 pbstr(mktemp(argv[2]));
295 break;
296
297 case TRNLTYPE:
298 /*
299 * dotranslit - replace all characters in the
300 * source string that appears in
301 * the "from" string with the corresponding
302 * characters in the "to" string.
303 *
304 */
305 if (argc > 3) {
306 char temp[MAXTOK];
307 if (argc > 4)
308 map(temp, argv[2], argv[3], argv[4]);
309 else
310 map(temp, argv[2], argv[3], null);
311 pbstr(temp);
312 }
313 else
314 if (argc > 2)
315 pbstr(argv[2]);
316 break;
317
318 case INDXTYPE:
319 /*
320 * doindex - find the index of the second argument
321 * string in the first argument string.
322 * -1 if not present.
323 */
324 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
325 break;
326
327 case ERRPTYPE:
328 /*
329 * doerrp - print the arguments to stderr file
330 *
331 */
332 if (argc > 2) {
333 for (n = 2; n < argc; n++)
334 fprintf(stderr,"%s ", argv[n]);
335 fprintf(stderr, "\n");
336 }
337 break;
338
339 case DNLNTYPE:
340 /*
341 * dodnl - eat-up-to and including newline
342 *
343 */
344 while ((c = gpbc()) != '\n' && c != EOF)
345 ;
346 break;
347
348 case M4WRTYPE:
349 /*
350 * dom4wrap - set up for wrap-up/wind-down activity
351 *
352 */
353 m4wraps = (argc > 2) ? strdup(argv[2]) : null;
354 break;
355
356 case EXITTYPE:
357 /*
358 * doexit - immediate exit from m4.
359 *
360 */
361 exit((argc > 2) ? atoi(argv[2]) : 0);
362 break;
363
364 case DEFNTYPE:
365 if (argc > 2)
366 for (n = 2; n < argc; n++)
367 dodefn(argv[n]);
368 break;
369
370 default:
371 error("m4: major botch in eval.");
372 break;
373 }
374}