new copyright; att/bsd/shared
[unix-history] / usr / src / usr.bin / m4 / eval.c
CommitLineData
5597fa04
KB
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 *
6ecf3d85 8 * %sccs.include.redist.c%
5597fa04
KB
9 */
10
11#ifndef lint
50841d34 12static char sccsid[] = "@(#)eval.c 5.4 (Berkeley) %G%";
5597fa04
KB
13#endif /* not lint */
14
15/*
16 * eval.c
17 * Facility: m4 macro processor
18 * by: oz
19 */
20
50841d34
KB
21#include <unistd.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
5597fa04
KB
25#include "mdef.h"
26#include "extr.h"
27
28extern ndptr lookup();
5597fa04
KB
29
30/*
31 * eval - evaluate built-in macros.
32 * argc - number of elements in argv.
33 * argv - element vector :
34 * argv[0] = definition of a user
35 * macro or nil if built-in.
36 * argv[1] = name of the macro or
37 * built-in.
38 * argv[2] = parameters to user-defined
39 * . macro or built-in.
40 * .
41 *
42 * Note that the minimum value for argc is 3. A call in the form
43 * of macro-or-builtin() will result in:
44 * argv[0] = nullstr
45 * argv[1] = macro-or-builtin
46 * argv[2] = nullstr
47 *
48 */
49
50eval (argv, argc, td)
51register char *argv[];
52register int argc;
53register int td;
54{
55 register int c, n;
56 static int sysval;
57
58#ifdef DEBUG
59 printf("argc = %d\n", argc);
60 for (n = 0; n < argc; n++)
61 printf("argv[%d] = %s\n", n, argv[n]);
62#endif
63 /*
64 * if argc == 3 and argv[2] is null,
65 * then we have macro-or-builtin() type call.
66 * We adjust argc to avoid further checking..
67 *
68 */
69 if (argc == 3 && !*(argv[2]))
70 argc--;
71
72 switch (td & ~STATIC) {
73
74 case DEFITYPE:
75 if (argc > 2)
76 dodefine(argv[2], (argc > 3) ? argv[3] : null);
77 break;
78
79 case PUSDTYPE:
80 if (argc > 2)
81 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
82 break;
83
84 case DUMPTYPE:
85 dodump(argv, argc);
86 break;
87
88 case EXPRTYPE:
89 /*
90 * doexpr - evaluate arithmetic expression
91 *
92 */
93 if (argc > 2)
94 pbnum(expr(argv[2]));
95 break;
96
97 case IFELTYPE:
98 if (argc > 4)
99 doifelse(argv, argc);
100 break;
101
102 case IFDFTYPE:
103 /*
104 * doifdef - select one of two alternatives based
105 * on the existence of another definition
106 */
107 if (argc > 3) {
108 if (lookup(argv[2]) != nil)
109 pbstr(argv[3]);
110 else if (argc > 4)
111 pbstr(argv[4]);
112 }
113 break;
114
115 case LENGTYPE:
116 /*
117 * dolen - find the length of the argument
118 *
119 */
120 if (argc > 2)
121 pbnum((argc > 2) ? strlen(argv[2]) : 0);
122 break;
123
124 case INCRTYPE:
125 /*
126 * doincr - increment the value of the argument
127 *
128 */
129 if (argc > 2)
130 pbnum(atoi(argv[2]) + 1);
131 break;
132
133 case DECRTYPE:
134 /*
135 * dodecr - decrement the value of the argument
136 *
137 */
138 if (argc > 2)
139 pbnum(atoi(argv[2]) - 1);
140 break;
141
5597fa04
KB
142 case SYSCTYPE:
143 /*
144 * dosys - execute system command
145 *
146 */
147 if (argc > 2)
148 sysval = system(argv[2]);
149 break;
150
151 case SYSVTYPE:
152 /*
153 * dosysval - return value of the last system call.
154 *
155 */
156 pbnum(sysval);
157 break;
5597fa04
KB
158
159 case INCLTYPE:
160 if (argc > 2)
161 if (!doincl(argv[2])) {
162 fprintf(stderr,"m4: %s: ",argv[2]);
163 error("cannot open for read.");
164 }
165 break;
166
167 case SINCTYPE:
168 if (argc > 2)
169 (void) doincl(argv[2]);
170 break;
171#ifdef EXTENDED
172 case PASTTYPE:
173 if (argc > 2)
174 if (!dopaste(argv[2])) {
175 fprintf(stderr,"m4: %s: ",argv[2]);
176 error("cannot open for read.");
177 }
178 break;
179
180 case SPASTYPE:
181 if (argc > 2)
182 (void) dopaste(argv[2]);
183 break;
184#endif
185 case CHNQTYPE:
186 dochq(argv, argc);
187 break;
188
189 case CHNCTYPE:
190 dochc(argv, argc);
191 break;
192
193 case SUBSTYPE:
194 /*
195 * dosub - select substring
196 *
197 */
198 if (argc > 3)
199 dosub(argv,argc);
200 break;
201
202 case SHIFTYPE:
203 /*
204 * doshift - push back all arguments except the
205 * first one (i.e. skip argv[2])
206 */
207 if (argc > 3) {
208 for (n = argc-1; n > 3; n--) {
209 putback(rquote);
210 pbstr(argv[n]);
211 putback(lquote);
212 putback(',');
213 }
214 putback(rquote);
215 pbstr(argv[3]);
216 putback(lquote);
217 }
218 break;
219
220 case DIVRTYPE:
221 if (argc > 2 && (n = atoi(argv[2])) != 0)
222 dodiv(n);
223 else {
224 active = stdout;
225 oindex = 0;
226 }
227 break;
228
229 case UNDVTYPE:
230 doundiv(argv, argc);
231 break;
232
233 case DIVNTYPE:
234 /*
235 * dodivnum - return the number of current
236 * output diversion
237 *
238 */
239 pbnum(oindex);
240 break;
241
242 case UNDFTYPE:
243 /*
244 * doundefine - undefine a previously defined
245 * macro(s) or m4 keyword(s).
246 */
247 if (argc > 2)
248 for (n = 2; n < argc; n++)
249 remhash(argv[n], ALL);
250 break;
251
252 case POPDTYPE:
253 /*
254 * dopopdef - remove the topmost definitions of
255 * macro(s) or m4 keyword(s).
256 */
257 if (argc > 2)
258 for (n = 2; n < argc; n++)
259 remhash(argv[n], TOP);
260 break;
261
262 case MKTMTYPE:
263 /*
264 * dotemp - create a temporary file
265 *
266 */
267 if (argc > 2)
268 pbstr(mktemp(argv[2]));
269 break;
270
271 case TRNLTYPE:
272 /*
273 * dotranslit - replace all characters in the
274 * source string that appears in
275 * the "from" string with the corresponding
276 * characters in the "to" string.
277 *
278 */
279 if (argc > 3) {
280 char temp[MAXTOK];
281 if (argc > 4)
282 map(temp, argv[2], argv[3], argv[4]);
283 else
284 map(temp, argv[2], argv[3], null);
285 pbstr(temp);
286 }
287 else
288 if (argc > 2)
289 pbstr(argv[2]);
290 break;
291
292 case INDXTYPE:
293 /*
294 * doindex - find the index of the second argument
295 * string in the first argument string.
296 * -1 if not present.
297 */
298 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
299 break;
300
301 case ERRPTYPE:
302 /*
303 * doerrp - print the arguments to stderr file
304 *
305 */
306 if (argc > 2) {
307 for (n = 2; n < argc; n++)
308 fprintf(stderr,"%s ", argv[n]);
309 fprintf(stderr, "\n");
310 }
311 break;
312
313 case DNLNTYPE:
314 /*
315 * dodnl - eat-up-to and including newline
316 *
317 */
318 while ((c = gpbc()) != '\n' && c != EOF)
319 ;
320 break;
321
322 case M4WRTYPE:
323 /*
324 * dom4wrap - set up for wrap-up/wind-down activity
325 *
326 */
50841d34 327 m4wraps = (argc > 2) ? strdup(argv[2]) : null;
5597fa04
KB
328 break;
329
330 case EXITTYPE:
331 /*
332 * doexit - immediate exit from m4.
333 *
334 */
335 exit((argc > 2) ? atoi(argv[2]) : 0);
336 break;
337
338 case DEFNTYPE:
339 if (argc > 2)
340 for (n = 2; n < argc; n++)
341 dodefn(argv[n]);
342 break;
343
344 default:
345 error("m4: major botch in eval.");
346 break;
347 }
348}