(********************************************************************)
(*                                                                  *)
(*  cc_conf.s7i   Configuration values for C compiler and runtime.  *)
(*  Copyright (C) 2013 - 2021  Thomas Mertes                        *)
(*                                                                  *)
(*  This file is part of the Seed7 Runtime Library.                 *)
(*                                                                  *)
(*  The Seed7 Runtime Library is free software; you can             *)
(*  redistribute it and/or modify it under the terms of the GNU     *)
(*  Lesser General Public License as published by the Free Software *)
(*  Foundation; either version 2.1 of the License, or (at your      *)
(*  option) any later version.                                      *)
(*                                                                  *)
(*  The Seed7 Runtime Library is distributed in the hope that it    *)
(*  will be useful, but WITHOUT ANY WARRANTY; without even the      *)
(*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *)
(*  PURPOSE.  See the GNU Lesser General Public License for more    *)
(*  details.                                                        *)
(*                                                                  *)
(*  You should have received a copy of the GNU Lesser General       *)
(*  Public License along with this program; if not, write to the    *)
(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


include "shell.s7i";
include "osfiles.s7i";
include "propertyfile.s7i";


(**
 *  Structure to describe C compiler and runtime library.
 *)
const type: ccConfigType is new struct

    (**
     *  TRUE if the Seed7 runtime library uses strings with capacity.
     *  The capacity of a string can be larger than its size.
     *  Strings with capacity can be enlarged without calling realloc().
     *)
    var boolean: WITH_STRI_CAPACITY           is FALSE;

    (**
     *  TRUE if the actual characters of a string can be stored elsewhere.
     *  This allows string slices without the need to copy characters.
     *)
    var boolean: ALLOW_STRITYPE_SLICES        is FALSE;

    (**
     *  TRUE if the actual characters of a bstring can be stored elsewhere.
     *  This allows bstring slices without the need to copy characters.
     *)
    var boolean: ALLOW_BSTRITYPE_SLICES       is FALSE;

    (**
     *  TRUE if right shifts preserve the sign of negative signed integers.
     *  The C standard specifies that the right shift of signed integers is
     *  implementation defined, if the shifted values are negative.
     *)
    var boolean: RSHIFT_DOES_SIGN_EXTEND      is FALSE;

    (**
     *  TRUE if signed integers are represented as twos complement numbers.
     *  This allows some simplified range checks in compiled programs.
     *)
    var boolean: TWOS_COMPLEMENT_INTTYPE      is FALSE;

    (**
     *  TRUE if the byte ordering of integers is little endian.
     *  With little endian byte ordering it is possible to get the elements
     *  of a union by casting the union to the desired element type.
     *)
    var boolean: LITTLE_ENDIAN_INTTYPE        is FALSE;

    (**
     *  TRUE if float comparisons with NaN and negative zero work okay.
     *  A comparison between NaN and any other value should return FALSE.
     *  Negative zero should be considered as identical to positive zero.
     *  Comparison refers to comparisons with  ==  <  >  <=  or  >= .
     *  If FLOAT_COMPARISON_OKAY is FALSE fltEq(), fltLt(), fltGt(), fltLe()
     *  and fltGe() should be used to do comparisons of float values.
     *)
    var boolean: FLOAT_COMPARISON_OKAY        is FALSE;

    (**
     *  TRUE if pow() works okay for a base of zero, one and NaN.
     *  If it is FALSE fltPow() should be used instead of pow().
     *)
    var boolean: POW_FUNCTION_OKAY            is FALSE;

    (**
     *  TRUE if fmod() works okay for Infinity, NaN and zero.
     *  If it is FALSE fltRem() should be used instead of fmod().
     *)
    var boolean: FMOD_FUNCTION_OKAY           is FALSE;

    (**
     *  TRUE if sqrt() works okay for a negative argument and NaN.
     *  If it is FALSE fltSqrt() should be used instead of sqrt().
     *)
    var boolean: SQRT_FUNCTION_OKAY           is FALSE;

    (**
     *  TRUE if exp() works okay for NaN.
     *  If it is FALSE fltExp() should be used instead of exp().
     *)
    var boolean: EXP_FUNCTION_OKAY            is FALSE;

    (**
     *  TRUE if log() works okay for zero, negative values and NaN.
     *  If it is FALSE fltLog() should be used instead of log().
     *)
    var boolean: LOG_FUNCTION_OKAY            is FALSE;

    (**
     *  TRUE if log10() works okay for zero, negative values and NaN.
     *  If it is FALSE fltLog10() should be used instead of log10().
     *)
    var boolean: LOG10_FUNCTION_OKAY          is FALSE;

    (**
     *  TRUE if log1p() works okay for -1.0, values < -1.0 and NaN.
     *  If it is FALSE fltLog1p() should be used instead of log1p().
     *)
    var boolean: LOG1P_FUNCTION_OKAY          is FALSE;

    (**
     *  TRUE if log2() works okay for zero, negative values and NaN.
     *  If it is FALSE fltLog2() should be used instead of log2().
     *)
    var boolean: LOG2_FUNCTION_OKAY           is FALSE;

    (**
     *  TRUE if ldexp() works okay for NaN.
     *  If it is FALSE fltLdexp() should be used instead of lsexp().
     *)
    var boolean: LDEXP_FUNCTION_OKAY          is FALSE;

    (**
     *  TRUE if frexp() works okay for Infinity, NaN and subnormal numbers.
     *  If it is FALSE fltDecompose() should be used instead of frexp().
     *)
    var boolean: FREXP_FUNCTION_OKAY          is FALSE;

    (**
     *  TRUE if the functions sigsetjmp() and siglongjmp() are available.
     *  If it is FALSE the functions setjmp() and longjmp() must
     *  be used instead.
     *)
    var boolean: HAS_SIGSETJMP                is FALSE;

    (**
     *  TRUE if integer divisions must be checked for a division by zero.
     *  This applies to the division operations div and mdiv.
     *  The generated C code should, if a division by zero occurs,
     *  raise the exception NUMERIC_ERROR instead of doing the
     *  illegal divide operation. If CHECK_INT_DIV_BY_ZERO is FALSE
     *  a division by zero always triggers SIGFPE. SIGFPE is caught
     *  by the Seed7 run-time library and triggers a NUMERIC_ERROR.
     *)
    var boolean: CHECK_INT_DIV_BY_ZERO        is FALSE;

    (**
     *  TRUE if the C expression 0/0 might not trigger SIGFPE.
     *  C compilers assume that so called "undefined behavior" will
     *  not happen. According to the C standard a division by 0
     *  triggers undefined behavior. This way a C compiler is allowed
     *  to optimize the expressions 0/0 and 0/variable to 0. Likewise
     *  the expression variable/variable can be optimized to 1.
     *  In Seed7 a division by zero is defined behavior, since it
     *  raises the exception NUMERIC_ERROR. This configuration
     *  setting applies to the division operations div and mdiv.
     *  The generated C code should, if a division by zero occurs,
     *  raise the exception NUMERIC_ERROR instead of allowing the
     *  C compiler to do its optimization.
     *)
    var boolean: CHECK_INT_DIV_ZERO_BY_ZERO   is FALSE;

    (**
     *  TRUE if integer remainder must be checked for a division by zero.
     *  This applies to the division operations rem and mod.
     *  The generated C code should, if a remainder by zero occurs,
     *  raise the exception NUMERIC_ERROR instead of doing the
     *  illegal divide operation. If CHECK_INT_REM_BY_ZERO is FALSE
     *  a remainder by zero always triggers SIGFPE. SIGFPE is caught
     *  by the Seed7 run-time library and triggers a NUMERIC_ERROR.
     *)
    var boolean: CHECK_INT_REM_BY_ZERO        is FALSE;

    (**
     *  TRUE if the C expression 0%0 might not trigger SIGFPE.
     *  C compilers assume that so called "undefined behavior" will
     *  not happen. According to the C standard a division by 0
     *  triggers undefined behavior. This way a C compiler is allowed
     *  to optimize the expressions 0%0 and 0%variable to 0. Likewise
     *  the expression variable%variable can be optimized to 0.
     *  In Seed7 a division by zero is defined behavior, since it
     *  raises the exception NUMERIC_ERROR. This configuration
     *  setting applies to the division operations rem and mod.
     *  The generated C code should, if a division by zero occurs,
     *  raise the exception NUMERIC_ERROR instead of allowing the
     *  C compiler to do its optimization.
     *)
    var boolean: CHECK_INT_REM_ZERO_BY_ZERO   is FALSE;

    (**
     *  TRUE if floating point divisions by zero cause compilation errors.
     *  Some C compilers check if the dividend is 0.0 and classify a
     *  floating point division by zero as fatal compilation error.
     *  Some C compilers even trigger wrong behavior if the dividend
     *  is 0.0. In this case FLOAT_ZERO_DIV_ERROR is also TRUE.
     *  If FLOAT_ZERO_DIV_ERROR is TRUE the generated C code should
     *  avoid divisions by zero and generate code to return Infinity,
     *  -Infinity or NaN instead.
     *)
    var boolean: FLOAT_ZERO_DIV_ERROR         is FALSE;

    (**
     *  TRUE if floating point divisions by zero don't conform to IEEE 754.
     *  According to IEEE 754 a floating point division by zero should
     *  return Infinity, -Infinity or NaN. In this case the compiler
     *  generates C code, which checks all float divisions ( / and /:= )
     *  for division by zero. The generated C code should return
     *  Infinity, -Infinity or NaN instead of doing the divide operation.
     *)
    var boolean: CHECK_FLOAT_DIV_BY_ZERO      is FALSE;

    (**
     *  TRUE if the C function exp2() is present.
     *)
    var boolean: HAS_EXP2                     is FALSE;

    (**
     *  TRUE if the C function exp10() is present.
     *)
    var boolean: HAS_EXP10                    is FALSE;

    (**
     *  TRUE if the C function expm1() is present.
     *)
    var boolean: HAS_EXPM1                    is FALSE;

    (**
     *  TRUE if the C function cbrt() is present.
     *)
    var boolean: HAS_CBRT                     is FALSE;

    (**
     *  TRUE if the C compiler limits the length of string literals.
     *  Some C compilers limit the maximum string literal length.
     *  There are limits of 2,048 bytes and 16,384 (16K) bytes.
     *  The actual limit is not interesting, but the fact that a
     *  limit exists or does not exist.
     *)
    var boolean: LIMITED_CSTRI_LITERAL_LEN    is FALSE;

    (**
     *  TRUE if switch statements work with 64-bit values.
     *  If it is FALSE a switch statement with a 64-bit value
     *  triggers a compile error.
     *)
    var boolean: SWITCH_WORKS_FOR_INT64TYPE   is FALSE;

    (**
     *  TRUE if a compound statement is allowed in a parentesized expression.
     *  If it is FALSE a compound statement block in a parentesized expression
     *  triggers a compile error.
     *)
    var boolean: STMT_BLOCK_IN_PARENTHESES_OK is FALSE;

    (**
     *  TRUE if #line directives can use UTF-8 encoded file names.
     *  The file names from #line directives are used by the debugger to
     *  allow source code debugging.
     *)
    var boolean: CC_SOURCE_UTF8               is FALSE;

    (**
     *  TRUE if the main function is named wmain.
     *  This is a way to support Unicode command line arguments under Windows.
     *  An alternate way to support Unicode command line arguments under
     *  Windows uses the functions getUtf16Argv() and freeUtf16Argv() (both
     *  defined in "cmd_win.c").
     *)
    var boolean: USE_WMAIN                    is FALSE;

    (**
     *  TRUE if the main function is named WinMain.
     *)
    var boolean: USE_WINMAIN                  is FALSE;

    (**
     *  TRUE if the main function invokes startMain after a button click.
     *  If a start button exists the main function will wait for
     *  a click on this button. Afterwards startMain is invoked.
     *  If no start button exists startMain is invoked immediately.
     *)
    var boolean: USE_START_MAIN               is FALSE;

    (**
     *  TRUE if the main function must be terminated with doExit().
     *)
    var boolean: USE_DO_EXIT                  is FALSE;

    (**
     *  TRUE if the type ''floatType'' is ''double''.
     *  If it is FALSE ''floatType'' is ''float''.
     *)
    var boolean: FLOATTYPE_DOUBLE             is FALSE;

    (**
     *  Size of the type ''intType'' in bits (either 32 or 64).
     *  A typedef can define ''intType'' as ''int32Type'' respectively
     *  ''int64Type''.
     *)
    var integer: INTTYPE_SIZE                 is 0;

    (**
     *  Size of the type ''floatType'' in bits.
     *)
    var integer: FLOATTYPE_SIZE               is 0;

    (**
     *  Size of a pointer in bits.
     *)
    var integer: POINTER_SIZE                 is 0;

    (**
     *  The maximum of INTTYPE_SIZE, FLOATTYPE_SIZE and POINTER_SIZE.
     *  This is also the size in bits of the types ''rtlValueUnion'',
     *  ''rtlObjectType'' and ''genericType'' (defined in data_rtl.h).
     *)
    var integer: GENERIC_SIZE                 is 0;

    (**
     *  Size of the type ''int'' in bits.
     *)
    var integer: INT_SIZE                     is 0;

    (**
     *  Minimum value of the type ''int''.
     *)
    var integer: INT_MIN                      is 0;

    (**
     *  Maximum value of the type ''int''.
     *)
    var integer: INT_MAX                      is 0;

    (**
     *  Size of the type ''long'' in bits.
     *)
    var integer: LONG_SIZE                    is 0;

    (**
     *  Number of mantissa bits in the binary ''floatType'' representation.
     *)
    var integer: FLOATTYPE_MANTISSA_BITS      is 0;

    (**
     *  Exponent offset in the binary ''floatType'' representation.
     *  To get the actual exponent the offset must be subtracted.
     *)
    var integer: FLOATTYPE_EXPONENT_OFFSET    is 0;

    (**
     *  Maximum from the continuous range of integers that map to floats.
     *  All integers from -INT_RANGE_IN_FLOATTYPE_MAX to
     *  INT_RANGE_IN_FLOATTYPE_MAX can be converted to ''floatType''
     *  and back to ''intType'' without loss.
     *)
    var integer: INT_RANGE_IN_FLOATTYPE_MAX   is 0;

    (**
     *  Minimum value that trunc() or round() can convert.
     *  Values below MINIMUM_TRUNC_ARGUMENT raise RANGE_ERROR,
     *  if trunc() or round() is applied to them.
     *)
    var integer: MINIMUM_TRUNC_ARGUMENT       is 0;

    (**
     *  Maximum value that trunc() or round() can convert.
     *  Values above MAXIMUM_TRUNC_ARGUMENT raise RANGE_ERROR,
     *  if trunc() or round() is applied to them.
     *)
    var integer: MAXIMUM_TRUNC_ARGUMENT       is 0;

    (**
     *  Mask for the alpha channel in a pixel.
     *  0 if there is no alpha channel.
     *)
    var integer: PIXEL_ALPHA_MASK             is 0;

    (**
     *  Mask for the red color in a pixel.
     *  0 if there is no mapping and drwRgbColor() should be used.
     *)
    var integer: PIXEL_RED_MASK               is 0;

    (**
     *  Mask for the green color in a pixel.
     *  0 if there is no mapping and drwRgbColor() should be used.
     *)
    var integer: PIXEL_GREEN_MASK             is 0;

    (**
     *  Mask for the blue color in a pixel.
     *  0 if there is no mapping and drwRgbColor() should be used.
     *)
    var integer: PIXEL_BLUE_MASK              is 0;

    (**
     *  Name of the variable deciding between macro and drwRgbColor().
     *  "" if no variable needs to be checked.
     *)
    var string: RGB_TO_PIXEL_FLAG_NAME        is "";

    (**
     *  Size of an integer in a ''pointList'' object.
     *  A ''pointList'' consists of (x, y) coordinate pairs where
     *  each x and y has the size POINT_LIST_INT_SIZE.
     *)
    var integer: POINT_LIST_INT_SIZE          is 0;

    (**
     *  TRUE if a ''pointList'' uses absolute coordinates.
     *  If it is FALSE the first (x, y) coordinate pair is absolute
     *  and the remaining (x, y) coordinates are relative to the
     *  previous coordinate pair.
     *)
    var boolean: POINT_LIST_ABSOLUTE          is FALSE;

    (**
     *  Multiplier for the linear congruential generator.
     *  A well known pseudorandom number generator algorithm.
     *)
    var integer: RAND_MULTIPLIER              is 0;

    (**
     *  Increment for the linear congruential generator.
     *  A well known pseudorandom number generator algorithm.
     *)
    var integer: RAND_INCREMENT               is 0;

    (**
     *  Name of a type for the boolean values 0 and 1.
     *  The runtime library and the compiler use a typedef to define
     *  the type ''boolType'' with BOOLTYPE.
     *)
    var string: BOOLTYPE                      is "";

    (**
     *  Name of a signed integer type that is 32 bits wide.
     *  The runtime library and the compiler use a typedef to define
     *  the type ''int32Type'' with INT32TYPE.
     *)
    var string: INT32TYPE                     is "";

    (**
     *  Name of an unsigned integer type that is 32 bits wide.
     *  The runtime library and the compiler use a typedef to define
     *  the type ''uint32Type'' with UINT32TYPE.
     *)
    var string: UINT32TYPE                    is "";

    (**
     *  Name of a signed integer type that is 64 bits wide.
     *  The runtime library and the compiler use a typedef to define
     *  the type ''int64Type'' with INT64TYPE.
     *)
    var string: INT64TYPE                     is "";

    (**
     *  Name of an unsigned integer type that is 64 bits wide.
     *  The runtime library and the compiler use a typedef to define
     *  the type ''uint64Type'' with UINT64TYPE.
     *)
    var string: UINT64TYPE                    is "";

    (**
     *  Name of a signed integer type that is 128 bits wide.
     *  The runtime library and the compiler use a typedef to define
     *  the type ''int128Type'' with INT128TYPE. Empty string if
     *  there is no 128-bit signed integer type.
     *)
    var string: INT128TYPE                    is "";

    (**
     *  Name of an unsigned integer type that is 128 bits wide.
     *  The runtime library and the compiler use a typedef to define
     *  the type ''uint128Type'' with UINT128TYPE. Empty string if
     *  there is no 128-bit unsigned integer type.
     *)
    var string: UINT128TYPE                   is "";

    (**
     *  The suffix used by the literals of the 32 bits wide integer type.
     *)
    var string: INT32TYPE_LITERAL_SUFFIX      is "";

    (**
     *  The suffix used by the literals of the 64 bits wide integer type.
     *)
    var string: INT64TYPE_LITERAL_SUFFIX      is "";

    (**
     *  Definition of several macros (likely, unlikely, noreturn).
     *)
    var string: MACRO_DEFS                    is "";

    (**
     *  Name of the signal that is raised if a signed integer overflow
     *  occurs. OVERFLOW_SIGNAL is an empty string, if a signed integer
     *  overflow does not raise a signal. The C compiler option
     *  CC_OPT_TRAP_OVERFLOW is used to generate traps for signed
     *  integer overflow.
     *)
    var string: OVERFLOW_SIGNAL               is "";

    (**
     *  Name of a C compiler builtin function to add with overflow check.
     *  Empty string if there is no such builtin function.
     *)
    var string: BUILTIN_ADD_OVERFLOW          is "";

    (**
     *  Name of a C compiler builtin function to subtract with overflow check.
     *  Empty string if there is no such builtin function.
     *)
    var string: BUILTIN_SUB_OVERFLOW          is "";

    (**
     *  Name of a C compiler builtin function to multiply with overflow check.
     *  Empty string if there is no such builtin function.
     *)
    var string: BUILTIN_MULT_OVERFLOW         is "";

    (**
     *  Defines what happens in case of an integer division overflow.
     *  An integer division can overflow with ''integer.first div -1''.
     *  In this case the following things can happen:
     *  * 0 it triggers an endless loop.
     *  * 1 it triggers a popup window.
     *  * 2 it returns integer.first.
     *  * 3 it returns some other value.
     *  * 4 it raises SIGFPE.
     *  * 5 it raises SIGILL.
     *  * 6 it raises SIGABRT.
     *  * 7 it raises SIGTRAP.
     *  In case of 0 (endless loop) the compiler
     *  must always check for an integer division overflow.
     *)
    var integer: INT_DIV_OVERFLOW             is 0;

    (**
     *  Defines what happens in case of an integer remainder overflow.
     *  An integer remainder can overflow with ''integer.first rem -1''.
     *  In this case the following things can happen:
     *  * 0 it triggers an endless loop.
     *  * 1 it triggers a popup window.
     *  * 2 it returns 0.
     *  * 3 it returns some other value.
     *  * 4 it raises SIGFPE.
     *  * 5 it raises SIGILL.
     *  * 6 it raises SIGABRT.
     *  * 7 it raises SIGTRAP.
     *  In case of 0 (endless loop) the compiler
     *  must always check for an integer remainder overflow.
     *)
    var integer: INT_REM_OVERFLOW             is 0;

    (**
     *  The extension used by the C compiler for object files.
     *  Several object files and libraries are linked together to
     *  an executable. Under Linux/Unix/BSD this is usually ".o".
     *  Under Windows this is ".o" for MinGW and Cygwin,
     *  but ".obj" for other compilers.
     *)
    var string: OBJECT_FILE_EXTENSION         is "";

    (**
     *  The extension used by the linker for static libraries.
     *  Several object files can be grouped to a library. Under
     *  Linux/Unix/BSD this is usually ".a". Under Windows this is
     *  ".a" for MinGW and Cygwin, but ".lib" for other linkers.
     *)
    var string: LIBRARY_FILE_EXTENSION        is "";

    (**
     *  The extension used by the operating system for executables.
     *  Since executable extensions are not used under
     *  Linux/Unix/BSD it is "" for them. Under Windows
     *  the value ".exe" is used.
     *)
    var string: EXECUTABLE_FILE_EXTENSION     is "";

    (**
     *  The extension of the file produced by linking a program.
     *  Normally this is identical to the EXECUTABLE_FILE_EXTENSION,
     *  but in case of Emscripten this is independent from the
     *  EXECUTABLE_FILE_EXTENSION.
     *)
    var string: LINKED_PROGRAM_EXTENSION      is "";

    (**
     *  Path to an INI file with the environment for the C compiler.
     *  If it is "" the C compiler does not need environment settings.
     *)
    var string: CC_ENVIRONMENT_INI            is "";

    (**
     *  Command to call the stand-alone C compiler and linker.
     *  Most IDEs provide also a stand-alone compiler/linker.
     *)
    var string: C_COMPILER                    is "";

    var string: CPLUSPLUS_COMPILER            is "";

    (**
     *  TRUE if C compiler and linker must be called via the shell.
     *  If it is FALSE C compiler and linker processes are started
     *  direct.
     *)
    var boolean: CALL_C_COMPILER_FROM_SHELL   is FALSE;

    var string: C_COMPILER_VERSION            is "";

    (**
     *  C compiler option to add source level debugging information.
     *  With this option source level debugging information is
     *  added to the object file.
     *)
    var array string: CC_OPT_DEBUG_INFO       is 0 times "";

    (**
     *  C compiler option to do link time optimization.
     *  If it is "" the C compiler does not support link time optimization.
     *)
    var string: CC_OPT_LINK_TIME_OPTIMIZATION is "";

    (**
     *  C compiler option to suppress all warnings.
     *)
    var string: CC_OPT_NO_WARNINGS            is "";

    (**
     *  C compiler option to optimize with a level of -O1.
     *)
    var array string: CC_OPT_OPTIMIZE_1       is 0 times "";

    (**
     *  C compiler option to optimize with a level of -O2.
     *)
    var array string: CC_OPT_OPTIMIZE_2       is 0 times "";

    (**
     *  C compiler option to optimize with a level of -O3.
     *)
    var array string: CC_OPT_OPTIMIZE_3       is 0 times "";

    (**
     *  C compiler option to generate traps for signed integer overflow.
     *  An integer overflow in the compiled program will trigger the
     *  signal defined with OVERFLOW_SIGNAL. CC_OPT_TRAP_OVERFLOW is
     *  an empty string, if the C compiler does not support such an
     *  option or if traps would not lead to a performance advantage.
     *)
    var string: CC_OPT_TRAP_OVERFLOW          is "";

    (**
     *  C compiler option to write the C compiler version information.
     *)
    var string: CC_OPT_VERSION_INFO           is "";

    (**
     *  C compiler flags to be used if C programs are compiled.
     *)
    var array string: CC_FLAGS                is 0 times "";

    (**
     *  File descriptor to which the C compiler writes errors.
     *  The MSVC stand-alone C compiler (CL) writes the error
     *  messages to standard output (file descriptor 1).
     *  The C compilers of Linux/Unix/BSD and the compilers from
     *  MinGW and Cygwin write the error messages to the error
     *  output (file descriptor 2).
     *)
    var integer: CC_ERROR_FILEDES             is 0;

    (**
     *  File descriptor to which the C compiler writes its version info.
     *)
    var integer: CC_VERSION_INFO_FILEDES      is 0;

    (**
     *  Linker option to add source level debugging information.
     *  With this option source level debugging information is
     *  added to the executable file. (e.g.: "-Z7" or "-v").
     *  Many compiler/linker combinations don't need this option
     *  to do source level debugging (use "").
     *)
    var string: LINKER_OPT_DEBUG_INFO         is "";

    (**
     *  TRUE if linking always requires the option
     *  CC_OPT_LINK_TIME_OPTIMIZATION.
     *)
    var boolean: LINKER_OPT_LTO_MANDATORY     is FALSE;

    (**
     *  Linker option to be used without source level debugging.
     *  This option can strip debug information (e.g.: "-Wl,--strip-debug").
     *)
    var string: LINKER_OPT_NO_DEBUG_INFO      is "";

    (**
     *  Linker option to provide the output filename (e.g.: "-o ").
     *  If no such option exists the value of LINKER_OPT_OUTPUT_FILE
     *  should be "". In this case it is assumed that the linker
     *  replaces the OBJECT_FILE_EXTENSION of the file with the
     *  LINKED_PROGRAM_EXTENSION.
     *)
    var string: LINKER_OPT_OUTPUT_FILE        is "";

    (**
     *  Linker option that needs to precede the special library.
     *  If no special library exists LINKER_OPT_SPECIAL_LIB is "".
     *)
    var string: LINKER_OPT_SPECIAL_LIB        is "";

    (**
     *  Linker option to specify the stack size of the executable.
     *  The argument for LINKER_OPT_STACK_SIZE is the stack size in
     *  bytes as decimal number. It must follow LINKER_OPT_STACK_SIZE
     *  immediately. The Seed7 compiler uses an argument of either
     *  DEFAULT_STACK_SIZE or the value specified with the -S Seed7
     *  compiler option. If no linker option for the stack size exists
     *  LINKER_OPT_STACK_SIZE is "".
     *)
    var string: LINKER_OPT_STACK_SIZE         is "";

    (**
     *  Standard linker options to link a compiled program.
     *  This contains options, that the linker always uses, and which
     *  are not covered by other LINKER_OPT_... settings.
     *)
    var array string: LINKER_FLAGS            is 0 times "";

    (**
     *  Default stack size for a compiled executable.
     *  This value is used, if the Seed7 compiler is invoked without -S.
     *  If LINKER_OPT_STACK_SIZE exists DEFAULT_STACK_SIZE is used
     *  as argument for the stack size. Additionally DEFAULT_STACK_SIZE
     *  is used as argument for setupStack().
     *)
    var integer: DEFAULT_STACK_SIZE           is 0;

    (**
     *  Options to link system libraries to a compiled program.
     *  This is intended for options to link libraries required by the
     *  Seed7 runtime library. E.g. libraries for socket.
     *)
    var array string: SYSTEM_LIBS             is 0 times "";

    (**
     *  Options to link system bigint libraries to a compiled program.
     *  This is intended for options to link libraries required by the
     *  Seed7 bigint.s7i runtime library (e.g.: "-lgmp").
     *)
    var array string: SYSTEM_BIGINT_LIBS      is 0 times "";

    (**
     *  Options to link system console libraries to a compiled program.
     *  This is intended for options to link libraries required by the
     *  Seed7 console runtime library (e.g.: "-lncurses").
     *)
    var array string: SYSTEM_CONSOLE_LIBS     is 0 times "";

    (**
     *  Options to link system database ibraries to a compiled program.
     *  This is intended for options to link libraries required by the
     *  Seed7 database runtime libraries (e.g.: "-lmysqlclient").
     *)
    var array string: SYSTEM_DATABASE_LIBS    is 0 times "";

    (**
     *  Options to link system graphic libraries to a compiled program.
     *  This is intended for options to link libraries required by the
     *  Seed7 graphic runtime library (e.g.: "-lX11").
     *)
    var array string: SYSTEM_DRAW_LIBS        is 0 times "";

    (**
     *  Options to link system mathematic libraries to a compiled program.
     *  This is intended for options to link libraries required by the
     *  Seed7 math.s7i runtime library. (e.g.: "-lm").
     *)
    var array string: SYSTEM_MATH_LIBS        is 0 times "";

    (**
     *  Name of the Seed7 runtime library (e.g.: "seed7_05.a").
     *)
    var string: SEED7_LIB                     is "";

    (**
     *  Name of the Seed7 graphic runtime library (e.g.: "s7_draw.a").
     *)
    var string: DRAW_LIB                      is "";

    (**
     *  Name of the Seed7 text console runtime library (e.g.: "s7_con.a").
     *)
    var string: CONSOLE_LIB                   is "";

    (**
     *  Name of the Seed7 database runtime library (e.g.: "s7_db.a").
     *)
    var string: DATABASE_LIB                  is "";

    (**
     *  Name of the Seed7 compiler data runtime library (e.g.: "s7_data.a").
     *)
    var string: COMP_DATA_LIB                 is "";

    (**
     *  Name of the Seed7 compiler runtime library (e.g.: "s7_comp.a").
     *)
    var string: COMPILER_LIB                  is "";

    (**
     *  Name of the special library (e.g.: "pre_js.js").
     *)
    var string: SPECIAL_LIB                   is "";

    (**
     *  Directory containing the Seed7 runtime libraries.
     *  This path uses the standard path representation (a slash is used
     *  as path separator and instead of a drive letter like "C:" the
     *  path "/c" is used).
     *)
    var string: S7_LIB_DIR                    is "";

    (**
     *  The current version revision level of interpreter and compiler.
     *  The versioning of Seed7 interpreter and compiler use the
     *  pattern major.minor.revision (e.g.: 5.1.4). The revision
     *  level is incremented automatically with every compilation
     *  of the Seed7 interpreter. This configuration value allows
     *  that interpreter and compiler share the same revision.
     *)
    var integer: VERSION_REVISION_LEVEL       is 0;

    (**
     *  Shell parameter to redirect to the file descriptor 1.
     *  Under Linux/Unix/BSD and Windows this is ">".
     *  The file to which the standard output should be
     *  redirected must be appended. E.g.: >myFile.
     *)
    var string: REDIRECT_FILEDES_1            is "";

    (**
     *  Shell parameter to redirect to the file descriptor 2.
     *  Under Linux/Unix/BSD and Windows this is "2>".
     *  The file to which the error output should be
     *  redirected must be appended. E.g.: 2>myFile.
     *)
    var string: REDIRECT_FILEDES_2            is "";

    (**
     *  Name of the NULL device to be used in shell command redirections.
     *  Under Linux/Unix/BSD this is "/dev/null".
     *  Under Windows this is "NUL:".
     *)
    var string: NULL_DEVICE                   is "";

    (**
     *  The suffix used by the literals of the type ''intType''.
     *)
    var string: INTTYPE_LITERAL_SUFFIX        is "";
  end struct;


const func string: configValue (in string: name)    is action "CMD_CONFIG_VALUE";


(**
 *  Determine the built-in (hard-coded) C compiler configuration values.
 *  @return a structure with the built-in configuration values.
 *)
const func ccConfigType: getBuiltInConfig is func
  result
    var ccConfigType: conf is ccConfigType.value;
  begin
    conf.WITH_STRI_CAPACITY            := boolean(configValue("WITH_STRI_CAPACITY"));
    conf.ALLOW_STRITYPE_SLICES         := boolean(configValue("ALLOW_STRITYPE_SLICES"));
    conf.ALLOW_BSTRITYPE_SLICES        := boolean(configValue("ALLOW_BSTRITYPE_SLICES"));
    conf.RSHIFT_DOES_SIGN_EXTEND       := boolean(configValue("RSHIFT_DOES_SIGN_EXTEND"));
    conf.TWOS_COMPLEMENT_INTTYPE       := boolean(configValue("TWOS_COMPLEMENT_INTTYPE"));
    conf.LITTLE_ENDIAN_INTTYPE         := boolean(configValue("LITTLE_ENDIAN_INTTYPE"));
    conf.FLOAT_COMPARISON_OKAY         := boolean(configValue("FLOAT_COMPARISON_OKAY"));
    conf.POW_FUNCTION_OKAY             := boolean(configValue("POW_FUNCTION_OKAY"));
    conf.FMOD_FUNCTION_OKAY            := boolean(configValue("FMOD_FUNCTION_OKAY"));
    conf.SQRT_FUNCTION_OKAY            := boolean(configValue("SQRT_FUNCTION_OKAY"));
    conf.EXP_FUNCTION_OKAY             := boolean(configValue("EXP_FUNCTION_OKAY"));
    conf.LOG_FUNCTION_OKAY             := boolean(configValue("LOG_FUNCTION_OKAY"));
    conf.LOG10_FUNCTION_OKAY           := boolean(configValue("LOG10_FUNCTION_OKAY"));
    conf.LOG1P_FUNCTION_OKAY           := boolean(configValue("LOG1P_FUNCTION_OKAY"));
    conf.LOG2_FUNCTION_OKAY            := boolean(configValue("LOG2_FUNCTION_OKAY"));
    conf.LDEXP_FUNCTION_OKAY           := boolean(configValue("LDEXP_FUNCTION_OKAY"));
    conf.FREXP_FUNCTION_OKAY           := boolean(configValue("FREXP_FUNCTION_OKAY"));
    conf.HAS_SIGSETJMP                 := boolean(configValue("HAS_SIGSETJMP"));
    conf.CHECK_INT_DIV_BY_ZERO         := boolean(configValue("CHECK_INT_DIV_BY_ZERO"));
    conf.CHECK_INT_DIV_ZERO_BY_ZERO    := boolean(configValue("CHECK_INT_DIV_ZERO_BY_ZERO"));
    conf.CHECK_INT_REM_BY_ZERO         := boolean(configValue("CHECK_INT_REM_BY_ZERO"));
    conf.CHECK_INT_REM_ZERO_BY_ZERO    := boolean(configValue("CHECK_INT_REM_ZERO_BY_ZERO"));
    conf.FLOAT_ZERO_DIV_ERROR          := boolean(configValue("FLOAT_ZERO_DIV_ERROR"));
    conf.CHECK_FLOAT_DIV_BY_ZERO       := boolean(configValue("CHECK_FLOAT_DIV_BY_ZERO"));
    conf.HAS_EXP2                      := boolean(configValue("HAS_EXP2"));
    conf.HAS_EXP10                     := boolean(configValue("HAS_EXP10"));
    conf.HAS_EXPM1                     := boolean(configValue("HAS_EXPM1"));
    conf.HAS_CBRT                      := boolean(configValue("HAS_CBRT"));
    conf.LIMITED_CSTRI_LITERAL_LEN     := boolean(configValue("LIMITED_CSTRI_LITERAL_LEN"));
    conf.SWITCH_WORKS_FOR_INT64TYPE    := boolean(configValue("SWITCH_WORKS_FOR_INT64TYPE"));
    conf.STMT_BLOCK_IN_PARENTHESES_OK  := boolean(configValue("STMT_BLOCK_IN_PARENTHESES_OK"));
    conf.CC_SOURCE_UTF8                := boolean(configValue("CC_SOURCE_UTF8"));
    conf.USE_WMAIN                     := boolean(configValue("USE_WMAIN"));
    conf.USE_WINMAIN                   := boolean(configValue("USE_WINMAIN"));
    conf.USE_START_MAIN                := boolean(configValue("USE_START_MAIN"));
    conf.USE_DO_EXIT                   := boolean(configValue("USE_DO_EXIT"));
    conf.FLOATTYPE_DOUBLE              := boolean(configValue("FLOATTYPE_DOUBLE"));
    conf.INTTYPE_SIZE                  := integer(configValue("INTTYPE_SIZE"));
    conf.FLOATTYPE_SIZE                := integer(configValue("FLOATTYPE_SIZE"));
    conf.POINTER_SIZE                  := integer(configValue("POINTER_SIZE"));
    conf.GENERIC_SIZE                  := max({conf.INTTYPE_SIZE, conf.FLOATTYPE_SIZE, conf.POINTER_SIZE});
    conf.INT_SIZE                      := integer(configValue("INT_SIZE"));
    conf.LONG_SIZE                     := integer(configValue("LONG_SIZE"));
    conf.FLOATTYPE_MANTISSA_BITS       := integer(configValue("FLOATTYPE_MANTISSA_BITS"));
    conf.FLOATTYPE_EXPONENT_OFFSET     := integer(configValue("FLOATTYPE_EXPONENT_OFFSET"));
    conf.INT_RANGE_IN_FLOATTYPE_MAX    := integer(configValue("INT_RANGE_IN_FLOATTYPE_MAX"));
    conf.MINIMUM_TRUNC_ARGUMENT        := integer(configValue("MINIMUM_TRUNC_ARGUMENT"));
    conf.MAXIMUM_TRUNC_ARGUMENT        := integer(configValue("MAXIMUM_TRUNC_ARGUMENT"));
    conf.PIXEL_ALPHA_MASK              := integer(configValue("PIXEL_ALPHA_MASK"), 16);
    conf.PIXEL_RED_MASK                := integer(configValue("PIXEL_RED_MASK"), 16);
    conf.PIXEL_GREEN_MASK              := integer(configValue("PIXEL_GREEN_MASK"), 16);
    conf.PIXEL_BLUE_MASK               := integer(configValue("PIXEL_BLUE_MASK"), 16);
    conf.RGB_TO_PIXEL_FLAG_NAME        := configValue("RGB_TO_PIXEL_FLAG_NAME");
    conf.POINT_LIST_INT_SIZE           := integer(configValue("POINT_LIST_INT_SIZE"));
    conf.POINT_LIST_ABSOLUTE           := boolean(configValue("POINT_LIST_ABSOLUTE"));
    conf.RAND_MULTIPLIER               := integer(configValue("RAND_MULTIPLIER"));
    conf.RAND_INCREMENT                := integer(configValue("RAND_INCREMENT"));
    conf.BOOLTYPE                      := configValue("BOOLTYPE");
    conf.INT32TYPE                     := configValue("INT32TYPE");
    conf.UINT32TYPE                    := configValue("UINT32TYPE");
    conf.INT64TYPE                     := configValue("INT64TYPE");
    conf.UINT64TYPE                    := configValue("UINT64TYPE");
    conf.INT128TYPE                    := configValue("INT128TYPE");
    conf.UINT128TYPE                   := configValue("UINT128TYPE");
    conf.INT32TYPE_LITERAL_SUFFIX      := configValue("INT32TYPE_LITERAL_SUFFIX");
    conf.INT64TYPE_LITERAL_SUFFIX      := configValue("INT64TYPE_LITERAL_SUFFIX");
    conf.MACRO_DEFS                    := configValue("MACRO_DEFS");
    conf.OVERFLOW_SIGNAL               := configValue("OVERFLOW_SIGNAL");
    conf.BUILTIN_ADD_OVERFLOW          := configValue("BUILTIN_ADD_OVERFLOW");
    conf.BUILTIN_SUB_OVERFLOW          := configValue("BUILTIN_SUB_OVERFLOW");
    conf.BUILTIN_MULT_OVERFLOW         := configValue("BUILTIN_MULT_OVERFLOW");
    conf.INT_DIV_OVERFLOW              := integer(configValue("INT_DIV_OVERFLOW"));
    conf.INT_REM_OVERFLOW              := integer(configValue("INT_REM_OVERFLOW"));
    conf.OBJECT_FILE_EXTENSION         := configValue("OBJECT_FILE_EXTENSION");
    conf.LIBRARY_FILE_EXTENSION        := configValue("LIBRARY_FILE_EXTENSION");
    conf.EXECUTABLE_FILE_EXTENSION     := configValue("EXECUTABLE_FILE_EXTENSION");
    conf.LINKED_PROGRAM_EXTENSION      := configValue("LINKED_PROGRAM_EXTENSION");
    conf.CC_ENVIRONMENT_INI            := configValue("CC_ENVIRONMENT_INI");
    conf.C_COMPILER                    := configValue("C_COMPILER");
    conf.CPLUSPLUS_COMPILER            := configValue("CPLUSPLUS_COMPILER");
    conf.CALL_C_COMPILER_FROM_SHELL    := boolean(configValue("CALL_C_COMPILER_FROM_SHELL"));
    conf.C_COMPILER_VERSION            := configValue("C_COMPILER_VERSION");
    conf.CC_OPT_DEBUG_INFO             := noEmptyStrings(split(configValue("CC_OPT_DEBUG_INFO"), ' '));
    conf.CC_OPT_LINK_TIME_OPTIMIZATION := configValue("CC_OPT_LINK_TIME_OPTIMIZATION");
    conf.CC_OPT_NO_WARNINGS            := configValue("CC_OPT_NO_WARNINGS");
    conf.CC_OPT_OPTIMIZE_1             := noEmptyStrings(split(configValue("CC_OPT_OPTIMIZE_1"), ' '));
    conf.CC_OPT_OPTIMIZE_2             := noEmptyStrings(split(configValue("CC_OPT_OPTIMIZE_2"), ' '));
    conf.CC_OPT_OPTIMIZE_3             := noEmptyStrings(split(configValue("CC_OPT_OPTIMIZE_3"), ' '));
    conf.CC_OPT_TRAP_OVERFLOW          := configValue("CC_OPT_TRAP_OVERFLOW");
    conf.CC_OPT_VERSION_INFO           := configValue("CC_OPT_VERSION_INFO");
    conf.CC_FLAGS                      := noEmptyStrings(split(configValue("CC_FLAGS"), ' '));
    conf.CC_ERROR_FILEDES              := integer(configValue("CC_ERROR_FILEDES"));
    conf.CC_VERSION_INFO_FILEDES       := integer(configValue("CC_VERSION_INFO_FILEDES"));
    conf.LINKER_OPT_DEBUG_INFO         := configValue("LINKER_OPT_DEBUG_INFO");
    conf.LINKER_OPT_LTO_MANDATORY      := boolean(configValue("LINKER_OPT_LTO_MANDATORY"));
    conf.LINKER_OPT_NO_DEBUG_INFO      := configValue("LINKER_OPT_NO_DEBUG_INFO");
    conf.LINKER_OPT_OUTPUT_FILE        := configValue("LINKER_OPT_OUTPUT_FILE");
    conf.LINKER_OPT_SPECIAL_LIB        := configValue("LINKER_OPT_SPECIAL_LIB");
    conf.LINKER_OPT_STACK_SIZE         := configValue("LINKER_OPT_STACK_SIZE");
    conf.LINKER_FLAGS                  := noEmptyStrings(split(configValue("LINKER_FLAGS"), ' '));
    conf.DEFAULT_STACK_SIZE            := integer(configValue("DEFAULT_STACK_SIZE"));
    conf.SYSTEM_LIBS                   := noEmptyStrings(split(configValue("SYSTEM_LIBS"), ' '));
    conf.SYSTEM_BIGINT_LIBS            := noEmptyStrings(split(configValue("SYSTEM_BIGINT_LIBS"), '\n'));
    conf.SYSTEM_CONSOLE_LIBS           := noEmptyStrings(split(configValue("SYSTEM_CONSOLE_LIBS"), '\n'));
    conf.SYSTEM_DATABASE_LIBS          := noEmptyStrings(split(configValue("SYSTEM_DATABASE_LIBS"), '\n'));
    conf.SYSTEM_DRAW_LIBS              := noEmptyStrings(split(configValue("SYSTEM_DRAW_LIBS"), '\n'));
    conf.SYSTEM_MATH_LIBS              := noEmptyStrings(split(configValue("SYSTEM_MATH_LIBS"), ' '));
    conf.SEED7_LIB                     := configValue("SEED7_LIB");
    conf.DRAW_LIB                      := configValue("DRAW_LIB");
    conf.CONSOLE_LIB                   := configValue("CONSOLE_LIB");
    conf.DATABASE_LIB                  := configValue("DATABASE_LIB");
    conf.COMP_DATA_LIB                 := configValue("COMP_DATA_LIB");
    conf.COMPILER_LIB                  := configValue("COMPILER_LIB");
    conf.SPECIAL_LIB                   := configValue("SPECIAL_LIB");
    conf.S7_LIB_DIR                    := configValue("S7_LIB_DIR");
    conf.VERSION_REVISION_LEVEL        := integer(configValue("VERSION_REVISION_LEVEL"));
    conf.REDIRECT_FILEDES_1            := configValue("REDIRECT_FILEDES_1");
    conf.REDIRECT_FILEDES_2            := configValue("REDIRECT_FILEDES_2");
    conf.NULL_DEVICE                   := configValue("NULL_DEVICE");
    if conf.INTTYPE_SIZE = 32 then
      conf.INTTYPE_LITERAL_SUFFIX := conf.INT32TYPE_LITERAL_SUFFIX;
    else
      conf.INTTYPE_LITERAL_SUFFIX := conf.INT64TYPE_LITERAL_SUFFIX;
    end if;
    if conf.INT_SIZE = 16 then
      if conf.TWOS_COMPLEMENT_INTTYPE then
        conf.INT_MIN := -32768;
      else
        conf.INT_MIN := -32767;
      end if;
      conf.INT_MAX :=  32767;
    elsif conf.INT_SIZE = 32 then
      if conf.TWOS_COMPLEMENT_INTTYPE then
        conf.INT_MIN := -2147483648;
      else
        conf.INT_MIN := -2147483647;
      end if;
      conf.INT_MAX :=  2147483647;
    elsif conf.INT_SIZE = 64 then
      if conf.TWOS_COMPLEMENT_INTTYPE then
        conf.INT_MIN := -9223372036854775807 - 1;
      else
        conf.INT_MIN := -9223372036854775807;
      end if;
      conf.INT_MAX :=  9223372036854775807;
    end if;
  end func;


(**
 *  Structure with configuration values for C compiler and runtime.
 *)
var ccConfigType: ccConf is getBuiltInConfig;


const proc: assignConfigValue (inout ccConfigType: conf, in string: name, in string: value) is func
  begin
    case name of
      when {"WITH_STRI_CAPACITY"}:            conf.WITH_STRI_CAPACITY            := boolean(value);
      when {"ALLOW_STRITYPE_SLICES"}:         conf.ALLOW_STRITYPE_SLICES         := boolean(value);
      when {"ALLOW_BSTRITYPE_SLICES"}:        conf.ALLOW_BSTRITYPE_SLICES        := boolean(value);
      when {"RSHIFT_DOES_SIGN_EXTEND"}:       conf.RSHIFT_DOES_SIGN_EXTEND       := boolean(value);
      when {"TWOS_COMPLEMENT_INTTYPE"}:       conf.TWOS_COMPLEMENT_INTTYPE       := boolean(value);
      when {"LITTLE_ENDIAN_INTTYPE"}:         conf.LITTLE_ENDIAN_INTTYPE         := boolean(value);
      when {"FLOAT_COMPARISON_OKAY"}:         conf.FLOAT_COMPARISON_OKAY         := boolean(value);
      when {"POW_FUNCTION_OKAY"}:             conf.POW_FUNCTION_OKAY             := boolean(value);
      when {"FMOD_FUNCTION_OKAY"}:            conf.FMOD_FUNCTION_OKAY            := boolean(value);
      when {"SQRT_FUNCTION_OKAY"}:            conf.SQRT_FUNCTION_OKAY            := boolean(value);
      when {"EXP_FUNCTION_OKAY"}:             conf.EXP_FUNCTION_OKAY             := boolean(value);
      when {"LOG_FUNCTION_OKAY"}:             conf.LOG_FUNCTION_OKAY             := boolean(value);
      when {"LOG10_FUNCTION_OKAY"}:           conf.LOG10_FUNCTION_OKAY           := boolean(value);
      when {"LOG1P_FUNCTION_OKAY"}:           conf.LOG1P_FUNCTION_OKAY           := boolean(value);
      when {"LOG2_FUNCTION_OKAY"}:            conf.LOG2_FUNCTION_OKAY            := boolean(value);
      when {"LDEXP_FUNCTION_OKAY"}:           conf.LDEXP_FUNCTION_OKAY           := boolean(value);
      when {"FREXP_FUNCTION_OKAY"}:           conf.FREXP_FUNCTION_OKAY           := boolean(value);
      when {"HAS_SIGSETJMP"}:                 conf.HAS_SIGSETJMP                 := boolean(value);
      when {"CHECK_INT_DIV_BY_ZERO"}:         conf.CHECK_INT_DIV_BY_ZERO         := boolean(value);
      when {"CHECK_INT_DIV_ZERO_BY_ZERO"}:    conf.CHECK_INT_DIV_ZERO_BY_ZERO    := boolean(value);
      when {"CHECK_INT_REM_BY_ZERO"}:         conf.CHECK_INT_REM_BY_ZERO         := boolean(value);
      when {"CHECK_INT_REM_ZERO_BY_ZERO"}:    conf.CHECK_INT_REM_ZERO_BY_ZERO    := boolean(value);
      when {"FLOAT_ZERO_DIV_ERROR"}:          conf.FLOAT_ZERO_DIV_ERROR          := boolean(value);
      when {"CHECK_FLOAT_DIV_BY_ZERO"}:       conf.CHECK_FLOAT_DIV_BY_ZERO       := boolean(value);
      when {"HAS_EXP2"}:                      conf.HAS_EXP2                      := boolean(value);
      when {"HAS_EXP10"}:                     conf.HAS_EXP10                     := boolean(value);
      when {"HAS_EXPM1"}:                     conf.HAS_EXPM1                     := boolean(value);
      when {"HAS_CBRT"}:                      conf.HAS_CBRT                      := boolean(value);
      when {"LIMITED_CSTRI_LITERAL_LEN"}:     conf.LIMITED_CSTRI_LITERAL_LEN     := boolean(value);
      when {"SWITCH_WORKS_FOR_INT64TYPE"}:    conf.SWITCH_WORKS_FOR_INT64TYPE    := boolean(value);
      when {"STMT_BLOCK_IN_PARENTHESES_OK"}:  conf.STMT_BLOCK_IN_PARENTHESES_OK  := boolean(value);
      when {"CC_SOURCE_UTF8"}:                conf.CC_SOURCE_UTF8                := boolean(value);
      when {"USE_WMAIN"}:                     conf.USE_WMAIN                     := boolean(value);
      when {"USE_WINMAIN"}:                   conf.USE_WINMAIN                   := boolean(value);
      when {"USE_START_MAIN"}:                conf.USE_START_MAIN                := boolean(value);
      when {"USE_DO_EXIT"}:                   conf.USE_DO_EXIT                   := boolean(value);
      when {"FLOATTYPE_DOUBLE"}:              conf.FLOATTYPE_DOUBLE              := boolean(value);
      when {"INTTYPE_SIZE"}:                  conf.INTTYPE_SIZE                  := integer(value);
      when {"FLOATTYPE_SIZE"}:                conf.FLOATTYPE_SIZE                := integer(value);
      when {"POINTER_SIZE"}:                  conf.POINTER_SIZE                  := integer(value);
      when {"GENERIC_SIZE"}:                  conf.GENERIC_SIZE                  := integer(value);
      when {"INT_SIZE"}:                      conf.INT_SIZE                      := integer(value);
      when {"LONG_SIZE"}:                     conf.LONG_SIZE                     := integer(value);
      when {"FLOATTYPE_MANTISSA_BITS"}:       conf.FLOATTYPE_MANTISSA_BITS       := integer(value);
      when {"FLOATTYPE_EXPONENT_OFFSET"}:     conf.FLOATTYPE_EXPONENT_OFFSET     := integer(value);
      when {"INT_RANGE_IN_FLOATTYPE_MAX"}:    conf.INT_RANGE_IN_FLOATTYPE_MAX    := integer(value);
      when {"MINIMUM_TRUNC_ARGUMENT"}:        conf.MINIMUM_TRUNC_ARGUMENT        := integer(value);
      when {"MAXIMUM_TRUNC_ARGUMENT"}:        conf.MAXIMUM_TRUNC_ARGUMENT        := integer(value);
      when {"PIXEL_ALPHA_MASK"}:              conf.PIXEL_ALPHA_MASK              := integer(value, 16);
      when {"PIXEL_RED_MASK"}:                conf.PIXEL_RED_MASK                := integer(value, 16);
      when {"PIXEL_GREEN_MASK"}:              conf.PIXEL_GREEN_MASK              := integer(value, 16);
      when {"PIXEL_BLUE_MASK"}:               conf.PIXEL_BLUE_MASK               := integer(value, 16);
      when {"RGB_TO_PIXEL_FLAG_NAME"}:        conf.RGB_TO_PIXEL_FLAG_NAME        := value;
      when {"POINT_LIST_INT_SIZE"}:           conf.POINT_LIST_INT_SIZE           := integer(value);
      when {"POINT_LIST_ABSOLUTE"}:           conf.POINT_LIST_ABSOLUTE           := boolean(value);
      when {"RAND_MULTIPLIER"}:               conf.RAND_MULTIPLIER               := integer(value);
      when {"RAND_INCREMENT"}:                conf.RAND_INCREMENT                := integer(value);
      when {"BOOLTYPE"}:                      conf.BOOLTYPE                      := value;
      when {"INT32TYPE"}:                     conf.INT32TYPE                     := value;
      when {"UINT32TYPE"}:                    conf.UINT32TYPE                    := value;
      when {"INT64TYPE"}:                     conf.INT64TYPE                     := value;
      when {"UINT64TYPE"}:                    conf.UINT64TYPE                    := value;
      when {"INT128TYPE"}:                    conf.INT128TYPE                    := value;
      when {"UINT128TYPE"}:                   conf.UINT128TYPE                   := value;
      when {"INT32TYPE_LITERAL_SUFFIX"}:      conf.INT32TYPE_LITERAL_SUFFIX      := value;
      when {"INT64TYPE_LITERAL_SUFFIX"}:      conf.INT64TYPE_LITERAL_SUFFIX      := value;
      when {"MACRO_DEFS"}:                    conf.MACRO_DEFS                    := value;
      when {"OVERFLOW_SIGNAL"}:               conf.OVERFLOW_SIGNAL               := value;
      when {"BUILTIN_ADD_OVERFLOW"}:          conf.BUILTIN_ADD_OVERFLOW          := value;
      when {"BUILTIN_SUB_OVERFLOW"}:          conf.BUILTIN_SUB_OVERFLOW          := value;
      when {"BUILTIN_MULT_OVERFLOW"}:         conf.BUILTIN_MULT_OVERFLOW         := value;
      when {"INT_DIV_OVERFLOW"}:              conf.INT_DIV_OVERFLOW              := integer(value);
      when {"INT_REM_OVERFLOW"}:              conf.INT_REM_OVERFLOW              := integer(value);
      when {"OBJECT_FILE_EXTENSION"}:         conf.OBJECT_FILE_EXTENSION         := value;
      when {"LIBRARY_FILE_EXTENSION"}:        conf.LIBRARY_FILE_EXTENSION        := value;
      when {"EXECUTABLE_FILE_EXTENSION"}:     conf.EXECUTABLE_FILE_EXTENSION     := value;
      when {"LINKED_PROGRAM_EXTENSION"}:      conf.LINKED_PROGRAM_EXTENSION      := value;
      when {"CC_ENVIRONMENT_INI"}:            conf.CC_ENVIRONMENT_INI            := value;
      when {"C_COMPILER"}:                    conf.C_COMPILER                    := value;
      when {"CPLUSPLUS_COMPILER"}:            conf.CPLUSPLUS_COMPILER            := value;
      when {"CALL_C_COMPILER_FROM_SHELL"}:    conf.CALL_C_COMPILER_FROM_SHELL    := boolean(value);
      when {"C_COMPILER_VERSION"}:            conf.C_COMPILER_VERSION            := value;
      when {"CC_OPT_DEBUG_INFO"}:             conf.CC_OPT_DEBUG_INFO             := noEmptyStrings(split(value, ' '));
      when {"CC_OPT_LINK_TIME_OPTIMIZATION"}: conf.CC_OPT_LINK_TIME_OPTIMIZATION := value;
      when {"CC_OPT_NO_WARNINGS"}:            conf.CC_OPT_NO_WARNINGS            := value;
      when {"CC_OPT_OPTIMIZE_1"}:             conf.CC_OPT_OPTIMIZE_1             := noEmptyStrings(split(value, ' '));
      when {"CC_OPT_OPTIMIZE_2"}:             conf.CC_OPT_OPTIMIZE_2             := noEmptyStrings(split(value, ' '));
      when {"CC_OPT_OPTIMIZE_3"}:             conf.CC_OPT_OPTIMIZE_3             := noEmptyStrings(split(value, ' '));
      when {"CC_OPT_TRAP_OVERFLOW"}:          conf.CC_OPT_TRAP_OVERFLOW          := value;
      when {"CC_OPT_VERSION_INFO"}:           conf.CC_OPT_VERSION_INFO           := value;
      when {"CC_FLAGS"}:                      conf.CC_FLAGS                      := noEmptyStrings(split(value, ' '));
      when {"CC_ERROR_FILEDES"}:              conf.CC_ERROR_FILEDES              := integer(value);
      when {"CC_VERSION_INFO_FILEDES"}:       conf.CC_VERSION_INFO_FILEDES       := integer(value);
      when {"LINKER_OPT_DEBUG_INFO"}:         conf.LINKER_OPT_DEBUG_INFO         := value;
      when {"LINKER_OPT_LTO_MANDATORY"}:      conf.LINKER_OPT_LTO_MANDATORY      := boolean(value);
      when {"LINKER_OPT_NO_DEBUG_INFO"}:      conf.LINKER_OPT_NO_DEBUG_INFO      := value;
      when {"LINKER_OPT_OUTPUT_FILE"}:        conf.LINKER_OPT_OUTPUT_FILE        := value;
      when {"LINKER_OPT_SPECIAL_LIB"}:        conf.LINKER_OPT_SPECIAL_LIB        := value;
      when {"LINKER_OPT_STACK_SIZE"}:         conf.LINKER_OPT_STACK_SIZE         := value;
      when {"LINKER_FLAGS"}:                  conf.LINKER_FLAGS                  := noEmptyStrings(split(value, ' '));
      when {"DEFAULT_STACK_SIZE"}:            conf.DEFAULT_STACK_SIZE            := integer(value);
      when {"SYSTEM_LIBS"}:                   conf.SYSTEM_LIBS                   := noEmptyStrings(split(value, ' '));
      when {"SYSTEM_BIGINT_LIBS"}:            conf.SYSTEM_BIGINT_LIBS            := noEmptyStrings(split(value, '\n'));
      when {"SYSTEM_CONSOLE_LIBS"}:           conf.SYSTEM_CONSOLE_LIBS           := noEmptyStrings(split(value, '\n'));
      when {"SYSTEM_DATABASE_LIBS"}:          conf.SYSTEM_DATABASE_LIBS          := noEmptyStrings(split(value, '\n'));
      when {"SYSTEM_DRAW_LIBS"}:              conf.SYSTEM_DRAW_LIBS              := noEmptyStrings(split(value, '\n'));
      when {"SYSTEM_MATH_LIBS"}:              conf.SYSTEM_MATH_LIBS              := noEmptyStrings(split(value, ' '));
      when {"SEED7_LIB"}:                     conf.SEED7_LIB                     := value;
      when {"DRAW_LIB"}:                      conf.DRAW_LIB                      := value;
      when {"CONSOLE_LIB"}:                   conf.CONSOLE_LIB                   := value;
      when {"DATABASE_LIB"}:                  conf.DATABASE_LIB                  := value;
      when {"COMP_DATA_LIB"}:                 conf.COMP_DATA_LIB                 := value;
      when {"COMPILER_LIB"}:                  conf.COMPILER_LIB                  := value;
      when {"SPECIAL_LIB"}:                   conf.SPECIAL_LIB                   := value;
      when {"S7_LIB_DIR"}:                    conf.S7_LIB_DIR                    := value;
      when {"VERSION_REVISION_LEVEL"}:        conf.VERSION_REVISION_LEVEL        := integer(value);
      when {"REDIRECT_FILEDES_1"}:            conf.REDIRECT_FILEDES_1            := value;
      when {"REDIRECT_FILEDES_2"}:            conf.REDIRECT_FILEDES_2            := value;
      when {"NULL_DEVICE"}:                   conf.NULL_DEVICE                   := value;
      when {"INTTYPE_LITERAL_SUFFIX"}:        conf.INTTYPE_LITERAL_SUFFIX        := value;
      when {"INT_MIN"}:                       conf.INT_MIN                       := integer(value);
      when {"INT_MAX"}:                       conf.INT_MAX                       := integer(value);
      otherwise:
        raise RANGE_ERROR;
    end case
  end func;


const func ccConfigType: readConfig (in string: configFileName) is func
  result
    var ccConfigType: conf is ccConfigType.value;
  local
    var propertyDataType: propertyData is propertyDataType.value;
    var string: name is "";
    var string: value is "";
  begin
    propertyData := readPropertyFile(configFileName);
    for value key name range propertyData do
      assignConfigValue(conf, name, value);
    end for;
  end func;


const func string: determineCCVersion is func
  result
    var string: c_compiler_version is "";
  local
    var array string: redirection is 0 times "";
    var string: ccVersionFile is "cc_version";
    var file: aFile is STD_NULL;
  begin
    ccVersionFile &:= "_" <& rand(0, 999999990) lpad0 9;
    case ccConf.CC_VERSION_INFO_FILEDES of
      when {1}:
        redirection &:= ccConf.REDIRECT_FILEDES_1 & ccVersionFile;
        redirection &:= ccConf.REDIRECT_FILEDES_2 & ccConf.NULL_DEVICE;
      when {2}:
        redirection &:= ccConf.REDIRECT_FILEDES_1 & ccConf.NULL_DEVICE;
        redirection &:= ccConf.REDIRECT_FILEDES_2 & ccVersionFile;
    end case;
    shellCmd(ccConf.C_COMPILER, ccConf.CC_OPT_VERSION_INFO <&
             " " <& join(redirection, " "));
    aFile := open(ccVersionFile, "r");
    if aFile <> STD_NULL then
      c_compiler_version := getln(aFile);
      close(aFile);
    end if;
    if fileType(ccVersionFile) = FILE_REGULAR then
      removeFile(ccVersionFile);
    end if;
  end func;


const func boolean: ccVersionIsOkay is
  return determineCCVersion = ccConf.C_COMPILER_VERSION;