Sat Jan 23 14:24:43 2016 UTC ()
Explain what REDIRECT is for.


(christos)
diff -r1.45 -r1.46 src/usr.bin/m4/main.c

cvs diff -r1.45 -r1.46 src/usr.bin/m4/main.c (switch to unified diff)

--- src/usr.bin/m4/main.c 2016/01/16 21:12:27 1.45
+++ src/usr.bin/m4/main.c 2016/01/23 14:24:43 1.46
@@ -1,806 +1,811 @@ @@ -1,806 +1,811 @@
1/* $OpenBSD: main.c,v 1.77 2009/10/14 17:19:47 sthen Exp $ */ 1/* $OpenBSD: main.c,v 1.77 2009/10/14 17:19:47 sthen Exp $ */
2/* $NetBSD: main.c,v 1.45 2016/01/16 21:12:27 christos Exp $ */ 2/* $NetBSD: main.c,v 1.46 2016/01/23 14:24:43 christos Exp $ */
3 3
4/*- 4/*-
5 * Copyright (c) 1989, 1993 5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved. 6 * The Regents of the University of California. All rights reserved.
7 * 7 *
8 * This code is derived from software contributed to Berkeley by 8 * This code is derived from software contributed to Berkeley by
9 * Ozan Yigit at York University. 9 * Ozan Yigit at York University.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors 19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 21 * without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. 33 * SUCH DAMAGE.
34 */ 34 */
35 35
36/* 36/*
37 * main.c 37 * main.c
38 * Facility: m4 macro processor 38 * Facility: m4 macro processor
39 * by: oz 39 * by: oz
40 */ 40 */
41#if HAVE_NBTOOL_CONFIG_H 41#if HAVE_NBTOOL_CONFIG_H
42#include "nbtool_config.h" 42#include "nbtool_config.h"
43#endif 43#endif
44#include <sys/cdefs.h> 44#include <sys/cdefs.h>
45__RCSID("$NetBSD: main.c,v 1.45 2016/01/16 21:12:27 christos Exp $"); 45__RCSID("$NetBSD: main.c,v 1.46 2016/01/23 14:24:43 christos Exp $");
46#include <assert.h> 46#include <assert.h>
47#include <signal.h> 47#include <signal.h>
48#include <getopt.h> 48#include <getopt.h>
49#include <err.h> 49#include <err.h>
50#include <errno.h> 50#include <errno.h>
51#include <unistd.h> 51#include <unistd.h>
52#include <stdio.h> 52#include <stdio.h>
53#include <ctype.h> 53#include <ctype.h>
54#include <string.h> 54#include <string.h>
55#include <stddef.h> 55#include <stddef.h>
56#include <stdint.h> 56#include <stdint.h>
57#include <stdlib.h> 57#include <stdlib.h>
58#include <ohash.h> 58#include <ohash.h>
59#include "mdef.h" 59#include "mdef.h"
60#include "stdd.h" 60#include "stdd.h"
61#include "extern.h" 61#include "extern.h"
62#include "pathnames.h" 62#include "pathnames.h"
63 63
64ndptr hashtab[HASHSIZE]; /* hash table for macros etc. */ 64ndptr hashtab[HASHSIZE]; /* hash table for macros etc. */
65stae *mstack; /* stack of m4 machine */ 65stae *mstack; /* stack of m4 machine */
66char *sstack; /* shadow stack, for string space extension */ 66char *sstack; /* shadow stack, for string space extension */
67static size_t STACKMAX; /* current maximum size of stack */ 67static size_t STACKMAX; /* current maximum size of stack */
68int sp; /* current m4 stack pointer */ 68int sp; /* current m4 stack pointer */
69int fp; /* m4 call frame pointer */ 69int fp; /* m4 call frame pointer */
70struct input_file infile[MAXINP];/* input file stack (0=stdin) */ 70struct input_file infile[MAXINP];/* input file stack (0=stdin) */
71FILE **outfile; /* diversion array(0=bitbucket)*/ 71FILE **outfile; /* diversion array(0=bitbucket)*/
72int maxout; 72int maxout;
73FILE *active; /* active output file pointer */ 73FILE *active; /* active output file pointer */
74int ilevel = 0; /* input file stack pointer */ 74int ilevel = 0; /* input file stack pointer */
75int oindex = 0; /* diversion index.. */ 75int oindex = 0; /* diversion index.. */
76const char *null = ""; /* as it says.. just a null.. */ 76const char *null = ""; /* as it says.. just a null.. */
77char **m4wraps = NULL; /* m4wraps array. */ 77char **m4wraps = NULL; /* m4wraps array. */
78int maxwraps = 0; /* size of m4wraps array */ 78int maxwraps = 0; /* size of m4wraps array */
79int wrapindex = 0; /* current offset in m4wraps */ 79int wrapindex = 0; /* current offset in m4wraps */
80char lquote[MAXCCHARS+1] = {LQUOTE}; /* left quote character (`) */ 80char lquote[MAXCCHARS+1] = {LQUOTE}; /* left quote character (`) */
81char rquote[MAXCCHARS+1] = {RQUOTE}; /* right quote character (') */ 81char rquote[MAXCCHARS+1] = {RQUOTE}; /* right quote character (') */
82char scommt[MAXCCHARS+1] = {SCOMMT}; /* start character for comment */ 82char scommt[MAXCCHARS+1] = {SCOMMT}; /* start character for comment */
83char ecommt[MAXCCHARS+1] = {ECOMMT}; /* end character for comment */ 83char ecommt[MAXCCHARS+1] = {ECOMMT}; /* end character for comment */
84int synch_lines = 0; /* line synchronisation for C preprocessor */ 84int synch_lines = 0; /* line synchronisation for C preprocessor */
85int prefix_builtins = 0; /* -P option to prefix builtin keywords */ 85int prefix_builtins = 0; /* -P option to prefix builtin keywords */
86int fatal_warnings = 0; /* -E option to exit on warnings */ 86int fatal_warnings = 0; /* -E option to exit on warnings */
87int quiet = 0; /* -Q option to silence warnings */ 87int quiet = 0; /* -Q option to silence warnings */
88int nesting_limit = -1; /* -L for nesting limit */ 88int nesting_limit = -1; /* -L for nesting limit */
89const char *freeze = NULL; /* -F to freeze state */ 89const char *freeze = NULL; /* -F to freeze state */
90const char *reload = NULL; /* -R to reload state */ 90const char *reload = NULL; /* -R to reload state */
91#ifndef REAL_FREEZE 91#ifndef REAL_FREEZE
92FILE *freezef = NULL; 92FILE *freezef = NULL;
93int thawing = 0; 93int thawing = 0;
94#endif 94#endif
95 95
96struct keyblk { 96struct keyblk {
97 const char *knam; /* keyword name */ 97 const char *knam; /* keyword name */
98 int ktyp; /* keyword type */ 98 int ktyp; /* keyword type */
99}; 99};
100 100
101struct keyblk keywrds[] = { /* m4 keywords to be installed */ 101struct keyblk keywrds[] = { /* m4 keywords to be installed */
102 { "include", INCLTYPE }, 102 { "include", INCLTYPE },
103 { "sinclude", SINCTYPE }, 103 { "sinclude", SINCTYPE },
104 { "define", DEFITYPE }, 104 { "define", DEFITYPE },
105 { "defn", DEFNTYPE }, 105 { "defn", DEFNTYPE },
106 { "divert", DIVRTYPE | NOARGS }, 106 { "divert", DIVRTYPE | NOARGS },
107 { "expr", EXPRTYPE }, 107 { "expr", EXPRTYPE },
108 { "eval", EXPRTYPE }, 108 { "eval", EXPRTYPE },
109 { "substr", SUBSTYPE }, 109 { "substr", SUBSTYPE },
110 { "ifelse", IFELTYPE }, 110 { "ifelse", IFELTYPE },
111 { "ifdef", IFDFTYPE }, 111 { "ifdef", IFDFTYPE },
112 { "len", LENGTYPE }, 112 { "len", LENGTYPE },
113 { "incr", INCRTYPE }, 113 { "incr", INCRTYPE },
114 { "decr", DECRTYPE }, 114 { "decr", DECRTYPE },
115 { "dnl", DNLNTYPE | NOARGS }, 115 { "dnl", DNLNTYPE | NOARGS },
116 { "changequote", CHNQTYPE | NOARGS }, 116 { "changequote", CHNQTYPE | NOARGS },
117 { "changecom", CHNCTYPE | NOARGS }, 117 { "changecom", CHNCTYPE | NOARGS },
118 { "index", INDXTYPE }, 118 { "index", INDXTYPE },
119#ifdef EXTENDED 119#ifdef EXTENDED
120 { "paste", PASTTYPE }, 120 { "paste", PASTTYPE },
121 { "spaste", SPASTYPE }, 121 { "spaste", SPASTYPE },
122 /* Newer extensions, needed to handle gnu-m4 scripts */ 122 /* Newer extensions, needed to handle gnu-m4 scripts */
123 { "indir", INDIRTYPE}, 123 { "indir", INDIRTYPE},
124 { "builtin", BUILTINTYPE}, 124 { "builtin", BUILTINTYPE},
125 { "patsubst", PATSTYPE}, 125 { "patsubst", PATSTYPE},
126 { "regexp", REGEXPTYPE}, 126 { "regexp", REGEXPTYPE},
127 { "esyscmd", ESYSCMDTYPE}, 127 { "esyscmd", ESYSCMDTYPE},
128 { "__file__", FILENAMETYPE | NOARGS}, 128 { "__file__", FILENAMETYPE | NOARGS},
129 { "__line__", LINETYPE | NOARGS}, 129 { "__line__", LINETYPE | NOARGS},
130#endif 130#endif
131 { "popdef", POPDTYPE }, 131 { "popdef", POPDTYPE },
132 { "pushdef", PUSDTYPE }, 132 { "pushdef", PUSDTYPE },
133 { "dumpdef", DUMPTYPE | NOARGS }, 133 { "dumpdef", DUMPTYPE | NOARGS },
134 { "shift", SHIFTYPE | NOARGS }, 134 { "shift", SHIFTYPE | NOARGS },
135 { "translit", TRNLTYPE }, 135 { "translit", TRNLTYPE },
136 { "undefine", UNDFTYPE }, 136 { "undefine", UNDFTYPE },
137 { "undivert", UNDVTYPE | NOARGS }, 137 { "undivert", UNDVTYPE | NOARGS },
138 { "divnum", DIVNTYPE | NOARGS }, 138 { "divnum", DIVNTYPE | NOARGS },
139 { "maketemp", MKTMTYPE }, 139 { "maketemp", MKTMTYPE },
140 { "errprint", ERRPTYPE | NOARGS }, 140 { "errprint", ERRPTYPE | NOARGS },
141 { "m4wrap", M4WRTYPE | NOARGS }, 141 { "m4wrap", M4WRTYPE | NOARGS },
142 { "m4exit", EXITTYPE | NOARGS }, 142 { "m4exit", EXITTYPE | NOARGS },
143 { "syscmd", SYSCTYPE }, 143 { "syscmd", SYSCTYPE },
144 { "sysval", SYSVTYPE | NOARGS }, 144 { "sysval", SYSVTYPE | NOARGS },
145 { "traceon", TRACEONTYPE | NOARGS }, 145 { "traceon", TRACEONTYPE | NOARGS },
146 { "traceoff", TRACEOFFTYPE | NOARGS }, 146 { "traceoff", TRACEOFFTYPE | NOARGS },
147 147
148#if defined(unix) || defined(__unix__)  148#if defined(unix) || defined(__unix__)
149 { "unix", SELFTYPE | NOARGS }, 149 { "unix", SELFTYPE | NOARGS },
150#else 150#else
151#ifdef vms 151#ifdef vms
152 { "vms", SELFTYPE | NOARGS }, 152 { "vms", SELFTYPE | NOARGS },
153#endif 153#endif
154#endif 154#endif
155}; 155};
156 156
157#define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk)) 157#define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk))
158 158
159#define MAXRECORD 50 159#define MAXRECORD 50
160static struct position { 160static struct position {
161 char *name; 161 char *name;
162 unsigned long line; 162 unsigned long line;
163} quotes[MAXRECORD], paren[MAXRECORD]; 163} quotes[MAXRECORD], paren[MAXRECORD];
164 164
165static void record(struct position *, int); 165static void record(struct position *, int);
166static void dump_stack(struct position *, int); 166static void dump_stack(struct position *, int);
167 167
168static void macro(void); 168static void macro(void);
169static void initkwds(void); 169static void initkwds(void);
170static ndptr inspect(int, char *); 170static ndptr inspect(int, char *);
171static int do_look_ahead(int, const char *); 171static int do_look_ahead(int, const char *);
172static void reallyoutputstr(const char *); 172static void reallyoutputstr(const char *);
173static void reallyputchar(int); 173static void reallyputchar(int);
174 174
175static void enlarge_stack(void); 175static void enlarge_stack(void);
176static void help(void); 176static void help(void);
177 177
178static void 178static void
179usage(FILE *f) 179usage(FILE *f)
180{ 180{
181 fprintf(f, "Usage: %s [-EGgiPQsv] [-Dname[=value]] [-d flags] " 181 fprintf(f, "Usage: %s [-EGgiPQsv] [-Dname[=value]] [-d flags] "
182 "[-I dirname] [-o filename] [-L limit]\n" 182 "[-I dirname] [-o filename] [-L limit]\n"
183 "\t[-t macro] [-Uname] [file ...]\n", getprogname()); 183 "\t[-t macro] [-Uname] [file ...]\n", getprogname());
184} 184}
185 185
186__dead static void 186__dead static void
187onintr(int signo) 187onintr(int signo)
188{ 188{
189 char intrmessage[] = "m4: interrupted.\n"; 189 char intrmessage[] = "m4: interrupted.\n";
190 write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1); 190 write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1);
191 _exit(1); 191 _exit(1);
192} 192}
193 193
194#define OPT_HELP 1 194#define OPT_HELP 1
195 195
196struct option longopts[] = { 196struct option longopts[] = {
197 { "debug", optional_argument, 0, 'd' }, 197 { "debug", optional_argument, 0, 'd' },
198 { "define", required_argument, 0, 'D' }, 198 { "define", required_argument, 0, 'D' },
199 { "error-output", required_argument, 0, 'e' }, 199 { "error-output", required_argument, 0, 'e' },
200 { "fatal-warnings", no_argument, 0, 'E' }, 200 { "fatal-warnings", no_argument, 0, 'E' },
201 { "freeze-state", required_argument, 0, 'F' }, 201 { "freeze-state", required_argument, 0, 'F' },
202 { "gnu", no_argument, 0, 'g' }, 202 { "gnu", no_argument, 0, 'g' },
203 { "help", no_argument, 0, OPT_HELP }, 203 { "help", no_argument, 0, OPT_HELP },
204 { "include", required_argument, 0, 'I' }, 204 { "include", required_argument, 0, 'I' },
205 { "interactive", no_argument, 0, 'i' }, 205 { "interactive", no_argument, 0, 'i' },
206 { "nesting-limit", required_argument, 0, 'L' }, 206 { "nesting-limit", required_argument, 0, 'L' },
207 { "prefix-builtins", no_argument, 0, 'P' }, 207 { "prefix-builtins", no_argument, 0, 'P' },
208 { "quiet", no_argument, 0, 'Q' }, 208 { "quiet", no_argument, 0, 'Q' },
209 { "reload-state", required_argument, 0, 'R' }, 209 { "reload-state", required_argument, 0, 'R' },
210 { "silent", no_argument, 0, 'Q' }, 210 { "silent", no_argument, 0, 'Q' },
211 { "synclines", no_argument, 0, 's' }, 211 { "synclines", no_argument, 0, 's' },
212 { "trace", required_argument, 0, 't' }, 212 { "trace", required_argument, 0, 't' },
213 { "traditional", no_argument, 0, 'G' }, 213 { "traditional", no_argument, 0, 'G' },
214 { "undefine", required_argument, 0, 'U' }, 214 { "undefine", required_argument, 0, 'U' },
215 { "version", no_argument, 0, 'v' }, 215 { "version", no_argument, 0, 'v' },
216#ifdef notyet 216#ifdef notyet
217 { "arglength", required_argument, 0, 'l' }, 217 { "arglength", required_argument, 0, 'l' },
218 { "debugfile", optional_argument, 0, OPT_DEBUGFILE }, 218 { "debugfile", optional_argument, 0, OPT_DEBUGFILE },
219 { "hashsize", required_argument, 0, 'H' }, 219 { "hashsize", required_argument, 0, 'H' },
220 { "warn-macro-sequence",optional_argument, 0, OPT_WARN_SEQUENCE }, 220 { "warn-macro-sequence",optional_argument, 0, OPT_WARN_SEQUENCE },
221#endif 221#endif
222 { 0, 0, 0, 0 }, 222 { 0, 0, 0, 0 },
223}; 223};
224 224
225int 225int
226main(int argc, char *argv[]) 226main(int argc, char *argv[])
227{ 227{
228 int c; 228 int c;
229 int n; 229 int n;
230 char *p; 230 char *p;
231 231
232 setprogname(argv[0]); 232 setprogname(argv[0]);
233 233
234 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 234 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
235 signal(SIGINT, onintr); 235 signal(SIGINT, onintr);
236 236
237 init_macros(); 237 init_macros();
238 initspaces(); 238 initspaces();
239 STACKMAX = INITSTACKMAX; 239 STACKMAX = INITSTACKMAX;
240 240
241 mstack = (stae *)xalloc(sizeof(stae) * STACKMAX, NULL); 241 mstack = (stae *)xalloc(sizeof(stae) * STACKMAX, NULL);
242 sstack = (char *)xalloc(STACKMAX, NULL); 242 sstack = (char *)xalloc(STACKMAX, NULL);
243 243
244 maxout = 0; 244 maxout = 0;
245 outfile = NULL; 245 outfile = NULL;
246 resizedivs(MAXOUT); 246 resizedivs(MAXOUT);
247 247
248 while ((c = getopt_long(argc, argv, "D:d:e:EF:GgI:iL:o:PR:Qst:U:v", 248 while ((c = getopt_long(argc, argv, "D:d:e:EF:GgI:iL:o:PR:Qst:U:v",
249 longopts, NULL)) != -1) 249 longopts, NULL)) != -1)
250 switch(c) { 250 switch(c) {
251 case 'D': /* define something..*/ 251 case 'D': /* define something..*/
252 for (p = optarg; *p; p++) 252 for (p = optarg; *p; p++)
253 if (*p == '=') 253 if (*p == '=')
254 break; 254 break;
255 if (*p) 255 if (*p)
256 *p++ = EOS; 256 *p++ = EOS;
257 dodefine(optarg, p); 257 dodefine(optarg, p);
258 break; 258 break;
259 case 'd': 259 case 'd':
260 set_trace_flags(optarg); 260 set_trace_flags(optarg);
261 break; 261 break;
262 case 'E': 262 case 'E':
263 fatal_warnings++; 263 fatal_warnings++;
264 break; 264 break;
265 case 'e': 265 case 'e':
266 if (freopen(optarg, "w+", stderr) == NULL) 266 if (freopen(optarg, "w+", stderr) == NULL)
267 err(EXIT_FAILURE, "Can't redirect errors to `%s'", 267 err(EXIT_FAILURE, "Can't redirect errors to `%s'",
268 optarg); 268 optarg);
269 break; 269 break;
270 case 'F': 270 case 'F':
271 freeze = optarg; 271 freeze = optarg;
272#ifndef REAL_FREEZE 272#ifndef REAL_FREEZE
273 if ((freezef = fopen(freeze, "w")) == NULL) 273 if ((freezef = fopen(freeze, "w")) == NULL)
274 err(EXIT_FAILURE, "Can't open `%s'", freeze); 274 err(EXIT_FAILURE, "Can't open `%s'", freeze);
275#endif 275#endif
276 break; 276 break;
277 case 'I': 277 case 'I':
278 addtoincludepath(optarg); 278 addtoincludepath(optarg);
279 break; 279 break;
280 case 'i': 280 case 'i':
281 setvbuf(stdout, NULL, _IONBF, 0); 281 setvbuf(stdout, NULL, _IONBF, 0);
282 signal(SIGINT, SIG_IGN); 282 signal(SIGINT, SIG_IGN);
283 break; 283 break;
284 case 'G': 284 case 'G':
285 mimic_gnu = 0; 285 mimic_gnu = 0;
286 break; 286 break;
287 case 'g': 287 case 'g':
288 mimic_gnu = 1; 288 mimic_gnu = 1;
289 break; 289 break;
290 case 'L': 290 case 'L':
291 nesting_limit = atoi(optarg); 291 nesting_limit = atoi(optarg);
292 break; 292 break;
293 case 'o': 293 case 'o':
294 trace_file(optarg); 294 trace_file(optarg);
295 break; 295 break;
296 case 'P': 296 case 'P':
297 prefix_builtins = 1; 297 prefix_builtins = 1;
298 break; 298 break;
299 case 'Q': 299 case 'Q':
300 quiet++; 300 quiet++;
301 break; 301 break;
302 case 'R': 302 case 'R':
303 reload = optarg; 303 reload = optarg;
304 break; 304 break;
305 case 's': 305 case 's':
306 synch_lines = 1; 306 synch_lines = 1;
307 break; 307 break;
308 case 't': 308 case 't':
309 mark_traced(optarg, 1); 309 mark_traced(optarg, 1);
310 break; 310 break;
311 case 'U': /* undefine... */ 311 case 'U': /* undefine... */
312 macro_popdef(optarg); 312 macro_popdef(optarg);
313 break; 313 break;
314 case 'v': 314 case 'v':
315 fprintf(stderr, "%s version %d\n", getprogname(), 315 fprintf(stderr, "%s version %d\n", getprogname(),
316 VERSION); 316 VERSION);
317 return EXIT_SUCCESS; 317 return EXIT_SUCCESS;
318 case OPT_HELP: 318 case OPT_HELP:
319 help(); 319 help();
320 return EXIT_SUCCESS; 320 return EXIT_SUCCESS;
321 case '?': 321 case '?':
322 default: 322 default:
323 usage(stderr); 323 usage(stderr);
324 return EXIT_FAILURE; 324 return EXIT_FAILURE;
325 } 325 }
326 326
327#ifdef REDIRECT 327#ifdef REDIRECT
 328 /*
 329 * This is meant only for debugging; it makes all output
 330 * go to a known file, even if the command line options
 331 * send it elsewhere. It should not be turned of in production code.
 332 */
328 if (freopen("/tmp/m4", "w+", stderr) == NULL) 333 if (freopen("/tmp/m4", "w+", stderr) == NULL)
329 err(EXIT_FAILURE, "Can't redirect errors to `%s'", 334 err(EXIT_FAILURE, "Can't redirect errors to `%s'",
330 "/tmp/m4"); 335 "/tmp/m4");
331#endif 336#endif
332 argc -= optind; 337 argc -= optind;
333 argv += optind; 338 argv += optind;
334 339
335 340
336 initkwds(); 341 initkwds();
337 if (mimic_gnu) 342 if (mimic_gnu)
338 setup_builtin("format", FORMATTYPE); 343 setup_builtin("format", FORMATTYPE);
339 344
340 active = stdout; /* default active output */ 345 active = stdout; /* default active output */
341 bbase[0] = bufbase; 346 bbase[0] = bufbase;
342 347
343 if (reload) { 348 if (reload) {
344#ifdef REAL_FREEZE 349#ifdef REAL_FREEZE
345 thaw_state(reload); 350 thaw_state(reload);
346#else 351#else
347 if (fopen_trypath(infile, reload) == NULL) 352 if (fopen_trypath(infile, reload) == NULL)
348 err(1, "Can't open `%s'", reload); 353 err(1, "Can't open `%s'", reload);
349 sp = -1; 354 sp = -1;
350 fp = 0; 355 fp = 0;
351 thawing = 1; 356 thawing = 1;
352 macro(); 357 macro();
353 thawing = 0; 358 thawing = 0;
354 release_input(infile); 359 release_input(infile);
355#endif 360#endif
356 } 361 }
357 362
358 if (!argc) { 363 if (!argc) {
359 sp = -1; /* stack pointer initialized */ 364 sp = -1; /* stack pointer initialized */
360 fp = 0; /* frame pointer initialized */ 365 fp = 0; /* frame pointer initialized */
361 set_input(infile+0, stdin, "stdin"); 366 set_input(infile+0, stdin, "stdin");
362 /* default input (naturally) */ 367 /* default input (naturally) */
363 macro(); 368 macro();
364 } else 369 } else
365 for (; argc--; ++argv) { 370 for (; argc--; ++argv) {
366 p = *argv; 371 p = *argv;
367 if (p[0] == '-' && p[1] == EOS) 372 if (p[0] == '-' && p[1] == EOS)
368 set_input(infile, stdin, "stdin"); 373 set_input(infile, stdin, "stdin");
369 else if (fopen_trypath(infile, p) == NULL) 374 else if (fopen_trypath(infile, p) == NULL)
370 err(1, "%s", p); 375 err(1, "%s", p);
371 sp = -1; 376 sp = -1;
372 fp = 0;  377 fp = 0;
373 macro(); 378 macro();
374 release_input(infile); 379 release_input(infile);
375 } 380 }
376 381
377 if (wrapindex) { 382 if (wrapindex) {
378 int i; 383 int i;
379 384
380 ilevel = 0; /* in case m4wrap includes.. */ 385 ilevel = 0; /* in case m4wrap includes.. */
381 bufbase = bp = buf; /* use the entire buffer */ 386 bufbase = bp = buf; /* use the entire buffer */
382 if (mimic_gnu) { 387 if (mimic_gnu) {
383 while (wrapindex != 0) { 388 while (wrapindex != 0) {
384 for (i = 0; i < wrapindex; i++) 389 for (i = 0; i < wrapindex; i++)
385 pbstr(m4wraps[i]); 390 pbstr(m4wraps[i]);
386 wrapindex =0; 391 wrapindex =0;
387 macro(); 392 macro();
388 } 393 }
389 } else { 394 } else {
390 for (i = 0; i < wrapindex; i++) { 395 for (i = 0; i < wrapindex; i++) {
391 pbstr(m4wraps[i]); 396 pbstr(m4wraps[i]);
392 macro(); 397 macro();
393 } 398 }
394 } 399 }
395 } 400 }
396 401
397 if (active != stdout) 402 if (active != stdout)
398 active = stdout; /* reset output just in case */ 403 active = stdout; /* reset output just in case */
399 for (n = 1; n < maxout; n++) /* default wrap-up: undivert */ 404 for (n = 1; n < maxout; n++) /* default wrap-up: undivert */
400 if (outfile[n] != NULL) 405 if (outfile[n] != NULL)
401 getdiv(n); 406 getdiv(n);
402 /* remove bitbucket if used */ 407 /* remove bitbucket if used */
403 if (outfile[0] != NULL) { 408 if (outfile[0] != NULL) {
404 (void) fclose(outfile[0]); 409 (void) fclose(outfile[0]);
405 } 410 }
406 411
407#ifdef REAL_FREEZE 412#ifdef REAL_FREEZE
408 if (freeze) 413 if (freeze)
409 freeze_state(freeze); 414 freeze_state(freeze);
410#else 415#else
411 if (freezef) 416 if (freezef)
412 fclose(freezef); 417 fclose(freezef);
413#endif 418#endif
414 419
415 return 0; 420 return 0;
416} 421}
417 422
418/* 423/*
419 * Look ahead for `token'. 424 * Look ahead for `token'.
420 * (on input `t == token[0]') 425 * (on input `t == token[0]')
421 * Used for comment and quoting delimiters. 426 * Used for comment and quoting delimiters.
422 * Returns 1 if `token' present; copied to output. 427 * Returns 1 if `token' present; copied to output.
423 * 0 if `token' not found; all characters pushed back 428 * 0 if `token' not found; all characters pushed back
424 */ 429 */
425static int 430static int
426do_look_ahead(int t, const char *token) 431do_look_ahead(int t, const char *token)
427{ 432{
428 int i; 433 int i;
429 434
430 assert((unsigned char)t == (unsigned char)token[0]); 435 assert((unsigned char)t == (unsigned char)token[0]);
431 436
432 for (i = 1; *++token; i++) { 437 for (i = 1; *++token; i++) {
433 t = gpbc(); 438 t = gpbc();
434 if (t == EOF || (unsigned char)t != (unsigned char)*token) { 439 if (t == EOF || (unsigned char)t != (unsigned char)*token) {
435 pushback(t); 440 pushback(t);
436 while (--i) 441 while (--i)
437 pushback(*--token); 442 pushback(*--token);
438 return 0; 443 return 0;
439 } 444 }
440 } 445 }
441 return 1; 446 return 1;
442} 447}
443 448
444#define LOOK_AHEAD(t, token) (t != EOF && \ 449#define LOOK_AHEAD(t, token) (t != EOF && \
445 (unsigned char)(t)==(unsigned char)(token)[0] && \ 450 (unsigned char)(t)==(unsigned char)(token)[0] && \
446 do_look_ahead(t,token)) 451 do_look_ahead(t,token))
447 452
448/* 453/*
449 * macro - the work horse.. 454 * macro - the work horse..
450 */ 455 */
451static void 456static void
452macro(void) 457macro(void)
453{ 458{
454 char token[MAXTOK+1]; 459 char token[MAXTOK+1];
455 int t, l; 460 int t, l;
456 ndptr p; 461 ndptr p;
457 int nlpar; 462 int nlpar;
458 463
459 cycle { 464 cycle {
460 t = gpbc(); 465 t = gpbc();
461 466
462 if (LOOK_AHEAD(t,lquote)) { /* strip quotes */ 467 if (LOOK_AHEAD(t,lquote)) { /* strip quotes */
463 nlpar = 0; 468 nlpar = 0;
464 record(quotes, nlpar++); 469 record(quotes, nlpar++);
465 /* 470 /*
466 * Opening quote: scan forward until matching 471 * Opening quote: scan forward until matching
467 * closing quote has been found. 472 * closing quote has been found.
468 */ 473 */
469 do { 474 do {
470 475
471 l = gpbc(); 476 l = gpbc();
472 if (LOOK_AHEAD(l,rquote)) { 477 if (LOOK_AHEAD(l,rquote)) {
473 if (--nlpar > 0) 478 if (--nlpar > 0)
474 outputstr(rquote); 479 outputstr(rquote);
475 } else if (LOOK_AHEAD(l,lquote)) { 480 } else if (LOOK_AHEAD(l,lquote)) {
476 record(quotes, nlpar++); 481 record(quotes, nlpar++);
477 outputstr(lquote); 482 outputstr(lquote);
478 } else if (l == EOF) { 483 } else if (l == EOF) {
479 if (!quiet) { 484 if (!quiet) {
480 if (nlpar == 1) 485 if (nlpar == 1)
481 warnx("unclosed quote:"); 486 warnx("unclosed quote:");
482 else 487 else
483 warnx( 488 warnx(
484 "%d unclosed quotes:", 489 "%d unclosed quotes:",
485 nlpar); 490 nlpar);
486 dump_stack(quotes, nlpar); 491 dump_stack(quotes, nlpar);
487 } 492 }
488 exit(EXIT_FAILURE); 493 exit(EXIT_FAILURE);
489 } else { 494 } else {
490 if (nlpar > 0) { 495 if (nlpar > 0) {
491 if (sp < 0) 496 if (sp < 0)
492 reallyputchar(l); 497 reallyputchar(l);
493 else 498 else
494 CHRSAVE(l); 499 CHRSAVE(l);
495 } 500 }
496 } 501 }
497 } 502 }
498 while (nlpar != 0); 503 while (nlpar != 0);
499 } else if (sp < 0 && LOOK_AHEAD(t, scommt)) { 504 } else if (sp < 0 && LOOK_AHEAD(t, scommt)) {
500 reallyoutputstr(scommt); 505 reallyoutputstr(scommt);
501 506
502 for(;;) { 507 for(;;) {
503 t = gpbc(); 508 t = gpbc();
504 if (LOOK_AHEAD(t, ecommt)) { 509 if (LOOK_AHEAD(t, ecommt)) {
505 reallyoutputstr(ecommt); 510 reallyoutputstr(ecommt);
506 break; 511 break;
507 } 512 }
508 if (t == EOF) 513 if (t == EOF)
509 break; 514 break;
510 reallyputchar(t); 515 reallyputchar(t);
511 } 516 }
512 } else if (t == '_' || isalpha(t)) { 517 } else if (t == '_' || isalpha(t)) {
513 p = inspect(t, token); 518 p = inspect(t, token);
514 if (p != NULL) 519 if (p != NULL)
515 pushback(l = gpbc()); 520 pushback(l = gpbc());
516 if (p == NULL || (l != LPAREN &&  521 if (p == NULL || (l != LPAREN &&
517 (macro_getdef(p)->type & NEEDARGS) != 0)) 522 (macro_getdef(p)->type & NEEDARGS) != 0))
518 outputstr(token); 523 outputstr(token);
519 else { 524 else {
520 /* 525 /*
521 * real thing.. First build a call frame: 526 * real thing.. First build a call frame:
522 */ 527 */
523 pushf(fp); /* previous call frm */ 528 pushf(fp); /* previous call frm */
524 pushf(macro_getdef(p)->type); /* type of the call */ 529 pushf(macro_getdef(p)->type); /* type of the call */
525 pushf(is_traced(p)); 530 pushf(is_traced(p));
526 pushf(0); /* parenthesis level */ 531 pushf(0); /* parenthesis level */
527 fp = sp; /* new frame pointer */ 532 fp = sp; /* new frame pointer */
528 /* 533 /*
529 * now push the string arguments: 534 * now push the string arguments:
530 */ 535 */
531 pushs1(macro_getdef(p)->defn); /* defn string */ 536 pushs1(macro_getdef(p)->defn); /* defn string */
532 pushs1((char *)macro_name(p)); /* macro name */ 537 pushs1((char *)macro_name(p)); /* macro name */
533 pushs(ep); /* start next..*/ 538 pushs(ep); /* start next..*/
534 539
535 if (l != LPAREN && PARLEV == 0) {  540 if (l != LPAREN && PARLEV == 0) {
536 /* no bracks */ 541 /* no bracks */
537 chrsave(EOS); 542 chrsave(EOS);
538 543
539 if ((size_t)sp == STACKMAX) 544 if ((size_t)sp == STACKMAX)
540 errx(1, "internal stack overflow"); 545 errx(1, "internal stack overflow");
541 eval((const char **) mstack+fp+1, 2,  546 eval((const char **) mstack+fp+1, 2,
542 CALTYP, TRACESTATUS); 547 CALTYP, TRACESTATUS);
543 548
544 ep = PREVEP; /* flush strspace */ 549 ep = PREVEP; /* flush strspace */
545 sp = PREVSP; /* previous sp.. */ 550 sp = PREVSP; /* previous sp.. */
546 fp = PREVFP; /* rewind stack...*/ 551 fp = PREVFP; /* rewind stack...*/
547 } 552 }
548 } 553 }
549 } else if (t == EOF) { 554 } else if (t == EOF) {
550 if (sp > -1 && ilevel <= 0) { 555 if (sp > -1 && ilevel <= 0) {
551 if (!quiet) { 556 if (!quiet) {
552 warnx("unexpected end of input, " 557 warnx("unexpected end of input, "
553 "unclosed parenthesis:"); 558 "unclosed parenthesis:");
554 dump_stack(paren, PARLEV); 559 dump_stack(paren, PARLEV);
555 } 560 }
556 exit(EXIT_FAILURE); 561 exit(EXIT_FAILURE);
557 } 562 }
558 if (ilevel <= 0) 563 if (ilevel <= 0)
559 break; /* all done thanks.. */ 564 break; /* all done thanks.. */
560 release_input(infile+ilevel--); 565 release_input(infile+ilevel--);
561 emit_synchline(); 566 emit_synchline();
562 bufbase = bbase[ilevel]; 567 bufbase = bbase[ilevel];
563 continue; 568 continue;
564 } else if (sp < 0) { /* not in a macro at all */ 569 } else if (sp < 0) { /* not in a macro at all */
565 reallyputchar(t); /* output directly.. */ 570 reallyputchar(t); /* output directly.. */
566 } 571 }
567 572
568 else switch(t) { 573 else switch(t) {
569 574
570 case LPAREN: 575 case LPAREN:
571 if (PARLEV > 0) 576 if (PARLEV > 0)
572 chrsave(t); 577 chrsave(t);
573 while (isspace(l = gpbc())) /* skip blank, tab, nl.. */ 578 while (isspace(l = gpbc())) /* skip blank, tab, nl.. */
574 if (PARLEV > 0) 579 if (PARLEV > 0)
575 chrsave(l); 580 chrsave(l);
576 pushback(l); 581 pushback(l);
577 record(paren, PARLEV++); 582 record(paren, PARLEV++);
578 break; 583 break;
579 584
580 case RPAREN: 585 case RPAREN:
581 if (--PARLEV > 0) 586 if (--PARLEV > 0)
582 chrsave(t); 587 chrsave(t);
583 else { /* end of argument list */ 588 else { /* end of argument list */
584 chrsave(EOS); 589 chrsave(EOS);
585 590
586 if ((size_t)sp == STACKMAX) 591 if ((size_t)sp == STACKMAX)
587 errx(1, "internal stack overflow"); 592 errx(1, "internal stack overflow");
588 593
589 eval((const char **) mstack+fp+1, sp-fp,  594 eval((const char **) mstack+fp+1, sp-fp,
590 CALTYP, TRACESTATUS); 595 CALTYP, TRACESTATUS);
591 596
592 ep = PREVEP; /* flush strspace */ 597 ep = PREVEP; /* flush strspace */
593 sp = PREVSP; /* previous sp.. */ 598 sp = PREVSP; /* previous sp.. */
594 fp = PREVFP; /* rewind stack...*/ 599 fp = PREVFP; /* rewind stack...*/
595 } 600 }
596 break; 601 break;
597 602
598 case COMMA: 603 case COMMA:
599 if (PARLEV == 1) { 604 if (PARLEV == 1) {
600 chrsave(EOS); /* new argument */ 605 chrsave(EOS); /* new argument */
601 while (isspace(l = gpbc())) 606 while (isspace(l = gpbc()))
602 ; 607 ;
603 pushback(l); 608 pushback(l);
604 pushs(ep); 609 pushs(ep);
605 } else 610 } else
606 chrsave(t); 611 chrsave(t);
607 break; 612 break;
608 613
609 default: 614 default:
610 if (LOOK_AHEAD(t, scommt)) { 615 if (LOOK_AHEAD(t, scommt)) {
611 char *q; 616 char *q;
612 for (q = scommt; *q; q++) 617 for (q = scommt; *q; q++)
613 chrsave(*q); 618 chrsave(*q);
614 for(;;) { 619 for(;;) {
615 t = gpbc(); 620 t = gpbc();
616 if (LOOK_AHEAD(t, ecommt)) { 621 if (LOOK_AHEAD(t, ecommt)) {
617 for (q = ecommt; *q; q++) 622 for (q = ecommt; *q; q++)
618 chrsave(*q); 623 chrsave(*q);
619 break; 624 break;
620 } 625 }
621 if (t == EOF) 626 if (t == EOF)
622 break; 627 break;
623 CHRSAVE(t); 628 CHRSAVE(t);
624 } 629 }
625 } else 630 } else
626 CHRSAVE(t); /* stack the char */ 631 CHRSAVE(t); /* stack the char */
627 break; 632 break;
628 } 633 }
629 } 634 }
630} 635}
631 636
632/*  637/*
633 * output string directly, without pushing it for reparses.  638 * output string directly, without pushing it for reparses.
634 */ 639 */
635void 640void
636outputstr(const char *s) 641outputstr(const char *s)
637{ 642{
638 if (sp < 0) 643 if (sp < 0)
639 reallyoutputstr(s); 644 reallyoutputstr(s);
640 else 645 else
641 while (*s) 646 while (*s)
642 CHRSAVE(*s++); 647 CHRSAVE(*s++);
643} 648}
644 649
645void 650void
646reallyoutputstr(const char *s) 651reallyoutputstr(const char *s)
647{ 652{
648 if (synch_lines) { 653 if (synch_lines) {
649 while (*s) { 654 while (*s) {
650 fputc(*s, active); 655 fputc(*s, active);
651 if (*s++ == '\n') { 656 if (*s++ == '\n') {
652 infile[ilevel].synch_lineno++; 657 infile[ilevel].synch_lineno++;
653 if (infile[ilevel].synch_lineno !=  658 if (infile[ilevel].synch_lineno !=
654 infile[ilevel].lineno) 659 infile[ilevel].lineno)
655 do_emit_synchline(); 660 do_emit_synchline();
656 } 661 }
657 } 662 }
658 } else 663 } else
659 fputs(s, active); 664 fputs(s, active);
660} 665}
661 666
662void 667void
663reallyputchar(int c) 668reallyputchar(int c)
664{ 669{
665 putc(c, active); 670 putc(c, active);
666 if (synch_lines && c == '\n') { 671 if (synch_lines && c == '\n') {
667 infile[ilevel].synch_lineno++; 672 infile[ilevel].synch_lineno++;
668 if (infile[ilevel].synch_lineno != infile[ilevel].lineno) 673 if (infile[ilevel].synch_lineno != infile[ilevel].lineno)
669 do_emit_synchline(); 674 do_emit_synchline();
670 } 675 }
671} 676}
672 677
673/* 678/*
674 * build an input token.. 679 * build an input token..
675 * consider only those starting with _ or A-Za-z.  680 * consider only those starting with _ or A-Za-z.
676 */ 681 */
677static ndptr 682static ndptr
678inspect(int c, char *tp)  683inspect(int c, char *tp)
679{ 684{
680 char *name = tp; 685 char *name = tp;
681 char *etp = tp+MAXTOK; 686 char *etp = tp+MAXTOK;
682 ndptr p; 687 ndptr p;
683  688
684 *tp++ = c; 689 *tp++ = c;
685 690
686 while ((isalnum(c = gpbc()) || c == '_') && tp < etp) 691 while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
687 *tp++ = c; 692 *tp++ = c;
688 if (c != EOF) 693 if (c != EOF)
689 PUSHBACK(c); 694 PUSHBACK(c);
690 *tp = EOS; 695 *tp = EOS;
691 /* token is too long, it won't match anything, but it can still 696 /* token is too long, it won't match anything, but it can still
692 * be output. */ 697 * be output. */
693 if (tp == ep) { 698 if (tp == ep) {
694 outputstr(name); 699 outputstr(name);
695 while (isalnum(c = gpbc()) || c == '_') { 700 while (isalnum(c = gpbc()) || c == '_') {
696 if (sp < 0) 701 if (sp < 0)
697 reallyputchar(c); 702 reallyputchar(c);
698 else 703 else
699 CHRSAVE(c); 704 CHRSAVE(c);
700 } 705 }
701 *name = EOS; 706 *name = EOS;
702 return NULL; 707 return NULL;
703 } 708 }
704 709
705 p = ohash_find(&macros, ohash_qlookupi(&macros, name, (void *)&tp)); 710 p = ohash_find(&macros, ohash_qlookupi(&macros, name, (void *)&tp));
706 if (p == NULL) 711 if (p == NULL)
707 return NULL; 712 return NULL;
708 if (macro_getdef(p) == NULL) 713 if (macro_getdef(p) == NULL)
709 return NULL; 714 return NULL;
710 return p; 715 return p;
711} 716}
712 717
713/* 718/*
714 * initkwds - initialise m4 keywords as fast as possible.  719 * initkwds - initialise m4 keywords as fast as possible.
715 * This very similar to install, but without certain overheads, 720 * This very similar to install, but without certain overheads,
716 * such as calling lookup. Malloc is not used for storing the  721 * such as calling lookup. Malloc is not used for storing the
717 * keyword strings, since we simply use the static pointers 722 * keyword strings, since we simply use the static pointers
718 * within keywrds block. 723 * within keywrds block.
719 */ 724 */
720static void 725static void
721initkwds(void) 726initkwds(void)
722{ 727{
723 unsigned int type; 728 unsigned int type;
724 size_t i; 729 size_t i;
725 730
726 for (i = 0; i < MAXKEYS; i++) { 731 for (i = 0; i < MAXKEYS; i++) {
727 type = keywrds[i].ktyp; 732 type = keywrds[i].ktyp;
728 if ((keywrds[i].ktyp & NOARGS) == 0) 733 if ((keywrds[i].ktyp & NOARGS) == 0)
729 type |= NEEDARGS; 734 type |= NEEDARGS;
730 setup_builtin(keywrds[i].knam, type); 735 setup_builtin(keywrds[i].knam, type);
731 } 736 }
732} 737}
733 738
734static void 739static void
735record(struct position *t, int lev) 740record(struct position *t, int lev)
736{ 741{
737 if (lev < MAXRECORD) { 742 if (lev < MAXRECORD) {
738 t[lev].name = CURRENT_NAME; 743 t[lev].name = CURRENT_NAME;
739 t[lev].line = CURRENT_LINE; 744 t[lev].line = CURRENT_LINE;
740 } 745 }
741} 746}
742 747
743static void 748static void
744dump_stack(struct position *t, int lev) 749dump_stack(struct position *t, int lev)
745{ 750{
746 int i; 751 int i;
747 752
748 for (i = 0; i < lev; i++) { 753 for (i = 0; i < lev; i++) {
749 if (i == MAXRECORD) { 754 if (i == MAXRECORD) {
750 fprintf(stderr, " ...\n"); 755 fprintf(stderr, " ...\n");
751 break; 756 break;
752 } 757 }
753 fprintf(stderr, " %s at line %lu\n",  758 fprintf(stderr, " %s at line %lu\n",
754 t[i].name, t[i].line); 759 t[i].name, t[i].line);
755 } 760 }
756} 761}
757 762
758 763
759static void  764static void
760enlarge_stack(void) 765enlarge_stack(void)
761{ 766{
762 STACKMAX += STACKMAX/2; 767 STACKMAX += STACKMAX/2;
763 mstack = xrealloc(mstack, sizeof(stae) * STACKMAX,  768 mstack = xrealloc(mstack, sizeof(stae) * STACKMAX,
764 "Evaluation stack overflow (%lu)",  769 "Evaluation stack overflow (%lu)",
765 (unsigned long)STACKMAX); 770 (unsigned long)STACKMAX);
766 sstack = xrealloc(sstack, STACKMAX, 771 sstack = xrealloc(sstack, STACKMAX,
767 "Evaluation stack overflow (%lu)",  772 "Evaluation stack overflow (%lu)",
768 (unsigned long)STACKMAX); 773 (unsigned long)STACKMAX);
769} 774}
770 775
771static const struct { 776static const struct {
772 const char *n; 777 const char *n;
773 const char *d; 778 const char *d;
774} nd [] = { 779} nd [] = {
775{ "-d, --debug[=flags]", "set debug flags" }, 780{ "-d, --debug[=flags]", "set debug flags" },
776{ "-D, --define=name[=value]", "define macro" }, 781{ "-D, --define=name[=value]", "define macro" },
777{ "-e, --error-output=file", "send error output to file" }, 782{ "-e, --error-output=file", "send error output to file" },
778{ "-E, --fatal-warnings", "exit on warnings" }, 783{ "-E, --fatal-warnings", "exit on warnings" },
779{ "-F, --freeze-state=file", "save state to file" }, 784{ "-F, --freeze-state=file", "save state to file" },
780{ "-g, --gnu", "enable gnu extensions" }, 785{ "-g, --gnu", "enable gnu extensions" },
781{ " --help", "print this message and exit" }, 786{ " --help", "print this message and exit" },
782{ "-I, --include=file", "include file" }, 787{ "-I, --include=file", "include file" },
783{ "-i, --interactive", "unbuffer output, ignore tty signals" }, 788{ "-i, --interactive", "unbuffer output, ignore tty signals" },
784{ "-L, --nesting-limit=num", "macro expansion nesting limit (unimpl)" }, 789{ "-L, --nesting-limit=num", "macro expansion nesting limit (unimpl)" },
785{ "-P, --prefix-builtins", "prefix builtins with m4_" }, 790{ "-P, --prefix-builtins", "prefix builtins with m4_" },
786{ "-Q, --quiet", "don't print warnings" }, 791{ "-Q, --quiet", "don't print warnings" },
787{ "-R, --reload-state=file", "restore state from file" }, 792{ "-R, --reload-state=file", "restore state from file" },
788{ "-Q, --silent", "don't print warnings" }, 793{ "-Q, --silent", "don't print warnings" },
789{ "-s, --synclines", "output line directives for cpp(1)" }, 794{ "-s, --synclines", "output line directives for cpp(1)" },
790{ "-t, --trace=macro", "trace the named macro" }, 795{ "-t, --trace=macro", "trace the named macro" },
791{ "-G, --traditional", "disable gnu extensions" }, 796{ "-G, --traditional", "disable gnu extensions" },
792{ "-U, --undefine=name", "undefine the named macro" }, 797{ "-U, --undefine=name", "undefine the named macro" },
793{ "-v, --version", "print the version number and exit" }, 798{ "-v, --version", "print the version number and exit" },
794}; 799};
795 800
796static void 801static void
797help(void) 802help(void)
798{ 803{
799 size_t i; 804 size_t i;
800 fprintf(stdout, "%s version %d\n\n", getprogname(), VERSION); 805 fprintf(stdout, "%s version %d\n\n", getprogname(), VERSION);
801 usage(stdout); 806 usage(stdout);
802 807
803 fprintf(stdout, "\nThe long options are:\n"); 808 fprintf(stdout, "\nThe long options are:\n");
804 for (i = 0; i < __arraycount(nd); i++) 809 for (i = 0; i < __arraycount(nd); i++)
805 fprintf(stdout, "\t%-25.25s\t%s\n", nd[i].n, nd[i].d); 810 fprintf(stdout, "\t%-25.25s\t%s\n", nd[i].n, nd[i].d);
806} 811}