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