Commit ce9e8982 ce9e898286c31564511c893480c66b25266f01f0 by Sergey Poznyakoff

Remove generated file, add source instead

1 parent 54a7ce71
1 /* A Bison parser, made by GNU Bison 2.3. */
2
3 /* Skeleton implementation for Bison's Yacc-like parsers in C
4
5 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
6 Free Software Foundation, Inc.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23 /* As a special exception, you may create a larger work that contains
24 part or all of the Bison parser skeleton and distribute that work
25 under terms of your choice, so long as that work isn't itself a
26 parser generator using the skeleton or a modified version thereof
27 as a parser skeleton. Alternatively, if you modify or redistribute
28 the parser skeleton itself, you may (at your option) remove this
29 special exception, which will cause the skeleton and the resulting
30 Bison output files to be licensed under the GNU General Public
31 License without this special exception.
32
33 This special exception was added by the Free Software Foundation in
34 version 2.2 of Bison. */
35
36 /* C LALR(1) parser skeleton written by Richard Stallman, by
37 simplifying the original so-called "semantic" parser. */
38
39 /* All symbols defined below should begin with mu_cfg_yy or YY, to avoid
40 infringing on user name space. This should be done even for local
41 variables, as they might otherwise be expanded by user macros.
42 There are some unavoidable exceptions within include files to
43 define necessary library symbols; they are noted "INFRINGES ON
44 USER NAME SPACE" below. */
45
46 /* Identify Bison output. */
47 #define YYBISON 1
48
49 /* Bison version. */
50 #define YYBISON_VERSION "2.3"
51
52 /* Skeleton name. */
53 #define YYSKELETON_NAME "yacc.c"
54
55 /* Pure parsers. */
56 #define YYPURE 0
57
58 /* Using locations. */
59 #define YYLSP_NEEDED 0
60
61
62
63 /* Tokens. */
64 #ifndef YYTOKENTYPE
65 # define YYTOKENTYPE
66 /* Put the tokens into the symbol table, so that GDB and other debuggers
67 know about them. */
68 enum mu_cfg_yytokentype {
69 MU_CFG_EOL_TOKEN = 258,
70 MU_CFG_START_TOKEN = 259,
71 MU_CFG_END_TOKEN = 260,
72 MU_CFG_STRING_TOKEN = 261
73 };
74 #endif
75 /* Tokens. */
76 #define MU_CFG_EOL_TOKEN 258
77 #define MU_CFG_START_TOKEN 259
78 #define MU_CFG_END_TOKEN 260
79 #define MU_CFG_STRING_TOKEN 261
80
81
82
83
84 /* Copy the first part of user declarations. */
85 #line 1 "cfg_parser.y"
86
87 /* cfg_parser.y -- general-purpose configuration file parser
88 Copyright (C) 2007 Free Software Foundation, Inc.
89
90 GNU Mailutils is free software; you can redistribute it and/or
91 modify it under the terms of the GNU General Public License as
92 published by the Free Software Foundation; either version 3, or (at
93 your option) any later version.
94
95 This program is distributed in the hope that it will be useful, but
96 WITHOUT ANY WARRANTY; without even the implied warranty of
97 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
98 General Public License for more details.
99
100 You should have received a copy of the GNU General Public License
101 along with this program. If not, see <http://www.gnu.org/licenses/>.
102 */
103
104 #include <stdio.h>
105 #include <stdlib.h>
106 #include <stdarg.h>
107 #include <string.h>
108 #include <netdb.h>
109 #include "intprops.h"
110 #include <mailutils/nls.h>
111 #include <mailutils/cfg.h>
112 #include <mailutils/errno.h>
113 #include <mailutils/error.h>
114
115 static mu_cfg_node_t *parse_tree;
116 mu_cfg_locus_t mu_cfg_locus;
117 int mu_cfg_tie_in;
118
119 static int _mu_cfg_errcnt;
120 static mu_cfg_lexer_t _mu_cfg_lexer;
121 mu_cfg_perror_t mu_cfg_perror;
122 static void *_mu_cfg_lexer_data;
123 mu_cfg_alloc_t _mu_cfg_alloc;
124 mu_cfg_free_t _mu_cfg_free;
125
126 static int
127 mu_cfg_yyerror (char *s)
128 {
129 mu_cfg_perror (_mu_cfg_lexer_data, &mu_cfg_locus, "%s", s);
130 return 0;
131 }
132
133 static int
134 mu_cfg_yylex ()
135 {
136 return _mu_cfg_lexer (_mu_cfg_lexer_data);
137 }
138
139 static mu_cfg_node_t *
140 mu_cfg_alloc_node (enum mu_cfg_node_type type, mu_cfg_locus_t *loc,
141 char *tag, char *label, mu_cfg_node_t *node)
142 {
143 char *p;
144 mu_cfg_node_t *np;
145 size_t size = sizeof *np + strlen (tag) + 1
146 + (label ? (strlen (label) + 1) : 0);
147 np = _mu_cfg_alloc (size);
148 if (!np)
149 {
150 mu_cfg_perror (_mu_cfg_lexer_data, &mu_cfg_locus,
151 _("Not enough memory"));
152 abort();
153 }
154 np->type = type;
155 np->locus = *loc;
156 p = (char*) (np + 1);
157 np->tag_name = p;
158 strcpy (p, tag);
159 p += strlen (p) + 1;
160 if (label)
161 {
162 np->tag_label = p;
163 strcpy (p, label);
164 }
165 else
166 np->tag_label = label;
167 np->node = node;
168 np->next = NULL;
169 return np;
170 }
171
172 static void
173 _mu_cfg_default_perror (void *ptr, const mu_cfg_locus_t *loc,
174 const char *fmt, ...)
175 {
176 va_list ap;
177
178 fprintf (stderr, "%s:", loc->file ? loc->file : _("unknown file"));
179 if (loc->line > 0)
180 fprintf (stderr, "%lu", (unsigned long) loc->line);
181 else
182 fprintf (stderr, "%s", _("unknown line"));
183 fprintf (stderr, ": ");
184 va_start (ap, fmt);
185 vfprintf (stderr, fmt, ap);
186 va_end (ap);
187 fprintf (stderr, "\n");
188 }
189
190
191
192 /* Enabling traces. */
193 #ifndef YYDEBUG
194 # define YYDEBUG 1
195 #endif
196
197 /* Enabling verbose error messages. */
198 #ifdef YYERROR_VERBOSE
199 # undef YYERROR_VERBOSE
200 # define YYERROR_VERBOSE 1
201 #else
202 # define YYERROR_VERBOSE 0
203 #endif
204
205 /* Enabling the token table. */
206 #ifndef YYTOKEN_TABLE
207 # define YYTOKEN_TABLE 0
208 #endif
209
210 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
211 typedef union YYSTYPE
212 #line 115 "cfg_parser.y"
213 {
214 mu_cfg_node_t node;
215 mu_cfg_node_t *pnode;
216 struct
217 {
218 mu_cfg_node_t *head, *tail;
219 } nodelist;
220 char *string;
221 }
222 /* Line 187 of yacc.c. */
223 #line 224 "cfg_parser.c"
224 YYSTYPE;
225 # define mu_cfg_yystype YYSTYPE /* obsolescent; will be withdrawn */
226 # define YYSTYPE_IS_DECLARED 1
227 # define YYSTYPE_IS_TRIVIAL 1
228 #endif
229
230
231
232 /* Copy the second part of user declarations. */
233
234
235 /* Line 216 of yacc.c. */
236 #line 237 "cfg_parser.c"
237
238 #ifdef short
239 # undef short
240 #endif
241
242 #ifdef YYTYPE_UINT8
243 typedef YYTYPE_UINT8 mu_cfg_yytype_uint8;
244 #else
245 typedef unsigned char mu_cfg_yytype_uint8;
246 #endif
247
248 #ifdef YYTYPE_INT8
249 typedef YYTYPE_INT8 mu_cfg_yytype_int8;
250 #elif (defined __STDC__ || defined __C99__FUNC__ \
251 || defined __cplusplus || defined _MSC_VER)
252 typedef signed char mu_cfg_yytype_int8;
253 #else
254 typedef short int mu_cfg_yytype_int8;
255 #endif
256
257 #ifdef YYTYPE_UINT16
258 typedef YYTYPE_UINT16 mu_cfg_yytype_uint16;
259 #else
260 typedef unsigned short int mu_cfg_yytype_uint16;
261 #endif
262
263 #ifdef YYTYPE_INT16
264 typedef YYTYPE_INT16 mu_cfg_yytype_int16;
265 #else
266 typedef short int mu_cfg_yytype_int16;
267 #endif
268
269 #ifndef YYSIZE_T
270 # ifdef __SIZE_TYPE__
271 # define YYSIZE_T __SIZE_TYPE__
272 # elif defined size_t
273 # define YYSIZE_T size_t
274 # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
275 || defined __cplusplus || defined _MSC_VER)
276 # include <stddef.h> /* INFRINGES ON USER NAME SPACE */
277 # define YYSIZE_T size_t
278 # else
279 # define YYSIZE_T unsigned int
280 # endif
281 #endif
282
283 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
284
285 #ifndef YY_
286 # if YYENABLE_NLS
287 # if ENABLE_NLS
288 # include <libintl.h> /* INFRINGES ON USER NAME SPACE */
289 # define YY_(msgid) dgettext ("bison-runtime", msgid)
290 # endif
291 # endif
292 # ifndef YY_
293 # define YY_(msgid) msgid
294 # endif
295 #endif
296
297 /* Suppress unused-variable warnings by "using" E. */
298 #if ! defined lint || defined __GNUC__
299 # define YYUSE(e) ((void) (e))
300 #else
301 # define YYUSE(e) /* empty */
302 #endif
303
304 /* Identity function, used to suppress warnings about constant conditions. */
305 #ifndef lint
306 # define YYID(n) (n)
307 #else
308 #if (defined __STDC__ || defined __C99__FUNC__ \
309 || defined __cplusplus || defined _MSC_VER)
310 static int
311 YYID (int i)
312 #else
313 static int
314 YYID (i)
315 int i;
316 #endif
317 {
318 return i;
319 }
320 #endif
321
322 #if ! defined mu_cfg_yyoverflow || YYERROR_VERBOSE
323
324 /* The parser invokes alloca or malloc; define the necessary symbols. */
325
326 # ifdef YYSTACK_USE_ALLOCA
327 # if YYSTACK_USE_ALLOCA
328 # ifdef __GNUC__
329 # define YYSTACK_ALLOC __builtin_alloca
330 # elif defined __BUILTIN_VA_ARG_INCR
331 # include <alloca.h> /* INFRINGES ON USER NAME SPACE */
332 # elif defined _AIX
333 # define YYSTACK_ALLOC __alloca
334 # elif defined _MSC_VER
335 # include <malloc.h> /* INFRINGES ON USER NAME SPACE */
336 # define alloca _alloca
337 # else
338 # define YYSTACK_ALLOC alloca
339 # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
340 || defined __cplusplus || defined _MSC_VER)
341 # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
342 # ifndef _STDLIB_H
343 # define _STDLIB_H 1
344 # endif
345 # endif
346 # endif
347 # endif
348 # endif
349
350 # ifdef YYSTACK_ALLOC
351 /* Pacify GCC's `empty if-body' warning. */
352 # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
353 # ifndef YYSTACK_ALLOC_MAXIMUM
354 /* The OS might guarantee only one guard page at the bottom of the stack,
355 and a page size can be as small as 4096 bytes. So we cannot safely
356 invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
357 to allow for a few compiler-allocated temporary stack slots. */
358 # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
359 # endif
360 # else
361 # define YYSTACK_ALLOC YYMALLOC
362 # define YYSTACK_FREE YYFREE
363 # ifndef YYSTACK_ALLOC_MAXIMUM
364 # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
365 # endif
366 # if (defined __cplusplus && ! defined _STDLIB_H \
367 && ! ((defined YYMALLOC || defined malloc) \
368 && (defined YYFREE || defined free)))
369 # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
370 # ifndef _STDLIB_H
371 # define _STDLIB_H 1
372 # endif
373 # endif
374 # ifndef YYMALLOC
375 # define YYMALLOC malloc
376 # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
377 || defined __cplusplus || defined _MSC_VER)
378 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
379 # endif
380 # endif
381 # ifndef YYFREE
382 # define YYFREE free
383 # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
384 || defined __cplusplus || defined _MSC_VER)
385 void free (void *); /* INFRINGES ON USER NAME SPACE */
386 # endif
387 # endif
388 # endif
389 #endif /* ! defined mu_cfg_yyoverflow || YYERROR_VERBOSE */
390
391
392 #if (! defined mu_cfg_yyoverflow \
393 && (! defined __cplusplus \
394 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
395
396 /* A type that is properly aligned for any stack member. */
397 union mu_cfg_yyalloc
398 {
399 mu_cfg_yytype_int16 mu_cfg_yyss;
400 YYSTYPE mu_cfg_yyvs;
401 };
402
403 /* The size of the maximum gap between one aligned stack and the next. */
404 # define YYSTACK_GAP_MAXIMUM (sizeof (union mu_cfg_yyalloc) - 1)
405
406 /* The size of an array large to enough to hold all stacks, each with
407 N elements. */
408 # define YYSTACK_BYTES(N) \
409 ((N) * (sizeof (mu_cfg_yytype_int16) + sizeof (YYSTYPE)) \
410 + YYSTACK_GAP_MAXIMUM)
411
412 /* Copy COUNT objects from FROM to TO. The source and destination do
413 not overlap. */
414 # ifndef YYCOPY
415 # if defined __GNUC__ && 1 < __GNUC__
416 # define YYCOPY(To, From, Count) \
417 __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
418 # else
419 # define YYCOPY(To, From, Count) \
420 do \
421 { \
422 YYSIZE_T mu_cfg_yyi; \
423 for (mu_cfg_yyi = 0; mu_cfg_yyi < (Count); mu_cfg_yyi++) \
424 (To)[mu_cfg_yyi] = (From)[mu_cfg_yyi]; \
425 } \
426 while (YYID (0))
427 # endif
428 # endif
429
430 /* Relocate STACK from its old location to the new one. The
431 local variables YYSIZE and YYSTACKSIZE give the old and new number of
432 elements in the stack, and YYPTR gives the new location of the
433 stack. Advance YYPTR to a properly aligned location for the next
434 stack. */
435 # define YYSTACK_RELOCATE(Stack) \
436 do \
437 { \
438 YYSIZE_T mu_cfg_yynewbytes; \
439 YYCOPY (&mu_cfg_yyptr->Stack, Stack, mu_cfg_yysize); \
440 Stack = &mu_cfg_yyptr->Stack; \
441 mu_cfg_yynewbytes = mu_cfg_yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
442 mu_cfg_yyptr += mu_cfg_yynewbytes / sizeof (*mu_cfg_yyptr); \
443 } \
444 while (YYID (0))
445
446 #endif
447
448 /* YYFINAL -- State number of the termination state. */
449 #define YYFINAL 10
450 /* YYLAST -- Last index in YYTABLE. */
451 #define YYLAST 17
452
453 /* YYNTOKENS -- Number of terminals. */
454 #define YYNTOKENS 7
455 /* YYNNTS -- Number of nonterminals. */
456 #define YYNNTS 8
457 /* YYNRULES -- Number of rules. */
458 #define YYNRULES 12
459 /* YYNRULES -- Number of states. */
460 #define YYNSTATES 19
461
462 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
463 #define YYUNDEFTOK 2
464 #define YYMAXUTOK 261
465
466 #define YYTRANSLATE(YYX) \
467 ((unsigned int) (YYX) <= YYMAXUTOK ? mu_cfg_yytranslate[YYX] : YYUNDEFTOK)
468
469 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
470 static const mu_cfg_yytype_uint8 mu_cfg_yytranslate[] =
471 {
472 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
473 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
474 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
475 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
476 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
477 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
478 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
479 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
480 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
481 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
482 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
483 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
484 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
485 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
486 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
487 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
488 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
489 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
490 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
491 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
492 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
493 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
494 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
495 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
496 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
497 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
498 5, 6
499 };
500
501 #if YYDEBUG
502 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
503 YYRHS. */
504 static const mu_cfg_yytype_uint8 mu_cfg_yyprhs[] =
505 {
506 0, 0, 3, 5, 7, 10, 11, 13, 15, 18,
507 24, 25, 26
508 };
509
510 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
511 static const mu_cfg_yytype_int8 mu_cfg_yyrhs[] =
512 {
513 8, 0, -1, 9, -1, 12, -1, 9, 12, -1,
514 -1, 11, -1, 3, -1, 11, 3, -1, 4, 10,
515 9, 5, 3, -1, -1, -1, 6, 13, 6, 14,
516 3, -1
517 };
518
519 /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
520 static const mu_cfg_yytype_uint8 mu_cfg_yyrline[] =
521 {
522 0, 127, 127, 133, 137, 145, 146, 149, 150, 153,
523 170, 171, 170
524 };
525 #endif
526
527 #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
528 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
529 First, the terminals, then, starting at YYNTOKENS, nonterminals. */
530 static const char *const mu_cfg_yytname[] =
531 {
532 "$end", "error", "$undefined", "MU_CFG_EOL_TOKEN", "MU_CFG_START_TOKEN",
533 "MU_CFG_END_TOKEN", "MU_CFG_STRING_TOKEN", "$accept", "input", "taglist",
534 "opt_eol", "eol", "tag", "@1", "@2", 0
535 };
536 #endif
537
538 # ifdef YYPRINT
539 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
540 token YYLEX-NUM. */
541 static const mu_cfg_yytype_uint16 mu_cfg_yytoknum[] =
542 {
543 0, 256, 257, 258, 259, 260, 261
544 };
545 # endif
546
547 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
548 static const mu_cfg_yytype_uint8 mu_cfg_yyr1[] =
549 {
550 0, 7, 8, 9, 9, 10, 10, 11, 11, 12,
551 13, 14, 12
552 };
553
554 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
555 static const mu_cfg_yytype_uint8 mu_cfg_yyr2[] =
556 {
557 0, 2, 1, 1, 2, 0, 1, 1, 2, 5,
558 0, 0, 5
559 };
560
561 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
562 STATE-NUM when YYTABLE doesn't specify something else to do. Zero
563 means the default is an error. */
564 static const mu_cfg_yytype_uint8 mu_cfg_yydefact[] =
565 {
566 0, 5, 10, 0, 2, 3, 7, 0, 6, 0,
567 1, 4, 0, 8, 11, 0, 0, 9, 12
568 };
569
570 /* YYDEFGOTO[NTERM-NUM]. */
571 static const mu_cfg_yytype_int8 mu_cfg_yydefgoto[] =
572 {
573 -1, 3, 4, 7, 8, 5, 9, 16
574 };
575
576 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
577 STATE-NUM. */
578 #define YYPACT_NINF -5
579 static const mu_cfg_yytype_int8 mu_cfg_yypact[] =
580 {
581 0, 2, -5, 7, 0, -5, -5, 0, 6, 4,
582 -5, -5, -3, -5, -5, 8, 9, -5, -5
583 };
584
585 /* YYPGOTO[NTERM-NUM]. */
586 static const mu_cfg_yytype_int8 mu_cfg_yypgoto[] =
587 {
588 -5, -5, 10, -5, -5, -4, -5, -5
589 };
590
591 /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
592 positive, shift that token. If negative, reduce the rule which
593 number is the opposite. If zero, do what YYDEFACT says.
594 If YYTABLE_NINF, syntax error. */
595 #define YYTABLE_NINF -1
596 static const mu_cfg_yytype_uint8 mu_cfg_yytable[] =
597 {
598 11, 1, 15, 2, 1, 6, 2, 10, 11, 13,
599 14, 17, 18, 0, 0, 0, 0, 12
600 };
601
602 static const mu_cfg_yytype_int8 mu_cfg_yycheck[] =
603 {
604 4, 4, 5, 6, 4, 3, 6, 0, 12, 3,
605 6, 3, 3, -1, -1, -1, -1, 7
606 };
607
608 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
609 symbol of state STATE-NUM. */
610 static const mu_cfg_yytype_uint8 mu_cfg_yystos[] =
611 {
612 0, 4, 6, 8, 9, 12, 3, 10, 11, 13,
613 0, 12, 9, 3, 6, 5, 14, 3, 3
614 };
615
616 #define mu_cfg_yyerrok (mu_cfg_yyerrstatus = 0)
617 #define mu_cfg_yyclearin (mu_cfg_yychar = YYEMPTY)
618 #define YYEMPTY (-2)
619 #define YYEOF 0
620
621 #define YYACCEPT goto mu_cfg_yyacceptlab
622 #define YYABORT goto mu_cfg_yyabortlab
623 #define YYERROR goto mu_cfg_yyerrorlab
624
625
626 /* Like YYERROR except do call mu_cfg_yyerror. This remains here temporarily
627 to ease the transition to the new meaning of YYERROR, for GCC.
628 Once GCC version 2 has supplanted version 1, this can go. */
629
630 #define YYFAIL goto mu_cfg_yyerrlab
631
632 #define YYRECOVERING() (!!mu_cfg_yyerrstatus)
633
634 #define YYBACKUP(Token, Value) \
635 do \
636 if (mu_cfg_yychar == YYEMPTY && mu_cfg_yylen == 1) \
637 { \
638 mu_cfg_yychar = (Token); \
639 mu_cfg_yylval = (Value); \
640 mu_cfg_yytoken = YYTRANSLATE (mu_cfg_yychar); \
641 YYPOPSTACK (1); \
642 goto mu_cfg_yybackup; \
643 } \
644 else \
645 { \
646 mu_cfg_yyerror (YY_("syntax error: cannot back up")); \
647 YYERROR; \
648 } \
649 while (YYID (0))
650
651
652 #define YYTERROR 1
653 #define YYERRCODE 256
654
655
656 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
657 If N is 0, then set CURRENT to the empty location which ends
658 the previous symbol: RHS[0] (always defined). */
659
660 #define YYRHSLOC(Rhs, K) ((Rhs)[K])
661 #ifndef YYLLOC_DEFAULT
662 # define YYLLOC_DEFAULT(Current, Rhs, N) \
663 do \
664 if (YYID (N)) \
665 { \
666 (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
667 (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
668 (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
669 (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
670 } \
671 else \
672 { \
673 (Current).first_line = (Current).last_line = \
674 YYRHSLOC (Rhs, 0).last_line; \
675 (Current).first_column = (Current).last_column = \
676 YYRHSLOC (Rhs, 0).last_column; \
677 } \
678 while (YYID (0))
679 #endif
680
681
682 /* YY_LOCATION_PRINT -- Print the location on the stream.
683 This macro was not mandated originally: define only if we know
684 we won't break user code: when these are the locations we know. */
685
686 #ifndef YY_LOCATION_PRINT
687 # if YYLTYPE_IS_TRIVIAL
688 # define YY_LOCATION_PRINT(File, Loc) \
689 fprintf (File, "%d.%d-%d.%d", \
690 (Loc).first_line, (Loc).first_column, \
691 (Loc).last_line, (Loc).last_column)
692 # else
693 # define YY_LOCATION_PRINT(File, Loc) ((void) 0)
694 # endif
695 #endif
696
697
698 /* YYLEX -- calling `mu_cfg_yylex' with the right arguments. */
699
700 #ifdef YYLEX_PARAM
701 # define YYLEX mu_cfg_yylex (YYLEX_PARAM)
702 #else
703 # define YYLEX mu_cfg_yylex ()
704 #endif
705
706 /* Enable debugging if requested. */
707 #if YYDEBUG
708
709 # ifndef YYFPRINTF
710 # include <stdio.h> /* INFRINGES ON USER NAME SPACE */
711 # define YYFPRINTF fprintf
712 # endif
713
714 # define YYDPRINTF(Args) \
715 do { \
716 if (mu_cfg_yydebug) \
717 YYFPRINTF Args; \
718 } while (YYID (0))
719
720 # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
721 do { \
722 if (mu_cfg_yydebug) \
723 { \
724 YYFPRINTF (stderr, "%s ", Title); \
725 mu_cfg_yy_symbol_print (stderr, \
726 Type, Value); \
727 YYFPRINTF (stderr, "\n"); \
728 } \
729 } while (YYID (0))
730
731
732 /*--------------------------------.
733 | Print this symbol on YYOUTPUT. |
734 `--------------------------------*/
735
736 /*ARGSUSED*/
737 #if (defined __STDC__ || defined __C99__FUNC__ \
738 || defined __cplusplus || defined _MSC_VER)
739 static void
740 mu_cfg_yy_symbol_value_print (FILE *mu_cfg_yyoutput, int mu_cfg_yytype, YYSTYPE const * const mu_cfg_yyvaluep)
741 #else
742 static void
743 mu_cfg_yy_symbol_value_print (mu_cfg_yyoutput, mu_cfg_yytype, mu_cfg_yyvaluep)
744 FILE *mu_cfg_yyoutput;
745 int mu_cfg_yytype;
746 YYSTYPE const * const mu_cfg_yyvaluep;
747 #endif
748 {
749 if (!mu_cfg_yyvaluep)
750 return;
751 # ifdef YYPRINT
752 if (mu_cfg_yytype < YYNTOKENS)
753 YYPRINT (mu_cfg_yyoutput, mu_cfg_yytoknum[mu_cfg_yytype], *mu_cfg_yyvaluep);
754 # else
755 YYUSE (mu_cfg_yyoutput);
756 # endif
757 switch (mu_cfg_yytype)
758 {
759 default:
760 break;
761 }
762 }
763
764
765 /*--------------------------------.
766 | Print this symbol on YYOUTPUT. |
767 `--------------------------------*/
768
769 #if (defined __STDC__ || defined __C99__FUNC__ \
770 || defined __cplusplus || defined _MSC_VER)
771 static void
772 mu_cfg_yy_symbol_print (FILE *mu_cfg_yyoutput, int mu_cfg_yytype, YYSTYPE const * const mu_cfg_yyvaluep)
773 #else
774 static void
775 mu_cfg_yy_symbol_print (mu_cfg_yyoutput, mu_cfg_yytype, mu_cfg_yyvaluep)
776 FILE *mu_cfg_yyoutput;
777 int mu_cfg_yytype;
778 YYSTYPE const * const mu_cfg_yyvaluep;
779 #endif
780 {
781 if (mu_cfg_yytype < YYNTOKENS)
782 YYFPRINTF (mu_cfg_yyoutput, "token %s (", mu_cfg_yytname[mu_cfg_yytype]);
783 else
784 YYFPRINTF (mu_cfg_yyoutput, "nterm %s (", mu_cfg_yytname[mu_cfg_yytype]);
785
786 mu_cfg_yy_symbol_value_print (mu_cfg_yyoutput, mu_cfg_yytype, mu_cfg_yyvaluep);
787 YYFPRINTF (mu_cfg_yyoutput, ")");
788 }
789
790 /*------------------------------------------------------------------.
791 | mu_cfg_yy_stack_print -- Print the state stack from its BOTTOM up to its |
792 | TOP (included). |
793 `------------------------------------------------------------------*/
794
795 #if (defined __STDC__ || defined __C99__FUNC__ \
796 || defined __cplusplus || defined _MSC_VER)
797 static void
798 mu_cfg_yy_stack_print (mu_cfg_yytype_int16 *bottom, mu_cfg_yytype_int16 *top)
799 #else
800 static void
801 mu_cfg_yy_stack_print (bottom, top)
802 mu_cfg_yytype_int16 *bottom;
803 mu_cfg_yytype_int16 *top;
804 #endif
805 {
806 YYFPRINTF (stderr, "Stack now");
807 for (; bottom <= top; ++bottom)
808 YYFPRINTF (stderr, " %d", *bottom);
809 YYFPRINTF (stderr, "\n");
810 }
811
812 # define YY_STACK_PRINT(Bottom, Top) \
813 do { \
814 if (mu_cfg_yydebug) \
815 mu_cfg_yy_stack_print ((Bottom), (Top)); \
816 } while (YYID (0))
817
818
819 /*------------------------------------------------.
820 | Report that the YYRULE is going to be reduced. |
821 `------------------------------------------------*/
822
823 #if (defined __STDC__ || defined __C99__FUNC__ \
824 || defined __cplusplus || defined _MSC_VER)
825 static void
826 mu_cfg_yy_reduce_print (YYSTYPE *mu_cfg_yyvsp, int mu_cfg_yyrule)
827 #else
828 static void
829 mu_cfg_yy_reduce_print (mu_cfg_yyvsp, mu_cfg_yyrule)
830 YYSTYPE *mu_cfg_yyvsp;
831 int mu_cfg_yyrule;
832 #endif
833 {
834 int mu_cfg_yynrhs = mu_cfg_yyr2[mu_cfg_yyrule];
835 int mu_cfg_yyi;
836 unsigned long int mu_cfg_yylno = mu_cfg_yyrline[mu_cfg_yyrule];
837 YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
838 mu_cfg_yyrule - 1, mu_cfg_yylno);
839 /* The symbols being reduced. */
840 for (mu_cfg_yyi = 0; mu_cfg_yyi < mu_cfg_yynrhs; mu_cfg_yyi++)
841 {
842 fprintf (stderr, " $%d = ", mu_cfg_yyi + 1);
843 mu_cfg_yy_symbol_print (stderr, mu_cfg_yyrhs[mu_cfg_yyprhs[mu_cfg_yyrule] + mu_cfg_yyi],
844 &(mu_cfg_yyvsp[(mu_cfg_yyi + 1) - (mu_cfg_yynrhs)])
845 );
846 fprintf (stderr, "\n");
847 }
848 }
849
850 # define YY_REDUCE_PRINT(Rule) \
851 do { \
852 if (mu_cfg_yydebug) \
853 mu_cfg_yy_reduce_print (mu_cfg_yyvsp, Rule); \
854 } while (YYID (0))
855
856 /* Nonzero means print parse trace. It is left uninitialized so that
857 multiple parsers can coexist. */
858 int mu_cfg_yydebug;
859 #else /* !YYDEBUG */
860 # define YYDPRINTF(Args)
861 # define YY_SYMBOL_PRINT(Title, Type, Value, Location)
862 # define YY_STACK_PRINT(Bottom, Top)
863 # define YY_REDUCE_PRINT(Rule)
864 #endif /* !YYDEBUG */
865
866
867 /* YYINITDEPTH -- initial size of the parser's stacks. */
868 #ifndef YYINITDEPTH
869 # define YYINITDEPTH 200
870 #endif
871
872 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
873 if the built-in stack extension method is used).
874
875 Do not make this value too large; the results are undefined if
876 YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
877 evaluated with infinite-precision integer arithmetic. */
878
879 #ifndef YYMAXDEPTH
880 # define YYMAXDEPTH 10000
881 #endif
882
883
884
885 #if YYERROR_VERBOSE
886
887 # ifndef mu_cfg_yystrlen
888 # if defined __GLIBC__ && defined _STRING_H
889 # define mu_cfg_yystrlen strlen
890 # else
891 /* Return the length of YYSTR. */
892 #if (defined __STDC__ || defined __C99__FUNC__ \
893 || defined __cplusplus || defined _MSC_VER)
894 static YYSIZE_T
895 mu_cfg_yystrlen (const char *mu_cfg_yystr)
896 #else
897 static YYSIZE_T
898 mu_cfg_yystrlen (mu_cfg_yystr)
899 const char *mu_cfg_yystr;
900 #endif
901 {
902 YYSIZE_T mu_cfg_yylen;
903 for (mu_cfg_yylen = 0; mu_cfg_yystr[mu_cfg_yylen]; mu_cfg_yylen++)
904 continue;
905 return mu_cfg_yylen;
906 }
907 # endif
908 # endif
909
910 # ifndef mu_cfg_yystpcpy
911 # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
912 # define mu_cfg_yystpcpy stpcpy
913 # else
914 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
915 YYDEST. */
916 #if (defined __STDC__ || defined __C99__FUNC__ \
917 || defined __cplusplus || defined _MSC_VER)
918 static char *
919 mu_cfg_yystpcpy (char *mu_cfg_yydest, const char *mu_cfg_yysrc)
920 #else
921 static char *
922 mu_cfg_yystpcpy (mu_cfg_yydest, mu_cfg_yysrc)
923 char *mu_cfg_yydest;
924 const char *mu_cfg_yysrc;
925 #endif
926 {
927 char *mu_cfg_yyd = mu_cfg_yydest;
928 const char *mu_cfg_yys = mu_cfg_yysrc;
929
930 while ((*mu_cfg_yyd++ = *mu_cfg_yys++) != '\0')
931 continue;
932
933 return mu_cfg_yyd - 1;
934 }
935 # endif
936 # endif
937
938 # ifndef mu_cfg_yytnamerr
939 /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
940 quotes and backslashes, so that it's suitable for mu_cfg_yyerror. The
941 heuristic is that double-quoting is unnecessary unless the string
942 contains an apostrophe, a comma, or backslash (other than
943 backslash-backslash). YYSTR is taken from mu_cfg_yytname. If YYRES is
944 null, do not copy; instead, return the length of what the result
945 would have been. */
946 static YYSIZE_T
947 mu_cfg_yytnamerr (char *mu_cfg_yyres, const char *mu_cfg_yystr)
948 {
949 if (*mu_cfg_yystr == '"')
950 {
951 YYSIZE_T mu_cfg_yyn = 0;
952 char const *mu_cfg_yyp = mu_cfg_yystr;
953
954 for (;;)
955 switch (*++mu_cfg_yyp)
956 {
957 case '\'':
958 case ',':
959 goto do_not_strip_quotes;
960
961 case '\\':
962 if (*++mu_cfg_yyp != '\\')
963 goto do_not_strip_quotes;
964 /* Fall through. */
965 default:
966 if (mu_cfg_yyres)
967 mu_cfg_yyres[mu_cfg_yyn] = *mu_cfg_yyp;
968 mu_cfg_yyn++;
969 break;
970
971 case '"':
972 if (mu_cfg_yyres)
973 mu_cfg_yyres[mu_cfg_yyn] = '\0';
974 return mu_cfg_yyn;
975 }
976 do_not_strip_quotes: ;
977 }
978
979 if (! mu_cfg_yyres)
980 return mu_cfg_yystrlen (mu_cfg_yystr);
981
982 return mu_cfg_yystpcpy (mu_cfg_yyres, mu_cfg_yystr) - mu_cfg_yyres;
983 }
984 # endif
985
986 /* Copy into YYRESULT an error message about the unexpected token
987 YYCHAR while in state YYSTATE. Return the number of bytes copied,
988 including the terminating null byte. If YYRESULT is null, do not
989 copy anything; just return the number of bytes that would be
990 copied. As a special case, return 0 if an ordinary "syntax error"
991 message will do. Return YYSIZE_MAXIMUM if overflow occurs during
992 size calculation. */
993 static YYSIZE_T
994 mu_cfg_yysyntax_error (char *mu_cfg_yyresult, int mu_cfg_yystate, int mu_cfg_yychar)
995 {
996 int mu_cfg_yyn = mu_cfg_yypact[mu_cfg_yystate];
997
998 if (! (YYPACT_NINF < mu_cfg_yyn && mu_cfg_yyn <= YYLAST))
999 return 0;
1000 else
1001 {
1002 int mu_cfg_yytype = YYTRANSLATE (mu_cfg_yychar);
1003 YYSIZE_T mu_cfg_yysize0 = mu_cfg_yytnamerr (0, mu_cfg_yytname[mu_cfg_yytype]);
1004 YYSIZE_T mu_cfg_yysize = mu_cfg_yysize0;
1005 YYSIZE_T mu_cfg_yysize1;
1006 int mu_cfg_yysize_overflow = 0;
1007 enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
1008 char const *mu_cfg_yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
1009 int mu_cfg_yyx;
1010
1011 # if 0
1012 /* This is so xgettext sees the translatable formats that are
1013 constructed on the fly. */
1014 YY_("syntax error, unexpected %s");
1015 YY_("syntax error, unexpected %s, expecting %s");
1016 YY_("syntax error, unexpected %s, expecting %s or %s");
1017 YY_("syntax error, unexpected %s, expecting %s or %s or %s");
1018 YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
1019 # endif
1020 char *mu_cfg_yyfmt;
1021 char const *mu_cfg_yyf;
1022 static char const mu_cfg_yyunexpected[] = "syntax error, unexpected %s";
1023 static char const mu_cfg_yyexpecting[] = ", expecting %s";
1024 static char const mu_cfg_yyor[] = " or %s";
1025 char mu_cfg_yyformat[sizeof mu_cfg_yyunexpected
1026 + sizeof mu_cfg_yyexpecting - 1
1027 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
1028 * (sizeof mu_cfg_yyor - 1))];
1029 char const *mu_cfg_yyprefix = mu_cfg_yyexpecting;
1030
1031 /* Start YYX at -YYN if negative to avoid negative indexes in
1032 YYCHECK. */
1033 int mu_cfg_yyxbegin = mu_cfg_yyn < 0 ? -mu_cfg_yyn : 0;
1034
1035 /* Stay within bounds of both mu_cfg_yycheck and mu_cfg_yytname. */
1036 int mu_cfg_yychecklim = YYLAST - mu_cfg_yyn + 1;
1037 int mu_cfg_yyxend = mu_cfg_yychecklim < YYNTOKENS ? mu_cfg_yychecklim : YYNTOKENS;
1038 int mu_cfg_yycount = 1;
1039
1040 mu_cfg_yyarg[0] = mu_cfg_yytname[mu_cfg_yytype];
1041 mu_cfg_yyfmt = mu_cfg_yystpcpy (mu_cfg_yyformat, mu_cfg_yyunexpected);
1042
1043 for (mu_cfg_yyx = mu_cfg_yyxbegin; mu_cfg_yyx < mu_cfg_yyxend; ++mu_cfg_yyx)
1044 if (mu_cfg_yycheck[mu_cfg_yyx + mu_cfg_yyn] == mu_cfg_yyx && mu_cfg_yyx != YYTERROR)
1045 {
1046 if (mu_cfg_yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
1047 {
1048 mu_cfg_yycount = 1;
1049 mu_cfg_yysize = mu_cfg_yysize0;
1050 mu_cfg_yyformat[sizeof mu_cfg_yyunexpected - 1] = '\0';
1051 break;
1052 }
1053 mu_cfg_yyarg[mu_cfg_yycount++] = mu_cfg_yytname[mu_cfg_yyx];
1054 mu_cfg_yysize1 = mu_cfg_yysize + mu_cfg_yytnamerr (0, mu_cfg_yytname[mu_cfg_yyx]);
1055 mu_cfg_yysize_overflow |= (mu_cfg_yysize1 < mu_cfg_yysize);
1056 mu_cfg_yysize = mu_cfg_yysize1;
1057 mu_cfg_yyfmt = mu_cfg_yystpcpy (mu_cfg_yyfmt, mu_cfg_yyprefix);
1058 mu_cfg_yyprefix = mu_cfg_yyor;
1059 }
1060
1061 mu_cfg_yyf = YY_(mu_cfg_yyformat);
1062 mu_cfg_yysize1 = mu_cfg_yysize + mu_cfg_yystrlen (mu_cfg_yyf);
1063 mu_cfg_yysize_overflow |= (mu_cfg_yysize1 < mu_cfg_yysize);
1064 mu_cfg_yysize = mu_cfg_yysize1;
1065
1066 if (mu_cfg_yysize_overflow)
1067 return YYSIZE_MAXIMUM;
1068
1069 if (mu_cfg_yyresult)
1070 {
1071 /* Avoid sprintf, as that infringes on the user's name space.
1072 Don't have undefined behavior even if the translation
1073 produced a string with the wrong number of "%s"s. */
1074 char *mu_cfg_yyp = mu_cfg_yyresult;
1075 int mu_cfg_yyi = 0;
1076 while ((*mu_cfg_yyp = *mu_cfg_yyf) != '\0')
1077 {
1078 if (*mu_cfg_yyp == '%' && mu_cfg_yyf[1] == 's' && mu_cfg_yyi < mu_cfg_yycount)
1079 {
1080 mu_cfg_yyp += mu_cfg_yytnamerr (mu_cfg_yyp, mu_cfg_yyarg[mu_cfg_yyi++]);
1081 mu_cfg_yyf += 2;
1082 }
1083 else
1084 {
1085 mu_cfg_yyp++;
1086 mu_cfg_yyf++;
1087 }
1088 }
1089 }
1090 return mu_cfg_yysize;
1091 }
1092 }
1093 #endif /* YYERROR_VERBOSE */
1094
1095
1096 /*-----------------------------------------------.
1097 | Release the memory associated to this symbol. |
1098 `-----------------------------------------------*/
1099
1100 /*ARGSUSED*/
1101 #if (defined __STDC__ || defined __C99__FUNC__ \
1102 || defined __cplusplus || defined _MSC_VER)
1103 static void
1104 mu_cfg_yydestruct (const char *mu_cfg_yymsg, int mu_cfg_yytype, YYSTYPE *mu_cfg_yyvaluep)
1105 #else
1106 static void
1107 mu_cfg_yydestruct (mu_cfg_yymsg, mu_cfg_yytype, mu_cfg_yyvaluep)
1108 const char *mu_cfg_yymsg;
1109 int mu_cfg_yytype;
1110 YYSTYPE *mu_cfg_yyvaluep;
1111 #endif
1112 {
1113 YYUSE (mu_cfg_yyvaluep);
1114
1115 if (!mu_cfg_yymsg)
1116 mu_cfg_yymsg = "Deleting";
1117 YY_SYMBOL_PRINT (mu_cfg_yymsg, mu_cfg_yytype, mu_cfg_yyvaluep, mu_cfg_yylocationp);
1118
1119 switch (mu_cfg_yytype)
1120 {
1121
1122 default:
1123 break;
1124 }
1125 }
1126
1127
1128 /* Prevent warnings from -Wmissing-prototypes. */
1129
1130 #ifdef YYPARSE_PARAM
1131 #if defined __STDC__ || defined __cplusplus
1132 int mu_cfg_yyparse (void *YYPARSE_PARAM);
1133 #else
1134 int mu_cfg_yyparse ();
1135 #endif
1136 #else /* ! YYPARSE_PARAM */
1137 #if defined __STDC__ || defined __cplusplus
1138 int mu_cfg_yyparse (void);
1139 #else
1140 int mu_cfg_yyparse ();
1141 #endif
1142 #endif /* ! YYPARSE_PARAM */
1143
1144
1145
1146 /* The look-ahead symbol. */
1147 int mu_cfg_yychar;
1148
1149 /* The semantic value of the look-ahead symbol. */
1150 YYSTYPE mu_cfg_yylval;
1151
1152 /* Number of syntax errors so far. */
1153 int mu_cfg_yynerrs;
1154
1155
1156
1157 /*----------.
1158 | mu_cfg_yyparse. |
1159 `----------*/
1160
1161 #ifdef YYPARSE_PARAM
1162 #if (defined __STDC__ || defined __C99__FUNC__ \
1163 || defined __cplusplus || defined _MSC_VER)
1164 int
1165 mu_cfg_yyparse (void *YYPARSE_PARAM)
1166 #else
1167 int
1168 mu_cfg_yyparse (YYPARSE_PARAM)
1169 void *YYPARSE_PARAM;
1170 #endif
1171 #else /* ! YYPARSE_PARAM */
1172 #if (defined __STDC__ || defined __C99__FUNC__ \
1173 || defined __cplusplus || defined _MSC_VER)
1174 int
1175 mu_cfg_yyparse (void)
1176 #else
1177 int
1178 mu_cfg_yyparse ()
1179
1180 #endif
1181 #endif
1182 {
1183
1184 int mu_cfg_yystate;
1185 int mu_cfg_yyn;
1186 int mu_cfg_yyresult;
1187 /* Number of tokens to shift before error messages enabled. */
1188 int mu_cfg_yyerrstatus;
1189 /* Look-ahead token as an internal (translated) token number. */
1190 int mu_cfg_yytoken = 0;
1191 #if YYERROR_VERBOSE
1192 /* Buffer for error messages, and its allocated size. */
1193 char mu_cfg_yymsgbuf[128];
1194 char *mu_cfg_yymsg = mu_cfg_yymsgbuf;
1195 YYSIZE_T mu_cfg_yymsg_alloc = sizeof mu_cfg_yymsgbuf;
1196 #endif
1197
1198 /* Three stacks and their tools:
1199 `mu_cfg_yyss': related to states,
1200 `mu_cfg_yyvs': related to semantic values,
1201 `mu_cfg_yyls': related to locations.
1202
1203 Refer to the stacks thru separate pointers, to allow mu_cfg_yyoverflow
1204 to reallocate them elsewhere. */
1205
1206 /* The state stack. */
1207 mu_cfg_yytype_int16 mu_cfg_yyssa[YYINITDEPTH];
1208 mu_cfg_yytype_int16 *mu_cfg_yyss = mu_cfg_yyssa;
1209 mu_cfg_yytype_int16 *mu_cfg_yyssp;
1210
1211 /* The semantic value stack. */
1212 YYSTYPE mu_cfg_yyvsa[YYINITDEPTH];
1213 YYSTYPE *mu_cfg_yyvs = mu_cfg_yyvsa;
1214 YYSTYPE *mu_cfg_yyvsp;
1215
1216
1217
1218 #define YYPOPSTACK(N) (mu_cfg_yyvsp -= (N), mu_cfg_yyssp -= (N))
1219
1220 YYSIZE_T mu_cfg_yystacksize = YYINITDEPTH;
1221
1222 /* The variables used to return semantic value and location from the
1223 action routines. */
1224 YYSTYPE mu_cfg_yyval;
1225
1226
1227 /* The number of symbols on the RHS of the reduced rule.
1228 Keep to zero when no symbol should be popped. */
1229 int mu_cfg_yylen = 0;
1230
1231 YYDPRINTF ((stderr, "Starting parse\n"));
1232
1233 mu_cfg_yystate = 0;
1234 mu_cfg_yyerrstatus = 0;
1235 mu_cfg_yynerrs = 0;
1236 mu_cfg_yychar = YYEMPTY; /* Cause a token to be read. */
1237
1238 /* Initialize stack pointers.
1239 Waste one element of value and location stack
1240 so that they stay on the same level as the state stack.
1241 The wasted elements are never initialized. */
1242
1243 mu_cfg_yyssp = mu_cfg_yyss;
1244 mu_cfg_yyvsp = mu_cfg_yyvs;
1245
1246 goto mu_cfg_yysetstate;
1247
1248 /*------------------------------------------------------------.
1249 | mu_cfg_yynewstate -- Push a new state, which is found in mu_cfg_yystate. |
1250 `------------------------------------------------------------*/
1251 mu_cfg_yynewstate:
1252 /* In all cases, when you get here, the value and location stacks
1253 have just been pushed. So pushing a state here evens the stacks. */
1254 mu_cfg_yyssp++;
1255
1256 mu_cfg_yysetstate:
1257 *mu_cfg_yyssp = mu_cfg_yystate;
1258
1259 if (mu_cfg_yyss + mu_cfg_yystacksize - 1 <= mu_cfg_yyssp)
1260 {
1261 /* Get the current used size of the three stacks, in elements. */
1262 YYSIZE_T mu_cfg_yysize = mu_cfg_yyssp - mu_cfg_yyss + 1;
1263
1264 #ifdef mu_cfg_yyoverflow
1265 {
1266 /* Give user a chance to reallocate the stack. Use copies of
1267 these so that the &'s don't force the real ones into
1268 memory. */
1269 YYSTYPE *mu_cfg_yyvs1 = mu_cfg_yyvs;
1270 mu_cfg_yytype_int16 *mu_cfg_yyss1 = mu_cfg_yyss;
1271
1272
1273 /* Each stack pointer address is followed by the size of the
1274 data in use in that stack, in bytes. This used to be a
1275 conditional around just the two extra args, but that might
1276 be undefined if mu_cfg_yyoverflow is a macro. */
1277 mu_cfg_yyoverflow (YY_("memory exhausted"),
1278 &mu_cfg_yyss1, mu_cfg_yysize * sizeof (*mu_cfg_yyssp),
1279 &mu_cfg_yyvs1, mu_cfg_yysize * sizeof (*mu_cfg_yyvsp),
1280
1281 &mu_cfg_yystacksize);
1282
1283 mu_cfg_yyss = mu_cfg_yyss1;
1284 mu_cfg_yyvs = mu_cfg_yyvs1;
1285 }
1286 #else /* no mu_cfg_yyoverflow */
1287 # ifndef YYSTACK_RELOCATE
1288 goto mu_cfg_yyexhaustedlab;
1289 # else
1290 /* Extend the stack our own way. */
1291 if (YYMAXDEPTH <= mu_cfg_yystacksize)
1292 goto mu_cfg_yyexhaustedlab;
1293 mu_cfg_yystacksize *= 2;
1294 if (YYMAXDEPTH < mu_cfg_yystacksize)
1295 mu_cfg_yystacksize = YYMAXDEPTH;
1296
1297 {
1298 mu_cfg_yytype_int16 *mu_cfg_yyss1 = mu_cfg_yyss;
1299 union mu_cfg_yyalloc *mu_cfg_yyptr =
1300 (union mu_cfg_yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (mu_cfg_yystacksize));
1301 if (! mu_cfg_yyptr)
1302 goto mu_cfg_yyexhaustedlab;
1303 YYSTACK_RELOCATE (mu_cfg_yyss);
1304 YYSTACK_RELOCATE (mu_cfg_yyvs);
1305
1306 # undef YYSTACK_RELOCATE
1307 if (mu_cfg_yyss1 != mu_cfg_yyssa)
1308 YYSTACK_FREE (mu_cfg_yyss1);
1309 }
1310 # endif
1311 #endif /* no mu_cfg_yyoverflow */
1312
1313 mu_cfg_yyssp = mu_cfg_yyss + mu_cfg_yysize - 1;
1314 mu_cfg_yyvsp = mu_cfg_yyvs + mu_cfg_yysize - 1;
1315
1316
1317 YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1318 (unsigned long int) mu_cfg_yystacksize));
1319
1320 if (mu_cfg_yyss + mu_cfg_yystacksize - 1 <= mu_cfg_yyssp)
1321 YYABORT;
1322 }
1323
1324 YYDPRINTF ((stderr, "Entering state %d\n", mu_cfg_yystate));
1325
1326 goto mu_cfg_yybackup;
1327
1328 /*-----------.
1329 | mu_cfg_yybackup. |
1330 `-----------*/
1331 mu_cfg_yybackup:
1332
1333 /* Do appropriate processing given the current state. Read a
1334 look-ahead token if we need one and don't already have one. */
1335
1336 /* First try to decide what to do without reference to look-ahead token. */
1337 mu_cfg_yyn = mu_cfg_yypact[mu_cfg_yystate];
1338 if (mu_cfg_yyn == YYPACT_NINF)
1339 goto mu_cfg_yydefault;
1340
1341 /* Not known => get a look-ahead token if don't already have one. */
1342
1343 /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
1344 if (mu_cfg_yychar == YYEMPTY)
1345 {
1346 YYDPRINTF ((stderr, "Reading a token: "));
1347 mu_cfg_yychar = YYLEX;
1348 }
1349
1350 if (mu_cfg_yychar <= YYEOF)
1351 {
1352 mu_cfg_yychar = mu_cfg_yytoken = YYEOF;
1353 YYDPRINTF ((stderr, "Now at end of input.\n"));
1354 }
1355 else
1356 {
1357 mu_cfg_yytoken = YYTRANSLATE (mu_cfg_yychar);
1358 YY_SYMBOL_PRINT ("Next token is", mu_cfg_yytoken, &mu_cfg_yylval, &mu_cfg_yylloc);
1359 }
1360
1361 /* If the proper action on seeing token YYTOKEN is to reduce or to
1362 detect an error, take that action. */
1363 mu_cfg_yyn += mu_cfg_yytoken;
1364 if (mu_cfg_yyn < 0 || YYLAST < mu_cfg_yyn || mu_cfg_yycheck[mu_cfg_yyn] != mu_cfg_yytoken)
1365 goto mu_cfg_yydefault;
1366 mu_cfg_yyn = mu_cfg_yytable[mu_cfg_yyn];
1367 if (mu_cfg_yyn <= 0)
1368 {
1369 if (mu_cfg_yyn == 0 || mu_cfg_yyn == YYTABLE_NINF)
1370 goto mu_cfg_yyerrlab;
1371 mu_cfg_yyn = -mu_cfg_yyn;
1372 goto mu_cfg_yyreduce;
1373 }
1374
1375 if (mu_cfg_yyn == YYFINAL)
1376 YYACCEPT;
1377
1378 /* Count tokens shifted since error; after three, turn off error
1379 status. */
1380 if (mu_cfg_yyerrstatus)
1381 mu_cfg_yyerrstatus--;
1382
1383 /* Shift the look-ahead token. */
1384 YY_SYMBOL_PRINT ("Shifting", mu_cfg_yytoken, &mu_cfg_yylval, &mu_cfg_yylloc);
1385
1386 /* Discard the shifted token unless it is eof. */
1387 if (mu_cfg_yychar != YYEOF)
1388 mu_cfg_yychar = YYEMPTY;
1389
1390 mu_cfg_yystate = mu_cfg_yyn;
1391 *++mu_cfg_yyvsp = mu_cfg_yylval;
1392
1393 goto mu_cfg_yynewstate;
1394
1395
1396 /*-----------------------------------------------------------.
1397 | mu_cfg_yydefault -- do the default action for the current state. |
1398 `-----------------------------------------------------------*/
1399 mu_cfg_yydefault:
1400 mu_cfg_yyn = mu_cfg_yydefact[mu_cfg_yystate];
1401 if (mu_cfg_yyn == 0)
1402 goto mu_cfg_yyerrlab;
1403 goto mu_cfg_yyreduce;
1404
1405
1406 /*-----------------------------.
1407 | mu_cfg_yyreduce -- Do a reduction. |
1408 `-----------------------------*/
1409 mu_cfg_yyreduce:
1410 /* mu_cfg_yyn is the number of a rule to reduce with. */
1411 mu_cfg_yylen = mu_cfg_yyr2[mu_cfg_yyn];
1412
1413 /* If YYLEN is nonzero, implement the default value of the action:
1414 `$$ = $1'.
1415
1416 Otherwise, the following line sets YYVAL to garbage.
1417 This behavior is undocumented and Bison
1418 users should not rely upon it. Assigning to YYVAL
1419 unconditionally makes the parser a bit smaller, and it avoids a
1420 GCC warning that YYVAL may be used uninitialized. */
1421 mu_cfg_yyval = mu_cfg_yyvsp[1-mu_cfg_yylen];
1422
1423
1424 YY_REDUCE_PRINT (mu_cfg_yyn);
1425 switch (mu_cfg_yyn)
1426 {
1427 case 2:
1428 #line 128 "cfg_parser.y"
1429 {
1430 parse_tree = (mu_cfg_yyvsp[(1) - (1)].nodelist).head;
1431 }
1432 break;
1433
1434 case 3:
1435 #line 134 "cfg_parser.y"
1436 {
1437 (mu_cfg_yyval.nodelist).head = (mu_cfg_yyval.nodelist).tail = (mu_cfg_yyvsp[(1) - (1)].pnode);
1438 }
1439 break;
1440
1441 case 4:
1442 #line 138 "cfg_parser.y"
1443 {
1444 (mu_cfg_yyval.nodelist) = (mu_cfg_yyvsp[(1) - (2)].nodelist);
1445 (mu_cfg_yyval.nodelist).tail->next = (mu_cfg_yyvsp[(2) - (2)].pnode);
1446 (mu_cfg_yyval.nodelist).tail = (mu_cfg_yyvsp[(2) - (2)].pnode);
1447 }
1448 break;
1449
1450 case 9:
1451 #line 154 "cfg_parser.y"
1452 {
1453 if ((mu_cfg_yyvsp[(4) - (5)].node).tag_name && strcmp ((mu_cfg_yyvsp[(4) - (5)].node).tag_name, (mu_cfg_yyvsp[(1) - (5)].node).tag_name))
1454 {
1455 mu_cfg_perror (_mu_cfg_lexer_data,
1456 &(mu_cfg_yyvsp[(1) - (5)].node).locus,
1457 _("Tag %s not closed"),
1458 (mu_cfg_yyvsp[(1) - (5)].node).tag_name);
1459 mu_cfg_perror (_mu_cfg_lexer_data,
1460 &(mu_cfg_yyvsp[(4) - (5)].node).locus,
1461 _("Found closing %s tag instead"),
1462 (mu_cfg_yyvsp[(4) - (5)].node).tag_name);
1463 _mu_cfg_errcnt++;
1464 }
1465 (mu_cfg_yyval.pnode) = mu_cfg_alloc_node (mu_cfg_node_tag, &(mu_cfg_yyvsp[(1) - (5)].node).locus,
1466 (mu_cfg_yyvsp[(1) - (5)].node).tag_name, (mu_cfg_yyvsp[(1) - (5)].node).tag_label, (mu_cfg_yyvsp[(3) - (5)].nodelist).head);
1467 }
1468 break;
1469
1470 case 10:
1471 #line 170 "cfg_parser.y"
1472 { mu_cfg_tie_in++; }
1473 break;
1474
1475 case 11:
1476 #line 171 "cfg_parser.y"
1477 { mu_cfg_tie_in = 0; }
1478 break;
1479
1480 case 12:
1481 #line 172 "cfg_parser.y"
1482 {
1483 (mu_cfg_yyval.pnode) = mu_cfg_alloc_node (mu_cfg_node_param, &mu_cfg_locus, (mu_cfg_yyvsp[(1) - (5)].string), (mu_cfg_yyvsp[(3) - (5)].string),
1484 NULL);
1485 }
1486 break;
1487
1488
1489 /* Line 1267 of yacc.c. */
1490 #line 1491 "cfg_parser.c"
1491 default: break;
1492 }
1493 YY_SYMBOL_PRINT ("-> $$ =", mu_cfg_yyr1[mu_cfg_yyn], &mu_cfg_yyval, &mu_cfg_yyloc);
1494
1495 YYPOPSTACK (mu_cfg_yylen);
1496 mu_cfg_yylen = 0;
1497 YY_STACK_PRINT (mu_cfg_yyss, mu_cfg_yyssp);
1498
1499 *++mu_cfg_yyvsp = mu_cfg_yyval;
1500
1501
1502 /* Now `shift' the result of the reduction. Determine what state
1503 that goes to, based on the state we popped back to and the rule
1504 number reduced by. */
1505
1506 mu_cfg_yyn = mu_cfg_yyr1[mu_cfg_yyn];
1507
1508 mu_cfg_yystate = mu_cfg_yypgoto[mu_cfg_yyn - YYNTOKENS] + *mu_cfg_yyssp;
1509 if (0 <= mu_cfg_yystate && mu_cfg_yystate <= YYLAST && mu_cfg_yycheck[mu_cfg_yystate] == *mu_cfg_yyssp)
1510 mu_cfg_yystate = mu_cfg_yytable[mu_cfg_yystate];
1511 else
1512 mu_cfg_yystate = mu_cfg_yydefgoto[mu_cfg_yyn - YYNTOKENS];
1513
1514 goto mu_cfg_yynewstate;
1515
1516
1517 /*------------------------------------.
1518 | mu_cfg_yyerrlab -- here on detecting error |
1519 `------------------------------------*/
1520 mu_cfg_yyerrlab:
1521 /* If not already recovering from an error, report this error. */
1522 if (!mu_cfg_yyerrstatus)
1523 {
1524 ++mu_cfg_yynerrs;
1525 #if ! YYERROR_VERBOSE
1526 mu_cfg_yyerror (YY_("syntax error"));
1527 #else
1528 {
1529 YYSIZE_T mu_cfg_yysize = mu_cfg_yysyntax_error (0, mu_cfg_yystate, mu_cfg_yychar);
1530 if (mu_cfg_yymsg_alloc < mu_cfg_yysize && mu_cfg_yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
1531 {
1532 YYSIZE_T mu_cfg_yyalloc = 2 * mu_cfg_yysize;
1533 if (! (mu_cfg_yysize <= mu_cfg_yyalloc && mu_cfg_yyalloc <= YYSTACK_ALLOC_MAXIMUM))
1534 mu_cfg_yyalloc = YYSTACK_ALLOC_MAXIMUM;
1535 if (mu_cfg_yymsg != mu_cfg_yymsgbuf)
1536 YYSTACK_FREE (mu_cfg_yymsg);
1537 mu_cfg_yymsg = (char *) YYSTACK_ALLOC (mu_cfg_yyalloc);
1538 if (mu_cfg_yymsg)
1539 mu_cfg_yymsg_alloc = mu_cfg_yyalloc;
1540 else
1541 {
1542 mu_cfg_yymsg = mu_cfg_yymsgbuf;
1543 mu_cfg_yymsg_alloc = sizeof mu_cfg_yymsgbuf;
1544 }
1545 }
1546
1547 if (0 < mu_cfg_yysize && mu_cfg_yysize <= mu_cfg_yymsg_alloc)
1548 {
1549 (void) mu_cfg_yysyntax_error (mu_cfg_yymsg, mu_cfg_yystate, mu_cfg_yychar);
1550 mu_cfg_yyerror (mu_cfg_yymsg);
1551 }
1552 else
1553 {
1554 mu_cfg_yyerror (YY_("syntax error"));
1555 if (mu_cfg_yysize != 0)
1556 goto mu_cfg_yyexhaustedlab;
1557 }
1558 }
1559 #endif
1560 }
1561
1562
1563
1564 if (mu_cfg_yyerrstatus == 3)
1565 {
1566 /* If just tried and failed to reuse look-ahead token after an
1567 error, discard it. */
1568
1569 if (mu_cfg_yychar <= YYEOF)
1570 {
1571 /* Return failure if at end of input. */
1572 if (mu_cfg_yychar == YYEOF)
1573 YYABORT;
1574 }
1575 else
1576 {
1577 mu_cfg_yydestruct ("Error: discarding",
1578 mu_cfg_yytoken, &mu_cfg_yylval);
1579 mu_cfg_yychar = YYEMPTY;
1580 }
1581 }
1582
1583 /* Else will try to reuse look-ahead token after shifting the error
1584 token. */
1585 goto mu_cfg_yyerrlab1;
1586
1587
1588 /*---------------------------------------------------.
1589 | mu_cfg_yyerrorlab -- error raised explicitly by YYERROR. |
1590 `---------------------------------------------------*/
1591 mu_cfg_yyerrorlab:
1592
1593 /* Pacify compilers like GCC when the user code never invokes
1594 YYERROR and the label mu_cfg_yyerrorlab therefore never appears in user
1595 code. */
1596 if (/*CONSTCOND*/ 0)
1597 goto mu_cfg_yyerrorlab;
1598
1599 /* Do not reclaim the symbols of the rule which action triggered
1600 this YYERROR. */
1601 YYPOPSTACK (mu_cfg_yylen);
1602 mu_cfg_yylen = 0;
1603 YY_STACK_PRINT (mu_cfg_yyss, mu_cfg_yyssp);
1604 mu_cfg_yystate = *mu_cfg_yyssp;
1605 goto mu_cfg_yyerrlab1;
1606
1607
1608 /*-------------------------------------------------------------.
1609 | mu_cfg_yyerrlab1 -- common code for both syntax error and YYERROR. |
1610 `-------------------------------------------------------------*/
1611 mu_cfg_yyerrlab1:
1612 mu_cfg_yyerrstatus = 3; /* Each real token shifted decrements this. */
1613
1614 for (;;)
1615 {
1616 mu_cfg_yyn = mu_cfg_yypact[mu_cfg_yystate];
1617 if (mu_cfg_yyn != YYPACT_NINF)
1618 {
1619 mu_cfg_yyn += YYTERROR;
1620 if (0 <= mu_cfg_yyn && mu_cfg_yyn <= YYLAST && mu_cfg_yycheck[mu_cfg_yyn] == YYTERROR)
1621 {
1622 mu_cfg_yyn = mu_cfg_yytable[mu_cfg_yyn];
1623 if (0 < mu_cfg_yyn)
1624 break;
1625 }
1626 }
1627
1628 /* Pop the current state because it cannot handle the error token. */
1629 if (mu_cfg_yyssp == mu_cfg_yyss)
1630 YYABORT;
1631
1632
1633 mu_cfg_yydestruct ("Error: popping",
1634 mu_cfg_yystos[mu_cfg_yystate], mu_cfg_yyvsp);
1635 YYPOPSTACK (1);
1636 mu_cfg_yystate = *mu_cfg_yyssp;
1637 YY_STACK_PRINT (mu_cfg_yyss, mu_cfg_yyssp);
1638 }
1639
1640 if (mu_cfg_yyn == YYFINAL)
1641 YYACCEPT;
1642
1643 *++mu_cfg_yyvsp = mu_cfg_yylval;
1644
1645
1646 /* Shift the error token. */
1647 YY_SYMBOL_PRINT ("Shifting", mu_cfg_yystos[mu_cfg_yyn], mu_cfg_yyvsp, mu_cfg_yylsp);
1648
1649 mu_cfg_yystate = mu_cfg_yyn;
1650 goto mu_cfg_yynewstate;
1651
1652
1653 /*-------------------------------------.
1654 | mu_cfg_yyacceptlab -- YYACCEPT comes here. |
1655 `-------------------------------------*/
1656 mu_cfg_yyacceptlab:
1657 mu_cfg_yyresult = 0;
1658 goto mu_cfg_yyreturn;
1659
1660 /*-----------------------------------.
1661 | mu_cfg_yyabortlab -- YYABORT comes here. |
1662 `-----------------------------------*/
1663 mu_cfg_yyabortlab:
1664 mu_cfg_yyresult = 1;
1665 goto mu_cfg_yyreturn;
1666
1667 #ifndef mu_cfg_yyoverflow
1668 /*-------------------------------------------------.
1669 | mu_cfg_yyexhaustedlab -- memory exhaustion comes here. |
1670 `-------------------------------------------------*/
1671 mu_cfg_yyexhaustedlab:
1672 mu_cfg_yyerror (YY_("memory exhausted"));
1673 mu_cfg_yyresult = 2;
1674 /* Fall through. */
1675 #endif
1676
1677 mu_cfg_yyreturn:
1678 if (mu_cfg_yychar != YYEOF && mu_cfg_yychar != YYEMPTY)
1679 mu_cfg_yydestruct ("Cleanup: discarding lookahead",
1680 mu_cfg_yytoken, &mu_cfg_yylval);
1681 /* Do not reclaim the symbols of the rule which action triggered
1682 this YYABORT or YYACCEPT. */
1683 YYPOPSTACK (mu_cfg_yylen);
1684 YY_STACK_PRINT (mu_cfg_yyss, mu_cfg_yyssp);
1685 while (mu_cfg_yyssp != mu_cfg_yyss)
1686 {
1687 mu_cfg_yydestruct ("Cleanup: popping",
1688 mu_cfg_yystos[*mu_cfg_yyssp], mu_cfg_yyvsp);
1689 YYPOPSTACK (1);
1690 }
1691 #ifndef mu_cfg_yyoverflow
1692 if (mu_cfg_yyss != mu_cfg_yyssa)
1693 YYSTACK_FREE (mu_cfg_yyss);
1694 #endif
1695 #if YYERROR_VERBOSE
1696 if (mu_cfg_yymsg != mu_cfg_yymsgbuf)
1697 YYSTACK_FREE (mu_cfg_yymsg);
1698 #endif
1699 /* Make sure YYID is used. */
1700 return YYID (mu_cfg_yyresult);
1701 }
1702
1703
1704 #line 178 "cfg_parser.y"
1705
1706
1707 int
1708 mu_cfg_parse (mu_cfg_node_t **ptree,
1709 void *data, mu_cfg_lexer_t lexer,
1710 mu_cfg_perror_t perror,
1711 mu_cfg_alloc_t palloc, mu_cfg_free_t pfree)
1712 {
1713 int rc;
1714
1715 _mu_cfg_lexer = lexer;
1716 _mu_cfg_lexer_data = data;
1717 mu_cfg_perror = perror ? perror : _mu_cfg_default_perror;
1718 _mu_cfg_alloc = palloc ? palloc : malloc;
1719 _mu_cfg_free = pfree ? pfree : free;
1720 _mu_cfg_errcnt = 0;
1721 mu_cfg_tie_in = 0;
1722 rc = mu_cfg_yyparse ();
1723 if (rc == 0 && _mu_cfg_errcnt)
1724 rc = 1;
1725 /* FIXME if (rc) free_memory; else */
1726 *ptree = parse_tree;
1727 return rc;
1728 }
1729
1730
1731
1732 static void
1733 print_level (FILE *fp, int level)
1734 {
1735 while (level--)
1736 {
1737 fputc (' ', fp);
1738 fputc (' ', fp);
1739 }
1740 }
1741
1742 struct tree_print
1743 {
1744 unsigned level;
1745 FILE *fp;
1746 };
1747
1748 int
1749 print_node (const mu_cfg_node_t *node, void *data)
1750 {
1751 struct tree_print *tp = data;
1752
1753 print_level (tp->fp, tp->level);
1754 switch (node->type)
1755 {
1756 case mu_cfg_node_undefined:
1757 fprintf (tp->fp, _("<UNDEFINED>"));
1758 break;
1759
1760 case mu_cfg_node_tag:
1761 fprintf (tp->fp, "<%s", node->tag_name);
1762 if (node->tag_label)
1763 fprintf (tp->fp, " %s", node->tag_label);
1764 fprintf (tp->fp, ">");
1765 tp->level++;
1766 break;
1767
1768 case mu_cfg_node_param:
1769 fprintf (tp->fp, "%s", node->tag_name);
1770 if (node->tag_label)
1771 fprintf (tp->fp, " %s", node->tag_label);
1772 break;
1773 }
1774 fprintf (tp->fp, "\n");
1775 return MU_CFG_ITER_OK;
1776 }
1777
1778 int
1779 print_node_end (const mu_cfg_node_t *node, void *data)
1780 {
1781 struct tree_print *tp = data;
1782 tp->level--;
1783 print_level (tp->fp, tp->level);
1784 fprintf (tp->fp, "</%s>\n", node->tag_name);
1785 return MU_CFG_ITER_OK;
1786 }
1787
1788 void
1789 mu_cfg_print_tree (FILE *fp, mu_cfg_node_t *node)
1790 {
1791 struct tree_print t;
1792 t.level = 0;
1793 t.fp = fp;
1794 mu_cfg_preorder (node, print_node, print_node_end, &t);
1795 }
1796
1797
1798
1799 static int
1800 _mu_cfg_preorder_recursive (mu_cfg_node_t *node,
1801 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end,
1802 void *data)
1803 {
1804 switch (node->type)
1805 {
1806 case mu_cfg_node_undefined:
1807 abort ();
1808
1809 case mu_cfg_node_tag:
1810 switch (beg (node, data))
1811 {
1812 case MU_CFG_ITER_OK:
1813 if (mu_cfg_preorder (node->node, beg, end, data))
1814 return MU_CFG_ITER_STOP;
1815 if (end && end (node, data) == MU_CFG_ITER_STOP)
1816 return MU_CFG_ITER_STOP;
1817 break;
1818
1819 case MU_CFG_ITER_SKIP:
1820 break;
1821
1822 case MU_CFG_ITER_STOP:
1823 return MU_CFG_ITER_STOP;
1824 }
1825 break;
1826
1827 case mu_cfg_node_param:
1828 return beg (node, data);
1829 }
1830 return MU_CFG_ITER_OK;
1831 }
1832
1833 int
1834 mu_cfg_preorder(mu_cfg_node_t *node,
1835 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end, void *data)
1836 {
1837 for (; node; node = node->next)
1838 if (_mu_cfg_preorder_recursive(node, beg, end, data) == MU_CFG_ITER_STOP)
1839 return 1;
1840 return 0;
1841 }
1842
1843 static int
1844 _mu_cfg_postorder_recursive(mu_cfg_node_t *node,
1845 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end,
1846 void *data)
1847 {
1848 switch (node->type)
1849 {
1850 case mu_cfg_node_undefined:
1851 abort ();
1852
1853 case mu_cfg_node_tag:
1854 switch (beg (node, data))
1855 {
1856 case MU_CFG_ITER_OK:
1857 if (mu_cfg_postorder (node->node, beg, end, data))
1858 return MU_CFG_ITER_STOP;
1859 if (end && end (node, data) == MU_CFG_ITER_STOP)
1860 return MU_CFG_ITER_STOP;
1861 break;
1862
1863 case MU_CFG_ITER_SKIP:
1864 break;
1865
1866 case MU_CFG_ITER_STOP:
1867 return MU_CFG_ITER_STOP;
1868 }
1869 break;
1870
1871 case mu_cfg_node_param:
1872 return beg (node, data);
1873 }
1874 return 0;
1875 }
1876
1877 int
1878 mu_cfg_postorder (mu_cfg_node_t *node,
1879 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end, void *data)
1880 {
1881 if (node->next
1882 && mu_cfg_postorder (node->next, beg, end, data) == MU_CFG_ITER_STOP)
1883 return 1;
1884 return _mu_cfg_postorder_recursive (node, beg, end, data)
1885 == MU_CFG_ITER_STOP;
1886 }
1887
1888
1889 static int
1890 free_section (const mu_cfg_node_t *node, void *data)
1891 {
1892 mu_cfg_free_t free_fn = data;
1893 if (node->type == mu_cfg_node_tag)
1894 free_fn ((void *) node);
1895 return MU_CFG_ITER_OK;
1896 }
1897
1898 static int
1899 free_param (const mu_cfg_node_t *node, void *data)
1900 {
1901 mu_cfg_free_t free_fn = data;
1902 if (node->type == mu_cfg_node_param)
1903 free_fn ((void*) node);
1904 return MU_CFG_ITER_OK;
1905 }
1906
1907 void
1908 mu_cfg_destroy_tree (mu_cfg_node_t **tree)
1909 {
1910 if (tree && *tree)
1911 {
1912 mu_cfg_postorder (*tree, free_param, free_section, _mu_cfg_free);
1913 *tree = NULL;
1914 }
1915 }
1916
1917
1918
1919 struct find_data
1920 {
1921 char *tag;
1922 char *label;
1923 char *next;
1924 const mu_cfg_node_t *node;
1925 };
1926
1927 static void
1928 parse_tag (struct find_data *fptr)
1929 {
1930 char *p = strchr (fptr->tag, '=');
1931 if (p)
1932 {
1933 *p++ = 0;
1934 fptr->label = p;
1935 fptr->next = p + strlen (p) + 1;
1936 }
1937 else
1938 {
1939 fptr->label = NULL;
1940 fptr->next = fptr->tag + strlen (fptr->tag) + 1;
1941 }
1942 }
1943
1944 static int
1945 node_finder (const mu_cfg_node_t *node, void *data)
1946 {
1947 struct find_data *fdptr = data;
1948 if (strcmp (fdptr->tag, node->tag_name) == 0
1949 && (!fdptr->label || strcmp (fdptr->label, node->tag_label) == 0))
1950 {
1951 fdptr->tag = fdptr->next;
1952 parse_tag (fdptr);
1953 if (fdptr->tag[0] == 0)
1954 {
1955 fdptr->node = node;
1956 return MU_CFG_ITER_STOP;
1957 }
1958 }
1959 return MU_CFG_ITER_OK;
1960 }
1961
1962 int
1963 mu_cfg_find_node (mu_cfg_node_t *tree, const char *path, mu_cfg_node_t **pval)
1964 {
1965 int rc;
1966 char *p;
1967 char *xpath;
1968 size_t len;
1969 struct find_data data;
1970
1971 len = strlen (path) + 1;
1972 xpath = calloc (1, len + 1);
1973 if (!xpath)
1974 return 1;
1975 strcpy (xpath, path);
1976 xpath[len-1] = '/';
1977 data.tag = xpath;
1978 for (p = data.tag; *p; p++)
1979 if (*p == '/')
1980 *p = 0;
1981 parse_tag (&data);
1982 rc = mu_cfg_preorder (tree, node_finder, NULL, &data);
1983 free (xpath);
1984 if (rc)
1985 {
1986 *pval = (mu_cfg_node_t *) data.node;
1987 return 0;
1988 }
1989 return MU_ERR_NOENT;
1990 }
1991
1992 int
1993 mu_cfg_find_node_label (mu_cfg_node_t *tree, const char *path,
1994 const char **pval)
1995 {
1996 mu_cfg_node_t *node;
1997 int rc = mu_cfg_find_node (tree, path, &node);
1998 if (rc)
1999 *pval = node->tag_label;
2000 return rc;
2001 }
2002
2003
2004 struct mu_cfg_section_list
2005 {
2006 struct mu_cfg_section_list *next;
2007 struct mu_cfg_section *sec;
2008 };
2009
2010 struct scan_tree_data
2011 {
2012 struct mu_cfg_section_list *list;
2013 void *call_data;
2014 int error;
2015 };
2016
2017 static struct mu_cfg_section *
2018 find_subsection (struct mu_cfg_section *sec, const char *ident, size_t len)
2019 {
2020 if (sec)
2021 {
2022 sec = sec->subsec;
2023 if (sec)
2024 {
2025 if (len == 0)
2026 len = strlen (ident);
2027
2028 for (; sec->ident; sec++)
2029 if (strlen (sec->ident) == len
2030 && memcmp (sec->ident, ident, len) == 0)
2031 return sec;
2032 }
2033 }
2034 return NULL;
2035 }
2036
2037 static struct mu_cfg_param *
2038 find_param (struct mu_cfg_section *sec, const char *ident, size_t len)
2039 {
2040 if (sec)
2041 {
2042 struct mu_cfg_param *p = sec->param;
2043 if (p)
2044 {
2045 if (len == 0)
2046 len = strlen (ident);
2047 for (; p->ident; p++)
2048 if (strlen (p->ident) == len && memcmp (p->ident, ident, len) == 0)
2049 return p;
2050 }
2051 }
2052 return NULL;
2053 }
2054
2055 static int
2056 push_section (struct scan_tree_data *dat, struct mu_cfg_section *sec)
2057 {
2058 struct mu_cfg_section_list *p = _mu_cfg_alloc (sizeof *p);
2059 if (!p)
2060 {
2061 mu_cfg_perror (dat->call_data, NULL, _("not enough memory"));
2062 return 1;
2063 }
2064 p->sec = sec;
2065 p->next = dat->list;
2066 dat->list = p;
2067 return 0;
2068 }
2069
2070 static struct mu_cfg_section *
2071 pop_section (struct scan_tree_data *dat)
2072 {
2073 struct mu_cfg_section_list *p = dat->list;
2074 struct mu_cfg_section *sec = p->sec;
2075 dat->list = p->next;
2076 _mu_cfg_free (p);
2077 return sec;
2078 }
2079
2080 #define STRTONUM(s, type, base, res, limit) \
2081 { \
2082 type sum = 0; \
2083 \
2084 while (*s) \
2085 { \
2086 type x; \
2087 \
2088 if ('0' <= *s && *s <= '9') \
2089 x = sum * base + *s - '0'; \
2090 else if (base == 16 && 'a' <= *s && *s <= 'f') \
2091 x = sum * base + *s - 'a'; \
2092 else if (base == 16 && 'A' <= *s && *s <= 'F') \
2093 x = sum * base + *s - 'A'; \
2094 else \
2095 break; \
2096 if (x <= sum) \
2097 { \
2098 mu_cfg_perror (sdata->call_data, \
2099 &node->locus, \
2100 _("numeric overflow")); \
2101 return 1; \
2102 } \
2103 else if (limit && x > limit) \
2104 { \
2105 mu_cfg_perror (sdata->call_data, \
2106 &node->locus, \
2107 _("value out of allowed range")); \
2108 return 1; \
2109 } \
2110 sum = x; \
2111 *s++; \
2112 } \
2113 res = sum; \
2114 }
2115
2116 #define STRxTONUM(s, type, res, limit) \
2117 { \
2118 int base; \
2119 if (*s == '0') \
2120 { \
2121 s++; \
2122 if (*s == 0) \
2123 base = 10; \
2124 else if (*s == 'x' || *s == 'X') \
2125 { \
2126 s++; \
2127 base = 16; \
2128 } \
2129 else \
2130 base = 8; \
2131 } else \
2132 base = 10; \
2133 STRTONUM (s, type, base, res, limit); \
2134 }
2135
2136 #define GETUNUM(str, type, res) \
2137 { \
2138 type tmpres; \
2139 const char *s = str; \
2140 STRxTONUM (s, type, tmpres, 0); \
2141 if (*s) \
2142 { \
2143 mu_cfg_perror (sdata->call_data, \
2144 &node->locus, \
2145 _("not a number (stopped near `%s')"), \
2146 s); \
2147 return 1; \
2148 } \
2149 res = tmpres; \
2150 }
2151
2152 #define GETSNUM(str, type, res) \
2153 { \
2154 unsigned type tmpres; \
2155 const char *s = str; \
2156 int sign; \
2157 unsigned type limit; \
2158 \
2159 if (*s == '-') \
2160 { \
2161 sign++; \
2162 s++; \
2163 limit = TYPE_MINIMUM (type); \
2164 limit = - limit; \
2165 } \
2166 else \
2167 { \
2168 sign = 0; \
2169 limit = TYPE_MAXIMUM (type); \
2170 } \
2171 \
2172 STRxTONUM (s, unsigned type, tmpres, limit); \
2173 if (*s) \
2174 { \
2175 mu_cfg_perror (sdata->call_data, \
2176 &node->locus, \
2177 _("not a number (stopped near `%s')"), \
2178 s); \
2179 return 1; \
2180 } \
2181 res = sign ? - tmpres : tmpres; \
2182 }
2183
2184 static int
2185 parse_ipv4 (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
2186 struct in_addr *res)
2187 {
2188 struct in_addr addr;
2189 if (inet_aton (node->tag_label, &addr) == 0)
2190 {
2191 mu_cfg_perror (sdata->call_data,
2192 &node->locus,
2193 _("not an IPv4"));
2194 return 1;
2195 }
2196 addr.s_addr = ntohl (addr.s_addr);
2197 *res = addr;
2198 return 0;
2199 }
2200
2201 static int
2202 parse_host (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
2203 struct in_addr *res)
2204 {
2205 struct in_addr addr;
2206 struct hostent *hp = gethostbyname (node->tag_label);
2207 if (hp)
2208 {
2209 addr.s_addr = *(unsigned long *)hp->h_addr;
2210 }
2211 else if (inet_aton(node->tag_label, &addr) == 0)
2212 {
2213 mu_cfg_perror (sdata->call_data,
2214 &node->locus,
2215 _("cannot resolve hostname `%s'"),
2216 node->tag_label);
2217 return 1;
2218 }
2219 addr.s_addr = ntohl (addr.s_addr);
2220 *res = addr;
2221 return 0;
2222 }
2223
2224 static int
2225 parse_cidr (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
2226 mu_cfg_cidr_t *res)
2227 {
2228 struct in_addr addr;
2229 unsigned long mask;
2230 char astr[16], *p, *s;
2231
2232 p = strchr (node->tag_label, '/');
2233 if (*p)
2234 {
2235 int len = p - node->tag_label;
2236 if (len > sizeof astr - 1) {
2237 mu_cfg_perror (sdata->call_data,
2238 &node->locus,
2239 _("not a valid IPv4 address in CIDR"));
2240 return 1;
2241 }
2242 memcpy (astr, node->tag_label, len);
2243 astr[len] = 0;
2244 if (inet_aton (astr, &addr) == 0)
2245 {
2246 mu_cfg_perror (sdata->call_data,
2247 &node->locus,
2248 _("not a valid IPv4 address in CIDR"));
2249 return 1;
2250 }
2251 addr.s_addr = ntohl (addr.s_addr);
2252
2253 p++;
2254 s = p;
2255 STRxTONUM (s, unsigned long, mask, 0);
2256 if (*s == '.')
2257 {
2258 struct in_addr a;
2259 if (inet_aton (p, &a) == 0)
2260 {
2261 mu_cfg_perror (sdata->call_data,
2262 &node->locus,
2263 _("not a valid network in CIDR"));
2264 return 1;
2265 }
2266 a.s_addr = ntohl (a.s_addr);
2267 for (mask = 0; (a.s_addr & 1) == 0 && mask < 32; )
2268 {
2269 mask++;
2270 a.s_addr >>= 1;
2271 }
2272 mask = 32 - mask;
2273 }
2274 else if (mask > 32)
2275 {
2276 mu_cfg_perror (sdata->call_data,
2277 &node->locus,
2278 _("not a valid network mask in CIDR"));
2279 return 1;
2280 }
2281 }
2282 else
2283 {
2284 int i;
2285 unsigned short x;
2286 addr.s_addr = 0;
2287
2288 for (i = 0; i < 3; i++)
2289 {
2290 STRxTONUM(p, unsigned short, x, 255);
2291 if (*p != '.')
2292 break;
2293 addr.s_addr = (addr.s_addr << 8) + x;
2294 }
2295
2296 if (*p)
2297 {
2298 mu_cfg_perror (sdata->call_data,
2299 &node->locus,
2300 _("not a CIDR (stopped near `%s')"),
2301 p);
2302 return 1;
2303 }
2304
2305 mask = i * 8;
2306
2307 addr.s_addr <<= (4 - i) * 8;
2308 }
2309
2310 res->addr = addr;
2311 res->mask = mask;
2312 return 0;
2313 }
2314
2315 static int
2316 parse_bool (struct scan_tree_data *sdata, const mu_cfg_node_t *node, int *res)
2317 {
2318 if (strcmp (node->tag_label, "yes") == 0
2319 || strcmp (node->tag_label, "on") == 0
2320 || strcmp (node->tag_label, "t") == 0
2321 || strcmp (node->tag_label, "true") == 0
2322 || strcmp (node->tag_label, "1") == 0)
2323 *res = 1;
2324 else if (strcmp (node->tag_label, "no") == 0
2325 || strcmp (node->tag_label, "off") == 0
2326 || strcmp (node->tag_label, "nil") == 0
2327 || strcmp (node->tag_label, "false") == 0
2328 || strcmp (node->tag_label, "0") == 0)
2329 *res = 0;
2330 else
2331 {
2332 mu_cfg_perror (sdata->call_data, &node->locus, _("not a boolean"));
2333 return 1;
2334 }
2335 return 0;
2336 }
2337
2338 static int
2339 parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
2340 {
2341 struct mu_cfg_param *param = find_param (sdata->list->sec, node->tag_name,
2342 0);
2343 if (!param)
2344 {
2345 mu_cfg_perror (sdata->call_data,
2346 &node->locus,
2347 _("unknown keyword `%s'"),
2348 node->tag_name);
2349 return 1;
2350 }
2351
2352 switch (param->type)
2353 {
2354 case mu_cfg_string:
2355 {
2356 size_t len = strlen (node->tag_label);
2357 char *s = _mu_cfg_alloc (len + 1);
2358 if (!s)
2359 {
2360 mu_cfg_perror (sdata->call_data,
2361 &node->locus,
2362 _("not enough memory"));
2363 return 1;
2364 }
2365 strcpy (s, node->tag_label);
2366 /* FIXME: free param->data? */
2367 *(char**)param->data = s;
2368 break;
2369 }
2370
2371 case mu_cfg_short:
2372 GETSNUM (node->tag_label, short, *(short*)param->data);
2373 break;
2374
2375 case mu_cfg_ushort:
2376 GETUNUM (node->tag_label, unsigned short, *(unsigned short*)param->data);
2377 break;
2378
2379 case mu_cfg_int:
2380 GETSNUM (node->tag_label, int, *(int*)param->data);
2381 break;
2382
2383 case mu_cfg_uint:
2384 GETUNUM (node->tag_label, unsigned int, *(unsigned int*)param->data);
2385 break;
2386
2387 case mu_cfg_long:
2388 GETSNUM (node->tag_label, long, *(long*)param->data);
2389 break;
2390
2391 case mu_cfg_ulong:
2392 GETUNUM (node->tag_label, unsigned long, *(unsigned long*)param->data);
2393 break;
2394
2395 case mu_cfg_size:
2396 GETUNUM (node->tag_label, size_t, *(size_t*)param->data);
2397 break;
2398
2399 case mu_cfg_off:
2400 mu_cfg_perror (sdata->call_data, &node->locus, _("not implemented yet"));
2401 /* GETSNUM(node->tag_label, off_t, *(off_t*)param->data); */
2402 return 1;
2403
2404 case mu_cfg_bool:
2405 if (parse_bool (sdata, node, (int*) param->data))
2406 return 1;
2407 break;
2408
2409 case mu_cfg_ipv4:
2410 if (parse_ipv4 (sdata, node, (struct in_addr *)param->data))
2411 return 1;
2412 break;
2413
2414 case mu_cfg_cidr:
2415 if (parse_cidr (sdata, node, (mu_cfg_cidr_t *)param->data))
2416 return 1;
2417 break;
2418
2419 case mu_cfg_host:
2420 if (parse_host (sdata, node, (struct in_addr *)param->data))
2421 return 1;
2422 break;
2423
2424 case mu_cfg_callback:
2425 if (param->callback (&node->locus, param->data, node->tag_label))
2426 return 1;
2427 break;
2428
2429 default:
2430 abort ();
2431 }
2432 return 0;
2433 }
2434
2435
2436 static int
2437 _scan_tree_helper (const mu_cfg_node_t *node, void *data)
2438 {
2439 struct scan_tree_data *sdata = data;
2440 struct mu_cfg_section *sec;
2441
2442 switch (node->type)
2443 {
2444 case mu_cfg_node_undefined:
2445 abort ();
2446
2447 case mu_cfg_node_tag:
2448 sec = find_subsection (sdata->list->sec, node->tag_name, 0);
2449 if (!sec)
2450 {
2451 mu_cfg_perror (sdata->call_data,
2452 &node->locus,
2453 _("unknown section `%s'"),
2454 node->tag_name);
2455 sdata->error++;
2456 return MU_CFG_ITER_SKIP;
2457 }
2458 if (!sec->subsec && !sec->param)
2459 return MU_CFG_ITER_SKIP;
2460 if (sec->parser &&
2461 sec->parser (mu_cfg_section_start, node,
2462 sec->data, sdata->call_data))
2463 {
2464 sdata->error++;
2465 return MU_CFG_ITER_SKIP;
2466 }
2467 push_section(sdata, sec);
2468 break;
2469
2470 case mu_cfg_node_param:
2471 if (parse_param (sdata, node))
2472 {
2473 sdata->error++;
2474 return MU_CFG_ITER_SKIP;
2475 }
2476 break;
2477 }
2478 return MU_CFG_ITER_OK;
2479 }
2480
2481 static int
2482 _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
2483 {
2484 struct scan_tree_data *sdata = data;
2485 struct mu_cfg_section *sec;
2486
2487 switch (node->type)
2488 {
2489 default:
2490 abort ();
2491
2492 case mu_cfg_node_tag:
2493 sec = pop_section (sdata);
2494 if (sec && sec->parser)
2495 {
2496 if (sec->parser (mu_cfg_section_end, node, sec->data,
2497 sdata->call_data))
2498 {
2499 sdata->error++;
2500 return MU_CFG_ITER_SKIP;
2501 }
2502 }
2503 }
2504 return MU_CFG_ITER_OK;
2505 }
2506
2507 int
2508 mu_cfg_scan_tree (mu_cfg_node_t *node,
2509 struct mu_cfg_section *sections,
2510 void *data, mu_cfg_perror_t perror,
2511 mu_cfg_alloc_t palloc, mu_cfg_free_t pfree)
2512 {
2513 struct scan_tree_data dat;
2514 dat.list = NULL;
2515 mu_cfg_perror = perror ? perror : _mu_cfg_default_perror;
2516 _mu_cfg_alloc = palloc ? palloc : malloc;
2517 _mu_cfg_free = pfree ? pfree : free;
2518 dat.call_data = data;
2519 dat.error = 0;
2520 if (push_section (&dat, sections))
2521 return 1;
2522 mu_cfg_preorder (node, _scan_tree_helper, _scan_tree_end_helper, &dat);
2523 pop_section (&dat);
2524 return dat.error;
2525 }
2526
2527 int
2528 mu_cfg_find_section (struct mu_cfg_section *root_sec,
2529 const char *path, struct mu_cfg_section **retval)
2530 {
2531 while (path[0])
2532 {
2533 struct mu_cfg_section *sec;
2534 size_t len;
2535 const char *p;
2536
2537 while (*path == '/')
2538 path++;
2539
2540 if (*path == 0)
2541 return MU_ERR_NOENT;
2542
2543 p = strchr (path, '/');
2544 if (p)
2545 len = p - path;
2546 else
2547 len = strlen (path);
2548
2549 sec = find_subsection (root_sec, path, len);
2550 if (!sec)
2551 return MU_ERR_NOENT;
2552 root_sec = sec;
2553 path += len;
2554 }
2555 if (retval)
2556 *retval = root_sec;
2557 return 0;
2558 }
2559
2560
2561
2562
2563
1 %{
2 /* cfg_parser.y -- general-purpose configuration file parser
3 Copyright (C) 2007 Free Software Foundation, Inc.
4
5 GNU Mailutils is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 3, or (at
8 your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <netdb.h>
24 #include "intprops.h"
25 #include <mailutils/nls.h>
26 #include <mailutils/cfg.h>
27 #include <mailutils/errno.h>
28 #include <mailutils/error.h>
29
30 static mu_cfg_node_t *parse_tree;
31 mu_cfg_locus_t mu_cfg_locus;
32 int mu_cfg_tie_in;
33
34 static int _mu_cfg_errcnt;
35 static mu_cfg_lexer_t _mu_cfg_lexer;
36 mu_cfg_perror_t mu_cfg_perror;
37 static void *_mu_cfg_lexer_data;
38 mu_cfg_alloc_t _mu_cfg_alloc;
39 mu_cfg_free_t _mu_cfg_free;
40
41 static int
42 yyerror (char *s)
43 {
44 mu_cfg_perror (_mu_cfg_lexer_data, &mu_cfg_locus, "%s", s);
45 return 0;
46 }
47
48 static int
49 yylex ()
50 {
51 return _mu_cfg_lexer (_mu_cfg_lexer_data);
52 }
53
54 static mu_cfg_node_t *
55 mu_cfg_alloc_node (enum mu_cfg_node_type type, mu_cfg_locus_t *loc,
56 char *tag, char *label, mu_cfg_node_t *node)
57 {
58 char *p;
59 mu_cfg_node_t *np;
60 size_t size = sizeof *np + strlen (tag) + 1
61 + (label ? (strlen (label) + 1) : 0);
62 np = _mu_cfg_alloc (size);
63 if (!np)
64 {
65 mu_cfg_perror (_mu_cfg_lexer_data, &mu_cfg_locus,
66 _("Not enough memory"));
67 abort();
68 }
69 np->type = type;
70 np->locus = *loc;
71 p = (char*) (np + 1);
72 np->tag_name = p;
73 strcpy (p, tag);
74 p += strlen (p) + 1;
75 if (label)
76 {
77 np->tag_label = p;
78 strcpy (p, label);
79 }
80 else
81 np->tag_label = label;
82 np->node = node;
83 np->next = NULL;
84 return np;
85 }
86
87 static void
88 _mu_cfg_default_perror (void *ptr, const mu_cfg_locus_t *loc,
89 const char *fmt, ...)
90 {
91 va_list ap;
92
93 fprintf (stderr, "%s:", loc->file ? loc->file : _("unknown file"));
94 if (loc->line > 0)
95 fprintf (stderr, "%lu", (unsigned long) loc->line);
96 else
97 fprintf (stderr, "%s", _("unknown line"));
98 fprintf (stderr, ": ");
99 va_start (ap, fmt);
100 vfprintf (stderr, fmt, ap);
101 va_end (ap);
102 fprintf (stderr, "\n");
103 }
104
105 %}
106
107 %token MU_CFG_EOL_TOKEN
108 %token <node> MU_CFG_START_TOKEN MU_CFG_END_TOKEN
109 %token <string> MU_CFG_STRING_TOKEN
110
111 %type <pnode> tag
112 %type <nodelist> taglist
113
114 %union
115 {
116 mu_cfg_node_t node;
117 mu_cfg_node_t *pnode;
118 struct
119 {
120 mu_cfg_node_t *head, *tail;
121 } nodelist;
122 char *string;
123 };
124
125 %%
126
127 input : taglist
128 {
129 parse_tree = $1.head;
130 }
131 ;
132
133 taglist : tag
134 {
135 $$.head = $$.tail = $1;
136 }
137 | taglist tag
138 {
139 $$ = $1;
140 $$.tail->next = $2;
141 $$.tail = $2;
142 }
143 ;
144
145 opt_eol : /* empty */
146 | eol
147 ;
148
149 eol : MU_CFG_EOL_TOKEN
150 | eol MU_CFG_EOL_TOKEN
151 ;
152
153 tag : MU_CFG_START_TOKEN opt_eol taglist MU_CFG_END_TOKEN MU_CFG_EOL_TOKEN
154 {
155 if ($4.tag_name && strcmp ($4.tag_name, $1.tag_name))
156 {
157 mu_cfg_perror (_mu_cfg_lexer_data,
158 &$1.locus,
159 _("Tag %s not closed"),
160 $1.tag_name);
161 mu_cfg_perror (_mu_cfg_lexer_data,
162 &$4.locus,
163 _("Found closing %s tag instead"),
164 $4.tag_name);
165 _mu_cfg_errcnt++;
166 }
167 $$ = mu_cfg_alloc_node (mu_cfg_node_tag, &$1.locus,
168 $1.tag_name, $1.tag_label, $3.head);
169 }
170 | MU_CFG_STRING_TOKEN { mu_cfg_tie_in++; }
171 MU_CFG_STRING_TOKEN { mu_cfg_tie_in = 0; } MU_CFG_EOL_TOKEN
172 {
173 $$ = mu_cfg_alloc_node (mu_cfg_node_param, &mu_cfg_locus, $1, $3,
174 NULL);
175 }
176 ;
177
178 %%
179
180 int
181 mu_cfg_parse (mu_cfg_node_t **ptree,
182 void *data, mu_cfg_lexer_t lexer,
183 mu_cfg_perror_t perror,
184 mu_cfg_alloc_t palloc, mu_cfg_free_t pfree)
185 {
186 int rc;
187
188 _mu_cfg_lexer = lexer;
189 _mu_cfg_lexer_data = data;
190 mu_cfg_perror = perror ? perror : _mu_cfg_default_perror;
191 _mu_cfg_alloc = palloc ? palloc : malloc;
192 _mu_cfg_free = pfree ? pfree : free;
193 _mu_cfg_errcnt = 0;
194 mu_cfg_tie_in = 0;
195 rc = yyparse ();
196 if (rc == 0 && _mu_cfg_errcnt)
197 rc = 1;
198 /* FIXME if (rc) free_memory; else */
199 *ptree = parse_tree;
200 return rc;
201 }
202
203
204
205 static void
206 print_level (FILE *fp, int level)
207 {
208 while (level--)
209 {
210 fputc (' ', fp);
211 fputc (' ', fp);
212 }
213 }
214
215 struct tree_print
216 {
217 unsigned level;
218 FILE *fp;
219 };
220
221 int
222 print_node (const mu_cfg_node_t *node, void *data)
223 {
224 struct tree_print *tp = data;
225
226 print_level (tp->fp, tp->level);
227 switch (node->type)
228 {
229 case mu_cfg_node_undefined:
230 fprintf (tp->fp, _("<UNDEFINED>"));
231 break;
232
233 case mu_cfg_node_tag:
234 fprintf (tp->fp, "<%s", node->tag_name);
235 if (node->tag_label)
236 fprintf (tp->fp, " %s", node->tag_label);
237 fprintf (tp->fp, ">");
238 tp->level++;
239 break;
240
241 case mu_cfg_node_param:
242 fprintf (tp->fp, "%s", node->tag_name);
243 if (node->tag_label)
244 fprintf (tp->fp, " %s", node->tag_label);
245 break;
246 }
247 fprintf (tp->fp, "\n");
248 return MU_CFG_ITER_OK;
249 }
250
251 int
252 print_node_end (const mu_cfg_node_t *node, void *data)
253 {
254 struct tree_print *tp = data;
255 tp->level--;
256 print_level (tp->fp, tp->level);
257 fprintf (tp->fp, "</%s>\n", node->tag_name);
258 return MU_CFG_ITER_OK;
259 }
260
261 void
262 mu_cfg_print_tree (FILE *fp, mu_cfg_node_t *node)
263 {
264 struct tree_print t;
265 t.level = 0;
266 t.fp = fp;
267 mu_cfg_preorder (node, print_node, print_node_end, &t);
268 }
269
270
271
272 static int
273 _mu_cfg_preorder_recursive (mu_cfg_node_t *node,
274 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end,
275 void *data)
276 {
277 switch (node->type)
278 {
279 case mu_cfg_node_undefined:
280 abort ();
281
282 case mu_cfg_node_tag:
283 switch (beg (node, data))
284 {
285 case MU_CFG_ITER_OK:
286 if (mu_cfg_preorder (node->node, beg, end, data))
287 return MU_CFG_ITER_STOP;
288 if (end && end (node, data) == MU_CFG_ITER_STOP)
289 return MU_CFG_ITER_STOP;
290 break;
291
292 case MU_CFG_ITER_SKIP:
293 break;
294
295 case MU_CFG_ITER_STOP:
296 return MU_CFG_ITER_STOP;
297 }
298 break;
299
300 case mu_cfg_node_param:
301 return beg (node, data);
302 }
303 return MU_CFG_ITER_OK;
304 }
305
306 int
307 mu_cfg_preorder(mu_cfg_node_t *node,
308 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end, void *data)
309 {
310 for (; node; node = node->next)
311 if (_mu_cfg_preorder_recursive(node, beg, end, data) == MU_CFG_ITER_STOP)
312 return 1;
313 return 0;
314 }
315
316 static int
317 _mu_cfg_postorder_recursive(mu_cfg_node_t *node,
318 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end,
319 void *data)
320 {
321 switch (node->type)
322 {
323 case mu_cfg_node_undefined:
324 abort ();
325
326 case mu_cfg_node_tag:
327 switch (beg (node, data))
328 {
329 case MU_CFG_ITER_OK:
330 if (mu_cfg_postorder (node->node, beg, end, data))
331 return MU_CFG_ITER_STOP;
332 if (end && end (node, data) == MU_CFG_ITER_STOP)
333 return MU_CFG_ITER_STOP;
334 break;
335
336 case MU_CFG_ITER_SKIP:
337 break;
338
339 case MU_CFG_ITER_STOP:
340 return MU_CFG_ITER_STOP;
341 }
342 break;
343
344 case mu_cfg_node_param:
345 return beg (node, data);
346 }
347 return 0;
348 }
349
350 int
351 mu_cfg_postorder (mu_cfg_node_t *node,
352 mu_cfg_iter_func_t beg, mu_cfg_iter_func_t end, void *data)
353 {
354 if (node->next
355 && mu_cfg_postorder (node->next, beg, end, data) == MU_CFG_ITER_STOP)
356 return 1;
357 return _mu_cfg_postorder_recursive (node, beg, end, data)
358 == MU_CFG_ITER_STOP;
359 }
360
361
362 static int
363 free_section (const mu_cfg_node_t *node, void *data)
364 {
365 mu_cfg_free_t free_fn = data;
366 if (node->type == mu_cfg_node_tag)
367 free_fn ((void *) node);
368 return MU_CFG_ITER_OK;
369 }
370
371 static int
372 free_param (const mu_cfg_node_t *node, void *data)
373 {
374 mu_cfg_free_t free_fn = data;
375 if (node->type == mu_cfg_node_param)
376 free_fn ((void*) node);
377 return MU_CFG_ITER_OK;
378 }
379
380 void
381 mu_cfg_destroy_tree (mu_cfg_node_t **tree)
382 {
383 if (tree && *tree)
384 {
385 mu_cfg_postorder (*tree, free_param, free_section, _mu_cfg_free);
386 *tree = NULL;
387 }
388 }
389
390
391
392 struct find_data
393 {
394 char *tag;
395 char *label;
396 char *next;
397 const mu_cfg_node_t *node;
398 };
399
400 static void
401 parse_tag (struct find_data *fptr)
402 {
403 char *p = strchr (fptr->tag, '=');
404 if (p)
405 {
406 *p++ = 0;
407 fptr->label = p;
408 fptr->next = p + strlen (p) + 1;
409 }
410 else
411 {
412 fptr->label = NULL;
413 fptr->next = fptr->tag + strlen (fptr->tag) + 1;
414 }
415 }
416
417 static int
418 node_finder (const mu_cfg_node_t *node, void *data)
419 {
420 struct find_data *fdptr = data;
421 if (strcmp (fdptr->tag, node->tag_name) == 0
422 && (!fdptr->label || strcmp (fdptr->label, node->tag_label) == 0))
423 {
424 fdptr->tag = fdptr->next;
425 parse_tag (fdptr);
426 if (fdptr->tag[0] == 0)
427 {
428 fdptr->node = node;
429 return MU_CFG_ITER_STOP;
430 }
431 }
432 return MU_CFG_ITER_OK;
433 }
434
435 int
436 mu_cfg_find_node (mu_cfg_node_t *tree, const char *path, mu_cfg_node_t **pval)
437 {
438 int rc;
439 char *p;
440 char *xpath;
441 size_t len;
442 struct find_data data;
443
444 len = strlen (path) + 1;
445 xpath = calloc (1, len + 1);
446 if (!xpath)
447 return 1;
448 strcpy (xpath, path);
449 xpath[len-1] = '/';
450 data.tag = xpath;
451 for (p = data.tag; *p; p++)
452 if (*p == '/')
453 *p = 0;
454 parse_tag (&data);
455 rc = mu_cfg_preorder (tree, node_finder, NULL, &data);
456 free (xpath);
457 if (rc)
458 {
459 *pval = (mu_cfg_node_t *) data.node;
460 return 0;
461 }
462 return MU_ERR_NOENT;
463 }
464
465 int
466 mu_cfg_find_node_label (mu_cfg_node_t *tree, const char *path,
467 const char **pval)
468 {
469 mu_cfg_node_t *node;
470 int rc = mu_cfg_find_node (tree, path, &node);
471 if (rc)
472 *pval = node->tag_label;
473 return rc;
474 }
475
476
477 struct mu_cfg_section_list
478 {
479 struct mu_cfg_section_list *next;
480 struct mu_cfg_section *sec;
481 };
482
483 struct scan_tree_data
484 {
485 struct mu_cfg_section_list *list;
486 void *call_data;
487 int error;
488 };
489
490 static struct mu_cfg_section *
491 find_subsection (struct mu_cfg_section *sec, const char *ident, size_t len)
492 {
493 if (sec)
494 {
495 sec = sec->subsec;
496 if (sec)
497 {
498 if (len == 0)
499 len = strlen (ident);
500
501 for (; sec->ident; sec++)
502 if (strlen (sec->ident) == len
503 && memcmp (sec->ident, ident, len) == 0)
504 return sec;
505 }
506 }
507 return NULL;
508 }
509
510 static struct mu_cfg_param *
511 find_param (struct mu_cfg_section *sec, const char *ident, size_t len)
512 {
513 if (sec)
514 {
515 struct mu_cfg_param *p = sec->param;
516 if (p)
517 {
518 if (len == 0)
519 len = strlen (ident);
520 for (; p->ident; p++)
521 if (strlen (p->ident) == len && memcmp (p->ident, ident, len) == 0)
522 return p;
523 }
524 }
525 return NULL;
526 }
527
528 static int
529 push_section (struct scan_tree_data *dat, struct mu_cfg_section *sec)
530 {
531 struct mu_cfg_section_list *p = _mu_cfg_alloc (sizeof *p);
532 if (!p)
533 {
534 mu_cfg_perror (dat->call_data, NULL, _("not enough memory"));
535 return 1;
536 }
537 p->sec = sec;
538 p->next = dat->list;
539 dat->list = p;
540 return 0;
541 }
542
543 static struct mu_cfg_section *
544 pop_section (struct scan_tree_data *dat)
545 {
546 struct mu_cfg_section_list *p = dat->list;
547 struct mu_cfg_section *sec = p->sec;
548 dat->list = p->next;
549 _mu_cfg_free (p);
550 return sec;
551 }
552
553 #define STRTONUM(s, type, base, res, limit) \
554 { \
555 type sum = 0; \
556 \
557 while (*s) \
558 { \
559 type x; \
560 \
561 if ('0' <= *s && *s <= '9') \
562 x = sum * base + *s - '0'; \
563 else if (base == 16 && 'a' <= *s && *s <= 'f') \
564 x = sum * base + *s - 'a'; \
565 else if (base == 16 && 'A' <= *s && *s <= 'F') \
566 x = sum * base + *s - 'A'; \
567 else \
568 break; \
569 if (x <= sum) \
570 { \
571 mu_cfg_perror (sdata->call_data, \
572 &node->locus, \
573 _("numeric overflow")); \
574 return 1; \
575 } \
576 else if (limit && x > limit) \
577 { \
578 mu_cfg_perror (sdata->call_data, \
579 &node->locus, \
580 _("value out of allowed range")); \
581 return 1; \
582 } \
583 sum = x; \
584 *s++; \
585 } \
586 res = sum; \
587 }
588
589 #define STRxTONUM(s, type, res, limit) \
590 { \
591 int base; \
592 if (*s == '0') \
593 { \
594 s++; \
595 if (*s == 0) \
596 base = 10; \
597 else if (*s == 'x' || *s == 'X') \
598 { \
599 s++; \
600 base = 16; \
601 } \
602 else \
603 base = 8; \
604 } else \
605 base = 10; \
606 STRTONUM (s, type, base, res, limit); \
607 }
608
609 #define GETUNUM(str, type, res) \
610 { \
611 type tmpres; \
612 const char *s = str; \
613 STRxTONUM (s, type, tmpres, 0); \
614 if (*s) \
615 { \
616 mu_cfg_perror (sdata->call_data, \
617 &node->locus, \
618 _("not a number (stopped near `%s')"), \
619 s); \
620 return 1; \
621 } \
622 res = tmpres; \
623 }
624
625 #define GETSNUM(str, type, res) \
626 { \
627 unsigned type tmpres; \
628 const char *s = str; \
629 int sign; \
630 unsigned type limit; \
631 \
632 if (*s == '-') \
633 { \
634 sign++; \
635 s++; \
636 limit = TYPE_MINIMUM (type); \
637 limit = - limit; \
638 } \
639 else \
640 { \
641 sign = 0; \
642 limit = TYPE_MAXIMUM (type); \
643 } \
644 \
645 STRxTONUM (s, unsigned type, tmpres, limit); \
646 if (*s) \
647 { \
648 mu_cfg_perror (sdata->call_data, \
649 &node->locus, \
650 _("not a number (stopped near `%s')"), \
651 s); \
652 return 1; \
653 } \
654 res = sign ? - tmpres : tmpres; \
655 }
656
657 static int
658 parse_ipv4 (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
659 struct in_addr *res)
660 {
661 struct in_addr addr;
662 if (inet_aton (node->tag_label, &addr) == 0)
663 {
664 mu_cfg_perror (sdata->call_data,
665 &node->locus,
666 _("not an IPv4"));
667 return 1;
668 }
669 addr.s_addr = ntohl (addr.s_addr);
670 *res = addr;
671 return 0;
672 }
673
674 static int
675 parse_host (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
676 struct in_addr *res)
677 {
678 struct in_addr addr;
679 struct hostent *hp = gethostbyname (node->tag_label);
680 if (hp)
681 {
682 addr.s_addr = *(unsigned long *)hp->h_addr;
683 }
684 else if (inet_aton(node->tag_label, &addr) == 0)
685 {
686 mu_cfg_perror (sdata->call_data,
687 &node->locus,
688 _("cannot resolve hostname `%s'"),
689 node->tag_label);
690 return 1;
691 }
692 addr.s_addr = ntohl (addr.s_addr);
693 *res = addr;
694 return 0;
695 }
696
697 static int
698 parse_cidr (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
699 mu_cfg_cidr_t *res)
700 {
701 struct in_addr addr;
702 unsigned long mask;
703 char astr[16], *p, *s;
704
705 p = strchr (node->tag_label, '/');
706 if (*p)
707 {
708 int len = p - node->tag_label;
709 if (len > sizeof astr - 1) {
710 mu_cfg_perror (sdata->call_data,
711 &node->locus,
712 _("not a valid IPv4 address in CIDR"));
713 return 1;
714 }
715 memcpy (astr, node->tag_label, len);
716 astr[len] = 0;
717 if (inet_aton (astr, &addr) == 0)
718 {
719 mu_cfg_perror (sdata->call_data,
720 &node->locus,
721 _("not a valid IPv4 address in CIDR"));
722 return 1;
723 }
724 addr.s_addr = ntohl (addr.s_addr);
725
726 p++;
727 s = p;
728 STRxTONUM (s, unsigned long, mask, 0);
729 if (*s == '.')
730 {
731 struct in_addr a;
732 if (inet_aton (p, &a) == 0)
733 {
734 mu_cfg_perror (sdata->call_data,
735 &node->locus,
736 _("not a valid network in CIDR"));
737 return 1;
738 }
739 a.s_addr = ntohl (a.s_addr);
740 for (mask = 0; (a.s_addr & 1) == 0 && mask < 32; )
741 {
742 mask++;
743 a.s_addr >>= 1;
744 }
745 mask = 32 - mask;
746 }
747 else if (mask > 32)
748 {
749 mu_cfg_perror (sdata->call_data,
750 &node->locus,
751 _("not a valid network mask in CIDR"));
752 return 1;
753 }
754 }
755 else
756 {
757 int i;
758 unsigned short x;
759 addr.s_addr = 0;
760
761 for (i = 0; i < 3; i++)
762 {
763 STRxTONUM(p, unsigned short, x, 255);
764 if (*p != '.')
765 break;
766 addr.s_addr = (addr.s_addr << 8) + x;
767 }
768
769 if (*p)
770 {
771 mu_cfg_perror (sdata->call_data,
772 &node->locus,
773 _("not a CIDR (stopped near `%s')"),
774 p);
775 return 1;
776 }
777
778 mask = i * 8;
779
780 addr.s_addr <<= (4 - i) * 8;
781 }
782
783 res->addr = addr;
784 res->mask = mask;
785 return 0;
786 }
787
788 static int
789 parse_bool (struct scan_tree_data *sdata, const mu_cfg_node_t *node, int *res)
790 {
791 if (strcmp (node->tag_label, "yes") == 0
792 || strcmp (node->tag_label, "on") == 0
793 || strcmp (node->tag_label, "t") == 0
794 || strcmp (node->tag_label, "true") == 0
795 || strcmp (node->tag_label, "1") == 0)
796 *res = 1;
797 else if (strcmp (node->tag_label, "no") == 0
798 || strcmp (node->tag_label, "off") == 0
799 || strcmp (node->tag_label, "nil") == 0
800 || strcmp (node->tag_label, "false") == 0
801 || strcmp (node->tag_label, "0") == 0)
802 *res = 0;
803 else
804 {
805 mu_cfg_perror (sdata->call_data, &node->locus, _("not a boolean"));
806 return 1;
807 }
808 return 0;
809 }
810
811 static int
812 parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
813 {
814 struct mu_cfg_param *param = find_param (sdata->list->sec, node->tag_name,
815 0);
816 if (!param)
817 {
818 mu_cfg_perror (sdata->call_data,
819 &node->locus,
820 _("unknown keyword `%s'"),
821 node->tag_name);
822 return 1;
823 }
824
825 switch (param->type)
826 {
827 case mu_cfg_string:
828 {
829 size_t len = strlen (node->tag_label);
830 char *s = _mu_cfg_alloc (len + 1);
831 if (!s)
832 {
833 mu_cfg_perror (sdata->call_data,
834 &node->locus,
835 _("not enough memory"));
836 return 1;
837 }
838 strcpy (s, node->tag_label);
839 /* FIXME: free param->data? */
840 *(char**)param->data = s;
841 break;
842 }
843
844 case mu_cfg_short:
845 GETSNUM (node->tag_label, short, *(short*)param->data);
846 break;
847
848 case mu_cfg_ushort:
849 GETUNUM (node->tag_label, unsigned short, *(unsigned short*)param->data);
850 break;
851
852 case mu_cfg_int:
853 GETSNUM (node->tag_label, int, *(int*)param->data);
854 break;
855
856 case mu_cfg_uint:
857 GETUNUM (node->tag_label, unsigned int, *(unsigned int*)param->data);
858 break;
859
860 case mu_cfg_long:
861 GETSNUM (node->tag_label, long, *(long*)param->data);
862 break;
863
864 case mu_cfg_ulong:
865 GETUNUM (node->tag_label, unsigned long, *(unsigned long*)param->data);
866 break;
867
868 case mu_cfg_size:
869 GETUNUM (node->tag_label, size_t, *(size_t*)param->data);
870 break;
871
872 case mu_cfg_off:
873 mu_cfg_perror (sdata->call_data, &node->locus, _("not implemented yet"));
874 /* GETSNUM(node->tag_label, off_t, *(off_t*)param->data); */
875 return 1;
876
877 case mu_cfg_bool:
878 if (parse_bool (sdata, node, (int*) param->data))
879 return 1;
880 break;
881
882 case mu_cfg_ipv4:
883 if (parse_ipv4 (sdata, node, (struct in_addr *)param->data))
884 return 1;
885 break;
886
887 case mu_cfg_cidr:
888 if (parse_cidr (sdata, node, (mu_cfg_cidr_t *)param->data))
889 return 1;
890 break;
891
892 case mu_cfg_host:
893 if (parse_host (sdata, node, (struct in_addr *)param->data))
894 return 1;
895 break;
896
897 case mu_cfg_callback:
898 if (param->callback (&node->locus, param->data, node->tag_label))
899 return 1;
900 break;
901
902 default:
903 abort ();
904 }
905 return 0;
906 }
907
908
909 static int
910 _scan_tree_helper (const mu_cfg_node_t *node, void *data)
911 {
912 struct scan_tree_data *sdata = data;
913 struct mu_cfg_section *sec;
914
915 switch (node->type)
916 {
917 case mu_cfg_node_undefined:
918 abort ();
919
920 case mu_cfg_node_tag:
921 sec = find_subsection (sdata->list->sec, node->tag_name, 0);
922 if (!sec)
923 {
924 mu_cfg_perror (sdata->call_data,
925 &node->locus,
926 _("unknown section `%s'"),
927 node->tag_name);
928 sdata->error++;
929 return MU_CFG_ITER_SKIP;
930 }
931 if (!sec->subsec && !sec->param)
932 return MU_CFG_ITER_SKIP;
933 if (sec->parser &&
934 sec->parser (mu_cfg_section_start, node,
935 sec->data, sdata->call_data))
936 {
937 sdata->error++;
938 return MU_CFG_ITER_SKIP;
939 }
940 push_section(sdata, sec);
941 break;
942
943 case mu_cfg_node_param:
944 if (parse_param (sdata, node))
945 {
946 sdata->error++;
947 return MU_CFG_ITER_SKIP;
948 }
949 break;
950 }
951 return MU_CFG_ITER_OK;
952 }
953
954 static int
955 _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
956 {
957 struct scan_tree_data *sdata = data;
958 struct mu_cfg_section *sec;
959
960 switch (node->type)
961 {
962 default:
963 abort ();
964
965 case mu_cfg_node_tag:
966 sec = pop_section (sdata);
967 if (sec && sec->parser)
968 {
969 if (sec->parser (mu_cfg_section_end, node, sec->data,
970 sdata->call_data))
971 {
972 sdata->error++;
973 return MU_CFG_ITER_SKIP;
974 }
975 }
976 }
977 return MU_CFG_ITER_OK;
978 }
979
980 int
981 mu_cfg_scan_tree (mu_cfg_node_t *node,
982 struct mu_cfg_section *sections,
983 void *data, mu_cfg_perror_t perror,
984 mu_cfg_alloc_t palloc, mu_cfg_free_t pfree)
985 {
986 struct scan_tree_data dat;
987 dat.list = NULL;
988 mu_cfg_perror = perror ? perror : _mu_cfg_default_perror;
989 _mu_cfg_alloc = palloc ? palloc : malloc;
990 _mu_cfg_free = pfree ? pfree : free;
991 dat.call_data = data;
992 dat.error = 0;
993 if (push_section (&dat, sections))
994 return 1;
995 mu_cfg_preorder (node, _scan_tree_helper, _scan_tree_end_helper, &dat);
996 pop_section (&dat);
997 return dat.error;
998 }
999
1000 int
1001 mu_cfg_find_section (struct mu_cfg_section *root_sec,
1002 const char *path, struct mu_cfg_section **retval)
1003 {
1004 while (path[0])
1005 {
1006 struct mu_cfg_section *sec;
1007 size_t len;
1008 const char *p;
1009
1010 while (*path == '/')
1011 path++;
1012
1013 if (*path == 0)
1014 return MU_ERR_NOENT;
1015
1016 p = strchr (path, '/');
1017 if (p)
1018 len = p - path;
1019 else
1020 len = strlen (path);
1021
1022 sec = find_subsection (root_sec, path, len);
1023 if (!sec)
1024 return MU_ERR_NOENT;
1025 root_sec = sec;
1026 path += len;
1027 }
1028 if (retval)
1029 *retval = root_sec;
1030 return 0;
1031 }
1032
1033
1034
1035