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