xref: /original-bsd/usr.bin/m4/eval.c (revision 95a66346)
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  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)eval.c	5.4 (Berkeley) 02/26/91";
13 #endif /* not lint */
14 
15 /*
16  * eval.c
17  * Facility: m4 macro processor
18  * by: oz
19  */
20 
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "mdef.h"
26 #include "extr.h"
27 
28 extern ndptr lookup();
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 
50 eval (argv, argc, td)
51 register char *argv[];
52 register int argc;
53 register 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 
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;
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 		 */
327 		m4wraps = (argc > 2) ? strdup(argv[2]) : null;
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 }
349