eval.c revision 1.14 1 1.14 tv /* $NetBSD: eval.c,v 1.14 2001/11/14 06:16:08 tv Exp $ */
2 1.14 tv /* $OpenBSD: eval.c,v 1.41 2001/10/10 23:25:31 espie Exp $ */
3 1.4 tls
4 1.1 cgd /*
5 1.2 glass * Copyright (c) 1989, 1993
6 1.2 glass * The Regents of the University of California. All rights reserved.
7 1.1 cgd *
8 1.1 cgd * This code is derived from software contributed to Berkeley by
9 1.2 glass * Ozan Yigit at York University.
10 1.1 cgd *
11 1.1 cgd * Redistribution and use in source and binary forms, with or without
12 1.1 cgd * modification, are permitted provided that the following conditions
13 1.1 cgd * are met:
14 1.1 cgd * 1. Redistributions of source code must retain the above copyright
15 1.1 cgd * notice, this list of conditions and the following disclaimer.
16 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 cgd * notice, this list of conditions and the following disclaimer in the
18 1.1 cgd * documentation and/or other materials provided with the distribution.
19 1.1 cgd * 3. All advertising materials mentioning features or use of this software
20 1.1 cgd * must display the following acknowledgement:
21 1.1 cgd * This product includes software developed by the University of
22 1.1 cgd * California, Berkeley and its contributors.
23 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
24 1.1 cgd * may be used to endorse or promote products derived from this software
25 1.1 cgd * without specific prior written permission.
26 1.1 cgd *
27 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 1.1 cgd * SUCH DAMAGE.
38 1.1 cgd */
39 1.1 cgd
40 1.10 lukem #include <sys/cdefs.h>
41 1.1 cgd #ifndef lint
42 1.4 tls #if 0
43 1.4 tls static char sccsid[] = "@(#)eval.c 8.2 (Berkeley) 4/27/95";
44 1.4 tls #else
45 1.14 tv __RCSID("$NetBSD: eval.c,v 1.14 2001/11/14 06:16:08 tv Exp $");
46 1.4 tls #endif
47 1.1 cgd #endif /* not lint */
48 1.1 cgd
49 1.1 cgd /*
50 1.1 cgd * eval.c
51 1.1 cgd * Facility: m4 macro processor
52 1.1 cgd * by: oz
53 1.1 cgd */
54 1.1 cgd
55 1.2 glass #include <sys/types.h>
56 1.10 lukem #include <err.h>
57 1.2 glass #include <errno.h>
58 1.14 tv #include <fcntl.h>
59 1.1 cgd #include <stdio.h>
60 1.1 cgd #include <stdlib.h>
61 1.14 tv #include <stddef.h>
62 1.1 cgd #include <string.h>
63 1.1 cgd #include "mdef.h"
64 1.2 glass #include "stdd.h"
65 1.2 glass #include "extern.h"
66 1.2 glass #include "pathnames.h"
67 1.1 cgd
68 1.14 tv #define BUILTIN_MARKER "__builtin_"
69 1.14 tv
70 1.14 tv static void dodefn __P((const char *));
71 1.14 tv static void dopushdef __P((const char *, const char *));
72 1.14 tv static void dodump __P((const char *[], int));
73 1.14 tv static void dotrace __P((const char *[], int, int));
74 1.14 tv static void doifelse __P((const char *[], int));
75 1.14 tv static int doincl __P((const char *));
76 1.14 tv static int dopaste __P((const char *));
77 1.14 tv static void gnu_dochq __P((const char *[], int));
78 1.14 tv static void dochq __P((const char *[], int));
79 1.14 tv static void gnu_dochc __P((const char *[], int));
80 1.14 tv static void dochc __P((const char *[], int));
81 1.14 tv static void dodiv __P((int));
82 1.14 tv static void doundiv __P((const char *[], int));
83 1.14 tv static void dosub __P((const char *[], int));
84 1.14 tv static void map __P((char *, const char *, const char *, const char *));
85 1.14 tv static const char *handledash __P((char *, char *, const char *));
86 1.14 tv static void expand_builtin __P((const char *[], int, int));
87 1.14 tv static void expand_macro __P((const char *[], int));
88 1.14 tv static void dump_one_def __P((ndptr));
89 1.14 tv
90 1.14 tv unsigned long expansion_id;
91 1.14 tv
92 1.1 cgd /*
93 1.14 tv * eval - eval all macros and builtins calls
94 1.1 cgd * argc - number of elements in argv.
95 1.1 cgd * argv - element vector :
96 1.1 cgd * argv[0] = definition of a user
97 1.1 cgd * macro or nil if built-in.
98 1.1 cgd * argv[1] = name of the macro or
99 1.1 cgd * built-in.
100 1.1 cgd * argv[2] = parameters to user-defined
101 1.1 cgd * . macro or built-in.
102 1.1 cgd * .
103 1.1 cgd *
104 1.14 tv * A call in the form of macro-or-builtin() will result in:
105 1.1 cgd * argv[0] = nullstr
106 1.1 cgd * argv[1] = macro-or-builtin
107 1.1 cgd * argv[2] = nullstr
108 1.14 tv *
109 1.14 tv * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
110 1.1 cgd */
111 1.14 tv void
112 1.14 tv eval(argv, argc, td)
113 1.14 tv const char *argv[];
114 1.14 tv int argc;
115 1.14 tv int td;
116 1.14 tv {
117 1.14 tv ssize_t mark = -1;
118 1.1 cgd
119 1.14 tv expansion_id++;
120 1.14 tv if (td & RECDEF)
121 1.14 tv errx(1, "%s at line %lu: expanding recursive definition for %s",
122 1.14 tv CURRENT_NAME, CURRENT_LINE, argv[1]);
123 1.14 tv if (traced_macros && is_traced(argv[1]))
124 1.14 tv mark = trace(argv, argc, infile+ilevel);
125 1.14 tv if (td == MACRTYPE)
126 1.14 tv expand_macro(argv, argc);
127 1.14 tv else
128 1.14 tv expand_builtin(argv, argc, td);
129 1.14 tv if (mark != -1)
130 1.14 tv finish_trace(mark);
131 1.14 tv }
132 1.14 tv
133 1.14 tv /*
134 1.14 tv * expand_builtin - evaluate built-in macros.
135 1.14 tv */
136 1.2 glass void
137 1.14 tv expand_builtin(argv, argc, td)
138 1.14 tv const char *argv[];
139 1.10 lukem int argc;
140 1.10 lukem int td;
141 1.1 cgd {
142 1.10 lukem int c, n;
143 1.14 tv int ac;
144 1.2 glass static int sysval = 0;
145 1.1 cgd
146 1.1 cgd #ifdef DEBUG
147 1.1 cgd printf("argc = %d\n", argc);
148 1.1 cgd for (n = 0; n < argc; n++)
149 1.1 cgd printf("argv[%d] = %s\n", n, argv[n]);
150 1.1 cgd #endif
151 1.14 tv
152 1.2 glass /*
153 1.2 glass * if argc == 3 and argv[2] is null, then we
154 1.2 glass * have macro-or-builtin() type call. We adjust
155 1.2 glass * argc to avoid further checking..
156 1.2 glass */
157 1.14 tv ac = argc;
158 1.14 tv
159 1.1 cgd if (argc == 3 && !*(argv[2]))
160 1.1 cgd argc--;
161 1.1 cgd
162 1.14 tv switch (td & TYPEMASK) {
163 1.1 cgd
164 1.1 cgd case DEFITYPE:
165 1.1 cgd if (argc > 2)
166 1.1 cgd dodefine(argv[2], (argc > 3) ? argv[3] : null);
167 1.1 cgd break;
168 1.1 cgd
169 1.1 cgd case PUSDTYPE:
170 1.1 cgd if (argc > 2)
171 1.1 cgd dopushdef(argv[2], (argc > 3) ? argv[3] : null);
172 1.1 cgd break;
173 1.1 cgd
174 1.1 cgd case DUMPTYPE:
175 1.1 cgd dodump(argv, argc);
176 1.1 cgd break;
177 1.1 cgd
178 1.14 tv case TRACEONTYPE:
179 1.14 tv dotrace(argv, argc, 1);
180 1.14 tv break;
181 1.14 tv
182 1.14 tv case TRACEOFFTYPE:
183 1.14 tv dotrace(argv, argc, 0);
184 1.14 tv break;
185 1.14 tv
186 1.1 cgd case EXPRTYPE:
187 1.2 glass /*
188 1.2 glass * doexpr - evaluate arithmetic
189 1.2 glass * expression
190 1.2 glass */
191 1.1 cgd if (argc > 2)
192 1.1 cgd pbnum(expr(argv[2]));
193 1.1 cgd break;
194 1.1 cgd
195 1.1 cgd case IFELTYPE:
196 1.1 cgd if (argc > 4)
197 1.1 cgd doifelse(argv, argc);
198 1.1 cgd break;
199 1.1 cgd
200 1.1 cgd case IFDFTYPE:
201 1.2 glass /*
202 1.2 glass * doifdef - select one of two
203 1.2 glass * alternatives based on the existence of
204 1.2 glass * another definition
205 1.2 glass */
206 1.1 cgd if (argc > 3) {
207 1.1 cgd if (lookup(argv[2]) != nil)
208 1.1 cgd pbstr(argv[3]);
209 1.1 cgd else if (argc > 4)
210 1.1 cgd pbstr(argv[4]);
211 1.1 cgd }
212 1.1 cgd break;
213 1.1 cgd
214 1.1 cgd case LENGTYPE:
215 1.2 glass /*
216 1.2 glass * dolen - find the length of the
217 1.2 glass * argument
218 1.2 glass */
219 1.14 tv pbnum((argc > 2) ? strlen(argv[2]) : 0);
220 1.1 cgd break;
221 1.1 cgd
222 1.1 cgd case INCRTYPE:
223 1.2 glass /*
224 1.2 glass * doincr - increment the value of the
225 1.2 glass * argument
226 1.2 glass */
227 1.1 cgd if (argc > 2)
228 1.1 cgd pbnum(atoi(argv[2]) + 1);
229 1.1 cgd break;
230 1.1 cgd
231 1.1 cgd case DECRTYPE:
232 1.2 glass /*
233 1.2 glass * dodecr - decrement the value of the
234 1.2 glass * argument
235 1.2 glass */
236 1.1 cgd if (argc > 2)
237 1.1 cgd pbnum(atoi(argv[2]) - 1);
238 1.1 cgd break;
239 1.1 cgd
240 1.1 cgd case SYSCTYPE:
241 1.2 glass /*
242 1.2 glass * dosys - execute system command
243 1.2 glass */
244 1.1 cgd if (argc > 2)
245 1.1 cgd sysval = system(argv[2]);
246 1.1 cgd break;
247 1.1 cgd
248 1.1 cgd case SYSVTYPE:
249 1.2 glass /*
250 1.2 glass * dosysval - return value of the last
251 1.2 glass * system call.
252 1.2 glass *
253 1.2 glass */
254 1.1 cgd pbnum(sysval);
255 1.1 cgd break;
256 1.1 cgd
257 1.14 tv case ESYSCMDTYPE:
258 1.14 tv if (argc > 2)
259 1.14 tv doesyscmd(argv[2]);
260 1.14 tv break;
261 1.1 cgd case INCLTYPE:
262 1.1 cgd if (argc > 2)
263 1.2 glass if (!doincl(argv[2]))
264 1.14 tv err(1, "%s at line %lu: include(%s)",
265 1.14 tv CURRENT_NAME, CURRENT_LINE, argv[2]);
266 1.1 cgd break;
267 1.1 cgd
268 1.1 cgd case SINCTYPE:
269 1.1 cgd if (argc > 2)
270 1.1 cgd (void) doincl(argv[2]);
271 1.1 cgd break;
272 1.1 cgd #ifdef EXTENDED
273 1.1 cgd case PASTTYPE:
274 1.1 cgd if (argc > 2)
275 1.2 glass if (!dopaste(argv[2]))
276 1.14 tv err(1, "%s at line %lu: paste(%s)",
277 1.14 tv CURRENT_NAME, CURRENT_LINE, argv[2]);
278 1.1 cgd break;
279 1.1 cgd
280 1.1 cgd case SPASTYPE:
281 1.1 cgd if (argc > 2)
282 1.1 cgd (void) dopaste(argv[2]);
283 1.1 cgd break;
284 1.1 cgd #endif
285 1.1 cgd case CHNQTYPE:
286 1.14 tv if (mimic_gnu)
287 1.14 tv gnu_dochq(argv, ac);
288 1.14 tv else
289 1.14 tv dochq(argv, argc);
290 1.1 cgd break;
291 1.1 cgd
292 1.1 cgd case CHNCTYPE:
293 1.14 tv if (mimic_gnu)
294 1.14 tv gnu_dochc(argv, ac);
295 1.14 tv else
296 1.14 tv dochc(argv, argc);
297 1.1 cgd break;
298 1.1 cgd
299 1.1 cgd case SUBSTYPE:
300 1.2 glass /*
301 1.2 glass * dosub - select substring
302 1.2 glass *
303 1.2 glass */
304 1.1 cgd if (argc > 3)
305 1.2 glass dosub(argv, argc);
306 1.1 cgd break;
307 1.1 cgd
308 1.1 cgd case SHIFTYPE:
309 1.2 glass /*
310 1.2 glass * doshift - push back all arguments
311 1.2 glass * except the first one (i.e. skip
312 1.2 glass * argv[2])
313 1.2 glass */
314 1.1 cgd if (argc > 3) {
315 1.2 glass for (n = argc - 1; n > 3; n--) {
316 1.9 cgd pbstr(rquote);
317 1.1 cgd pbstr(argv[n]);
318 1.9 cgd pbstr(lquote);
319 1.7 pk putback(COMMA);
320 1.1 cgd }
321 1.9 cgd pbstr(rquote);
322 1.1 cgd pbstr(argv[3]);
323 1.9 cgd pbstr(lquote);
324 1.1 cgd }
325 1.1 cgd break;
326 1.1 cgd
327 1.1 cgd case DIVRTYPE:
328 1.1 cgd if (argc > 2 && (n = atoi(argv[2])) != 0)
329 1.1 cgd dodiv(n);
330 1.1 cgd else {
331 1.1 cgd active = stdout;
332 1.1 cgd oindex = 0;
333 1.1 cgd }
334 1.1 cgd break;
335 1.1 cgd
336 1.1 cgd case UNDVTYPE:
337 1.1 cgd doundiv(argv, argc);
338 1.1 cgd break;
339 1.1 cgd
340 1.1 cgd case DIVNTYPE:
341 1.2 glass /*
342 1.2 glass * dodivnum - return the number of
343 1.2 glass * current output diversion
344 1.2 glass */
345 1.1 cgd pbnum(oindex);
346 1.1 cgd break;
347 1.1 cgd
348 1.1 cgd case UNDFTYPE:
349 1.2 glass /*
350 1.2 glass * doundefine - undefine a previously
351 1.2 glass * defined macro(s) or m4 keyword(s).
352 1.2 glass */
353 1.1 cgd if (argc > 2)
354 1.1 cgd for (n = 2; n < argc; n++)
355 1.1 cgd remhash(argv[n], ALL);
356 1.1 cgd break;
357 1.1 cgd
358 1.1 cgd case POPDTYPE:
359 1.2 glass /*
360 1.2 glass * dopopdef - remove the topmost
361 1.2 glass * definitions of macro(s) or m4
362 1.2 glass * keyword(s).
363 1.2 glass */
364 1.1 cgd if (argc > 2)
365 1.1 cgd for (n = 2; n < argc; n++)
366 1.1 cgd remhash(argv[n], TOP);
367 1.1 cgd break;
368 1.1 cgd
369 1.1 cgd case MKTMTYPE:
370 1.2 glass /*
371 1.2 glass * dotemp - create a temporary file
372 1.2 glass */
373 1.11 mrg if (argc > 2) {
374 1.11 mrg int fd;
375 1.14 tv char *temp;
376 1.11 mrg
377 1.14 tv temp = xstrdup(argv[2]);
378 1.14 tv
379 1.14 tv fd = mkstemp(temp);
380 1.11 mrg if (fd == -1)
381 1.14 tv err(1,
382 1.14 tv "%s at line %lu: couldn't make temp file %s",
383 1.14 tv CURRENT_NAME, CURRENT_LINE, argv[2]);
384 1.11 mrg close(fd);
385 1.14 tv pbstr(temp);
386 1.14 tv free(temp);
387 1.11 mrg }
388 1.1 cgd break;
389 1.1 cgd
390 1.1 cgd case TRNLTYPE:
391 1.2 glass /*
392 1.2 glass * dotranslit - replace all characters in
393 1.2 glass * the source string that appears in the
394 1.2 glass * "from" string with the corresponding
395 1.2 glass * characters in the "to" string.
396 1.2 glass */
397 1.1 cgd if (argc > 3) {
398 1.14 tv char temp[STRSPMAX+1];
399 1.1 cgd if (argc > 4)
400 1.1 cgd map(temp, argv[2], argv[3], argv[4]);
401 1.1 cgd else
402 1.1 cgd map(temp, argv[2], argv[3], null);
403 1.1 cgd pbstr(temp);
404 1.14 tv } else if (argc > 2)
405 1.1 cgd pbstr(argv[2]);
406 1.1 cgd break;
407 1.1 cgd
408 1.1 cgd case INDXTYPE:
409 1.2 glass /*
410 1.2 glass * doindex - find the index of the second
411 1.2 glass * argument string in the first argument
412 1.2 glass * string. -1 if not present.
413 1.2 glass */
414 1.1 cgd pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
415 1.1 cgd break;
416 1.1 cgd
417 1.1 cgd case ERRPTYPE:
418 1.2 glass /*
419 1.2 glass * doerrp - print the arguments to stderr
420 1.2 glass * file
421 1.2 glass */
422 1.1 cgd if (argc > 2) {
423 1.1 cgd for (n = 2; n < argc; n++)
424 1.2 glass fprintf(stderr, "%s ", argv[n]);
425 1.1 cgd fprintf(stderr, "\n");
426 1.1 cgd }
427 1.1 cgd break;
428 1.1 cgd
429 1.1 cgd case DNLNTYPE:
430 1.2 glass /*
431 1.2 glass * dodnl - eat-up-to and including
432 1.2 glass * newline
433 1.2 glass */
434 1.1 cgd while ((c = gpbc()) != '\n' && c != EOF)
435 1.1 cgd ;
436 1.1 cgd break;
437 1.1 cgd
438 1.1 cgd case M4WRTYPE:
439 1.2 glass /*
440 1.2 glass * dom4wrap - set up for
441 1.2 glass * wrap-up/wind-down activity
442 1.2 glass */
443 1.2 glass m4wraps = (argc > 2) ? xstrdup(argv[2]) : null;
444 1.1 cgd break;
445 1.1 cgd
446 1.1 cgd case EXITTYPE:
447 1.2 glass /*
448 1.2 glass * doexit - immediate exit from m4.
449 1.2 glass */
450 1.3 mycroft killdiv();
451 1.1 cgd exit((argc > 2) ? atoi(argv[2]) : 0);
452 1.1 cgd break;
453 1.1 cgd
454 1.1 cgd case DEFNTYPE:
455 1.1 cgd if (argc > 2)
456 1.1 cgd for (n = 2; n < argc; n++)
457 1.1 cgd dodefn(argv[n]);
458 1.1 cgd break;
459 1.1 cgd
460 1.14 tv case INDIRTYPE: /* Indirect call */
461 1.14 tv if (argc > 2)
462 1.14 tv doindir(argv, argc);
463 1.14 tv break;
464 1.14 tv
465 1.14 tv case BUILTINTYPE: /* Builtins only */
466 1.14 tv if (argc > 2)
467 1.14 tv dobuiltin(argv, argc);
468 1.14 tv break;
469 1.14 tv
470 1.14 tv case PATSTYPE:
471 1.14 tv if (argc > 2)
472 1.14 tv dopatsubst(argv, argc);
473 1.14 tv break;
474 1.14 tv case REGEXPTYPE:
475 1.14 tv if (argc > 2)
476 1.14 tv doregexp(argv, argc);
477 1.14 tv break;
478 1.14 tv case LINETYPE:
479 1.14 tv doprintlineno(infile+ilevel);
480 1.14 tv break;
481 1.14 tv case FILENAMETYPE:
482 1.14 tv doprintfilename(infile+ilevel);
483 1.14 tv break;
484 1.14 tv case SELFTYPE:
485 1.14 tv pbstr(rquote);
486 1.14 tv pbstr(argv[1]);
487 1.14 tv pbstr(lquote);
488 1.14 tv break;
489 1.1 cgd default:
490 1.14 tv errx(1, "%s at line %lu: eval: major botch.",
491 1.14 tv CURRENT_NAME, CURRENT_LINE);
492 1.1 cgd break;
493 1.1 cgd }
494 1.2 glass }
495 1.2 glass
496 1.2 glass /*
497 1.14 tv * expand_macro - user-defined macro expansion
498 1.2 glass */
499 1.2 glass void
500 1.14 tv expand_macro(argv, argc)
501 1.14 tv const char *argv[];
502 1.10 lukem int argc;
503 1.2 glass {
504 1.14 tv const char *t;
505 1.14 tv const char *p;
506 1.10 lukem int n;
507 1.10 lukem int argno;
508 1.2 glass
509 1.2 glass t = argv[0]; /* defn string as a whole */
510 1.2 glass p = t;
511 1.2 glass while (*p)
512 1.2 glass p++;
513 1.2 glass p--; /* last character of defn */
514 1.2 glass while (p > t) {
515 1.2 glass if (*(p - 1) != ARGFLAG)
516 1.14 tv PUTBACK(*p);
517 1.2 glass else {
518 1.2 glass switch (*p) {
519 1.2 glass
520 1.2 glass case '#':
521 1.2 glass pbnum(argc - 2);
522 1.2 glass break;
523 1.2 glass case '0':
524 1.2 glass case '1':
525 1.2 glass case '2':
526 1.2 glass case '3':
527 1.2 glass case '4':
528 1.2 glass case '5':
529 1.2 glass case '6':
530 1.2 glass case '7':
531 1.2 glass case '8':
532 1.2 glass case '9':
533 1.2 glass if ((argno = *p - '0') < argc - 1)
534 1.2 glass pbstr(argv[argno + 1]);
535 1.2 glass break;
536 1.2 glass case '*':
537 1.14 tv if (argc > 2) {
538 1.14 tv for (n = argc - 1; n > 2; n--) {
539 1.14 tv pbstr(argv[n]);
540 1.14 tv putback(COMMA);
541 1.14 tv }
542 1.14 tv pbstr(argv[2]);
543 1.14 tv }
544 1.2 glass break;
545 1.14 tv case '@':
546 1.14 tv if (argc > 2) {
547 1.14 tv for (n = argc - 1; n > 2; n--) {
548 1.14 tv pbstr(rquote);
549 1.14 tv pbstr(argv[n]);
550 1.14 tv pbstr(lquote);
551 1.14 tv putback(COMMA);
552 1.14 tv }
553 1.13 jdolecek pbstr(rquote);
554 1.14 tv pbstr(argv[2]);
555 1.13 jdolecek pbstr(lquote);
556 1.13 jdolecek }
557 1.14 tv break;
558 1.2 glass default:
559 1.14 tv PUTBACK(*p);
560 1.14 tv PUTBACK('$');
561 1.2 glass break;
562 1.2 glass }
563 1.2 glass p--;
564 1.2 glass }
565 1.2 glass p--;
566 1.2 glass }
567 1.2 glass if (p == t) /* do last character */
568 1.14 tv PUTBACK(*p);
569 1.2 glass }
570 1.2 glass
571 1.2 glass /*
572 1.2 glass * dodefine - install definition in the table
573 1.2 glass */
574 1.2 glass void
575 1.2 glass dodefine(name, defn)
576 1.14 tv const char *name;
577 1.14 tv const char *defn;
578 1.2 glass {
579 1.10 lukem ndptr p;
580 1.14 tv int n;
581 1.2 glass
582 1.2 glass if (!*name)
583 1.14 tv errx(1, "%s at line %lu: null definition.", CURRENT_NAME,
584 1.14 tv CURRENT_LINE);
585 1.2 glass if ((p = lookup(name)) == nil)
586 1.2 glass p = addent(name);
587 1.2 glass else if (p->defn != null)
588 1.2 glass free((char *) p->defn);
589 1.14 tv if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) {
590 1.14 tv n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1);
591 1.14 tv if (n != -1) {
592 1.14 tv p->type = n & TYPEMASK;
593 1.14 tv if ((n & NOARGS) == 0)
594 1.14 tv p->type |= NEEDARGS;
595 1.14 tv p->defn = null;
596 1.14 tv return;
597 1.14 tv }
598 1.14 tv }
599 1.2 glass if (!*defn)
600 1.2 glass p->defn = null;
601 1.2 glass else
602 1.2 glass p->defn = xstrdup(defn);
603 1.2 glass p->type = MACRTYPE;
604 1.14 tv if (STREQ(name, defn))
605 1.14 tv p->type |= RECDEF;
606 1.2 glass }
607 1.2 glass
608 1.2 glass /*
609 1.2 glass * dodefn - push back a quoted definition of
610 1.2 glass * the given name.
611 1.2 glass */
612 1.14 tv static void
613 1.2 glass dodefn(name)
614 1.14 tv const char *name;
615 1.2 glass {
616 1.10 lukem ndptr p;
617 1.14 tv const char *real;
618 1.2 glass
619 1.14 tv if ((p = lookup(name)) != nil) {
620 1.14 tv if (p->defn != null) {
621 1.14 tv pbstr(rquote);
622 1.14 tv pbstr(p->defn);
623 1.14 tv pbstr(lquote);
624 1.14 tv } else if ((real = builtin_realname(p->type)) != NULL) {
625 1.14 tv pbstr(real);
626 1.14 tv pbstr(BUILTIN_MARKER);
627 1.14 tv }
628 1.2 glass }
629 1.2 glass }
630 1.2 glass
631 1.2 glass /*
632 1.2 glass * dopushdef - install a definition in the hash table
633 1.2 glass * without removing a previous definition. Since
634 1.2 glass * each new entry is entered in *front* of the
635 1.2 glass * hash bucket, it hides a previous definition from
636 1.2 glass * lookup.
637 1.2 glass */
638 1.14 tv static void
639 1.2 glass dopushdef(name, defn)
640 1.14 tv const char *name;
641 1.14 tv const char *defn;
642 1.2 glass {
643 1.10 lukem ndptr p;
644 1.2 glass
645 1.2 glass if (!*name)
646 1.14 tv errx(1, "%s at line %lu: null definition", CURRENT_NAME,
647 1.14 tv CURRENT_LINE);
648 1.2 glass p = addent(name);
649 1.2 glass if (!*defn)
650 1.2 glass p->defn = null;
651 1.2 glass else
652 1.2 glass p->defn = xstrdup(defn);
653 1.2 glass p->type = MACRTYPE;
654 1.14 tv if (STREQ(name, defn))
655 1.14 tv p->type |= RECDEF;
656 1.14 tv }
657 1.14 tv
658 1.14 tv /*
659 1.14 tv * dump_one_def - dump the specified definition.
660 1.14 tv */
661 1.14 tv static void
662 1.14 tv dump_one_def(p)
663 1.14 tv ndptr p;
664 1.14 tv {
665 1.14 tv const char *real;
666 1.14 tv
667 1.14 tv if (mimic_gnu) {
668 1.14 tv if ((p->type & TYPEMASK) == MACRTYPE)
669 1.14 tv fprintf(traceout, "%s:\t%s\n", p->name, p->defn);
670 1.14 tv else {
671 1.14 tv real = builtin_realname(p->type);
672 1.14 tv if (real == NULL)
673 1.14 tv real = null;
674 1.14 tv fprintf(traceout, "%s:\t<%s>\n", p->name, real);
675 1.14 tv }
676 1.14 tv } else
677 1.14 tv fprintf(traceout, "`%s'\t`%s'\n", p->name, p->defn);
678 1.2 glass }
679 1.2 glass
680 1.2 glass /*
681 1.2 glass * dodumpdef - dump the specified definitions in the hash
682 1.2 glass * table to stderr. If nothing is specified, the entire
683 1.2 glass * hash table is dumped.
684 1.2 glass */
685 1.14 tv static void
686 1.2 glass dodump(argv, argc)
687 1.14 tv const char *argv[];
688 1.10 lukem int argc;
689 1.2 glass {
690 1.10 lukem int n;
691 1.2 glass ndptr p;
692 1.2 glass
693 1.2 glass if (argc > 2) {
694 1.2 glass for (n = 2; n < argc; n++)
695 1.2 glass if ((p = lookup(argv[n])) != nil)
696 1.14 tv dump_one_def(p);
697 1.14 tv } else {
698 1.2 glass for (n = 0; n < HASHSIZE; n++)
699 1.2 glass for (p = hashtab[n]; p != nil; p = p->nxtptr)
700 1.14 tv dump_one_def(p);
701 1.2 glass }
702 1.2 glass }
703 1.2 glass
704 1.2 glass /*
705 1.14 tv * dotrace - mark some macros as traced/untraced depending upon on.
706 1.14 tv */
707 1.14 tv static void
708 1.14 tv dotrace(argv, argc, on)
709 1.14 tv const char *argv[];
710 1.14 tv int argc;
711 1.14 tv int on;
712 1.14 tv {
713 1.14 tv int n;
714 1.14 tv
715 1.14 tv if (argc > 2) {
716 1.14 tv for (n = 2; n < argc; n++)
717 1.14 tv mark_traced(argv[n], on);
718 1.14 tv } else
719 1.14 tv mark_traced(NULL, on);
720 1.14 tv }
721 1.14 tv
722 1.14 tv /*
723 1.2 glass * doifelse - select one of two alternatives - loop.
724 1.2 glass */
725 1.14 tv static void
726 1.2 glass doifelse(argv, argc)
727 1.14 tv const char *argv[];
728 1.10 lukem int argc;
729 1.2 glass {
730 1.2 glass cycle {
731 1.2 glass if (STREQ(argv[2], argv[3]))
732 1.2 glass pbstr(argv[4]);
733 1.2 glass else if (argc == 6)
734 1.2 glass pbstr(argv[5]);
735 1.2 glass else if (argc > 6) {
736 1.2 glass argv += 3;
737 1.2 glass argc -= 3;
738 1.2 glass continue;
739 1.2 glass }
740 1.2 glass break;
741 1.2 glass }
742 1.2 glass }
743 1.2 glass
744 1.2 glass /*
745 1.2 glass * doinclude - include a given file.
746 1.2 glass */
747 1.14 tv static int
748 1.2 glass doincl(ifile)
749 1.14 tv const char *ifile;
750 1.2 glass {
751 1.2 glass if (ilevel + 1 == MAXINP)
752 1.14 tv errx(1, "%s at line %lu: too many include files.",
753 1.14 tv CURRENT_NAME, CURRENT_LINE);
754 1.14 tv if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
755 1.2 glass ilevel++;
756 1.2 glass bbase[ilevel] = bufbase = bp;
757 1.2 glass return (1);
758 1.14 tv } else
759 1.2 glass return (0);
760 1.2 glass }
761 1.2 glass
762 1.2 glass #ifdef EXTENDED
763 1.2 glass /*
764 1.2 glass * dopaste - include a given file without any
765 1.2 glass * macro processing.
766 1.2 glass */
767 1.14 tv static int
768 1.2 glass dopaste(pfile)
769 1.14 tv const char *pfile;
770 1.2 glass {
771 1.2 glass FILE *pf;
772 1.10 lukem int c;
773 1.2 glass
774 1.2 glass if ((pf = fopen(pfile, "r")) != NULL) {
775 1.2 glass while ((c = getc(pf)) != EOF)
776 1.2 glass putc(c, active);
777 1.2 glass (void) fclose(pf);
778 1.2 glass return (1);
779 1.14 tv } else
780 1.2 glass return (0);
781 1.2 glass }
782 1.2 glass #endif
783 1.2 glass
784 1.14 tv static void
785 1.14 tv gnu_dochq(argv, ac)
786 1.14 tv const char *argv[];
787 1.14 tv int ac;
788 1.14 tv {
789 1.14 tv /* In gnu-m4 mode, the only way to restore quotes is to have no
790 1.14 tv * arguments at all. */
791 1.14 tv if (ac == 2) {
792 1.14 tv lquote[0] = LQUOTE, lquote[1] = EOS;
793 1.14 tv rquote[0] = RQUOTE, rquote[1] = EOS;
794 1.14 tv } else {
795 1.14 tv strlcpy(lquote, argv[2], sizeof(lquote));
796 1.14 tv if(ac > 3)
797 1.14 tv strlcpy(rquote, argv[3], sizeof(rquote));
798 1.14 tv else
799 1.14 tv rquote[0] = EOS;
800 1.14 tv }
801 1.14 tv }
802 1.14 tv
803 1.2 glass /*
804 1.2 glass * dochq - change quote characters
805 1.2 glass */
806 1.14 tv static void
807 1.2 glass dochq(argv, argc)
808 1.14 tv const char *argv[];
809 1.10 lukem int argc;
810 1.2 glass {
811 1.2 glass if (argc > 2) {
812 1.2 glass if (*argv[2])
813 1.14 tv strlcpy(lquote, argv[2], sizeof(lquote));
814 1.14 tv else {
815 1.14 tv lquote[0] = LQUOTE;
816 1.14 tv lquote[1] = EOS;
817 1.14 tv }
818 1.2 glass if (argc > 3) {
819 1.2 glass if (*argv[3])
820 1.14 tv strlcpy(rquote, argv[3], sizeof(rquote));
821 1.14 tv } else
822 1.5 pk strcpy(rquote, lquote);
823 1.14 tv } else {
824 1.14 tv lquote[0] = LQUOTE, lquote[1] = EOS;
825 1.14 tv rquote[0] = RQUOTE, rquote[1] = EOS;
826 1.2 glass }
827 1.14 tv }
828 1.14 tv
829 1.14 tv static void
830 1.14 tv gnu_dochc(argv, ac)
831 1.14 tv const char *argv[];
832 1.14 tv int ac;
833 1.14 tv {
834 1.14 tv /* In gnu-m4 mode, no arguments mean no comment
835 1.14 tv * arguments at all. */
836 1.14 tv if (ac == 2) {
837 1.14 tv scommt[0] = EOS;
838 1.14 tv ecommt[0] = EOS;
839 1.14 tv } else {
840 1.14 tv if (*argv[2])
841 1.14 tv strlcpy(scommt, argv[2], sizeof(scommt));
842 1.14 tv else
843 1.14 tv scommt[0] = SCOMMT, scommt[1] = EOS;
844 1.14 tv if(ac > 3 && *argv[3])
845 1.14 tv strlcpy(ecommt, argv[3], sizeof(ecommt));
846 1.14 tv else
847 1.14 tv ecommt[0] = ECOMMT, ecommt[1] = EOS;
848 1.2 glass }
849 1.2 glass }
850 1.2 glass /*
851 1.2 glass * dochc - change comment characters
852 1.2 glass */
853 1.14 tv static void
854 1.2 glass dochc(argv, argc)
855 1.14 tv const char *argv[];
856 1.10 lukem int argc;
857 1.2 glass {
858 1.2 glass if (argc > 2) {
859 1.2 glass if (*argv[2])
860 1.14 tv strlcpy(scommt, argv[2], sizeof(scommt));
861 1.2 glass if (argc > 3) {
862 1.2 glass if (*argv[3])
863 1.14 tv strlcpy(ecommt, argv[3], sizeof(ecommt));
864 1.2 glass }
865 1.2 glass else
866 1.14 tv ecommt[0] = ECOMMT, ecommt[1] = EOS;
867 1.2 glass }
868 1.2 glass else {
869 1.14 tv scommt[0] = SCOMMT, scommt[1] = EOS;
870 1.14 tv ecommt[0] = ECOMMT, ecommt[1] = EOS;
871 1.2 glass }
872 1.2 glass }
873 1.2 glass
874 1.2 glass /*
875 1.2 glass * dodivert - divert the output to a temporary file
876 1.2 glass */
877 1.14 tv static void
878 1.2 glass dodiv(n)
879 1.10 lukem int n;
880 1.2 glass {
881 1.14 tv int fd;
882 1.9 cgd
883 1.14 tv oindex = n;
884 1.14 tv if (n >= maxout) {
885 1.14 tv if (mimic_gnu)
886 1.14 tv resizedivs(n + 10);
887 1.14 tv else
888 1.14 tv n = 0; /* bitbucket */
889 1.14 tv }
890 1.9 cgd
891 1.14 tv if (n < 0)
892 1.14 tv n = 0; /* bitbucket */
893 1.14 tv if (outfile[n] == NULL) {
894 1.14 tv char fname[] = _PATH_DIVNAME;
895 1.14 tv
896 1.14 tv if ((fd = mkstemp(fname)) < 0 ||
897 1.14 tv (outfile[n] = fdopen(fd, "w+")) == NULL)
898 1.14 tv err(1, "%s: cannot divert", fname);
899 1.14 tv if (unlink(fname) == -1)
900 1.14 tv err(1, "%s: cannot unlink", fname);
901 1.2 glass }
902 1.14 tv active = outfile[n];
903 1.2 glass }
904 1.2 glass
905 1.2 glass /*
906 1.2 glass * doundivert - undivert a specified output, or all
907 1.2 glass * other outputs, in numerical order.
908 1.2 glass */
909 1.14 tv static void
910 1.2 glass doundiv(argv, argc)
911 1.14 tv const char *argv[];
912 1.10 lukem int argc;
913 1.2 glass {
914 1.10 lukem int ind;
915 1.10 lukem int n;
916 1.2 glass
917 1.2 glass if (argc > 2) {
918 1.2 glass for (ind = 2; ind < argc; ind++) {
919 1.2 glass n = atoi(argv[ind]);
920 1.14 tv if (n > 0 && n < maxout && outfile[n] != NULL)
921 1.2 glass getdiv(n);
922 1.2 glass
923 1.2 glass }
924 1.2 glass }
925 1.2 glass else
926 1.14 tv for (n = 1; n < maxout; n++)
927 1.2 glass if (outfile[n] != NULL)
928 1.2 glass getdiv(n);
929 1.2 glass }
930 1.2 glass
931 1.2 glass /*
932 1.2 glass * dosub - select substring
933 1.2 glass */
934 1.14 tv static void
935 1.2 glass dosub(argv, argc)
936 1.14 tv const char *argv[];
937 1.10 lukem int argc;
938 1.2 glass {
939 1.14 tv const char *ap, *fc, *k;
940 1.10 lukem int nc;
941 1.2 glass
942 1.14 tv ap = argv[2]; /* target string */
943 1.2 glass #ifdef EXPR
944 1.14 tv fc = ap + expr(argv[3]); /* first char */
945 1.2 glass #else
946 1.14 tv fc = ap + atoi(argv[3]); /* first char */
947 1.2 glass #endif
948 1.14 tv nc = strlen(fc);
949 1.14 tv if (argc >= 5)
950 1.2 glass #ifdef EXPR
951 1.14 tv nc = min(nc, expr(argv[4]));
952 1.2 glass #else
953 1.14 tv nc = min(nc, atoi(argv[4]));
954 1.2 glass #endif
955 1.2 glass if (fc >= ap && fc < ap + strlen(ap))
956 1.14 tv for (k = fc + nc - 1; k >= fc; k--)
957 1.2 glass putback(*k);
958 1.2 glass }
959 1.2 glass
960 1.2 glass /*
961 1.2 glass * map:
962 1.2 glass * map every character of s1 that is specified in from
963 1.2 glass * into s3 and replace in s. (source s1 remains untouched)
964 1.2 glass *
965 1.2 glass * This is a standard implementation of map(s,from,to) function of ICON
966 1.2 glass * language. Within mapvec, we replace every character of "from" with
967 1.2 glass * the corresponding character in "to". If "to" is shorter than "from",
968 1.2 glass * than the corresponding entries are null, which means that those
969 1.2 glass * characters dissapear altogether. Furthermore, imagine
970 1.2 glass * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
971 1.2 glass * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
972 1.2 glass * ultimately maps to `*'. In order to achieve this effect in an efficient
973 1.2 glass * manner (i.e. without multiple passes over the destination string), we
974 1.2 glass * loop over mapvec, starting with the initial source character. if the
975 1.2 glass * character value (dch) in this location is different than the source
976 1.2 glass * character (sch), sch becomes dch, once again to index into mapvec, until
977 1.2 glass * the character value stabilizes (i.e. sch = dch, in other words
978 1.2 glass * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
979 1.2 glass * character, it will stabilize, since mapvec[0] == 0 at all times. At the
980 1.2 glass * end, we restore mapvec* back to normal where mapvec[n] == n for
981 1.2 glass * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
982 1.2 glass * about 5 times faster than any algorithm that makes multiple passes over
983 1.2 glass * destination string.
984 1.2 glass */
985 1.14 tv static void
986 1.2 glass map(dest, src, from, to)
987 1.10 lukem char *dest;
988 1.14 tv const char *src;
989 1.14 tv const char *from;
990 1.14 tv const char *to;
991 1.14 tv {
992 1.14 tv const char *tmp;
993 1.14 tv unsigned char sch, dch;
994 1.14 tv static char frombis[257];
995 1.14 tv static char tobis[257];
996 1.14 tv static unsigned char mapvec[256] = {
997 1.14 tv 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
998 1.14 tv 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
999 1.14 tv 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
1000 1.14 tv 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
1001 1.14 tv 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
1002 1.14 tv 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
1003 1.14 tv 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
1004 1.14 tv 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
1005 1.14 tv 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
1006 1.14 tv 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
1007 1.14 tv 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
1008 1.14 tv 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
1009 1.14 tv 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
1010 1.14 tv 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
1011 1.14 tv 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
1012 1.14 tv 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
1013 1.14 tv 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
1014 1.14 tv 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
1015 1.2 glass };
1016 1.2 glass
1017 1.2 glass if (*src) {
1018 1.14 tv if (mimic_gnu) {
1019 1.14 tv /*
1020 1.14 tv * expand character ranges on the fly
1021 1.14 tv */
1022 1.14 tv from = handledash(frombis, frombis + 256, from);
1023 1.14 tv to = handledash(tobis, tobis + 256, to);
1024 1.14 tv }
1025 1.2 glass tmp = from;
1026 1.2 glass /*
1027 1.2 glass * create a mapping between "from" and
1028 1.2 glass * "to"
1029 1.2 glass */
1030 1.2 glass while (*from)
1031 1.14 tv mapvec[(unsigned char)(*from++)] = (*to) ?
1032 1.14 tv (unsigned char)(*to++) : 0;
1033 1.2 glass
1034 1.2 glass while (*src) {
1035 1.14 tv sch = (unsigned char)(*src++);
1036 1.14 tv dch = mapvec[sch];
1037 1.2 glass while (dch != sch) {
1038 1.2 glass sch = dch;
1039 1.14 tv dch = mapvec[sch];
1040 1.2 glass }
1041 1.14 tv if ((*dest = (char)dch))
1042 1.2 glass dest++;
1043 1.2 glass }
1044 1.2 glass /*
1045 1.2 glass * restore all the changed characters
1046 1.2 glass */
1047 1.2 glass while (*tmp) {
1048 1.14 tv mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
1049 1.2 glass tmp++;
1050 1.2 glass }
1051 1.2 glass }
1052 1.14 tv *dest = '\0';
1053 1.14 tv }
1054 1.14 tv
1055 1.14 tv
1056 1.14 tv /*
1057 1.14 tv * handledash:
1058 1.14 tv * use buffer to copy the src string, expanding character ranges
1059 1.14 tv * on the way.
1060 1.14 tv */
1061 1.14 tv static const char *
1062 1.14 tv handledash(buffer, end, src)
1063 1.14 tv char *buffer;
1064 1.14 tv char *end;
1065 1.14 tv const char *src;
1066 1.14 tv {
1067 1.14 tv char *p;
1068 1.14 tv
1069 1.14 tv p = buffer;
1070 1.14 tv while(*src) {
1071 1.14 tv if (src[1] == '-' && src[2]) {
1072 1.14 tv unsigned char i;
1073 1.14 tv for (i = (unsigned char)src[0];
1074 1.14 tv i <= (unsigned char)src[2]; i++) {
1075 1.14 tv *p++ = i;
1076 1.14 tv if (p == end) {
1077 1.14 tv *p = '\0';
1078 1.14 tv return buffer;
1079 1.14 tv }
1080 1.14 tv }
1081 1.14 tv src += 3;
1082 1.14 tv } else
1083 1.14 tv *p++ = *src++;
1084 1.14 tv if (p == end)
1085 1.14 tv break;
1086 1.14 tv }
1087 1.14 tv *p = '\0';
1088 1.14 tv return buffer;
1089 1.1 cgd }
1090 1.14 tv
1091