1 /* A lexical scanner generated by flex*/
2 
3 /* Scanner skeleton version:
4  * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
5  */
6 
7 #define FLEX_SCANNER
8 #define YY_FLEX_MAJOR_VERSION 2
9 #define YY_FLEX_MINOR_VERSION 5
10 
11 #include <stdio.h>
12 
13 /* for isatty() */
14 #if defined(_WIN32) || defined(_WIN64)
15 #include <io.h>
16 #else
17 #include <unistd.h>
18 #endif
19 
20 /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
21 #ifdef c_plusplus
22 #ifndef __cplusplus
23 #define __cplusplus
24 #endif
25 #endif
26 
27 
28 #ifdef __cplusplus
29 
30 #include <stdlib.h>
31 
32 /* Use prototypes in function declarations. */
33 #define YY_USE_PROTOS
34 
35 /* The "const" storage-class-modifier is valid. */
36 #define YY_USE_CONST
37 
38 #else	/* ! __cplusplus */
39 
40 #if __STDC__
41 
42 #define YY_USE_PROTOS
43 #define YY_USE_CONST
44 
45 #endif	/* __STDC__ */
46 #endif	/* ! __cplusplus */
47 
48 #ifdef __TURBOC__
49  #pragma warn -rch
50  #pragma warn -use
51 #include <io.h>
52 #include <stdlib.h>
53 #define YY_USE_CONST
54 #define YY_USE_PROTOS
55 #endif
56 
57 #ifdef YY_USE_CONST
58 #define yyconst const
59 #else
60 #define yyconst
61 #endif
62 
63 
64 #ifdef YY_USE_PROTOS
65 #define YY_PROTO(proto) proto
66 #else
67 #define YY_PROTO(proto) ()
68 #endif
69 
70 /* Returned upon end-of-file. */
71 #define YY_NULL 0
72 
73 /* Promotes a possibly negative, possibly signed char to an unsigned
74  * integer for use as an array index.  If the signed char is negative,
75  * we want to instead treat it as an 8-bit unsigned char, hence the
76  * double cast.
77  */
78 #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
79 
80 /* Enter a start condition.  This macro really ought to take a parameter,
81  * but we do it the disgusting crufty way forced on us by the ()-less
82  * definition of BEGIN.
83  */
84 #define BEGIN yy_start = 1 + 2 *
85 
86 /* Translate the current start state into a value that can be later handed
87  * to BEGIN to return to the state.  The YYSTATE alias is for lex
88  * compatibility.
89  */
90 #define YY_START ((yy_start - 1) / 2)
91 #define YYSTATE YY_START
92 
93 /* Action number for EOF rule of a given start state. */
94 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
95 
96 /* Special action meaning "start processing a new file". */
97 #define YY_NEW_FILE yyrestart( yyin )
98 
99 #define YY_END_OF_BUFFER_CHAR 0
100 
101 /* Size of default input buffer. */
102 #define YY_BUF_SIZE 16384
103 
104 typedef struct yy_buffer_state *YY_BUFFER_STATE;
105 
106 extern int yyleng;
107 extern FILE *yyin, *yyout;
108 
109 #define EOB_ACT_CONTINUE_SCAN 0
110 #define EOB_ACT_END_OF_FILE 1
111 #define EOB_ACT_LAST_MATCH 2
112 
113 /* The funky do-while in the following #define is used to turn the definition
114  * int a single C statement (which needs a semi-colon terminator).  This
115  * avoids problems with code like:
116  *
117  * 	if ( condition_holds )
118  *		yyless( 5 );
119  *	else
120  *		do_something_else();
121  *
122  * Prior to using the do-while the compiler would get upset at the
123  * "else" because it interpreted the "if" statement as being all
124  * done when it reached the ';' after the yyless() call.
125  */
126 
127 /* Return all but the first 'n' matched characters back to the input stream. */
128 
129 #define yyless(n) \
130 	do \
131 		{ \
132 		/* Undo effects of setting up yytext. */ \
133 		*yy_cp = yy_hold_char; \
134 		YY_RESTORE_YY_MORE_OFFSET \
135 		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
136 		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
137 		} \
138 	while ( 0 )
139 
140 #define unput(c) yyunput( c, yytext_ptr )
141 
142 /* Some routines like yy_flex_realloc() are emitted as static but are
143    not called by all lexers. This generates warnings in some compilers,
144    notably GCC. Arrange to suppress these. */
145 #ifdef __GNUC__
146 #define YY_MAY_BE_UNUSED __attribute__((unused))
147 #else
148 #define YY_MAY_BE_UNUSED
149 #endif
150 
151 /* The following is because we cannot portably get our hands on size_t
152  * (without autoconf's help, which isn't available because we want
153  * flex-generated scanners to compile on their own).
154  */
155 typedef unsigned int yy_size_t;
156 
157 
158 struct yy_buffer_state
159 	{
160 	FILE *yy_input_file;
161 
162 	char *yy_ch_buf;		/* input buffer */
163 	char *yy_buf_pos;		/* current position in input buffer */
164 
165 	/* Size of input buffer in bytes, not including room for EOB
166 	 * characters.
167 	 */
168 	yy_size_t yy_buf_size;
169 
170 	/* Number of characters read into yy_ch_buf, not including EOB
171 	 * characters.
172 	 */
173 	int yy_n_chars;
174 
175 	/* Whether we "own" the buffer - i.e., we know we created it,
176 	 * and can realloc() it to grow it, and should free() it to
177 	 * delete it.
178 	 */
179 	int yy_is_our_buffer;
180 
181 	/* Whether this is an "interactive" input source; if so, and
182 	 * if we're using stdio for input, then we want to use getc()
183 	 * instead of fread(), to make sure we stop fetching input after
184 	 * each newline.
185 	 */
186 	int yy_is_interactive;
187 
188 	/* Whether we're considered to be at the beginning of a line.
189 	 * If so, '^' rules will be active on the next match, otherwise
190 	 * not.
191 	 */
192 	int yy_at_bol;
193 
194 	/* Whether to try to fill the input buffer when we reach the
195 	 * end of it.
196 	 */
197 	int yy_fill_buffer;
198 
199 	int yy_buffer_status;
200 #define YY_BUFFER_NEW 0
201 #define YY_BUFFER_NORMAL 1
202 	/* When an EOF's been seen but there's still some text to process
203 	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
204 	 * shouldn't try reading from the input source any more.  We might
205 	 * still have a bunch of tokens to match, though, because of
206 	 * possible backing-up.
207 	 *
208 	 * When we actually see the EOF, we change the status to "new"
209 	 * (via yyrestart()), so that the user can continue scanning by
210 	 * just pointing yyin at a new input file.
211 	 */
212 #define YY_BUFFER_EOF_PENDING 2
213 	};
214 
215 static YY_BUFFER_STATE yy_current_buffer = 0;
216 
217 /* We provide macros for accessing buffer states in case in the
218  * future we want to put the buffer states in a more general
219  * "scanner state".
220  */
221 #define YY_CURRENT_BUFFER yy_current_buffer
222 
223 
224 /* yy_hold_char holds the character lost when yytext is formed. */
225 static char yy_hold_char;
226 
227 static int yy_n_chars;		/* number of characters read into yy_ch_buf */
228 
229 
230 int yyleng;
231 
232 /* Points to current character in buffer. */
233 static char *yy_c_buf_p = (char *) 0;
234 static int yy_init = 1;		/* whether we need to initialize */
235 static int yy_start = 0;	/* start state number */
236 
237 /* Flag which is used to allow yywrap()'s to do buffer switches
238  * instead of setting up a fresh yyin.  A bit of a hack ...
239  */
240 static int yy_did_buffer_switch_on_eof;
241 
242 void yyrestart YY_PROTO(( FILE *input_file ));
243 
244 void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
245 void yy_load_buffer_state YY_PROTO(( void ));
246 YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
247 void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
248 void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
249 void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
250 #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
251 
252 YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
253 YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
254 YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
255 
256 static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
257 static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )) YY_MAY_BE_UNUSED;
258 static void yy_flex_free YY_PROTO(( void * ));
259 
260 #define yy_new_buffer yy_create_buffer
261 
262 #define yy_set_interactive(is_interactive) \
263 	{ \
264 	if ( ! yy_current_buffer ) \
265 		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
266 	yy_current_buffer->yy_is_interactive = is_interactive; \
267 	}
268 
269 #define yy_set_bol(at_bol) \
270 	{ \
271 	if ( ! yy_current_buffer ) \
272 		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
273 	yy_current_buffer->yy_at_bol = at_bol; \
274 	}
275 
276 #define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
277 
278 typedef unsigned char YY_CHAR;
279 FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
280 typedef int yy_state_type;
281 extern char *yytext;
282 #define yytext_ptr yytext
283 
284 static yy_state_type yy_get_previous_state YY_PROTO(( void ));
285 static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
286 static int yy_get_next_buffer YY_PROTO(( void ));
287 static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
288 
289 /* Done after the current pattern has been matched and before the
290  * corresponding action - sets up yytext.
291  */
292 #define YY_DO_BEFORE_ACTION \
293 	yytext_ptr = yy_bp; \
294 	yyleng = (int) (yy_cp - yy_bp); \
295 	yy_hold_char = *yy_cp; \
296 	*yy_cp = '\0'; \
297 	yy_c_buf_p = yy_cp;
298 
299 #define YY_NUM_RULES 43
300 #define YY_END_OF_BUFFER 44
301 static yyconst short int yy_accept[128] =
302     {   0,
303         0,    0,    0,    0,    0,    0,   44,   42,    2,    1,
304        42,   34,   35,   42,   42,   16,   27,   25,   42,   42,
305        42,   42,   42,   42,   42,   42,   42,   36,   37,   15,
306        31,   33,   32,   34,   35,   38,   39,   30,   42,   42,
307        29,   28,    2,    0,   40,   41,   23,   26,   24,    0,
308         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
309        15,   38,    0,   29,   29,   29,    0,   28,    0,    0,
310         0,    0,    0,    0,   22,    0,    0,    0,   18,   29,
311         0,   29,    0,   17,    0,    0,    0,    0,   21,    0,
312        11,    0,    0,    0,   19,    0,    0,    0,    0,    0,
313 
314         0,   20,    0,    0,    0,    0,   13,    3,    4,    6,
315        10,    0,    0,    3,    0,    0,    7,   12,    0,    0,
316         8,    9,    0,    0,   14,    5,    0
317     } ;
318 
319 static yyconst int yy_ec[256] =
320     {   0,
321         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
322         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
323         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
324         1,    2,    1,    4,    5,    1,    1,    1,    1,    6,
325         7,    8,    9,   10,    9,   11,   12,   13,   14,   15,
326        16,   16,   16,   16,   16,   16,   16,   17,   18,   19,
327        20,   21,    1,    1,   22,   23,   24,   25,   26,   27,
328        28,   27,   29,   27,   30,   31,   32,   33,   34,   35,
329        27,   36,   37,   38,   39,   27,   40,   27,   41,   27,
330        42,    1,   43,    1,   44,    1,   45,   45,   45,   45,
331 
332        46,   45,   45,   45,   45,   45,   45,   45,   45,   45,
333        45,   45,   45,   45,   45,   45,   45,   45,   45,   45,
334        45,   45,   47,   48,   49,    1,    1,    1,    1,    1,
335         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
336         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
337         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
338         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
339         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
340         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
341         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
342 
343         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
344         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
345         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
346         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
347         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
348         1,    1,    1,    1,    1
349     } ;
350 
351 static yyconst int yy_meta[50] =
352     {   0,
353         1,    2,    1,    1,    1,    2,    2,    2,    2,    2,
354         2,    2,    3,    3,    3,    3,    2,    1,    2,    1,
355         2,    3,    3,    3,    3,    3,    3,    3,    3,    3,
356         3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
357         3,    2,    2,    3,    3,    3,    1,    1,    1
358     } ;
359 
360 static yyconst short int yy_base[131] =
361     {   0,
362         0,    0,   49,    0,   98,    0,  315,  316,  312,  316,
363       310,  316,  316,  304,  291,  316,  290,  289,  277,  122,
364       271,  273,  279,  123,  278,  265,  280,  316,  316,  140,
365       316,  316,  316,    0,    0,    0,  316,  316,  146,  151,
366       157,    0,  299,  297,  316,  316,  316,  316,  316,  270,
367       261,  264,  262,  257,  253,  260,  269,  269,  254,  261,
368       161,    0,  165,  176,  182,  197,  205,    0,  266,  263,
369       255,  246,  258,  243,  260,  240,  241,  239,  316,  211,
370       216,  220,  230,  316,  237,  230,  236,  229,  316,  240,
371       230,  227,  257,  235,  316,  230,  219,  222,  224,  224,
372 
373       148,  316,  215,  225,  223,  211,  211,  225,  186,  186,
374       316,  178,  186,  231,  180,  190,  186,  316,  151,  145,
375       316,  316,  131,  120,  316,  316,  316,  277,  279,  148
376     } ;
377 
378 static yyconst short int yy_def[131] =
379     {   0,
380       127,    1,  127,    3,  127,    5,  127,  127,  127,  127,
381       128,  127,  127,  127,  127,  127,  127,  127,  127,  127,
382       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
383       127,  127,  127,  129,  129,  129,  127,  127,  127,  127,
384       127,  130,  127,  128,  127,  127,  127,  127,  127,  127,
385       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
386       127,  129,  127,  127,  127,  127,  127,  130,  127,  127,
387       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
388       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
389       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
390 
391       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
392       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
393       127,  127,  127,  127,  127,  127,    0,  127,  127,  127
394     } ;
395 
396 static yyconst short int yy_nxt[366] =
397     {   0,
398         8,    9,   10,    8,   11,   12,   13,    8,    8,    8,
399         8,   14,    8,    8,    8,    8,   15,   16,   17,    8,
400        18,   19,    8,    8,   20,    8,    8,   21,   22,   23,
401        24,    8,    8,    8,    8,   25,   26,   27,    8,    8,
402         8,   28,   29,    8,   30,   30,   31,   32,   33,    8,
403         9,   10,    8,   11,   34,   35,    8,    8,    8,    8,
404        14,   36,   36,   36,   36,    8,   37,    8,    8,    8,
405        36,   36,   36,   36,   36,   36,   36,   36,   36,   36,
406        36,   36,   36,   36,   36,   36,   36,   36,   36,   36,
407        28,   29,   36,   36,   36,   31,   32,   33,    8,    9,
408 
409        10,   38,   11,   12,   13,    8,   39,    8,   40,   14,
410        41,   41,   41,   41,    8,    8,    8,    8,    8,   42,
411        42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
412        42,   42,   42,   42,   42,   42,   42,   42,   42,   28,
413        29,    8,   42,   42,   31,   32,   33,   51,   56,  101,
414        68,   57,   61,   61,   61,   61,   63,  126,   64,   64,
415        64,   64,   52,   65,   65,   65,   65,   66,  125,   64,
416        64,   64,   64,   61,   61,   61,   61,   65,   65,   65,
417        65,  124,   67,   61,   61,   61,   66,  123,   64,   64,
418        64,   64,  108,  108,   65,   65,   65,   65,  116,  117,
419 
420       122,   67,   67,  121,   61,   61,   61,   67,  120,   80,
421        80,   80,   80,   81,  119,  118,  115,   82,   82,   82,
422        82,   67,   67,   80,   80,   80,   80,   67,   82,   82,
423        82,   82,   82,   82,   82,   82,   67,  114,  114,  114,
424       114,  113,   67,  114,  114,  114,  114,  112,  111,  110,
425       109,  107,  106,  105,  104,  103,   67,  102,  101,  100,
426        99,   98,   97,   96,   95,   94,   93,   92,  114,  114,
427       114,   91,   90,   89,  114,  114,  114,   44,   44,   44,
428        62,   62,   88,   87,   86,   85,   84,   83,   79,   78,
429        77,   76,   75,   74,   73,   72,   71,   70,   69,   45,
430 
431        43,   60,   59,   58,   55,   54,   53,   50,   49,   48,
432        47,   46,   45,   43,  127,    7,  127,  127,  127,  127,
433       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
434       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
435       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
436       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
437       127,  127,  127,  127,  127
438     } ;
439 
440 static yyconst short int yy_chk[366] =
441     {   0,
442         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
443         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
444         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
445         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
446         1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
447         3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
448         3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
449         3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
450         3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
451         3,    3,    3,    3,    3,    3,    3,    3,    5,    5,
452 
453         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
454         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
455         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
456         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
457         5,    5,    5,    5,    5,    5,    5,   20,   24,  101,
458       130,   24,   30,   30,   30,   30,   39,  124,   39,   39,
459        39,   39,   20,   40,   40,   40,   40,   41,  123,   41,
460        41,   41,   41,   61,   61,   61,   61,   63,   63,   63,
461        63,  120,   41,   30,   30,   30,   64,  119,   64,   64,
462        64,   64,  101,  101,   65,   65,   65,   65,  110,  110,
463 
464       117,   64,   41,  116,   61,   61,   61,   65,  115,   66,
465        66,   66,   66,   67,  113,  112,  109,   67,   67,   67,
466        67,   64,   66,   80,   80,   80,   80,   65,   81,   81,
467        81,   81,   82,   82,   82,   82,   80,  108,  108,  108,
468       108,  107,   66,  114,  114,  114,  114,  106,  105,  104,
469       103,  100,   99,   98,   97,   96,   80,   94,   93,   92,
470        91,   90,   88,   87,   86,   85,   83,   78,  108,  108,
471       108,   77,   76,   75,  114,  114,  114,  128,  128,  128,
472       129,  129,   74,   73,   72,   71,   70,   69,   60,   59,
473        58,   57,   56,   55,   54,   53,   52,   51,   50,   44,
474 
475        43,   27,   26,   25,   23,   22,   21,   19,   18,   17,
476        15,   14,   11,    9,    7,  127,  127,  127,  127,  127,
477       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
478       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
479       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
480       127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
481       127,  127,  127,  127,  127
482     } ;
483 
484 static yy_state_type yy_last_accepting_state;
485 static char *yy_last_accepting_cpos;
486 
487 /* The intent behind this definition is that it'll catch
488  * any uses of REJECT which flex missed.
489  */
490 #define REJECT reject_used_but_not_detected
491 #define yymore() yymore_used_but_not_detected
492 #define YY_MORE_ADJ 0
493 #define YY_RESTORE_YY_MORE_OFFSET
494 char *yytext;
495 /* #line 1 "nidrgen.l" */
496 #define INITIAL 0
497 /* #line 2 "nidrgen.l" */
498 /*********************************************************************
499 Copyright 2008, 2010 Sandia Corporation.  Under the terms of Contract
500 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
501 retains certain rights in this software.
502 
503 Redistribution and use in source and binary forms, with or without
504 modification, are permitted provided that the following conditions
505 are met:
506 
507 * Redistributions of source code must retain the above copyright
508 notice, this list of conditions and the following disclaimer.
509 
510 * Redistributions in binary form must reproduce the above copyright
511 notice, this list of conditions and the following disclaimer in the
512 documentation and/or other materials provided with the distribution.
513 
514 * Neither the name of Sandia Corporation nor the names of its
515 contributors may be used to endorse or promote products derived from
516 this software without specific prior written permission.
517 
518 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
519 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
520 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
521 A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
522 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
523 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
524 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
525 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
526 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
527 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
528 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
529 ***********************************************************************/
530 
531 #include <ctype.h>
532 #include <math.h>
533 #include <stdarg.h>
534 #include <stdio.h>
535 #include <stdlib.h>
536 #include <string.h>
537 #include "nidr.h"	/* for KeyWordKind */
538 
539 #ifndef NO_NIDR_DYNLIB
540 typedef KeyWord *(*KW_ADD)(void);
541 #ifdef _WIN32
542 #include <windows.h>
543 #define dlopen(x,y) LoadLibrary(x)
544 #define find_dlsym(a,b,c) (a = (KW_ADD)GetProcAddress((HINSTANCE)(b),c))
545 #define dlclose(x) FreeLibrary((HMODULE)x)
546 #define NO_DLERROR
547 #else
548 #include <dlfcn.h>
549 #define find_dlsym(a,b,c) (a = (KW_ADD)dlsym(b,c))
550 #undef NO_DLERROR
551 #endif
552 #endif
553 
554 #ifndef DMBLK_GULP
555 #define DMBLK_GULP 1024
556 #endif
557 #ifndef DMLBK_SGULP
558 #define DMBLK_SGULP 16000
559 #endif
560 #ifndef MBLK_GULP
561 #define MBLK_GULP 8191
562 #endif
563 #ifndef KWSTACKLEN
564 #define KWSTACKLEN 100	/*should be overkill*/
565 #endif
566 #ifndef DEFTAGLEN
567 #define DEFTAGLEN 2048	/* should be overkill*/
568 #endif
569 
570  typedef union
571 YYSTYPE { char *s; } YYSTYPE;
572 
573  enum LastSeen {
574 	Saw_kwname	= 1,
575 	Saw_type	= 2,
576 	Saw_func	= 3,
577 	Saw_dflt	= 4,
578 	Saw_dfltname	= 5,
579 	Saw_lt		= 6,
580 	Saw_le		= 7,
581 	Saw_ge		= 8,
582 	Saw_gt		= 9,
583 	Saw_desc	= 10,
584 	Saw_group	= 11,
585 	Saw_tag		= 12,
586 	Saw_len		= 13,
587 	Saw_dy		= 14
588 	};
589 
590  static const char *tokname[] = {
591 	"<bug>",
592 	"kwname",
593 	"type",
594 	"{funcspec}",
595 	":=",
596 	"#define name for :=",
597 	"<",
598 	"<=",
599 	">=",
600 	">",
601 	"DESC",
602 	"GROUP",
603 	"TAG",
604 	"LEN"
605 	};
606 
607  enum ParState {
608 	/* parstate values... */
609 	PPar_emtpy	= 0,
610 	PPar_starting	= 1,
611 	PPar_started	= 2,
612 	PPar_leftpar	= 3,
613 	Dupchecking	= 4,
614 	Dupchecked	= 5,
615 	Printing	= 6,
616 	KwStacked	= 7,
617 	Sorted		= 8,
618 	Leftput		= 9,
619 	Parchecked	= 10
620 	};
621 
622  /* values for lastseen also include single characters ( [ { } ] ) ; */
623 
624  /* enums to make constants visible to debuggers */
625  enum {
626 	DMblk_gulp	= DMBLK_GULP,
627 	Dmblk_sgulp	= DMBLK_SGULP,
628 	Mblk_gulp	= MBLK_GULP,
629 	KW_stacklen	= KWSTACKLEN,
630 	Br_stacklen	= 2*KW_stacklen,
631 	DHTlen		= 997,
632 	DHTfactor	= 43,
633 	HTlen		= 127,
634 	KWPlen		= 32,
635 	KWOUTlen0	= 128 };
636 
637  typedef struct Defhash Defhash;
638  typedef struct DefhashHead DefhashHead;
639  typedef struct DefhashTab DefhashTab;
640  typedef struct HashHead HashHead;
641  typedef struct KWctx KWctx;
642  typedef struct Mblk Mblk;
643  typedef struct Taghash Taghash;
644  typedef struct StrList StrList;
645 
646  struct
647 DefhashHead {
648 	DefhashHead *hnext, *thread;
649 	char *name;
650 	};
651 
652  struct
653 Defhash {
654 	DefhashHead hh;
655 	char *value;
656 	int qkeep;
657 	};
658 
659  struct
660 Taghash {
661 	DefhashHead hh;
662 	KWctx *kw;
663 	int uses;
664 	};
665 
666  struct
667 DefhashTab {
668 	DefhashHead *Tab[DHTlen];
669 	DefhashHead *lastdh;
670 	size_t nalloc;	/* size of new entry allocations in units of sizeof(void*) */
671 	int nent;
672 	};
673 
674  struct
675 Mblk {
676 	Mblk *next;
677 	void *stuff[Mblk_gulp];
678 	};
679 
680  struct
681 HashHead { HashHead *hnext, *hprev; };
682 
683  struct
684 StrList {
685 	HashHead h;
686 	StrList *next;
687 	char *val;
688 	int Lineno;
689 	int primary;
690 	int seqno;
691 	int needrev;
692 	};
693 
694  struct
695 KWctx {
696 	KWctx *next;
697 	StrList *names;	/* list of name and aliases */
698 	char *name1;	/* first name (for tagout) */
699 	KWctx *kw;	/* list of contained keywords */
700 	KWctx *master;	/* non-null ==> this is an alias; use master's kwkno */
701 	KWctx *pmaster;	/* used in computing paoff */
702 	KWctx *pparent;	/* paren parent, for ((...)|(...) ...) */
703 	KWctx *rparent;	/* "real" parent, for stuff inside ((...)) */
704 	StrList *funcs;	/* pre- and post order functions and (void*) args */
705 	char *Br_top;	/* Br_top when this keyword began */
706 	char *lb;	/* lower bound (if kind & KWKind_Lb is nonzero) */
707 	char *ub;	/* upper bound (if kind & KWKind_Ub is nonzero) */
708 	char *init;	/* initial value (if kind & KWKind_init is nonzero) and */
709 			/* kind & KWKind_Mask is 1 or 2 (KWKind_Int or KWKind_Real) */
710 	char *cinit;	/* initial value for STRING-valued keyword,	*/
711 			/* ==> (kind & (KWKind_Mask | KWKind_init))	*/
712 			/*	== (KWKind_Str | KWKind_init)		*/
713 	char *defname;	/* name of preprocessor token to be #defined */
714 	char *desc;
715 	char *dylib;
716 	char *group;
717 	char *tag;
718 	char *len;	/* keyword giving array length */
719 	size_t dtnext;	/* for adjusting deftag when this keyword goes out of scope */
720 	size_t name1len;
721 	int alt;	/* alternative group number of this keyword */
722 	int kind;	/* kind of values for this keyword */
723 	int kno;	/* number of this keyword, for generating kw_n names */
724 	int kwkno;	/* number of this keyword's kw array (if any) */
725 	int kwknop;	/* if this is a pparent and has a pparent, kwkno for this and parents */
726 	int nalt;	/* number of alternative groups in contained keywords */
727 	int nfcn;	/* number of function and arg entries in funcs */
728 	int nkw;	/* number of contained keywords */
729 	int nreq;	/* number of required elements in contained keywords */
730 	int req;	/* required group for this keyword (0 if optional) */
731 	enum ParState parstate;	/* state in handling ((...)) */
732 	int altoffset;	/* for expand */
733 	int reqoffset;	/* for expand */
734 	int level;
735 	int objno;	/* for kwcomp2 */
736 	int agroup;	/* for GuiKeyWord */
737 	int paoff;	/* offset of primary keyword */
738 	};
739 
740  static int lastagroup, lastobjno, nalias, seqno;
741 
742  Defhash *lastdef;
743  DefhashTab DHTab, TagTab;
744  FILE *mtagout, *tagin, *tagout;
745  HashHead HTab[HTlen];
746  KWctx KWbase, *lastkw, *lastkw1;
747  KWctx *KWStack[KW_stacklen], **KWtop = KWStack;
748  Mblk FirstMblk, *CurMblk = &FirstMblk;
749  YYSTYPE yyval;
750  char Br_stack[Br_stacklen], *Br_top = Br_stack;
751  char deftag[DEFTAGLEN], *dtend = deftag + DEFTAGLEN - 2, *dtnext = deftag;
752  char *infname, *lasttag, *progname, *specfile, *tagfname;
753  int Lineno = 1, dfltgroup = 1, startwarn = 1, wantfuncs = 1;
754  int brace, btype, dupnames, dynlibseen, dynline, expand, guikeywds, ignoretags;
755  int kwmult, lastkno, lastseen, liberror, libexpand, missing, needcomma, nsquawk;
756  int or_mode, saweof;
757  size_t mbavail = Mblk_gulp;
758  void **mbnext = FirstMblk.stuff;
759  static void Eat_comment(void);
760  static void Keywd(const char *);
761  static void Saw_num(const char*);
762  static void Saw_quote(void);
763  static void Saw_tok(int, int);
764 
765  /* Possible values for *Br_top:
766  //	 0  ==> empty (for Br_stack[0] only)
767  //	'(' ==> open paren seen, awaiting ')'
768  //	'[' ==> open square bracket, awaiting ']'
769  */
770 
771  static void
botch(const char * fmt,...)772 botch(const char *fmt, ...)
773 {
774 	va_list ap;
775 	va_start(ap, fmt);
776 	fprintf(stderr, "\n%s:\n\tbotch on line %d", progname, Lineno);
777 	if (infname)
778 		fprintf(stderr, " of \"%s\"", infname);
779 	fprintf(stderr, ":\n\t");
780 	vfprintf(stderr, fmt, ap);
781 	fputs(".\n", stderr);
782 	va_end(ap);
783 	exit(1);
784 	}
785 
786  static void
squawk(const char * fmt,...)787 squawk(const char *fmt, ...)
788 {
789 	va_list ap;
790 	va_start(ap, fmt);
791 	fprintf(stderr, "\n%s: line %d", progname, Lineno);
792 	if (infname)
793 		fprintf(stderr, " of \"%s\"", infname);
794 	fprintf(stderr, ":\n\t");
795 	vfprintf(stderr, fmt, ap);
796 	fputs(".\n", stderr);
797 	va_end(ap);
798 	++nsquawk;
799 	}
800 
801  static void*
Malloc(size_t L,const char * where)802 Malloc(size_t L, const char *where)
803 {
804 	void *rv = malloc(L);
805 	if (!rv)
806 		botch("malloc(%lu) failure in %s()", (unsigned long)L);
807 	return rv;
808 	}
809 
810  static void*
Realloc(void * rv,size_t L,const char * where)811 Realloc(void *rv, size_t L, const char *where)
812 {
813 	rv = realloc(rv, L);
814 	if (!rv)
815 		botch("ralloc(%lu) failure in %s()", (unsigned long)L);
816 	return rv;
817 	}
818 
819  void
unexpected(const char * what)820 unexpected(const char *what)
821 { botch("unexpected \"%s\"", what); }
822 
823  static void *
Alloc(size_t len)824 Alloc(size_t len)
825 {
826 	Mblk *mb;
827 	size_t L;
828 	void *rv;
829 
830 	L = (len + sizeof(void*) - 1)/sizeof(void*);
831 	if (L >= Mblk_gulp)
832 		botch("Alloc(%lu) failure", (unsigned long)len);
833 	if (L > mbavail) {
834 		if (!(mb = CurMblk->next)) {
835 			mb = (Mblk*)Malloc(sizeof(Mblk), "Alloc");
836 			CurMblk->next = mb;
837 			}
838 		CurMblk = mb;
839 		mbavail = Mblk_gulp;
840 		mbnext = mb->stuff;
841 		mb->next = 0;
842 		memset(mbnext, 0, sizeof(mb->stuff));
843 		}
844 	rv = mbnext;
845 	mbnext += L;
846 	mbavail -= L;
847 	return rv;
848 	}
849 
850  StrList *
new_StrList(const char * s,StrList * nxt)851 new_StrList(const char *s, StrList *nxt)
852 {
853 	size_t L = strlen(s) + 1;
854 	StrList *rv = (StrList*)Alloc(sizeof(StrList) + L);
855 	strcpy(rv->val = (char*)(rv + 1), s);
856 	if ((rv->next = nxt))
857 		rv->needrev = 1;
858 	rv->Lineno = Lineno;
859 	return rv;
860 	}
861 
862  static void
Alias(const char * s)863 Alias(const char *s)
864 {
865 	KWctx *kw;
866 	StrList *sl;
867 
868 	if (lastseen != Saw_kwname)
869 		botch("ALIAS out of place");
870 	kw = lastkw;
871 	for(s += 6; *s <= ' '; s++);
872 	sl = kw->names = new_StrList(s, kw->names);
873 	++nalias;
874 	sl->seqno = ++seqno;
875 	lastseen = Saw_kwname;
876 	}
877 
878  static void
reqchk(const char * a,const char * s)879 reqchk(const char *a, const char *s)
880 {
881 	if (a)
882 		while(*a)
883 			if (*a++ == lastseen)
884 				return;
885 	botch("\"%s\" out of place", s);
886 	}
887 
888  static void
reqchk1(const char * a,const char * s)889 reqchk1(const char *a, const char *s)
890 {
891 	int c;
892 
893 	if (*Br_top != *s) {
894 		if ((c = *Br_top)) {
895 			switch(c) {
896 			 case '[': c = ']'; break;
897 			 case '(': c = ')'; break;
898 			 default:  c = '?';
899 			 }
900 			botch("Missing '%c'", c);
901 			}
902 		else
903 			a = 0;
904 		}
905 	reqchk(a, s+1);
906 	}
907 
908  static void
Bar(void)909 Bar(void)
910 {
911 	static char allowed[] = { /*(*/ ')', Saw_kwname, Saw_type, 0 };
912 	reqchk(KWtop - KWStack > 1 || KWtop[0]->kw ? allowed : "", "|");
913 	lastseen = '|';
914 	lastkw = lastkw1 = 0;
915 	or_mode = 1;
916 	}
917 
918  static void
Lpar(void)919 Lpar(void)
920 {
921 	KWctx *kw;
922 	int olastseen = lastseen;
923 	static char allowed[] = { '(', '[', '|', ']', ')', Saw_kwname, Saw_type, 0 };
924 
925 	reqchk(allowed, "("/*)*/);
926 	lastseen = '('; /*)*/
927 	if (KWtop > KWStack) {
928 		kw = KWtop[0];
929 		if (or_mode && kw->parstate == PPar_leftpar && !kw->kw) {
930 			dtnext = deftag + kw->dtnext;
931 			--KWtop;
932 			Keywd(0);
933 			kw->pparent = KWtop[0];
934 			}
935 		else if (olastseen == '(' || olastseen == '[' /*])*/)
936 			Keywd(0);
937 		lastseen = '(' /*)*/;
938 		}
939 	if (++Br_top - Br_stack >= Br_stacklen)
940 		botch("Br_stack overflow");
941 	*Br_top = '('; /*)*/
942 	lastkw = lastkw1 = 0;
943 	}
944 
945  static void
Lsqb(void)946 Lsqb(void)
947 {
948 	static char allowed[] = { /*([*/ ']', ')', Saw_kwname, Saw_type, 0 };
949 	reqchk(allowed, "["/*]*/);
950 	if (++Br_top - Br_stack >= Br_stacklen)
951 		botch("Br_stack overflow");
952 	lastseen = *Br_top = '['; /*]*/
953 	lastkw = lastkw1 = 0;
954 	}
955 
956  static void
Rpar(void)957 Rpar(void)
958 {
959 	static char allowed[] =  {/*[(*/ ')', ']', Saw_kwname, Saw_type, 0 };
960 	reqchk1(allowed, "()");
961 	if (KWtop <= KWStack)
962 		botch("bug: KW stack error");
963 	--Br_top;
964 	if (!KWtop[0]->kw && KWtop - KWStack > 2
965 	 && KWtop[-1]->parstate == PPar_starting)
966 		KWtop[-1]->Br_top = Br_top;
967 	--KWtop;
968 	lastseen = /*(*/ ')';
969 	lastkw = lastkw1 = 0;
970 	}
971 
972  static void
Rsqb(void)973 Rsqb(void)
974 {
975 	static char allowed[] = {/*(*/')', '[', ']', Saw_kwname, Saw_type, 0 };
976 	reqchk1(allowed, "[]");
977 	if (KWtop <= KWStack)
978 		botch("bug: KW stack error");
979 	--Br_top;
980 	--KWtop;
981 	lastseen = /*[*/ ']';
982 	lastkw = lastkw1 = 0;
983 	}
984 
985  static void
Lbrace(void)986 Lbrace(void)
987 {
988 	if (brace++ || (lastseen != Saw_kwname && lastseen != Saw_type))
989 		unexpected("{");
990 	lastseen = '{'; /*}}*/
991 	}
992 
993  static void
Rbrace(void)994 Rbrace(void)
995 {
996 	if (--brace || (lastseen != Saw_func && lastseen != ';'))
997 		/*{{*/unexpected("}");
998 	lastseen = Saw_type;
999 	}
1000 
1001  static void
Type(int n,const char * s)1002 Type(int n, const char *s)
1003 {
1004 	if (lastseen != Saw_kwname || !lastkw)
1005 		botch("type %s out of place", s);
1006 	lastkw->kind |= n;
1007 	lastkw = 0;
1008 	lastseen = Saw_type;
1009 	}
1010 
1011  static char *
def_name(const char * s0)1012 def_name(const char *s0)
1013 {
1014 	char *s;
1015 	const char *s1;
1016 	size_t L, L1;
1017 	static char *slast, *snext;
1018 
1019 	s1 = s0;
1020 	while(*s1++);
1021 	L = s1 - s0;
1022 	if (snext + L > slast) {
1023 		snext = (char*)Malloc(L1 = Dmblk_sgulp + L, "def_name");
1024 		slast = snext + L1;
1025 		}
1026 	strcpy(s = snext, s0);
1027 	snext += L;
1028 	return s;
1029 	}
1030 
1031 static void **DHHlast, **DHHnext;	/* Could be private to DHHlookup, but here */
1032 					/* to make them visible to debuggers. */
1033  static DefhashHead *
DHHlookup(const char * s0,DefhashTab * Htab,int add)1034 DHHlookup(const char *s0, DefhashTab *Htab, int add)
1035 {
1036 	DefhashHead *h, **hp;
1037 	const char *s;
1038 	size_t L;
1039 	unsigned int c, x;
1040 
1041 	for(x = 0, s = s0; (c = *(unsigned char*)s); ++s)
1042 		x += DHTfactor*x + c;
1043 	x %= DHTlen;
1044 	for(hp = &Htab->Tab[x]; (h = *hp); hp = &h->hnext) {
1045 		if (!strcmp(s0, h->name))
1046 			return h;
1047 		}
1048 	if (!add)
1049 		return h;
1050 	Htab->nent++;
1051 	if (DHHnext + Htab->nalloc >= DHHlast) {
1052 		DHHnext = (void**)Malloc(L = DMblk_gulp*sizeof(void*), "DHHlookup");
1053 		DHHlast = DHHnext + DMblk_gulp;
1054 		memset(DHHnext, 0, L);
1055 		}
1056 	*hp = h = (DefhashHead*)DHHnext;
1057 	DHHnext += Htab->nalloc;
1058 	h->name = def_name(s0);
1059 	h->thread = Htab->lastdh;
1060 	return Htab->lastdh = h;
1061 	}
1062 
1063  static void
bothplaces(KWctx * kw,const char * name)1064 bothplaces(KWctx *kw, const char *name)
1065 { squawk("For %s, %s appears both in specfile and tagfile", kw->names->val, name); }
1066 
1067  static void
tagimport(KWctx * kw,KWctx * tw)1068 tagimport(KWctx *kw, KWctx *tw)
1069 {
1070 	typedef struct KWimport KWimport;
1071 	struct KWimport { const char *name; size_t off; };
1072 	static KWimport Imp[] = {
1073 		{ "lower bound",	offsetof(KWctx,lb) },
1074 		{ "upper bound",	offsetof(KWctx,ub) },
1075 		{ "default (:= value)",	offsetof(KWctx,init) },
1076 		{ "default (:= value)",	offsetof(KWctx,cinit) },
1077 		{ "defname",		offsetof(KWctx,defname) },
1078 		{ "DESC",		offsetof(KWctx,desc) },
1079 		{ "GROUP",		offsetof(KWctx,group) },
1080 		{ "LEN",		offsetof(KWctx,len) },
1081 		{0}};
1082 	KWimport *ki;
1083 #define field(k,n) *(char**)((char*)k+n)
1084 	for(ki = Imp; ki->name; ++ki) {
1085 		if (field(tw,ki->off)) {
1086 			if (field(kw,ki->off))
1087 				bothplaces(kw, ki->name);
1088 			else
1089 				field(kw,ki->off) = field(tw,ki->off);
1090 			}
1091 		}
1092 #undef field
1093 	}
1094 
1095 #ifndef NO_NIDR_DYNLIB
1096 
1097 static const char *typename[8] = {
1098 	"no value", "INTEGER", "REAL", "STRING",
1099 	"(Bug! no value LIST)", "INTEGERLIST", "REALLIST", "STRINGLIST" };
1100 
1101  static int
kwseqnocomp(const void * a,const void * b)1102 kwseqnocomp(const void *a, const void *b)
1103 {
1104 	const KeyWordx *ka, *kb;
1105 
1106 	ka = *(KeyWordx**)a;
1107 	kb = *(KeyWordx**)b;
1108 	return (int)ka->seqno - (int)kb->seqno;
1109 	}
1110 
1111  static void
Lsqbpar(void)1112 Lsqbpar(void)
1113 {
1114 	Lsqb();
1115 	Lpar();
1116 	}
1117 
1118  static void
Rparsqb(void)1119 Rparsqb(void)
1120 {
1121 	Rpar();
1122 	Rsqb();
1123 	}
1124 
1125  static void
Nobrak(void)1126 Nobrak(void) {}
1127 
1128  typedef struct
1129 KW_Cstak { KeyWordx **Cstak; Uint n, nmax; } KW_Cstak;
1130 
1131  static void kw_finish(int);
1132  static void kw_insert(KeyWord*, KW_Cstak*, int);
1133 
1134  static KeyWord*
kw_stakadj(KeyWord * kw,KW_Cstak * Stk,int needbar,int n0,KeyWord * okw3)1135 kw_stakadj(KeyWord *kw, KW_Cstak *Stk, int needbar, int n0, KeyWord *okw3)
1136 {
1137 	KeyWordx *kw1, *kw2, **x;
1138 	Uint i, j, k, nst, nz;
1139 
1140 	kw1 = (KeyWordx*)kw;
1141 	nz = 0;
1142 	while(!kw1[++nz].kw.name);
1143 	if (nz == 1 && *kw1[nz].kw.name)
1144 		okw3 = 0;
1145 	nst = Stk->n;
1146 	x = Stk->Cstak;
1147 	kw2 = (KeyWordx*)kw1->kw.kw;
1148 	for(i = 0; i < nst; ++i) {
1149 		if (x[i]->kw.kw == &kw2->kw) {
1150 			j = i;
1151 			++kw1;
1152 			/* No need to test kw1->kw.name in the following loop */
1153 			/* as the == test will fail if kw1->kw.name is nonzero. */
1154 			while(++j < nst && x[j]->kw.kw == kw1->kw.kw)
1155 				++kw1;
1156 			k = nz - (j-i);
1157 			goto have_jk;
1158 			}
1159 		}
1160 	k = nz;
1161 	j = n0;
1162  have_jk:
1163 	while(nst > j) {
1164 		kw_insert(&x[--nst]->kw, Stk, 0);
1165 		Rpar();
1166 		}
1167 	if (needbar)
1168 		Bar();
1169 	if (k) {
1170 		if (nst + k > Stk->nmax)
1171 			x = Stk->Cstak = (KeyWordx**)Realloc(x,
1172 				(Stk->nmax = 2)*sizeof(KeyWordx*), "kw_stakadj");
1173 		do {
1174 			if (kw1->kw.kw != okw3)
1175 				Lpar();
1176 			x[j++] = kw1++;
1177 			}
1178 			while(--k);
1179 		nst = j;
1180 		}
1181 	Stk->n = nst;
1182 	if (!*kw1->kw.name)
1183 		return 0;
1184 	return &kw1->kw;
1185 	}
1186 
1187  static int
same_funcs(KeyWordx * kw1,KeyWordx * kw2)1188 same_funcs(KeyWordx *kw1, KeyWordx *kw2)
1189 {
1190 	KeyWordx *kw3, *kw4;
1191 
1192 	if (!kw1->kw.nkw || !kw2->kw.nkw)
1193 		return 0;
1194 	kw3 = (KeyWordx*)kw1->kw.kw;
1195 	kw4 = (KeyWordx*)kw2->kw.kw;
1196 	if (kw3 == kw4)
1197 		return 1;
1198 	if (kw4->kw.name)
1199 		return 0;
1200 	kw4 = (KeyWordx*)kw4->kw.kw;
1201 	return kw3 == kw4;
1202 	}
1203 
1204  static char *
StrCpy(const char * s)1205 StrCpy(const char *s)
1206 {
1207 	char *t;
1208 	size_t L;
1209 
1210 	if (!s)
1211 		return 0;
1212 	L = strlen(s);
1213 	t = (char*)Alloc(L+1);
1214 	strcpy(t,s);
1215 	return t;
1216 	}
1217 
1218  static int Saw_name(const char*);
1219  static void Saw_stok(int, size_t);
1220 
1221  static void
kw_insert(KeyWord * kw,KW_Cstak * Stk,int top)1222 kw_insert(KeyWord *kw, KW_Cstak *Stk, int top)
1223 {
1224 	enum { NKW0 = 32 };
1225 	KeyWord *kw3, *kw30, *okw3;
1226 	KeyWordx *kw0, *kw1, *kw2, *kw4, **x, *x0[NKW0];
1227 	Uint i, j, k, knd, nkw, nst0, nst1;
1228 	char buf[32];
1229 	int alt2, incc, needbar, needbar1, samef0, samef1;
1230 	typedef void (*Brak)(void);
1231 	Brak Lbrak, Rbrak;
1232 
1233 	kw1 = (KeyWordx*)kw->kw;
1234 	while(!kw1->kw.name)
1235 		++kw1;
1236 	nkw = kw->nkw;
1237 	x = x0;
1238 	if (nkw > NKW0)
1239 		x = (KeyWordx**)Malloc(nkw * sizeof(KeyWordx*), "kw_insert");
1240 	for(i = 0; i < nkw; ++i)
1241 		x[i] = kw1++;
1242 	if (nkw > 1)
1243 		qsort(x, nkw, sizeof(KeyWordx*), kwseqnocomp);
1244 	kw0 = 0;
1245 	kw30 = 0;
1246 	nst0 = Stk->n;
1247 	for(i = j = samef0 = 0; i < nkw; i = j) {
1248 		kw1 = x[i];
1249 		kw2 = 0;
1250 		while(++j < nkw) {
1251 			kw2 = x[j];
1252 			if (!kw2->kw.paoff)
1253 				break;
1254 			kw2 = 0;
1255 			}
1256 		Lbrak = Rbrak = 0;
1257 		okw3 = kw30;
1258 		if (top) {
1259 			kw_finish(kw1->kw.kind & KWKind_12);
1260 			kw3 = kw1->kw.kw;
1261 			Rbrak = Nobrak;
1262 			goto nobrak;
1263 			}
1264 		needbar = needbar1 = kw0 && kw0->kw.alt == kw1->kw.alt;
1265 		nst1 = Stk->n;
1266 		alt2 = incc = 0;
1267 		kw4 = 0;
1268 		if (kw2) {
1269 			alt2 = kw1->kw.alt == kw2->kw.alt;
1270 			kw4 = (KeyWordx*)kw2->kw.kw;
1271 			}
1272 		if ((kw3 = kw30 = kw1->kw.kw)) {
1273 			if (!kw3->name) {
1274 				kw3 = kw_stakadj(kw3, Stk, needbar, nst0, okw3);
1275 				needbar1 = 0;
1276 				}
1277 			else
1278 				while(Stk->n > nst0) {
1279 					if (Stk->Cstak[Stk->n-1]->kw.kw == kw3) {
1280 						if (kw4 && kw4->kw.kw == kw3)
1281 							incc = 1; /* in contained context */
1282 						break;
1283 						}
1284 					kw_insert(&Stk->Cstak[--Stk->n]->kw, Stk, 0);
1285 					Rpar();
1286 					}
1287 			}
1288 		else while(Stk->n > nst0) {
1289 			kw_insert(&Stk->Cstak[--Stk->n]->kw, Stk, 0);
1290 			Rpar();
1291 			}
1292 		samef0 = needbar && same_funcs(kw1,kw0);
1293 		samef1 = alt2    && same_funcs(kw1,kw2);
1294 		if (kw3) {
1295 			if (samef1) {
1296 				if (!needbar)
1297 					Lbrak = kw1->kw.req ? Lpar : Lsqbpar;
1298 				else if (!samef0 && kw3->name)
1299 					Lbrak = Lpar;
1300 				kw3 = 0;
1301 				goto barchk;
1302 				}
1303 			else if (needbar) {
1304 				if (!incc)
1305 					Rbrak = alt2 || kw1->kw.req ? Rpar : Rparsqb;
1306 				if (!samef0
1307 				 && (Stk->n <= nst1
1308 				    || !kw0 || kw0->kw.kw != Stk->Cstak[Stk->n-1]->kw.kw))
1309 					Lbrak = Lpar;
1310 				}
1311 			else if (kw1->kw.req) {
1312 				Lbrak = Lpar;
1313 				Rbrak = Rpar;
1314 				}
1315 			else {
1316 				Lbrak = Lsqb;
1317 				Rbrak = Rsqb;
1318 				if (alt2) {
1319 					Lbrak = Lsqbpar;
1320 					Rbrak = Rpar;
1321 					}
1322 				}
1323 			if (kw2) {
1324 				if (kw4 && !kw4->kw.name && kw4->kw.kw == kw3)
1325 					goto zap_kw3;
1326 				if (Stk->n > 0 && Stk->Cstak[Stk->n-1]->kw.kw == kw3)
1327 					--Stk->n;
1328 				}
1329 			else if (Stk->n > 0 && Stk->Cstak[Stk->n-1]->kw.kw == kw3) {
1330  zap_kw3:
1331 				Rbrak = 0;
1332 				kw3 = 0;
1333 				}
1334 			}
1335 		else if (!kw1->kw.req) {
1336 			if (!needbar)
1337 				Lbrak = Lsqb;
1338 			if (!alt2)
1339 				Rbrak = Rsqb;
1340 			}
1341  barchk:
1342 		if (needbar1)
1343 			Bar();
1344 		if (Lbrak)
1345 			Lbrak();
1346  nobrak:
1347 		Keywd(kw1->kw.name);
1348 		while(++i < j) {
1349 			kw2 = x[i];
1350 			Alias(kw2->kw.name - 6);	/* Alias will increment by 6 */
1351 			}
1352 		knd = kw1->kw.kind;
1353 		if ((k = knd & (KWKind_Mask|KWKind_List)))
1354 			Type(k, typename[k]);
1355 		if ((k = knd & KWKind_Lb)) {
1356 			Saw_tok(knd & KWKind_strictLb ? Saw_gt : Saw_ge, KWKind_Lb);
1357 			btype = k;
1358 			snprintf(buf, sizeof(buf), "%g", kw1->kw.Lb);
1359 			Saw_num(buf);
1360 			}
1361 		if ((k = knd & KWKind_Ub)) {
1362 			Saw_tok(knd & KWKind_strictUb ? Saw_lt : Saw_le, KWKind_Ub);
1363 			btype = k;
1364 			snprintf(buf, sizeof(buf), "%g", kw1->kw.Ub);
1365 			Saw_num(buf);
1366 			}
1367 		if (kw1->init || kw1->cinit) {
1368 			Saw_tok(Saw_dflt, KWKind_init);
1369 			lastdef = 0;
1370 			if (kw1->defname)
1371 				Saw_name(kw1->defname);
1372 			if (kw1->init)
1373 				Saw_num(kw1->init);
1374 			else
1375 				lastkw1->cinit = StrCpy(kw1->cinit);
1376 			}
1377 		if (kw1->funcs)
1378 			lastkw1->funcs = new_StrList(kw1->funcs, 0);
1379 		else if (kw1->kw.f.vf && !kw1->kw.f.final) {
1380 			lastkw1->dylib = StrCpy((const char*)kw1->kw.f.vf);
1381 			dynlibseen = 1;
1382 			}
1383 		else
1384 			lastkw1->funcs = new_StrList("0", 0);
1385 		lastkw1->desc  = StrCpy(kw1->desc);
1386 		lastkw1->group = StrCpy(kw1->group);
1387 		if (kw1->alen) {
1388 			Saw_stok(Saw_len, offsetof(KWctx,len));
1389 			lastkw1->kind |= knd & KWKind_Len1OK;
1390 			Saw_name(kw1->alen);
1391 			}
1392 		if (Rbrak) {
1393 			if (kw3)
1394 				kw_insert((KeyWord*)kw1, Stk, 0);
1395 			Rbrak();
1396 			}
1397 		kw0 = kw1;
1398 		if (top) {
1399 			while(Stk->n > 0) {
1400 				kw_insert(&Stk->Cstak[--Stk->n]->kw, Stk, 0);
1401 				Rpar();
1402 				}
1403 			if (!kw2)
1404 				kw_finish(-1);
1405 			}
1406 		}
1407 	while(Stk->n > nst0) {
1408 		kw_insert(&Stk->Cstak[--Stk->n]->kw, Stk, 0);
1409 		Rpar();
1410 		}
1411 	if (x != x0)
1412 		free(x);
1413 	}
1414 
1415  static void
kw_insert1(KeyWord * kw,int top)1416 kw_insert1(KeyWord *kw, int top)
1417 {
1418 	KW_Cstak Stk;
1419 
1420 	Stk.n = 0;
1421 	Stk.Cstak = (KeyWordx**)Malloc((Stk.nmax = 64)*sizeof(KeyWordx*), "kw_insert1");
1422 	if (top) {
1423 		KWtop = KWStack;
1424 		KWbase.kw = 0;
1425 		}
1426 	kw_insert(kw, &Stk, top);
1427 	while(Stk.n > 0) {
1428 		kw_insert(&Stk.Cstak[--Stk.n]->kw, &Stk, 0);
1429 		Rpar();
1430 		}
1431 	free(Stk.Cstak);
1432 	}
1433 
1434  static int
libread1(const char * kname,const char * lname,Uint n,int allow_top)1435 libread1(const char *kname, const char *lname, Uint n, int allow_top)
1436 {
1437 	KW_ADD kwa;
1438 	KeyWord *kw, kw0;
1439 	Uint i;
1440 	const char *s;
1441 	void *h, (*Botch)(const char*, ...);
1442 
1443 	h = dlopen(lname, RTLD_NOW);
1444 	if (!h) {
1445 		Botch = botch;
1446 		if (kname && libexpand)
1447 			Botch = squawk;
1448 #ifndef _WIN32
1449 		if ((s = dlerror()))
1450 			if (kname)
1451 				Botch("Cannot open library \"%s\" for %s:\n\t%s",
1452 					lname, kname, s);
1453 			else
1454 				Botch("Cannot open library \"%s\":\n\t%s",
1455 					lname, s);
1456 		else
1457 #endif
1458 			if (kname)
1459 				Botch("Cannot open library \"%s\" for %s",
1460 					lname, kname);
1461 			else
1462 				Botch("Cannot open library \"%s\"", lname);
1463 		return ++liberror;
1464 		}
1465 	if (!find_dlsym(kwa, h, "keyword_add"))
1466 		botch("dlsym(\"keyword_add\") failed for %s", lname);
1467 	kw = (*kwa)();
1468 	if (!(s = kw->name)) {
1469 		s = "<NULL>";
1470 		goto namebotch;
1471 		}
1472 	if (allow_top) {
1473 		if (strcmp(s, "KeywordTop")) {
1474 			if (allow_top == 2) {
1475 				memset(&kw0, 0, sizeof(KeyWord));
1476 				kw0.kw = kw;
1477 				kw = &kw0;
1478 				kw0.nkw = 1;
1479 				}
1480 			else
1481 				allow_top = 0;
1482 			}
1483 		else
1484 			kname = 0;
1485 		}
1486 	else if (kname && strcmp(s, kname)) {
1487  namebotch:
1488 		botch("Library %s: expected top keyword to be %s but got %s",
1489 			lname, kname, s);
1490 		}
1491 	if (kname) {
1492 		i = kw->kind & (KWKind_Mask|KWKind_List);
1493 		if (i != n)
1494 			botch("Library %s: expected %s to be %s, but got %s",
1495 				lname, kname, typename[n], typename[i]);
1496 		}
1497 	if (kw->kw)
1498 		kw_insert1(kw, allow_top);
1499 	dlclose(h);
1500 	return 0;
1501 	}
1502 
1503  static int
lib_read(KWctx * kc,int allow_top)1504 lib_read(KWctx *kc, int allow_top)
1505 {
1506 	const char *kname, *lname;
1507 
1508 	kname = kc->name1;
1509 	lname = kc->dylib;
1510 	kc->dylib = 0;
1511 	return libread1(kname, lname, kc->kind & (KWKind_Mask|KWKind_List), allow_top);
1512 	}
1513 #else
1514 
1515  static int
lib_read(KWctx * kc,int allow_top)1516 lib_read(KWctx *kc, int allow_top)
1517 {
1518 	botch("dlsym(\"keyword_add\") failed for %s", kc->dylib);
1519 	return 1;
1520 	}
1521 #endif
1522 
1523  static void
Keywd(const char * s)1524 Keywd(const char *s)
1525 {
1526 	KWctx *kw, *kw0, *kw1, *kw2, *kwm, **kwp;
1527 	StrList *nam;
1528 	Taghash *th;
1529 	char *s1;
1530 	int alt, lsave, req;
1531 	size_t L, L1;
1532 	static char allowed[] = { '(',')','[',']','|', Saw_kwname, Saw_type, 0 };
1533 
1534 	if (tagin)
1535 		botch("Inappropriate text \"%s\" in tagfile \"%s\"", s, tagfname);
1536 	kw1 = *KWtop;
1537 #ifndef NO_NIDR_DYNLIB
1538 	if (kw1->dylib && libexpand && !lib_read(kw1,0))
1539 		kw1 = *KWtop;
1540 #endif
1541 	kw0 = kw1;
1542 	kwm = 0;
1543 	if (!kw1->names && s) {
1544 		switch(kw1->parstate) {
1545 		  case PPar_emtpy:
1546 			do {
1547 				kw1->parstate = PPar_starting;
1548 				kw1 = kw1->pparent;
1549 				}
1550 				while(kw1 && kw1->parstate == PPar_emtpy);
1551 			kw1 = kw0->rparent;
1552 			break;
1553 		  case PPar_starting:
1554 			if (or_mode)
1555 				kw1 = kw0->rparent;
1556 			else
1557 				kw1->parstate = PPar_started;
1558 			break;
1559 		  }
1560 		}
1561 	if (or_mode && !kw1->kw) {
1562 		kw2 = KWtop[-1];
1563 		if (!kw2->names && kw2->parstate == PPar_starting)
1564 			kw2 = kw2->rparent;
1565 		if (s)
1566 			kw1->master = kwm = kw1;
1567 		kw1 = kw2;
1568 		}
1569 	L = alt = req = 0;
1570 	if (s) {
1571 		kwp = KWStack + kw1->level + 1;
1572 		if (kwp > KWtop)
1573 			kwp = KWtop;
1574 		while(kwp > KWStack) {
1575 			kw2 = *kwp--;
1576 			if (kw2->name1) {
1577 				dtnext = deftag + kw2->dtnext;
1578 				L = kw2->name1len;
1579 				strcpy(dtnext-L, kw2->name1);
1580 				break;
1581 				}
1582 			}
1583 		alt = ++kw1->nalt;
1584 		if (*Br_top != '['/*]*/ || Br_top == kw1->Br_top) {
1585 			req = ++kw1->nreq;
1586 			if (*Br_top == '(' /*)*/) /* allow [(...)|...] */
1587 				for(s1 = Br_top; --s1 > kw1->Br_top; ) {
1588 					if (*s1 != '(' /*)*/) {
1589 						if (*s1 == '[' /*]*/) {
1590 							--kw1->nreq;
1591 							req = 0;
1592 							}
1593 						break;
1594 						}
1595 					}
1596 			}
1597 		if (or_mode) {
1598 			alt = --kw1->nalt;
1599 			if (req)
1600 				req = --kw1->nreq;
1601 			}
1602 		if (lastseen)
1603 			reqchk(allowed, s);
1604 		or_mode = 0;
1605 		}
1606 	lastkw = lastkw1 = kw = (KWctx*) Alloc(sizeof(KWctx));
1607 	if (!kw0->names)
1608 		kw->pparent = kw0;
1609 	if (s) {
1610 		kw->names = nam = new_StrList(s,0);
1611 		kw->name1 = nam->val;
1612 		kw->name1len = L = strlen(s);
1613 		for(kwp = KWtop; kwp > KWStack; --kwp) {
1614 			kw2 = *kwp;
1615 			if (kw2->names) {
1616 				if (kwp < KWtop) {
1617 					L1 = kw2->dtnext + L + 1;
1618 					while(++kwp <= KWtop) {
1619 						kw2 = *kwp;
1620 						if (!kw2->name1) {
1621 							kw2->name1 = kw->name1;
1622 							kw2->name1len = L;
1623 							kw2->dtnext = L1;
1624 							}
1625 						}
1626 					}
1627 				break;
1628 				}
1629 			}
1630 		if (kw1->dylib) {
1631 			lsave = Lineno;
1632 			Lineno = dynline; /* Line where DYNLIB appeared */
1633 			squawk("Suppressing DYNLIB for %s to parse contained keywords",
1634 				kw1->names ? kw1->names->val : "???? (bug!)");
1635 			Lineno = lsave;
1636 			kw1->dylib = 0;
1637 			}
1638 		nam->primary = KWKind_primary;
1639 		nam->seqno = ++seqno;
1640 		kw->next = kw1->kw;
1641 		kw1->kw = kw;
1642 		if (lastseen == '(' /*)*/)
1643 			kw->parstate = PPar_leftpar;
1644 		kw->agroup = lastagroup++;
1645 		}
1646 	else {
1647 		kw->objno = ++lastobjno;
1648 		if (!kw1->kw && (kw->rparent = kw1->rparent))
1649 			kw1 = kw->rparent;
1650 		else
1651 			kw->rparent = kw1;
1652 		alt = kw1->alt;
1653 		req = kw1->req;
1654 		}
1655 	kw->alt = alt;
1656 	kw->req = req;
1657 	kw->Br_top = Br_top;
1658 	kw->master = kwm;
1659 	kw->level = KWtop - KWStack;
1660 	if (lastseen == '(' || lastseen == '[' /*])*/ || KWtop == KWStack) {
1661 		if (++KWtop - KWStack >= KW_stacklen)
1662 			botch("KW stack overflow");
1663 		*KWtop = kw;
1664 		}
1665 	lasttag = 0;
1666 	if (s) {
1667 		if (dtnext > deftag)
1668 			*dtnext++ = '/';
1669 		if (dtnext + L >= dtend)
1670 			botch("deftag overflow");
1671 		memcpy(dtnext, s, L);
1672 		*(dtnext += L) = 0;
1673 		if (tagout)
1674 			fprintf(tagout, "TAG \"%s\"\n", deftag);
1675 		if (tagfname) {
1676 			if ((th = (Taghash*)DHHlookup(deftag, &TagTab, ignoretags))) {
1677 				++th->uses;
1678 				lasttag = th->hh.name;
1679 				if (!ignoretags) {
1680 					lastkw1->tag = lasttag;
1681 					tagimport(lastkw1, th->kw);
1682 					}
1683 				}
1684 			else if (mtagout)
1685 				fprintf(mtagout, "TAG \"%s\" #missing\n", deftag);
1686 			}
1687 		}
1688 	kw->dtnext = dtnext - deftag;
1689 	if (lastseen == 0)
1690 		kw->kind = kwmult;
1691 	lastseen = Saw_kwname;
1692 	}
1693 
1694  static void
kw_finish(int nextkind)1695 kw_finish(int nextkind)
1696 {
1697 	KWctx *kw;
1698 
1699 	if (*Br_top)
1700 		botch("unmatched '%c'", *Br_top);
1701 	if (KWtop - KWStack > 1)
1702 		botch("bug: KW stack botch in kw_finish");
1703 	if (KWtop > KWStack) {
1704 		kw = *KWtop;
1705 		if (kw->dylib && libexpand)
1706 			lib_read(kw, nextkind == -1);
1707 		}
1708 	KWtop = KWStack;
1709 	dtnext = deftag;
1710 	lastseen = 0;
1711 	kwmult = nextkind < 0 ? 0 : nextkind;
1712 	}
1713 
1714  static void
funcbotch(KWctx * kw)1715 funcbotch(KWctx *kw)
1716 {
1717 	botch("Keyword %s:\n\t\t\"start\" and \"final\" functions cannot be used with DYNLIB"
1718 		".\n\t\tThey must be supplied by the dynamically loaded library",
1719 		kw->names->val);
1720 	}
1721 
1722  static void
Fnc(char * s)1723 Fnc(char *s)
1724 {
1725 	KWctx *kw;
1726 
1727 	if (!(kw = lastkw1))
1728 		botch("misplaced {...}");
1729 	if (++kw->nfcn > 4)
1730 		botch("too many functions in {...}");
1731 	else if (kw->dylib)
1732 		funcbotch(kw);
1733 	else if (kw->kind & KWKind_Libname)
1734 		botch("Keyword %s:\n\t\t\"start\" and \"final\" functions "
1735 			"cannot be used with LIBNAME.",
1736 			kw->names->val);
1737 	kw->funcs = wantfuncs ? new_StrList(s, kw->funcs) : 0;
1738 	lastseen = Saw_func;
1739 	}
1740 
1741  static const char*
tname_adj(const char * tname,int what,int kbits)1742 tname_adj(const char *tname, int what, int kbits)
1743 {
1744 	Uint k = lastkw1->kind;
1745 
1746 	switch(what) {
1747 	 case Saw_lt:
1748 		if (k & KWKind_caneqUb)
1749 			tname = "<=";
1750 		break;
1751 	 case Saw_le:
1752 		if (k & KWKind_strictUb)
1753 			tname = "<";
1754 		break;
1755 	 case Saw_ge:
1756 		if (k & KWKind_strictLb)
1757 			tname = ">";
1758 		break;
1759 	 case Saw_gt:
1760 		if (k & KWKind_caneqLb)
1761 			tname = ">=";
1762 	 }
1763 	return tname;
1764 	}
1765 
1766  static void
Saw_tok(int what,int kbits)1767 Saw_tok(int what, int kbits)
1768 {
1769 	const char *tname;
1770 
1771 	if ((lastseen == Saw_kwname || lastseen == Saw_type) && lastkw1) {
1772 		if (lastkw1->kind & kbits) {
1773 			tname = tokname[what];
1774 			if (kbits & (KWKind_Lb | KWKind_Ub))
1775 				tname = tname_adj(tname, what, kbits);
1776 			botch("%s already seen for keyword %s",
1777 				tname, lastkw1->names->val);
1778 			}
1779 		lastseen = what;
1780 		}
1781 	else
1782 		unexpected(tokname[what]);
1783 	}
1784 
1785  static void
Saw_stok(int what,size_t woff)1786 Saw_stok(int what, size_t woff)
1787 {
1788 	StrList *sl;
1789 
1790 	if ((lastseen == Saw_kwname || lastseen == Saw_type) && lastkw1) {
1791 		if (*(void**)((char*)lastkw1 + woff)) {
1792 			if ((sl = lastkw1->names))
1793 				botch("%s already seen for keyword %s",
1794 					tokname[what], sl->val);
1795 			else
1796 				botch("%s already seen", tokname[what]);
1797 			}
1798 		lastseen = what;
1799 		}
1800 	else
1801 		unexpected(tokname[what]);
1802 	}
1803 
1804  static KWctx *
lenfind(const char * s)1805 lenfind(const char *s)
1806 {
1807 	KWctx *kw, *kw0, **pkw;
1808 	StrList *sl;
1809 
1810 	kw0 = lastkw1;
1811 	for(pkw = KWtop; pkw > KWStack; --pkw) {
1812 		kw = *pkw;
1813 		for(kw = kw->kw; kw; kw = kw->next) {
1814 			for(sl = kw->names; sl; sl = sl->next)
1815 				if (!strcmp(sl->val, s))
1816 					return kw;
1817 			}
1818 		}
1819 	return 0;
1820 	}
1821 
1822  static void
alreadyseen(const char * what)1823 alreadyseen(const char *what)
1824 {
1825 	squawk("%s already given for %s", what, lastkw1->names->val);
1826 	}
1827 
1828  static int
Saw_name(const char * s)1829 Saw_name(const char *s)
1830 {
1831 	KWctx *kw;
1832 	StrList *sl;
1833 	Taghash *th;
1834 	const char *s1;
1835 	static const char notfound[] =
1836 		"keyword \"%s\" not found in this or an enclosing context";
1837 
1838 	if (lastkw1) {
1839 		switch(lastseen) {
1840 		  case Saw_dflt:
1841 			lastseen = Saw_dfltname;
1842 			lastdef = (Defhash*)DHHlookup(s, &DHTab, 1);
1843 			if (!lastkw1->defname)
1844 				lastkw1->defname = def_name(s);
1845 			else if (lastdef->value
1846 				 && ((s1 = lastkw1->init) || (s1 = lastkw1->cinit))
1847 				 && strcmp(s1, lastdef->value))
1848 					squawk("Inconsistent definitions for %s: %s and %s\n",
1849 						lastdef->hh.name, lastdef->value, s1);
1850 			return 0;
1851 		  case Saw_len:
1852 			if (lastkw1->len) {
1853 				alreadyseen("LEN");
1854 				goto ret1;
1855 				}
1856 			kw = lenfind(s);
1857 			if (!kw)
1858 				squawk(notfound,s);
1859 			else {
1860 				if ((kw->kind & KWKind_Mask) != KWKind_Int)
1861 					squawk("%s is not of type INTEGER", kw->names->val);
1862 				for(sl = kw->names; sl->next; sl = sl->next);
1863 				lastkw1->len = sl->val;
1864 				}
1865 			goto ret1;
1866 		  case Saw_group:
1867 			if (lastkw1->group)
1868 				alreadyseen("GROUP");
1869 			else
1870 				strcpy(lastkw1->group = (char*)Alloc(strlen(s)+1), s);
1871 			goto ret1;
1872 		  case Saw_tag:
1873 			if (tagin)
1874 				goto new_tag;
1875 			if (lasttag) {
1876 				alreadyseen("TAG");
1877 				goto ret1;
1878 				}
1879 			if (!tagfname && !ignoretags) {
1880 				squawk("TAG \"%s\" not found: no tag file given", s);
1881 				goto ret1;
1882 				}
1883 			th = (Taghash*)DHHlookup(s, &TagTab, ignoretags);
1884 			if (!th)
1885 				squawk("TAG \"%s\" not found in tag file \"%s\"", s, tagfname);
1886 			else {
1887 				++th->uses;
1888 				lasttag = th->hh.name;
1889 				if (!ignoretags) {
1890 					lastkw1->tag = lasttag;
1891 					tagimport(lastkw1, th->kw);
1892 					}
1893 				}
1894  ret1:
1895 			lastseen = Saw_type;
1896 			return 1;
1897 		  }
1898 		}
1899 	else if (tagin) {
1900  new_tag:
1901 		th = (Taghash*)DHHlookup(s, &TagTab, 1);
1902 		if (th->kw)
1903 			squawk("Tag \"%s\" already seen in tagfile %s\n", s, tagfname);
1904 		else
1905 			th->kw = lastkw1 = (KWctx*) Alloc(sizeof(KWctx));
1906 		goto ret1;
1907 		}
1908 	botch("unexpected name \"%s\"", s);
1909 	return 0; /* not reached */
1910 	}
1911 
1912  static void
boundalready(const char * what)1913 boundalready(const char *what)
1914 {
1915 	squawk("%s bound already given for %s", what, lastkw1->names->val);
1916 	}
1917 
1918  static void
set_lastdef(const char * s,int qkeep)1919 set_lastdef(const char *s, int qkeep)
1920 {
1921 	if (!lastdef->value) {
1922 		lastdef->value = def_name(s);
1923 		lastdef->qkeep = qkeep;
1924 		}
1925 	else if (strcmp(s, lastdef->value))
1926 		squawk("Two := values for %s: %s and %s", lastdef->hh.name,
1927 			lastdef->value, s);
1928 	}
1929 
1930  static void
Saw_num(const char * s)1931 Saw_num(const char *s)
1932 {
1933 	Defhash *ld;
1934 	double x, xa;
1935 	char *se, **sp;
1936 	int k;
1937 	static double b[3];
1938 
1939 	static char allowed[] = { Saw_dflt, Saw_dfltname, Saw_lt, Saw_le, Saw_ge, Saw_gt, 0 };
1940 
1941 	reqchk(allowed, "number");
1942 	x = strtod(s,&se);
1943 	if (*se)
1944 		botch("invalid number: \"%s\"", s);
1945 	ld = 0;
1946 	sp = 0;
1947 	switch(lastseen) {
1948 		case Saw_dflt:
1949 		case Saw_dfltname:
1950 			sp = &lastkw1->init;
1951 			lastkw1->kind |= KWKind_init;
1952 			ld = lastdef;
1953 			if ((lastkw1->kind & KWKind_Mask) == KWKind_Int)
1954 				x = x >= 0. ? floor(x) : ceil(x);
1955 			b[2] = x;
1956 			if (lastkw1->lb && x < b[0])
1957 				squawk("default value inconsistent with lower bound");
1958 			if (lastkw1->ub && x > b[1])
1959 				squawk("default value inconsistent with upper bound");
1960 			break;
1961 		case Saw_gt:
1962 		case Saw_ge:
1963 			if (lastkw1->lb) {
1964 				boundalready("lower");
1965 				goto ret;
1966 				}
1967 			if ((lastkw1->kind & KWKind_Mask) == KWKind_Int) {
1968 				xa = ceil(x);
1969 				if (xa > x) {
1970 					if (btype == KWKind_strictLb)
1971 						btype = KWKind_caneqLb;
1972 					x = xa;
1973 					}
1974 				}
1975 			sp = &lastkw1->lb;
1976 			lastkw1->kind |= btype;
1977 			b[0] = x;
1978 			if (lastkw1->ub && x >= b[1])
1979 				squawk("inconsistent bounds");
1980 			if (lastkw1->init && x > b[2])
1981 				squawk("lower bound inconsistent with default value");
1982 			break;
1983 		case Saw_le:
1984 		case Saw_lt:
1985 			if (lastkw1->ub) {
1986 				boundalready("upper");
1987 				goto ret;
1988 				}
1989 			if ((lastkw1->kind & KWKind_Mask) == KWKind_Int) {
1990 				xa = floor(x);
1991 				if (xa < x) {
1992 					if (btype == KWKind_strictUb)
1993 						btype = KWKind_caneqUb;
1994 					x = xa;
1995 					}
1996 				}
1997 			sp = &lastkw1->ub;
1998 			lastkw1->kind |= btype;
1999 			b[1] = x;
2000 			if (lastkw1->lb && x <= b[0])
2001 				squawk("inconsistent bounds");
2002 			if (lastkw1->init && x < b[2])
2003 				squawk("upper bound inconsistent with default value");
2004 			break;
2005 		default:
2006 			unexpected(s);
2007 		}
2008 	k = lastkw1->kind & KWKind_Mask;
2009 	if ((k == KWKind_Void && !tagin) || k == KWKind_Str)
2010 		squawk("cannot accept a %s value", tokname[lastseen]);
2011 	else {
2012 		strcpy(*sp = (char*)Alloc(strlen(s)+1), s);
2013 		if (ld)
2014 			set_lastdef(s, 0);
2015 		}
2016  ret:
2017 	lastseen = Saw_type;
2018 	}
2019 
2020 #define FNC 1
2021 #define VAL 2
2022 
2023 /* #line 2011 "nidrgen.c" */
2024 
2025 /* Macros after this point can all be overridden by user definitions in
2026  * section 1.
2027  */
2028 
2029 #ifndef YY_SKIP_YYWRAP
2030 #ifdef __cplusplus
2031 extern "C" int yywrap YY_PROTO(( void ));
2032 #else
2033 extern int yywrap YY_PROTO(( void ));
2034 #endif
2035 #endif
2036 
2037 #ifndef YY_NO_UNPUT
2038 static void yyunput YY_PROTO(( int c, char *buf_ptr ));
2039 #endif
2040 
2041 #ifndef yytext_ptr
2042 static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
2043 #endif
2044 
2045 #ifdef YY_NEED_STRLEN
2046 static int yy_flex_strlen YY_PROTO(( yyconst char * ));
2047 #endif
2048 
2049 #ifndef YY_NO_INPUT
2050 #ifdef __cplusplus
2051 static int yyinput YY_PROTO(( void ));
2052 #else
2053 static int input YY_PROTO(( void ));
2054 #endif
2055 #endif
2056 
2057 #if YY_STACK_USED
2058 static int yy_start_stack_ptr = 0;
2059 static int yy_start_stack_depth = 0;
2060 static int *yy_start_stack = 0;
2061 #ifndef YY_NO_PUSH_STATE
2062 static void yy_push_state YY_PROTO(( int new_state ));
2063 #endif
2064 #ifndef YY_NO_POP_STATE
2065 static void yy_pop_state YY_PROTO(( void ));
2066 #endif
2067 #ifndef YY_NO_TOP_STATE
2068 static int yy_top_state YY_PROTO(( void ));
2069 #endif
2070 
2071 #else
2072 #define YY_NO_PUSH_STATE 1
2073 #define YY_NO_POP_STATE 1
2074 #define YY_NO_TOP_STATE 1
2075 #endif
2076 
2077 #ifdef YY_MALLOC_DECL
2078 YY_MALLOC_DECL
2079 #else
2080 #if __STDC__
2081 #ifndef __cplusplus
2082 #include <stdlib.h>
2083 #endif
2084 #else
2085 /* Just try to get by without declaring the routines.  This will fail
2086  * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
2087  * or sizeof(void*) != sizeof(int).
2088  */
2089 #endif
2090 #endif
2091 
2092 /* Amount of stuff to slurp up with each read. */
2093 #ifndef YY_READ_BUF_SIZE
2094 #define YY_READ_BUF_SIZE 8192
2095 #endif
2096 
2097 /* Copy whatever the last rule matched to the standard output. */
2098 
2099 #ifndef ECHO
2100 /* This used to be an fputs(), but since the string might contain NUL's,
2101  * we now use fwrite().
2102  */
2103 #define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
2104 #endif
2105 
2106 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
2107  * is returned in "result".
2108  */
2109 #ifndef YY_INPUT
2110 #define YY_INPUT(buf,result,max_size) \
2111 	if ( yy_current_buffer->yy_is_interactive ) \
2112 		{ \
2113 		int c = '*', n; \
2114 		for ( n = 0; n < max_size && \
2115 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
2116 			buf[n] = (char) c; \
2117 		if ( c == '\n' ) \
2118 			buf[n++] = (char) c; \
2119 		if ( c == EOF && ferror( yyin ) ) \
2120 			YY_FATAL_ERROR( "input in flex scanner failed" ); \
2121 		result = n; \
2122 		} \
2123 	else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
2124 		  && ferror( yyin ) ) \
2125 		YY_FATAL_ERROR( "input in flex scanner failed" );
2126 #endif
2127 
2128 /* No semi-colon after return; correct usage is to write "yyterminate();" -
2129  * we don't want an extra ';' after the "return" because that will cause
2130  * some compilers to complain about unreachable statements.
2131  */
2132 #ifndef yyterminate
2133 #define yyterminate() return YY_NULL
2134 #endif
2135 
2136 /* Number of entries by which start-condition stack grows. */
2137 #ifndef YY_START_STACK_INCR
2138 #define YY_START_STACK_INCR 25
2139 #endif
2140 
2141 /* Report a fatal error. */
2142 #ifndef YY_FATAL_ERROR
2143 #define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
2144 #endif
2145 
2146 /* Default declaration of generated scanner - a define so the user can
2147  * easily add parameters.
2148  */
2149 #ifndef YY_DECL
2150 #define YY_DECL int yylex YY_PROTO(( void ))
2151 #endif
2152 
2153 /* Code executed at the beginning of each rule, after yytext and yyleng
2154  * have been set up.
2155  */
2156 #ifndef YY_USER_ACTION
2157 #define YY_USER_ACTION
2158 #endif
2159 
2160 /* Code executed at the end of each rule. */
2161 #ifndef YY_BREAK
2162 #define YY_BREAK break;
2163 #endif
2164 
2165 #define YY_RULE_SETUP \
2166 	YY_USER_ACTION
2167 
2168 YY_DECL
2169 	{
2170 	register yy_state_type yy_current_state;
2171 	register char *yy_cp = NULL, *yy_bp = NULL;
2172 	register int yy_act;
2173 
2174 /* #line 1528 "nidrgen.l" */
2175 
2176 
2177 /* #line 2165 "nidrgen.c" */
2178 
2179 	if ( yy_init )
2180 		{
2181 		yy_init = 0;
2182 
2183 #ifdef YY_USER_INIT
2184 		YY_USER_INIT;
2185 #endif
2186 
2187 		if ( ! yy_start )
2188 			yy_start = 1;	/* first start state */
2189 
2190 		if ( ! yyin )
2191 			yyin = stdin;
2192 
2193 		if ( ! yyout )
2194 			yyout = stdout;
2195 
2196 		if ( ! yy_current_buffer )
2197 			yy_current_buffer =
2198 				yy_create_buffer( yyin, YY_BUF_SIZE );
2199 
2200 		yy_load_buffer_state();
2201 		}
2202 
2203 	while ( 1 )		/* loops until end-of-file is reached */
2204 		{
2205 		yy_cp = yy_c_buf_p;
2206 
2207 		/* Support of yytext. */
2208 		*yy_cp = yy_hold_char;
2209 
2210 		/* yy_bp points to the position in yy_ch_buf of the start of
2211 		 * the current run.
2212 		 */
2213 		yy_bp = yy_cp;
2214 
2215 		yy_current_state = yy_start;
2216 yy_match:
2217 		do
2218 			{
2219 			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
2220 			if ( yy_accept[yy_current_state] )
2221 				{
2222 				yy_last_accepting_state = yy_current_state;
2223 				yy_last_accepting_cpos = yy_cp;
2224 				}
2225 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
2226 				{
2227 				yy_current_state = (int) yy_def[yy_current_state];
2228 				if ( yy_current_state >= 128 )
2229 					yy_c = yy_meta[(unsigned int) yy_c];
2230 				}
2231 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
2232 			++yy_cp;
2233 			}
2234 		while ( yy_base[yy_current_state] != 316 );
2235 
2236 yy_find_action:
2237 		yy_act = yy_accept[yy_current_state];
2238 		if ( yy_act == 0 )
2239 			{ /* have to back up */
2240 			yy_cp = yy_last_accepting_cpos;
2241 			yy_current_state = yy_last_accepting_state;
2242 			yy_act = yy_accept[yy_current_state];
2243 			}
2244 
2245 		YY_DO_BEFORE_ACTION;
2246 
2247 
2248 do_action:	/* This label is used only to access EOF actions. */
2249 
2250 
2251 		switch ( yy_act )
2252 	{ /* beginning of action switch */
2253 			case 0: /* must back up */
2254 			/* undo the effects of YY_DO_BEFORE_ACTION */
2255 			*yy_cp = yy_hold_char;
2256 			yy_cp = yy_last_accepting_cpos;
2257 			yy_current_state = yy_last_accepting_state;
2258 			goto yy_find_action;
2259 
2260 case 1:
2261 YY_RULE_SETUP
2262 /* #line 1530 "nidrgen.l" */
2263 { ++Lineno; }
2264 	YY_BREAK
2265 case 2:
2266 YY_RULE_SETUP
2267 /* #line 1531 "nidrgen.l" */
2268 {}
2269 	YY_BREAK
2270 case 3:
2271 YY_RULE_SETUP
2272 /* #line 1532 "nidrgen.l" */
2273 { Alias(yytext); }
2274 	YY_BREAK
2275 case 4:
2276 YY_RULE_SETUP
2277 /* #line 1533 "nidrgen.l" */
2278 { Type(KWKind_Int, yytext); }
2279 	YY_BREAK
2280 case 5:
2281 YY_RULE_SETUP
2282 /* #line 1534 "nidrgen.l" */
2283 { Type(KWKind_Int | KWKind_List, yytext); }
2284 	YY_BREAK
2285 case 6:
2286 YY_RULE_SETUP
2287 /* #line 1535 "nidrgen.l" */
2288 { kw_finish(0); }
2289 	YY_BREAK
2290 case 7:
2291 YY_RULE_SETUP
2292 /* #line 1536 "nidrgen.l" */
2293 { kw_finish(KWKind_1); }
2294 	YY_BREAK
2295 case 8:
2296 YY_RULE_SETUP
2297 /* #line 1537 "nidrgen.l" */
2298 { kw_finish(KWKind_01); }
2299 	YY_BREAK
2300 case 9:
2301 YY_RULE_SETUP
2302 /* #line 1538 "nidrgen.l" */
2303 { kw_finish(KWKind_12); }
2304 	YY_BREAK
2305 case 10:
2306 YY_RULE_SETUP
2307 /* #line 1539 "nidrgen.l" */
2308 { Type(KWKind_Str|KWKind_Libname, yytext); }
2309 	YY_BREAK
2310 case 11:
2311 YY_RULE_SETUP
2312 /* #line 1540 "nidrgen.l" */
2313 { Type(KWKind_Real, yytext); }
2314 	YY_BREAK
2315 case 12:
2316 YY_RULE_SETUP
2317 /* #line 1541 "nidrgen.l" */
2318 { Type(KWKind_Real | KWKind_List, yytext); }
2319 	YY_BREAK
2320 case 13:
2321 YY_RULE_SETUP
2322 /* #line 1542 "nidrgen.l" */
2323 { Type(KWKind_Str, yytext); }
2324 	YY_BREAK
2325 case 14:
2326 YY_RULE_SETUP
2327 /* #line 1543 "nidrgen.l" */
2328 { Type(KWKind_Str | KWKind_List, yytext); }
2329 	YY_BREAK
2330 case 15:
2331 YY_RULE_SETUP
2332 /* #line 1544 "nidrgen.l" */
2333 { Keywd(yytext); }
2334 	YY_BREAK
2335 case 16:
2336 YY_RULE_SETUP
2337 /* #line 1545 "nidrgen.l" */
2338 { kw_finish(-1); }
2339 	YY_BREAK
2340 case 17:
2341 YY_RULE_SETUP
2342 /* #line 1546 "nidrgen.l" */
2343 { Saw_stok(Saw_desc, offsetof(KWctx,desc));	BEGIN VAL; }
2344 	YY_BREAK
2345 case 18:
2346 YY_RULE_SETUP
2347 /* #line 1547 "nidrgen.l" */
2348 { Saw_stok(Saw_tag, offsetof(KWctx,tag));	BEGIN VAL; }
2349 	YY_BREAK
2350 case 19:
2351 YY_RULE_SETUP
2352 /* #line 1548 "nidrgen.l" */
2353 { Saw_stok(Saw_group, offsetof(KWctx,group));	BEGIN VAL; }
2354 	YY_BREAK
2355 case 20:
2356 YY_RULE_SETUP
2357 /* #line 1549 "nidrgen.l" */
2358 { Saw_tok(Saw_dy, offsetof(KWctx,dylib));
2359 			  dynlibseen = 1; dynline = Lineno;		BEGIN VAL; }
2360 	YY_BREAK
2361 case 21:
2362 YY_RULE_SETUP
2363 /* #line 1551 "nidrgen.l" */
2364 { Saw_stok(Saw_len, offsetof(KWctx,len));
2365 			  lastkw1->kind |= KWKind_Len1OK;		BEGIN VAL; }
2366 	YY_BREAK
2367 case 22:
2368 YY_RULE_SETUP
2369 /* #line 1553 "nidrgen.l" */
2370 { Saw_stok(Saw_len, offsetof(KWctx,len));	BEGIN VAL; }
2371 	YY_BREAK
2372 case 23:
2373 YY_RULE_SETUP
2374 /* #line 1554 "nidrgen.l" */
2375 { Saw_tok(Saw_dflt, KWKind_init); lastdef = 0;	BEGIN VAL; }
2376 	YY_BREAK
2377 case 24:
2378 YY_RULE_SETUP
2379 /* #line 1555 "nidrgen.l" */
2380 { Saw_tok(Saw_ge, KWKind_Lb); btype = KWKind_caneqLb;	BEGIN VAL; }
2381 	YY_BREAK
2382 case 25:
2383 YY_RULE_SETUP
2384 /* #line 1556 "nidrgen.l" */
2385 { Saw_tok(Saw_gt, KWKind_Lb); btype = KWKind_strictLb;	BEGIN VAL; }
2386 	YY_BREAK
2387 case 26:
2388 YY_RULE_SETUP
2389 /* #line 1557 "nidrgen.l" */
2390 { Saw_tok(Saw_le, KWKind_Ub); btype = KWKind_caneqUb;	BEGIN VAL; }
2391 	YY_BREAK
2392 case 27:
2393 YY_RULE_SETUP
2394 /* #line 1558 "nidrgen.l" */
2395 { Saw_tok(Saw_lt, KWKind_Ub); btype = KWKind_strictUb;	BEGIN VAL; }
2396 	YY_BREAK
2397 case 28:
2398 YY_RULE_SETUP
2399 /* #line 1559 "nidrgen.l" */
2400 { if (Saw_name(yytext))	BEGIN INITIAL; }
2401 	YY_BREAK
2402 case 29:
2403 YY_RULE_SETUP
2404 /* #line 1560 "nidrgen.l" */
2405 { Saw_num(yytext);	BEGIN INITIAL; }
2406 	YY_BREAK
2407 case 30:
2408 YY_RULE_SETUP
2409 /* #line 1561 "nidrgen.l" */
2410 { Saw_quote();		BEGIN INITIAL; }
2411 	YY_BREAK
2412 case 31:
2413 YY_RULE_SETUP
2414 /* #line 1563 "nidrgen.l" */
2415 { Lbrace(); BEGIN FNC; }
2416 	YY_BREAK
2417 case 32:
2418 YY_RULE_SETUP
2419 /* #line 1564 "nidrgen.l" */
2420 { Rbrace(); BEGIN INITIAL; }
2421 	YY_BREAK
2422 case 33:
2423 YY_RULE_SETUP
2424 /* #line 1565 "nidrgen.l" */
2425 { Bar(); }
2426 	YY_BREAK
2427 case 34:
2428 YY_RULE_SETUP
2429 /* #line 1566 "nidrgen.l" */
2430 { Lpar(); }
2431 	YY_BREAK
2432 case 35:
2433 YY_RULE_SETUP
2434 /* #line 1567 "nidrgen.l" */
2435 { Rpar(); }
2436 	YY_BREAK
2437 case 36:
2438 YY_RULE_SETUP
2439 /* #line 1568 "nidrgen.l" */
2440 { Lsqb(); }
2441 	YY_BREAK
2442 case 37:
2443 YY_RULE_SETUP
2444 /* #line 1569 "nidrgen.l" */
2445 { Rsqb(); }
2446 	YY_BREAK
2447 case 38:
2448 YY_RULE_SETUP
2449 /* #line 1570 "nidrgen.l" */
2450 { Fnc(yytext); }
2451 	YY_BREAK
2452 case 39:
2453 YY_RULE_SETUP
2454 /* #line 1571 "nidrgen.l" */
2455 {}
2456 	YY_BREAK
2457 case 40:
2458 YY_RULE_SETUP
2459 /* #line 1572 "nidrgen.l" */
2460 {++Lineno;}
2461 	YY_BREAK
2462 case 41:
2463 YY_RULE_SETUP
2464 /* #line 1573 "nidrgen.l" */
2465 { Eat_comment(); }
2466 	YY_BREAK
2467 case 42:
2468 YY_RULE_SETUP
2469 /* #line 1574 "nidrgen.l" */
2470 { botch("\"%s\" unexpected", yytext); }
2471 	YY_BREAK
2472 case 43:
2473 YY_RULE_SETUP
2474 /* #line 1576 "nidrgen.l" */
2475 ECHO;
2476 	YY_BREAK
2477 /* #line 2465 "nidrgen.c" */
2478 case YY_STATE_EOF(INITIAL):
2479 case YY_STATE_EOF(FNC):
2480 case YY_STATE_EOF(VAL):
2481 	yyterminate();
2482 
2483 	case YY_END_OF_BUFFER:
2484 		{
2485 		/* Amount of text matched not including the EOB char. */
2486 		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
2487 
2488 		/* Undo the effects of YY_DO_BEFORE_ACTION. */
2489 		*yy_cp = yy_hold_char;
2490 		YY_RESTORE_YY_MORE_OFFSET
2491 
2492 		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
2493 			{
2494 			/* We're scanning a new file or input source.  It's
2495 			 * possible that this happened because the user
2496 			 * just pointed yyin at a new source and called
2497 			 * yylex().  If so, then we have to assure
2498 			 * consistency between yy_current_buffer and our
2499 			 * globals.  Here is the right place to do so, because
2500 			 * this is the first action (other than possibly a
2501 			 * back-up) that will match for the new input source.
2502 			 */
2503 			yy_n_chars = yy_current_buffer->yy_n_chars;
2504 			yy_current_buffer->yy_input_file = yyin;
2505 			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
2506 			}
2507 
2508 		/* Note that here we test for yy_c_buf_p "<=" to the position
2509 		 * of the first EOB in the buffer, since yy_c_buf_p will
2510 		 * already have been incremented past the NUL character
2511 		 * (since all states make transitions on EOB to the
2512 		 * end-of-buffer state).  Contrast this with the test
2513 		 * in input().
2514 		 */
2515 		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
2516 			{ /* This was really a NUL. */
2517 			yy_state_type yy_next_state;
2518 
2519 			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
2520 
2521 			yy_current_state = yy_get_previous_state();
2522 
2523 			/* Okay, we're now positioned to make the NUL
2524 			 * transition.  We couldn't have
2525 			 * yy_get_previous_state() go ahead and do it
2526 			 * for us because it doesn't know how to deal
2527 			 * with the possibility of jamming (and we don't
2528 			 * want to build jamming into it because then it
2529 			 * will run more slowly).
2530 			 */
2531 
2532 			yy_next_state = yy_try_NUL_trans( yy_current_state );
2533 
2534 			yy_bp = yytext_ptr + YY_MORE_ADJ;
2535 
2536 			if ( yy_next_state )
2537 				{
2538 				/* Consume the NUL. */
2539 				yy_cp = ++yy_c_buf_p;
2540 				yy_current_state = yy_next_state;
2541 				goto yy_match;
2542 				}
2543 
2544 			else
2545 				{
2546 				yy_cp = yy_c_buf_p;
2547 				goto yy_find_action;
2548 				}
2549 			}
2550 
2551 		else switch ( yy_get_next_buffer() )
2552 			{
2553 			case EOB_ACT_END_OF_FILE:
2554 				{
2555 				yy_did_buffer_switch_on_eof = 0;
2556 
2557 				if ( yywrap() )
2558 					{
2559 					/* Note: because we've taken care in
2560 					 * yy_get_next_buffer() to have set up
2561 					 * yytext, we can now set up
2562 					 * yy_c_buf_p so that if some total
2563 					 * hoser (like flex itself) wants to
2564 					 * call the scanner after we return the
2565 					 * YY_NULL, it'll still work - another
2566 					 * YY_NULL will get returned.
2567 					 */
2568 					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
2569 
2570 					yy_act = YY_STATE_EOF(YY_START);
2571 					goto do_action;
2572 					}
2573 
2574 				else
2575 					{
2576 					if ( ! yy_did_buffer_switch_on_eof )
2577 						YY_NEW_FILE;
2578 					}
2579 				break;
2580 				}
2581 
2582 			case EOB_ACT_CONTINUE_SCAN:
2583 				yy_c_buf_p =
2584 					yytext_ptr + yy_amount_of_matched_text;
2585 
2586 				yy_current_state = yy_get_previous_state();
2587 
2588 				yy_cp = yy_c_buf_p;
2589 				yy_bp = yytext_ptr + YY_MORE_ADJ;
2590 				goto yy_match;
2591 
2592 			case EOB_ACT_LAST_MATCH:
2593 				yy_c_buf_p =
2594 				&yy_current_buffer->yy_ch_buf[yy_n_chars];
2595 
2596 				yy_current_state = yy_get_previous_state();
2597 
2598 				yy_cp = yy_c_buf_p;
2599 				yy_bp = yytext_ptr + YY_MORE_ADJ;
2600 				goto yy_find_action;
2601 			}
2602 		break;
2603 		}
2604 
2605 	default:
2606 		YY_FATAL_ERROR(
2607 			"fatal flex scanner internal error--no action found" );
2608 	} /* end of action switch */
2609 		} /* end of scanning one token */
2610 	} /* end of yylex */
2611 
2612 
2613 /* yy_get_next_buffer - try to read in a new buffer
2614  *
2615  * Returns a code representing an action:
2616  *	EOB_ACT_LAST_MATCH -
2617  *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
2618  *	EOB_ACT_END_OF_FILE - end of file
2619  */
2620 
yy_get_next_buffer()2621 static int yy_get_next_buffer()
2622 	{
2623 	register char *dest = yy_current_buffer->yy_ch_buf;
2624 	register char *source = yytext_ptr;
2625 	register int number_to_move, i;
2626 	int ret_val;
2627 
2628 	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
2629 		YY_FATAL_ERROR(
2630 		"fatal flex scanner internal error--end of buffer missed" );
2631 
2632 	if ( yy_current_buffer->yy_fill_buffer == 0 )
2633 		{ /* Don't try to fill the buffer, so this is an EOF. */
2634 		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
2635 			{
2636 			/* We matched a single character, the EOB, so
2637 			 * treat this as a final EOF.
2638 			 */
2639 			return EOB_ACT_END_OF_FILE;
2640 			}
2641 
2642 		else
2643 			{
2644 			/* We matched some text prior to the EOB, first
2645 			 * process it.
2646 			 */
2647 			return EOB_ACT_LAST_MATCH;
2648 			}
2649 		}
2650 
2651 	/* Try to read more data. */
2652 
2653 	/* First move last chars to start of buffer. */
2654 	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
2655 
2656 	for ( i = 0; i < number_to_move; ++i )
2657 		*(dest++) = *(source++);
2658 
2659 	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
2660 		/* don't do the read, it's not guaranteed to return an EOF,
2661 		 * just force an EOF
2662 		 */
2663 		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
2664 
2665 	else
2666 		{
2667 		int num_to_read =
2668 			yy_current_buffer->yy_buf_size - number_to_move - 1;
2669 
2670 		while ( num_to_read <= 0 )
2671 			{ /* Not enough room in the buffer - grow it. */
2672 #ifdef YY_USES_REJECT
2673 			YY_FATAL_ERROR(
2674 "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
2675 #else
2676 
2677 			/* just a shorter name for the current buffer */
2678 			YY_BUFFER_STATE b = yy_current_buffer;
2679 
2680 			int yy_c_buf_p_offset =
2681 				(int) (yy_c_buf_p - b->yy_ch_buf);
2682 
2683 			if ( b->yy_is_our_buffer )
2684 				{
2685 				int new_size = b->yy_buf_size * 2;
2686 
2687 				if ( new_size <= 0 )
2688 					b->yy_buf_size += b->yy_buf_size / 8;
2689 				else
2690 					b->yy_buf_size *= 2;
2691 
2692 				b->yy_ch_buf = (char *)
2693 					/* Include room in for 2 EOB chars. */
2694 					yy_flex_realloc( (void *) b->yy_ch_buf,
2695 							 b->yy_buf_size + 2 );
2696 				}
2697 			else
2698 				/* Can't grow it, we don't own it. */
2699 				b->yy_ch_buf = 0;
2700 
2701 			if ( ! b->yy_ch_buf )
2702 				YY_FATAL_ERROR(
2703 				"fatal error - scanner input buffer overflow" );
2704 
2705 			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
2706 
2707 			num_to_read = yy_current_buffer->yy_buf_size -
2708 						number_to_move - 1;
2709 #endif
2710 			}
2711 
2712 		if ( num_to_read > YY_READ_BUF_SIZE )
2713 			num_to_read = YY_READ_BUF_SIZE;
2714 
2715 		/* Read in more data. */
2716 		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
2717 			yy_n_chars, num_to_read );
2718 
2719 		yy_current_buffer->yy_n_chars = yy_n_chars;
2720 		}
2721 
2722 	if ( yy_n_chars == 0 )
2723 		{
2724 		if ( number_to_move == YY_MORE_ADJ )
2725 			{
2726 			ret_val = EOB_ACT_END_OF_FILE;
2727 			yyrestart( yyin );
2728 			}
2729 
2730 		else
2731 			{
2732 			ret_val = EOB_ACT_LAST_MATCH;
2733 			yy_current_buffer->yy_buffer_status =
2734 				YY_BUFFER_EOF_PENDING;
2735 			}
2736 		}
2737 
2738 	else
2739 		ret_val = EOB_ACT_CONTINUE_SCAN;
2740 
2741 	yy_n_chars += number_to_move;
2742 	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
2743 	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
2744 
2745 	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
2746 
2747 	return ret_val;
2748 	}
2749 
2750 
2751 /* yy_get_previous_state - get the state just before the EOB char was reached */
2752 
yy_get_previous_state()2753 static yy_state_type yy_get_previous_state()
2754 	{
2755 	register yy_state_type yy_current_state;
2756 	register char *yy_cp;
2757 
2758 	yy_current_state = yy_start;
2759 
2760 	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
2761 		{
2762 		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
2763 		if ( yy_accept[yy_current_state] )
2764 			{
2765 			yy_last_accepting_state = yy_current_state;
2766 			yy_last_accepting_cpos = yy_cp;
2767 			}
2768 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
2769 			{
2770 			yy_current_state = (int) yy_def[yy_current_state];
2771 			if ( yy_current_state >= 128 )
2772 				yy_c = yy_meta[(unsigned int) yy_c];
2773 			}
2774 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
2775 		}
2776 
2777 	return yy_current_state;
2778 	}
2779 
2780 
2781 /* yy_try_NUL_trans - try to make a transition on the NUL character
2782  *
2783  * synopsis
2784  *	next_state = yy_try_NUL_trans( current_state );
2785  */
2786 
2787 #ifdef YY_USE_PROTOS
yy_try_NUL_trans(yy_state_type yy_current_state)2788 static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
2789 #else
2790 static yy_state_type yy_try_NUL_trans( yy_current_state )
2791 yy_state_type yy_current_state;
2792 #endif
2793 	{
2794 	register int yy_is_jam;
2795 	register char *yy_cp = yy_c_buf_p;
2796 
2797 	register YY_CHAR yy_c = 1;
2798 	if ( yy_accept[yy_current_state] )
2799 		{
2800 		yy_last_accepting_state = yy_current_state;
2801 		yy_last_accepting_cpos = yy_cp;
2802 		}
2803 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
2804 		{
2805 		yy_current_state = (int) yy_def[yy_current_state];
2806 		if ( yy_current_state >= 128 )
2807 			yy_c = yy_meta[(unsigned int) yy_c];
2808 		}
2809 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
2810 	yy_is_jam = (yy_current_state == 127);
2811 
2812 	return yy_is_jam ? 0 : yy_current_state;
2813 	}
2814 
2815 
2816 #ifndef YY_NO_UNPUT
2817 #ifdef YY_USE_PROTOS
yyunput(int c,register char * yy_bp)2818 static void yyunput( int c, register char *yy_bp )
2819 #else
2820 static void yyunput( c, yy_bp )
2821 int c;
2822 register char *yy_bp;
2823 #endif
2824 	{
2825 	register char *yy_cp = yy_c_buf_p;
2826 
2827 	/* undo effects of setting up yytext */
2828 	*yy_cp = yy_hold_char;
2829 
2830 	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
2831 		{ /* need to shift things up to make room */
2832 		/* +2 for EOB chars. */
2833 		register int number_to_move = yy_n_chars + 2;
2834 		register char *dest = &yy_current_buffer->yy_ch_buf[
2835 					yy_current_buffer->yy_buf_size + 2];
2836 		register char *source =
2837 				&yy_current_buffer->yy_ch_buf[number_to_move];
2838 
2839 		while ( source > yy_current_buffer->yy_ch_buf )
2840 			*--dest = *--source;
2841 
2842 		yy_cp += (int) (dest - source);
2843 		yy_bp += (int) (dest - source);
2844 		yy_current_buffer->yy_n_chars =
2845 			yy_n_chars = yy_current_buffer->yy_buf_size;
2846 
2847 		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
2848 			YY_FATAL_ERROR( "flex scanner push-back overflow" );
2849 		}
2850 
2851 	*--yy_cp = (char) c;
2852 
2853 
2854 	yytext_ptr = yy_bp;
2855 	yy_hold_char = *yy_cp;
2856 	yy_c_buf_p = yy_cp;
2857 	}
2858 #endif	/* ifndef YY_NO_UNPUT */
2859 
2860 
2861 #ifndef YY_NO_INPUT
2862 #ifdef __cplusplus
yyinput()2863 static int yyinput()
2864 #else
2865 static int input()
2866 #endif
2867 	{
2868 	int c;
2869 
2870 	*yy_c_buf_p = yy_hold_char;
2871 
2872 	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
2873 		{
2874 		/* yy_c_buf_p now points to the character we want to return.
2875 		 * If this occurs *before* the EOB characters, then it's a
2876 		 * valid NUL; if not, then we've hit the end of the buffer.
2877 		 */
2878 		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
2879 			/* This was really a NUL. */
2880 			*yy_c_buf_p = '\0';
2881 
2882 		else
2883 			{ /* need more input */
2884 			int offset = yy_c_buf_p - yytext_ptr;
2885 			++yy_c_buf_p;
2886 
2887 			switch ( yy_get_next_buffer() )
2888 				{
2889 				case EOB_ACT_LAST_MATCH:
2890 					/* This happens because yy_g_n_b()
2891 					 * sees that we've accumulated a
2892 					 * token and flags that we need to
2893 					 * try matching the token before
2894 					 * proceeding.  But for input(),
2895 					 * there's no matching to consider.
2896 					 * So convert the EOB_ACT_LAST_MATCH
2897 					 * to EOB_ACT_END_OF_FILE.
2898 					 */
2899 
2900 					/* Reset buffer status. */
2901 					yyrestart( yyin );
2902 
2903 					/* fall through */
2904 
2905 				case EOB_ACT_END_OF_FILE:
2906 					{
2907 					if ( yywrap() )
2908 						return EOF;
2909 
2910 					if ( ! yy_did_buffer_switch_on_eof )
2911 						YY_NEW_FILE;
2912 #ifdef __cplusplus
2913 					return yyinput();
2914 #else
2915 					return input();
2916 #endif
2917 					}
2918 
2919 				case EOB_ACT_CONTINUE_SCAN:
2920 					yy_c_buf_p = yytext_ptr + offset;
2921 					break;
2922 				}
2923 			}
2924 		}
2925 
2926 	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
2927 	*yy_c_buf_p = '\0';	/* preserve yytext */
2928 	yy_hold_char = *++yy_c_buf_p;
2929 
2930 
2931 	return c;
2932 	}
2933 #endif /* YY_NO_INPUT */
2934 
2935 #ifdef YY_USE_PROTOS
yyrestart(FILE * input_file)2936 void yyrestart( FILE *input_file )
2937 #else
2938 void yyrestart( input_file )
2939 FILE *input_file;
2940 #endif
2941 	{
2942 	if ( ! yy_current_buffer )
2943 		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
2944 
2945 	yy_init_buffer( yy_current_buffer, input_file );
2946 	yy_load_buffer_state();
2947 	}
2948 
2949 
2950 #ifdef YY_USE_PROTOS
yy_switch_to_buffer(YY_BUFFER_STATE new_buffer)2951 void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
2952 #else
2953 void yy_switch_to_buffer( new_buffer )
2954 YY_BUFFER_STATE new_buffer;
2955 #endif
2956 	{
2957 	if ( yy_current_buffer == new_buffer )
2958 		return;
2959 
2960 	if ( yy_current_buffer )
2961 		{
2962 		/* Flush out information for old buffer. */
2963 		*yy_c_buf_p = yy_hold_char;
2964 		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
2965 		yy_current_buffer->yy_n_chars = yy_n_chars;
2966 		}
2967 
2968 	yy_current_buffer = new_buffer;
2969 	yy_load_buffer_state();
2970 
2971 	/* We don't actually know whether we did this switch during
2972 	 * EOF (yywrap()) processing, but the only time this flag
2973 	 * is looked at is after yywrap() is called, so it's safe
2974 	 * to go ahead and always set it.
2975 	 */
2976 	yy_did_buffer_switch_on_eof = 1;
2977 	}
2978 
2979 
2980 #ifdef YY_USE_PROTOS
yy_load_buffer_state(void)2981 void yy_load_buffer_state( void )
2982 #else
2983 void yy_load_buffer_state()
2984 #endif
2985 	{
2986 	yy_n_chars = yy_current_buffer->yy_n_chars;
2987 	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
2988 	yyin = yy_current_buffer->yy_input_file;
2989 	yy_hold_char = *yy_c_buf_p;
2990 	}
2991 
2992 
2993 #ifdef YY_USE_PROTOS
yy_create_buffer(FILE * file,int size)2994 YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
2995 #else
2996 YY_BUFFER_STATE yy_create_buffer( file, size )
2997 FILE *file;
2998 int size;
2999 #endif
3000 	{
3001 	YY_BUFFER_STATE b;
3002 
3003 	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
3004 	if ( ! b )
3005 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
3006 
3007 	b->yy_buf_size = size;
3008 
3009 	/* yy_ch_buf has to be 2 characters longer than the size given because
3010 	 * we need to put in 2 end-of-buffer characters.
3011 	 */
3012 	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
3013 	if ( ! b->yy_ch_buf )
3014 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
3015 
3016 	b->yy_is_our_buffer = 1;
3017 
3018 	yy_init_buffer( b, file );
3019 
3020 	return b;
3021 	}
3022 
3023 
3024 #ifdef YY_USE_PROTOS
yy_delete_buffer(YY_BUFFER_STATE b)3025 void yy_delete_buffer( YY_BUFFER_STATE b )
3026 #else
3027 void yy_delete_buffer( b )
3028 YY_BUFFER_STATE b;
3029 #endif
3030 	{
3031 	if ( ! b )
3032 		return;
3033 
3034 	if ( b == yy_current_buffer )
3035 		yy_current_buffer = (YY_BUFFER_STATE) 0;
3036 
3037 	if ( b->yy_is_our_buffer )
3038 		yy_flex_free( (void *) b->yy_ch_buf );
3039 
3040 	yy_flex_free( (void *) b );
3041 	}
3042 
3043 
3044 
3045 #ifdef YY_USE_PROTOS
yy_init_buffer(YY_BUFFER_STATE b,FILE * file)3046 void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
3047 #else
3048 void yy_init_buffer( b, file )
3049 YY_BUFFER_STATE b;
3050 FILE *file;
3051 #endif
3052 
3053 
3054 	{
3055 	yy_flush_buffer( b );
3056 
3057 	b->yy_input_file = file;
3058 	b->yy_fill_buffer = 1;
3059 
3060 #if YY_ALWAYS_INTERACTIVE
3061 	b->yy_is_interactive = 1;
3062 #else
3063 #if YY_NEVER_INTERACTIVE
3064 	b->yy_is_interactive = 0;
3065 #else
3066 	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
3067 #endif
3068 #endif
3069 	}
3070 
3071 
3072 #ifdef YY_USE_PROTOS
yy_flush_buffer(YY_BUFFER_STATE b)3073 void yy_flush_buffer( YY_BUFFER_STATE b )
3074 #else
3075 void yy_flush_buffer( b )
3076 YY_BUFFER_STATE b;
3077 #endif
3078 
3079 	{
3080 	if ( ! b )
3081 		return;
3082 
3083 	b->yy_n_chars = 0;
3084 
3085 	/* We always need two end-of-buffer characters.  The first causes
3086 	 * a transition to the end-of-buffer state.  The second causes
3087 	 * a jam in that state.
3088 	 */
3089 	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
3090 	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
3091 
3092 	b->yy_buf_pos = &b->yy_ch_buf[0];
3093 
3094 	b->yy_at_bol = 1;
3095 	b->yy_buffer_status = YY_BUFFER_NEW;
3096 
3097 	if ( b == yy_current_buffer )
3098 		yy_load_buffer_state();
3099 	}
3100 
3101 
3102 #ifndef YY_NO_SCAN_BUFFER
3103 #ifdef YY_USE_PROTOS
yy_scan_buffer(char * base,yy_size_t size)3104 YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
3105 #else
3106 YY_BUFFER_STATE yy_scan_buffer( base, size )
3107 char *base;
3108 yy_size_t size;
3109 #endif
3110 	{
3111 	YY_BUFFER_STATE b;
3112 
3113 	if ( size < 2 ||
3114 	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
3115 	     base[size-1] != YY_END_OF_BUFFER_CHAR )
3116 		/* They forgot to leave room for the EOB's. */
3117 		return 0;
3118 
3119 	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
3120 	if ( ! b )
3121 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
3122 
3123 	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
3124 	b->yy_buf_pos = b->yy_ch_buf = base;
3125 	b->yy_is_our_buffer = 0;
3126 	b->yy_input_file = 0;
3127 	b->yy_n_chars = b->yy_buf_size;
3128 	b->yy_is_interactive = 0;
3129 	b->yy_at_bol = 1;
3130 	b->yy_fill_buffer = 0;
3131 	b->yy_buffer_status = YY_BUFFER_NEW;
3132 
3133 	yy_switch_to_buffer( b );
3134 
3135 	return b;
3136 	}
3137 #endif
3138 
3139 
3140 #ifndef YY_NO_SCAN_STRING
3141 #ifdef YY_USE_PROTOS
yy_scan_string(yyconst char * yy_str)3142 YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
3143 #else
3144 YY_BUFFER_STATE yy_scan_string( yy_str )
3145 yyconst char *yy_str;
3146 #endif
3147 	{
3148 	int len;
3149 	for ( len = 0; yy_str[len]; ++len )
3150 		;
3151 
3152 	return yy_scan_bytes( yy_str, len );
3153 	}
3154 #endif
3155 
3156 
3157 #ifndef YY_NO_SCAN_BYTES
3158 #ifdef YY_USE_PROTOS
yy_scan_bytes(yyconst char * bytes,int len)3159 YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
3160 #else
3161 YY_BUFFER_STATE yy_scan_bytes( bytes, len )
3162 yyconst char *bytes;
3163 int len;
3164 #endif
3165 	{
3166 	YY_BUFFER_STATE b;
3167 	char *buf;
3168 	yy_size_t n;
3169 	int i;
3170 
3171 	/* Get memory for full buffer, including space for trailing EOB's. */
3172 	n = len + 2;
3173 	buf = (char *) yy_flex_alloc( n );
3174 	if ( ! buf )
3175 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
3176 
3177 	for ( i = 0; i < len; ++i )
3178 		buf[i] = bytes[i];
3179 
3180 	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
3181 
3182 	b = yy_scan_buffer( buf, n );
3183 	if ( ! b )
3184 		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
3185 
3186 	/* It's okay to grow etc. this buffer, and we should throw it
3187 	 * away when we're done.
3188 	 */
3189 	b->yy_is_our_buffer = 1;
3190 
3191 	return b;
3192 	}
3193 #endif
3194 
3195 
3196 #ifndef YY_NO_PUSH_STATE
3197 #ifdef YY_USE_PROTOS
yy_push_state(int new_state)3198 static void yy_push_state( int new_state )
3199 #else
3200 static void yy_push_state( new_state )
3201 int new_state;
3202 #endif
3203 	{
3204 	if ( yy_start_stack_ptr >= yy_start_stack_depth )
3205 		{
3206 		yy_size_t new_size;
3207 
3208 		yy_start_stack_depth += YY_START_STACK_INCR;
3209 		new_size = yy_start_stack_depth * sizeof( int );
3210 
3211 		if ( ! yy_start_stack )
3212 			yy_start_stack = (int *) yy_flex_alloc( new_size );
3213 
3214 		else
3215 			yy_start_stack = (int *) yy_flex_realloc(
3216 					(void *) yy_start_stack, new_size );
3217 
3218 		if ( ! yy_start_stack )
3219 			YY_FATAL_ERROR(
3220 			"out of memory expanding start-condition stack" );
3221 		}
3222 
3223 	yy_start_stack[yy_start_stack_ptr++] = YY_START;
3224 
3225 	BEGIN(new_state);
3226 	}
3227 #endif
3228 
3229 
3230 #ifndef YY_NO_POP_STATE
yy_pop_state()3231 static void yy_pop_state()
3232 	{
3233 	if ( --yy_start_stack_ptr < 0 )
3234 		YY_FATAL_ERROR( "start-condition stack underflow" );
3235 
3236 	BEGIN(yy_start_stack[yy_start_stack_ptr]);
3237 	}
3238 #endif
3239 
3240 
3241 #ifndef YY_NO_TOP_STATE
yy_top_state()3242 static int yy_top_state()
3243 	{
3244 	return yy_start_stack[yy_start_stack_ptr - 1];
3245 	}
3246 #endif
3247 
3248 #ifndef YY_EXIT_FAILURE
3249 #define YY_EXIT_FAILURE 2
3250 #endif
3251 
3252 #ifdef YY_USE_PROTOS
yy_fatal_error(yyconst char msg[])3253 static void yy_fatal_error( yyconst char msg[] )
3254 #else
3255 static void yy_fatal_error( msg )
3256 char msg[];
3257 #endif
3258 	{
3259 	(void) fprintf( stderr, "%s\n", msg );
3260 	exit( YY_EXIT_FAILURE );
3261 	}
3262 
3263 
3264 
3265 /* Redefine yyless() so it works in section 3 code. */
3266 
3267 #undef yyless
3268 #define yyless(n) \
3269 	do \
3270 		{ \
3271 		/* Undo effects of setting up yytext. */ \
3272 		yytext[yyleng] = yy_hold_char; \
3273 		yy_c_buf_p = yytext + n; \
3274 		yy_hold_char = *yy_c_buf_p; \
3275 		*yy_c_buf_p = '\0'; \
3276 		yyleng = n; \
3277 		} \
3278 	while ( 0 )
3279 
3280 
3281 /* Internal utility routines. */
3282 
3283 #ifndef yytext_ptr
3284 #ifdef YY_USE_PROTOS
yy_flex_strncpy(char * s1,yyconst char * s2,int n)3285 static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
3286 #else
3287 static void yy_flex_strncpy( s1, s2, n )
3288 char *s1;
3289 yyconst char *s2;
3290 int n;
3291 #endif
3292 	{
3293 	register int i;
3294 	for ( i = 0; i < n; ++i )
3295 		s1[i] = s2[i];
3296 	}
3297 #endif
3298 
3299 #ifdef YY_NEED_STRLEN
3300 #ifdef YY_USE_PROTOS
yy_flex_strlen(yyconst char * s)3301 static int yy_flex_strlen( yyconst char *s )
3302 #else
3303 static int yy_flex_strlen( s )
3304 yyconst char *s;
3305 #endif
3306 	{
3307 	register int n;
3308 	for ( n = 0; s[n]; ++n )
3309 		;
3310 
3311 	return n;
3312 	}
3313 #endif
3314 
3315 
3316 #ifdef YY_USE_PROTOS
yy_flex_alloc(yy_size_t size)3317 static void *yy_flex_alloc( yy_size_t size )
3318 #else
3319 static void *yy_flex_alloc( size )
3320 yy_size_t size;
3321 #endif
3322 	{
3323 	return (void *) malloc( size );
3324 	}
3325 
3326 #ifdef YY_USE_PROTOS
yy_flex_realloc(void * ptr,yy_size_t size)3327 static void *yy_flex_realloc( void *ptr, yy_size_t size )
3328 #else
3329 static void *yy_flex_realloc( ptr, size )
3330 void *ptr;
3331 yy_size_t size;
3332 #endif
3333 	{
3334 	/* The cast to (char *) in the following accommodates both
3335 	 * implementations that use char* generic pointers, and those
3336 	 * that use void* generic pointers.  It works with the latter
3337 	 * because both ANSI C and C++ allow castless assignment from
3338 	 * any pointer type to void*, and deal with argument conversions
3339 	 * as though doing an assignment.
3340 	 */
3341 	return (void *) realloc( (char *) ptr, size );
3342 	}
3343 
3344 #ifdef YY_USE_PROTOS
yy_flex_free(void * ptr)3345 static void yy_flex_free( void *ptr )
3346 #else
3347 static void yy_flex_free( ptr )
3348 void *ptr;
3349 #endif
3350 	{
3351 	free( ptr );
3352 	}
3353 
3354 #if YY_MAIN
main()3355 int main()
3356 	{
3357 	yylex();
3358 	return 0;
3359 	}
3360 #endif
3361 /* #line 1576 "nidrgen.l" */
3362 
3363 
3364  static void
cantopen(char * what)3365 cantopen(char *what)
3366 { fprintf(stderr, "%s: cannot open \"%s\"\n", progname, what); }
3367 
3368  int
yywrap(void)3369 yywrap(void)
3370 {
3371 	if (tagin) {
3372 		if (tagin != stdin)
3373 			fclose(tagin);
3374 		tagin = 0;
3375 		Lineno = 1;
3376 		saweof = 1;
3377 		if (*specfile == '-' && !specfile[1]) {
3378 			yyin = stdin;
3379 			infname = 0;
3380 			return 0;
3381 			}
3382 		if ((yyin = fopen(infname = specfile, "r")))
3383 			return 0;
3384 		cantopen(specfile);
3385 		exit(1);
3386 		}
3387 	return 1;
3388 	}
3389 
3390  static void
Eat_comment(void)3391 Eat_comment(void)
3392 {
3393 	int c;
3394 
3395 	for(;;) {
3396 		c = input();
3397  c_check:
3398 		if (c == EOF)
3399 			botch("EOF within /* comment */");
3400 		if (c == '*') {
3401 			c = input();
3402 			if (c == '/')
3403 				return;
3404 			goto c_check;
3405 			}
3406 		if (c == '\n')
3407 			++Lineno;
3408 		}
3409 	}
3410 
3411  static void
Saw_quote(void)3412 Saw_quote(void)
3413 {
3414 	KWctx *kw, *kw1, *kw2;
3415 	char buf[1024];
3416 	char *b, *b0, *be, *lname;
3417 	int c, c0;
3418 	size_t L, L0, L1;
3419 	unsigned char *us;
3420 
3421 	static char escname[32];
3422 	static char hexdig[16] = "0123456789abcdef";
3423 	static unsigned char esetup[] = "\aa\bb\ff\nn\rr\tt\vv";
3424 
3425 	if (!escname['\a'])
3426 		for(us = esetup; *us; us += 2)
3427 			escname[*us] = us[1];	/* assuming ASCII */
3428 	b0 = b = buf;
3429 	L = sizeof(buf);
3430 	be = b + L - 3;	/* allow room for /xhh */
3431 	c0 = 0;
3432 	saweof = 0;
3433 	for(;;) {
3434 		c = input();
3435 		if (c == EOF)
3436 			botch("EOF within quoted string");
3437 		if (b >= be) {
3438 			L1 = b - b0;
3439 			L0 = L;
3440 			L <<= 1;
3441 			be = (char*)Malloc(L, "Saw_quote");
3442 			memcpy(be, b0, L1);
3443 			if (b0 != buf)
3444 				free(b0);
3445 			b0 = be;
3446 			b = b0 + L1;
3447 			be = b0 + L - 3;
3448 			}
3449 		if (c < ' ') {
3450 			*b++ = '\\';
3451 			if (escname[c]) {
3452 				if (c == '\n')
3453 					++Lineno;
3454 				c = escname[c];
3455 				}
3456 			else {
3457 				*b++ = 'x';
3458 				*b++ = '0' + (c >> 4);
3459 				c = hexdig[c & 0xf];
3460 				}
3461 			}
3462 		*b++ = c;
3463 		if (c0 == '\\')
3464 			c0 = 0;
3465 		else {
3466 			c0 = c;
3467 			if (c == '"') {
3468 				while((c = input()) <= ' ') {
3469 					if (c == EOF || !c) {
3470 						c = ';';
3471 						break;
3472 						}
3473 					if (c == '\n')
3474 						++Lineno;
3475 					}
3476 				if (c == '"' && !saweof) {
3477 					--b;
3478 					continue;
3479 					}
3480 				unput(c);
3481 				break;
3482 				}
3483 			}
3484 		}
3485 	b[-1] = 0;	/* replacing " */
3486 	if (lastseen == Saw_tag) {
3487 		if (saweof) /* kludge around poor flex design */ {
3488 			tagin = stdin;
3489 			Saw_name(b0);
3490 			tagin = 0;
3491 			}
3492 		else
3493 			Saw_name(b0);
3494 		}
3495 	else {
3496 		L = b - b0;
3497 		be = (char*)Alloc(L);
3498 		memcpy(be, b0, L);
3499 		switch(lastseen) {
3500 		  case Saw_dflt:
3501 		  case Saw_dfltname:
3502 			if ((lastkw1->kind & KWKind_Mask) != KWKind_Str)
3503 				botch("%s cannot have a string-valued := value",
3504 					lastkw1->names->val);
3505 			lastkw1->cinit = be;
3506 			if (lastdef)
3507 				set_lastdef(b0, 1);
3508 			break;
3509 		  case Saw_desc:
3510 			lastkw1->desc = be;
3511 			break;
3512 		  case Saw_dy:
3513 			lastkw1->dylib = be;
3514 			if (lastkw1->nfcn > 0)
3515 				funcbotch(lastkw1);
3516 			if (libexpand) {
3517 				kw = *KWtop;
3518 				lastseen = Saw_kwname;
3519 				if (kw == lastkw1)
3520 					kw = *--KWtop;
3521 				else if ((kw2 = kw->rparent))
3522 					kw = kw2;
3523 				kw1 = lastkw1;
3524 				if ((kw2 = kw->kw) == kw1) {
3525 					if ((kw2 = kw->kw = kw2->next)
3526 					 && kw2->alt == kw1->alt)
3527 						Bar();
3528 					else  {
3529 						--kw->alt;
3530 						if (kw1->req)
3531 							--kw->nreq;
3532 						}
3533 					}
3534 				Lpar();
3535 				Keywd(kw1->name1);
3536 				lname = kw1->dylib;
3537 				if (lib_read(kw1,0))
3538 					lastkw1->dylib = lname;
3539 				Rpar();
3540 				if (kw1->parstate == PPar_leftpar)
3541 					++KWtop;
3542 				}
3543 			break;
3544 		  case Saw_group:
3545 			lastkw1->group = be;
3546 			break;
3547 		  default:
3548 			unexpected("string");
3549 		  }
3550 		}
3551 	if (b0 != buf)
3552 		free(b0);
3553 	lastseen = Saw_type;
3554 	}
3555 
3556  static int
usage(int rc)3557 usage(int rc)
3558 {
3559 	fprintf(rc ? stderr : stdout,
3560 	"Usage: %s [options] specfile [tagfile [defs_out [keywds_out]]]\n\
3561 	where the last two are output files, \".\" means \"omit\", and \"-\"\n\
3562 	means write to stdout.  Missing trailing arguments are not read\n\
3563 	or written, except that if all outputs are missing, \". -\" is assumed.\n\
3564 	Options may modify this behavior.\noptions:\n\
3565 	-D		{ just write definitions to stdout }\n\
3566 	-d		{ suppress test for ambiguity from duplicate keywords }\n\
3567 	-e		{ expand ((...)) for debugging }\n\
3568 	-f		{ omit functions, i.e., {...} with -p; without -p,\n\
3569 			  supply NULL function pointers }\n\
3570 	-G		{ for keywords with a TAG but not GROUP, do not assume\n\
3571 			  that implictly GROUP == TAG }\n\
3572 	-g		{ write GuiKeyWord rather than KeyWord header;\n\
3573 			  with -p, include GUI details: TAG, DESC, GROUP, LEN }\n\
3574 	-h headername	{ Specify header file(s), e.g., \"-h nidr.h\";\n\
3575 			  several -h options can be given;\n\
3576 			  default = -h- ==> no headers }\n\
3577 	-j specsum	{ write file specsum for use by \"dakreord specsum ...\"\n\
3578 			  and \"dakreorder -j specsum ...\" }\n\
3579 	-k keyname	{ library mode with input containing several keywords\n\
3580 			  to be contained in keyword keyname; implies -l and\n\
3581 			  has no other effect if -D, -g, -j, -p, or -s is given.\n\
3582 			  If -l is given without -k and several keywords appear\n\
3583 			  in the input, assume \"-k KeywordTop\". }\n\
3584 	-L libname	{ obtain keyword details from library libname (compiled\n\
3585 			  from source produced by an earlier \"nidrgen -l ...\"\n\
3586 			  invocation); non-option arguments in this case are\n\
3587 			  [defs_out [keywds_out]] }\n\
3588 	-l		{ library mode: with -D, -g, -j, -p, or -s, attempt to\n\
3589 			  load libraries specified with \"DYNLIB libname\" and\n\
3590 			  incorporate keyword specifications provided by the\n\
3591 			  loaded libraries; otherwise generate source for\n\
3592 			  compilation into a shared library for loading when a\n\
3593 			  keyword marked with \"DYNLIB libname\" (in a separate\n\
3594 			  run of nidrgen) is seen.  The library provides\n\
3595 			  contained keywords and any needed final routine for\n\
3596 			  the marked keyword. }\n\
3597 	-m mtagfile	{ just write to mtagfile tags not found in tagfile }\n\
3598 	-n namespname	{ assume namespace namespname;\n\
3599 			  default = -n Dakota\n\
3600 			  -n- ==> no namespace }\n\
3601 	-p[w]		{ pretty-print rather than produce KeyWord header;\n\
3602 			  add w spaces (default 2) for each nested context. }\n\
3603 	-s[w]		{ like -p[w], but sort the keywords }\n\
3604 	-T outtagfile	{ write dummy tagfile to outtagfile (and quit) }\n\
3605 	-t		{ ignore TAG fields if tagfile is not given }\n\
3606 	-w		{ cancel warn mode: do not report (on stderr)\n\
3607 			  the number of implicitly named start routines;\n\
3608 			  still flag their names  with /*!!*/ }\n",
3609 		progname);
3610 	return rc;
3611 	}
3612 
3613  static StrList *
reverse(StrList ** x)3614 reverse(StrList **x)
3615 {
3616 	StrList *s, *t, *u;
3617 
3618 	if (!(s = *x) || !s->next)
3619 		return s;
3620 	for(t = 0; s; s = u) {
3621 		u = s->next;
3622 		s->next = t;
3623 		t = s;
3624 		}
3625 	return *x = t;
3626 	}
3627 
3628  static int
kwcomp(const void * a,const void * b)3629 kwcomp(const void *a, const void *b)
3630 {
3631 	return strcmp((*(const KWctx**)a)->names->val, (*(const KWctx**)b)->names->val);
3632 	}
3633 
3634  static KWctx *
kwsort(KWctx * kw0)3635 kwsort(KWctx *kw0)
3636 {
3637 	/* Sort keywords after expanding kw list with aliases; compute nkw, */
3638 	/* including aliases. */
3639 
3640 	KWctx *kw, *kw1, *kw2, *kwm, **x, **x0, **xe, *x00[512];
3641 	StrList *dname, *minname, *nam, **pmin, **pnam;
3642 	char *descsave, *groupsave;
3643 	int agadj, nk;
3644 	size_t L, nkw, nkwa, onkwa;
3645 
3646 	reverse(&kw0->funcs);
3647 	nkw = nkwa = 0;
3648 	for(kw = kw0->kw; kw; kw = kw->next) {
3649 		++nkw;
3650 		pmin = &kw->names;
3651 		minname = *pmin;
3652 		pnam = &minname->next;
3653 		onkwa = nkwa;
3654 		while((nam = *pnam)) {
3655 			dname = nam;
3656 			++nkwa;
3657 			if (strcmp(nam->val, minname->val) < 0) {
3658 				pmin = pnam;
3659 				minname = nam;
3660 				}
3661 			pnam = &nam->next;
3662 			}
3663 		agadj = 2*kw->agroup;
3664 		kw->agroup = agadj + 1;
3665 		if (nkwa > onkwa) {
3666 			*pmin = minname->next;
3667 			minname->next = kw->names;
3668 			nam = kw->names = minname;
3669 			nk = kw->kno;	/* ALias() made room for nk use below */
3670 			descsave = kw->desc;
3671 			groupsave = kw->group;
3672 			if (dname != minname) {
3673 				kw->desc = kw->group = 0;
3674 				kw->agroup = agadj;
3675 				}
3676 			kwm = kw;
3677 			kw = kw2 = 0;
3678 			if (nam->primary)
3679 				kw2 = kwm;
3680 			while((nam = nam->next)) {
3681 				kw1 = (KWctx*)Alloc(sizeof(KWctx));
3682 				if (!kw)
3683 					kw = kw1;	/* so kw->next is right */
3684 				kw1->next = kwm->next;
3685 				kwm->next = kw1;
3686 				kw1->names = nam;
3687 				kw1->master = kwm;
3688 				kw1->kind = kwm->kind;
3689 				kw1->kno = ++nk;
3690 				kw1->agroup = agadj;
3691 				if (nam == dname) {
3692 					kw1->desc = descsave;
3693 					kw1->group = groupsave;
3694 					kw1->agroup = agadj + 1;
3695 					}
3696 				if (nam->primary)
3697 					kw2 = kw1;
3698 				}
3699 			if (kw2 != kwm && !guikeywds) {
3700 				kw2->defname = kwm->defname;
3701 				kwm->defname = 0;
3702 				kw2->len = kwm->defname;
3703 				kwm->defname = 0;
3704 				kw2->len = kwm->len;
3705 				kwm->len = 0;
3706 				kw2->init = kwm->init;
3707 				kwm->init = 0;
3708 				kw2->cinit = kwm->cinit;
3709 				kwm->cinit = 0;
3710 				kw2->dylib = kwm->dylib;
3711 				/* no need to change kwm->dylib */
3712 				}
3713 			for(kw1 = kwm;; kw1 = kw1->next) {
3714 				if (kw1 != kw2)
3715 					kw1->pmaster = kw2;
3716 				if (kw1 == kw)
3717 					break;
3718 				}
3719 			}
3720 		}
3721 	kw0->nkw = (int)(nkw += nkwa);
3722 	if (nkw <= 1)
3723 		return kw0->kw;
3724 	x0 = x00;
3725 	if (nkw > sizeof(x00)/sizeof(x00[0]))
3726 		x0 = (KWctx**)Malloc(L = nkw*sizeof(KWctx*), "kwsort");
3727 	for(x = x0, kw = kw0->kw; kw; kw = kw->next)
3728 		*x++ = kw;
3729 	qsort(x0, nkw, sizeof(KWctx*), kwcomp);
3730 	for(xe = x - 1, x = x0; x < xe; ++x) {
3731 		if (!strcmp(x[0]->names->val, x[1]->names->val)) {
3732 			fprintf(stderr, "%s: duplicate appearance of \"%s\"\n",
3733 				progname, x[0]->names->val);
3734 			++dupnames;
3735 			}
3736 		x[0]->next = x[1];
3737 		}
3738 	x[0]->next = 0;
3739 	for(x = x0, ++xe; x < xe; ++x)
3740 		(*x)->paoff = x - x0;
3741 	for(x = x0; x < xe; ++x)
3742 		if ((kw1 = (kw = *x)->pmaster))
3743 			kw->paoff = kw1->paoff - kw->paoff;
3744 	for(x = x0; x < xe; ++x)
3745 		if (!(kw = *x)->pmaster)
3746 			kw->paoff = 0;
3747 	kw0->kw = kw = x0[0];
3748 	if (x0 != x00)
3749 		free(x0);
3750 	return kw;
3751 	}
3752 
3753  static int
alphanum(char * s)3754 alphanum(char *s)
3755 {
3756 	for(; *s; ++s)
3757 		if (!isalnum(*s))
3758 			return 0;
3759 	return 1;
3760 	}
3761 
3762  enum CommaState {
3763 	CS_Comma = 0,
3764 	CS_Clbra = 1,
3765 	CS_rbraC = 2,
3766 	CS_lrbrC = 3,
3767 	CS_rbr2C = 4
3768 	};
3769 
3770  static const char
3771 	*Commasx[5] = { ",", ",{", "},", ",{},",/*{{*/ "}}," },
3772 	*Commas0[5] = { ",", ",", ",", ",", "," };
3773  static const char **Comma;
3774 
3775  typedef struct Zbuf Zbuf;
3776  struct
3777 Zbuf {
3778 	char buf[80];	/* overkill */
3779 	char *b;
3780 	int nnz;
3781 	enum CommaState cs;
3782 	};
3783 
3784  static void
iput(int i,Zbuf * z)3785 iput(int i, Zbuf *z)
3786 {
3787 	char *s;
3788 	const char *t;
3789 
3790 	t = Comma[z->cs];
3791 	if (i == 0) {
3792 		s = z->b;
3793 		for(; (*s = *t); ++s, ++t);
3794 		*s++ = '0';
3795 		z->b = s;
3796 		}
3797 	else {
3798 		if (z->b > z->buf) {
3799 			*z->b = 0;
3800 			printf(z->b = z->buf);
3801 			}
3802 		printf("%s%d", t, i);
3803 		++z->nnz;
3804 		}
3805 	z->cs = CS_Comma;
3806 	}
3807 
3808  static void
nput(char * s,Zbuf * z)3809 nput(char *s, Zbuf *z)
3810 {
3811 	char *fmt, *s1;
3812 	const char *t;
3813 
3814 	t = Comma[z->cs];
3815 	if (!s || (strtod(s,&s1) == 0. && !*s1)) {
3816 		s = z->b;
3817 		for(; (*s = *t); ++s, ++t);
3818 		*s++ = '0';
3819 		*s++ = '.';
3820 		z->b = s;
3821 		}
3822 	else {
3823 		fmt = "%s%s.";
3824 		for(s1 = s; *s1; ++s1)
3825 			switch(*s1) {
3826 				case '.':
3827 				case 'e':
3828 				case 'E':
3829 					fmt = "%s%s";
3830 					goto have_fmt;
3831 				}
3832  have_fmt:
3833 		if (z->b > z->buf) {
3834 			*z->b = 0;
3835 			printf(z->b = z->buf);
3836 			}
3837 		printf(fmt, t, s);
3838 		++z->nnz;
3839 		}
3840 	z->cs = CS_Comma;
3841 	}
3842 
3843  static void
sput(char * s,Zbuf * z)3844 sput(char *s, Zbuf *z)
3845 {
3846 	const char *t;
3847 
3848 	t = Comma[z->cs];
3849 	if (!s) {
3850 		s = z->b;
3851 		for(; (*s = *t); ++s, ++t);
3852 		*s++ = '0';
3853 		z->b = s;
3854 		}
3855 	else {
3856 		if (z->b > z->buf) {
3857 			*z->b = 0;
3858 			printf(z->b = z->buf);
3859 			}
3860 		printf("%s\"%s\"", t, s);
3861 		++z->nnz;
3862 		}
3863 	z->cs = CS_Comma;
3864 	}
3865 
3866  static void
zbclear(Zbuf * z)3867 zbclear(Zbuf *z)
3868 {
3869 	if (z->b > z->buf) {
3870 		*z->b = 0;
3871 		printf("%s", z->b = z->buf);
3872 		}
3873 	z->cs = CS_Comma;
3874 	}
3875 
3876  typedef struct
3877 FCat { char *b, *b0, *be; } FCat;
3878 
3879  static char *
func_cat(FCat * fc,StrList * f)3880 func_cat(FCat *fc, StrList *f)
3881 {
3882 	char *b, *b1, *be;
3883 	int k, n;
3884 	size_t L, L1, L2, L3;
3885 
3886 	if (!f)
3887 		return 0;
3888 	if (!f->next)
3889 		return f->val;
3890 	b = fc->b;
3891 	be = fc->be;
3892 	for(n = k = 0; f; f = f->next, ++n) {
3893 		L = L1 = strlen(f->val);
3894 		if (n) {
3895 			++L1;
3896 			if (n & 1) {
3897 				if (alphanum(f->val)) {
3898 					k = 2;
3899 					L1 += 7;
3900 					}
3901 				else {
3902 					k = 3;
3903 					L1 += 9;
3904 					}
3905 				}
3906 			else
3907 				k = 1;
3908 			}
3909 		if (L1 > be - b) {
3910 			L2 = b - fc->b;
3911 			L3 = 2*(be - fc->b + L1);
3912 			b1 = (char*)Malloc(L3, "func_cat");
3913 			if (L2)
3914 				memcpy(b1, fc->b, L2);
3915 			if (fc->b != fc->b0)
3916 				free(fc->b);
3917 			fc->b = b1;
3918 			be = fc->be = b1 + L3;
3919 			b = b1 + L2;
3920 			}
3921 		switch(k) {
3922 			case 0: break;
3923 			case 1: *b++ = ',';
3924 				break;
3925 			case 2: memcpy(b, ",(void*)", 8);
3926 				b += 8;
3927 				break;
3928 			case 3: memcpy(b, ",(void*)(", 9);
3929 				b += 9;
3930 			}
3931 		strcpy(b, f->val);
3932 		b += L;
3933 		if (k == 3)
3934 			*b++ = ')';
3935 		*b = 0;
3936 		}
3937 	return fc->b;
3938 	}
3939 
3940  static void
kwout(KWctx * kw,KWctx ** kwtop,Uint xflag)3941 kwout(KWctx *kw, KWctx **kwtop, Uint xflag)
3942 {
3943 	FCat fc;
3944 	KWctx *kw0, *kw1, *kw2, *kwm, *kwp, **kws, **x, *x0[KWOUTlen0];
3945 	StrList *S, *nam;
3946 	Zbuf z;
3947 	char fbuf[256], *funcs, *s;
3948 	const char *fmt, *ffmt;
3949 	int aoff, k, i, m, m1, n, roff, sentinnel, skipfuncs;
3950 
3951 	if (expand && !kw->names)
3952 		return;
3953 	if (needcomma) {
3954 		printf(",\n");
3955 		needcomma = 0;
3956 		}
3957 	kw1 = kw->kw;
3958 	n = 0;
3959 	fc.b = fc.b0 = fbuf;
3960 	fc.be = fbuf + sizeof(fbuf);
3961 	if (kw->names) {
3962 		kw0 = kw1;
3963 		if (kw->parstate != KwStacked)
3964 			for(kw2 = kw->pparent; kw2; kw2 = kw2->pparent) {
3965 				kw2->next = kw1;
3966 				kw1 = kw2;
3967 				++n;
3968 				}
3969 		if (!kw0) {
3970 			if (!--n) {
3971 				kw->nkw = kw1->nkw;
3972 				if (kw1->kwkno) {
3973 					kw->kwkno = kw1->kwkno;
3974 					return;
3975 					}
3976 				kw->kwkno = lastkno + 1;
3977 				kw = kw1;
3978 				kw1 = kw->kw;
3979 				}
3980 			else {
3981 				kw2 = kw->pparent;
3982 				if (kw2->kwknop) {
3983 					kw->kwkno = kw2->kwknop;
3984 					return;
3985 					}
3986 				kw2->kwknop = lastkno + 1;
3987 				kw1 = kw2;
3988 				while((kw2 = kw2->pparent)) {
3989 					kw2->next = kw1;
3990 					kw1 = kw2;
3991 					}
3992 				}
3993 			}
3994 		}
3995 	for(m = 0, kw0 = kw1; kw0; kw0 = kw0->next)
3996 		++m;
3997 	if (expand)
3998 		for(kw0 = kw1; kw0 && !kw0->names; kw0 = kw0->next)
3999 			for(kw2 = kw0->kw; kw2; kw2 = kw2->next)
4000 				++m;
4001 	x = x0;
4002 	if (m > KWOUTlen0)
4003 		x = (KWctx**)Malloc(m*sizeof(KWctx*), "kwout");
4004 	m = 0;
4005 	kw0 = kw1;
4006 	if (expand) {
4007 		aoff = kw->nalt;
4008 		roff = kw->nreq;
4009 		for(; kw0 && !kw0->names; kw0 = kw0->next) {
4010 			for(kw2 = kw0->kw; kw2; kw2 = kw2->next) {
4011 				kw2->altoffset = aoff;
4012 				kw2->reqoffset = roff;
4013 				x[m++] = kw2;
4014 				}
4015 			aoff += kw0->nalt;
4016 			roff += kw0->nreq;
4017 			}
4018 		kw->nalt = aoff;
4019 		kw->nreq = roff;
4020 		}
4021 	for(; kw0; kw0 = kw0->next)
4022 		x[m++] = kw0;
4023 	sentinnel = 0;
4024 	if (expand) {
4025 		kw->nkw = m;
4026 		qsort(x, m, sizeof(KWctx*), kwcomp);
4027 		for(i = 1; i < m; ++i)
4028 			if (!strcmp(x[i-1]->names->val, x[i]->names->val)) {
4029 				fprintf(stderr, "%s: duplicate appearance of \"%s\"\n",
4030 					progname, x[i]->names->val);
4031 				++dupnames;
4032 				}
4033 		}
4034 	else if (kw->nkw == 0)
4035 		sentinnel = 1;
4036 	m1 = m + sentinnel;
4037 	printf("\tkw_%d[%d] = {\n" /*}*/, kw->kwkno = ++lastkno, m1);
4038 	needcomma = 1;
4039 	z.nnz = 0;
4040 	skipfuncs = !wantfuncs && !xflag;
4041 	for(i = 0; i < m;) {
4042 		kw1 = x[i++];
4043 		if (!(kwm = kw1->master))
4044 			kwm = kw1;
4045 		if (!(kwp = kw1->pmaster))
4046 			kwp = kw1;
4047 		fputs(xflag ? "\t\t{{" : "\t\t{" /*}}}*/, stdout);
4048 		z.b = z.buf;
4049 		z.cs = CS_Comma;
4050 		if ((nam = kw1->names)) {
4051 			k = kwp->kind | kw1->names->primary | xflag;
4052 			if (kwp->dylib)
4053 				k |= KWKind_Dynlib;
4054 			printf(k < 16
4055 				? "\"%s\",%d"
4056 				: "\"%s\",0x%x", kw1->names->val, k);
4057 			iput(kwm->nkw, &z);
4058 			iput(kwm->alt + kwm->altoffset, &z);
4059 			iput(kwm->req ? kwm->req + kwm->reqoffset : 0, &z);
4060 			}
4061 		else {
4062 			if (xflag)
4063 				printf("0,0x%x", xflag);
4064 			else
4065 				printf("0,0");
4066 			iput(kwm->nkw, &z);
4067 			iput(0, &z);
4068 			iput(0, &z);
4069 			}
4070 		if (guikeywds)
4071 			iput(kw1->agroup, &z);
4072 		if ((n = kwm->kwkno)) {
4073 			zbclear(&z);
4074 			printf(xflag ? ",(KeyWord*)kw_%d": ",kw_%d", n);
4075 			}
4076 		else
4077 			iput(0, &z);
4078 		nput(kwp->lb, &z);
4079 		nput(kwp->ub, &z);
4080 		ffmt = /*{{{*/ !xflag ? "}%s" : "}}%s";
4081 		if (guikeywds) {
4082 			nput(kwm->init, &z);
4083 			sput(kwm->cinit, &z);
4084 			sput(kw1->desc, &z);
4085 			if (!(s = kw1->group) && dfltgroup)
4086 				s = kw1->tag;
4087 			sput(s, &z);
4088 			if (kwm->len)
4089 				sput(kwm->len, &z);
4090 			if (kwm->dylib)
4091 				sput(kwm->dylib, &z);
4092 			goto nofuncs;
4093 			}
4094 		iput(kw1->paoff, &z);
4095 		if (skipfuncs && !kwp->dylib)
4096 			goto nofuncs;
4097 		z.nnz = 0;
4098 		funcs = 0;
4099 		if (kwp->dylib) {
4100 			z.cs = CS_Clbra;
4101 			for(n = 0; n < 3; ++n)
4102 				iput(0,&z);
4103 			zbclear(&z);
4104 			printf(",(void*)\"%s\"", kwp->dylib);
4105 			z.cs = CS_rbr2C;
4106 			z.nnz = 0;
4107 			}
4108 		else if ((S = kwp->funcs)) {
4109 			if (!S->next && !strcmp(S->val,"0"))
4110 				goto xcheck;
4111 			if (!kwp->kw && S->needrev)
4112 				S = reverse(&kwp->funcs);
4113 			funcs = func_cat(&fc, S);
4114 			goto funcput;
4115 			}
4116 		else if ((S = kwm->funcs)) {
4117 			funcs = func_cat(&fc, S);
4118  funcput:
4119 			z.cs = CS_lrbrC;
4120 			if (funcs && wantfuncs & 1) {
4121 				zbclear(&z);
4122 				printf(",%s", funcs);
4123 				z.cs = CS_rbraC;
4124 				}
4125 			else
4126 				iput(0,&z);
4127 			}
4128 		else if (kwm->names && wantfuncs & 1 && !(kwm->kind & KWKind_Libname)) {
4129 			++missing;
4130 			printf(",/*!!*/");
4131 			for(kws = KWStack; ++kws <= kwtop; ) {
4132 				if (!(kw2 = *kws)->names)
4133 					kw2 = kw2->rparent;
4134 				printf("%s_", kw2->names->val);
4135 				}
4136 			printf("%s_start", kwm->names->val);
4137 			}
4138  xcheck:
4139 		if (xflag) {
4140 			if (z.nnz) {
4141 				z.cs = z.cs == CS_rbraC ? CS_rbr2C : CS_rbraC;
4142 				ffmt = /*{{{*/ "}}}%s";
4143 				z.nnz = 0;
4144 				}
4145 			else if (z.cs == CS_rbr2C)
4146 				ffmt = /*{{{*/ "}}}%s";
4147 			else {
4148 				z.cs = CS_rbraC;
4149 				ffmt = /*{{*/ "}}%s";
4150 				}
4151 			z.b = z.buf;
4152 			iput(nam ? nam->seqno : 0, &z);
4153 			iput(kw1->agroup, &z);
4154 			sput(funcs, &z);
4155 			sput(kw1->desc, &z);
4156 			sput(kw1->group, &z);
4157 			sput(kw1->defname, &z);
4158 			sput(kw1->len, &z);
4159 			sput(kw1->init, &z);
4160 			sput(kw1->cinit, &z);
4161 			if (z.nnz)
4162 				ffmt = /*{*/ "}%s";
4163 			}
4164  nofuncs:
4165 		printf(ffmt, i < m1 ? ",\n" : "\n");
4166 		}
4167 	if (sentinnel)
4168 		fputs("\t\t{\"\"}\n", stdout);
4169 	printf(/*{*/"\t\t}");
4170 	if (x != x0)
4171 		free(x);
4172 	if (fc.b != fbuf)
4173 		free(fc.b);
4174 	}
4175 
4176  static void
hashclear(KWctx * kw)4177 hashclear(KWctx *kw)
4178 {
4179 	StrList *sl;
4180 
4181 	kw->parstate = Dupchecked;
4182 	for(kw = kw->kw; kw; kw = kw->next)
4183 		for(sl = kw->names; sl; sl = sl->next) {
4184 			sl->h.hnext->hprev = sl->h.hprev;
4185 			sl->h.hprev->hnext = sl->h.hnext;
4186 			sl->h.hprev = sl->h.hnext = 0;
4187 			}
4188 	}
4189 
4190  static void
dupfound(HashHead * h0,StrList * sl,StrList * sl1)4191 dupfound(HashHead *h0, StrList *sl, StrList *sl1)
4192 {
4193 	StrList *sl2, *sl3;
4194 
4195 	++dupnames;
4196 	for(sl2 = sl1; sl2->h.hnext != h0; sl2 = sl3) {
4197 		sl3 = (StrList*)sl2->h.hnext;
4198 		if (strcmp(sl->val, sl3->val))
4199 			break;
4200 		}
4201 	fprintf(stderr, "Warning: \"%s\" on line %d also appears on line%s %d",
4202 		sl->val, sl->Lineno, "s" + (sl2 == sl1), sl1->Lineno);
4203 	while(sl1 != sl2) {
4204 		sl1 = (StrList*)sl1->h.hnext;
4205 		fprintf(stderr, ", %d", sl1->Lineno);
4206 		}
4207 	fputs(".\n", stderr);
4208 	}
4209 
4210  static KWctx **
hashadd(KWctx * kw,KWctx ** kwtop)4211 hashadd(KWctx *kw, KWctx **kwtop)
4212 {
4213 	HashHead *h, *h0;
4214 	KWctx *kw1;
4215 	StrList *sl, *sl1;
4216 	char *s;
4217 	int n;
4218 	unsigned int c, x;
4219 
4220 	kw->parstate = Dupchecking;
4221 	for(kw1 = kw->kw; kw1; kw1 = kw1->next)
4222 		for(sl = kw1->names; sl; sl = sl->next) {
4223 			x = 0;
4224 			s = sl->val;
4225 			while((c = *(unsigned char*)s++))
4226 				x = 43*x + c - ' ';
4227 			h0 = &HTab[x % HTlen];
4228 			for(h = h0->hnext; h != h0; h = h->hnext) {
4229 				sl1 = (StrList*)h;
4230 				n = strcmp(sl->val, sl1->val);
4231 				if (n <= 0) {
4232 					if (n == 0)
4233 						dupfound(h0,sl,sl1);
4234 					break;
4235 					}
4236 				}
4237 			sl->h.hnext = h;
4238 			h->hprev = (sl->h.hprev = h->hprev)->hnext = (HashHead *)sl;
4239 			}
4240 	if ((kw1 = kw->kw))
4241 		*++kwtop = kw1;
4242 	return kwtop;
4243 	}
4244 
4245  static void
dup_check(void)4246 dup_check(void)
4247 {
4248 	HashHead *h, *he;
4249 	KWctx *kw, *kw1, *kw2, **kwtop, **kwbot, *plist;
4250 	int lev;
4251 
4252 	for(h = HTab, he = h + HTlen; h < he; ++h)
4253 		h->hnext = h->hprev = h;
4254 	plist = 0;
4255 	kwtop = kwbot = KWStack;
4256 	*kwtop = &KWbase;
4257 	for(;;) {
4258 		kw = *kwtop;
4259 		lev = kw->level;
4260 		while(plist && plist->level >= lev) {
4261 			hashclear(plist);
4262 			plist = plist->next;
4263 			}
4264 		if (kw->parstate == Dupchecking) {
4265 			hashclear(kw);
4266 			if ((*kwtop = kw->next))
4267 				continue;
4268 			if (kwtop <= kwbot)
4269 				break;
4270 			--kwtop;
4271 			continue;
4272 			}
4273 		if ((kw1 = kw->pparent) && kw1->parstate != Dupchecking) {
4274 			for(kw2 = kw1; plist && kw2; plist = plist->next) {
4275 				while(kw2->level > plist->level && (kw2 = kw2->pparent));
4276 				if (kw2 != plist)
4277 					break;
4278 				hashclear(plist);
4279 				}
4280 			kw2 = 0;
4281 			do {
4282 				if (kw1->kw) {
4283 					kw1->next = kw2;
4284 					kw2 = kw1;
4285 					}
4286 				}
4287 				while((kw1 = kw1->pparent) && kw1->parstate != Dupchecking);
4288 			while(kw2) {
4289 				kwtop = hashadd(kw2, kwtop);
4290 				kw1 = kw2;
4291 				kw2 = kw2->next;
4292 				kw1->next = plist;
4293 				plist = kw1;
4294 				}
4295 			}
4296 		kwtop = hashadd(kw, kwtop);
4297 		}
4298 	}
4299 
4300  static void
prkwname(KWctx * kw,const char * suf,int needrev)4301 prkwname(KWctx *kw, const char *suf, int needrev)
4302 {
4303 	int k;
4304 	StrList *S;
4305 	static const char *kname[] = { "BUG", "INTEGER", "REAL", "STRING" };
4306 
4307 	if (needrev)
4308 		reverse(&kw->names);
4309 	S = kw->names;
4310 	printf("%s", S->val);
4311 	while((S = S->next))
4312 		printf(" ALIAS %s", S->val);
4313 	if ((k = kw->kind & KWKind_Mask)) {
4314 		printf(" %s", kname[k]);
4315 		if (kw->kind & KWKind_List)
4316 			printf("LIST");
4317 		}
4318 	if (kw->lb)
4319 		printf(" %s %s", kw->kind & KWKind_strictLb ? ">" : ">=", kw->lb);
4320 	if (kw->ub)
4321 		printf(" %s %s", kw->kind & KWKind_strictUb ? "<" : "<=", kw->ub);
4322 	if (kw->defname && wantfuncs & 1) {
4323 		if (kw->init)
4324 			printf(" := %s %s", kw->defname, kw->init);
4325 		else if (kw->cinit)
4326 			printf(" := %s \"%s\"", kw->defname, kw->cinit);
4327 		}
4328 	else {
4329 		if (kw->init)
4330 			printf(" := %s", kw->init);
4331 		else if (kw->cinit)
4332 			printf(" := \"%s\"", kw->cinit);
4333 		}
4334 	if (!(wantfuncs&1))
4335 		goto sufchk;
4336 	if (kw->tag)
4337 		printf(ignoretags ? " TAG \"%s\"" : " /*TAG \"%s\"*/", kw->tag);
4338 	if (kw->funcs) {
4339 		fputs(" {", stdout);
4340 		reverse(&kw->funcs);
4341 		for(S = kw->funcs;;) {
4342 			fputs(S->val, stdout);
4343 			if (!(S = S->next))
4344 				break;
4345 			putchar(',');
4346 			}
4347 		putchar('}');
4348 		}
4349 	if (kw->len)
4350 		printf(" LEN %s", kw->len);
4351 	if (kw->group)
4352 		printf(" GROUP \"%s\"", kw->group);
4353 	if (kw->desc)
4354 		printf(" DESC \"%s\"", kw->desc);
4355  sufchk:
4356 	if (kw->dylib)
4357 		printf(" DYNLIB \"%s\"", kw->dylib);
4358 	if (suf)
4359 		fputs(suf, stdout);
4360 	if (needrev == 2)
4361 		reverse(&kw->names);
4362 	}
4363 
4364  static KWctx *
kwrev(KWctx ** pkw)4365 kwrev(KWctx **pkw)
4366 {
4367 	KWctx *kw, *kw0, *kw1;
4368 	kw1 = *pkw;
4369 	for(kw0 = 0; (kw = kw1); kw0 = kw) {
4370 		kw1 = kw->next;
4371 		kw->next = kw0;
4372 		}
4373 	return *pkw = kw0;
4374 	}
4375 
4376  static int
StrListcmp(StrList * sl1,StrList * sl2)4377 StrListcmp(StrList *sl1, StrList *sl2)
4378 {
4379 	if (sl1 == sl2)
4380 		return 0;
4381 	while(sl1) {
4382 		if (!sl2 || strcmp(sl1->val, sl2->val))
4383 			return 1;
4384 		sl1 = sl1->next;
4385 		sl2 = sl2->next;
4386 		}
4387 	return sl2 != 0;
4388 	}
4389 
4390 #if 0	/* Could hash keywords and use the following samekw to find duplicate  */
4391 	/* contained keywords, noting duplicates when found in a new, normally */
4392 	/* NULL pointer in KWctx, but so far this does not appear worthwhile.  */
4393 #define OffsetOf(T,f) ((char*)&((T*)0)->f - (char*)0)
4394 #define NumberOf(x) (sizeof(x)/sizeof(x[0]))
4395 #define ValueOf(T,x,o) (*(T*)((char*)x + o))
4396 
4397  static int
4398 samekw(KWctx *kw1, KWctx *kw2)
4399 {
4400 	char *s1, *s2;
4401 	size_t *sp, *spe;
4402 
4403 	static size_t
4404 		Intoff[] = {
4405 			OffsetOf(KWctx,alt),
4406 			OffsetOf(KWctx,kind),
4407 			OffsetOf(KWctx,nalt),
4408 			OffsetOf(KWctx,nkw),
4409 			OffsetOf(KWctx,nreq),
4410 			OffsetOf(KWctx,req)
4411 			},
4412 		Stroff[] = {
4413 			OffsetOf(KWctx,lb),
4414 			OffsetOf(KWctx,ub),
4415 			OffsetOf(KWctx,init),
4416 			OffsetOf(KWctx,cinit),
4417 			OffsetOf(KWctx,defname),
4418 			OffsetOf(KWctx,desc),
4419 			OffsetOf(KWctx,dylib),
4420 			OffsetOf(KWctx,group),
4421 			OffsetOf(KWctx,len)
4422 			};
4423 	while(kw1) {
4424 		if (!kw2)
4425 			return 0;
4426 		if (kw1->pparent != kw2->pparent
4427 		 || kw1->rparent != kw2->rparent)
4428 			return 0;
4429 		if (StrListcmp(kw1->names, kw2->names)
4430 		 || StrListcmp(kw1->funcs, kw2->funcs))
4431 			return 0;
4432 		for(sp = Intoff, spe = sp + NumberOf(Intoff); sp < spe; ++sp)
4433 			if (ValueOf(int,kw1,*sp) != ValueOf(int,kw2,*sp))
4434 				return 0;
4435 		for(sp = Stroff, spe = sp + NumberOf(Stroff); sp < spe; ++sp) {
4436 			s1 = ValueOf(char*,kw1,*sp);
4437 			s2 = ValueOf(char*,kw2,*sp);
4438 			if (s1 != s2 && (!s1 || !s2 || strcmp(s1,s2)))
4439 				return 0;
4440 			}
4441 		kw1 = kw1->next;
4442 		kw2 = kw2->next;
4443 		}
4444 	return kw2 == 0;
4445 	}
4446 #undef ValueOf
4447 #undef NumberOf
4448 #undef OffsetOf
4449 #endif
4450 
4451  static void
paradj(int needrev)4452 paradj(int needrev)
4453 {
4454 	KWctx *kw, *kw1, *kw2, **kwp, **kwtop, **kwbot, *plist;
4455 	int lev;
4456 
4457 	kwtop = kwbot = KWStack;
4458 	*kwtop = &KWbase;
4459 	if (needrev)
4460 		kwrev(kwtop);
4461 
4462 	/* remove extra parens */
4463 
4464 	for(;; --kwtop) {
4465 		for(kw = *kwtop; kw; kw = kw->next) {
4466  top:
4467 			if (needrev && (kw1 = kw->kw) && kw1->next)
4468 				kwrev(&kw->kw);
4469 			if ((kw1 = kw->pparent) && kw1->parstate != Parchecked) {
4470 				kwp = &kw->pparent;
4471 				plist = kw;
4472 				for(;;) {
4473 					if (kw1->kw) {
4474 						*kwtop++ = kw1;
4475 						kw1->parstate = Parchecked;
4476 						*kwp = kw1;
4477 						kwp = &kw1->pparent;
4478 						kw1->next = plist;
4479 						plist = kw1;
4480 						}
4481 					if (!(*kwp = kw1->pparent)) {
4482 						lev = kw1->level;
4483 						break;
4484 						}
4485 					kw1 = *kwp;
4486 					if (kw1->parstate == Parchecked) {
4487 						lev = kw1->level + 1;
4488 						break;
4489 						}
4490 					}
4491 				for(;; plist = kw1) {
4492 					plist->level = lev++;
4493 					if (plist == kw)
4494 						break;
4495 					kw1 = plist->next;
4496 					plist->next = 0;
4497 					}
4498 				}
4499 			if (kw->kw) {
4500 				if ((*kwtop = kw->next))
4501 					++kwtop;
4502 				kw = kw->kw;
4503 				goto top;
4504 				}
4505 			}
4506 		if (kwtop <= kwbot)
4507 			break;
4508 		}
4509 	}
4510 
4511  static KWctx *
masteradj(KWctx * kw)4512 masteradj(KWctx *kw)
4513 {
4514 	/* to help print (nm1 | nm2 foo goo), make nm2 "master" */
4515 	KWctx *kw1, *kw2, *kw3, *kwm, *rv;
4516 
4517 	for(kw1 = kw, kw3 = 0; kw1; kw1 = kw1->next) {
4518 		if ((kw2 = kw1->master))
4519 			kw3 = kw2->master = kw2;
4520 		}
4521 	if (!kw3)
4522 		return kw;
4523 	for(rv = kw; kw; kw = kw->next) {
4524 		kwm = kw->master;
4525 		if ((kw1 = kw->next) && kw1->master == kwm && kwm) {
4526 			kw3 = kw->kw ? kw : 0;
4527 			do {
4528 				kw2 = kw1;
4529 				if (kw1->kw) {
4530 					if (kw3)
4531 						botch("Two masters in masteradj!");
4532 					kw3 = kw1;
4533 					}
4534 				}
4535 				while((kw1 = kw1->next) && kw1->master == kwm);
4536 			if (kw3 || kw2->pparent) {
4537 				if (kw2 != kw3) {
4538 					kw2->pparent = kw3->pparent;
4539 					kw2->kw = kw3->kw;
4540 					kw3->kw = 0;
4541 					}
4542 				for(;;kw = kw->next) {
4543 					kw->master = kw2;
4544 					if (kw == kw2)
4545 						break;
4546 					}
4547 				}
4548 			else
4549 				for(;;kw = kw->next) {
4550 					kw->master = 0;
4551 					if (kw == kw2)
4552 						break;
4553 					}
4554 			kw = kw2;
4555 			}
4556 		}
4557 	return rv;
4558 	}
4559 
4560  static void
xmasteradj(KWctx ** x,int n)4561 xmasteradj(KWctx **x, int n)
4562 {
4563 	/* variant of masteradj for pretty_ex1 */
4564 	KWctx *kw, *kw1, *kw2, *kw3, *kwm;
4565 	int i, j;
4566 
4567 	for(i = 0, kw3 = 0; i < n; ++i) {
4568 		kw1 = x[i];
4569 		if ((kw2 = kw1->master))
4570 			kw3 = kw2->master = kw2;
4571 		}
4572 	if (!kw3)
4573 		return;
4574 	for(i = 0; i < n; i = j) {
4575 		j = i + 1;
4576 		kw = x[i];
4577 		kwm = kw->master;
4578 		if (j < n && kwm && (kw1 = x[j])->master == kwm) {
4579 			kw3 = kw->kw ? kw : 0;
4580 			do {
4581 				kw2 = kw1;
4582 				if (kw1->kw) {
4583 					if (kw3)
4584 						botch("Two masters in xmasteradj!");
4585 					kw3 = kw1;
4586 					}
4587 				}
4588 				while(++j < n && (kw1 = x[j])->master == kwm);
4589 			if (kw3 || kw2->pparent) {
4590 				if (kw2 != kw3) {
4591 					kw2->pparent = kw3->pparent;
4592 					kw2->kw = kw3->kw;
4593 					kw3->kw = 0;
4594 					}
4595 				for(;;kw = x[++i]) {
4596 					kw->master = kw2;
4597 					if (kw == kw2)
4598 						break;
4599 					}
4600 				}
4601 			else
4602 				for(;; kw = x[++i]) {
4603 					kw->master = 0;
4604 					if (kw == kw2)
4605 						break;
4606 					}
4607 			}
4608 		}
4609 	}
4610 
4611  static void
do_indent(int indent)4612 do_indent(int indent)
4613 {
4614 	for(indent += 8; indent >= 8; indent -= 8)
4615 		putchar('\t');
4616 	for(; indent > 0; --indent)
4617 		putchar(' ');
4618 	}
4619 
4620  static void
do_indent1(int indent)4621 do_indent1(int indent)	/* write indent-1 spaces */
4622 {
4623 	while(--indent > 0)
4624 		putchar(' ');
4625 	}
4626 
4627  static const char *KEYKIND[4] = { "KEYWORD ", "KEYWORD01 ", "KEYWORD1 ", "KEYWORD12 " };
4628 
4629  static void
pretty_print(int iinc,int needrev)4630 pretty_print(int iinc, int needrev)
4631 {
4632 	KWctx *kw, *kw1, *kw2, *kw3, **kwtop, **kwbot, *plist;
4633 	const char *s;
4634 	int alt, indent, lev, needindent, needspace;
4635 
4636 	kwtop = kwbot = KWStack;
4637 	indent = 0;
4638 	plist = 0;
4639 	needindent = 1;
4640 	for(kw1 = KWbase.kw; kw1;) {
4641 		fputs(KEYKIND[(kw1->kind >> KWtopshift) & 3], stdout);
4642 		prkwname(kw1, "\n", needrev);
4643 		*kwtop = masteradj(kw1->kw);
4644 		alt = 0;
4645 		for(;;--kwtop) {
4646 	 top:
4647 			for(kw = *kwtop; kw; kw = kw->next) {
4648 				lev = kw->level;
4649 				if (needindent) {
4650 					do_indent(indent);
4651 					needindent = 0;
4652 					}
4653 				if (plist
4654 				 && (plist->level > lev
4655 				  || (plist->level == lev && plist != kw->pparent))) {
4656  finishpar:
4657 					*kwtop = kw;
4658 					*++kwtop = plist;
4659 					*++kwtop = masteradj(plist->kw);
4660 					plist->alt = alt;
4661 					alt = 0;
4662 					plist = plist->next;
4663 					goto top;
4664 					}
4665 				if (kw->parstate == Printing) {
4666 					s = !kw->names || /*[(*/kw->req ? ")\n" : "]\n";
4667 					if (kw->kw && !kw->req
4668 					 && kw->next && kw->next->alt == kw->alt) {
4669 						s = /*(*/ ")\n";
4670 						indent -= iinc;
4671 						}
4672 					fputs(s, stdout);
4673 					needindent = 1;
4674 					alt = kw->alt;
4675 					indent -= iinc;
4676 					if (!kw->names) {
4677 						alt = kw->alt;
4678 						goto bot;
4679 						}
4680 					continue;
4681 					}
4682 				if (plist)
4683 					for (kw2 = kw->pparent;
4684 							kw2 && kw2->parstate != Printing;
4685 							kw2 = kw2->pparent) {
4686 						if (plist->level >= kw2->level)
4687 							goto finishpar;
4688 						}
4689 				needindent = 1;
4690 				needspace = 0;
4691 				if (alt == kw->alt) {
4692 					putchar('|');
4693 					needspace = 1;
4694 					}
4695 				if ((kw2 = kw->pparent) && kw2->parstate != Printing) {
4696 					kw3 = 0;
4697 					do {
4698 						if (kw2->parstate == Printing)
4699 							break;
4700 						if (kw2->kw) {
4701 							kw2->next = kw3;
4702 							kw3 = kw2;
4703 							kw2->parstate = Printing;
4704 							if (needspace) {
4705 								putchar('\n');
4706 								needspace = 0;
4707 								do_indent(indent);
4708 								}
4709 							indent += iinc;
4710 							putchar('('); /*)*/
4711 							do_indent1(iinc);
4712 							}
4713 						}
4714 						while((kw2 = kw2->pparent));
4715 					while(kw3) {
4716 						kw2 = kw3->next;
4717 						kw3->next = plist;
4718 						plist = kw3;
4719 						kw3 = kw2;
4720 						}
4721 					}
4722 				if ((kw2 = kw->master) && kw == kw2)
4723 					kw2 = 0;
4724 				if (!kw->kw && (!kw2 || kw2->parstate == Leftput)) {
4725 					if (needspace)
4726 						putchar(' ');
4727 					if (!kw->req) {
4728 						if (alt != kw->alt) {
4729 							fputs("[ ", stdout);
4730 							alt = kw->alt;
4731 							}
4732 						s = /*[*/ " ]\n";
4733 						if ((kw2 = kw->next) && kw2->alt == alt)
4734 							s = "\n";
4735 						prkwname(kw, s, needrev);
4736 						continue;
4737 						}
4738 					alt = kw->alt;
4739 					prkwname(kw, "\n", needrev);
4740 					continue;
4741 					}
4742 				if (kw->parstate == Leftput) {
4743 					if (needspace)
4744 						goto putspace;
4745 					}
4746 				else {
4747 					if (needspace) {
4748 						putchar('\n');
4749 						do_indent(indent);
4750 						}
4751 					putchar(kw->req ? '(' : '['); /*])*/
4752 					if (kw->kw && !kw->req
4753 					 && kw->next && kw->next->alt == kw->alt) {
4754 						do_indent1(iinc);
4755 						putchar('('/*)*/);
4756 						indent += iinc;
4757 						}
4758 					indent += iinc;
4759  putspace:
4760 					do_indent1(iinc);
4761 					}
4762 				kw->parstate = Printing;
4763 				prkwname(kw, "\n", needrev);
4764 				if (kw2) {
4765 					alt = kw->alt;
4766 					kw2->parstate = Leftput;
4767 					continue;
4768 					}
4769 				alt = 0;
4770 				*kwtop = kw;
4771 				*++kwtop = masteradj(kw->kw);
4772 				goto top;
4773 				}
4774  bot:
4775 			if (kwtop == kwbot) {
4776 				if (plist) {
4777 					*kwtop++ = plist;
4778 					*kwtop++ = masteradj(plist->kw);
4779 					plist->alt = alt;
4780 					alt = 0;
4781 					plist = plist->next;
4782 					}
4783 				else {
4784 					if (indent) {
4785 						if (needindent)
4786 							do_indent(indent);
4787 						fputs(/*(*/")\n", stdout);
4788 						needindent = 1;
4789 						indent -= iinc;
4790 						}
4791 					break;
4792 					}
4793 				}
4794 			}
4795 		if (!(kw1 = kw1->next))
4796 			break;
4797 		putchar('\n');
4798 		}
4799 	}
4800 
4801  static void
nslist(StrList * h,const char * fmt)4802 nslist(StrList *h, const char *fmt)
4803 {
4804 	for(; h; h = h->next)
4805 		printf(fmt, h->val);
4806 	}
4807 
4808  static void
Output(StrList * headers,StrList * nsname,int hwant,const char * kname,int libmode,int nwant)4809 Output(StrList *headers, StrList *nsname, int hwant, const char *kname, int libmode, int nwant)
4810 {
4811 	KWctx *kw, *kw1, *kw2, **kwtop, **kwbot;
4812 	StrList *h;
4813 	Uint xflag;
4814 	const char *fmt;
4815 	int kwkno;
4816 	static char
4817 		libfmt1[] = "#ifdef __cplusplus\nextern \"C\" {\n"
4818 			"KeyWord *keyword_add(void);\n}\n#endif\n\n"
4819 			" KeyWord*\nkeyword_add(void) {\n\t",
4820 		libfmt2[] = "kw_%d[0].kw;\n\t}\n",
4821 		libfmt3[] = /*{*/ "kw_%d.kw;\n\t}\n";
4822 
4823 	if (hwant && headers) {
4824 		for(h = reverse(&headers); h; h = h->next)
4825 			printf(*h->val == '<' /*>*/
4826 				? "#include %s\n"
4827 				: "#include \"%s\"\n", h->val);
4828 		}
4829 	if (nwant) {
4830 		if (nsname)
4831 			reverse(&nsname);
4832 		else
4833 			nsname = new_StrList("Dakota", nsname);
4834 		putchar('\n');
4835 		nslist(nsname, "namespace %s {\n" /*}*/);
4836 		}
4837 	/* BMA (20160923): Suppress keyword count summary to avoid merge conflicts */
4838 	//printf("\n/** %d distinct keywords (plus %d aliases) **/\n", lastagroup, nalias);
4839 	printf("\nstatic %sKeyWord%s\n", guikeywds ? "Gui" : "", libmode ? "x" : "");
4840 	kwtop = kwbot = KWStack;
4841 	*kwtop = &KWbase;
4842 	if (libmode) {
4843 		xflag = KWKind_Extended;
4844 		Comma = Commasx;
4845 		}
4846 	else {
4847 		xflag = 0;
4848 		Comma = Commas0;
4849 		}
4850 	for(;;--kwtop) {
4851  top:
4852 		for(kw = *kwtop; kw; kw = kw->next) {
4853 			if ((kw->master && kw->master != kw)
4854 			|| ((!(kw1 = kw->pparent) || kw->parstate == KwStacked) && !kw->kw)
4855 			|| kw->kwkno)
4856 				continue;
4857 			if (kw1 && kw1->parstate != KwStacked) {
4858 				if ((kw1 = kw->pparent) && kw1->parstate != KwStacked) {
4859 					kw1->parstate = KwStacked;
4860 					*kwtop = kw;
4861 					*++kwtop = kw1;
4862 					kw2 = *++kwtop = kwsort(kw1);
4863 					do kw2->parstate = KwStacked;
4864 						while((kw2 = kw2->next));
4865 					while((kw1 = kw1->pparent) && kw1->parstate != KwStacked) {
4866 						kw1->parstate = KwStacked;
4867 						*++kwtop = kw1;
4868 						kw2 = *++kwtop = kwsort(kw1);
4869 						do kw2->parstate = KwStacked;
4870 							while((kw2 = kw2->next));
4871 						}
4872 					goto top;
4873 					}
4874 				if (!kw1 && !kw->kw)
4875 					continue;
4876 				}
4877 			if (!kw->nkw && kw->kw) {
4878 				*kwtop = kw;
4879 				*++kwtop = kwsort(kw);
4880 				goto top;
4881 				}
4882 			kwout(kw, kwtop, xflag);
4883 			}
4884 		if (kwtop == kwbot)
4885 			break;
4886 		}
4887 	printf(";\n\n");
4888 	if (nwant) {
4889 		nslist(reverse(&nsname), /*{*/"} // namespace %s\n");
4890 		putchar('\n');
4891 		reverse(&nsname);
4892 		}
4893 
4894 	printf("#ifdef __cplusplus\n");
4895 	printf("extern \"C\" {\n");
4896 	printf("#endif\n");
4897 
4898 	kwkno = KWbase.kwkno;
4899 	if (libmode) {
4900 		if (KWbase.nkw > 1 && !kname)
4901 			kname = "KeywordTop";
4902 		printf(libfmt1);
4903 		fmt = libfmt2;
4904 		if (kname) {
4905 			printf("static KeyWordx kw_%d = { \"%s\", 0x%x,%d,%d,%d,(KeyWord*)",
4906 				kwkno + 1, kname, KWKind_Dynmult, KWbase.nkw,
4907 				KWbase.alt, KWbase.req);
4908 			if (nwant) {
4909 				nslist(nsname, "%s::");
4910 				nwant = 0;
4911 				}
4912 			printf("kw_%d };\n\t", kwkno++);
4913 			fmt = libfmt3;
4914 			}
4915 		printf("return &");
4916 		}
4917 	else {
4918 		printf("KeyWord Dakota_Keyword_Top = {\"KeywordTop\",0,%d,%d,%d,",
4919 			KWbase.nkw, KWbase.alt, KWbase.req);
4920 		fmt = "kw_%d};\n";
4921 		}
4922 	if (nwant)
4923 		nslist(nsname, "%s::");
4924 	printf(fmt, kwkno);
4925 
4926         printf("#ifdef __cplusplus\n");
4927         printf("}\n");
4928         printf("#endif\n");
4929 
4930 	if (startwarn && missing && !guikeywds)
4931 		fprintf(stderr, "%s: %d start routines implicitly named.\n",
4932 			progname, missing);
4933 	}
4934 
4935  typedef struct Valhash Valhash;
4936 
4937  struct
4938 Valhash {
4939 	DefhashHead hh;
4940 	Uint n;
4941 	Valhash *thread;
4942 	};
4943 
4944  static Kwpack *kwpack, *kwpack0, *kwpacke;
4945  static size_t kwpack_len, strtab_len = 1;
4946  static DefhashTab FpTab, StrTab;
4947  static Valhash *FpTabLast, *StrTabLast;
4948 
4949  static Uint
NumOff(char * name)4950 NumOff(char *name)
4951 {
4952 	Valhash *v;
4953 	if (!name || !*name || (*name == '0' && !name[1]))
4954 		return 0;
4955 	v = (Valhash*)DHHlookup(name, &FpTab, 1);
4956 	if (!v->n) {
4957 		v->n = FpTab.nent;
4958 		v->thread = FpTabLast;
4959 		FpTabLast = v;
4960 		}
4961 	return v->n;
4962 	}
4963 
4964  static Uint
StrOff(char * name)4965 StrOff(char *name)
4966 {
4967 	Valhash *v;
4968 	if (!name)
4969 		return 0;
4970 	v = (Valhash*)DHHlookup(name, &StrTab, 1);
4971 	if (!v->n) {
4972 		v->n = strtab_len;
4973 		strtab_len += strlen(name) + 1;
4974 		v->thread = StrTabLast;
4975 		StrTabLast = v;
4976 		}
4977 	return v->n;
4978 	}
4979 
4980  static void
kwjout(KWctx * kw,KWctx ** kwtop)4981 kwjout(KWctx *kw, KWctx **kwtop)
4982 {
4983 	KWctx *kw0, *kw1, *kw2, *kwm, **x, *x0[KWOUTlen0];
4984 	Kwpack *p;
4985 	Uint lastknoj;
4986 	int i, m, n;
4987 	size_t L;
4988 
4989 	kw1 = kw->kw;
4990 	n = 0;
4991 	lastknoj = kwpack - kwpack0 + 1;
4992 	if (kw->names) {
4993 		kw0 = kw1;
4994 		if (kw->parstate != KwStacked)
4995 			for(kw2 = kw->pparent; kw2; kw2 = kw2->pparent) {
4996 				kw2->next = kw1;
4997 				kw1 = kw2;
4998 				++n;
4999 				}
5000 		if (!kw0) {
5001 			if (!--n) {
5002 				kw->nkw = kw1->nkw;
5003 				if (kw1->kwkno) {
5004 					kw->kwkno = kw1->kwkno;
5005 					return;
5006 					}
5007 				kw->kwkno = lastknoj;
5008 				kw = kw1;
5009 				kw1 = kw->kw;
5010 				}
5011 			else {
5012 				kw2 = kw->pparent;
5013 				if (kw2->kwknop) {
5014 					kw->kwkno = kw2->kwknop;
5015 					return;
5016 					}
5017 				kw2->kwknop = lastknoj;
5018 				kw1 = kw2;
5019 				while((kw2 = kw2->pparent)) {
5020 					kw2->next = kw1;
5021 					kw1 = kw2;
5022 					}
5023 				}
5024 			}
5025 		}
5026 	for(m = 0, kw0 = kw1; kw0; kw0 = kw0->next)
5027 		++m;
5028 	x = x0;
5029 	if (m > KWOUTlen0)
5030 		x = (KWctx**)Malloc(m*sizeof(KWctx*), "kwjout");
5031 	m = 0;
5032 	for(kw0 = kw1; kw0; kw0 = kw0->next)
5033 		x[m++] = kw0;
5034 	kw->kwkno = lastknoj;
5035 	++lastkno;
5036 	for(i = 0; i < m;) {
5037 		if (++kwpack >= kwpacke) {
5038 			L = 2*kwpack_len;
5039 			kwpack0 = (Kwpack*)Realloc(kwpack0, L*sizeof(Kwpack), "kwjout");
5040 			kwpacke = kwpack0 + L;
5041 			kwpack = kwpack0 + kwpack_len;
5042 			memset(kwpack, 0, kwpack_len*sizeof(Kwpack));
5043 			kwpack_len = L;
5044 			}
5045 		p = kwpack;
5046 		kw1 = x[i++];
5047 		if (!(kwm = kw1->master))
5048 			kwm = kw1;
5049 		p->nkw = kwm->nkw;
5050 		if (kw1->names) {
5051 			p->name = StrOff(kw1->names->val);
5052 			p->kind = kw1->kind | kw1->names->primary;
5053 			p->alt = kwm->alt + kwm->altoffset;
5054 			if (kwm->req)
5055 				p->req = kwm->req + kwm->reqoffset;
5056 			if (kwm->dylib) {
5057 				p->dylib = StrOff(kwm->dylib);
5058 				p->kind |= KWKind_Dynlib;
5059 				}
5060 			}
5061 		p->kw = kwm->kwkno;
5062 		p->Lb = NumOff(kw1->lb);
5063 		p->Ub = NumOff(kw1->ub);
5064 		p->poff = kw1->paoff;
5065 		}
5066 	if (x != x0)
5067 		free(x);
5068 	}
5069 
5070  static Valhash *
Vreverse(Valhash * sh)5071 Vreverse(Valhash *sh)
5072 {
5073 	Valhash *sh0, *sh1;
5074 	for(sh0 = 0; sh; sh = sh1) {
5075 		sh1 = sh->thread;
5076 		sh->thread = sh0;
5077 		sh0 = sh;
5078 		}
5079 	return sh0;
5080 	}
5081 
5082  static void
kwpack_adjust(Kwpack * kp,Uint nkw)5083 kwpack_adjust(Kwpack *kp, Uint nkw)
5084 {
5085 	Kwpack0 *qp, *qpe;
5086 
5087 	qp = (Kwpack0*)kp;
5088 	for(qpe = qp + nkw; qp < qpe; ++kp, ++qp) {
5089 		memcpy(qp, kp, sizeof(Kwpack0) - sizeof(int));
5090 		qp->poff = kp->poff;
5091 		}
5092 	}
5093 
5094  static void
jOutput(char * jfname)5095 jOutput(char *jfname)
5096 {
5097 	FILE *f;
5098 	KWctx *kw, *kw1, *kw2, **kwtop, **kwbot;
5099 	Kwpack *kp;
5100 	Uint nkw0;
5101 	Valhash *vh;
5102 	double d;
5103 	size_t L, Lkw, Ls;
5104 	static KwpHead head = { "DakreorderKwds\n", 1e13, 0x1234abcd };
5105 	static double zbuf[2];
5106 
5107 	FpTab.nalloc  = (sizeof(Valhash) + sizeof(void*) - 1)/sizeof(void*);
5108 	StrTab.nalloc = (sizeof(Valhash) + sizeof(void*) - 1)/sizeof(void*);
5109 	kwpack_len = 128;
5110 	kwpack = kwpack0 = (Kwpack*)Malloc(kwpack_len * sizeof(Kwpack), "jOutput");
5111 	memset(kwpack, 0, kwpack_len * sizeof(Kwpack));
5112 	kwpacke = kwpack0 + kwpack_len;
5113 	kwtop = kwbot = KWStack;
5114 	*kwtop = &KWbase;
5115 	for(;;--kwtop) {
5116  top:
5117 		for(kw = *kwtop; kw; kw = kw->next) {
5118 			if ((kw->master && kw->master != kw)
5119 			|| ((!(kw1 = kw->pparent) || kw->parstate == KwStacked) && !kw->kw)
5120 			|| kw->kwkno)
5121 				continue;
5122 			if (kw1 && kw1->parstate != KwStacked) {
5123 				if ((kw1 = kw->pparent) && kw1->parstate != KwStacked) {
5124 					kw1->parstate = KwStacked;
5125 					*kwtop = kw;
5126 					*++kwtop = kw1;
5127 					kw2 = *++kwtop = kwsort(kw1);
5128 					do kw2->parstate = KwStacked;
5129 						while((kw2 = kw2->next));
5130 					while((kw1 = kw1->pparent) && kw1->parstate != KwStacked) {
5131 						kw1->parstate = KwStacked;
5132 						*++kwtop = kw1;
5133 						kw2 = *++kwtop = kwsort(kw1);
5134 						do kw2->parstate = KwStacked;
5135 							while((kw2 = kw2->next));
5136 						}
5137 					goto top;
5138 					}
5139 				if (!kw1 && !kw->kw)
5140 					continue;
5141 				}
5142 			if (!kw->nkw && kw->kw) {
5143 				*kwtop = kw;
5144 				*++kwtop = kwsort(kw);
5145 				goto top;
5146 				}
5147 			kwjout(kw, kwtop);
5148 			}
5149 		if (kwtop == kwbot)
5150 			break;
5151 		}
5152 	StrTabLast = Vreverse(StrTabLast);
5153 	FpTabLast = Vreverse(FpTabLast);
5154 	nkw0 = kwpack - kwpack0;
5155 	head.nkw = nkw0 + 1;
5156 	kp = kwpack0;
5157 	kp->kw = nkw0 - KWbase.nkw + 1;
5158 	kp->nkw = KWbase.nkw;
5159 	kp->alt = KWbase.alt;
5160 	kp->req = KWbase.req;
5161 	head.strtab_offset = (FpTab.nent+1)*sizeof(double);
5162 	Ls = (strtab_len + 7) & ~7;
5163 	head.kw_offset = head.strtab_offset + Ls;
5164 	if ((head.pad = dynlibseen))
5165 		Lkw = sizeof(Kwpack);
5166 	else {
5167 		Lkw = sizeof(Kwpack0);
5168 		kwpack_adjust(kp, head.nkw);
5169 		}
5170 	head.end_offset = head.kw_offset + head.nkw * Lkw;
5171 	f = fopen(jfname, "wb");
5172 	if (!f) {
5173 		fprintf(stderr, "Could not open \"%s\"\n", jfname);
5174 		exit(1);
5175 		}
5176 	fwrite(&head, sizeof(head), 1, f);
5177 	for(vh = FpTabLast; vh; vh = vh->thread) {
5178 		d = strtod(vh->hh.name,0);
5179 		fwrite(&d, sizeof(double), 1, f);
5180 		}
5181 	fwrite(&zbuf,9,1,f);
5182 	for(vh = StrTabLast; vh; vh = vh->thread)
5183 		fwrite(vh->hh.name, strlen(vh->hh.name) + 1, 1, f);
5184 	if ((L = Ls - strtab_len))
5185 		fwrite(&zbuf, L, 1, f);	/* align */
5186 	fwrite(kp, Lkw, head.nkw, f);
5187 	fclose(f);
5188 	}
5189 
5190  typedef int (*KWcomp)(const void*, const void*);
5191 
5192  static const char **zalt;
5193 
5194  static int
kwcomp1(const void * a,const void * b)5195 kwcomp1(const void *a, const void *b)
5196 {
5197 	const KWctx *ka, *kb;
5198 
5199 	ka = *(const KWctx**)a;
5200 	kb = *(const KWctx**)b;
5201 	if (ka->req) {
5202 		if (!kb->req)
5203 			return -1;
5204 		}
5205 	else if (kb->req)
5206 		return 1;
5207 	if (ka->alt == kb->alt) {
5208 		if (ka->master != kb->master) {
5209 			if (!ka->master)
5210 				return -1;
5211 			if (!kb->master)
5212 				return 1;
5213 			ka = ka->master;
5214 			kb = kb->master;
5215 			}
5216 		return strcmp(ka->names->val, kb->names->val);
5217 		}
5218 	return strcmp(zalt[ka->alt], zalt[kb->alt]);
5219 	}
5220 
5221  static int
kwcomp2(const void * a,const void * b)5222 kwcomp2(const void *a, const void *b)
5223 {
5224 	const KWctx *ka, *kb, *pa, *pb;
5225 
5226 	ka = *(const KWctx**)a;
5227 	kb = *(const KWctx**)b;
5228 	if (ka->req) {
5229 		if (!kb->req)
5230 			return -1;
5231 		}
5232 	else if (kb->req)
5233 		return 1;
5234 	if (ka->alt == kb->alt) {
5235 		pa = ka->master ? ka->master->pparent : ka->pparent;
5236 		pb = kb->master ? kb->master->pparent : kb->pparent;
5237 		if (pa != pb)
5238 			return ka->objno - kb->objno;
5239 		if (ka->master != kb->master) {
5240 			if (!ka->master)
5241 				return -1;
5242 			if (!kb->master)
5243 				return 1;
5244 			ka = ka->master;
5245 			kb = kb->master;
5246 			}
5247 		return strcmp(ka->names->val, kb->names->val);
5248 		}
5249 	return strcmp(zalt[ka->alt], zalt[kb->alt]);
5250 	}
5251 
5252  static void
do_sort(KWctx * kw,KWcomp KWcmp)5253 do_sort(KWctx *kw, KWcomp KWcmp)
5254 {
5255 	KWctx *kw1, *kwm, **x, *x0[KWPlen];
5256 	const char *z0[KWPlen];
5257 	int i, n, na;
5258 
5259 	for(n = 0, kw1 = kw->kw; kw1; kw1 = kw1->next) {
5260 		++n;
5261 		reverse(&kw1->names);
5262 		}
5263 	if (n <= 1)
5264 		return;
5265 	x = n > KWPlen ? (KWctx**)Malloc(n*sizeof(KWctx*), "do_sort") : x0;
5266 	na = kw->nalt + 1;
5267 	zalt = na <= KWPlen ? z0 : (const char**)Malloc(na*sizeof(const char*), "do_sort");
5268 	memset(zalt, 0, na*sizeof(const char*));
5269 	for(n = 0, kw1 = kw->kw; kw1; kw1 = kw1->next) {
5270 		x[n++] = kw1;
5271 		if ((kwm = kw1->master))
5272 			kwm->master = kwm;
5273 		if (!zalt[i = kw1->alt]
5274 		 || strcmp(kw1->names->val, zalt[i]) < 0)
5275 			zalt[i] = kw1->names->val;
5276 		}
5277 	qsort(x, n--, sizeof(KWctx*), KWcmp);
5278 	for(i = 0; i < n; ++i)
5279 		x[i]->next = x[i+1];
5280 	x[n]->next = 0;
5281 	kw->kw = x[0];
5282 	if (zalt != z0)
5283 		free(zalt);
5284 	if (x != x0)
5285 		free(x);
5286 	}
5287 
5288  static void
ksort(KWcomp KWcmp)5289 ksort(KWcomp KWcmp)
5290 {
5291 	KWctx *kw, *kw1, **kwtop, **kwtop0, **kwbot;
5292 
5293 	kwtop = kwbot = KWStack;
5294 
5295 	for(*kwtop = &KWbase;; --kwtop) {
5296  top:
5297 		kw = *kwtop;
5298  top1:
5299 		while(kw) {
5300 			if ((kw1 = kw->pparent) && kw1->parstate != Sorted) {
5301 				*kwtop = kw;
5302 				kwtop0 = kwtop;
5303 				do {
5304 					kw1->parstate = Sorted;
5305 					*++kwtop = kw1;
5306 					}
5307 					while((kw1 = kw1->pparent) && kw1->parstate != Sorted);
5308 				if (kwtop > kwtop0)
5309 					goto top;
5310 				}
5311 			if (kw->kw) {
5312 				do_sort(kw, KWcmp);
5313 				if ((*kwtop = kw->next))
5314 					++kwtop;
5315 				kw = *kwtop = kw->kw;
5316 				goto top1;
5317 				}
5318 			kw = kw->next;
5319 			}
5320 		if (kwtop <= kwbot)
5321 			break;
5322 		}
5323 	}
5324 
5325  static void
pretty_ex1(KWctx * kw,KWctx * prevkw,KWctx * nextkw,int indent,int iinc,int needrev)5326 pretty_ex1(KWctx *kw, KWctx *prevkw, KWctx *nextkw, int indent, int iinc, int needrev)
5327 {
5328 	KWctx *kw0, *kw1, *kw2, *kwm, *kwp, *kwp0, **x, *y, *y1;
5329 	const char *suf, *z0[KWPlen];
5330 	int ep, i, i0, ia, j, n, na, np;
5331 
5332 	n = 0;
5333 	x = 0;
5334 	y = 0;
5335 	kw1 = kw->kw;
5336 	if (needrev == 1)
5337 		needrev = 2;
5338 	if ((kwp0 = kwp = kw->pparent) && (!kw->master || kw->master == kw)) {
5339 		for(;;) {
5340 			if (kwp->parstate != Printing) {
5341 				kwp->parstate = Printing;
5342 				for(kw1 = kwp->kw; kw1; kw1 = kw1->next)
5343 					kw1->pparent = 0;	/* avoid infinite loops */
5344 				}
5345 			for(kw1 = kwp->kw; kw1; kw1 = kw1->next)
5346 				++n;
5347 			if (!(kw1 = kwp->pparent))
5348 				break;
5349 			kwp = kwp->pparent = kw1;
5350 			}
5351 		np = n;
5352 		for(kw1 = kw->kw; kw1; kw1 = kw1->next)
5353 			++n;
5354 		y = y1 = (KWctx*)Malloc(np*sizeof(KWctx) + n*sizeof(KWctx*), "pretty_ex1");
5355 		x = (KWctx**)(y + np);
5356 		for(i = 0, kw1 = kw->kw; kw1; kw1 = kw1->next)
5357 			x[i++] = kw1;
5358 		i0 = i;
5359 		for(kwp = kwp0; kwp; kwp = kwp->pparent) {
5360 			j = i;
5361 			na = i + kwp->nalt;
5362 			for(kw1 = kwp->kw; kw1; kw1 = kw1->next, ++y1) {
5363 				memcpy(y1, kw1, sizeof(KWctx));
5364 				x[i++] = y1;
5365 				y1->alt += j;
5366 				}
5367 			}
5368 		if (!needrev) {
5369 			for(j = i0; j < n; ++j) {
5370 				kw1 = x[j];
5371 				kw1->nreq = -(kw1->nreq + 1);
5372 				}
5373 			zalt = ++na <= KWPlen ? z0
5374 				: (const char**)Malloc(na*sizeof(const char*), "pretty_ex1");
5375 			memset(zalt, 0, na*sizeof(const char*));
5376 			for(j = 0; j < n; ++j) {
5377 				kw1 = x[j];
5378 				if ((kwm = kw1->master))
5379 					kwm->master = kwm;
5380 				if (!zalt[i = kw1->alt]
5381 				 || strcmp(kw1->names->val, zalt[i]) < 0)
5382 					zalt[i] = kw1->names->val;
5383 				}
5384 			qsort(x, n, sizeof(KWctx*), kwcomp1);
5385 			if (zalt != z0)
5386 				free(zalt);
5387 			for(j = 0; j < n; ++j) {
5388 				kw1 = x[j];
5389 				if (kw1->nreq < 0) {
5390 					kw1->nreq = -(kw1->nreq + 1);
5391 					kw1->pparent = 0;
5392 					}
5393 				}
5394 			}
5395 		kw1 = x[0];
5396 		xmasteradj(x, n);
5397 		}
5398 	if (kw1) {
5399 		if (!x)
5400 			kw1 = masteradj(kw->kw);
5401 		ep = kw->req;
5402 		if (prevkw && kw->alt == prevkw->alt) {
5403 			ia = kw->master && kw->master == prevkw->master ? iinc : 0;
5404 			do_indent(indent + ia);
5405 			if (!prevkw->master || prevkw->master != kw->master) {
5406 				fputs("|\n", stdout);
5407 				do_indent(indent + ia);
5408 				putchar('(');
5409 				}
5410 			else
5411 				putchar('|');
5412 			}
5413 		else {
5414 			do_indent(indent);
5415 			if (kw->req)
5416 				putchar('('/*)*/);
5417 			else {
5418 				putchar('[');
5419 				if (nextkw && !nextkw->req && kw->alt == nextkw->alt) {
5420 					ep = 1;
5421 					do_indent1(iinc);
5422 					putchar('(');
5423 					indent += iinc;
5424 					}
5425 				}
5426 			}
5427 		do_indent1(iinc);
5428 		indent += iinc;
5429 		prkwname(kw, "\n", needrev);
5430 		i = 0;
5431 		kw0 = 0;
5432 		while(kw1) {
5433 			if (x)
5434 				kw2 = ++i >= n ? 0 : x[i];
5435 			else
5436 				kw2 = kw1->next;
5437 			pretty_ex1(kw1, kw0, kw2, indent, iinc, needrev);
5438 			kw0 = kw1;
5439 			kw1 = kw2;
5440 			}
5441 		if (x)
5442 			free(y);
5443 		do_indent(indent);
5444 		fputs(ep ? ")\n" : "]\n", stdout);
5445 		}
5446 	else {
5447 		if (prevkw && kw->alt == prevkw->alt
5448 		 && kw->master && kw->master == prevkw->master)
5449 			indent += iinc;
5450 		do_indent(indent);
5451 		suf = "\n";
5452 		if (prevkw && kw->alt == prevkw->alt) {
5453 			if (kw->master && kw->master != prevkw->master) {
5454 				fputs("|\n", stdout);
5455 				do_indent(indent);
5456 				fputs("( ", stdout);
5457 				}
5458 			else {
5459 				fputs("| ", stdout);
5460 				if (!kw->req)
5461 					goto rbcheck;
5462 				}
5463 			}
5464 		else if (kw->req) {
5465 			if (prevkw) {
5466 				if (prevkw->master != kw->master)
5467 					goto putlpar;
5468 				}
5469 			else if (kw != kw->master && kw->master) {
5470  putlpar:
5471 				fputs("( ", stdout);
5472 				}
5473 			}
5474 		else {
5475 			fputs("[ ", stdout);
5476  rbcheck:
5477 			if (!nextkw || nextkw->alt != kw->alt)
5478 				suf = " ]\n";
5479 			}
5480 		prkwname(kw, suf, needrev);
5481 		}
5482 	}
5483 
5484  static void
pretty_expand(int iinc,int needrev)5485 pretty_expand(int iinc, int needrev)
5486 {
5487 	KWctx *kw, *kw0, *kw1, *kw2;
5488 
5489 	if ((kw = KWbase.kw)) for(;;) {
5490 		masteradj(kw->kw);
5491 		fputs(KEYKIND[(kw->kind >> KWtopshift) & 3], stdout);
5492 		prkwname(kw, "\n", needrev);
5493 		kw0 = 0;
5494 		for(kw1 = kw->kw; kw1; kw1 = kw2) {
5495 			kw2 = kw1->next;
5496 			pretty_ex1(kw1, kw0, kw2, 0, iinc, needrev);
5497 			kw0 = kw1;
5498 			}
5499 		if (!(kw = kw->next))
5500 			break;
5501 		putchar('\n');
5502 		}
5503 	}
5504 
5505  static int
Str_option(char * s,char *** pav,int * want,StrList ** ps)5506 Str_option(char *s, char ***pav, int *want, StrList **ps)
5507 {
5508 	if (*++s || (s = *++*pav)) {
5509 		if (*s == '-' && ! s[1])
5510 			*want = 0;
5511 		else
5512 			*ps = new_StrList(s, *ps);
5513 		return 0;
5514 		}
5515 	return 1;
5516 	}
5517 
5518  static int
version(void)5519 version(void)
5520 {
5521 	printf("nidrgen version 20100528\n");
5522 	return 0;
5523 	}
5524 
5525  static int
tagcomp(const void * a,const void * b)5526 tagcomp(const void *a, const void *b)
5527 {
5528 	return strcmp(*(const char**)a, *(const char**)b);
5529 	}
5530 
5531  static int
unused_tags()5532 unused_tags()
5533 {
5534 	Taghash *th;
5535 	char **x;
5536 	size_t i, nbad;
5537 
5538 	nbad = 0;
5539 	for(th = (Taghash*)TagTab.lastdh; th; th = (Taghash*)th->hh.thread)
5540 		if (!th->uses)
5541 			++nbad;
5542 	if (!nbad)
5543 		return 0;
5544 	x = (char**)Malloc(nbad*sizeof(char*), "unsed_tags");
5545 	for(i = 0, th = (Taghash*)TagTab.lastdh; th; th = (Taghash*)th->hh.thread)
5546 		if (!th->uses)
5547 			x[i++] = th->hh.name;
5548 	fprintf(stderr, "%lu unused tag definition%s in %s:\n",
5549 		(unsigned long)nbad, "s" + (nbad == 1), tagfname);
5550 	if (nbad > 1)
5551 		qsort(x, nbad, sizeof(char*), tagcomp);
5552 	for(i = 0; i < nbad; ++i)
5553 		fprintf(stderr, "\t\"%s\"\n", x[i]);
5554 	free(x);
5555 	return 1;
5556 	}
5557 
5558  static int
defcomp(const void * a,const void * b)5559 defcomp(const void *a, const void *b)
5560 {
5561 	return strcmp((*(const Defhash**)a)->hh.name, (*(const Defhash**)b)->hh.name);
5562 	}
5563 
5564  static void
write_defs(FILE * f)5565 write_defs(FILE *f)
5566 {
5567 	Defhash *d, **x, **x1;
5568 	DefhashHead *dh;
5569 	size_t i, n;
5570 
5571 	n = DHTab.nent;
5572 	x = x1 = (Defhash**)Malloc(n*sizeof(Defhash*), "write_defs");
5573 	for(dh = DHTab.lastdh, i = 0; dh; dh = dh->thread) {
5574 		if (++i > n)
5575 			botch("lastdef count botch");
5576 		*x1++ = (Defhash*)dh;
5577 		}
5578 	qsort(x, n, sizeof(Defhash*), defcomp);
5579 	for(i = 0; i < n; ++i) {
5580 		d = x[i];
5581 		fprintf(f, d->qkeep ? "#define %s \"%s\"\n"
5582 			: "#define %s %s\n",
5583 			d->hh.name, d->value);
5584 		}
5585 	}
5586 
5587  int
main(int argc,char ** argv)5588 main(int argc, char **argv)
5589 {
5590 	FILE *f;
5591 	StrList *headers, *mtagname, *nsname, *outtagname;
5592 	char *defsout, *jfname, *ofname, *s, *se;
5593 	const char *kname, *libex, *libname;
5594 	int defwrite, dupcheck, hwant, libmode, needrev, nwant, pprint, sort, x;
5595 
5596 	KWStack[0] = &KWbase;
5597 	DHTab.nalloc  = (sizeof(Defhash) + sizeof(void*) - 1)/sizeof(void*);
5598 	TagTab.nalloc = (sizeof(Taghash) + sizeof(void*) - 1)/sizeof(void*);
5599 	KWbase.names = new_StrList("$top",0);
5600 	progname = argv[0];
5601 	if (argc <= 1)
5602  usage1:	return usage(1);
5603 	headers = mtagname = nsname = outtagname = 0;
5604 	kname = libex = libname = defsout = jfname = ofname = 0;
5605 	dupcheck = hwant = needrev = nwant = 1;
5606 	defwrite = libmode = pprint = sort = 0;
5607  nextopt:
5608 	while((s = *++argv) && *s == '-' && s[1]) {
5609 		while(*++s)
5610 		switch(*s) {
5611 		 case 'D':
5612 			defwrite = libexpand = 1;
5613 			libex = "-D";
5614 			break;
5615 		 case 'T':
5616 			if (Str_option(s, &argv, &hwant, &outtagname))
5617 				goto usage1;
5618 			goto nextopt;
5619 		 case 'd':
5620 			dupcheck = 0;
5621 			break;
5622 		 case 'e':
5623 			expand = 1;
5624 			break;
5625 		 case 'f':
5626 			wantfuncs = 0;
5627 			break;
5628 		 case 'g':
5629 			guikeywds = libexpand = 1;
5630 			libex = "-g";
5631 			break;
5632 		 case 'G':
5633 			dfltgroup = 0;
5634 			break;
5635 		 case 'h':
5636 			if (Str_option(s, &argv, &hwant, &headers))
5637 				goto usage1;
5638 			goto nextopt;
5639 		 case 'j':
5640 			if (!*++s && !(s = *++argv))
5641 				goto usage1;
5642 			jfname = s;
5643 			libexpand = 1;
5644 			libex = "-j";
5645 			goto nextopt;
5646 		 case 'k':
5647 			if (!*++s && !(s = *++argv))
5648 				goto usage1;
5649 			kname = s;
5650 			libmode = 1;
5651 			goto nextopt;
5652 		 case 'l':
5653 			libmode = 1;
5654 			break;
5655 		 case 'L':
5656  have_L:
5657 			if (*++s)
5658 				libname = s;
5659 			else if (!(libname = *++argv))
5660 				return usage(1);
5661 			goto nextopt;
5662 		 case 'm':
5663 			if (Str_option(s, &argv, &hwant, &mtagname))
5664 				goto usage1;
5665 			goto nextopt;
5666 		 case 'n':
5667 			if (Str_option(s, &argv, &nwant, &nsname))
5668 				goto usage1;
5669 			goto nextopt;
5670 		 case 't':
5671 			ignoretags = 1;
5672 			break;
5673 		 case 's':
5674 			sort = 1;
5675 			needrev = 0;
5676 			libex = "-s";
5677 			for(;;++s) {
5678 				switch(s[1]) {
5679 				  case 'L': ++s; goto have_L;
5680 				  case 'e': expand = 1;
5681 					    continue;
5682 				  case 'f': wantfuncs = 0;
5683 				  case 'p': continue;
5684 				  }
5685 				break;
5686 				}
5687 			/* no break */
5688 		 case 'p':
5689 			libexpand = 1;
5690 			pprint = 2;
5691 			if (!libex)
5692 				libex = "-p";
5693 			for(;;++s) {
5694 				switch(s[1]) {
5695 				  case 'L':
5696 					++s;
5697 					goto have_L;
5698 				  case 'e':
5699 					expand = 1;
5700 					continue;
5701 				  case 'f':
5702 					wantfuncs = 0;
5703 					continue;
5704 				  case 's':
5705 					sort = 1;
5706 					needrev = 0;
5707 					continue;
5708 				  case 't':
5709 					ignoretags = 1;
5710 					continue;
5711 				  }
5712 				break;
5713 				}
5714 			if (*++s) {
5715 				pprint = (int)strtol(s,&se,10);
5716 				if (pprint < 1 || se)
5717 					goto usage1;
5718 				}
5719 			goto nextopt;
5720 		 case 'v':
5721 			return version();
5722 		 case 'w':
5723 			startwarn = 0;
5724 			break;
5725 		 case '?':
5726 			return usage(s[1] != 0);
5727 		 case '-':
5728 			if (!strcmp(++s,"help"))
5729 				return usage(0);
5730 			if (!strcmp(s,"version"))
5731 				return version();
5732 			if (!*s) {
5733 				s = *++argv;
5734 				goto argsdone;
5735 				}
5736 			/* no break */
5737 		  default:
5738 			goto usage1;
5739 		  }
5740 		}
5741  argsdone:
5742 	if (libname) {
5743 		if (s && argv[1] && argv[2])
5744 			return usage(1);
5745 		if ((defsout = s))
5746 			ofname = argv[1];
5747 		if (mtagname) {
5748 			fprintf(stderr, "\n%s: ignoreing -m due to -L\n", progname);
5749 			mtagname = 0;
5750 			}
5751 		goto lcheck;
5752 		}
5753 	if (!s || (argv[1] && argv[2] && argv[3] && argv[4]))
5754 		return usage(1);
5755 	if ((tagfname = argv[1])) {
5756 		specfile = s;
5757 		s = tagfname;
5758 		lastseen = Saw_kwname;
5759 		lastkw1 = &KWbase;
5760 		if ((defsout = argv[2]))
5761 			ofname = argv[3];
5762 		}
5763 	else if (mtagout) {
5764 		fprintf(stderr, "%s: -m specified but no tagfile given.\n", progname);
5765 		return 1;
5766 		}
5767 	if (*s == '-' && !s[1])
5768 		yyin = stdin;
5769 	else if (!(yyin = fopen(infname = s, "r"))) {
5770 		cantopen(s);
5771 		return 1;
5772 		}
5773 	if (specfile)
5774 		tagin = yyin;
5775 	if ((mtagname && (!(mtagout = fopen(s = mtagname->val, "w"))))
5776 	 || (outtagname && !(tagout = fopen(s = outtagname->val, "w")))) {
5777 		cantopen(s);
5778 		return 1;
5779 		}
5780  lcheck:
5781 	if (libmode) {
5782 		wantfuncs |= 2;
5783 		if (libexpand && kname) {
5784 			libmode = 0;
5785 			fprintf(stderr, "\n%s: ignoring -k due to %s\n",
5786 				progname, libex);
5787 			}
5788 		}
5789 	else
5790 		libexpand = 0;
5791 	if (libname)
5792 #ifndef NO_NIDR_DYNLIB
5793 		libread1(0, libname, 0, 2);
5794 #else
5795 		{
5796 		fprintf(stderr, "\ndlopen for \"%s\" is NOT SUPPORTED\n", libname);
5797 		return usage(1);
5798 		}
5799 #endif
5800 	else if ((x = yylex())) {
5801 		fprintf(stderr, "\n%s: Surprise return %d from yylex()\n", progname, x);
5802 		return x;
5803 		}
5804 	if (mtagout)
5805 		fclose(mtagout);
5806 	if (tagout)
5807 		fclose(tagout);
5808 	if (tagout || mtagout)
5809 		goto done;
5810 	if (Br_top > Br_stack) {
5811 		fputs("Missing ", stderr);
5812 		do putc(/*[*/ *Br_top-- == '(' ? ')' : ']', stderr);
5813 			while(Br_top >Br_stack);
5814 		fputs(" at end of file.\n", stderr);
5815 		return 1;
5816 		}
5817 	if (nsquawk > liberror)
5818 		return 1;
5819 	if (tagfname && unused_tags())
5820 		return 1;
5821 	if (KWbase.kw) {
5822 		paradj(needrev);
5823 		if (dupcheck)
5824 			dup_check();
5825 		}
5826 	if (jfname)
5827 		ofname = 0;
5828 	else if (ofname && !freopen(ofname, "w", stdout)) {
5829 		fprintf(stderr, "%s: Cannot open output file \"%s\"\n", progname, ofname);
5830 		return 1;
5831 		}
5832 	if (KWbase.kw) {
5833 		if (pprint) {
5834 			if (expand) {
5835 				if (sort)
5836 					ksort(kwcomp1);
5837 				pretty_expand(pprint, needrev);
5838 				}
5839 			else {
5840 				if (sort)
5841 					ksort(kwcomp2);
5842 				pretty_print(pprint, needrev);
5843 				}
5844 			}
5845 		else if (!defwrite) {
5846 			if (jfname)
5847 				jOutput(jfname);
5848 			else
5849 				Output(headers, nsname, hwant, kname,
5850 					guikeywds ? 0 : libmode, nwant);
5851 			}
5852 		else if (DHTab.lastdh)
5853 			write_defs(stdout);
5854 		}
5855 	if (!defwrite && defsout) {
5856 		f = fopen(defsout,"w");
5857 		if (!f) {
5858 			fprintf(stderr, "%s:  cannot open defs file \"%s\"\n",
5859 				progname, defsout);
5860 			return 1;
5861 			}
5862 		write_defs(f);
5863 		fclose(f);
5864 		}
5865  done:
5866 	return dupnames > 0 ? 1 : liberror ? 2 : 0;
5867 	}
5868