
(********************************************************************)
(*                                                                  *)
(*  cc_conf.s7i   Configuration values for C compiler and runtime.  *)
(*  Copyright (C) 2013 - 2020  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";


(**
 *  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, a 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, a negative values and NaN.
     *  If it is FALSE fltLog10() should be used instead of log10().
     *)
    var boolean: LOG10_FUNCTION_OKAY          is FALSE;

    (**
     *  TRUE if log2() works okay for zero, a 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 error. The generated
     *  C code should avoid this situation and generate code to
     *  raise the exception NUMERIC_ERROR 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 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 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;

    (**
     *  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 "";

    (**
     *  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 "";

    (**
     *  Standard linker options to link a compiled program.
     *  This is intended for options that specify the stack size or
     *  similar things (e.g.: "-Wl,--gc-sections,--stack,4194304").
     *)
    var array string: LINKER_FLAGS            is 0 times "";

    (**
     *  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 math or socket.
     *)
    var array string: SYSTEM_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 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 additional libraries to a compiled program.
     *  This is intended for options to link libraries required by
     *  the multiprecision library (e.g.: "-lgmp").
     *)
    var array string: ADDITIONAL_SYSTEM_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;
  local
    var string: configValue is "";
  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.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_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.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.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.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_FLAGS                  := noEmptyStrings(split(configValue("LINKER_FLAGS"), ' '));
    conf.SYSTEM_LIBS                   := noEmptyStrings(split(configValue("SYSTEM_LIBS"), ' '));
    conf.SYSTEM_DRAW_LIBS              := noEmptyStrings(split(configValue("SYSTEM_DRAW_LIBS"), ' '));
    conf.SYSTEM_CONSOLE_LIBS           := noEmptyStrings(split(configValue("SYSTEM_CONSOLE_LIBS"), ' '));
    conf.SYSTEM_DATABASE_LIBS          := noEmptyStrings(split(configValue("SYSTEM_DATABASE_LIBS"), '\n'));
    conf.ADDITIONAL_SYSTEM_LIBS        := noEmptyStrings(split(configValue("ADDITIONAL_SYSTEM_LIBS"), '\n'));
    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.
 *)
const ccConfigType: ccConf is getBuiltInConfig;


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;
    cmd_sh(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;
