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