diff --git a/CMakeLists.txt b/CMakeLists.txt index 051ef685b1..0aa9c05e95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1546,9 +1546,35 @@ foreach(_plugin_src_dir ${PLUGIN_SRC_DIRS}) add_subdirectory( ${_plugin_src_dir} ) endforeach() -# Large file support (e.g. make off_t 64 bit if supported) -include(gmxTestLargeFiles) -gmx_test_large_files(GMX_LARGEFILES) +# +# Large file support on UN*X, a/k/a LFS. +# +# On Windows, we require _fseeki64() and _ftelli64(). Visual +# Studio has had supported them since Visual Studio 2005/MSVCR80, +# and we require newer versions, so we know we have them. +# +if(NOT WIN32) + include(FindLFS) + if(LFS_FOUND) + # + # Add the required #defines. + # + add_definitions(${LFS_DEFINITIONS}) + endif() + + # + # Check for fseeko as well. + # + include(FindFseeko) + if(FSEEKO_FOUND) + set(HAVE_FSEEKO ON) + + # + # Add the required #defines. + # + add_definitions(${FSEEKO_DEFINITIONS}) + endif() +endif() set( VERSION ${PROJECT_VERSION} ) if(VCSVERSION_OVERRIDE) diff --git a/cmake/TestFileOffsetBits.c b/cmake/TestFileOffsetBits.c deleted file mode 100644 index 882abb4cfc..0000000000 --- a/cmake/TestFileOffsetBits.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This code was copied from http://www.gromacs.org/ - * and its toplevel COPYING file starts with: - * - * GROMACS is free software, distributed under the GNU General Public License - * (GPL) Version 2. - */ - -#include - -/* detect failure even with -Wno-error on command line */ -#pragma GCC diagnostic error "-Werror" - -int main(int argc, char **argv) -{ - /* Cause a compile-time error if off_t is smaller than 64 bits */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) - int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; - /* silence unused errors */ - (void)off_t_is_large; - (void)argc; - (void)argv; - return 0; -} diff --git a/cmake/TestLargeFiles.c.cmakein b/cmake/TestLargeFiles.c.cmakein deleted file mode 100644 index 2dcf0f3a9b..0000000000 --- a/cmake/TestLargeFiles.c.cmakein +++ /dev/null @@ -1,40 +0,0 @@ -/* - * and its toplevel COPYING file starts with: - * - * GROMACS is free software, distributed under the GNU General Public License - * (GPL) Version 2. - */ - -#cmakedefine _LARGEFILE_SOURCE -#cmakedefine _LARGEFILE64_SOURCE -#cmakedefine _LARGE_FILES -#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ - -/* detect failure even with -Wno-error on command line */ -#pragma GCC diagnostic error "-Werror" - -#include -#include -#include - -int main(int argc, char **argv) -{ - /* Cause a compile-time error if off_t is smaller than 64 bits, - * and make sure we have ftello / fseeko. - */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) - int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; - /* silence unused warnings */ - FILE *fp; - off_t offset; - (void)off_t_is_large; - (void)argc; - (void)argv; - fp = fopen(argv[0],"r"); - offset = ftello( fp ); - - fseeko( fp, offset, SEEK_CUR ); - fclose(fp); - return 0; -} - diff --git a/cmake/modules/FindFseeko.cmake b/cmake/modules/FindFseeko.cmake new file mode 100644 index 0000000000..ca53a5a614 --- /dev/null +++ b/cmake/modules/FindFseeko.cmake @@ -0,0 +1,85 @@ +# CMake support for fseeko +# +# Based on FindLFS.cmake by +# Copyright (C) 2016 Julian Andres Klode . +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# This defines the following variables +# +# FSEEKO_DEFINITIONS - List of definitions to pass to add_definitions() +# FSEEKO_COMPILE_OPTIONS - List of definitions to pass to add_compile_options() +# FSEEKO_LIBRARIES - List of libraries and linker flags +# FSEEKO_FOUND - If there is Large files support +# + +include(CheckCSourceCompiles) +include(FindPackageHandleStandardArgs) +include(CMakePushCheckState) + +# Check for the availability of fseeko() +# The cases handled are: +# +# * Native fseeko() +# * Preprocessor flag -D_LARGEFILE_SOURCE +# +function(_fseeko_check) + set(_fseeko_cppflags) + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS}) + message(STATUS "Looking for native fseeko support") + check_symbol_exists(fseeko stdio.h fseeko_native) + cmake_pop_check_state() + if (fseeko_native) + message(STATUS "Looking for native fseeko support - found") + set(FSEEKO_FOUND TRUE) + else() + message(STATUS "Looking for native fseeko support - not found") + endif() + + if (NOT FSEEKO_FOUND) + # See if it's available with _LARGEFILE_SOURCE. + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS} "-D_LARGEFILE_SOURCE") + check_symbol_exists(fseeko stdio.h fseeko_need_largefile_source) + cmake_pop_check_state() + if (fseeko_need_largefile_source) + message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - found") + set(FSEEKO_FOUND TRUE) + set(_fseeko_cppflags "-D_LARGEFILE_SOURCE") + else() + message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - not found") + endif() + endif() + + set(FSEEKO_DEFINITIONS ${_fseeko_cppflags} CACHE STRING "Extra definitions for fseeko support") + set(FSEEKO_COMPILE_OPTIONS "" CACHE STRING "Extra compiler options for fseeko support") + set(FSEEKO_LIBRARIES "" CACHE STRING "Extra definitions for fseeko support") + set(FSEEKO_FOUND ${FSEEKO_FOUND} CACHE INTERNAL "Found fseeko") +endfunction() + +if (NOT FSEEKO_FOUND) + _fseeko_check() +endif() + +find_package_handle_standard_args(FSEEKO "Could not find fseeko. Set FSEEKO_DEFINITIONS, FSEEKO_COMPILE_OPTIONS, FSEEKO_LIBRARIES." FSEEKO_FOUND) diff --git a/cmake/modules/FindLFS.cmake b/cmake/modules/FindLFS.cmake new file mode 100644 index 0000000000..be5f0d4875 --- /dev/null +++ b/cmake/modules/FindLFS.cmake @@ -0,0 +1,153 @@ +# CMake support for large files +# +# Copyright (C) 2016 Julian Andres Klode . +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# This defines the following variables +# +# LFS_DEFINITIONS - List of definitions to pass to add_definitions() +# LFS_COMPILE_OPTIONS - List of definitions to pass to add_compile_options() +# LFS_LIBRARIES - List of libraries and linker flags +# LFS_FOUND - If there is Large files support +# + +include(CheckCSourceCompiles) +include(FindPackageHandleStandardArgs) +include(CMakePushCheckState) + +# Test program to check for LFS. Requires that off_t has at least 8 byte large +set(_lfs_test_source + " + #include + typedef char my_static_assert[sizeof(off_t) >= 8 ? 1 : -1]; + int main(void) { return 0; } + " +) + +# Check if the given options are needed +# +# This appends to the variables _lfs_cppflags, _lfs_cflags, and _lfs_ldflags, +# it also sets LFS_FOUND to 1 if it works. +function(_lfs_check_compiler_option var options definitions libraries) + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${options}) + set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${definitions}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_DEFINITIONS} ${libraries}) + + message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries}") + check_c_source_compiles("${_lfs_test_source}" ${var}) + cmake_pop_check_state() + + if(${var}) + message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - found") + set(_lfs_cppflags ${_lfs_cppflags} ${definitions} PARENT_SCOPE) + set(_lfs_cflags ${_lfs_cflags} ${options} PARENT_SCOPE) + set(_lfs_ldflags ${_lfs_ldflags} ${libraries} PARENT_SCOPE) + set(LFS_FOUND TRUE PARENT_SCOPE) + else() + message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - not found") + endif() +endfunction() + +# Check for the availability of LFS. +# The cases handled are: +# +# * Native LFS +# * Output of getconf LFS_CFLAGS; getconf LFS_LIBS; getconf LFS_LDFLAGS +# * Preprocessor flag -D_FILE_OFFSET_BITS=64 +# * Preprocessor flag -D_LARGE_FILES +# +function(_lfs_check) + set(_lfs_cflags) + set(_lfs_cppflags) + set(_lfs_ldflags) + set(_lfs_libs) + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + message(STATUS "Looking for native LFS support") + check_c_source_compiles("${_lfs_test_source}" lfs_native) + cmake_pop_check_state() + if (lfs_native) + message(STATUS "Looking for native LFS support - found") + set(LFS_FOUND TRUE) + else() + message(STATUS "Looking for native LFS support - not found") + endif() + + if (NOT LFS_FOUND) + # Check using getconf. If getconf fails, don't worry, the check in + # _lfs_check_compiler_option will fail as well. + execute_process(COMMAND getconf LFS_CFLAGS + OUTPUT_VARIABLE _lfs_cflags_raw + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + execute_process(COMMAND getconf LFS_LIBS + OUTPUT_VARIABLE _lfs_libs_tmp + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + execute_process(COMMAND getconf LFS_LDFLAGS + OUTPUT_VARIABLE _lfs_ldflags_tmp + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + + separate_arguments(_lfs_cflags_raw) + separate_arguments(_lfs_ldflags_tmp) + separate_arguments(_lfs_libs_tmp) + + # Move -D flags to the place they are supposed to be + foreach(flag ${_lfs_cflags_raw}) + if (flag MATCHES "-D.*") + list(APPEND _lfs_cppflags_tmp ${flag}) + else() + list(APPEND _lfs_cflags_tmp ${flag}) + endif() + endforeach() + + # Check if the flags we received (if any) produce working LFS support + _lfs_check_compiler_option(lfs_getconf_works + "${_lfs_cflags_tmp}" + "${_lfs_cppflags_tmp}" + "${_lfs_libs_tmp};${_lfs_ldflags_tmp}") + endif() + + if(NOT LFS_FOUND) # IRIX stuff + _lfs_check_compiler_option(lfs_need_n32 "-n32" "" "") + endif() + if(NOT LFS_FOUND) # Linux and friends + _lfs_check_compiler_option(lfs_need_file_offset_bits "" "-D_FILE_OFFSET_BITS=64" "") + endif() + if(NOT LFS_FOUND) # AIX + _lfs_check_compiler_option(lfs_need_large_files "" "-D_LARGE_FILES=1" "") + endif() + + set(LFS_DEFINITIONS ${_lfs_cppflags} CACHE STRING "Extra definitions for large file support") + set(LFS_COMPILE_OPTIONS ${_lfs_cflags} CACHE STRING "Extra definitions for large file support") + set(LFS_LIBRARIES ${_lfs_libs} ${_lfs_ldflags} CACHE STRING "Extra definitions for large file support") + set(LFS_FOUND ${LFS_FOUND} CACHE INTERNAL "Found LFS") +endfunction() + +if (NOT LFS_FOUND) + _lfs_check() +endif() + +find_package_handle_standard_args(LFS "Could not find LFS. Set LFS_DEFINITIONS, LFS_COMPILE_OPTIONS, LFS_LIBRARIES." LFS_FOUND) diff --git a/cmake/modules/gmxTestLargeFiles.cmake b/cmake/modules/gmxTestLargeFiles.cmake deleted file mode 100644 index 4c131299bc..0000000000 --- a/cmake/modules/gmxTestLargeFiles.cmake +++ /dev/null @@ -1,134 +0,0 @@ -# This code was copied from http://www.gromacs.org/ -# and its toplevel COPYING file starts with: -# -# GROMACS is free software, distributed under the GNU General Public License -# (GPL) Version 2. - -# - Define macro to check large file support -# -# GMX_TEST_LARGE_FILES(VARIABLE) -# -# VARIABLE will be set to true if 64-bit file support is available. -# This macro will also set defines as necessary to enable large file -# support, for instance: -# _LARGE_FILES -# _LARGEFILE_SOURCE -# _FILE_OFFSET_BITS=64 -# -# However, it is YOUR job to make sure these defines are set in a cmakedefine so they -# end up in a config.h file that is included in your source if necessary! - -MACRO(GMX_TEST_LARGE_FILES VARIABLE) - IF(NOT DEFINED ${VARIABLE}) - if(CMAKE_C_COMPILER_ID MATCHES "MSVC") - # - # This is Visual Studio; Visual Studio has supported - # _fseeki64 and _ftelli64 since Visual Studio 2005 / MSVCR80, - # and we require newer versions, so we know we have them. - # - MESSAGE(STATUS "_fseeki64 and _ftelli64 are present") - else(CMAKE_C_COMPILER_ID MATCHES "MSVC") - # - # This is UN*X, or some other Windows compiler. - # - # For UN*X, we do the Large File Support tests, to see - # whether it's present and, if so what we need to define - # to enable it. - # - # XXX - what's the right thing to do on Windows with, - # for example, MinGW? - # - # On most platforms it is probably overkill to first test - # the flags for 64-bit off_t, and then separately fseeko. - # However, in the future we might have 128-bit seek offsets - # to support 128-bit filesystems that allow 128-bit offsets - # (ZFS), so it might be dangerous to indiscriminately set - # e.g. _FILE_OFFSET_BITS=64. - # - MESSAGE(STATUS "Checking for 64-bit off_t") - - # First check without any special flags - TRY_COMPILE(FILE64_OK "${CMAKE_BINARY_DIR}" - "${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c") - if(FILE64_OK) - MESSAGE(STATUS "64-bit off_t is present with no special flags") - endif(FILE64_OK) - - if(NOT FILE64_OK) - # Test with _FILE_OFFSET_BITS=64 - TRY_COMPILE(FILE64_OK "${CMAKE_BINARY_DIR}" - "${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c" - COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" ) - if(FILE64_OK) - MESSAGE(STATUS "64-bit off_t is present with _FILE_OFFSET_BITS=64") - set(_FILE_OFFSET_BITS 64 CACHE INTERNAL "64-bit off_t requires _FILE_OFFSET_BITS=64") - endif(FILE64_OK) - endif(NOT FILE64_OK) - - if(NOT FILE64_OK) - # Test with _LARGE_FILES - TRY_COMPILE(FILE64_OK "${CMAKE_BINARY_DIR}" - "${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c" - COMPILE_DEFINITIONS "-D_LARGE_FILES" ) - if(FILE64_OK) - MESSAGE(STATUS "64-bit off_t is present with _LARGE_FILES") - set(_LARGE_FILES 1 CACHE INTERNAL "64-bit off_t requires _LARGE_FILES") - endif(FILE64_OK) - endif(NOT FILE64_OK) - - if(NOT FILE64_OK) - # Test with _LARGEFILE_SOURCE - TRY_COMPILE(FILE64_OK "${CMAKE_BINARY_DIR}" - "${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c" - COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) - if(FILE64_OK) - MESSAGE(STATUS "64-bit off_t is present with _LARGEFILE_SOURCE") - set(_LARGEFILE_SOURCE 1 CACHE INTERNAL "64-bit off_t requires _LARGEFILE_SOURCE") - endif(FILE64_OK) - endif(NOT FILE64_OK) - - if(NOT FILE64_OK) - MESSAGE(STATUS "64-bit file offset support not available") - else(NOT FILE64_OK) - # Set the flags we might have determined to be required above - configure_file("${CMAKE_SOURCE_DIR}/cmake/TestLargeFiles.c.cmakein" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") - - # - # If this is Windows, assume we have _fseeki64/_ftelli64 - # available. If this is UN*X, check for fseeko/ftello. - # - if(NOT WIN32) - MESSAGE(STATUS "Checking for fseeko/ftello") - # Test if ftello/fseeko are available - TRY_COMPILE(FSEEKO_COMPILE_OK "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") - if(FSEEKO_COMPILE_OK) - MESSAGE(STATUS "Checking for fseeko/ftello - present") - endif(FSEEKO_COMPILE_OK) - - if(NOT FSEEKO_COMPILE_OK) - # glibc 2.2 neds _LARGEFILE_SOURCE for fseeko (but not 64-bit off_t...) - TRY_COMPILE(FSEEKO_COMPILE_OK "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c" - COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) - if(FSEEKO_COMPILE_OK) - MESSAGE(STATUS "Checking for fseeko/ftello - present with _LARGEFILE_SOURCE") - set(_LARGEFILE_SOURCE 1 CACHE INTERNAL "64-bit fseeko requires _LARGEFILE_SOURCE") - endif(FSEEKO_COMPILE_OK) - endif(NOT FSEEKO_COMPILE_OK) - if(FSEEKO_COMPILE_OK) - SET(${VARIABLE} 1 CACHE INTERNAL "Result of test for large file support" FORCE) - set(HAVE_FSEEKO 1 CACHE INTERNAL "64-bit fseeko is available" FORCE) - else(FSEEKO_COMPILE_OK) - MESSAGE(STATUS "Checking for fseeko/ftello - not found") - SET(${VARIABLE} 0 CACHE INTERNAL "Result of test for large file support" FORCE) - endif(FSEEKO_COMPILE_OK) - endif(NOT WIN32) - endif(NOT FILE64_OK) - endif(CMAKE_C_COMPILER_ID MATCHES "MSVC") - ENDIF(NOT DEFINED ${VARIABLE}) -ENDMACRO(GMX_TEST_LARGE_FILES VARIABLE) - - - diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in index 7a664d8c49..c106537cfe 100644 --- a/cmakeconfig.h.in +++ b/cmakeconfig.h.in @@ -325,12 +325,6 @@ /* Build androiddump with libpcap instead of wireshark stuff */ #cmakedefine ANDROIDDUMP_USE_LIBPCAP 1 -/* Large file support */ -#cmakedefine _LARGEFILE_SOURCE -#cmakedefine _LARGEFILE64_SOURCE -#cmakedefine _LARGE_FILES -#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ - /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ /* Note: not use in the code */ diff --git a/tools/checklicenses.py b/tools/checklicenses.py index 5a8dda2ba0..9927f947bd 100755 --- a/tools/checklicenses.py +++ b/tools/checklicenses.py @@ -100,9 +100,6 @@ PATH_SPECIFIC_ALLOWED_LICENSES = { 'epan/except.h': [ 'UNKNOWN', ], - 'cmake/TestFileOffsetBits.c': [ - 'UNKNOWN', - ], # Generated header files by lex/lemon/whatever 'epan/dtd_grammar.h': [ 'UNKNOWN', diff --git a/tools/cppcheck/cppcheck.sh b/tools/cppcheck/cppcheck.sh index e7e4518e71..93fbd31821 100755 --- a/tools/cppcheck/cppcheck.sh +++ b/tools/cppcheck/cppcheck.sh @@ -95,7 +95,7 @@ fi [ "$MODE" = "html" ] && [ "$COLORIZE_HTML_MODE" = "yes" ] || COLORIZE_HTML_MODE="no" if [ "$LAST_COMMITS" -gt 0 ] ; then - TARGET=$( git diff --name-only HEAD~"$LAST_COMMITS".. | grep -E '\.(c|cpp)$' ) + TARGET=$( git diff --name-only --diff-filter=d HEAD~"$LAST_COMMITS".. | grep -E '\.(c|cpp)$' ) if [ -z "${TARGET//[[:space:]]/}" ] ; then >&2 echo "No C or C++ files found in the last $LAST_COMMITS commit(s)." exit_cleanup 0