diff --git a/backport-Add-logic-to-handle-memory-allocation-failures.patch b/backport-Add-logic-to-handle-memory-allocation-failures.patch new file mode 100644 index 0000000000000000000000000000000000000000..24b3f3c92c5a367f724887c59870e7c1d75bdd72 --- /dev/null +++ b/backport-Add-logic-to-handle-memory-allocation-failures.patch @@ -0,0 +1,3439 @@ +From 2c40b58062abcec834187ad965e30ad7568ce9b7 Mon Sep 17 00:00:00 2001 +From: Mark Lindner +Date: Mon, 21 Nov 2022 20:28:57 -0700 +Subject: [PATCH] Add logic to handle memory allocation failures. + +More generically, this patch adds handling of fatal errors. +Memory allocation failures are currently the only type of +fatal error. + +- New C API config_set_fatal_error_func() allowing caller + to provide a fatal error handler. +- A default handler will write a message to stderr and then + call abort(). +- The C++ library installs an internal handler that throws + std::bad_alloc +- Route all malloc/calloc/realloc requests through new + wrapper functions libconfig_malloc(), libconfig_calloc(), + libconfig_realloc(), which call the above and then check + the return value. If it's NULL, they call the fatal error handler. +- Force the flex- and bison-generated code to call the libconfig + alloc functions instead of their default ones. +--- + ac_config.h.in | 98 ++- + debian/copyright | 2 +- + doc/libconfig.texi | 44 +- + examples/c++/example1.cpp | 2 +- + examples/c++/example2.cpp | 2 +- + examples/c++/example3.cpp | 2 +- + examples/c++/example4.cpp | 2 +- + examples/c/example1.c | 2 +- + examples/c/example2.c | 2 +- + examples/c/example3.c | 2 +- + examples/c/example4.c | 2 +- + lib/grammar.c | 1221 +++++++++++++++++-------------------- + lib/grammar.h | 79 ++- + lib/grammar.y | 4 +- + lib/libconfig.c | 16 +- + lib/libconfig.h | 7 +- + lib/libconfig.h++ | 2 +- + lib/libconfig.hh | 2 +- + lib/libconfigcpp.c++ | 12 +- + lib/libconfigcpp.cc | 2 +- + lib/parsectx.h | 2 +- + lib/scanctx.c | 2 +- + lib/scanctx.h | 2 +- + lib/scanner.c | 138 ++--- + lib/scanner.h | 7 +- + lib/scanner.l | 15 +- + lib/strbuf.c | 4 +- + lib/strbuf.h | 2 +- + lib/strvec.c | 4 +- + lib/strvec.h | 2 +- + lib/util.c | 66 +- + lib/util.h | 12 +- + lib/wincompat.c | 2 +- + lib/wincompat.h | 2 +- + tests/tests.c | 10 +- + 35 files changed, 957 insertions(+), 818 deletions(-) + +diff --git a/ac_config.h.in b/ac_config.h.in +index 6244938..33d48bd 100644 +--- a/ac_config.h.in ++++ b/ac_config.h.in +@@ -9,8 +9,8 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_INTTYPES_H + +-/* Define to 1 if you have the header file. */ +-#undef HAVE_MEMORY_H ++/* Define to 1 if you have the header file. */ ++#undef HAVE_MINIX_CONFIG_H + + /* Define to 1 if you have the `newlocale' function. */ + #undef HAVE_NEWLOCALE +@@ -18,6 +18,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_STDINT_H + ++/* Define to 1 if you have the header file. */ ++#undef HAVE_STDIO_H ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_STDLIB_H + +@@ -39,6 +42,9 @@ + /* Define to 1 if you have the `uselocale' function. */ + #undef HAVE_USELOCALE + ++/* Define to 1 if you have the header file. */ ++#undef HAVE_WCHAR_H ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_XLOCALE_H + +@@ -67,7 +73,9 @@ + /* Define to the version of this package. */ + #undef PACKAGE_VERSION + +-/* Define to 1 if you have the ANSI C header files. */ ++/* Define to 1 if all of the C90 standard headers exist (not just the ones ++ required in a freestanding environment). This macro is provided for ++ backward compatibility; new code need not use it. */ + #undef STDC_HEADERS + + /* Configured target name. */ +@@ -77,21 +85,87 @@ + #ifndef _ALL_SOURCE + # undef _ALL_SOURCE + #endif ++/* Enable general extensions on macOS. */ ++#ifndef _DARWIN_C_SOURCE ++# undef _DARWIN_C_SOURCE ++#endif ++/* Enable general extensions on Solaris. */ ++#ifndef __EXTENSIONS__ ++# undef __EXTENSIONS__ ++#endif + /* Enable GNU extensions on systems that have them. */ + #ifndef _GNU_SOURCE + # undef _GNU_SOURCE + #endif +-/* Enable threading extensions on Solaris. */ ++/* Enable X/Open compliant socket functions that do not require linking ++ with -lxnet on HP-UX 11.11. */ ++#ifndef _HPUX_ALT_XOPEN_SOCKET_API ++# undef _HPUX_ALT_XOPEN_SOCKET_API ++#endif ++/* Identify the host operating system as Minix. ++ This macro does not affect the system headers' behavior. ++ A future release of Autoconf may stop defining this macro. */ ++#ifndef _MINIX ++# undef _MINIX ++#endif ++/* Enable general extensions on NetBSD. ++ Enable NetBSD compatibility extensions on Minix. */ ++#ifndef _NETBSD_SOURCE ++# undef _NETBSD_SOURCE ++#endif ++/* Enable OpenBSD compatibility extensions on NetBSD. ++ Oddly enough, this does nothing on OpenBSD. */ ++#ifndef _OPENBSD_SOURCE ++# undef _OPENBSD_SOURCE ++#endif ++/* Define to 1 if needed for POSIX-compatible behavior. */ ++#ifndef _POSIX_SOURCE ++# undef _POSIX_SOURCE ++#endif ++/* Define to 2 if needed for POSIX-compatible behavior. */ ++#ifndef _POSIX_1_SOURCE ++# undef _POSIX_1_SOURCE ++#endif ++/* Enable POSIX-compatible threading on Solaris. */ + #ifndef _POSIX_PTHREAD_SEMANTICS + # undef _POSIX_PTHREAD_SEMANTICS + #endif ++/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ ++#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ ++# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ ++#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ ++# undef __STDC_WANT_IEC_60559_BFP_EXT__ ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ ++#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ ++# undef __STDC_WANT_IEC_60559_DFP_EXT__ ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ ++#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ ++# undef __STDC_WANT_IEC_60559_FUNCS_EXT__ ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ ++#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ ++# undef __STDC_WANT_IEC_60559_TYPES_EXT__ ++#endif ++/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ ++#ifndef __STDC_WANT_LIB_EXT2__ ++# undef __STDC_WANT_LIB_EXT2__ ++#endif ++/* Enable extensions specified by ISO/IEC 24747:2009. */ ++#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ ++# undef __STDC_WANT_MATH_SPEC_FUNCS__ ++#endif + /* Enable extensions on HP NonStop. */ + #ifndef _TANDEM_SOURCE + # undef _TANDEM_SOURCE + #endif +-/* Enable general extensions on Solaris. */ +-#ifndef __EXTENSIONS__ +-# undef __EXTENSIONS__ ++/* Enable X/Open extensions. Define to 500 only if necessary ++ to make mbstate_t available. */ ++#ifndef _XOPEN_SOURCE ++# undef _XOPEN_SOURCE + #endif + + +@@ -102,15 +176,5 @@ + `char[]'. */ + #undef YYTEXT_POINTER + +-/* Define to 1 if on MINIX. */ +-#undef _MINIX +- +-/* Define to 2 if the system does not provide POSIX.1 features except with +- this defined. */ +-#undef _POSIX_1_SOURCE +- +-/* Define to 1 if you need to in order for `stat' and other things to work. */ +-#undef _POSIX_SOURCE +- + /* Define to empty if `const' does not conform to ANSI C. */ + #undef const +diff --git a/debian/copyright b/debian/copyright +index 94a3ec2..4cb34b0 100644 +--- a/debian/copyright ++++ b/debian/copyright +@@ -11,7 +11,7 @@ Upstream Author: Mark A Lindner + Jose Luis Tallon - Enhancements, bugfixes + + +-Copyright: Copyright (C) 2005-2015 Mark A Lindner ++Copyright: Copyright (C) 2005-2023 Mark A Lindner + + License: LGPL-2.1 + +diff --git a/doc/libconfig.texi b/doc/libconfig.texi +index 9645077..09b5443 100644 +--- a/doc/libconfig.texi ++++ b/doc/libconfig.texi +@@ -7,7 +7,7 @@ + @settitle libconfig + + @set edition 1.7.3 +-@set update-date 20 Jun 2021 ++@set update-date 22 Nov 2022 + @set subtitle-text A Library For Processing Structured Configuration Files + @set author-text Mark A.@: Lindner + +@@ -38,7 +38,7 @@ + + @page + @vskip 0pt plus 1filll +-Copyright @copyright{} 2004-2021 Mark A Lindner ++Copyright @copyright{} 2004-2023 Mark A Lindner + + Permission is granted to make and distribute verbatim copies of + this manual provided the copyright notice and this permission notice +@@ -800,6 +800,42 @@ and a parsing error, respectively. + + @end deftypefun + ++@deftypefun void config_set_fatal_error_func (@w{config_fatal_error_fn_t @var{func}}) ++ ++@b{Since @i{v1.7.3}} ++ ++@cindex fatal error ++Specifies the function @var{func} to call when a fatal error is encountered. ++If @var{func} is @code{NULL}, the default fatal error handler function will ++be reinstated. ++ ++@tindex config_fatal_error_fn_t ++The type @i{config_fatal_error_fn_t} is a type alias ++for a function whose signature is: ++ ++@deftypefun @w{void} func (@w{const char *@var{message}}) ++ ++The function receives an error message @var{message}. The function is ++not expected to return to the caller; if it does, the resulting ++behavior is undefined. ++ ++@end deftypefun ++ ++Fatal errors are unrecoverable, and the only reasonable course of ++action is to abort the calling process. The default fatal error ++handler function writes a message to standard error and then calls ++@code{abort()}. One potential alternate implementation would be to ++call @code{exit()} with an exit status that indicates to the parent ++process (such as a watchdog process) that the current process has ++encountered an unrecoverable condition and should be respawned. ++ ++In the current implementation, the only condition that will produce a ++fatal error is a memory allocation failure---that is, a @code{NULL} ++return value from @code{malloc()}, @code{calloc()}, or ++@code{realloc()}. ++ ++@end deftypefun ++ + @deftypefun void config_set_include_dir (@w{config_t *@var{config}}, @w{const char *@var{include_dir}}) + @deftypefunx {const char *} config_get_include_dir (@w{const config_t *@var{config}}) + +@@ -879,8 +915,8 @@ implementations of such include functions are not included. + + @end deftypefun + +-@deftypefun {unsigned short} config_get_float_precision(@w{config_t *@var{config}}) +-@deftypefunx void config_set_float_precision(@w{config_t *@var{config}}, @w{unsigned short @var{digits}}) ++@deftypefun {unsigned short} config_get_float_precision (@w{config_t *@var{config}}) ++@deftypefunx void config_set_float_precision (@w{config_t *@var{config}}, @w{unsigned short @var{digits}}) + + @b{Since @i{v1.6}} + +diff --git a/examples/c++/example1.cpp b/examples/c++/example1.cpp +index 1fb5ff6..7e88db4 100644 +--- a/examples/c++/example1.cpp ++++ b/examples/c++/example1.cpp +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2010 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/examples/c++/example2.cpp b/examples/c++/example2.cpp +index 13f862c..6afdfb3 100644 +--- a/examples/c++/example2.cpp ++++ b/examples/c++/example2.cpp +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2010 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/examples/c++/example3.cpp b/examples/c++/example3.cpp +index da5caf5..d913f05 100644 +--- a/examples/c++/example3.cpp ++++ b/examples/c++/example3.cpp +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2010 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/examples/c++/example4.cpp b/examples/c++/example4.cpp +index b23f4c5..3cb90e4 100644 +--- a/examples/c++/example4.cpp ++++ b/examples/c++/example4.cpp +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2010 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/examples/c/example1.c b/examples/c/example1.c +index 0c7b5b4..f2ff9af 100644 +--- a/examples/c/example1.c ++++ b/examples/c/example1.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/examples/c/example2.c b/examples/c/example2.c +index 2859bd9..eeac345 100644 +--- a/examples/c/example2.c ++++ b/examples/c/example2.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/examples/c/example3.c b/examples/c/example3.c +index 5b7f8a7..aa27db5 100644 +--- a/examples/c/example3.c ++++ b/examples/c/example3.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/examples/c/example4.c b/examples/c/example4.c +index 05396c5..3f546a2 100644 +--- a/examples/c/example4.c ++++ b/examples/c/example4.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/grammar.c b/lib/grammar.c +index a4a37ec..26aa039 100644 +--- a/lib/grammar.c ++++ b/lib/grammar.c +@@ -1,8 +1,9 @@ +-/* A Bison parser, made by GNU Bison 3.0.4. */ ++/* A Bison parser, made by GNU Bison 3.8. */ + + /* Bison implementation for Yacc-like parsers in C + +- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. ++ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, ++ Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -15,7 +16,7 @@ + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +- along with this program. If not, see . */ ++ along with this program. If not, see . */ + + /* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work +@@ -33,6 +34,10 @@ + /* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + ++/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, ++ especially those whose name start with YY_ or yy_. They are ++ private implementation details that can be changed or removed. */ ++ + /* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. +@@ -40,11 +45,11 @@ + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +-/* Identify Bison output. */ +-#define YYBISON 1 ++/* Identify Bison output, and Bison version. */ ++#define YYBISON 30800 + +-/* Bison version. */ +-#define YYBISON_VERSION "3.0.4" ++/* Bison version string. */ ++#define YYBISON_VERSION "3.8" + + /* Skeleton name. */ + #define YYSKELETON_NAME "yacc.c" +@@ -66,9 +71,8 @@ + #define yydebug libconfig_yydebug + #define yynerrs libconfig_yynerrs + +- +-/* Copy the first part of user declarations. */ +-#line 32 "grammar.y" /* yacc.c:339 */ ++/* First part of user prologue. */ ++#line 32 "grammar.y" + + #include + #include +@@ -83,6 +87,8 @@ + extern int libconfig_yylex(); + extern int libconfig_yyget_lineno(); + ++#define YYMALLOC libconfig_malloc ++ + static const char *err_array_elem_type = "mismatched element type in array"; + static const char *err_duplicate_setting = "duplicate setting name"; + +@@ -111,26 +117,31 @@ void libconfig_yyerror(void *scanner, struct parse_context *ctx, + } + + +-#line 115 "grammar.c" /* yacc.c:339 */ ++#line 121 "grammar.c" + ++# ifndef YY_CAST ++# ifdef __cplusplus ++# define YY_CAST(Type, Val) static_cast (Val) ++# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) ++# else ++# define YY_CAST(Type, Val) ((Type) (Val)) ++# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) ++# endif ++# endif + # ifndef YY_NULLPTR +-# if defined __cplusplus && 201103L <= __cplusplus +-# define YY_NULLPTR nullptr ++# if defined __cplusplus ++# if 201103L <= __cplusplus ++# define YY_NULLPTR nullptr ++# else ++# define YY_NULLPTR 0 ++# endif + # else +-# define YY_NULLPTR 0 ++# define YY_NULLPTR ((void*)0) + # endif + # endif + +-/* Enabling verbose error messages. */ +-#ifdef YYERROR_VERBOSE +-# undef YYERROR_VERBOSE +-# define YYERROR_VERBOSE 1 +-#else +-# define YYERROR_VERBOSE 0 +-#endif +- +-/* In a future release of Bison, this section will be replaced +- by #include "y.tab.h". */ ++/* Use api.header.include to #include this header ++ instead of duplicating it here. */ + #ifndef YY_LIBCONFIG_YY_GRAMMAR_H_INCLUDED + # define YY_LIBCONFIG_YY_GRAMMAR_H_INCLUDED + /* Debug traces. */ +@@ -141,34 +152,43 @@ void libconfig_yyerror(void *scanner, struct parse_context *ctx, + extern int libconfig_yydebug; + #endif + +-/* Token type. */ ++/* Token kinds. */ + #ifndef YYTOKENTYPE + # define YYTOKENTYPE + enum yytokentype + { +- TOK_BOOLEAN = 258, +- TOK_INTEGER = 259, +- TOK_HEX = 260, +- TOK_INTEGER64 = 261, +- TOK_HEX64 = 262, +- TOK_FLOAT = 263, +- TOK_STRING = 264, +- TOK_NAME = 265, +- TOK_EQUALS = 266, +- TOK_NEWLINE = 267, +- TOK_ARRAY_START = 268, +- TOK_ARRAY_END = 269, +- TOK_LIST_START = 270, +- TOK_LIST_END = 271, +- TOK_COMMA = 272, +- TOK_GROUP_START = 273, +- TOK_GROUP_END = 274, +- TOK_SEMICOLON = 275, +- TOK_GARBAGE = 276, +- TOK_ERROR = 277 ++ YYEMPTY = -2, ++ YYEOF = 0, /* "end of file" */ ++ YYerror = 256, /* error */ ++ YYUNDEF = 257, /* "invalid token" */ ++ TOK_BOOLEAN = 258, /* TOK_BOOLEAN */ ++ TOK_INTEGER = 259, /* TOK_INTEGER */ ++ TOK_HEX = 260, /* TOK_HEX */ ++ TOK_INTEGER64 = 261, /* TOK_INTEGER64 */ ++ TOK_HEX64 = 262, /* TOK_HEX64 */ ++ TOK_FLOAT = 263, /* TOK_FLOAT */ ++ TOK_STRING = 264, /* TOK_STRING */ ++ TOK_NAME = 265, /* TOK_NAME */ ++ TOK_EQUALS = 266, /* TOK_EQUALS */ ++ TOK_NEWLINE = 267, /* TOK_NEWLINE */ ++ TOK_ARRAY_START = 268, /* TOK_ARRAY_START */ ++ TOK_ARRAY_END = 269, /* TOK_ARRAY_END */ ++ TOK_LIST_START = 270, /* TOK_LIST_START */ ++ TOK_LIST_END = 271, /* TOK_LIST_END */ ++ TOK_COMMA = 272, /* TOK_COMMA */ ++ TOK_GROUP_START = 273, /* TOK_GROUP_START */ ++ TOK_GROUP_END = 274, /* TOK_GROUP_END */ ++ TOK_SEMICOLON = 275, /* TOK_SEMICOLON */ ++ TOK_GARBAGE = 276, /* TOK_GARBAGE */ ++ TOK_ERROR = 277 /* TOK_ERROR */ + }; ++ typedef enum yytokentype yytoken_kind_t; + #endif +-/* Tokens. */ ++/* Token kinds. */ ++#define YYEMPTY -2 ++#define YYEOF 0 ++#define YYerror 256 ++#define YYUNDEF 257 + #define TOK_BOOLEAN 258 + #define TOK_INTEGER 259 + #define TOK_HEX 260 +@@ -192,19 +212,18 @@ extern int libconfig_yydebug; + + /* Value type. */ + #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +- + union YYSTYPE + { +-#line 76 "grammar.y" /* yacc.c:355 */ ++#line 78 "grammar.y" + + int ival; + long long llval; + double fval; + char *sval; + +-#line 206 "grammar.c" /* yacc.c:355 */ +-}; ++#line 225 "grammar.c" + ++}; + typedef union YYSTYPE YYSTYPE; + # define YYSTYPE_IS_TRIVIAL 1 + # define YYSTYPE_IS_DECLARED 1 +@@ -212,40 +231,155 @@ typedef union YYSTYPE YYSTYPE; + + + ++#if !defined libconfig_yyerror && !defined YYERROR_IS_DECLARED ++void libconfig_yyerror (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx, const char *msg); ++#endif ++#if !defined libconfig_yylex && !defined YYLEX_IS_DECLARED ++int libconfig_yylex (YYSTYPE *yylvalp, void *scanner); ++#endif ++ + int libconfig_yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx); + ++ + #endif /* !YY_LIBCONFIG_YY_GRAMMAR_H_INCLUDED */ ++/* Symbol kind. */ ++enum yysymbol_kind_t ++{ ++ YYSYMBOL_YYEMPTY = -2, ++ YYSYMBOL_YYEOF = 0, /* "end of file" */ ++ YYSYMBOL_YYerror = 1, /* error */ ++ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ ++ YYSYMBOL_TOK_BOOLEAN = 3, /* TOK_BOOLEAN */ ++ YYSYMBOL_TOK_INTEGER = 4, /* TOK_INTEGER */ ++ YYSYMBOL_TOK_HEX = 5, /* TOK_HEX */ ++ YYSYMBOL_TOK_INTEGER64 = 6, /* TOK_INTEGER64 */ ++ YYSYMBOL_TOK_HEX64 = 7, /* TOK_HEX64 */ ++ YYSYMBOL_TOK_FLOAT = 8, /* TOK_FLOAT */ ++ YYSYMBOL_TOK_STRING = 9, /* TOK_STRING */ ++ YYSYMBOL_TOK_NAME = 10, /* TOK_NAME */ ++ YYSYMBOL_TOK_EQUALS = 11, /* TOK_EQUALS */ ++ YYSYMBOL_TOK_NEWLINE = 12, /* TOK_NEWLINE */ ++ YYSYMBOL_TOK_ARRAY_START = 13, /* TOK_ARRAY_START */ ++ YYSYMBOL_TOK_ARRAY_END = 14, /* TOK_ARRAY_END */ ++ YYSYMBOL_TOK_LIST_START = 15, /* TOK_LIST_START */ ++ YYSYMBOL_TOK_LIST_END = 16, /* TOK_LIST_END */ ++ YYSYMBOL_TOK_COMMA = 17, /* TOK_COMMA */ ++ YYSYMBOL_TOK_GROUP_START = 18, /* TOK_GROUP_START */ ++ YYSYMBOL_TOK_GROUP_END = 19, /* TOK_GROUP_END */ ++ YYSYMBOL_TOK_SEMICOLON = 20, /* TOK_SEMICOLON */ ++ YYSYMBOL_TOK_GARBAGE = 21, /* TOK_GARBAGE */ ++ YYSYMBOL_TOK_ERROR = 22, /* TOK_ERROR */ ++ YYSYMBOL_YYACCEPT = 23, /* $accept */ ++ YYSYMBOL_configuration = 24, /* configuration */ ++ YYSYMBOL_setting_list = 25, /* setting_list */ ++ YYSYMBOL_setting_list_optional = 26, /* setting_list_optional */ ++ YYSYMBOL_setting_terminator = 27, /* setting_terminator */ ++ YYSYMBOL_setting = 28, /* setting */ ++ YYSYMBOL_29_1 = 29, /* $@1 */ ++ YYSYMBOL_array = 30, /* array */ ++ YYSYMBOL_31_2 = 31, /* $@2 */ ++ YYSYMBOL_list = 32, /* list */ ++ YYSYMBOL_33_3 = 33, /* $@3 */ ++ YYSYMBOL_value = 34, /* value */ ++ YYSYMBOL_string = 35, /* string */ ++ YYSYMBOL_simple_value = 36, /* simple_value */ ++ YYSYMBOL_value_list = 37, /* value_list */ ++ YYSYMBOL_value_list_optional = 38, /* value_list_optional */ ++ YYSYMBOL_simple_value_list = 39, /* simple_value_list */ ++ YYSYMBOL_simple_value_list_optional = 40, /* simple_value_list_optional */ ++ YYSYMBOL_group = 41, /* group */ ++ YYSYMBOL_42_4 = 42 /* $@4 */ ++}; ++typedef enum yysymbol_kind_t yysymbol_kind_t; ++ + +-/* Copy the second part of user declarations. */ + +-#line 222 "grammar.c" /* yacc.c:358 */ + + #ifdef short + # undef short + #endif + +-#ifdef YYTYPE_UINT8 +-typedef YYTYPE_UINT8 yytype_uint8; +-#else +-typedef unsigned char yytype_uint8; ++/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure ++ and (if available) are included ++ so that the code can choose integer types of a good width. */ ++ ++#ifndef __PTRDIFF_MAX__ ++# include /* INFRINGES ON USER NAME SPACE */ ++# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ ++# include /* INFRINGES ON USER NAME SPACE */ ++# define YY_STDINT_H ++# endif + #endif + +-#ifdef YYTYPE_INT8 +-typedef YYTYPE_INT8 yytype_int8; ++/* Narrow types that promote to a signed type and that can represent a ++ signed or unsigned integer of at least N bits. In tables they can ++ save space and decrease cache pressure. Promoting to a signed type ++ helps avoid bugs in integer arithmetic. */ ++ ++#ifdef __INT_LEAST8_MAX__ ++typedef __INT_LEAST8_TYPE__ yytype_int8; ++#elif defined YY_STDINT_H ++typedef int_least8_t yytype_int8; + #else + typedef signed char yytype_int8; + #endif + +-#ifdef YYTYPE_UINT16 +-typedef YYTYPE_UINT16 yytype_uint16; ++#ifdef __INT_LEAST16_MAX__ ++typedef __INT_LEAST16_TYPE__ yytype_int16; ++#elif defined YY_STDINT_H ++typedef int_least16_t yytype_int16; ++#else ++typedef short yytype_int16; ++#endif ++ ++/* Work around bug in HP-UX 11.23, which defines these macros ++ incorrectly for preprocessor constants. This workaround can likely ++ be removed in 2023, as HPE has promised support for HP-UX 11.23 ++ (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of ++ . */ ++#ifdef __hpux ++# undef UINT_LEAST8_MAX ++# undef UINT_LEAST16_MAX ++# define UINT_LEAST8_MAX 255 ++# define UINT_LEAST16_MAX 65535 ++#endif ++ ++#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ ++typedef __UINT_LEAST8_TYPE__ yytype_uint8; ++#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ ++ && UINT_LEAST8_MAX <= INT_MAX) ++typedef uint_least8_t yytype_uint8; ++#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX ++typedef unsigned char yytype_uint8; + #else +-typedef unsigned short int yytype_uint16; ++typedef short yytype_uint8; + #endif + +-#ifdef YYTYPE_INT16 +-typedef YYTYPE_INT16 yytype_int16; ++#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ ++typedef __UINT_LEAST16_TYPE__ yytype_uint16; ++#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ ++ && UINT_LEAST16_MAX <= INT_MAX) ++typedef uint_least16_t yytype_uint16; ++#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX ++typedef unsigned short yytype_uint16; + #else +-typedef short int yytype_int16; ++typedef int yytype_uint16; ++#endif ++ ++#ifndef YYPTRDIFF_T ++# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ ++# define YYPTRDIFF_T __PTRDIFF_TYPE__ ++# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ ++# elif defined PTRDIFF_MAX ++# ifndef ptrdiff_t ++# include /* INFRINGES ON USER NAME SPACE */ ++# endif ++# define YYPTRDIFF_T ptrdiff_t ++# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX ++# else ++# define YYPTRDIFF_T long ++# define YYPTRDIFF_MAXIMUM LONG_MAX ++# endif + #endif + + #ifndef YYSIZE_T +@@ -253,15 +387,28 @@ typedef short int yytype_int16; + # define YYSIZE_T __SIZE_TYPE__ + # elif defined size_t + # define YYSIZE_T size_t +-# elif ! defined YYSIZE_T ++# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ + # include /* INFRINGES ON USER NAME SPACE */ + # define YYSIZE_T size_t + # else +-# define YYSIZE_T unsigned int ++# define YYSIZE_T unsigned + # endif + #endif + +-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) ++#define YYSIZE_MAXIMUM \ ++ YY_CAST (YYPTRDIFF_T, \ ++ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ ++ ? YYPTRDIFF_MAXIMUM \ ++ : YY_CAST (YYSIZE_T, -1))) ++ ++#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) ++ ++ ++/* Stored state numbers (used for stacks). */ ++typedef yytype_int8 yy_state_t; ++ ++/* State numbers in computations. */ ++typedef int yy_state_fast_t; + + #ifndef YY_ + # if defined YYENABLE_NLS && YYENABLE_NLS +@@ -275,47 +422,43 @@ typedef short int yytype_int16; + # endif + #endif + +-#ifndef YY_ATTRIBUTE +-# if (defined __GNUC__ \ +- && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ +- || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +-# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +-# else +-# define YY_ATTRIBUTE(Spec) /* empty */ +-# endif +-#endif + + #ifndef YY_ATTRIBUTE_PURE +-# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) ++# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) ++# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) ++# else ++# define YY_ATTRIBUTE_PURE ++# endif + #endif + + #ifndef YY_ATTRIBUTE_UNUSED +-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +-#endif +- +-#if !defined _Noreturn \ +- && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +-# if defined _MSC_VER && 1200 <= _MSC_VER +-# define _Noreturn __declspec (noreturn) ++# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) ++# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) + # else +-# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) ++# define YY_ATTRIBUTE_UNUSED + # endif + #endif + + /* Suppress unused-variable warnings by "using" E. */ + #if ! defined lint || defined __GNUC__ +-# define YYUSE(E) ((void) (E)) ++# define YY_USE(E) ((void) (E)) + #else +-# define YYUSE(E) /* empty */ ++# define YY_USE(E) /* empty */ + #endif + +-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ + /* Suppress an incorrect diagnostic about yylval being uninitialized. */ +-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ +- _Pragma ("GCC diagnostic push") \ +- _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ ++#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ ++# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 ++# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ ++ _Pragma ("GCC diagnostic push") \ ++ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") ++# else ++# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ ++ _Pragma ("GCC diagnostic push") \ ++ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ ++# endif ++# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") + #else + # define YY_INITIAL_VALUE(Value) Value +@@ -328,8 +471,22 @@ typedef short int yytype_int16; + # define YY_INITIAL_VALUE(Value) /* Nothing. */ + #endif + ++#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ ++# define YY_IGNORE_USELESS_CAST_BEGIN \ ++ _Pragma ("GCC diagnostic push") \ ++ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") ++# define YY_IGNORE_USELESS_CAST_END \ ++ _Pragma ("GCC diagnostic pop") ++#endif ++#ifndef YY_IGNORE_USELESS_CAST_BEGIN ++# define YY_IGNORE_USELESS_CAST_BEGIN ++# define YY_IGNORE_USELESS_CAST_END ++#endif ++ + +-#if ! defined yyoverflow || YYERROR_VERBOSE ++#define YY_ASSERT(E) ((void) (0 && (E))) ++ ++#if !defined yyoverflow + + /* The parser invokes alloca or malloc; define the necessary symbols. */ + +@@ -394,8 +551,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ + # endif + # endif + # endif +-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ +- ++#endif /* !defined yyoverflow */ + + #if (! defined yyoverflow \ + && (! defined __cplusplus \ +@@ -404,17 +560,17 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ + /* A type that is properly aligned for any stack member. */ + union yyalloc + { +- yytype_int16 yyss_alloc; ++ yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; + }; + + /* The size of the maximum gap between one aligned stack and the next. */ +-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) ++# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + + /* The size of an array large to enough to hold all stacks, each with + N elements. */ + # define YYSTACK_BYTES(N) \ +- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ ++ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + + # define YYCOPY_NEEDED 1 +@@ -427,11 +583,11 @@ union yyalloc + # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ +- YYSIZE_T yynewbytes; \ ++ YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ +- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ +- yyptr += yynewbytes / sizeof (*yyptr); \ ++ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ ++ yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + +@@ -443,12 +599,12 @@ union yyalloc + # ifndef YYCOPY + # if defined __GNUC__ && 1 < __GNUC__ + # define YYCOPY(Dst, Src, Count) \ +- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) ++ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) + # else + # define YYCOPY(Dst, Src, Count) \ + do \ + { \ +- YYSIZE_T yyi; \ ++ YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ +@@ -471,17 +627,20 @@ union yyalloc + /* YYNSTATES -- Number of states. */ + #define YYNSTATES 47 + +-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned +- by yylex, with out-of-bounds checking. */ +-#define YYUNDEFTOK 2 ++/* YYMAXUTOK -- Last valid token kind. */ + #define YYMAXUTOK 277 + +-#define YYTRANSLATE(YYX) \ +- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) ++ ++/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM ++ as returned by yylex, with out-of-bounds checking. */ ++#define YYTRANSLATE(YYX) \ ++ (0 <= (YYX) && (YYX) <= YYMAXUTOK \ ++ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ ++ : YYSYMBOL_YYUNDEF) + + /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM +- as returned by yylex, without out-of-bounds checking. */ +-static const yytype_uint8 yytranslate[] = ++ as returned by yylex. */ ++static const yytype_int8 yytranslate[] = + { + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +@@ -514,57 +673,60 @@ static const yytype_uint8 yytranslate[] = + }; + + #if YYDEBUG +- /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +-static const yytype_uint16 yyrline[] = ++/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ ++static const yytype_int16 yyrline[] = + { +- 0, 92, 92, 94, 98, 99, 102, 104, 107, 109, +- 110, 115, 114, 134, 133, 157, 156, 179, 180, 181, +- 182, 186, 187, 191, 211, 233, 255, 277, 299, 317, +- 345, 346, 347, 350, 352, 356, 357, 358, 361, 363, +- 368, 367 ++ 0, 94, 94, 96, 100, 101, 104, 106, 109, 111, ++ 112, 117, 116, 136, 135, 159, 158, 181, 182, 183, ++ 184, 188, 189, 193, 213, 235, 257, 279, 301, 319, ++ 347, 348, 349, 352, 354, 358, 359, 360, 363, 365, ++ 370, 369 + }; + #endif + +-#if YYDEBUG || YYERROR_VERBOSE || 0 ++/** Accessing symbol of state STATE. */ ++#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) ++ ++#if YYDEBUG || 0 ++/* The user-facing name of the symbol whose (internal) number is ++ YYSYMBOL. No bounds checking. */ ++static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; ++ + /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ + static const char *const yytname[] = + { +- "$end", "error", "$undefined", "TOK_BOOLEAN", "TOK_INTEGER", "TOK_HEX", +- "TOK_INTEGER64", "TOK_HEX64", "TOK_FLOAT", "TOK_STRING", "TOK_NAME", +- "TOK_EQUALS", "TOK_NEWLINE", "TOK_ARRAY_START", "TOK_ARRAY_END", +- "TOK_LIST_START", "TOK_LIST_END", "TOK_COMMA", "TOK_GROUP_START", +- "TOK_GROUP_END", "TOK_SEMICOLON", "TOK_GARBAGE", "TOK_ERROR", "$accept", +- "configuration", "setting_list", "setting_list_optional", +- "setting_terminator", "setting", "$@1", "array", "$@2", "list", "$@3", +- "value", "string", "simple_value", "value_list", "value_list_optional", +- "simple_value_list", "simple_value_list_optional", "group", "$@4", YY_NULLPTR ++ "\"end of file\"", "error", "\"invalid token\"", "TOK_BOOLEAN", ++ "TOK_INTEGER", "TOK_HEX", "TOK_INTEGER64", "TOK_HEX64", "TOK_FLOAT", ++ "TOK_STRING", "TOK_NAME", "TOK_EQUALS", "TOK_NEWLINE", "TOK_ARRAY_START", ++ "TOK_ARRAY_END", "TOK_LIST_START", "TOK_LIST_END", "TOK_COMMA", ++ "TOK_GROUP_START", "TOK_GROUP_END", "TOK_SEMICOLON", "TOK_GARBAGE", ++ "TOK_ERROR", "$accept", "configuration", "setting_list", ++ "setting_list_optional", "setting_terminator", "setting", "$@1", "array", ++ "$@2", "list", "$@3", "value", "string", "simple_value", "value_list", ++ "value_list_optional", "simple_value_list", "simple_value_list_optional", ++ "group", "$@4", YY_NULLPTR + }; +-#endif + +-# ifdef YYPRINT +-/* YYTOKNUM[NUM] -- (External) token number corresponding to the +- (internal) symbol number NUM (which must be that of a token). */ +-static const yytype_uint16 yytoknum[] = ++static const char * ++yysymbol_name (yysymbol_kind_t yysymbol) + { +- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, +- 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, +- 275, 276, 277 +-}; +-# endif ++ return yytname[yysymbol]; ++} ++#endif + +-#define YYPACT_NINF -26 ++#define YYPACT_NINF (-26) + +-#define yypact_value_is_default(Yystate) \ +- (!!((Yystate) == (-26))) ++#define yypact_value_is_default(Yyn) \ ++ ((Yyn) == YYPACT_NINF) + +-#define YYTABLE_NINF -1 ++#define YYTABLE_NINF (-1) + +-#define yytable_value_is_error(Yytable_value) \ ++#define yytable_value_is_error(Yyn) \ + 0 + +- /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing +- STATE-NUM. */ ++/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing ++ STATE-NUM. */ + static const yytype_int8 yypact[] = + { + -8, -26, 12, -8, -26, 5, -26, -26, 0, -26, +@@ -574,10 +736,10 @@ static const yytype_int8 yypact[] = + 23, -26, 0, -26, -26, -26, -26 + }; + +- /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. +- Performed when YYTABLE does not specify something else to do. Zero +- means the default is an error. */ +-static const yytype_uint8 yydefact[] = ++/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. ++ Performed when YYTABLE does not specify something else to do. Zero ++ means the default is an error. */ ++static const yytype_int8 yydefact[] = + { + 2, 11, 0, 3, 4, 0, 1, 5, 0, 23, + 24, 26, 25, 27, 28, 21, 13, 15, 40, 18, +@@ -586,24 +748,24 @@ static const yytype_uint8 yydefact[] = + 37, 14, 32, 16, 41, 36, 31 + }; + +- /* YYPGOTO[NTERM-NUM]. */ ++/* YYPGOTO[NTERM-NUM]. */ + static const yytype_int8 yypgoto[] = + { + -26, -26, -5, -26, -26, -3, -26, -26, -26, -26, + -26, -25, -26, -15, -26, -26, -26, -26, -26, -26 + }; + +- /* YYDEFGOTO[NTERM-NUM]. */ ++/* YYDEFGOTO[NTERM-NUM]. */ + static const yytype_int8 yydefgoto[] = + { +- -1, 2, 3, 39, 30, 4, 5, 19, 25, 20, ++ 0, 2, 3, 39, 30, 4, 5, 19, 25, 20, + 26, 21, 22, 23, 36, 37, 33, 34, 24, 27 + }; + +- /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If +- positive, shift that token. If negative, reduce the rule whose +- number is the opposite. If YYTABLE_NINF, syntax error. */ +-static const yytype_uint8 yytable[] = ++/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If ++ positive, shift that token. If negative, reduce the rule whose ++ number is the opposite. If YYTABLE_NINF, syntax error. */ ++static const yytype_int8 yytable[] = + { + 7, 35, 1, 9, 10, 11, 12, 13, 14, 15, + 32, 28, 6, 16, 29, 17, 8, 46, 18, 31, +@@ -619,9 +781,9 @@ static const yytype_int8 yycheck[] = + 7, 8, 9, 19, -1, 38 + }; + +- /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing +- symbol of state STATE-NUM. */ +-static const yytype_uint8 yystos[] = ++/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of ++ state STATE-NUM. */ ++static const yytype_int8 yystos[] = + { + 0, 10, 24, 25, 28, 29, 0, 28, 11, 3, + 4, 5, 6, 7, 8, 9, 13, 15, 18, 30, +@@ -630,8 +792,8 @@ static const yytype_uint8 yystos[] = + 17, 14, 17, 16, 19, 36, 34 + }; + +- /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +-static const yytype_uint8 yyr1[] = ++/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ ++static const yytype_int8 yyr1[] = + { + 0, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 27, 29, 28, 31, 30, 33, 32, 34, 34, 34, +@@ -640,8 +802,8 @@ static const yytype_uint8 yyr1[] = + 42, 41 + }; + +- /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +-static const yytype_uint8 yyr2[] = ++/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ ++static const yytype_int8 yyr2[] = + { + 0, 2, 0, 1, 1, 2, 0, 1, 0, 1, + 1, 0, 5, 0, 4, 0, 4, 1, 1, 1, +@@ -651,39 +813,39 @@ static const yytype_uint8 yyr2[] = + }; + + ++enum { YYENOMEM = -2 }; ++ + #define yyerrok (yyerrstatus = 0) + #define yyclearin (yychar = YYEMPTY) +-#define YYEMPTY (-2) +-#define YYEOF 0 + + #define YYACCEPT goto yyacceptlab + #define YYABORT goto yyabortlab + #define YYERROR goto yyerrorlab ++#define YYNOMEM goto yyexhaustedlab + + + #define YYRECOVERING() (!!yyerrstatus) + +-#define YYBACKUP(Token, Value) \ +-do \ +- if (yychar == YYEMPTY) \ +- { \ +- yychar = (Token); \ +- yylval = (Value); \ +- YYPOPSTACK (yylen); \ +- yystate = *yyssp; \ +- goto yybackup; \ +- } \ +- else \ +- { \ +- yyerror (scanner, ctx, scan_ctx, YY_("syntax error: cannot back up")); \ +- YYERROR; \ +- } \ +-while (0) +- +-/* Error token number */ +-#define YYTERROR 1 +-#define YYERRCODE 256 +- ++#define YYBACKUP(Token, Value) \ ++ do \ ++ if (yychar == YYEMPTY) \ ++ { \ ++ yychar = (Token); \ ++ yylval = (Value); \ ++ YYPOPSTACK (yylen); \ ++ yystate = *yyssp; \ ++ goto yybackup; \ ++ } \ ++ else \ ++ { \ ++ yyerror (scanner, ctx, scan_ctx, YY_("syntax error: cannot back up")); \ ++ YYERROR; \ ++ } \ ++ while (0) ++ ++/* Backward compatibility with an undocumented macro. ++ Use YYerror or YYUNDEF. */ ++#define YYERRCODE YYUNDEF + + + /* Enable debugging if requested. */ +@@ -700,58 +862,55 @@ do { \ + YYFPRINTF Args; \ + } while (0) + +-/* This macro is provided for backward compatibility. */ +-#ifndef YY_LOCATION_PRINT +-# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +-#endif + + +-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ ++ ++# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ + do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ +- Type, Value, scanner, ctx, scan_ctx); \ ++ Kind, Value, scanner, ctx, scan_ctx); \ + YYFPRINTF (stderr, "\n"); \ + } \ + } while (0) + + +-/*----------------------------------------. +-| Print this symbol's value on YYOUTPUT. | +-`----------------------------------------*/ ++/*-----------------------------------. ++| Print this symbol's value on YYO. | ++`-----------------------------------*/ + + static void +-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) ++yy_symbol_value_print (FILE *yyo, ++ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) + { +- FILE *yyo = yyoutput; +- YYUSE (yyo); +- YYUSE (scanner); +- YYUSE (ctx); +- YYUSE (scan_ctx); ++ FILE *yyoutput = yyo; ++ YY_USE (yyoutput); ++ YY_USE (scanner); ++ YY_USE (ctx); ++ YY_USE (scan_ctx); + if (!yyvaluep) + return; +-# ifdef YYPRINT +- if (yytype < YYNTOKENS) +- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +-# endif +- YYUSE (yytype); ++ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN ++ YY_USE (yykind); ++ YY_IGNORE_MAYBE_UNINITIALIZED_END + } + + +-/*--------------------------------. +-| Print this symbol on YYOUTPUT. | +-`--------------------------------*/ ++/*---------------------------. ++| Print this symbol on YYO. | ++`---------------------------*/ + + static void +-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) ++yy_symbol_print (FILE *yyo, ++ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) + { +- YYFPRINTF (yyoutput, "%s %s (", +- yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); ++ YYFPRINTF (yyo, "%s %s (", ++ yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); + +- yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx); +- YYFPRINTF (yyoutput, ")"); ++ yy_symbol_value_print (yyo, yykind, yyvaluep, scanner, ctx, scan_ctx); ++ YYFPRINTF (yyo, ")"); + } + + /*------------------------------------------------------------------. +@@ -760,7 +919,7 @@ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, voi + `------------------------------------------------------------------*/ + + static void +-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) ++yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) + { + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) +@@ -783,21 +942,21 @@ do { \ + `------------------------------------------------*/ + + static void +-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) ++yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, ++ int yyrule, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) + { +- unsigned long int yylno = yyrline[yyrule]; ++ int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; +- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", ++ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, +- yystos[yyssp[yyi + 1 - yynrhs]], +- &(yyvsp[(yyi + 1) - (yynrhs)]) +- , scanner, ctx, scan_ctx); ++ YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), ++ &yyvsp[(yyi + 1) - (yynrhs)], scanner, ctx, scan_ctx); + YYFPRINTF (stderr, "\n"); + } + } +@@ -812,8 +971,8 @@ do { \ + multiple parsers can coexist. */ + int yydebug; + #else /* !YYDEBUG */ +-# define YYDPRINTF(Args) +-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) ++# define YYDPRINTF(Args) ((void) 0) ++# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) + # define YY_STACK_PRINT(Bottom, Top) + # define YY_REDUCE_PRINT(Rule) + #endif /* !YYDEBUG */ +@@ -836,253 +995,35 @@ int yydebug; + #endif + + +-#if YYERROR_VERBOSE + +-# ifndef yystrlen +-# if defined __GLIBC__ && defined _STRING_H +-# define yystrlen strlen +-# else +-/* Return the length of YYSTR. */ +-static YYSIZE_T +-yystrlen (const char *yystr) +-{ +- YYSIZE_T yylen; +- for (yylen = 0; yystr[yylen]; yylen++) +- continue; +- return yylen; +-} +-# endif +-# endif +- +-# ifndef yystpcpy +-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +-# define yystpcpy stpcpy +-# else +-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in +- YYDEST. */ +-static char * +-yystpcpy (char *yydest, const char *yysrc) +-{ +- char *yyd = yydest; +- const char *yys = yysrc; +- +- while ((*yyd++ = *yys++) != '\0') +- continue; +- +- return yyd - 1; +-} +-# endif +-# endif +- +-# ifndef yytnamerr +-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary +- quotes and backslashes, so that it's suitable for yyerror. The +- heuristic is that double-quoting is unnecessary unless the string +- contains an apostrophe, a comma, or backslash (other than +- backslash-backslash). YYSTR is taken from yytname. If YYRES is +- null, do not copy; instead, return the length of what the result +- would have been. */ +-static YYSIZE_T +-yytnamerr (char *yyres, const char *yystr) +-{ +- if (*yystr == '"') +- { +- YYSIZE_T yyn = 0; +- char const *yyp = yystr; +- +- for (;;) +- switch (*++yyp) +- { +- case '\'': +- case ',': +- goto do_not_strip_quotes; +- +- case '\\': +- if (*++yyp != '\\') +- goto do_not_strip_quotes; +- /* Fall through. */ +- default: +- if (yyres) +- yyres[yyn] = *yyp; +- yyn++; +- break; +- +- case '"': +- if (yyres) +- yyres[yyn] = '\0'; +- return yyn; +- } +- do_not_strip_quotes: ; +- } + +- if (! yyres) +- return yystrlen (yystr); +- +- return yystpcpy (yyres, yystr) - yyres; +-} +-# endif + +-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message +- about the unexpected token YYTOKEN for the state stack whose top is +- YYSSP. +- +- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is +- not large enough to hold the message. In that case, also set +- *YYMSG_ALLOC to the required number of bytes. Return 2 if the +- required number of bytes is too large to store. */ +-static int +-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, +- yytype_int16 *yyssp, int yytoken) +-{ +- YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); +- YYSIZE_T yysize = yysize0; +- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; +- /* Internationalized format string. */ +- const char *yyformat = YY_NULLPTR; +- /* Arguments of yyformat. */ +- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; +- /* Number of reported tokens (one for the "unexpected", one per +- "expected"). */ +- int yycount = 0; +- +- /* There are many possibilities here to consider: +- - If this state is a consistent state with a default action, then +- the only way this function was invoked is if the default action +- is an error action. In that case, don't check for expected +- tokens because there are none. +- - The only way there can be no lookahead present (in yychar) is if +- this state is a consistent state with a default action. Thus, +- detecting the absence of a lookahead is sufficient to determine +- that there is no unexpected or expected token to report. In that +- case, just report a simple "syntax error". +- - Don't assume there isn't a lookahead just because this state is a +- consistent state with a default action. There might have been a +- previous inconsistent state, consistent state with a non-default +- action, or user semantic action that manipulated yychar. +- - Of course, the expected token list depends on states to have +- correct lookahead information, and it depends on the parser not +- to perform extra reductions after fetching a lookahead from the +- scanner and before detecting a syntax error. Thus, state merging +- (from LALR or IELR) and default reductions corrupt the expected +- token list. However, the list is correct for canonical LR with +- one exception: it will still contain any token that will not be +- accepted due to an error action in a later state. +- */ +- if (yytoken != YYEMPTY) +- { +- int yyn = yypact[*yyssp]; +- yyarg[yycount++] = yytname[yytoken]; +- if (!yypact_value_is_default (yyn)) +- { +- /* Start YYX at -YYN if negative to avoid negative indexes in +- YYCHECK. In other words, skip the first -YYN actions for +- this state because they are default actions. */ +- int yyxbegin = yyn < 0 ? -yyn : 0; +- /* Stay within bounds of both yycheck and yytname. */ +- int yychecklim = YYLAST - yyn + 1; +- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; +- int yyx; +- +- for (yyx = yyxbegin; yyx < yyxend; ++yyx) +- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR +- && !yytable_value_is_error (yytable[yyx + yyn])) +- { +- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) +- { +- yycount = 1; +- yysize = yysize0; +- break; +- } +- yyarg[yycount++] = yytname[yyx]; +- { +- YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); +- if (! (yysize <= yysize1 +- && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) +- return 2; +- yysize = yysize1; +- } +- } +- } +- } +- +- switch (yycount) +- { +-# define YYCASE_(N, S) \ +- case N: \ +- yyformat = S; \ +- break +- YYCASE_(0, YY_("syntax error")); +- YYCASE_(1, YY_("syntax error, unexpected %s")); +- YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); +- YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); +- YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); +- YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +-# undef YYCASE_ +- } +- +- { +- YYSIZE_T yysize1 = yysize + yystrlen (yyformat); +- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) +- return 2; +- yysize = yysize1; +- } +- +- if (*yymsg_alloc < yysize) +- { +- *yymsg_alloc = 2 * yysize; +- if (! (yysize <= *yymsg_alloc +- && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) +- *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; +- return 1; +- } +- +- /* Avoid sprintf, as that infringes on the user's name space. +- Don't have undefined behavior even if the translation +- produced a string with the wrong number of "%s"s. */ +- { +- char *yyp = *yymsg; +- int yyi = 0; +- while ((*yyp = *yyformat) != '\0') +- if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) +- { +- yyp += yytnamerr (yyp, yyarg[yyi++]); +- yyformat += 2; +- } +- else +- { +- yyp++; +- yyformat++; +- } +- } +- return 0; +-} +-#endif /* YYERROR_VERBOSE */ + + /*-----------------------------------------------. + | Release the memory associated to this symbol. | + `-----------------------------------------------*/ + + static void +-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) ++yydestruct (const char *yymsg, ++ yysymbol_kind_t yykind, YYSTYPE *yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) + { +- YYUSE (yyvaluep); +- YYUSE (scanner); +- YYUSE (ctx); +- YYUSE (scan_ctx); ++ YY_USE (yyvaluep); ++ YY_USE (scanner); ++ YY_USE (ctx); ++ YY_USE (scan_ctx); + if (!yymsg) + yymsg = "Deleting"; +- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); ++ YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +- switch (yytype) ++ switch (yykind) + { +- case 9: /* TOK_STRING */ +-#line 88 "grammar.y" /* yacc.c:1257 */ +- { free(((*yyvaluep).sval)); } +-#line 1083 "grammar.c" /* yacc.c:1257 */ ++ case YYSYMBOL_TOK_STRING: /* TOK_STRING */ ++#line 90 "grammar.y" ++ { free(((*yyvaluep).sval)); } ++#line 1025 "grammar.c" + break; + +- + default: + break; + } +@@ -1092,6 +1033,8 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *scanner, str + + + ++ ++ + /*----------. + | yyparse. | + `----------*/ +@@ -1099,7 +1042,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *scanner, str + int + yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) + { +-/* The lookahead symbol. */ ++/* Lookahead token kind. */ + int yychar; + + +@@ -1110,45 +1053,38 @@ YY_INITIAL_VALUE (static YYSTYPE yyval_default;) + YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + + /* Number of syntax errors so far. */ +- int yynerrs; ++ int yynerrs = 0; + +- int yystate; ++ yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ +- int yyerrstatus; +- +- /* The stacks and their tools: +- 'yyss': related to states. +- 'yyvs': related to semantic values. ++ int yyerrstatus = 0; + +- Refer to the stacks through separate pointers, to allow yyoverflow ++ /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + +- /* The state stack. */ +- yytype_int16 yyssa[YYINITDEPTH]; +- yytype_int16 *yyss; +- yytype_int16 *yyssp; ++ /* Their size. */ ++ YYPTRDIFF_T yystacksize = YYINITDEPTH; + +- /* The semantic value stack. */ +- YYSTYPE yyvsa[YYINITDEPTH]; +- YYSTYPE *yyvs; +- YYSTYPE *yyvsp; ++ /* The state stack: array, bottom, top. */ ++ yy_state_t yyssa[YYINITDEPTH]; ++ yy_state_t *yyss = yyssa; ++ yy_state_t *yyssp = yyss; + +- YYSIZE_T yystacksize; ++ /* The semantic value stack: array, bottom, top. */ ++ YYSTYPE yyvsa[YYINITDEPTH]; ++ YYSTYPE *yyvs = yyvsa; ++ YYSTYPE *yyvsp = yyvs; + + int yyn; ++ /* The return value of yyparse. */ + int yyresult; +- /* Lookahead token as an internal (translated) token number. */ +- int yytoken = 0; ++ /* Lookahead symbol kind. */ ++ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +-#if YYERROR_VERBOSE +- /* Buffer for error messages, and its allocated size. */ +- char yymsgbuf[128]; +- char *yymsg = yymsgbuf; +- YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +-#endif ++ + + #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + +@@ -1156,71 +1092,75 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + Keep to zero when no symbol should be popped. */ + int yylen = 0; + +- yyssp = yyss = yyssa; +- yyvsp = yyvs = yyvsa; +- yystacksize = YYINITDEPTH; +- + YYDPRINTF ((stderr, "Starting parse\n")); + +- yystate = 0; +- yyerrstatus = 0; +- yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ ++ + goto yysetstate; + ++ + /*------------------------------------------------------------. +-| yynewstate -- Push a new state, which is found in yystate. | ++| yynewstate -- push a new state, which is found in yystate. | + `------------------------------------------------------------*/ +- yynewstate: ++yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + +- yysetstate: +- *yyssp = yystate; ++ ++/*--------------------------------------------------------------------. ++| yysetstate -- set current state (the top of the stack) to yystate. | ++`--------------------------------------------------------------------*/ ++yysetstate: ++ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); ++ YY_ASSERT (0 <= yystate && yystate < YYNSTATES); ++ YY_IGNORE_USELESS_CAST_BEGIN ++ *yyssp = YY_CAST (yy_state_t, yystate); ++ YY_IGNORE_USELESS_CAST_END ++ YY_STACK_PRINT (yyss, yyssp); + + if (yyss + yystacksize - 1 <= yyssp) ++#if !defined yyoverflow && !defined YYSTACK_RELOCATE ++ YYNOMEM; ++#else + { + /* Get the current used size of the three stacks, in elements. */ +- YYSIZE_T yysize = yyssp - yyss + 1; ++ YYPTRDIFF_T yysize = yyssp - yyss + 1; + +-#ifdef yyoverflow ++# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ ++ yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; +- yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), +- &yyss1, yysize * sizeof (*yyssp), +- &yyvs1, yysize * sizeof (*yyvsp), ++ &yyss1, yysize * YYSIZEOF (*yyssp), ++ &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); +- + yyss = yyss1; + yyvs = yyvs1; + } +-#else /* no yyoverflow */ +-# ifndef YYSTACK_RELOCATE +- goto yyexhaustedlab; +-# else ++# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) +- goto yyexhaustedlab; ++ YYNOMEM; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { +- yytype_int16 *yyss1 = yyss; ++ yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = +- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); ++ YY_CAST (union yyalloc *, ++ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) +- goto yyexhaustedlab; ++ YYNOMEM; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + # undef YYSTACK_RELOCATE +@@ -1228,30 +1168,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + YYSTACK_FREE (yyss1); + } + # endif +-#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + +- YYDPRINTF ((stderr, "Stack size increased to %lu\n", +- (unsigned long int) yystacksize)); ++ YY_IGNORE_USELESS_CAST_BEGIN ++ YYDPRINTF ((stderr, "Stack size increased to %ld\n", ++ YY_CAST (long, yystacksize))); ++ YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } ++#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + +- YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + ++ + /*-----------. + | yybackup. | + `-----------*/ + yybackup: +- + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + +@@ -1262,18 +1203,29 @@ yybackup: + + /* Not known => get a lookahead token if don't already have one. */ + +- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ ++ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { +- YYDPRINTF ((stderr, "Reading a token: ")); ++ YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (&yylval, scanner); + } + + if (yychar <= YYEOF) + { +- yychar = yytoken = YYEOF; ++ yychar = YYEOF; ++ yytoken = YYSYMBOL_YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } ++ else if (yychar == YYerror) ++ { ++ /* The scanner already issued an error message, process directly ++ to error recovery. But do not keep the error token as ++ lookahead, it is too special and may lead us to an endless ++ loop in error recovery. */ ++ yychar = YYUNDEF; ++ yytoken = YYSYMBOL_YYerror; ++ goto yyerrlab1; ++ } + else + { + yytoken = YYTRANSLATE (yychar); +@@ -1301,15 +1253,13 @@ yybackup: + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); +- +- /* Discard the shifted token. */ +- yychar = YYEMPTY; +- + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + ++ /* Discard the shifted token. */ ++ yychar = YYEMPTY; + goto yynewstate; + + +@@ -1324,7 +1274,7 @@ yydefault: + + + /*-----------------------------. +-| yyreduce -- Do a reduction. | ++| yyreduce -- do a reduction. | + `-----------------------------*/ + yyreduce: + /* yyn is the number of a rule to reduce with. */ +@@ -1344,9 +1294,9 @@ yyreduce: + YY_REDUCE_PRINT (yyn); + switch (yyn) + { +- case 11: +-#line 115 "grammar.y" /* yacc.c:1646 */ +- { ++ case 11: /* $@1: %empty */ ++#line 117 "grammar.y" ++ { + ctx->setting = config_setting_add(ctx->parent, (yyvsp[0].sval), CONFIG_TYPE_NONE); + + if(ctx->setting == NULL) +@@ -1359,12 +1309,12 @@ yyreduce: + CAPTURE_PARSE_POS(ctx->setting); + } + } +-#line 1363 "grammar.c" /* yacc.c:1646 */ ++#line 1313 "grammar.c" + break; + +- case 13: +-#line 134 "grammar.y" /* yacc.c:1646 */ +- { ++ case 13: /* $@2: %empty */ ++#line 136 "grammar.y" ++ { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_ARRAY); +@@ -1377,21 +1327,21 @@ yyreduce: + ctx->setting = NULL; + } + } +-#line 1381 "grammar.c" /* yacc.c:1646 */ ++#line 1331 "grammar.c" + break; + +- case 14: +-#line 149 "grammar.y" /* yacc.c:1646 */ +- { ++ case 14: /* array: TOK_ARRAY_START $@2 simple_value_list_optional TOK_ARRAY_END */ ++#line 151 "grammar.y" ++ { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } +-#line 1390 "grammar.c" /* yacc.c:1646 */ ++#line 1340 "grammar.c" + break; + +- case 15: +-#line 157 "grammar.y" /* yacc.c:1646 */ +- { ++ case 15: /* $@3: %empty */ ++#line 159 "grammar.y" ++ { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_LIST); +@@ -1404,33 +1354,33 @@ yyreduce: + ctx->setting = NULL; + } + } +-#line 1408 "grammar.c" /* yacc.c:1646 */ ++#line 1358 "grammar.c" + break; + +- case 16: +-#line 172 "grammar.y" /* yacc.c:1646 */ +- { ++ case 16: /* list: TOK_LIST_START $@3 value_list_optional TOK_LIST_END */ ++#line 174 "grammar.y" ++ { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } +-#line 1417 "grammar.c" /* yacc.c:1646 */ ++#line 1367 "grammar.c" + break; + +- case 21: +-#line 186 "grammar.y" /* yacc.c:1646 */ +- { libconfig_parsectx_append_string(ctx, (yyvsp[0].sval)); free((yyvsp[0].sval)); } +-#line 1423 "grammar.c" /* yacc.c:1646 */ ++ case 21: /* string: TOK_STRING */ ++#line 188 "grammar.y" ++ { libconfig_parsectx_append_string(ctx, (yyvsp[0].sval)); free((yyvsp[0].sval)); } ++#line 1373 "grammar.c" + break; + +- case 22: +-#line 187 "grammar.y" /* yacc.c:1646 */ +- { libconfig_parsectx_append_string(ctx, (yyvsp[0].sval)); free((yyvsp[0].sval)); } +-#line 1429 "grammar.c" /* yacc.c:1646 */ ++ case 22: /* string: string TOK_STRING */ ++#line 189 "grammar.y" ++ { libconfig_parsectx_append_string(ctx, (yyvsp[0].sval)); free((yyvsp[0].sval)); } ++#line 1379 "grammar.c" + break; + +- case 23: +-#line 192 "grammar.y" /* yacc.c:1646 */ +- { ++ case 23: /* simple_value: TOK_BOOLEAN */ ++#line 194 "grammar.y" ++ { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_bool_elem(ctx->parent, -1, +@@ -1449,12 +1399,12 @@ yyreduce: + else + config_setting_set_bool(ctx->setting, (int)(yyvsp[0].ival)); + } +-#line 1453 "grammar.c" /* yacc.c:1646 */ ++#line 1403 "grammar.c" + break; + +- case 24: +-#line 212 "grammar.y" /* yacc.c:1646 */ +- { ++ case 24: /* simple_value: TOK_INTEGER */ ++#line 214 "grammar.y" ++ { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[0].ival)); +@@ -1475,12 +1425,12 @@ yyreduce: + config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT); + } + } +-#line 1479 "grammar.c" /* yacc.c:1646 */ ++#line 1429 "grammar.c" + break; + +- case 25: +-#line 234 "grammar.y" /* yacc.c:1646 */ +- { ++ case 25: /* simple_value: TOK_INTEGER64 */ ++#line 236 "grammar.y" ++ { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[0].llval)); +@@ -1501,12 +1451,12 @@ yyreduce: + config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT); + } + } +-#line 1505 "grammar.c" /* yacc.c:1646 */ ++#line 1455 "grammar.c" + break; + +- case 26: +-#line 256 "grammar.y" /* yacc.c:1646 */ +- { ++ case 26: /* simple_value: TOK_HEX */ ++#line 258 "grammar.y" ++ { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[0].ival)); +@@ -1527,12 +1477,12 @@ yyreduce: + config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX); + } + } +-#line 1531 "grammar.c" /* yacc.c:1646 */ ++#line 1481 "grammar.c" + break; + +- case 27: +-#line 278 "grammar.y" /* yacc.c:1646 */ +- { ++ case 27: /* simple_value: TOK_HEX64 */ ++#line 280 "grammar.y" ++ { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[0].llval)); +@@ -1553,12 +1503,12 @@ yyreduce: + config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX); + } + } +-#line 1557 "grammar.c" /* yacc.c:1646 */ ++#line 1507 "grammar.c" + break; + +- case 28: +-#line 300 "grammar.y" /* yacc.c:1646 */ +- { ++ case 28: /* simple_value: TOK_FLOAT */ ++#line 302 "grammar.y" ++ { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_float_elem(ctx->parent, -1, (yyvsp[0].fval)); +@@ -1575,12 +1525,12 @@ yyreduce: + else + config_setting_set_float(ctx->setting, (yyvsp[0].fval)); + } +-#line 1579 "grammar.c" /* yacc.c:1646 */ ++#line 1529 "grammar.c" + break; + +- case 29: +-#line 318 "grammar.y" /* yacc.c:1646 */ +- { ++ case 29: /* simple_value: string */ ++#line 320 "grammar.y" ++ { + if(IN_ARRAY() || IN_LIST()) + { + const char *s = libconfig_parsectx_take_string(ctx); +@@ -1604,12 +1554,12 @@ yyreduce: + __delete(s); + } + } +-#line 1608 "grammar.c" /* yacc.c:1646 */ ++#line 1558 "grammar.c" + break; + +- case 40: +-#line 368 "grammar.y" /* yacc.c:1646 */ +- { ++ case 40: /* $@4: %empty */ ++#line 370 "grammar.y" ++ { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_GROUP); +@@ -1622,20 +1572,21 @@ yyreduce: + ctx->setting = NULL; + } + } +-#line 1626 "grammar.c" /* yacc.c:1646 */ ++#line 1576 "grammar.c" + break; + +- case 41: +-#line 383 "grammar.y" /* yacc.c:1646 */ +- { ++ case 41: /* group: TOK_GROUP_START $@4 setting_list_optional TOK_GROUP_END */ ++#line 385 "grammar.y" ++ { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } +-#line 1635 "grammar.c" /* yacc.c:1646 */ ++#line 1585 "grammar.c" + break; + + +-#line 1639 "grammar.c" /* yacc.c:1646 */ ++#line 1589 "grammar.c" ++ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires +@@ -1649,25 +1600,23 @@ yyreduce: + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ +- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); ++ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; +- YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ +- +- yyn = yyr1[yyn]; +- +- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; +- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) +- yystate = yytable[yystate]; +- else +- yystate = yydefgoto[yyn - YYNTOKENS]; ++ { ++ const int yylhs = yyr1[yyn] - YYNTOKENS; ++ const int yyi = yypgoto[yylhs] + *yyssp; ++ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp ++ ? yytable[yyi] ++ : yydefgoto[yylhs]); ++ } + + goto yynewstate; + +@@ -1678,50 +1627,14 @@ yyreduce: + yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ +- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); +- ++ yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +-#if ! YYERROR_VERBOSE + yyerror (scanner, ctx, scan_ctx, YY_("syntax error")); +-#else +-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ +- yyssp, yytoken) +- { +- char const *yymsgp = YY_("syntax error"); +- int yysyntax_error_status; +- yysyntax_error_status = YYSYNTAX_ERROR; +- if (yysyntax_error_status == 0) +- yymsgp = yymsg; +- else if (yysyntax_error_status == 1) +- { +- if (yymsg != yymsgbuf) +- YYSTACK_FREE (yymsg); +- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); +- if (!yymsg) +- { +- yymsg = yymsgbuf; +- yymsg_alloc = sizeof yymsgbuf; +- yysyntax_error_status = 2; +- } +- else +- { +- yysyntax_error_status = YYSYNTAX_ERROR; +- yymsgp = yymsg; +- } +- } +- yyerror (scanner, ctx, scan_ctx, yymsgp); +- if (yysyntax_error_status == 2) +- goto yyexhaustedlab; +- } +-# undef YYSYNTAX_ERROR +-#endif + } + +- +- + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an +@@ -1750,12 +1663,11 @@ yyerrlab: + | yyerrorlab -- error raised explicitly by YYERROR. | + `---------------------------------------------------*/ + yyerrorlab: +- +- /* Pacify compilers like GCC when the user code never invokes +- YYERROR and the label yyerrorlab therefore never appears in user +- code. */ +- if (/*CONSTCOND*/ 0) +- goto yyerrorlab; ++ /* Pacify compilers when the user code never invokes YYERROR and the ++ label yyerrorlab therefore never appears in user code. */ ++ if (0) ++ YYERROR; ++ ++yynerrs; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ +@@ -1772,13 +1684,14 @@ yyerrorlab: + yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + ++ /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { +- yyn += YYTERROR; +- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) ++ yyn += YYSYMBOL_YYerror; ++ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) +@@ -1792,7 +1705,7 @@ yyerrlab1: + + + yydestruct ("Error: popping", +- yystos[yystate], yyvsp, scanner, ctx, scan_ctx); ++ YY_ACCESSING_SYMBOL (yystate), yyvsp, scanner, ctx, scan_ctx); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); +@@ -1804,7 +1717,7 @@ yyerrlab1: + + + /* Shift the error token. */ +- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); ++ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; +@@ -1815,26 +1728,30 @@ yyerrlab1: + `-------------------------------------*/ + yyacceptlab: + yyresult = 0; +- goto yyreturn; ++ goto yyreturnlab; ++ + + /*-----------------------------------. + | yyabortlab -- YYABORT comes here. | + `-----------------------------------*/ + yyabortlab: + yyresult = 1; +- goto yyreturn; ++ goto yyreturnlab; ++ + +-#if !defined yyoverflow || YYERROR_VERBOSE +-/*-------------------------------------------------. +-| yyexhaustedlab -- memory exhaustion comes here. | +-`-------------------------------------------------*/ ++/*-----------------------------------------------------------. ++| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | ++`-----------------------------------------------------------*/ + yyexhaustedlab: + yyerror (scanner, ctx, scan_ctx, YY_("memory exhausted")); + yyresult = 2; +- /* Fall through. */ +-#endif ++ goto yyreturnlab; ++ + +-yyreturn: ++/*----------------------------------------------------------. ++| yyreturnlab -- parsing is finished, clean up and return. | ++`----------------------------------------------------------*/ ++yyreturnlab: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at +@@ -1850,18 +1767,16 @@ yyreturn: + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", +- yystos[*yyssp], yyvsp, scanner, ctx, scan_ctx); ++ YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, scanner, ctx, scan_ctx); + YYPOPSTACK (1); + } + #ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); + #endif +-#if YYERROR_VERBOSE +- if (yymsg != yymsgbuf) +- YYSTACK_FREE (yymsg); +-#endif ++ + return yyresult; + } +-#line 389 "grammar.y" /* yacc.c:1906 */ ++ ++#line 391 "grammar.y" + +diff --git a/lib/grammar.h b/lib/grammar.h +index 9b746df..84fa1c9 100644 +--- a/lib/grammar.h ++++ b/lib/grammar.h +@@ -1,8 +1,9 @@ +-/* A Bison parser, made by GNU Bison 3.0.4. */ ++/* A Bison parser, made by GNU Bison 3.8. */ + + /* Bison interface for Yacc-like parsers in C + +- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. ++ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, ++ Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -15,7 +16,7 @@ + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +- along with this program. If not, see . */ ++ along with this program. If not, see . */ + + /* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work +@@ -30,6 +31,10 @@ + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + ++/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, ++ especially those whose name start with YY_ or yy_. They are ++ private implementation details that can be changed or removed. */ ++ + #ifndef YY_LIBCONFIG_YY_GRAMMAR_H_INCLUDED + # define YY_LIBCONFIG_YY_GRAMMAR_H_INCLUDED + /* Debug traces. */ +@@ -40,34 +45,43 @@ + extern int libconfig_yydebug; + #endif + +-/* Token type. */ ++/* Token kinds. */ + #ifndef YYTOKENTYPE + # define YYTOKENTYPE + enum yytokentype + { +- TOK_BOOLEAN = 258, +- TOK_INTEGER = 259, +- TOK_HEX = 260, +- TOK_INTEGER64 = 261, +- TOK_HEX64 = 262, +- TOK_FLOAT = 263, +- TOK_STRING = 264, +- TOK_NAME = 265, +- TOK_EQUALS = 266, +- TOK_NEWLINE = 267, +- TOK_ARRAY_START = 268, +- TOK_ARRAY_END = 269, +- TOK_LIST_START = 270, +- TOK_LIST_END = 271, +- TOK_COMMA = 272, +- TOK_GROUP_START = 273, +- TOK_GROUP_END = 274, +- TOK_SEMICOLON = 275, +- TOK_GARBAGE = 276, +- TOK_ERROR = 277 ++ YYEMPTY = -2, ++ YYEOF = 0, /* "end of file" */ ++ YYerror = 256, /* error */ ++ YYUNDEF = 257, /* "invalid token" */ ++ TOK_BOOLEAN = 258, /* TOK_BOOLEAN */ ++ TOK_INTEGER = 259, /* TOK_INTEGER */ ++ TOK_HEX = 260, /* TOK_HEX */ ++ TOK_INTEGER64 = 261, /* TOK_INTEGER64 */ ++ TOK_HEX64 = 262, /* TOK_HEX64 */ ++ TOK_FLOAT = 263, /* TOK_FLOAT */ ++ TOK_STRING = 264, /* TOK_STRING */ ++ TOK_NAME = 265, /* TOK_NAME */ ++ TOK_EQUALS = 266, /* TOK_EQUALS */ ++ TOK_NEWLINE = 267, /* TOK_NEWLINE */ ++ TOK_ARRAY_START = 268, /* TOK_ARRAY_START */ ++ TOK_ARRAY_END = 269, /* TOK_ARRAY_END */ ++ TOK_LIST_START = 270, /* TOK_LIST_START */ ++ TOK_LIST_END = 271, /* TOK_LIST_END */ ++ TOK_COMMA = 272, /* TOK_COMMA */ ++ TOK_GROUP_START = 273, /* TOK_GROUP_START */ ++ TOK_GROUP_END = 274, /* TOK_GROUP_END */ ++ TOK_SEMICOLON = 275, /* TOK_SEMICOLON */ ++ TOK_GARBAGE = 276, /* TOK_GARBAGE */ ++ TOK_ERROR = 277 /* TOK_ERROR */ + }; ++ typedef enum yytokentype yytoken_kind_t; + #endif +-/* Tokens. */ ++/* Token kinds. */ ++#define YYEMPTY -2 ++#define YYEOF 0 ++#define YYerror 256 ++#define YYUNDEF 257 + #define TOK_BOOLEAN 258 + #define TOK_INTEGER 259 + #define TOK_HEX 260 +@@ -91,19 +105,18 @@ extern int libconfig_yydebug; + + /* Value type. */ + #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +- + union YYSTYPE + { +-#line 76 "grammar.y" /* yacc.c:1909 */ ++#line 78 "grammar.y" + + int ival; + long long llval; + double fval; + char *sval; + +-#line 105 "grammar.h" /* yacc.c:1909 */ +-}; ++#line 118 "grammar.h" + ++}; + typedef union YYSTYPE YYSTYPE; + # define YYSTYPE_IS_TRIVIAL 1 + # define YYSTYPE_IS_DECLARED 1 +@@ -111,6 +124,14 @@ typedef union YYSTYPE YYSTYPE; + + + ++#if !defined libconfig_yyerror && !defined YYERROR_IS_DECLARED ++void libconfig_yyerror (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx, const char *msg); ++#endif ++#if !defined libconfig_yylex && !defined YYLEX_IS_DECLARED ++int libconfig_yylex (YYSTYPE *yylvalp, void *scanner); ++#endif ++ + int libconfig_yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx); + ++ + #endif /* !YY_LIBCONFIG_YY_GRAMMAR_H_INCLUDED */ +diff --git a/lib/grammar.y b/lib/grammar.y +index 87dac00..f614fa7 100644 +--- a/lib/grammar.y ++++ b/lib/grammar.y +@@ -1,7 +1,7 @@ + /* -*- mode: C -*- */ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -43,6 +43,8 @@ + extern int libconfig_yylex(); + extern int libconfig_yyget_lineno(); + ++#define YYMALLOC libconfig_malloc ++ + static const char *err_array_elem_type = "mismatched element type in array"; + static const char *err_duplicate_setting = "duplicate setting name"; + +diff --git a/lib/libconfig.c b/lib/libconfig.c +index 2f3cbfa..1a935be 100644 +--- a/lib/libconfig.c ++++ b/lib/libconfig.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -374,7 +374,7 @@ static void __config_list_add(config_list_t *list, config_setting_t *setting) + { + if((list->length % CHUNK_SIZE) == 0) + { +- list->elements = (config_setting_t **)realloc( ++ list->elements = (config_setting_t **)libconfig_realloc( + list->elements, + (list->length + CHUNK_SIZE) * sizeof(config_setting_t *)); + } +@@ -392,7 +392,7 @@ static config_setting_t *__config_list_search(config_list_t *list, + config_setting_t **found = NULL; + unsigned int i; + +- if(! list) ++ if(! list || ! name) + return(NULL); + + for(i = 0, found = list->elements; i < list->length; i++, found++) +@@ -825,6 +825,12 @@ void config_set_hook(config_t *config, void *hook) + + /* ------------------------------------------------------------------------- */ + ++void config_set_fatal_error_func(config_fatal_error_fn_t func) { ++ libconfig_set_fatal_error_func(func); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ + static config_setting_t *config_setting_create(config_setting_t *parent, + const char *name, int type) + { +@@ -1741,7 +1747,7 @@ const char **config_default_include_func(config_t *config, + + if(include_dir && IS_RELATIVE_PATH(path)) + { +- file = (char *)malloc(strlen(include_dir) + strlen(path) + 2); ++ file = (char *)libconfig_malloc(strlen(include_dir) + strlen(path) + 2); + strcpy(file, include_dir); + strcat(file, FILE_SEPARATOR); + strcat(file, path); +@@ -1751,7 +1757,7 @@ const char **config_default_include_func(config_t *config, + + *error = NULL; + +- files = (const char **)malloc(sizeof(char **) * 2); ++ files = (const char **)libconfig_malloc(sizeof(char **) * 2); + files[0] = file; + files[1] = NULL; + +diff --git a/lib/libconfig.h b/lib/libconfig.h +index 5e4eea3..411ac13 100644 +--- a/lib/libconfig.h ++++ b/lib/libconfig.h +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -110,6 +110,8 @@ typedef const char ** (*config_include_fn_t)(struct config_t *, + const char *, + const char **); + ++typedef void (*config_fatal_error_fn_t)(const char *); ++ + typedef struct config_t + { + config_setting_t *root; +@@ -173,6 +175,9 @@ extern LIBCONFIG_API void config_init(config_t *config); + extern LIBCONFIG_API void config_destroy(config_t *config); + extern LIBCONFIG_API void config_clear(config_t *config); + ++extern LIBCONFIG_API void config_set_fatal_error_func( ++ config_fatal_error_fn_t func); ++ + extern LIBCONFIG_API int config_setting_get_int( + const config_setting_t *setting); + extern LIBCONFIG_API long long config_setting_get_int64( +diff --git a/lib/libconfig.h++ b/lib/libconfig.h++ +index 18578fa..c16e97b 100644 +--- a/lib/libconfig.h++ ++++ b/lib/libconfig.h++ +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/libconfig.hh b/lib/libconfig.hh +index a3257d0..6ba0893 100644 +--- a/lib/libconfig.hh ++++ b/lib/libconfig.hh +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A structured configuration file parsing library +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/libconfigcpp.c++ b/lib/libconfigcpp.c++ +index 9cdee4d..b269685 100644 +--- a/lib/libconfigcpp.c++ ++++ b/lib/libconfigcpp.c++ +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -48,6 +48,15 @@ static const char **__include_func(config_t *config, + + // --------------------------------------------------------------------------- + ++static void __fatal_error_func(const char *message) ++{ ++ // Assume memory allocation failure; this is the only fatal error ++ // condition currently defined. ++ throw std::bad_alloc(); ++} ++ ++// --------------------------------------------------------------------------- ++ + ParseException::ParseException(const char *file, int line, const char *error) + : _file(file ? ::strdup(file) : NULL), _line(line), _error(error) + { +@@ -321,6 +330,7 @@ Config::Config() + config_set_hook(_config, reinterpret_cast(this)); + config_set_destructor(_config, ConfigDestructor); + config_set_include_func(_config, __include_func); ++ config_set_fatal_error_func(__fatal_error_func); + } + + // --------------------------------------------------------------------------- +diff --git a/lib/libconfigcpp.cc b/lib/libconfigcpp.cc +index cab4f64..b5ce1c3 100644 +--- a/lib/libconfigcpp.cc ++++ b/lib/libconfigcpp.cc +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A structured configuration file parsing library +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/parsectx.h b/lib/parsectx.h +index 02ce511..854278f 100644 +--- a/lib/parsectx.h ++++ b/lib/parsectx.h +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/scanctx.c b/lib/scanctx.c +index 02130ab..cc7d8ac 100644 +--- a/lib/scanctx.c ++++ b/lib/scanctx.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/scanctx.h b/lib/scanctx.h +index 3c5c374..cd8b6be 100644 +--- a/lib/scanctx.h ++++ b/lib/scanctx.h +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/scanner.c b/lib/scanner.c +index df1aed9..87c98da 100644 +--- a/lib/scanner.c ++++ b/lib/scanner.c +@@ -556,6 +556,8 @@ void yyfree ( void * , yyscan_t yyscanner ); + } + #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + ++/* Begin user sect3 */ ++ + #define libconfig_yywrap(yyscanner) (/*CONSTCOND*/1) + #define YY_SKIP_YYWRAP + typedef flex_uint8_t YY_CHAR; +@@ -760,7 +762,7 @@ static const flex_int32_t yy_rule_can_match_eol[45] = + /* -*- mode: C -*- */ + /* -------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -780,7 +782,7 @@ static const flex_int32_t yy_rule_can_match_eol[45] = + ---------------------------------------------------------------------------- + */ + #define YY_NO_UNISTD_H 1 +-#line 36 "scanner.l" ++#line 37 "scanner.l" + + #ifdef _MSC_VER + #pragma warning (disable: 4996) +@@ -800,10 +802,10 @@ static const flex_int32_t yy_rule_can_match_eol[45] = + + #define YY_NO_INPUT // Suppress generation of useless input() function + +-#line 803 "scanner.c" +- + #line 805 "scanner.c" + ++#line 807 "scanner.c" ++ + #define INITIAL 0 + #define SINGLE_LINE_COMMENT 1 + #define MULTI_LINE_COMMENT 2 +@@ -1079,10 +1081,10 @@ YY_DECL + } + + { +-#line 70 "scanner.l" ++#line 71 "scanner.l" + + +-#line 1085 "scanner.c" ++#line 1087 "scanner.c" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { +@@ -1150,85 +1152,85 @@ do_action: /* This label is used only to access EOF actions. */ + + case 1: + YY_RULE_SETUP +-#line 72 "scanner.l" ++#line 73 "scanner.l" + { BEGIN SINGLE_LINE_COMMENT; } + YY_BREAK + case 2: + /* rule 2 can match eol */ + YY_RULE_SETUP +-#line 73 "scanner.l" ++#line 74 "scanner.l" + { BEGIN INITIAL; } + YY_BREAK + case 3: + YY_RULE_SETUP +-#line 74 "scanner.l" ++#line 75 "scanner.l" + { /* ignore */ } + YY_BREAK + case 4: + YY_RULE_SETUP +-#line 76 "scanner.l" ++#line 77 "scanner.l" + { BEGIN MULTI_LINE_COMMENT; } + YY_BREAK + case 5: + YY_RULE_SETUP +-#line 77 "scanner.l" ++#line 78 "scanner.l" + { BEGIN INITIAL; } + YY_BREAK + case 6: + YY_RULE_SETUP +-#line 78 "scanner.l" ++#line 79 "scanner.l" + { /* ignore */ } + YY_BREAK + case 7: + /* rule 7 can match eol */ + YY_RULE_SETUP +-#line 79 "scanner.l" ++#line 80 "scanner.l" + { /* ignore */ } + YY_BREAK + case 8: + YY_RULE_SETUP +-#line 81 "scanner.l" ++#line 82 "scanner.l" + { BEGIN STRING; } + YY_BREAK + case 9: + /* rule 9 can match eol */ + YY_RULE_SETUP +-#line 82 "scanner.l" ++#line 83 "scanner.l" + { libconfig_scanctx_append_string(yyextra, yytext); } + YY_BREAK + case 10: + YY_RULE_SETUP +-#line 83 "scanner.l" ++#line 84 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\n'); } + YY_BREAK + case 11: + YY_RULE_SETUP +-#line 84 "scanner.l" ++#line 85 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\r'); } + YY_BREAK + case 12: + YY_RULE_SETUP +-#line 85 "scanner.l" ++#line 86 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\t'); } + YY_BREAK + case 13: + YY_RULE_SETUP +-#line 86 "scanner.l" ++#line 87 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\f'); } + YY_BREAK + case 14: + YY_RULE_SETUP +-#line 87 "scanner.l" ++#line 88 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\\'); } + YY_BREAK + case 15: + YY_RULE_SETUP +-#line 88 "scanner.l" ++#line 89 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\"'); } + YY_BREAK + case 16: + YY_RULE_SETUP +-#line 89 "scanner.l" ++#line 90 "scanner.l" + { + char c = (char)(strtol(yytext + 2, NULL, 16) & 0xFF); + libconfig_scanctx_append_char(yyextra, c); +@@ -1236,12 +1238,12 @@ YY_RULE_SETUP + YY_BREAK + case 17: + YY_RULE_SETUP +-#line 93 "scanner.l" ++#line 94 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\\'); } + YY_BREAK + case 18: + YY_RULE_SETUP +-#line 94 "scanner.l" ++#line 95 "scanner.l" + { + yylval->sval = libconfig_scanctx_take_string(yyextra); + BEGIN INITIAL; +@@ -1250,28 +1252,28 @@ YY_RULE_SETUP + YY_BREAK + case 19: + YY_RULE_SETUP +-#line 100 "scanner.l" ++#line 101 "scanner.l" + { BEGIN INCLUDE; } + YY_BREAK + case 20: + /* rule 20 can match eol */ + YY_RULE_SETUP +-#line 101 "scanner.l" ++#line 102 "scanner.l" + { libconfig_scanctx_append_string(yyextra, yytext); } + YY_BREAK + case 21: + YY_RULE_SETUP +-#line 102 "scanner.l" ++#line 103 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\\'); } + YY_BREAK + case 22: + YY_RULE_SETUP +-#line 103 "scanner.l" ++#line 104 "scanner.l" + { libconfig_scanctx_append_char(yyextra, '\"'); } + YY_BREAK + case 23: + YY_RULE_SETUP +-#line 104 "scanner.l" ++#line 105 "scanner.l" + { + const char *error = NULL; + const char *path = libconfig_scanctx_take_string(yyextra); +@@ -1298,57 +1300,57 @@ YY_RULE_SETUP + case 24: + /* rule 24 can match eol */ + YY_RULE_SETUP +-#line 127 "scanner.l" ++#line 128 "scanner.l" + { /* ignore */ } + YY_BREAK + case 25: + YY_RULE_SETUP +-#line 128 "scanner.l" ++#line 129 "scanner.l" + { /* ignore */ } + YY_BREAK + case 26: + YY_RULE_SETUP +-#line 130 "scanner.l" ++#line 131 "scanner.l" + { return(TOK_EQUALS); } + YY_BREAK + case 27: + YY_RULE_SETUP +-#line 131 "scanner.l" ++#line 132 "scanner.l" + { return(TOK_COMMA); } + YY_BREAK + case 28: + YY_RULE_SETUP +-#line 132 "scanner.l" ++#line 133 "scanner.l" + { return(TOK_GROUP_START); } + YY_BREAK + case 29: + YY_RULE_SETUP +-#line 133 "scanner.l" ++#line 134 "scanner.l" + { return(TOK_GROUP_END); } + YY_BREAK + case 30: + YY_RULE_SETUP +-#line 134 "scanner.l" ++#line 135 "scanner.l" + { yylval->ival = 1; return(TOK_BOOLEAN); } + YY_BREAK + case 31: + YY_RULE_SETUP +-#line 135 "scanner.l" ++#line 136 "scanner.l" + { yylval->ival = 0; return(TOK_BOOLEAN); } + YY_BREAK + case 32: + YY_RULE_SETUP +-#line 136 "scanner.l" ++#line 137 "scanner.l" + { yylval->sval = yytext; return(TOK_NAME); } + YY_BREAK + case 33: + YY_RULE_SETUP +-#line 137 "scanner.l" ++#line 138 "scanner.l" + { yylval->fval = atof(yytext); return(TOK_FLOAT); } + YY_BREAK + case 34: + YY_RULE_SETUP +-#line 138 "scanner.l" ++#line 139 "scanner.l" + { + int ok; + long long llval = libconfig_parse_integer(yytext, &ok); +@@ -1369,12 +1371,12 @@ YY_RULE_SETUP + YY_BREAK + case 35: + YY_RULE_SETUP +-#line 155 "scanner.l" ++#line 156 "scanner.l" + { yylval->llval = atoll(yytext); return(TOK_INTEGER64); } + YY_BREAK + case 36: + YY_RULE_SETUP +-#line 156 "scanner.l" ++#line 157 "scanner.l" + { + yylval->ival = strtoul(yytext, NULL, 16); + return(TOK_HEX); +@@ -1382,7 +1384,7 @@ YY_RULE_SETUP + YY_BREAK + case 37: + YY_RULE_SETUP +-#line 160 "scanner.l" ++#line 161 "scanner.l" + { + yylval->llval = libconfig_parse_hex64(yytext); + return(TOK_HEX64); +@@ -1390,32 +1392,32 @@ YY_RULE_SETUP + YY_BREAK + case 38: + YY_RULE_SETUP +-#line 164 "scanner.l" ++#line 165 "scanner.l" + { return(TOK_ARRAY_START); } + YY_BREAK + case 39: + YY_RULE_SETUP +-#line 165 "scanner.l" ++#line 166 "scanner.l" + { return(TOK_ARRAY_END); } + YY_BREAK + case 40: + YY_RULE_SETUP +-#line 166 "scanner.l" ++#line 167 "scanner.l" + { return(TOK_LIST_START); } + YY_BREAK + case 41: + YY_RULE_SETUP +-#line 167 "scanner.l" ++#line 168 "scanner.l" + { return(TOK_LIST_END); } + YY_BREAK + case 42: + YY_RULE_SETUP +-#line 168 "scanner.l" ++#line 169 "scanner.l" + { return(TOK_SEMICOLON); } + YY_BREAK + case 43: + YY_RULE_SETUP +-#line 169 "scanner.l" ++#line 170 "scanner.l" + { return(TOK_GARBAGE); } + YY_BREAK + case YY_STATE_EOF(INITIAL): +@@ -1423,7 +1425,7 @@ case YY_STATE_EOF(SINGLE_LINE_COMMENT): + case YY_STATE_EOF(MULTI_LINE_COMMENT): + case YY_STATE_EOF(STRING): + case YY_STATE_EOF(INCLUDE): +-#line 171 "scanner.l" ++#line 172 "scanner.l" + { + const char *error = NULL; + FILE *fp; +@@ -1459,10 +1461,10 @@ case YY_STATE_EOF(INCLUDE): + YY_BREAK + case 44: + YY_RULE_SETUP +-#line 203 "scanner.l" ++#line 205 "scanner.l" + ECHO; + YY_BREAK +-#line 1465 "scanner.c" ++#line 1467 "scanner.c" + + case YY_END_OF_BUFFER: + { +@@ -2582,35 +2584,25 @@ static int yy_flex_strlen (const char * s , yyscan_t yyscanner) + } + #endif + +-void *yyalloc (yy_size_t size , yyscan_t yyscanner) ++void yyfree (void * ptr , yyscan_t yyscanner) + { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; +- return malloc(size); ++ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ + } + +-void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +-{ +- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +- (void)yyg; ++#define YYTABLES_NAME "yytables" + +- /* The cast to (char *) in the following accommodates both +- * implementations that use char* generic pointers, and those +- * that use void* generic pointers. It works with the latter +- * because both ANSI C and C++ allow castless assignment from +- * any pointer type to void*, and deal with argument conversions +- * as though doing an assignment. +- */ +- return realloc(ptr, size); +-} ++#line 205 "scanner.l" + +-void yyfree (void * ptr , yyscan_t yyscanner) ++ ++void *libconfig_yyalloc(size_t bytes, void *yyscanner) + { +- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +- (void)yyg; +- free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ ++ return(libconfig_malloc(bytes)); + } + +-#define YYTABLES_NAME "yytables" ++void *libconfig_yyrealloc(void *ptr, size_t bytes, void *yyscanner) ++{ ++ return(libconfig_realloc(ptr, bytes)); ++} + +-#line 203 "scanner.l" +diff --git a/lib/scanner.h b/lib/scanner.h +index b902fd9..2bf8b06 100644 +--- a/lib/scanner.h ++++ b/lib/scanner.h +@@ -436,6 +436,8 @@ void *yyalloc ( yy_size_t , yyscan_t yyscanner ); + void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); + void yyfree ( void * , yyscan_t yyscanner ); + ++/* Begin user sect3 */ ++ + #define libconfig_yywrap(yyscanner) (/*CONSTCOND*/1) + #define YY_SKIP_YYWRAP + +@@ -712,8 +714,9 @@ extern int yylex \ + #undef yyTABLES_NAME + #endif + +-#line 203 "scanner.l" ++#line 205 "scanner.l" ++ + +-#line 717 "scanner.h" ++#line 720 "scanner.h" + #undef libconfig_yyIN_HEADER + #endif /* libconfig_yyHEADER_H */ +diff --git a/lib/scanner.l b/lib/scanner.l +index 21c1271..6b750e4 100644 +--- a/lib/scanner.l ++++ b/lib/scanner.l +@@ -1,7 +1,7 @@ + /* -*- mode: C -*- */ + /* -------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -31,6 +31,7 @@ + %option header-file="scanner.h" + %option outfile="lex.yy.c" + %option extra-type="struct scan_context *" ++%option noyyalloc noyyrealloc + + %{ + +@@ -200,3 +201,15 @@ include_open ^[ \t]*@include[ \t]+\" + yyterminate(); + } + } ++ ++%% ++ ++void *libconfig_yyalloc(size_t bytes, void *yyscanner) ++{ ++ return(libconfig_malloc(bytes)); ++} ++ ++void *libconfig_yyrealloc(void *ptr, size_t bytes, void *yyscanner) ++{ ++ return(libconfig_realloc(ptr, bytes)); ++} +diff --git a/lib/strbuf.c b/lib/strbuf.c +index fa2d913..c9763fb 100644 +--- a/lib/strbuf.c ++++ b/lib/strbuf.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -38,7 +38,7 @@ void libconfig_strbuf_ensure_capacity(strbuf_t *buf, size_t len) + if(newlen > buf->capacity) + { + buf->capacity = (newlen + (STRING_BLOCK_SIZE - 1)) & mask; +- buf->string = (char *)realloc(buf->string, buf->capacity); ++ buf->string = (char *)libconfig_realloc(buf->string, buf->capacity); + } + } + +diff --git a/lib/strbuf.h b/lib/strbuf.h +index 0bc9b13..7385b05 100644 +--- a/lib/strbuf.h ++++ b/lib/strbuf.h +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/strvec.c b/lib/strvec.c +index e1c3daa..09289c2 100644 +--- a/lib/strvec.c ++++ b/lib/strvec.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -34,7 +34,7 @@ void libconfig_strvec_append(strvec_t *vec, const char *s) + if(vec->length == vec->capacity) + { + vec->capacity += CHUNK_SIZE; +- vec->strings = (const char **)realloc( ++ vec->strings = (const char **)libconfig_realloc( + (void *)vec->strings, + (vec->capacity + 1) * sizeof(const char *)); + vec->end = vec->strings + vec->length; +diff --git a/lib/strvec.h b/lib/strvec.h +index e90aa2c..2781afb 100644 +--- a/lib/strvec.h ++++ b/lib/strvec.h +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2020 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/util.c b/lib/util.c +index b4b00b8..e0e141f 100644 +--- a/lib/util.c ++++ b/lib/util.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -30,6 +30,70 @@ + + /* ------------------------------------------------------------------------- */ + ++void libconfig_fatal_error_handler(const char *message) ++{ ++ if(write(STDERR_FILENO, (const void *)message, strlen(message))) {} ++ abort(); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ ++static void (*__libconfig_fatal_error_func)(const char *) = ++ libconfig_fatal_error_handler; ++ ++static const char *__libconfig_malloc_failure_message = ++ "\alibconfig: memory allocation failure\n"; ++ ++/* ------------------------------------------------------------------------- */ ++ ++void libconfig_set_fatal_error_func(void (*func)(const char *)) ++{ ++ __libconfig_fatal_error_func = (func ? func ++ : libconfig_fatal_error_handler); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ ++void libconfig_fatal_error(const char *message) ++{ ++ __libconfig_fatal_error_func(message); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ ++void *libconfig_malloc(size_t size) ++{ ++ void *ptr = malloc(size); ++ if(!ptr) ++ libconfig_fatal_error(__libconfig_malloc_failure_message); ++ ++ return(ptr); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ ++void *libconfig_calloc(size_t nmemb, size_t size) ++{ ++ void *ptr = calloc(nmemb, size); ++ if(!ptr) ++ libconfig_fatal_error(__libconfig_malloc_failure_message); ++ ++ return(ptr); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ ++void *libconfig_realloc(void *ptr, size_t size) ++{ ++ ptr = realloc(ptr, size); ++ if(!ptr) ++ libconfig_fatal_error(__libconfig_malloc_failure_message); ++ ++ return(ptr); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ + long long libconfig_parse_integer(const char *s, int *ok) + { + long long llval; +diff --git a/lib/util.h b/lib/util.h +index 9cd2463..99d7e9f 100644 +--- a/lib/util.h ++++ b/lib/util.h +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -23,7 +23,15 @@ + #include + #include + +-#define __new(T) (T *)calloc(1, sizeof(T)) /* zeroed */ ++extern void libconfig_set_fatal_error_func(void (*func)(const char *)); ++ ++extern void libconfig_fatal_error(const char *message); ++ ++extern void *libconfig_malloc(size_t size); ++extern void *libconfig_calloc(size_t nmemb, size_t size); ++extern void *libconfig_realloc(void *ptr, size_t size); ++ ++#define __new(T) (T *)libconfig_calloc(1, sizeof(T)) /* zeroed */ + #define __delete(P) free((void *)(P)) + #define __zero(P) memset((void *)(P), 0, sizeof(*P)) + +diff --git a/lib/wincompat.c b/lib/wincompat.c +index 8a243f9..044b82f 100644 +--- a/lib/wincompat.c ++++ b/lib/wincompat.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/lib/wincompat.h b/lib/wincompat.h +index 5de29c3..26ebac5 100644 +--- a/lib/wincompat.h ++++ b/lib/wincompat.h +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +diff --git a/tests/tests.c b/tests/tests.c +index c12a0c6..7d37655 100644 +--- a/tests/tests.c ++++ b/tests/tests.c +@@ -1,6 +1,6 @@ + /* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files +- Copyright (C) 2005-2018 Mark A Lindner ++ Copyright (C) 2005-2023 Mark A Lindner + + This file is part of libconfig. + +@@ -64,8 +64,8 @@ static void parse_file_and_compare_error(const char *input_file, + const char *parse_error) + { + config_t cfg; +- char actual_error[128]; +- char expected_error[128]; ++ char actual_error[256]; ++ char expected_error[256]; + + config_init(&cfg); + TT_ASSERT_FALSE(config_read_file(&cfg, input_file)); +@@ -88,8 +88,8 @@ static void parse_string_and_compare_error(const char *input_text, + const char *parse_error) + { + config_t cfg; +- char actual_error[128]; +- char expected_error[128]; ++ char actual_error[256]; ++ char expected_error[256]; + + config_init(&cfg); + TT_ASSERT_FALSE(config_read_string(&cfg, input_text)); +-- +2.27.0 + diff --git a/backport-Added-unit-test-for-config_read.patch b/backport-Added-unit-test-for-config_read.patch new file mode 100644 index 0000000000000000000000000000000000000000..0bd4abd0bf4702a23ba6bc9fcc33e7b036355706 --- /dev/null +++ b/backport-Added-unit-test-for-config_read.patch @@ -0,0 +1,57 @@ +From 92b5bba28f4497790e4111839ff0c45ed72a0b8a Mon Sep 17 00:00:00 2001 +From: Mark Lindner +Date: Tue, 22 Nov 2022 14:40:08 -0700 +Subject: [PATCH] Added unit test for config_read() + +--- + tests/tests.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/tests/tests.c b/tests/tests.c +index 2b6d5e8..1637414 100644 +--- a/tests/tests.c ++++ b/tests/tests.c +@@ -638,6 +638,32 @@ TT_TEST(SettingLookups) + + /* ------------------------------------------------------------------------- */ + ++TT_TEST(ReadStream) ++{ ++ config_t cfg; ++ int ok; ++ FILE *stream; ++ ++ config_init(&cfg); ++ config_set_include_dir(&cfg, "./testdata"); ++ ++ stream = fopen("testdata/nesting.cfg", "rt"); ++ TT_ASSERT_PTR_NOTNULL(stream); ++ ++ ok = config_read(&cfg, stream); ++ ++ fclose(stream); ++ ++ if(!ok) ++ { ++ printf("error: %s:%d\n", config_error_text(&cfg), ++ config_error_line(&cfg)); ++ } ++ TT_ASSERT_TRUE(ok); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ + int main(int argc, char **argv) + { + int failures; +@@ -657,6 +683,7 @@ int main(int argc, char **argv) + TT_SUITE_TEST(LibConfigTests, EscapedStrings); + TT_SUITE_TEST(LibConfigTests, OverrideSetting); + TT_SUITE_TEST(LibConfigTests, SettingLookups); ++ TT_SUITE_TEST(LibConfigTests, ReadStream); + TT_SUITE_RUN(LibConfigTests); + failures = TT_SUITE_NUM_FAILURES(LibConfigTests); + TT_SUITE_END(LibConfigTests); +-- +2.27.0 + diff --git a/backport-Fixed-various-bugs-in-setting-lookups-by-name-path.patch b/backport-Fixed-various-bugs-in-setting-lookups-by-name-path.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8ad95c0215f94fd85fe4d780b2513e597457d4e --- /dev/null +++ b/backport-Fixed-various-bugs-in-setting-lookups-by-name-path.patch @@ -0,0 +1,281 @@ +From 5ff6aecbdb7f85a8e7a2ea7fd63c03b4bdd42076 Mon Sep 17 00:00:00 2001 +From: Mark Lindner +Date: Tue, 22 Nov 2022 14:10:16 -0700 +Subject: [PATCH] Fixed various bugs in setting lookups by name/path. + +--- + lib/libconfig.c | 79 ++++++++++++++------------------ + tests/testdata/nesting.cfg | 6 +++ + tests/tests.c | 94 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 135 insertions(+), 44 deletions(-) + create mode 100644 tests/testdata/nesting.cfg + +diff --git a/lib/libconfig.c b/lib/libconfig.c +index 1a935be..e25ed26 100644 +--- a/lib/libconfig.c ++++ b/lib/libconfig.c +@@ -125,32 +125,6 @@ static void __config_locale_restore(void) + + /* ------------------------------------------------------------------------- */ + +-static int __config_name_compare(const char *a, const char *b) +-{ +- const char *p, *q; +- +- for(p = a, q = b; ; p++, q++) +- { +- int pd = ((! *p) || strchr(PATH_TOKENS, *p)); +- int qd = ((! *q) || strchr(PATH_TOKENS, *q)); +- +- if(pd && qd) +- break; +- else if(pd) +- return(-1); +- else if(qd) +- return(1); +- else if(*p < *q) +- return(-1); +- else if(*p > *q) +- return(1); +- } +- +- return(0); +-} +- +-/* ------------------------------------------------------------------------- */ +- + static void __config_indent(FILE *stream, int depth, unsigned short w) + { + if(w) +@@ -385,8 +359,12 @@ static void __config_list_add(config_list_t *list, config_setting_t *setting) + + /* ------------------------------------------------------------------------- */ + ++/* This function takes the length of the name to be searched for, so that one ++ * component of a longer path can be passed in. ++ */ + static config_setting_t *__config_list_search(config_list_t *list, + const char *name, ++ size_t namelen, + unsigned int *idx) + { + config_setting_t **found = NULL; +@@ -400,7 +378,8 @@ static config_setting_t *__config_list_search(config_list_t *list, + if(! (*found)->name) + continue; + +- if(! __config_name_compare(name, (*found)->name)) ++ if((strlen((*found)->name) == namelen) ++ && !strncmp(name, (*found)->name, namelen)) + { + if(idx) + *idx = i; +@@ -1226,27 +1205,37 @@ config_setting_t *config_setting_lookup(config_setting_t *setting, + const char *p = path; + config_setting_t *found = setting; + +- for(;;) ++ while(*p && found) + { +- while(*p && strchr(PATH_TOKENS, *p)) +- p++; +- +- if(! *p) +- break; ++ if(strchr(PATH_TOKENS, *p)) ++ ++p; + + if(*p == '[') +- found = config_setting_get_elem(found, atoi(++p)); +- else +- found = config_setting_get_member(found, p); ++ { ++ char *q; ++ long index = strtol(++p, &q, 10); ++ if(*q != ']') ++ return NULL; + +- if(! found) +- break; ++ p = ++q; ++ found = config_setting_get_elem(found, index); ++ } ++ else if(found->type == CONFIG_TYPE_GROUP) ++ { ++ const char *q = p; + +- while(! strchr(PATH_TOKENS, *p)) +- p++; ++ while(*q && !strchr(PATH_TOKENS, *q)) ++ ++q; ++ ++ found = __config_list_search(found->value.list, p, (size_t)(q - p), ++ NULL); ++ p = q; ++ } ++ else ++ break; + } + +- return(*p || (found == setting) ? NULL : found); ++ return((*p || (found == setting)) ? NULL : found); + } + + /* ------------------------------------------------------------------------- */ +@@ -1565,7 +1554,7 @@ config_setting_t *config_setting_get_member(const config_setting_t *setting, + if(setting->type != CONFIG_TYPE_GROUP) + return(NULL); + +- return(__config_list_search(setting->value.list, name, NULL)); ++ return(__config_list_search(setting->value.list, name, strlen(name), NULL)); + } + + /* ------------------------------------------------------------------------- */ +@@ -1676,9 +1665,11 @@ int config_setting_remove(config_setting_t *parent, const char *name) + break; + } + +- }while(*++settingName); ++ } ++ while(*++settingName); + +- if(!(setting = __config_list_search(setting->parent->value.list, settingName, &idx))) ++ if(!(setting = __config_list_search(setting->parent->value.list, settingName, ++ strlen(settingName), &idx))) + return(CONFIG_FALSE); + + __config_list_remove(setting->parent->value.list, idx); +diff --git a/tests/testdata/nesting.cfg b/tests/testdata/nesting.cfg +new file mode 100644 +index 0000000..3e37234 +--- /dev/null ++++ b/tests/testdata/nesting.cfg +@@ -0,0 +1,6 @@ ++ ++foo = ( ++ { string: "orange", number: 3, flag: false, array: [7, 13] }, ++ { string: "blue", number: 11, flag: true, array: [1, 2, 3, 4] }, ++ { string: "red", number: 7, flag: false, array: [77, 88] } ++) +diff --git a/tests/tests.c b/tests/tests.c +index 7d37655..2b6d5e8 100644 +--- a/tests/tests.c ++++ b/tests/tests.c +@@ -482,6 +482,15 @@ TT_TEST(EscapedStrings) + TT_ASSERT_TRUE(ok); + TT_ASSERT_STR_EQ("abc\"def\"", str); + ++ ok = config_lookup_string(&cfg, "escape_seqs.dquote.[0]", &str); ++ TT_ASSERT_FALSE(ok); ++ ++ ok = config_lookup_string(&cfg, "escape_seqs.dquote.extrajunk", &str); ++ TT_ASSERT_FALSE(ok); ++ ++ ok = config_lookup_string(&cfg, "escape_seqs.dquote.", &str); ++ TT_ASSERT_TRUE(ok); ++ + config_destroy(&cfg); + } + +@@ -545,6 +554,90 @@ TT_TEST(OverrideSetting) + + /* ------------------------------------------------------------------------- */ + ++TT_TEST(SettingLookups) ++{ ++ config_t cfg; ++ int ok; ++ int ival; ++ const char *str; ++ config_setting_t *setting, *parent; ++ ++ config_init(&cfg); ++ config_set_options(&cfg, CONFIG_OPTION_ALLOW_OVERRIDES); ++ config_set_include_dir(&cfg, "./testdata"); ++ ++ ok = config_read_file(&cfg, "testdata/nesting.cfg"); ++ if(!ok) ++ { ++ printf("error: %s:%d\n", config_error_text(&cfg), ++ config_error_line(&cfg)); ++ } ++ TT_ASSERT_TRUE(ok); ++ ++ ok = config_lookup_string(&cfg, "foo.[0].string", &str); ++ TT_ASSERT_TRUE(ok); ++ TT_ASSERT_STR_EQ("orange", str); ++ ++ ok = config_lookup_int(&cfg, "foo.[1].array.[3]", &ival); ++ TT_ASSERT_TRUE(ok); ++ TT_ASSERT_INT_EQ(4, ival); ++ ++ ok = config_lookup_bool(&cfg, "foo.[1].flag", &ival); ++ TT_ASSERT_TRUE(ok); ++ TT_ASSERT_INT_EQ(CONFIG_TRUE, ival); ++ ++ ok = config_lookup_int(&cfg, "foo.[2].number", &ival); ++ TT_ASSERT_TRUE(ok); ++ TT_ASSERT_INT_EQ(7, ival); ++ ++ ok = config_lookup_string(&cfg, "foo.[0].string.blah", &str); ++ TT_ASSERT_FALSE(ok); ++ ++ ok = config_lookup_string(&cfg, "foo.[0].string.[0]", &str); ++ TT_ASSERT_FALSE(ok); ++ ++ ok = config_lookup_string(&cfg, "foo.[0].[1]", &str); ++ TT_ASSERT_FALSE(ok); ++ ++ ok = config_lookup_string(&cfg, "foo.[0].array.[0].blah", &str); ++ TT_ASSERT_FALSE(ok); ++ ++ ok = config_lookup_string(&cfg, "[0]", &str); ++ TT_ASSERT_FALSE(ok); ++ ++ setting = config_lookup(&cfg, "foo.[0].array.[0]"); ++ TT_ASSERT_PTR_NOTNULL(setting); ++ ++ setting = config_lookup(&cfg, "foo.[0].array.[0"); ++ TT_ASSERT_PTR_NULL(setting); ++ ++ setting = config_lookup(&cfg, "/foo.[0].array.[0]"); ++ TT_ASSERT_PTR_NOTNULL(setting); ++ ++ setting = config_lookup(&cfg, "/foo/[0]/array/[0]"); ++ TT_ASSERT_PTR_NOTNULL(setting); ++ ++ parent = config_lookup(&cfg, ".foo"); ++ TT_ASSERT_PTR_NOTNULL(parent); ++ ++ setting = config_setting_lookup(parent, ".[0]"); ++ TT_ASSERT_PTR_NOTNULL(setting); ++ ++ setting = config_setting_lookup(parent, ".[0].array"); ++ TT_ASSERT_PTR_NOTNULL(setting); ++ ++ setting = config_setting_lookup(parent, ".[0].array.[1]"); ++ TT_ASSERT_PTR_NOTNULL(setting); ++ ++ setting = config_setting_lookup(parent, "[0].array.[1000]"); ++ TT_ASSERT_PTR_NULL(setting); ++ ++ setting = config_setting_lookup(parent, "[0].array.[0].blah"); ++ TT_ASSERT_PTR_NULL(setting); ++} ++ ++/* ------------------------------------------------------------------------- */ ++ + int main(int argc, char **argv) + { + int failures; +@@ -563,6 +656,7 @@ int main(int argc, char **argv) + TT_SUITE_TEST(LibConfigTests, RemoveSetting); + TT_SUITE_TEST(LibConfigTests, EscapedStrings); + TT_SUITE_TEST(LibConfigTests, OverrideSetting); ++ TT_SUITE_TEST(LibConfigTests, SettingLookups); + TT_SUITE_RUN(LibConfigTests); + failures = TT_SUITE_NUM_FAILURES(LibConfigTests); + TT_SUITE_END(LibConfigTests); +-- +2.27.0 + diff --git a/libconfig.spec b/libconfig.spec index e3ef263ff984baa742518fd006bcd27cf7044e2b..51318bcfb3958294d198d4e1aff9d38c45663551 100644 --- a/libconfig.spec +++ b/libconfig.spec @@ -1,6 +1,6 @@ Name: libconfig Version: 1.7.3 -Release: 2 +Release: 3 Summary: C/C++ Configuration File Library License: LGPLv2+ URL: http://www.hyperrealm.com/libconfig/libconfig.html @@ -9,6 +9,11 @@ URL: http://www.hyperrealm.com/libconfig/libconfig.html Source0: https://github.com/hyperrealm/libconfig/releases/download/v%{version}/%{name}-%{version}.tar.gz Source1: libconfig.pdf + +Patch6000: backport-Add-logic-to-handle-memory-allocation-failures.patch +Patch6001: backport-Fixed-various-bugs-in-setting-lookups-by-name-path.patch +Patch6002: backport-Added-unit-test-for-config_read.patch + Patch9000: add-to-strbuf_append_string.patch BuildRequires: git gcc gcc-c++ bison flex @@ -63,6 +68,12 @@ make check %{_libdir}/*.la %changelog +* Tue Dec 06 2022 shixuantong - 1.7.3-3 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:Add logic to handle memory allocation failures + * Thu Oct 27 2022 dongyuzhen - 1.7.3-2 - Type:bugfix - ID:NA