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