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