improve behaviour under VPC, fixes from nicolas tittley.
[minix.git] / commands / m4 / eval.c
blobb1f472bd58997a9f29adb9ee6bd226454df164a3
1 /*
2 * eval.c
3 * Facility: m4 macro processor
4 * by: oz
5 */
7 #include "mdef.h"
8 #include "extr.h"
11 * eval - evaluate built-in macros.
12 * argc - number of elements in argv.
13 * argv - element vector :
14 * argv[0] = definition of a user
15 * macro or nil if built-in.
16 * argv[1] = name of the macro or
17 * built-in.
18 * argv[2] = parameters to user-defined
19 * . macro or built-in.
20 * .
22 * Note that the minimum value for argc is 3. A call in the form
23 * of macro-or-builtin() will result in:
24 * argv[0] = nullstr
25 * argv[1] = macro-or-builtin
26 * argv[2] = nullstr
30 void eval (argv, argc, td)
31 register char *argv[];
32 register int argc;
33 register int td;
35 register int c, n;
36 static int sysval;
38 #ifdef DEBUG
39 printf("argc = %d\n", argc);
40 for (n = 0; n < argc; n++)
41 printf("argv[%d] = %s\n", n, argv[n]);
42 #endif
44 * if argc == 3 and argv[2] is null,
45 * then we have macro-or-builtin() type call.
46 * We adjust argc to avoid further checking..
49 if (argc == 3 && !*(argv[2]))
50 argc--;
52 switch (td & ~STATIC) {
54 case DEFITYPE:
55 if (argc > 2)
56 dodefine(argv[2], (argc > 3) ? argv[3] : null);
57 break;
59 case PUSDTYPE:
60 if (argc > 2)
61 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
62 break;
64 case DUMPTYPE:
65 dodump(argv, argc);
66 break;
68 case EXPRTYPE:
70 * doexpr - evaluate arithmetic expression
73 if (argc > 2)
74 pbnum(expr(argv[2]));
75 break;
77 case IFELTYPE:
78 if (argc > 4)
79 doifelse(argv, argc);
80 break;
82 case IFDFTYPE:
84 * doifdef - select one of two alternatives based
85 * on the existence of another definition
87 if (argc > 3) {
88 if (lookup(argv[2]) != nil)
89 pbstr(argv[3]);
90 else if (argc > 4)
91 pbstr(argv[4]);
93 break;
95 case LENGTYPE:
97 * dolen - find the length of the argument
100 if (argc > 2)
101 pbnum((argc > 2) ? strlen(argv[2]) : 0);
102 break;
104 case INCRTYPE:
106 * doincr - increment the value of the argument
109 if (argc > 2)
110 pbnum(atoi(argv[2]) + 1);
111 break;
113 case DECRTYPE:
115 * dodecr - decrement the value of the argument
118 if (argc > 2)
119 pbnum(atoi(argv[2]) - 1);
120 break;
122 #if unix || vms
124 case SYSCTYPE:
126 * dosys - execute system command
129 if (argc > 2)
130 sysval = system(argv[2]);
131 break;
133 case SYSVTYPE:
135 * dosysval - return value of the last system call.
138 pbnum(sysval);
139 break;
140 #endif
142 case INCLTYPE:
143 if (argc > 2)
144 if (!doincl(argv[2])) {
145 fprintf(stderr,"m4: %s: ",argv[2]);
146 error("cannot open for read.");
148 break;
150 case SINCTYPE:
151 if (argc > 2)
152 (void) doincl(argv[2]);
153 break;
154 #ifdef EXTENDED
155 case PASTTYPE:
156 if (argc > 2)
157 if (!dopaste(argv[2])) {
158 fprintf(stderr,"m4: %s: ",argv[2]);
159 error("cannot open for read.");
161 break;
163 case SPASTYPE:
164 if (argc > 2)
165 (void) dopaste(argv[2]);
166 break;
167 #endif
168 case CHNQTYPE:
169 dochq(argv, argc);
170 break;
172 case CHNCTYPE:
173 dochc(argv, argc);
174 break;
176 case SUBSTYPE:
178 * dosub - select substring
181 if (argc > 3)
182 dosub(argv,argc);
183 break;
185 case SHIFTYPE:
187 * doshift - push back all arguments except the
188 * first one (i.e. skip argv[2])
190 if (argc > 3) {
191 for (n = argc-1; n > 3; n--) {
192 putback(rquote);
193 pbstr(argv[n]);
194 putback(lquote);
195 putback(',');
197 putback(rquote);
198 pbstr(argv[3]);
199 putback(lquote);
201 break;
203 case DIVRTYPE:
204 if (argc > 2 && (n = atoi(argv[2])) != 0)
205 dodiv(n);
206 else {
207 active = stdout;
208 oindex = 0;
210 break;
212 case UNDVTYPE:
213 doundiv(argv, argc);
214 break;
216 case DIVNTYPE:
218 * dodivnum - return the number of current
219 * output diversion
222 pbnum(oindex);
223 break;
225 case UNDFTYPE:
227 * doundefine - undefine a previously defined
228 * macro(s) or m4 keyword(s).
230 if (argc > 2)
231 for (n = 2; n < argc; n++)
232 remhash(argv[n], ALL);
233 break;
235 case POPDTYPE:
237 * dopopdef - remove the topmost definitions of
238 * macro(s) or m4 keyword(s).
240 if (argc > 2)
241 for (n = 2; n < argc; n++)
242 remhash(argv[n], TOP);
243 break;
245 case MKTMTYPE:
247 * dotemp - create a temporary file
250 if (argc > 2)
251 pbstr(mktemp(argv[2]));
252 break;
254 case TRNLTYPE:
256 * dotranslit - replace all characters in the
257 * source string that appears in
258 * the "from" string with the corresponding
259 * characters in the "to" string.
262 if (argc > 3) {
263 char temp[MAXTOK];
264 if (argc > 4)
265 map(temp, argv[2], argv[3], argv[4]);
266 else
267 map(temp, argv[2], argv[3], null);
268 pbstr(temp);
270 else
271 if (argc > 2)
272 pbstr(argv[2]);
273 break;
275 case INDXTYPE:
277 * doindex - find the index of the second argument
278 * string in the first argument string.
279 * -1 if not present.
281 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
282 break;
284 case ERRPTYPE:
286 * doerrp - print the arguments to stderr file
289 if (argc > 2) {
290 for (n = 2; n < argc; n++)
291 fprintf(stderr,"%s ", argv[n]);
292 fprintf(stderr, "\n");
294 break;
296 case DNLNTYPE:
298 * dodnl - eat-up-to and including newline
301 while ((c = gpbc()) != '\n' && c != EOF)
303 break;
305 case M4WRTYPE:
307 * dom4wrap - set up for wrap-up/wind-down activity
310 m4wraps = (argc > 2) ? strsave(argv[2]) : null;
311 break;
313 case EXITTYPE:
315 * doexit - immediate exit from m4.
318 exit((argc > 2) ? atoi(argv[2]) : 0);
319 break;
321 case DEFNTYPE:
322 if (argc > 2)
323 for (n = 2; n < argc; n++)
324 dodefn(argv[n]);
325 break;
327 default:
328 error("m4: major botch in eval.");
329 break;