├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ └── CI_build.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG ├── CMakeLists.txt ├── CMake_Modules └── FindPCRE2.cmake ├── CONTRIBUTING ├── CONTRIBUTORS ├── INSTALL.md ├── LICENSE ├── README.md ├── SECURITY.md ├── build.ps1 ├── cmake_uninstall.cmake.in ├── doc ├── .gitignore ├── CMakeLists.txt └── Doxyfile.in ├── include ├── CMakeLists.txt ├── editorconfig │ ├── editorconfig.h │ └── editorconfig_handle.h └── util.h ├── init.ps1 ├── logo └── logo.png ├── mk-src-archive.sh ├── patch.ps1 ├── src ├── .gitignore ├── CMakeLists.txt ├── bin │ ├── .gitignore │ ├── CMakeLists.txt │ └── main.c ├── config.h.in └── lib │ ├── .gitignore │ ├── CMakeLists.txt │ ├── EditorConfigConfig.cmake.in │ ├── ec_glob.c │ ├── ec_glob.h │ ├── editorconfig.c │ ├── editorconfig.h │ ├── editorconfig.pc.in │ ├── editorconfig_handle.c │ ├── editorconfig_handle.h │ ├── global.h │ ├── ini.c │ ├── ini.h │ ├── misc.c │ ├── misc.h │ └── utarray.h └── test.ps1 /.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = LF 7 | [*.[ch]] 8 | indent_style = space 9 | indent_size = 4 10 | max_line_length = 80 11 | [README.md] 12 | max_line_length = 80 13 | [CMakeLists.txt] 14 | indent_style = space 15 | indent_size = 4 16 | max_line_length = 80 17 | [*.sh] 18 | indent_style = space 19 | indent_size = 2 20 | [*.yml] 21 | indent_style = space 22 | indent_size = 2 23 | [*.ps1] 24 | indent_style = space 25 | indent_size = 4 26 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | # Maintain dependencies for GitHub Actions 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "weekly" 13 | -------------------------------------------------------------------------------- /.github/workflows/CI_build.yml: -------------------------------------------------------------------------------- 1 | name: CI_build 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build_windows: 7 | 8 | runs-on: windows-2022 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | build_configuration: [Release, Debug] 13 | build_platform: [x64, arm64, x86] 14 | build_vsver: [17] 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | submodules: recursive 20 | 21 | - name: Download PCRE2 sources 22 | run: ./init.ps1 -pcre "10.45" 23 | 24 | - name: Build and install PCRE2 25 | run: ./build.ps1 -proj pcre2 -config ${{ matrix.build_configuration }} -arch ${{ matrix.build_platform }} -vsver ${{ matrix.build_vsver }} -init -install 26 | 27 | - name: Build and install editorconfig-core-c 28 | run: ./build.ps1 -proj core -config ${{ matrix.build_configuration }} -arch ${{ matrix.build_platform }} -vsver ${{ matrix.build_vsver }} -init -install 29 | 30 | - name: Run the core tests 31 | if: matrix.build_platform == 'x86' || matrix.build_platform == 'x64' 32 | run: ./test.ps1 -proj core -config ${{ matrix.build_configuration }} -arch ${{ matrix.build_platform }} 33 | 34 | - name: Get short SHA 35 | run: echo "SHORT_SHA=$("${{ github.sha }}".SubString(0, 8))" >> $env:GITHUB_ENV 36 | 37 | - name: zip artifacts for ${{ matrix.build_platform }} on ${{ github.ref_name }} with sha ${{ github.sha }} 38 | if: matrix.build_configuration == 'Release' 39 | run: 7z a editorconfig-core-c_${{ env.SHORT_SHA }}_${{ matrix.build_platform }}.zip .\bin\${{ matrix.build_platform }}-static\build\* 40 | 41 | - name: Archive artifacts for ${{ matrix.build_platform }} 42 | if: matrix.build_configuration == 'Release' 43 | uses: actions/upload-artifact@v4 44 | with: 45 | name: editorconfig-core-c_${{ env.SHORT_SHA }}_${{ matrix.build_platform }}.zip 46 | path: editorconfig-core-c_${{ env.SHORT_SHA }}_${{ matrix.build_platform }}.zip 47 | 48 | - name: Create release on tagging 49 | uses: softprops/action-gh-release@v2 50 | if: startsWith(github.ref, 'refs/tags/') 51 | with: 52 | files: editorconfig-core-c_${{ env.SHORT_SHA }}_${{ matrix.build_platform }}.zip 53 | 54 | 55 | 56 | build_linux: 57 | 58 | runs-on: ubuntu-24.04 59 | strategy: 60 | fail-fast: false 61 | matrix: 62 | compiler: 63 | - { compiler: GNU, CC: gcc-14, CXX: g++-14 } 64 | - { compiler: LLVM, CC: clang-18, CXX: clang++-18 } 65 | build_configuration: [Release, Debug] 66 | build_platform: ["Unix Makefiles"] 67 | 68 | steps: 69 | - uses: actions/checkout@v4 70 | with: 71 | submodules: recursive 72 | 73 | - name: Install packages via apt 74 | run: | 75 | sudo apt-get -qq update 76 | sudo apt-get -qq install -y libpcre2-dev cmake doxygen graphviz 77 | 78 | - name: generate cmake 79 | env: 80 | CC: ${{ matrix.compiler.CC }} 81 | CXX: ${{ matrix.compiler.CXX }} 82 | run: | 83 | mkdir _build 84 | cd _build 85 | cmake -G "${{ matrix.build_platform }}" -DCMAKE_INSTALL_PREFIX=../_install .. 86 | 87 | - name: build cmake 88 | run: | 89 | cd _build 90 | cmake --build . --config ${{ matrix.build_configuration }} --target install 91 | 92 | - name: run tests 93 | run: | 94 | cd _build 95 | ctest -VV --output-on-failure . 96 | 97 | build_macos: 98 | 99 | runs-on: macos-latest 100 | strategy: 101 | fail-fast: false 102 | matrix: 103 | build_configuration: [Release, Debug] 104 | build_platform: ["Unix Makefiles"] 105 | 106 | steps: 107 | - uses: actions/checkout@v4 108 | with: 109 | submodules: recursive 110 | 111 | - name: generate cmake 112 | run: | 113 | mkdir _build 114 | cd _build 115 | cmake -G "${{ matrix.build_platform }}" -DCMAKE_INSTALL_PREFIX=../_install .. 116 | 117 | - name: build cmake 118 | run: | 119 | cd _build 120 | cmake --build . --config ${{ matrix.build_configuration }} --target install 121 | 122 | - name: run tests 123 | run: | 124 | cd _build 125 | ctest -VV --output-on-failure . 126 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by CMake 2 | CMakeCache.txt 3 | CMakeFiles 4 | Makefile 5 | cmake_install.cmake 6 | install_manifest.txt 7 | 8 | # conf file 9 | /cmake_uninstall.cmake 10 | 11 | # Generated by CPack 12 | /CPackConfig.cmake 13 | /CPackSourceConfig.cmake 14 | /_CPack_Packages 15 | 16 | # Generated by CTest 17 | /Testing 18 | CTestTestfile.cmake 19 | 20 | # By `make package` 21 | /editorconfig*.deb 22 | /editorconfig*.rpm 23 | /editorconfig*.sh 24 | /editorconfig*.tar.Z 25 | /editorconfig*.tar.gz 26 | /editorconfig*.zip 27 | 28 | # Generated by `make` 29 | /bin 30 | /lib 31 | 32 | # Eclipse 33 | .project 34 | 35 | # Editor backup/temporary files 36 | ~* 37 | *~ 38 | *.swp 39 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tests"] 2 | path = tests 3 | url = https://github.com/editorconfig/editorconfig-core-test.git 4 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v0.12.9 2 | 3 | - lib/ec_glob: Fix potentially uninitialized variable warning. 4 | 5 | v0.12.8 6 | 7 | - Bump CMake requirement to 3.16.3 8 | - lib/ec_glob: plug leak of nums utarray 9 | - Clarify the steps of building from source. 10 | 11 | v0.12.7 12 | 13 | - Fix pointer overflow in STRING_CAT. 14 | - Fix a few more stack buffer overflows. 15 | - Add license for FindPcre2 from LuaDist. 16 | - Document and CI fixes. 17 | 18 | v0.12.6 19 | 20 | - Update property key, value length limits per spec change. 21 | - Fix potential buffer overflow in ec_glob. 22 | - CI fixes. 23 | - Fix paths in pkg-config file with absolute CMAKE_INSTALL_*. 24 | - Fix cross compiling for Windows. 25 | 26 | v0.12.5 27 | 28 | - Fix memory leak in editorconfig_parse() which would occur if no .editorconfig is found. 29 | 30 | v0.12.4 31 | 32 | - Add Windows build scripts. 33 | - Updated AppVeyor to use new scripts. 34 | 35 | v0.12.3 36 | 37 | - Bump required minimum cmake version to 2.8.12. 38 | - Support pcre2 and drop support for pcre. 39 | 40 | v0.12.2 41 | 42 | - Add support for pkgconfig. 43 | - Memory leaks and crash fixes. 44 | - Improve error messages. 45 | - Add CI on AppVeyor. 46 | 47 | v0.12.1 48 | 49 | - Fix an issue that libeditorconfig calls exit()---this should not be 50 | called in a library function. (#12) 51 | - Bump required minimum cmake version to 2.8.7. 52 | - Use GNU installation dirs for OS portability. (#13) 53 | 54 | v0.12.0 55 | 56 | New dependency: pcre 57 | 58 | - The glob engine is rewritten to take the advantages of pcre; 59 | - support nested curly braces; 60 | - number range match support (e.g. {3...120} matches integers from 3 to 120); 61 | - slashes in brackets are considered special. 62 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists.txt for core testing in 2 | # editorconfig-core-c. 3 | # 4 | # Copyright (c) 2011-2024 EditorConfig Team 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | # POSSIBILITY OF SUCH DAMAGE. 27 | # 28 | 29 | cmake_minimum_required(VERSION 3.16.3) 30 | cmake_policy(VERSION 3.16.3) 31 | 32 | project(editorconfig VERSION "0.12.10" LANGUAGES C) 33 | 34 | set(PROJECT_VERSION_SUFFIX "-development") 35 | 36 | include(GNUInstallDirs) 37 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake_Modules") 38 | 39 | # set default compilation directory 40 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") 41 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") 42 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") 43 | 44 | # uninstall target 45 | configure_file( 46 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" 47 | "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" 48 | IMMEDIATE @ONLY) 49 | 50 | add_custom_target(uninstall 51 | COMMAND ${CMAKE_COMMAND} -P 52 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) 53 | 54 | # package target 55 | set(HOME_URL "https://editorconfig.org") 56 | set(MAILING_LIST "editorconfig@googlegroups.com") 57 | 58 | set(CPACK_PACKAGE_VENDOR "EditorConfig Team") 59 | set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) 60 | set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) 61 | set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) 62 | set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") 63 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") 64 | set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") 65 | set(CPACK_PACKAGE_INSTALL_DIRECTORY "editorconfig") 66 | 67 | if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Mac OS X 68 | set(CPACK_GENERATOR "STGZ;TGZ;TZ") 69 | elseif(UNIX) 70 | # UNIX should be checked before WIN32 since cygwin makes UNIX and WIN32 71 | # both true 72 | set(CPACK_GENERATOR "STGZ;TGZ;TZ;DEB;RPM") 73 | elseif(WIN32) 74 | set(CPACK_GENERATOR "ZIP;NSIS") 75 | endif() 76 | 77 | set(CPACK_MONOLITHIC_INSTALL 1) 78 | set(CPACK_SOURCE_GENERATOR "TGZ;TBZ2") 79 | set(CPACK_PACKAGE_CONTACT "EditorConfig <${MAILING_LIST}>") 80 | set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.md) 81 | set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") 82 | # get the architecture of Deb package. The name of the architecture is not 83 | # always the same with ${CMAKE_SYSTEM_PROCESSOR} 84 | if(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE) 85 | execute_process(COMMAND dpkg --print-architecture 86 | OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE) 87 | set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${arch}") 88 | endif() 89 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${HOME_URL}) 90 | set(CPACK_NSIS_CONTACT ${CPACK_PACKAGE_CONTACT}) 91 | set(CPACK_NSIS_DISPLAY_NAME "EditorConfig Core") 92 | set(CPACK_NSIS_PACKAGE_HOMEPAGE ${HOME_URL}) 93 | set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "editorconfig") 94 | set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) 95 | set(CPACK_RPM_PACKAGE_LICENSE "Simplified BSD license") 96 | set(CPACK_RPM_PACKAGE_URL ${HOME_URL}) 97 | include(CPack) 98 | 99 | add_subdirectory(src) 100 | add_subdirectory(doc) 101 | add_subdirectory(include) 102 | 103 | # Testing. Type "make test" to run tests. Only do this if the test submodule is 104 | # checked out. 105 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt) 106 | enable_testing() 107 | set(EDITORCONFIG_CMD "editorconfig_bin") 108 | set(EDITORCONFIG_CMD_IS_TARGET TRUE) 109 | # TRUE => use the given CMake target, here, "editorconfig_bin", 110 | # rather than an executable file named "editorconfig_bin". 111 | # Used by tests/CMakeLists.txt. 112 | add_subdirectory(tests) 113 | message(STATUS "Tests enabled") 114 | else() 115 | message(WARNING 116 | " Testing files are not found. Testing will not be available. If you obtained the source tree through git, please run `git submodule update --init` to update the tests submodule.") 117 | endif() 118 | 119 | # This is a way to find the EXE name for debugging. However, it issues a 120 | # CMake warning under policy CMP0026. 121 | #get_target_property(out_name editorconfig_bin LOCATION) 122 | #message(STATUS "main: Editorconfig binary will be in -${out_name}-") 123 | -------------------------------------------------------------------------------- /CMake_Modules/FindPCRE2.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Sven Strickroth 2 | # Copyright (C) 2007-2009 LuaDist. 3 | # Created by Peter Kapec 4 | # Redistribution and use of this file is allowed according to the terms of the MIT license. 5 | # For details see the COPYRIGHT file distributed with LuaDist. 6 | # Note: 7 | # Searching headers and libraries is very simple and is NOT as powerful as scripts 8 | # distributed with CMake, because LuaDist defines directories to search for. 9 | # Everyone is encouraged to contact the author with improvements. Maybe this file 10 | # becomes part of CMake distribution sometimes. 11 | 12 | # - Find pcre2 13 | # Find the native PCRE2 headers and libraries. 14 | # 15 | # PCRE2_INCLUDE_DIRS - where to find pcre.h, etc. 16 | # PCRE2_LIBRARIES - List of libraries when using pcre. 17 | # PCRE2_FOUND - True if pcre found. 18 | 19 | # Look for the header file. 20 | FIND_PATH(PCRE2_INCLUDE_DIR NAMES pcre2.h) 21 | 22 | # Look for the library. 23 | FIND_LIBRARY(PCRE2_LIBRARY_RELEASE NAMES pcre2-8 pcre2-8-static) 24 | FIND_LIBRARY(PCRE2_LIBRARY_DEBUG NAMES pcre2-8d pcre2-8-staticd) 25 | 26 | # Handle the QUIETLY and REQUIRED arguments and set PCRE2_FOUND to TRUE if all listed variables are TRUE. 27 | INCLUDE(FindPackageHandleStandardArgs) 28 | INCLUDE(SelectLibraryConfigurations) 29 | 30 | SELECT_LIBRARY_CONFIGURATIONS(PCRE2) 31 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_INCLUDE_DIR) 32 | 33 | # Copy the results to the output variables. 34 | IF(PCRE2_FOUND) 35 | SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY}) 36 | SET(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR}) 37 | ELSE(PCRE2_FOUND) 38 | SET(PCRE2_LIBRARIES) 39 | SET(PCRE2_INCLUDE_DIRS) 40 | ENDIF(PCRE2_FOUND) 41 | 42 | MARK_AS_ADVANCED(PCRE2_INCLUDE_DIRS PCRE2_LIBRARIES) 43 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Thanks for contributing EditorConfig C Core! 2 | 3 | To contribute, please first read through README and https://editorconfig.org to roughly understand 4 | what EditorConfig is for and the role of EditorConfig C Core. 5 | 6 | To make code contribution, you'll need to first fork our git repository, make changes in your 7 | repository, and create a pull request. This is pretty standard for most projects hosted on GitHub. 8 | If you are new to GitHub, take a look at this tutorial: 9 | https://akrabat.com/the-beginners-guide-to-contributing-to-a-github-project/ 10 | 11 | When you make changes, also please remember to update CONTRIBUTORS and CHANGELOG if applicable. -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Contributors to EditorConfig C Core: 2 | 3 | Hong Xu 4 | Ralf Habacker 5 | Trey Hunner 6 | William Swanson 7 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | Runtime Dependency 2 | ================== 3 | 4 | - [PCRE2][] (>= 10.00, since version 0.12.0) 5 | 6 | Installing From a Binary Package 7 | ================================ 8 | 9 | Windows binary packages can be downloaded [here](http://sourceforge.net/projects/editorconfig/files/EditorConfig-C-Core/). 10 | 11 | Windows users can also install EditorConfig core by [Chocolatey](http://chocolatey.org/packages/editorconfig.core). 12 | 13 | Debian (Jessie and later): `apt-get install editorconfig` 14 | 15 | ArchLinux: `pacman -S editorconfig-core-c` 16 | 17 | Fedora: `dnf install editorconfig` 18 | 19 | Mac OS X users can `brew install editorconfig` with [Homebrew](http://brew.sh). 20 | Generally Linux users can also install with [LinuxBrew](https://github.com/Homebrew/linuxbrew) 21 | by `brew install editorconfig`. 22 | 23 | Manually Install from Source 24 | ============================ 25 | 26 | **(To build on Windows: Since it's usually a lot harder to manually build on Windows, see the 27 | section "Automated Build on Windows" for an easier way.)** 28 | 29 | Dependencies 30 | ------------ 31 | 32 | In principle, you should be able to build the source using any C compiler that 33 | is C99 compliant (i.e., virtually any C compiler that is not archaic). Before 34 | installing, you need to install the building tool [cmake][] (version >= 3.16.3) 35 | and dependency [PCRE2][]. To install cmake and pcre with package manager: 36 | 37 | - Arch Linux: `pacman -S cmake pcre2` 38 | - Homebrew on OS X: `brew install cmake pcre2` 39 | - Ubuntu/Debian: `apt-get install cmake libpcre2-dev` 40 | 41 | Make sure cmake is in your PATH environment variable. on Windows, you also need 42 | to build PCRE2 from source. If you want to build the MT version of this library, 43 | after running `cmake .` in the PCRE2 source directory, please replace all 44 | occurrence of "MD" with "MT" in the CMakeCache.txt. 45 | 46 | Obtaining Source 47 | ---------------- 48 | 49 | The easiest way to obtain EditorConfig C core source is using git: 50 | 51 | git clone --recursive https://github.com/editorconfig/editorconfig-core-c.git 52 | 53 | Alternatively, you can download the source tarball/zipfile from [SourceForge][] 54 | and unarchive it. 55 | 56 | Start Building 57 | -------------- 58 | 59 | Switch to the root directory of EditorConfig C core source directory and execute 60 | the following command: 61 | 62 | cmake . 63 | 64 | If successful, the project file will be generated. There are various options 65 | could be used when generating the project file: 66 | 67 | -DBUILD_DOCUMENTATION=[ON|OFF] Default: ON 68 | If this option is on and doxygen is found, the html documentation and 69 | man pages will be generated. 70 | e.g. cmake -DBUILD_DOCUMENTATION=OFF . 71 | 72 | -DBUILD_STATICALLY_LINKED_EXE=[ON|OFF] Default: OFF 73 | If this option is on, the executable will be linked statically to all 74 | libraries. On MSVC, this means that EditorConfig will be statically 75 | linked to the executable. On GCC, this means all libraries (glibc and 76 | EditorConfig) are statically linked to the executable. 77 | e.g. cmake -DBUILD_STATICALLY_LINKED_EXE=ON . 78 | 79 | -DINSTALL_HTML_DOC=[ON|OFF] Default: OFF 80 | If this option is on and BUILD_DOCUMENTATION is on, html documentation 81 | will be installed when execute "make install" or something similar. 82 | e.g. cmake -DINSTALL_HTML_DOC=ON . 83 | 84 | -DDOXYGEN_EXECUTABLE=/path/to/doxygen 85 | If doxygen could not be found automatically and you need to generate 86 | documentation, try to set this option to the path to doxygen. 87 | e.g. cmake -DDOXYGEN_EXECUTABLE=/opt/doxygen/bin/doxygen . 88 | 89 | On UNIX/Linux with gcc, the project file is often a Makefile, in which case you 90 | can type "make" to compile editorconfig. If you are using a different compiler 91 | or platform the compilation command may differ. For example, if you generate an 92 | NMake Makefile and you want to use Microsoft Visual C++ to build editorconfig, 93 | then the build command would be "nmake". 94 | 95 | After the compilation succeeds, use the following command to install (require 96 | root or admin privilege): 97 | 98 | make install 99 | 100 | This command will copy all the files you need to corresponding directories: 101 | editorconfig libraries will be copied to PREFIX/lib and executables will be 102 | copied to PREFIX/bin. 103 | 104 | Note that you have to use ldconfig or change LD_LIBRARY_PATH to specify the 105 | PREFIX/lib as one of the library searching directory on UNIX/Linux to make sure 106 | that source files could be linked to the libraries and executables depending on 107 | these libraries could be executed properly. 108 | 109 | Automated Build on Windows 110 | ========================== 111 | 112 | Requirements on Windows are [Visual Studio] 2015, 2017, 2019 or 2022, [cmake] 3.16.3 or higher and Powershell 3 or higher. For Visual Studio the community edition is sufficient, but the [C++ workload](https://docs.microsoft.com/en-us/cpp/build/vscpp-step-0-installation?view=vs-2017) is required. 113 | 114 | Non-static build is currently not supported. 115 | 116 | Download pcre2 117 | -------------- 118 | 119 | You have to download and extract the pcre2 sources after checkout. 120 | 121 | ```powershell 122 | ~> ./init.ps1 [-pcre "10.45"] 123 | ``` 124 | 125 | Arguments: 126 | 127 | -pcre Optional; pcre2 version to download. 128 | 129 | Build Library 130 | ------------- 131 | 132 | To build pcre2 and editorconfig core library in one step use the `-init` and `-install` arguments at the same time. 133 | 134 | ```powershell 135 | ~> ./build.ps1 -init -install 136 | ``` 137 | 138 | The `-init` argument will generate the required cmake build files for Visual Studio. This is required after initial checkout or `CMakeLists.txt` changes. 139 | The `-install` argument will put the binaries to a location (`bin/$(ARCH)-static/build`) that the editorconfig project can find and link the library. This folder can be used to distribute the build binaries. 140 | For the other arguments please see below. 141 | 142 | ```powershell 143 | ~> ./build.ps1 [-proj all | core | pcre2] [-init] [-install] [-vsver 17 | 16 | 15 | 14 ] [-arch x64 | x86 | arm64] [-config Release | Debug] 144 | ``` 145 | 146 | Arguments: 147 | 148 | -proj Optional; Project to build. 149 | -init Optional; (Re)Generate cmake build files, required first time or on `CMakeLists.txt` changes. 150 | -install Optional; Install to `bin/$(ARCH)-static/build` folder. 151 | -vsver Optional; Visual Studio version (major version number) to use. 152 | -arch Optional; Architecture to build for. 153 | -config Optional; Debug or release build. 154 | 155 | ### Build pcre2 Library 156 | 157 | ```powershell 158 | ~> ./build.ps1 -proj pcre2 -init -install 159 | ``` 160 | 161 | ### Build EditorConfig Core Library 162 | 163 | ```powershell 164 | ~> ./build.ps1 -proj core -init 165 | ``` 166 | 167 | 168 | ### Run Tests 169 | On Windows the test `utf_8_char` is disabled. 170 | 171 | ```powershell 172 | ~> ./test.ps1 [-arch x64 | x86 | arm64] [-config Release | Debug] 173 | ``` 174 | 175 | Arguments: 176 | 177 | -arch Optional; Architecture to build for. 178 | -config Optional; Debug or release build. 179 | 180 | 181 | [cmake]: https://cmake.org 182 | [PCRE2]: https://pcre.org/ 183 | [Visual Studio]: https://visualstudio.microsoft.com 184 | [SourceForge]: https://sourceforge.net/projects/editorconfig/files/EditorConfig-C-Core/ 185 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless otherwise stated, all files are distributed under the Simplified BSD 2 | license. The inih(`src/lib/ini.c` and `src/lib/ini.h`) library is distributed 3 | under the New BSD license. `src/lib/utarray.h` is distributed under the Revised 4 | BSD License. The See LICENSE file for details. Some code in src/lib/misc.c is 5 | distributed under their own license (see the source file for details). 6 | 7 | Copyright (c) 2011-2013 EditorConfig Team, including Hong Xu and Trey Hunner 8 | Copyright (c) 2014 Hong Xu 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | 1. Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimer. 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | POSSIBILITY OF SUCH DAMAGE. 31 | 32 | 33 | Third Party 34 | =========== 35 | 36 | CMake_Modules/FindPCRE2.cmake 37 | 38 | LuaDist License 39 | --------------- 40 | 41 | LuaDist is licensed under the terms of the MIT license reproduced below. 42 | This means that LuaDist is free software and can be used for both academic 43 | and commercial purposes at absolutely no cost. 44 | 45 | Modules and Lua bindings contained in "dist" packages have their 46 | individual copyright. 47 | 48 | =============================================================================== 49 | 50 | Copyright (C) 2007-2010 LuaDist. 51 | 52 | Permission is hereby granted, free of charge, to any person obtaining a copy 53 | of this software and associated documentation files (the "Software"), to deal 54 | in the Software without restriction, including without limitation the rights 55 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 56 | copies of the Software, and to permit persons to whom the Software is 57 | furnished to do so, subject to the following conditions: 58 | 59 | The above copyright notice and this permission notice shall be included in 60 | all copies or substantial portions of the Software. 61 | 62 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 66 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 67 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 68 | THE SOFTWARE. 69 | 70 | =============================================================================== 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [EditorConfig][] 2 | ================ 3 | 4 | [![GitHub release](https://img.shields.io/github/release/editorconfig/editorconfig-core-c.svg)](../../releases/latest) 5 | [![Build Status](https://github.com/editorconfig/editorconfig-core-c/actions/workflows/CI_build.yml/badge.svg)](https://github.com/editorconfig/editorconfig-core-c/actions/workflows/CI_build.yml) 6 | [![Build status](https://ci.appveyor.com/api/projects/status/u9t8m4uech5kejoi/branch/master?svg=true)](https://ci.appveyor.com/project/xuhdev/editorconfig-core-c/branch/master) 7 | 8 | EditorConfig makes it easy to maintain the correct coding style when switching 9 | between different text editors and between different projects. The 10 | EditorConfig project maintains a file format and plugins for various text 11 | editors which allow this file format to be read and used by those editors. For 12 | information on the file format and supported text editors, see the 13 | [EditorConfig website][EditorConfig]. 14 | 15 | 16 | Contributing 17 | ------------ 18 | 19 | This is the README file for the *EditorConfig C Core* codebase. This code 20 | produces a program that accepts a filename as input and will look for 21 | `.editorconfig` files with sections applicable to the given file, outputting 22 | any properties found. 23 | 24 | When developing an editor plugin for reading EditorConfig files, the 25 | EditorConfig core code can be used to locate and parse these files. This means 26 | the file locator, INI parser, and file globbing mechanisms can all be 27 | maintained in one code base, resulting in less code repetition between plugins. 28 | 29 | 30 | Installation 31 | ------------ 32 | 33 | See the [INSTALL.md][] file for instructions. 34 | 35 | Getting Help 36 | ------------ 37 | 38 | For help with the EditorConfig C Core code, please write to our 39 | [mailing list][]. Bugs and feature requests should be submitted to our 40 | [issue tracker][]. If you find any security bugs, please report them at the 41 | [security page][].. 42 | 43 | If you are writing a plugin a language that can import C libraries, you may 44 | want to import and use the EditorConfig library directly. If you do use the 45 | EditorConfig core as a C library, check the [documentation][] for latest stable 46 | version for help. The documentation for latest development version is also 47 | available [online][dev doc]. 48 | 49 | 50 | License 51 | ------- 52 | 53 | Unless otherwise stated, all files are distributed under the Simplified BSD 54 | license. The inih(`src/lib/ini.c` and `src/lib/ini.h`) library is distributed 55 | under the New BSD license. `src/lib/utarray.h` is distributed under the Revised 56 | BSD License. The See LICENSE file for details. Some code in `src/lib/misc.c` is 57 | distributed under their own license (see the source file for details). See the 58 | LICENSE file for details. 59 | 60 | [EditorConfig]: https://editorconfig.org "EditorConfig Homepage" 61 | [INSTALL.md]: https://github.com/editorconfig/editorconfig-core-c/blob/master/INSTALL.md 62 | [mailing list]: http://groups.google.com/group/editorconfig "EditorConfig mailing list" 63 | [issue tracker]: https://github.com/editorconfig/editorconfig-core-c/issues 64 | [documentation]: http://docs.editorconfig.org/ "EditorConfig C Core documentation" 65 | [downloads]: https://sourceforge.net/projects/editorconfig/files/EditorConfig-C-Core/ 66 | [dev doc]: http://docs.editorconfig.org/en/master "EditorConfig C Core latest development version documentation" 67 | [security page]: https://github.com/editorconfig/editorconfig-core-c/security 68 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only the latest release is supported. However, if you use a downstream OS distribution (e.g., Ubuntu, Debian, Fedora, FreeBSD), they may patch out security bugs without following our latest releases. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | Please report them in the [security page](https://github.com/editorconfig/editorconfig-core-c/security/advisories). 10 | -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [ValidateSet("pcre2","core", "all")] 3 | [string] $proj = "all", 4 | 5 | [switch] $init, 6 | 7 | [switch] $install, 8 | 9 | [ValidateSet("ON","OFF")] 10 | [string] $static = "ON", 11 | 12 | [ValidateSet("Debug","Release")] 13 | [string] $config = "Release", 14 | 15 | [ValidateSet("x86","x64","arm64")] 16 | [string] $arch = "x64", 17 | 18 | 19 | [ValidateSet("17","16","15","14")] 20 | [int] $vsver = 15 21 | ) 22 | 23 | $ErrorActionPreference="stop" 24 | 25 | function exec 26 | { 27 | param 28 | ( 29 | [ScriptBlock] $ScriptBlock, 30 | [int[]] $AllowedExitCodes = @(0) 31 | ) 32 | 33 | $backupErrorActionPreference = $script:ErrorActionPreference 34 | 35 | $script:ErrorActionPreference = "Continue" 36 | try 37 | { 38 | & $ScriptBlock 39 | if ($AllowedExitCodes -notcontains $LASTEXITCODE) 40 | { 41 | throw "Execution failed with exit code $LASTEXITCODE" 42 | } 43 | } 44 | finally 45 | { 46 | $script:ErrorActionPreference = $backupErrorActionPreference 47 | } 48 | } 49 | 50 | if ($proj -eq "all"){ 51 | .\build.ps1 -proj pcre2 -init:$init -install:$install -vsver $vsver -arch $arch -config $config -static $static 52 | .\build.ps1 -proj core -init:$init -install:$install -vsver $vsver -arch $arch -config $config -static $static 53 | return 54 | } 55 | 56 | $PREFIX="../build" 57 | 58 | $dest = "bin" 59 | 60 | if ((Test-Path $dest) -ne $true){ 61 | throw "Missing build path! Used init?" 62 | } 63 | 64 | $dest += "\$arch" 65 | 66 | if($static -eq "ON"){ 67 | $dest += "-static" 68 | } 69 | 70 | $dest += "\$proj" 71 | 72 | if ($init) { 73 | "Generating $proj build files" | Write-Host -ForegroundColor DarkGreen 74 | 75 | $gen = "Visual Studio " 76 | 77 | switch ($vsver) { 78 | 17 { 79 | $gen += "17 2022" 80 | } 81 | 16 { 82 | $gen += "16 2019" 83 | } 84 | 15 { 85 | $gen += "15 2017" 86 | } 87 | 14 { 88 | $gen += "14 2015" 89 | } 90 | 12 { 91 | $gen += "12 2013" 92 | } 93 | default { 94 | throw "Visual Studio version $vsver not supported!" 95 | } 96 | } 97 | 98 | $cmake_arch="" 99 | if($arch -eq "x64"){ 100 | $cmake_arch += "x64" 101 | } 102 | elseif($arch -eq "x86"){ 103 | $cmake_arch += "Win32" 104 | } 105 | elseif($arch -eq "arm64"){ 106 | $cmake_arch += "ARM64" 107 | } 108 | 109 | mkdir $dest -ErrorAction SilentlyContinue | Out-Null 110 | Push-Location $dest 111 | try { 112 | $MsvcRuntime = if($static -eq "ON") { "MultiThreaded" } else { "MultiThreadedDLL" } 113 | switch ($proj) { 114 | pcre2 { 115 | $BUILD_SHARED_LIBS = "ON" 116 | if ($static -eq "ON"){ $BUILD_SHARED_LIBS = "OFF"} 117 | exec { cmake -G "$gen" -A $cmake_arch -DCMAKE_INSTALL_PREFIX="$PREFIX" -DPCRE2_STATIC_RUNTIME="$static" -DCMAKE_MSVC_RUNTIME_LIBRARY="$MsvcRuntime" ` 118 | -DBUILD_SHARED_LIBS="$BUILD_SHARED_LIBS" -DPCRE2_BUILD_PCRE2GREP="OFF" -DPCRE2_BUILD_TESTS="OFF" ` 119 | "../../pcre2" } 120 | } 121 | core { 122 | exec { cmake -G "$gen" -A $cmake_arch -DCMAKE_INSTALL_PREFIX="$PREFIX" -DCMAKE_MSVC_RUNTIME_LIBRARY="$MsvcRuntime" -DPCRE2_STATIC="$static" "../../../." } 123 | } 124 | } 125 | } finally { 126 | Pop-Location 127 | } 128 | } 129 | 130 | if ((Test-Path $dest) -ne $true){ 131 | throw "Missing build path! Used init?" 132 | } 133 | 134 | "Compiling $proj" | Write-Host -ForegroundColor DarkGreen 135 | 136 | exec { cmake --build $dest `-- /p:Configuration=$config } 137 | 138 | if ($install) { 139 | "Installing $proj" | Write-Host -ForegroundColor DarkGreen 140 | switch ($proj) { 141 | pcre2 { 142 | exec { cmake --build $dest --target install `-- /p:Configuration=$config } 143 | } 144 | core { 145 | exec { cmake --build $dest --target install `-- /p:Configuration=$config } 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2012 EditorConfig Team 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | # POSSIBILITY OF SUCH DAMAGE. 25 | # 26 | 27 | # Suppress the warning from cmake 2.6 or higher (list command no longer ignores 28 | # empty elements) 29 | if(NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) 30 | cmake_policy(SET CMP0007 NEW) 31 | endif(NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) 32 | 33 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 34 | message(FATAL_ERROR 35 | "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") 36 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 37 | 38 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 39 | string(REGEX REPLACE "\n" ";" files "${files}") 40 | list(REVERSE files) 41 | foreach(file ${files}) 42 | message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") 43 | if(EXISTS "$ENV{DESTDIR}${file}") 44 | execute_process( 45 | COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}" 46 | OUTPUT_VARIABLE rm_out 47 | RESULT_VARIABLE rm_retval) 48 | if(NOT ${rm_retval} EQUAL 0) 49 | message(FATAL_ERROR 50 | "Problem when removing \"$ENV{DESTDIR}${file}\"") 51 | endif(NOT ${rm_retval} EQUAL 0) 52 | else(EXISTS "$ENV{DESTDIR}${file}") 53 | message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") 54 | endif(EXISTS "$ENV{DESTDIR}${file}") 55 | endforeach(file) 56 | 57 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | /Doxyfile 2 | /Doxyfile_cmd 3 | /html 4 | /man 5 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2013 EditorConfig Team 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | # POSSIBILITY OF SUCH DAMAGE. 25 | # 26 | 27 | option(BUILD_DOCUMENTATION 28 | "Use Doxygen to create the HTML and man page documentation" ON) 29 | 30 | # Whether to install the html documentation. Only valid when 31 | # BUILD_DOCUMENTATION is set to ON 32 | option(INSTALL_HTML_DOC 33 | "Install the generated html documentation" OFF) 34 | 35 | if(BUILD_DOCUMENTATION) 36 | 37 | find_package(Doxygen) 38 | 39 | if(DOXYGEN_FOUND) 40 | 41 | # Generating the main part of the doc. Although it generates 42 | # editorconfig.3, we discard that file 43 | set(DOC_MAN_SECTION 3) 44 | set(DOC_GEN_HTML "YES") 45 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 46 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 47 | 48 | add_custom_command( 49 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/html/index.html 50 | COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" 51 | MAIN_DEPENDENCY 52 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 53 | DEPENDS 54 | ${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig.h 55 | ${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig_handle.h 56 | ${PROJECT_SOURCE_DIR}/logo/logo.png 57 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 58 | 59 | set(EC_MANPAGE_DIR ${CMAKE_CURRENT_BINARY_DIR}/man) 60 | set(EC_MANPAGE1_DIR ${EC_MANPAGE_DIR}/man1) 61 | set(EC_MANPAGE3_DIR ${EC_MANPAGE_DIR}/man3) 62 | set(EC_MANPAGE5_DIR ${EC_MANPAGE_DIR}/man5) 63 | 64 | # Generating man page of editorconfig command. Although we have other 65 | # .1s other than editorconfig.1, we ignore them 66 | set(DOC_MAN_SECTION 1) 67 | set(DOC_GEN_HTML "NO") 68 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 69 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-1) 70 | 71 | add_custom_command( 72 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/man/man1/editorconfig.1 73 | COMMAND 74 | ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/man 75 | COMMAND 76 | ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-1" 77 | MAIN_DEPENDENCY 78 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 79 | DEPENDS 80 | ${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig.h 81 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 82 | 83 | # Generating man page editorconfig-format.5. Although we have other 84 | # .5s other than editorconfig-format.5, we ignore them 85 | set(DOC_MAN_SECTION 5) 86 | set(DOC_GEN_HTML "NO") 87 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 88 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-5) 89 | 90 | add_custom_command( 91 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/man/man5/editorconfig-format.5 92 | COMMAND 93 | ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/man 94 | COMMAND 95 | ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-5" 96 | MAIN_DEPENDENCY 97 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 98 | DEPENDS 99 | ${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig.h 100 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 101 | 102 | # doc generation target 103 | add_custom_target(doc ALL DEPENDS 104 | ${CMAKE_CURRENT_BINARY_DIR}/html/index.html 105 | ${EC_MANPAGE1_DIR}/editorconfig.1 106 | ${EC_MANPAGE5_DIR}/editorconfig-format.5) 107 | 108 | # install man pages 109 | # Since we cannot avoid generating editorconfig.3 with doxygen, which 110 | # is the manpage of the command line interface with a manpage number 3, 111 | # we need to exclude it when installing man3. Same for 112 | # editorconfig-format.3 113 | install(DIRECTORY ${EC_MANPAGE3_DIR} 114 | DESTINATION "${CMAKE_INSTALL_MANDIR}" 115 | PATTERN editorconfig.3 EXCLUDE 116 | PATTERN editorconfig-format.3 EXCLUDE 117 | REGEX ._include_. EXCLUDE) 118 | 119 | install(FILES 120 | ${EC_MANPAGE1_DIR}/editorconfig.1 121 | DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") 122 | install(FILES 123 | ${EC_MANPAGE5_DIR}/editorconfig-format.5 124 | DESTINATION "${CMAKE_INSTALL_MANDIR}/man5") 125 | 126 | # "make clean" should also clean generated docs 127 | set_directory_properties(PROPERTIES 128 | ADDITIONAL_MAKE_CLEAN_FILES "html;man") 129 | 130 | if(INSTALL_HTML_DOC) 131 | install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" 132 | DESTINATION "${CMAKE_INSTALL_DOCDIR}") 133 | endif(INSTALL_HTML_DOC) 134 | 135 | else(DOXYGEN_FOUND) 136 | message(WARNING 137 | " Doxygen is not found. Documentation will not be generated.") 138 | endif(DOXYGEN_FOUND) 139 | endif(BUILD_DOCUMENTATION) 140 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2012 EditorConfig Team 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | # POSSIBILITY OF SUCH DAMAGE. 25 | # 26 | 27 | install(FILES 28 | editorconfig/editorconfig.h 29 | editorconfig/editorconfig_handle.h 30 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/editorconfig") 31 | 32 | -------------------------------------------------------------------------------- /include/editorconfig/editorconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | /*! 27 | * @mainpage EditorConfig C Core Documentation 28 | * 29 | * This is the documentation of EditorConfig C Core. In this documentation, you 30 | * could find the document of the @ref editorconfig and the document of 31 | * EditorConfig Core C APIs in editorconfig.h and editorconfig_handle.h. 32 | */ 33 | 34 | /*! 35 | * @page editorconfig EditorConfig Command 36 | * 37 | * @section usage Usage of the `editorconfig` command line tool 38 | * 39 | * Usage: editorconfig [OPTIONS] FILEPATH1 [FILEPATH2 FILEPATH3 ...] 40 | * 41 | * FILEPATH can be a hyphen (-) if you want to path(s) to be read from stdin. 42 | * Hyphen can also be specified with other file names. In this way, both file 43 | * paths from stdin and the paths specified on the command line will be used. 44 | * If more than one path specified on the command line, or the paths are 45 | * reading from stdin (even only one path is read from stdin), the output 46 | * format would be INI format, instead of the simple "key=value" lines. 47 | * 48 | * @htmlonly 49 | * 50 | * 51 | * 52 | * 53 | * 54 | * 55 | * 56 | * 57 | * 58 | * 59 | * 60 | * 61 | * 62 | * 63 | * 64 | * 65 | * 66 | * 67 | * 68 | * 69 | * 70 | * 71 | *
-fSpecify conf filename other than ".editorconfig".
-bSpecify version (used by devs to test compatibility).
-h OR --helpPrint this help message.
--versionDisplay version information.
72 | * @endhtmlonly 73 | * @manonly 74 | * 75 | * \-f Specify conf filename other than ".editorconfig". 76 | * 77 | * \-b Specify version (used by devs to test compatibility). 78 | * 79 | * \-h OR \-\-help Print this help message. 80 | * 81 | * \-\-version Display version information. 82 | * 83 | * @endmanonly 84 | * 85 | * @section related Related Pages 86 | * 87 | * @ref editorconfig-format 88 | * @manonly 89 | * editorconfig-format(5) 90 | * @endmanonly 91 | */ 92 | 93 | /*! 94 | * @page editorconfig-format EditorConfig File Format 95 | * 96 | * @section format EditorConfig File Format 97 | * 98 | * EditorConfig files use an INI format that is compatible with the format used 99 | * by Python ConfigParser Library, but [ and ] are allowed in the section names. 100 | * The section names are filepath globs, similar to the format accepted by 101 | * gitignore. Forward slashes (/) are used as path separators and semicolons (;) 102 | * or octothorpes (#) are used for comments. Comments should go individual lines. 103 | * EditorConfig files should be UTF-8 encoded, with either CRLF or LF line 104 | * separators. 105 | * 106 | * Filename globs containing path separators (/) match filepaths in the same 107 | * way as the filename globs used by .gitignore files. Backslashes (\\) are 108 | * not allowed as path separators. 109 | * 110 | * A semicolon character (;) starts a line comment that terminates at the end 111 | * of the line. Line comments and blank lines are ignored when parsing. 112 | * Comments may be added to the ends of non-empty lines. An octothorpe 113 | * character (#) may be used instead of a semicolon to denote the start of a 114 | * comment. 115 | * 116 | * @section file-location Filename and Location 117 | * 118 | * When a filename is given to EditorConfig a search is performed in the 119 | * directory of the given file and all parent directories for an EditorConfig 120 | * file (named ".editorconfig" by default). All found EditorConfig files are 121 | * searched for sections with section names matching the given filename. The 122 | * search will stop if an EditorConfig file is found with the root property set 123 | * to true or when reaching the root filesystem directory. 124 | * 125 | * Files are read top to bottom and the most recent rules found take 126 | * precedence. If multiple EditorConfig files have matching sections, the rules 127 | * from the closer EditorConfig file are read last, so properties in closer 128 | * files take precedence. 129 | * 130 | * @section patterns Wildcard Patterns 131 | * 132 | * Section names in EditorConfig files are filename globs that support pattern 133 | * matching through Unix shell-style wildcards. These filename globs recognize 134 | * the following as special characters for wildcard matching: 135 | * 136 | * @htmlonly 137 | * 138 | * 139 | * 140 | * 141 | * 142 | * 143 | * 144 | * 145 | *
*Matches any string of characters, except path separators (/)
**Matches any string of characters
?Matches any single character
[seq]Matches any single character in seq
[!seq]Matches any single character not in seq
{s1,s2,s3}Matches any of the strings given (separated by commas, can be nested)
{num1..num2}Matches any integer numbers between num1 and num2, where num1 and num2 can be either positive or negative
146 | * @endhtmlonly 147 | * @manonly 148 | * * Matches any string of characters, except path separators (/) 149 | * 150 | * ** Matches any string of characters 151 | * 152 | * ? Matches any single character 153 | * 154 | * [seq] Matches any single character in seq 155 | * 156 | * [!seq] Matches any single character not in seq 157 | * 158 | * {s1,s2,s3} Matches any of the strings given (separated by commas, can be nested) 159 | * 160 | * {num1..num2} Matches any integer numbers between num1 and num2, where num1 and num2 can be either positive or negative 161 | * 162 | * @endmanonly 163 | * 164 | * The backslash character (\) can be used to escape a character so it is not 165 | * interpreted as a special character. 166 | * 167 | * The maximum length of a section name is 4096 characters. All sections 168 | * exceeding this limit are ignored. 169 | * 170 | * @section properties Supported Properties 171 | * 172 | * EditorConfig file sections contain properties, which are name-value pairs 173 | * separated by an equal sign (=). EditorConfig plugins will ignore unrecognized 174 | * property names and properties with invalid values. 175 | * 176 | * Here is the list of all property names understood by EditorConfig and all valid values for these properties: 177 | * 178 | *
    179 | *
  • indent_style: set to "tab" or "space" to use hard tabs or soft tabs respectively. The values are case insensitive.
  • 180 | *
  • indent_size: a whole number defining the number of columns used for each indentation level and the width of soft tabs (when supported). If this equals to "tab", the indent_size will be set to the tab size, which should be tab_width if tab_width is specified, or the tab size set by editor if tab_width is not specified. The values are case insensitive.
  • 181 | *
  • tab_width: a whole number defining the number of columns used to represent a tab character. This defaults to the value of indent_size and should not usually need to be specified.
  • 182 | *
  • end_of_line: set to "lf", "cr", or "crlf" to control how line breaks are represented. The values are case insensitive.
  • 183 | *
  • charset: set to "latin1", "utf-8", "utf-8-bom", "utf-16be" or "utf-16le" to control the character set. Use of "utf-8-bom" is discouraged.
  • 184 | *
  • trim_trailing_whitespace: set to "true" to remove any whitespace characters preceding newline characters and "false" to ensure it doesn't.
  • 185 | *
  • insert_final_newline: set to "true" ensure file ends with a newline when saving and "false" to ensure it doesn't.
  • 186 | *
  • root: special property that should be specified at the top of the file outside of any sections. Set to "true" to stop .editorconfig files search on current file. The value is case insensitive.
  • 187 | *
188 | * 189 | * For any property, a value of "unset" is to remove the effect of that 190 | * property, even if it has been set before. For example, add "indent_size = 191 | * unset" to undefine indent_size property (and use editor default). 192 | * 193 | * Property names are case insensitive and all property names are lowercased 194 | * when parsing. The maximum length of a property name is 50 characters and the 195 | * maximum length of a property value is 255 characters. Any property beyond 196 | * these limits would be ignored. 197 | */ 198 | 199 | /*! 200 | * @file editorconfig/editorconfig.h 201 | * @brief Header file of EditorConfig. 202 | * 203 | * Related page: @ref editorconfig-format 204 | * @manonly 205 | * editorconfig-format(5) 206 | * @endmanonly 207 | * 208 | * @author EditorConfig Team 209 | */ 210 | 211 | #ifndef EDITORCONFIG_EDITORCONFIG_H__ 212 | #define EDITORCONFIG_EDITORCONFIG_H__ 213 | 214 | /* When included from a user program, EDITORCONFIG_EXPORT may not be defined, 215 | * and we define it here*/ 216 | #ifndef EDITORCONFIG_EXPORT 217 | # define EDITORCONFIG_EXPORT 218 | #endif 219 | 220 | #include 221 | 222 | #ifdef __cplusplus 223 | extern "C" { 224 | #endif 225 | 226 | /*! 227 | * @brief Parse editorconfig files corresponding to the file path given by 228 | * full_filename, and related information is input and output in h. 229 | * 230 | * An example is available at 231 | * src/bin/main.c 232 | * in EditorConfig C Core source code. 233 | * 234 | * @param full_filename The full path of a file that is edited by the editor 235 | * for which the parsing result is. 236 | * 237 | * @param h The @ref editorconfig_handle to be used and returned from this 238 | * function (including the parsing result). The @ref editorconfig_handle should 239 | * be created by editorconfig_handle_init(). 240 | * 241 | * @retval 0 Everything is OK. 242 | * 243 | * @retval "Positive Integer" A parsing error occurs. The return value would be 244 | * the line number of parsing error. err_file obtained from h by calling 245 | * editorconfig_handle_get_err_file() will also be filled with the file path 246 | * that caused the parsing error. 247 | * 248 | * @retval "Negative Integer" Some error occured. See below for the reason of 249 | * the error for each return value. 250 | * 251 | * @retval EDITORCONFIG_PARSE_NOT_FULL_PATH The full_filename is not a full 252 | * path name. 253 | * 254 | * @retval EDITORCONFIG_PARSE_MEMORY_ERROR A memory error occurs. 255 | * 256 | * @retval EDITORCONFIG_PARSE_VERSION_TOO_NEW The required version specified in 257 | * @ref editorconfig_handle is greater than the current version. 258 | * 259 | */ 260 | EDITORCONFIG_EXPORT 261 | int editorconfig_parse(const char* full_filename, editorconfig_handle h); 262 | 263 | /*! 264 | * @brief Get the error message from the error number returned by 265 | * editorconfig_parse(). 266 | * 267 | * An example is available at 268 | * src/bin/main.c 269 | * in EditorConfig C Core source code. 270 | * 271 | * @param err_num The error number that is used to obtain the error message. 272 | * 273 | * @return The error message corresponding to err_num. 274 | */ 275 | EDITORCONFIG_EXPORT 276 | const char* editorconfig_get_error_msg(int err_num); 277 | 278 | /*! 279 | * editorconfig_parse() return value: the full_filename parameter of 280 | * editorconfig_parse() is not a full path name 281 | */ 282 | #define EDITORCONFIG_PARSE_NOT_FULL_PATH (-2) 283 | /*! 284 | * editorconfig_parse() return value: a memory error occurs. 285 | */ 286 | #define EDITORCONFIG_PARSE_MEMORY_ERROR (-3) 287 | /*! 288 | * editorconfig_parse() return value: the required version specified in @ref 289 | * editorconfig_handle is greater than the current version. 290 | */ 291 | #define EDITORCONFIG_PARSE_VERSION_TOO_NEW (-4) 292 | 293 | /*! 294 | * @brief Get the version number of EditorConfig. 295 | * 296 | * An example is available at 297 | * src/bin/main.c 298 | * in EditorConfig C Core source code. 299 | * 300 | * @param major If not null, the integer pointed by major will be filled with 301 | * the major version of EditorConfig. 302 | * 303 | * @param minor If not null, the integer pointed by minor will be filled with 304 | * the minor version of EditorConfig. 305 | * 306 | * @param patch If not null, the integer pointed by patch will be filled 307 | * with the patch version of EditorConfig. 308 | * 309 | * @return None. 310 | */ 311 | EDITORCONFIG_EXPORT 312 | void editorconfig_get_version(int* major, int* minor, int* patch); 313 | 314 | /*! 315 | * @brief Get the version suffix. 316 | * 317 | * @return The version suffix, such as "-development" for a development 318 | * version, empty string for a stable version. 319 | */ 320 | EDITORCONFIG_EXPORT 321 | const char* editorconfig_get_version_suffix(void); 322 | 323 | #ifdef __cplusplus 324 | } 325 | #endif 326 | 327 | #endif /* !EDITORCONFIG_EDITORCONFIG_H__ */ 328 | 329 | -------------------------------------------------------------------------------- /include/editorconfig/editorconfig_handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | /*! 28 | * @file editorconfig/editorconfig_handle.h 29 | * @brief Header file of EditorConfig handle. 30 | * 31 | * @author EditorConfig Team 32 | */ 33 | 34 | #ifndef EDITORCONFIG_EDITORCONFIG_HANDLE_H__ 35 | #define EDITORCONFIG_EDITORCONFIG_HANDLE_H__ 36 | 37 | /* When included from a user program, EDITORCONFIG_EXPORT may not be defined, 38 | * and we define it here*/ 39 | #ifndef EDITORCONFIG_EXPORT 40 | # define EDITORCONFIG_EXPORT 41 | #endif 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | /*! 48 | * @brief The editorconfig handle object type 49 | */ 50 | typedef void* editorconfig_handle; 51 | 52 | /*! 53 | * @brief Create and initialize a default editorconfig_handle object. 54 | * 55 | * @retval NULL Failed to create the editorconfig_handle object. 56 | * 57 | * @retval non-NULL The created editorconfig_handle object is returned. 58 | */ 59 | EDITORCONFIG_EXPORT 60 | editorconfig_handle editorconfig_handle_init(void); 61 | 62 | /*! 63 | * @brief Destroy an editorconfig_handle object 64 | * 65 | * @param h The editorconfig_handle object needs to be destroyed. 66 | * 67 | * @retval zero The editorconfig_handle object is destroyed successfully. 68 | * 69 | * @retval non-zero Failed to destroy the editorconfig_handle object. 70 | */ 71 | EDITORCONFIG_EXPORT 72 | int editorconfig_handle_destroy(editorconfig_handle h); 73 | 74 | /*! 75 | * @brief Get the err_file field of an editorconfig_handle object 76 | * 77 | * @param h The editorconfig_handle object whose err_file needs to be obtained. 78 | * 79 | * @retval NULL No error file exists. 80 | * 81 | * @retval non-NULL The pointer to the path of the file caused the parsing 82 | * error is returned. 83 | */ 84 | EDITORCONFIG_EXPORT 85 | const char* editorconfig_handle_get_err_file(editorconfig_handle h); 86 | 87 | /*! 88 | * @brief Get the version fields of an editorconfig_handle object. 89 | * 90 | * @param h The editorconfig_handle object whose version field need to be 91 | * obtained. 92 | * 93 | * @param major If not null, the integer pointed by major will be filled with 94 | * the major version field of the editorconfig_handle object. 95 | * 96 | * @param minor If not null, the integer pointed by minor will be filled with 97 | * the minor version field of the editorconfig_handle object. 98 | * 99 | * @param patch If not null, the integer pointed by patch will be filled 100 | * with the patch version field of the editorconfig_handle object. 101 | * 102 | * @return None. 103 | */ 104 | EDITORCONFIG_EXPORT 105 | void editorconfig_handle_get_version(const editorconfig_handle h, int* major, 106 | int* minor, int* patch); 107 | 108 | /*! 109 | * @brief Set the version fields of an editorconfig_handle object. 110 | * 111 | * @param h The editorconfig_handle object whose version fields need to be set. 112 | * 113 | * @param major If not less than 0, the major version field will be set to 114 | * major. If this parameter is less than 0, the major version field of the 115 | * editorconfig_handle object will remain unchanged. 116 | * 117 | * @param minor If not less than 0, the minor version field will be set to 118 | * minor. If this parameter is less than 0, the minor version field of the 119 | * editorconfig_handle object will remain unchanged. 120 | * 121 | * @param patch If not less than 0, the patch version field will be set to 122 | * patch. If this parameter is less than 0, the patch version field of the 123 | * editorconfig_handle object will remain unchanged. 124 | * 125 | * @return None. 126 | */ 127 | EDITORCONFIG_EXPORT 128 | void editorconfig_handle_set_version(const editorconfig_handle h, int major, 129 | int minor, int patch); 130 | /*! 131 | * @brief Set the conf_file_name field of an editorconfig_handle object. 132 | * 133 | * @param h The editorconfig_handle object whose conf_file_name field needs to 134 | * be set. 135 | * 136 | * @param conf_file_name The new value of the conf_file_name field of the 137 | * editorconfig_handle object. 138 | * 139 | * @return None. 140 | */ 141 | EDITORCONFIG_EXPORT 142 | void editorconfig_handle_set_conf_file_name(editorconfig_handle h, 143 | const char* conf_file_name); 144 | 145 | /*! 146 | * @brief Get the conf_file_name field of an editorconfig_handle object. 147 | * 148 | * @param h The editorconfig_handle object whose conf_file_name field needs to 149 | * be obtained. 150 | * 151 | * @return The value of the conf_file_name field of the editorconfig_handle 152 | * object. 153 | */ 154 | EDITORCONFIG_EXPORT 155 | const char* editorconfig_handle_get_conf_file_name(const editorconfig_handle h); 156 | 157 | /*! 158 | * @brief Get the nth name and value fields of an editorconfig_handle object. 159 | * 160 | * @param h The editorconfig_handle object whose name and value fields need to 161 | * be obtained. 162 | * 163 | * @param n The zero-based index of the name and value fields to be obtained. 164 | * 165 | * @param name If not null, *name will be set to point to the obtained name. 166 | * 167 | * @param value If not null, *value will be set to point to the obtained value. 168 | * 169 | * @return None. 170 | */ 171 | EDITORCONFIG_EXPORT 172 | void editorconfig_handle_get_name_value(const editorconfig_handle h, int n, 173 | const char** name, const char** value); 174 | 175 | /*! 176 | * @brief Get the count of name and value fields of an editorconfig_handle 177 | * object. 178 | * 179 | * @param h The editorconfig_handle object whose count of name and value fields 180 | * need to be obtained. 181 | * 182 | * @return the count of name and value fields of the editorconfig_handle 183 | * object. 184 | */ 185 | EDITORCONFIG_EXPORT 186 | int editorconfig_handle_get_name_value_count(const editorconfig_handle h); 187 | 188 | #ifdef __cplusplus 189 | } 190 | #endif 191 | 192 | #endif /* !EDITORCONFIG_EDITORCONFIG_HANDLE_H__ */ 193 | 194 | -------------------------------------------------------------------------------- /include/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Hong Xu 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | /* 28 | * Small useful inline functions. 29 | */ 30 | 31 | #ifndef UTIL_H__ 32 | #define UTIL_H__ 33 | 34 | /* 35 | * An version of atoi that handles strings corresponding to integers that are 36 | * out of range. 37 | */ 38 | static inline int ec_atoi(const char* str) 39 | { 40 | return (int) strtol(str, (char **) NULL, 10); 41 | } 42 | 43 | #endif /* !UTIL_H__ */ 44 | -------------------------------------------------------------------------------- /init.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | $pcre="10.45" 3 | ) 4 | 5 | $ErrorActionPreference="Stop" 6 | $dest = "bin" 7 | 8 | if (Test-Path $dest){ 9 | Remove-Item $dest -Recurse -Force -Confirm:$false 10 | } 11 | 12 | New-Item $dest -ItemType Directory -ErrorAction SilentlyContinue | Out-Null 13 | 14 | ##################################################################### 15 | # pcre 16 | ##################################################################### 17 | $url = "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$($pcre)/pcre2-$($pcre).zip" 18 | $output = "$dest\pcre-$($pcre).zip" 19 | 20 | "Downloading pcre2 v$pcre sources" | Write-Host -ForegroundColor DarkGreen 21 | Start-BitsTransfer -Source $url -Destination $output 22 | 23 | "Extracting pcre2 v$pcre sources" | Write-Host -ForegroundColor DarkGreen 24 | Expand-Archive -Path $output -DestinationPath $dest 25 | Rename-Item -Path "$dest\pcre2-$($pcre)" -NewName "pcre2" 26 | 27 | if(Test-Path "pcre-$($pcre).patch") { 28 | "Applying pcre patches" | Write-Host -ForegroundColor DarkGreen 29 | .\patch.ps1 -patch "pcre-$($pcre).patch" -path $dest\pcre2 30 | } 31 | -------------------------------------------------------------------------------- /logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/editorconfig/editorconfig-core-c/71cbdf0f428ca8c6d2d9d3fcdee1d069e194bab5/logo/logo.png -------------------------------------------------------------------------------- /mk-src-archive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Make a source archive for the current EditorConfig version. 4 | 5 | if [ $# -ne 1 ]; then 6 | echo "Usage: "$0" VERSION" 7 | echo "" 8 | echo "e.g. "$0" 0.10.0" 9 | echo 10 | exit 11 | fi 12 | 13 | curl -L https://raw.githubusercontent.com/Kentzo/git-archive-all/master/git_archive_all.py | python - editorconfig-core-c-$*.tar.gz 14 | curl -L https://raw.githubusercontent.com/Kentzo/git-archive-all/master/git_archive_all.py | python - editorconfig-core-c-$*.zip 15 | -------------------------------------------------------------------------------- /patch.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | $path, 3 | $patch 4 | ) 5 | 6 | $ErrorActionPreference="Stop" 7 | $dest = "tools" 8 | 9 | if ((Test-Path $dest) -ne $true){ 10 | New-Item $dest -ItemType Directory | Out-Null 11 | } 12 | 13 | ##################################################################### 14 | # patch 15 | ##################################################################### 16 | if (-ne Test-Path "$dest\bin\patch.exe") { 17 | $url = "http://gnuwin32.sourceforge.net/downlinks/patch-bin-zip.php" 18 | $output = "$dest\patch.zip" 19 | 20 | "Downloading patch binary" | Write-Host -ForegroundColor DarkGreen 21 | Start-BitsTransfer -Source $url -Destination $output 22 | 23 | "Extracting patch binary" | Write-Host -ForegroundColor DarkGreen 24 | Expand-Archive -Path $output -DestinationPath $dest 25 | @" 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | "@ | Out-File -FilePath $dest\bin\patch.exe.manifest -Encoding utf8 39 | (Get-ChildItem $dest\bin\patch.exe).LastWriteTime = Get-Date 40 | } 41 | 42 | Get-Content $patch | & $dest\bin\patch.exe -d $path -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | /auto 2 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2019 EditorConfig Team 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | # POSSIBILITY OF SUCH DAMAGE. 25 | # 26 | 27 | include(CheckFunctionExists) 28 | include(CheckTypeSize) 29 | 30 | option(BUILD_STATICALLY_LINKED_EXE 31 | "Statically link all libraries when building the executable. This will also disable shared library." 32 | OFF) 33 | 34 | if(BUILD_STATICALLY_LINKED_EXE AND NOT WIN32) 35 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 36 | endif() 37 | 38 | find_package(PCRE2 REQUIRED) 39 | 40 | if(PCRE2_FOUND) 41 | include_directories(BEFORE ${PCRE2_INCLUDE_DIRS}) 42 | option(PCRE2_STATIC "Turn this option ON when linking to PCRE2 static library" OFF) 43 | endif() 44 | 45 | # config.h will be generated in src/auto, we should include it. 46 | include_directories(BEFORE 47 | ${CMAKE_CURRENT_BINARY_DIR}/auto) 48 | 49 | check_function_exists(strcasecmp HAVE_STRCASECMP) 50 | check_function_exists(strdup HAVE_STRDUP) 51 | check_function_exists(stricmp HAVE_STRICMP) 52 | check_function_exists(strndup HAVE_STRNDUP) 53 | check_function_exists(strlwr HAVE_STRLWR) 54 | 55 | check_type_size(_Bool HAVE__BOOL) 56 | check_type_size("const char*" HAVE_CONST) 57 | 58 | configure_file( 59 | ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in 60 | ${CMAKE_CURRENT_BINARY_DIR}/auto/config.h) 61 | 62 | include_directories(BEFORE 63 | "${PROJECT_SOURCE_DIR}/include") 64 | 65 | # Use unsigned char to represent plain char 66 | if(MSVC) 67 | add_definitions("-J") 68 | else() 69 | add_definitions("-funsigned-char") 70 | endif() 71 | 72 | add_subdirectory(lib) 73 | add_subdirectory(bin) 74 | 75 | -------------------------------------------------------------------------------- /src/bin/.gitignore: -------------------------------------------------------------------------------- 1 | /editorconfig* 2 | -------------------------------------------------------------------------------- /src/bin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2012 EditorConfig Team 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | # POSSIBILITY OF SUCH DAMAGE. 25 | # 26 | 27 | link_directories(${CMAKE_ARCHIVE_OUTPUT_DIR}) 28 | 29 | set(editorconfig_BINSRCS 30 | main.c) 31 | 32 | # targets 33 | add_executable(editorconfig_bin ${editorconfig_BINSRCS}) 34 | 35 | if(BUILD_STATICALLY_LINKED_EXE) 36 | target_link_libraries(editorconfig_bin editorconfig_static) 37 | if(NOT WIN32) 38 | # Add -static for linker if we want a statically linked executable 39 | target_link_libraries(editorconfig_bin "-static") 40 | 41 | # libpcre2 might be dynamically linked against pthreads (at least on Ubuntu Xenial) 42 | target_link_libraries(editorconfig_bin "-pthread") 43 | endif() 44 | else(BUILD_STATICALLY_LINKED_EXE) 45 | target_link_libraries(editorconfig_bin editorconfig_shared) 46 | endif(BUILD_STATICALLY_LINKED_EXE) 47 | set_target_properties(editorconfig_bin PROPERTIES 48 | OUTPUT_NAME editorconfig 49 | VERSION ${PROJECT_VERSION}) 50 | 51 | install(TARGETS editorconfig_bin 52 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") 53 | 54 | -------------------------------------------------------------------------------- /src/bin/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include "config.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "util.h" 36 | 37 | 38 | static void version(FILE* stream) 39 | { 40 | int major; 41 | int minor; 42 | int patch; 43 | 44 | editorconfig_get_version(&major, &minor, &patch); 45 | 46 | fprintf(stream,"EditorConfig C Core Version %d.%d.%d%s\n", 47 | major, minor, patch, editorconfig_get_version_suffix()); 48 | } 49 | 50 | static void usage(FILE* stream, const char* command) 51 | { 52 | fprintf(stream, "Usage: %s [OPTIONS] FILEPATH1 [FILEPATH2 FILEPATH3 ...]\n", command); 53 | fprintf(stream, "FILEPATH can be a hyphen (-) if you want to path(s) to be read from stdin.\n"); 54 | 55 | fprintf(stream, "\n"); 56 | fprintf(stream, "-f Specify conf filename other than \".editorconfig\".\n"); 57 | fprintf(stream, "-b Specify version (used by devs to test compatibility).\n"); 58 | fprintf(stream, "-h OR --help Print this help message.\n"); 59 | fprintf(stream, "-v OR --version Display version information.\n"); 60 | } 61 | 62 | /* 63 | * Returns strdup(s) and exits if it fails. 64 | */ 65 | static char* xstrdup(const char* s) 66 | { 67 | char* new_s = strdup(s); 68 | if (new_s == NULL) 69 | { 70 | fprintf(stderr, "Unable to allocate memory.\n"); 71 | exit(1); 72 | } 73 | return new_s; 74 | } 75 | 76 | int main(int argc, const char* argv[]) 77 | { 78 | char* full_filename = NULL; 79 | int err_num; 80 | int i; 81 | int name_value_count; 82 | editorconfig_handle eh; 83 | char** file_paths = NULL; 84 | int path_count; /* the count of path input*/ 85 | /* Will be a EditorConfig file name if -f is specified on command line */ 86 | const char* conf_filename = NULL; 87 | 88 | int version_major = -1; 89 | int version_minor = -1; 90 | int version_patch = -1; 91 | 92 | /* File names read from stdin are put in this buffer temporarily */ 93 | char file_line_buffer[FILENAME_MAX + 1]; 94 | 95 | _Bool f_flag = 0; 96 | _Bool b_flag = 0; 97 | 98 | if (argc <= 1) { 99 | version(stderr); 100 | usage(stderr, argv[0]); 101 | exit(1); 102 | } 103 | 104 | for (i = 1; i < argc; ++i) { 105 | 106 | if (b_flag) { 107 | char* pos; 108 | int ver; 109 | int ver_pos = 0; 110 | char* argvi; 111 | 112 | argvi = xstrdup(argv[i]); 113 | 114 | b_flag = 0; 115 | 116 | /* convert the argument -b into a version number */ 117 | pos = strtok(argvi, "."); 118 | 119 | while (pos != NULL) { 120 | ver = ec_atoi(pos); 121 | 122 | switch(ver_pos) { 123 | case 0: 124 | version_major = ver; 125 | break; 126 | case 1: 127 | version_minor = ver; 128 | break; 129 | case 2: 130 | version_patch = ver; 131 | break; 132 | default: 133 | fprintf(stderr, "Invalid version number: %s\n", argv[i]); 134 | exit(1); 135 | } 136 | ++ ver_pos; 137 | 138 | pos = strtok(NULL, "."); 139 | } 140 | 141 | free(argvi); 142 | } else if (f_flag) { 143 | f_flag = 0; 144 | conf_filename = argv[i]; 145 | } else if (strcmp(argv[i], "--version") == 0 || 146 | strcmp(argv[i], "-v") == 0) { 147 | version(stdout); 148 | exit(0); 149 | } else if (strcmp(argv[i], "--help") == 0 || 150 | strcmp(argv[i], "-h") == 0) { 151 | version(stdout); 152 | usage(stdout, argv[0]); 153 | exit(0); 154 | } else if (strcmp(argv[i], "-b") == 0) 155 | b_flag = 1; 156 | else if (strcmp(argv[i], "-f") == 0) 157 | f_flag = 1; 158 | else if (i < argc) { 159 | /* If there are other args left, regard them as file names */ 160 | 161 | path_count = argc - i; 162 | file_paths = (char**) malloc(path_count * sizeof(char*)); 163 | 164 | if (file_paths == NULL) 165 | { 166 | perror("Unable to allocate memory"); 167 | exit(2); 168 | } 169 | 170 | for (; i < argc; ++i) 171 | file_paths[path_count + i - argc] = xstrdup(argv[i]); 172 | } else { 173 | usage(stderr, argv[0]); 174 | exit(1); 175 | } 176 | } 177 | 178 | if (!file_paths) { /* No filename is set */ 179 | usage(stderr, argv[0]); 180 | exit(1); 181 | } 182 | 183 | /* Go through all the files in the argument list */ 184 | for (i = 0; i < path_count; ++i) { 185 | 186 | int j; 187 | 188 | full_filename = file_paths[i]; 189 | 190 | /* Print the file path first, with [], if more than one file is 191 | * specified */ 192 | if (path_count > 1 && strcmp(full_filename, "-")) 193 | printf("[%s]\n", full_filename); 194 | 195 | if (!strcmp(full_filename, "-")) { 196 | int len; 197 | 198 | /* Read a line from stdin. If EOF encountered, continue */ 199 | if (!fgets(file_line_buffer, FILENAME_MAX + 1, stdin)) { 200 | if (!feof(stdin)) 201 | perror("Failed to read stdin"); 202 | 203 | free(full_filename); 204 | continue; 205 | } 206 | 207 | -- i; 208 | 209 | /* trim the trailing space characters */ 210 | len = strlen(file_line_buffer) - 1; 211 | while (len >= 0 && isspace(file_line_buffer[len])) 212 | -- len; 213 | if (len < 0) /* we meet a blank line */ 214 | continue; 215 | file_line_buffer[len + 1] = '\0'; 216 | 217 | full_filename = file_line_buffer; 218 | while (isspace(*full_filename)) 219 | ++ full_filename; 220 | 221 | full_filename = xstrdup(full_filename); 222 | 223 | printf("[%s]\n", full_filename); 224 | } 225 | 226 | /* Initialize the EditorConfig handle */ 227 | eh = editorconfig_handle_init(); 228 | 229 | if (eh == NULL) 230 | { 231 | perror("Unable to create EditorConfig handle"); 232 | exit(3); 233 | } 234 | 235 | /* Set conf file name */ 236 | if (conf_filename) 237 | editorconfig_handle_set_conf_file_name(eh, conf_filename); 238 | 239 | /* Set the version to be compatible with */ 240 | editorconfig_handle_set_version(eh, 241 | version_major, version_minor, version_patch); 242 | 243 | /* parsing the editorconfig files */ 244 | err_num = editorconfig_parse(full_filename, eh); 245 | free(full_filename); 246 | 247 | if (err_num != 0) { 248 | /* print error message */ 249 | fputs(editorconfig_get_error_msg(err_num), stderr); 250 | if (err_num > 0) 251 | fprintf(stderr, ":%d \"%s\"", err_num, 252 | editorconfig_handle_get_err_file(eh)); 253 | fprintf(stderr, "\n"); 254 | exit(1); 255 | } 256 | 257 | /* print the result */ 258 | name_value_count = editorconfig_handle_get_name_value_count(eh); 259 | for (j = 0; j < name_value_count; ++j) { 260 | const char* name; 261 | const char* value; 262 | 263 | editorconfig_handle_get_name_value(eh, j, &name, &value); 264 | printf("%s=%s\n", name, value); 265 | } 266 | 267 | if (editorconfig_handle_destroy(eh) != 0) { 268 | fprintf(stderr, "Failed to destroy editorconfig_handle.\n"); 269 | exit(1); 270 | } 271 | } 272 | 273 | free(file_paths); 274 | 275 | exit(0); 276 | } 277 | 278 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef CONFIG_H__ 28 | #define CONFIG_H__ 29 | 30 | #ifndef UNIX 31 | #cmakedefine UNIX 32 | #endif 33 | 34 | #ifndef WIN32 35 | #cmakedefine WIN32 36 | #endif 37 | 38 | #cmakedefine HAVE_STRCASECMP 39 | #cmakedefine HAVE_STRDUP 40 | #cmakedefine HAVE_STRICMP 41 | #cmakedefine HAVE_STRNDUP 42 | #cmakedefine HAVE_STRLWR 43 | 44 | #cmakedefine HAVE__BOOL 45 | 46 | #cmakedefine HAVE_CONST 47 | 48 | #ifndef HAVE_CONST 49 | # define const 50 | #endif 51 | 52 | #cmakedefine CMAKE_COMPILER_IS_GNUCC 53 | #cmakedefine MSVC 54 | 55 | #cmakedefine PCRE2_STATIC 56 | #define PCRE2_CODE_UNIT_WIDTH 8 57 | 58 | /* For gcc, we define _GNU_SOURCE to use gcc extensions */ 59 | #ifdef CMAKE_COMPILER_IS_GNUCC 60 | # ifndef _GNU_SOURCE 61 | # define _GNU_SOURCE 62 | # endif /* _GNU_SOURCE */ 63 | #endif /* CMAKE_COMPILER_IS_GNUCC */ 64 | 65 | #ifdef MSVC 66 | # define _CRT_SECURE_NO_WARNINGS 1 67 | # pragma warning(disable: 4996) 68 | #endif 69 | 70 | /* _Bool type */ 71 | #ifndef HAVE__BOOL 72 | # define _Bool signed char 73 | #endif 74 | 75 | #define EC_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ 76 | #define EC_VERSION_MINOR @PROJECT_VERSION_MINOR@ 77 | #define EC_VERSION_PATCH @PROJECT_VERSION_PATCH@ 78 | #define EC_VERSION_SUFFIX "@PROJECT_VERSION_SUFFIX@" 79 | 80 | 81 | #endif /* !CONFIG_H__ */ 82 | -------------------------------------------------------------------------------- /src/lib/.gitignore: -------------------------------------------------------------------------------- 1 | /editorconfig.dll 2 | /editorconfig_static.lib 3 | /libeditorconfig.so* 4 | /libeditorconfig_static.a 5 | -------------------------------------------------------------------------------- /src/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2019 EditorConfig Team 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | # POSSIBILITY OF SUCH DAMAGE. 25 | # 26 | 27 | set(editorconfig_LIBSRCS 28 | ec_glob.c 29 | editorconfig.c 30 | editorconfig_handle.c 31 | ini.c 32 | misc.c 33 | ) 34 | 35 | add_library(editorconfig_shared SHARED ${editorconfig_LIBSRCS}) 36 | target_include_directories(editorconfig_shared 37 | INTERFACE $ 38 | ) 39 | set_target_properties(editorconfig_shared PROPERTIES 40 | OUTPUT_NAME editorconfig 41 | SOVERSION 0 42 | VERSION ${PROJECT_VERSION}) 43 | 44 | # We need to link Shwapi since we use PathIsRelative 45 | if(WIN32) 46 | target_link_libraries(editorconfig_shared shlwapi) 47 | endif() 48 | target_link_libraries(editorconfig_shared ${PCRE2_LIBRARIES}) 49 | if (BUILD_STATICALLY_LINKED_EXE) 50 | # disable shared library build when static is enabled 51 | set_target_properties(editorconfig_shared PROPERTIES 52 | EXCLUDE_FROM_ALL 1) 53 | endif() 54 | 55 | add_library(editorconfig_static STATIC ${editorconfig_LIBSRCS}) 56 | target_include_directories(editorconfig_static 57 | INTERFACE $ 58 | ) 59 | set_target_properties(editorconfig_static PROPERTIES 60 | OUTPUT_NAME editorconfig_static 61 | VERSION ${PROJECT_VERSION}) 62 | 63 | # We need to link Shwapi since we use PathIsRelative 64 | if(WIN32) 65 | target_link_libraries(editorconfig_static shlwapi) 66 | endif() 67 | target_link_libraries(editorconfig_static ${PCRE2_LIBRARIES}) 68 | 69 | # EditorConfig package name for find_package() and the CMake package registry. 70 | # On UNIX the system registry is usually just "lib/cmake/". 71 | # See cmake-package(7) for details. 72 | set(config_package_name "EditorConfig") 73 | set(editorconfig_CONFIG_NAME "${config_package_name}Config") 74 | set(editorconfig_CONFIG_VERSION_NAME "${config_package_name}ConfigVersion") 75 | set(editorconfig_CONFIG_EXPORT_NAME "${config_package_name}Targets") 76 | set(editorconfig_CONFIG_INSTALL_LIBDIR 77 | "${CMAKE_INSTALL_LIBDIR}/cmake/${config_package_name}") 78 | 79 | install(TARGETS editorconfig_static 80 | EXPORT ${editorconfig_CONFIG_EXPORT_NAME} 81 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 82 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 83 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) 84 | 85 | if(NOT BUILD_STATICALLY_LINKED_EXE) 86 | install(TARGETS editorconfig_shared 87 | EXPORT ${editorconfig_CONFIG_EXPORT_NAME} 88 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 89 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 90 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) 91 | endif() 92 | 93 | if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") 94 | set(libdir_for_pc_file "${CMAKE_INSTALL_LIBDIR}") 95 | else() 96 | set(libdir_for_pc_file "\${prefix}/${CMAKE_INSTALL_LIBDIR}") 97 | endif() 98 | if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") 99 | set(includedir_for_pc_file "${CMAKE_INSTALL_INCLUDEDIR}") 100 | else() 101 | set(includedir_for_pc_file "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") 102 | endif() 103 | configure_file( 104 | ${CMAKE_CURRENT_SOURCE_DIR}/editorconfig.pc.in 105 | ${CMAKE_CURRENT_BINARY_DIR}/editorconfig.pc 106 | @ONLY) 107 | 108 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/editorconfig.pc 109 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) 110 | 111 | include(CMakePackageConfigHelpers) 112 | 113 | configure_package_config_file(${editorconfig_CONFIG_NAME}.cmake.in 114 | ${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_NAME}.cmake 115 | INSTALL_DESTINATION ${editorconfig_CONFIG_INSTALL_LIBDIR}) 116 | 117 | write_basic_package_version_file( 118 | ${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_VERSION_NAME}.cmake 119 | COMPATIBILITY AnyNewerVersion) 120 | 121 | install(FILES 122 | ${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_NAME}.cmake 123 | ${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_VERSION_NAME}.cmake 124 | DESTINATION ${editorconfig_CONFIG_INSTALL_LIBDIR}) 125 | 126 | install(EXPORT ${editorconfig_CONFIG_EXPORT_NAME} 127 | DESTINATION ${editorconfig_CONFIG_INSTALL_LIBDIR}) 128 | -------------------------------------------------------------------------------- /src/lib/EditorConfigConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/@editorconfig_CONFIG_EXPORT_NAME@.cmake") 4 | -------------------------------------------------------------------------------- /src/lib/ec_glob.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Hong Xu 3 | * Copyright (c) 2018 Sven Strickroth 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "global.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #define utarray_oom() { return -2; } 36 | #include "utarray.h" 37 | #include "misc.h" 38 | #include "util.h" 39 | 40 | #include "ec_glob.h" 41 | 42 | /* Special characters */ 43 | const char ec_special_chars[] = "?[]\\*-{},"; 44 | 45 | typedef struct int_pair 46 | { 47 | int num1; 48 | int num2; 49 | } int_pair; 50 | static const UT_icd ut_int_pair_icd = {sizeof(int_pair),NULL,NULL,NULL}; 51 | 52 | /* concatenate the string then move the pointer to the end */ 53 | #define STRING_CAT(p, string, end) do { \ 54 | size_t string_len = strlen(string); \ 55 | assert(end > p); \ 56 | if (string_len >= (size_t)(end - p)) { \ 57 | ret = -1; \ 58 | goto cleanup; \ 59 | } \ 60 | strcat(p, string); \ 61 | p += string_len; \ 62 | } while(0) 63 | 64 | /* safely add a char to a string then move the pointer to the end */ 65 | #define ADD_CHAR(string, new_chr, end) do { \ 66 | if (string + 1 >= end) { \ 67 | ret = -1; \ 68 | goto cleanup; \ 69 | } \ 70 | *(string ++) = new_chr; \ 71 | } while(0) 72 | 73 | #define PATTERN_MAX 4097 74 | /* 75 | * Whether the string matches the given glob pattern. Return 0 if successful, return -1 if a PCRE 76 | * error or other regex error occurs, and return -2 if an OOM outside PCRE occurs. 77 | */ 78 | EDITORCONFIG_LOCAL 79 | int ec_glob(const char *pattern, const char *string) 80 | { 81 | size_t i; 82 | int_pair * p; 83 | char * c; 84 | char pcre_str[2 * PATTERN_MAX] = "^"; 85 | char * p_pcre; 86 | char * pcre_str_end; 87 | int brace_level = 0; 88 | _Bool is_in_bracket = 0; 89 | int error_code; 90 | size_t erroffset; 91 | pcre2_code * re; 92 | int rc; 93 | size_t * pcre_result; 94 | pcre2_match_data * pcre_match_data = NULL; 95 | char l_pattern[2 * PATTERN_MAX]; 96 | _Bool are_braces_paired = 1; 97 | UT_array * nums; /* number ranges */ 98 | int ret = 0; 99 | 100 | strcpy(l_pattern, pattern); 101 | p_pcre = pcre_str + 1; 102 | pcre_str_end = pcre_str + 2 * PATTERN_MAX; 103 | 104 | /* Determine whether curly braces are paired */ 105 | { 106 | int left_count = 0; 107 | int right_count = 0; 108 | for (c = l_pattern; *c; ++ c) 109 | { 110 | if (*c == '\\' && *(c+1) != '\0') 111 | { 112 | ++ c; 113 | continue; 114 | } 115 | 116 | if (*c == '}') 117 | ++ right_count; 118 | else if (*c == '{') 119 | ++ left_count; 120 | 121 | if (right_count > left_count) 122 | { 123 | are_braces_paired = 0; 124 | break; 125 | } 126 | } 127 | 128 | if (right_count != left_count) 129 | are_braces_paired = 0; 130 | } 131 | 132 | /* used to search for {num1..num2} case */ 133 | re = pcre2_compile("^\\{[\\+\\-]?\\d+\\.\\.[\\+\\-]?\\d+\\}$", PCRE2_ZERO_TERMINATED, 0, 134 | &error_code, &erroffset, NULL); 135 | if (!re) /* failed to compile */ 136 | return -1; 137 | 138 | utarray_new(nums, &ut_int_pair_icd); 139 | 140 | for (c = l_pattern; *c; ++ c) 141 | { 142 | switch (*c) 143 | { 144 | case '\\': /* also skip the next one */ 145 | if (*(c+1) != '\0') 146 | { 147 | ADD_CHAR(p_pcre, *(c++), pcre_str_end); 148 | ADD_CHAR(p_pcre, *c, pcre_str_end); 149 | } 150 | else 151 | STRING_CAT(p_pcre, "\\\\", pcre_str_end); 152 | 153 | break; 154 | case '?': 155 | STRING_CAT(p_pcre, "[^/]", pcre_str_end); 156 | break; 157 | case '*': 158 | if (*(c+1) == '*') /* case of ** */ 159 | { 160 | STRING_CAT(p_pcre, ".*", pcre_str_end); 161 | ++ c; 162 | } 163 | else /* case of * */ 164 | STRING_CAT(p_pcre, "[^\\/]*", pcre_str_end); 165 | 166 | break; 167 | case '[': 168 | if (is_in_bracket) /* inside brackets, we really mean bracket */ 169 | { 170 | STRING_CAT(p_pcre, "\\[", pcre_str_end); 171 | break; 172 | } 173 | 174 | { 175 | /* check whether we have slash within the bracket */ 176 | _Bool has_slash = 0; 177 | char * cc; 178 | for (cc = c; *cc && *cc != ']'; ++ cc) 179 | { 180 | if (*cc == '\\' && *(cc+1) != '\0') 181 | { 182 | ++ cc; 183 | continue; 184 | } 185 | 186 | if (*cc == '/') 187 | { 188 | has_slash = 1; 189 | break; 190 | } 191 | } 192 | 193 | /* if we have slash in the brackets, just do it literally */ 194 | if (has_slash) 195 | { 196 | char * right_bracket = strchr(c, ']'); 197 | 198 | if (!right_bracket) /* The right bracket may not exist */ 199 | right_bracket = c + strlen(c); 200 | 201 | STRING_CAT(p_pcre, "\\", pcre_str_end); 202 | /* Boundary check for strncat below. */ 203 | if (pcre_str_end - p_pcre <= right_bracket - c) { 204 | return -1; 205 | } 206 | strncat(p_pcre, c, right_bracket - c); 207 | if (*right_bracket) /* right_bracket is a bracket */ 208 | STRING_CAT(p_pcre, "\\]", pcre_str_end); 209 | p_pcre += strlen(p_pcre); 210 | c = right_bracket; 211 | if (!*c) 212 | /* end of string, meaning that right_bracket is not a 213 | * bracket. Then we go back one character to make the 214 | * parsing end normally for the counter in the "for" 215 | * loop. */ 216 | c -= 1; 217 | break; 218 | } 219 | } 220 | 221 | is_in_bracket = 1; 222 | if (*(c+1) == '!') /* case of [!...] */ 223 | { 224 | STRING_CAT(p_pcre, "[^", pcre_str_end); 225 | ++ c; 226 | } 227 | else 228 | STRING_CAT(p_pcre, "[", pcre_str_end); 229 | 230 | break; 231 | 232 | case ']': 233 | is_in_bracket = 0; 234 | ADD_CHAR(p_pcre, *c, pcre_str_end); 235 | break; 236 | 237 | case '-': 238 | if (is_in_bracket) /* in brackets, - indicates range */ 239 | ADD_CHAR(p_pcre, *c, pcre_str_end); 240 | else 241 | STRING_CAT(p_pcre, "\\-", pcre_str_end); 242 | 243 | break; 244 | case '{': 245 | if (!are_braces_paired) 246 | { 247 | STRING_CAT(p_pcre, "\\{", pcre_str_end); 248 | break; 249 | } 250 | 251 | /* Check the case of {single}, where single can be empty */ 252 | { 253 | char * cc; 254 | _Bool is_single = 1; 255 | 256 | for (cc = c + 1; *cc != '\0' && *cc != '}'; ++ cc) 257 | { 258 | if (*cc == '\\' && *(cc+1) != '\0') 259 | { 260 | ++ cc; 261 | continue; 262 | } 263 | 264 | if (*cc == ',') 265 | { 266 | is_single = 0; 267 | break; 268 | } 269 | } 270 | 271 | if (*cc == '\0') 272 | is_single = 0; 273 | 274 | if (is_single) /* escape the { and the corresponding } */ 275 | { 276 | const char * double_dots; 277 | int_pair pair; 278 | 279 | pcre2_match_data * match_data = pcre2_match_data_create_from_pattern(re, NULL); 280 | 281 | /* Check the case of {num1..num2} */ 282 | rc = pcre2_match(re, c, cc - c + 1, 0, 0, match_data, NULL); 283 | 284 | pcre2_match_data_free(match_data); 285 | 286 | if (rc < 0) /* not {num1..num2} case */ 287 | { 288 | STRING_CAT(p_pcre, "\\{", pcre_str_end); 289 | 290 | memmove(cc+1, cc, strlen(cc) + 1); 291 | *cc = '\\'; 292 | 293 | break; 294 | } 295 | 296 | /* Get the range */ 297 | double_dots = strstr(c, ".."); 298 | pair.num1 = ec_atoi(c + 1); 299 | pair.num2 = ec_atoi(double_dots + 2); 300 | 301 | utarray_push_back(nums, &pair); 302 | 303 | STRING_CAT(p_pcre, "([\\+\\-]?\\d+)", pcre_str_end); 304 | c = cc; 305 | 306 | break; 307 | } 308 | } 309 | 310 | ++ brace_level; 311 | STRING_CAT(p_pcre, "(?:", pcre_str_end); 312 | break; 313 | 314 | case '}': 315 | if (!are_braces_paired) 316 | { 317 | STRING_CAT(p_pcre, "\\}", pcre_str_end); 318 | break; 319 | } 320 | 321 | -- brace_level; 322 | STRING_CAT(p_pcre, ")", pcre_str_end); 323 | break; 324 | 325 | case ',': 326 | if (brace_level > 0) /* , inside {...} */ 327 | STRING_CAT(p_pcre, "|", pcre_str_end); 328 | else 329 | STRING_CAT(p_pcre, "\\,", pcre_str_end); 330 | break; 331 | 332 | case '/': 333 | // /**/ case, match both single / and /anything/ 334 | if (!strncmp(c, "/**/", 4)) 335 | { 336 | STRING_CAT(p_pcre, "(\\/|\\/.*\\/)", pcre_str_end); 337 | c += 3; 338 | } 339 | else 340 | STRING_CAT(p_pcre, "\\/", pcre_str_end); 341 | 342 | break; 343 | 344 | default: 345 | if (!isalnum(*c)) 346 | STRING_CAT(p_pcre, "\\", pcre_str_end); 347 | 348 | ADD_CHAR(p_pcre, *c, pcre_str_end); 349 | } 350 | } 351 | 352 | ADD_CHAR(p_pcre, '$', pcre_str_end); 353 | 354 | pcre2_code_free(re); /* ^\\d+\\.\\.\\d+$ */ 355 | 356 | re = pcre2_compile(pcre_str, PCRE2_ZERO_TERMINATED, 0, &error_code, &erroffset, NULL); 357 | 358 | if (!re) /* failed to compile */ 359 | { 360 | utarray_free(nums); 361 | return -1; 362 | } 363 | 364 | pcre_match_data = pcre2_match_data_create_from_pattern(re, NULL); 365 | rc = pcre2_match(re, string, strlen(string), 0, 0, pcre_match_data, NULL); 366 | 367 | if (rc < 0) /* failed to match */ 368 | { 369 | if (rc == PCRE2_ERROR_NOMATCH) 370 | ret = EC_GLOB_NOMATCH; 371 | else 372 | ret = rc; 373 | 374 | goto cleanup; 375 | } 376 | 377 | /* Whether the numbers are in the desired range? */ 378 | pcre_result = pcre2_get_ovector_pointer(pcre_match_data); 379 | for(p = (int_pair *) utarray_front(nums), i = 1; p; 380 | ++ i, p = (int_pair *) utarray_next(nums, p)) 381 | { 382 | const char * substring_start = string + pcre_result[2 * i]; 383 | size_t substring_length = pcre_result[2 * i + 1] - pcre_result[2 * i]; 384 | char * num_string; 385 | int num; 386 | 387 | /* we don't consider 0digits such as 010 as matched */ 388 | if (*substring_start == '0') 389 | break; 390 | 391 | num_string = strndup(substring_start, substring_length); 392 | if (num_string == NULL) { 393 | ret = -2; 394 | goto cleanup; 395 | } 396 | num = ec_atoi(num_string); 397 | free(num_string); 398 | 399 | if (num < p->num1 || num > p->num2) /* not matched */ 400 | break; 401 | } 402 | 403 | if (p != NULL) /* numbers not matched */ 404 | ret = EC_GLOB_NOMATCH; 405 | 406 | cleanup: 407 | 408 | pcre2_code_free(re); 409 | pcre2_match_data_free(pcre_match_data); 410 | utarray_free(nums); 411 | 412 | return ret; 413 | } 414 | -------------------------------------------------------------------------------- /src/lib/ec_glob.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Hong Xu 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef EC_GLOB_H__ 28 | #define EC_GLOB_H__ 29 | 30 | #include "global.h" 31 | 32 | #define EC_GLOB_NOMATCH 1 /* Match failed. */ 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | EDITORCONFIG_LOCAL 38 | int ec_glob(const char * pattern, const char * string); 39 | 40 | /* Special characters. */ 41 | extern const char ec_special_chars[]; 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* !EC_GLOB_H__ */ 48 | -------------------------------------------------------------------------------- /src/lib/editorconfig.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2012 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include "global.h" 28 | #include "editorconfig.h" 29 | #include "misc.h" 30 | #include "ini.h" 31 | #include "ec_glob.h" 32 | 33 | /* could be used to fast locate these properties in an 34 | * array_editorconfig_name_value */ 35 | typedef struct 36 | { 37 | const editorconfig_name_value* indent_style; 38 | const editorconfig_name_value* indent_size; 39 | const editorconfig_name_value* tab_width; 40 | } special_property_name_value_pointers; 41 | 42 | typedef struct 43 | { 44 | editorconfig_name_value* name_values; 45 | int current_value_count; 46 | int max_value_count; 47 | special_property_name_value_pointers spnvp; 48 | } array_editorconfig_name_value; 49 | 50 | typedef struct 51 | { 52 | char* full_filename; 53 | char* editorconfig_file_dir; 54 | array_editorconfig_name_value array_name_value; 55 | } handler_first_param; 56 | 57 | /* 58 | * Set the special pointers for a name 59 | */ 60 | static void set_special_property_name_value_pointers( 61 | const editorconfig_name_value* nv, 62 | special_property_name_value_pointers* spnvp) 63 | { 64 | /* set speical pointers */ 65 | if (!strcmp(nv->name, "indent_style")) 66 | spnvp->indent_style = nv; 67 | else if (!strcmp(nv->name, "indent_size")) 68 | spnvp->indent_size = nv; 69 | else if (!strcmp(nv->name, "tab_width")) 70 | spnvp->tab_width = nv; 71 | } 72 | 73 | /* 74 | * Set the name and value of a editorconfig_name_value structure 75 | */ 76 | static void set_name_value(editorconfig_name_value* nv, const char* name, 77 | const char* value, special_property_name_value_pointers* spnvp) 78 | { 79 | if (name) 80 | nv->name = strdup(name); 81 | if (value) 82 | nv->value = strdup(value); 83 | /* lowercase the value when the name is one of the following */ 84 | if (!strcmp(nv->name, "end_of_line") || 85 | !strcmp(nv->name, "indent_style") || 86 | !strcmp(nv->name, "indent_size") || 87 | !strcmp(nv->name, "insert_final_newline") || 88 | !strcmp(nv->name, "trim_trailing_whitespace") || 89 | !strcmp(nv->name, "charset")) 90 | strlwr(nv->value); 91 | 92 | /* set special pointers */ 93 | set_special_property_name_value_pointers(nv, spnvp); 94 | } 95 | 96 | /* 97 | * reset special property name value pointers 98 | */ 99 | static void reset_special_property_name_value_pointers( 100 | array_editorconfig_name_value* aenv) 101 | { 102 | int i; 103 | 104 | for (i = 0; i < aenv->current_value_count; ++ i) 105 | set_special_property_name_value_pointers( 106 | &aenv->name_values[i], &aenv->spnvp); 107 | } 108 | 109 | /* 110 | * Find the editorconfig_name_value from name in a editorconfig_name_value 111 | * array. 112 | */ 113 | static int find_name_value_from_name(const editorconfig_name_value* env, 114 | int count, const char* name) 115 | { 116 | int i; 117 | 118 | for (i = 0; i < count; ++i) 119 | if (!strcmp(env[i].name, name)) /* found */ 120 | return i; 121 | 122 | return -1; 123 | } 124 | 125 | /* initialize array_editorconfig_name_value */ 126 | static void array_editorconfig_name_value_init( 127 | array_editorconfig_name_value* aenv) 128 | { 129 | memset(aenv, 0, sizeof(array_editorconfig_name_value)); 130 | } 131 | 132 | static int array_editorconfig_name_value_add( 133 | array_editorconfig_name_value* aenv, 134 | const char* name, const char* value) 135 | { 136 | #define VALUE_COUNT_INITIAL 30 137 | #define VALUE_COUNT_INCREASEMENT 10 138 | int name_value_pos; 139 | /* always use name_lwr but not name, since property names are case 140 | * insensitive */ 141 | char name_lwr[MAX_PROPERTY_NAME+1] = {0}; 142 | /* For the first time we came here, aenv->name_values is NULL */ 143 | if (aenv->name_values == NULL) { 144 | aenv->name_values = (editorconfig_name_value*)malloc( 145 | sizeof(editorconfig_name_value) * VALUE_COUNT_INITIAL); 146 | 147 | if (aenv->name_values == NULL) 148 | return -1; 149 | 150 | aenv->max_value_count = VALUE_COUNT_INITIAL; 151 | aenv->current_value_count = 0; 152 | } 153 | 154 | 155 | /* name_lwr is the lowercase property name */ 156 | strlwr(strncpy(name_lwr, name, MAX_PROPERTY_NAME)); 157 | 158 | name_value_pos = find_name_value_from_name( 159 | aenv->name_values, aenv->current_value_count, name_lwr); 160 | 161 | if (name_value_pos >= 0) { /* current name has already been used */ 162 | free(aenv->name_values[name_value_pos].value); 163 | set_name_value(&aenv->name_values[name_value_pos], 164 | (const char*)NULL, value, &aenv->spnvp); 165 | return 0; 166 | } 167 | 168 | /* if the space is not enough, allocate more before add the new name and 169 | * value */ 170 | if (aenv->current_value_count >= aenv->max_value_count) { 171 | 172 | editorconfig_name_value* new_values; 173 | int new_max_value_count; 174 | 175 | new_max_value_count = aenv->current_value_count + 176 | VALUE_COUNT_INCREASEMENT; 177 | new_values = (editorconfig_name_value*)realloc(aenv->name_values, 178 | sizeof(editorconfig_name_value) * new_max_value_count); 179 | 180 | if (new_values == NULL) /* error occured */ 181 | return -1; 182 | 183 | aenv->name_values = new_values; 184 | aenv->max_value_count = new_max_value_count; 185 | 186 | /* reset special pointers */ 187 | reset_special_property_name_value_pointers(aenv); 188 | } 189 | 190 | set_name_value(&aenv->name_values[aenv->current_value_count], 191 | name_lwr, value, &aenv->spnvp); 192 | ++ aenv->current_value_count; 193 | 194 | return 0; 195 | #undef VALUE_COUNT_INITIAL 196 | #undef VALUE_COUNT_INCREASEMENT 197 | } 198 | 199 | static void array_editorconfig_name_value_clear( 200 | array_editorconfig_name_value* aenv) 201 | { 202 | int i; 203 | 204 | for (i = 0; i < aenv->current_value_count; ++i) { 205 | free(aenv->name_values[i].name); 206 | free(aenv->name_values[i].value); 207 | } 208 | 209 | free(aenv->name_values); 210 | } 211 | 212 | /* 213 | * Accept INI property value and store known values in handler_first_param 214 | * struct. 215 | */ 216 | static int ini_handler(void* hfp, const char* section, const char* name, 217 | const char* value) 218 | { 219 | handler_first_param* hfparam = (handler_first_param*)hfp; 220 | /* prepend ** to pattern */ 221 | char* pattern; 222 | 223 | /* root = true, clear all previous values */ 224 | if (*section == '\0' && !strcasecmp(name, "root") && 225 | !strcasecmp(value, "true")) { 226 | array_editorconfig_name_value_clear(&hfparam->array_name_value); 227 | array_editorconfig_name_value_init(&hfparam->array_name_value); 228 | return 1; 229 | } 230 | 231 | /* Pattern would be: /dir/of/editorconfig/file[double_star]/[section] if 232 | * section does not contain '/', or /dir/of/editorconfig/file[section] 233 | * if section starts with a '/', or /dir/of/editorconfig/file/[section] if 234 | * section contains '/' but does not start with '/'. 235 | * 236 | * If the dir part has any special characters as defined by ec_glob.c, we 237 | * need to escape them. 238 | */ 239 | pattern = (char*)malloc( 240 | /* The 2 here is for possible escaping. */ 241 | strlen(hfparam->editorconfig_file_dir) * sizeof(char) * 2 + 242 | sizeof("**/") + strlen(section) * sizeof(char)); 243 | if (!pattern) 244 | return 0; 245 | 246 | /* Escaping special characters in the directory part. */ 247 | char* ptr = hfparam->editorconfig_file_dir; 248 | char* ptr_prev = ptr; 249 | char* ptr_pattern = pattern; 250 | for (; (ptr = strpbrk(ptr, ec_special_chars)) != NULL; ++ ptr, ptr_prev = ptr) 251 | { 252 | ptrdiff_t s = ptr - ptr_prev; 253 | memcpy(ptr_pattern, ptr_prev, s * sizeof(char)); 254 | ptr_pattern += s; 255 | *(ptr_pattern ++) = '\\'; /* escaping char */ 256 | *(ptr_pattern ++) = *ptr; 257 | } 258 | strcpy(ptr_pattern, ptr_prev); 259 | 260 | if (strchr(section, '/') == NULL) /* No / is found, append '[star][star]/' */ 261 | strcat(pattern, "**/"); 262 | else if (*section != '/') /* The first char is not '/' but section contains 263 | '/', append a '/' */ 264 | strcat(pattern, "/"); 265 | 266 | strcat(pattern, section); 267 | 268 | if (ec_glob(pattern, hfparam->full_filename) == 0) { 269 | if (array_editorconfig_name_value_add(&hfparam->array_name_value, name, 270 | value)) { 271 | free(pattern); 272 | return 0; 273 | } 274 | } 275 | 276 | free(pattern); 277 | return 1; 278 | } 279 | 280 | /* 281 | * Split an absolute file path into directory and filename parts. 282 | * 283 | * If absolute_path does not contain a path separator, set directory and 284 | * filename to NULL pointers. 285 | * 286 | * Returns -1 if an OOM error occurs. Otherwise returns 0. 287 | */ 288 | static int split_file_path(char** directory, char** filename, 289 | const char* absolute_path) 290 | { 291 | char* path_char = strrchr(absolute_path, '/'); 292 | 293 | if (path_char == NULL) { 294 | if (directory) 295 | *directory = NULL; 296 | if (filename) 297 | *filename = NULL; 298 | return 0; 299 | } 300 | 301 | if (directory != NULL) { 302 | *directory = strndup(absolute_path, 303 | (size_t)(path_char - absolute_path)); 304 | if (*directory == NULL) 305 | return -1; 306 | } 307 | 308 | if (filename != NULL) { 309 | *filename = strndup(path_char+1, strlen(path_char)-1); 310 | if (*filename == NULL) { 311 | if (directory != NULL) 312 | free(*directory); 313 | return -1; 314 | } 315 | } 316 | 317 | return 0; 318 | } 319 | 320 | /* 321 | * Return the number of slashes in given filename 322 | */ 323 | static int count_slashes(const char* filename) 324 | { 325 | int slash_count; 326 | for (slash_count = 0; *filename != '\0'; filename++) { 327 | if (*filename == '/') { 328 | slash_count++; 329 | } 330 | } 331 | return slash_count; 332 | } 333 | 334 | /* 335 | * Return an array of full filenames for files in every directory in and above 336 | * the given path with the name of the relative filename given. Return NULL if 337 | * failed (OOM). 338 | */ 339 | static char** get_filenames(const char* path, const char* filename) 340 | { 341 | char* currdir = NULL; 342 | char** files; 343 | int slashes = count_slashes(path); 344 | int i; 345 | 346 | files = (char**) calloc(slashes+1, sizeof(char*)); 347 | if (files == NULL) 348 | goto failure_cleanup; 349 | 350 | currdir = strdup(path); 351 | if (currdir == NULL) 352 | goto failure_cleanup; 353 | 354 | for (i = slashes - 1; i >= 0; --i) { 355 | char* currdir1 = currdir; 356 | int err_split; 357 | err_split = split_file_path(&currdir, NULL, currdir1); 358 | free(currdir1); 359 | if (err_split == -1) 360 | goto failure_cleanup; 361 | files[i] = malloc(strlen(currdir) + strlen(filename) + 2); 362 | strcpy(files[i], currdir); 363 | strcat(files[i], "/"); 364 | strcat(files[i], filename); 365 | } 366 | 367 | free(currdir); 368 | 369 | files[slashes] = NULL; 370 | 371 | return files; 372 | 373 | failure_cleanup: 374 | 375 | free(currdir); 376 | 377 | if (files != NULL) { 378 | for (i = 0; i < slashes; ++ i) 379 | free(files[i]); 380 | free(files); 381 | } 382 | 383 | return NULL; 384 | } 385 | 386 | /* 387 | * Free the memory used by an array of strings that was created by 388 | * get_filenames(). 389 | */ 390 | static void free_filenames(char **filenames) 391 | { 392 | if (filenames != NULL) { 393 | for (char** filename = filenames; *filename != NULL; filename++) { 394 | free(*filename); 395 | } 396 | free(filenames); 397 | } 398 | } 399 | 400 | /* 401 | * version number comparison 402 | */ 403 | static int editorconfig_compare_version( 404 | const struct editorconfig_version* v0, 405 | const struct editorconfig_version* v1) 406 | { 407 | /* compare major */ 408 | if (v0->major > v1->major) 409 | return 1; 410 | else if (v0->major < v1->major) 411 | return -1; 412 | 413 | /* compare minor */ 414 | if (v0->minor > v1->minor) 415 | return 1; 416 | else if (v0->minor < v1->minor) 417 | return -1; 418 | 419 | /* compare patch */ 420 | if (v0->patch > v1->patch) 421 | return 1; 422 | else if (v0->patch < v1->patch) 423 | return -1; 424 | 425 | return 0; 426 | } 427 | 428 | EDITORCONFIG_EXPORT 429 | const char* editorconfig_get_error_msg(int err_num) 430 | { 431 | if(err_num > 0) 432 | return "Failed to parse file."; 433 | 434 | switch(err_num) { 435 | case 0: 436 | return "No error occurred."; 437 | case EDITORCONFIG_PARSE_NOT_FULL_PATH: 438 | return "Input file must be a full path name."; 439 | case EDITORCONFIG_PARSE_MEMORY_ERROR: 440 | return "Memory error."; 441 | case EDITORCONFIG_PARSE_VERSION_TOO_NEW: 442 | return "Required version is greater than the current version."; 443 | } 444 | 445 | return "Unknown error."; 446 | } 447 | 448 | /* 449 | * See the header file for the use of this function 450 | */ 451 | EDITORCONFIG_EXPORT 452 | int editorconfig_parse(const char* full_filename, editorconfig_handle h) 453 | { 454 | handler_first_param hfp; 455 | char** config_file; 456 | char** config_files = NULL; 457 | int err_num = 0; 458 | int i; 459 | struct editorconfig_handle* eh = (struct editorconfig_handle*)h; 460 | struct editorconfig_version cur_ver; 461 | struct editorconfig_version tmp_ver; 462 | 463 | /* get current version */ 464 | editorconfig_get_version(&cur_ver.major, &cur_ver.minor, 465 | &cur_ver.patch); 466 | 467 | /* if version is set to 0.0.0, we set it to current version */ 468 | if (eh->ver.major == 0 && 469 | eh->ver.minor == 0 && 470 | eh->ver.patch == 0) 471 | eh->ver = cur_ver; 472 | 473 | if (editorconfig_compare_version(&eh->ver, &cur_ver) > 0) 474 | return EDITORCONFIG_PARSE_VERSION_TOO_NEW; 475 | 476 | if (eh->err_file) { 477 | free(eh->err_file); 478 | eh->err_file = NULL; 479 | } 480 | 481 | /* if eh->conf_file_name is NULL, we set ".editorconfig" as the default 482 | * conf file name */ 483 | if (!eh->conf_file_name) 484 | eh->conf_file_name = ".editorconfig"; 485 | 486 | if (eh->name_values) { 487 | /* free name_values */ 488 | for (i = 0; i < eh->name_value_count; ++i) { 489 | free(eh->name_values[i].name); 490 | free(eh->name_values[i].value); 491 | } 492 | free(eh->name_values); 493 | 494 | eh->name_values = NULL; 495 | eh->name_value_count = 0; 496 | } 497 | memset(&hfp, 0, sizeof(hfp)); 498 | 499 | hfp.full_filename = strdup(full_filename); 500 | if (hfp.full_filename == NULL) { 501 | err_num = EDITORCONFIG_PARSE_MEMORY_ERROR; 502 | goto cleanup; 503 | } 504 | 505 | /* return an error if file path is not absolute */ 506 | if (!is_file_path_absolute(full_filename)) { 507 | err_num = EDITORCONFIG_PARSE_NOT_FULL_PATH; 508 | goto cleanup; 509 | } 510 | 511 | #ifdef WIN32 512 | /* replace all backslashes with slashes on Windows */ 513 | str_replace(hfp.full_filename, '\\', '/'); 514 | #endif 515 | 516 | array_editorconfig_name_value_init(&hfp.array_name_value); 517 | 518 | config_files = get_filenames(hfp.full_filename, eh->conf_file_name); 519 | if (config_files == NULL) { 520 | err_num = EDITORCONFIG_PARSE_MEMORY_ERROR; 521 | goto cleanup; 522 | } 523 | for (config_file = config_files; *config_file != NULL; config_file++) { 524 | int ini_err_num; 525 | err_num = split_file_path(&hfp.editorconfig_file_dir, NULL, *config_file); 526 | if (err_num == -1) { 527 | err_num = EDITORCONFIG_PARSE_MEMORY_ERROR; 528 | goto cleanup; 529 | } 530 | 531 | if ((ini_err_num = ini_parse(*config_file, ini_handler, &hfp)) != 0 && 532 | /* ignore error caused by I/O, maybe caused by non exist file */ 533 | ini_err_num != -1) { 534 | /* No need to specifically deal with the return value of the strdup 535 | of this line. If any error occurs for this strdup call, 536 | eh->err_file would simply be NULL.*/ 537 | eh->err_file = strdup(*config_file); 538 | err_num = ini_err_num; 539 | goto cleanup; 540 | } 541 | 542 | free(hfp.editorconfig_file_dir); 543 | hfp.editorconfig_file_dir = NULL; 544 | } 545 | 546 | /* value proprocessing */ 547 | 548 | /* For v0.9 */ 549 | SET_EDITORCONFIG_VERSION(&tmp_ver, 0, 9, 0); 550 | if (editorconfig_compare_version(&eh->ver, &tmp_ver) >= 0) { 551 | /* Set indent_size to "tab" if indent_size is not specified and 552 | * indent_style is set to "tab". Only should be done after v0.9 */ 553 | if (hfp.array_name_value.spnvp.indent_style && 554 | !hfp.array_name_value.spnvp.indent_size && 555 | !strcmp(hfp.array_name_value.spnvp.indent_style->value, "tab")) 556 | array_editorconfig_name_value_add(&hfp.array_name_value, 557 | "indent_size", "tab"); 558 | /* Set indent_size to tab_width if indent_size is "tab" and tab_width is 559 | * specified. This behavior is specified for v0.9 and up. */ 560 | if (hfp.array_name_value.spnvp.indent_size && 561 | hfp.array_name_value.spnvp.tab_width && 562 | !strcmp(hfp.array_name_value.spnvp.indent_size->value, "tab")) 563 | array_editorconfig_name_value_add(&hfp.array_name_value, "indent_size", 564 | hfp.array_name_value.spnvp.tab_width->value); 565 | } 566 | 567 | /* Set tab_width to indent_size if indent_size is specified. If version is 568 | * not less than 0.9.0, we also need to check when the indent_size is set 569 | * to "tab", we should not duplicate the value to tab_width */ 570 | if (hfp.array_name_value.spnvp.indent_size && 571 | !hfp.array_name_value.spnvp.tab_width && 572 | (editorconfig_compare_version(&eh->ver, &tmp_ver) < 0 || 573 | strcmp(hfp.array_name_value.spnvp.indent_size->value, "tab"))) 574 | array_editorconfig_name_value_add(&hfp.array_name_value, "tab_width", 575 | hfp.array_name_value.spnvp.indent_size->value); 576 | 577 | eh->name_value_count = hfp.array_name_value.current_value_count; 578 | 579 | if (eh->name_value_count == 0) { /* no value is set, just return 0. */ 580 | free(hfp.full_filename); 581 | free_filenames(config_files); 582 | return 0; 583 | } 584 | eh->name_values = hfp.array_name_value.name_values; 585 | eh->name_values = realloc( /* realloc to truncate the unused spaces */ 586 | eh->name_values, 587 | sizeof(editorconfig_name_value) * eh->name_value_count); 588 | if (eh->name_values == NULL) { 589 | free(hfp.full_filename); 590 | free_filenames(config_files); 591 | return EDITORCONFIG_PARSE_MEMORY_ERROR; 592 | } 593 | 594 | cleanup: 595 | free_filenames(config_files); 596 | free(hfp.full_filename); 597 | free(hfp.editorconfig_file_dir); 598 | 599 | return err_num; 600 | } 601 | 602 | /* 603 | * See header file 604 | */ 605 | EDITORCONFIG_EXPORT 606 | void editorconfig_get_version(int* major, int* minor, int* patch) 607 | { 608 | if (major) 609 | *major = EC_VERSION_MAJOR; 610 | if (minor) 611 | *minor = EC_VERSION_MINOR; 612 | if (patch) 613 | *patch = EC_VERSION_PATCH; 614 | } 615 | 616 | /* 617 | * See header file 618 | */ 619 | EDITORCONFIG_EXPORT 620 | const char* editorconfig_get_version_suffix(void) 621 | { 622 | return EC_VERSION_SUFFIX; 623 | } 624 | -------------------------------------------------------------------------------- /src/lib/editorconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef EDITORCONFIG_H__ 28 | #define EDITORCONFIG_H__ 29 | 30 | #include 31 | 32 | #include "editorconfig_handle.h" 33 | 34 | typedef struct editorconfig_name_value editorconfig_name_value; 35 | 36 | #endif /* !EDITORCONFIG_H__ */ 37 | 38 | -------------------------------------------------------------------------------- /src/lib/editorconfig.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | libdir=@libdir_for_pc_file@ 3 | includedir=@includedir_for_pc_file@ 4 | 5 | Name: editorconfig 6 | Description: Library handling EditorConfig files, a file format defining coding styles in projects. 7 | Version: @PROJECT_VERSION@ 8 | Libs: -L${libdir} -leditorconfig 9 | Cflags: -I${includedir} 10 | -------------------------------------------------------------------------------- /src/lib/editorconfig_handle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2012 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include "editorconfig_handle.h" 28 | 29 | /* 30 | * See header file 31 | */ 32 | EDITORCONFIG_EXPORT 33 | editorconfig_handle editorconfig_handle_init(void) 34 | { 35 | editorconfig_handle h; 36 | 37 | h = (editorconfig_handle)malloc(sizeof(struct editorconfig_handle)); 38 | 39 | if (!h) 40 | return (editorconfig_handle)NULL; 41 | 42 | memset(h, 0, sizeof(struct editorconfig_handle)); 43 | 44 | return h; 45 | } 46 | 47 | /* 48 | * See header file 49 | */ 50 | EDITORCONFIG_EXPORT 51 | int editorconfig_handle_destroy(editorconfig_handle h) 52 | { 53 | int i; 54 | struct editorconfig_handle* eh = (struct editorconfig_handle*)h; 55 | 56 | 57 | if (h == NULL) 58 | return 0; 59 | 60 | /* free name_values */ 61 | for (i = 0; i < eh->name_value_count; ++i) { 62 | free(eh->name_values[i].name); 63 | free(eh->name_values[i].value); 64 | } 65 | free(eh->name_values); 66 | 67 | /* free err_file */ 68 | if (eh->err_file) 69 | free(eh->err_file); 70 | 71 | /* free eh itself */ 72 | free(eh); 73 | 74 | return 0; 75 | } 76 | 77 | /* 78 | * See header file 79 | */ 80 | EDITORCONFIG_EXPORT 81 | const char* editorconfig_handle_get_err_file(const editorconfig_handle h) 82 | { 83 | return ((const struct editorconfig_handle*)h)->err_file; 84 | } 85 | 86 | /* 87 | * See header file 88 | */ 89 | EDITORCONFIG_EXPORT 90 | void editorconfig_handle_get_version(const editorconfig_handle h, int* major, 91 | int* minor, int* patch) 92 | { 93 | if (major) 94 | *major = ((const struct editorconfig_handle*)h)->ver.major; 95 | if (minor) 96 | *minor = ((const struct editorconfig_handle*)h)->ver.minor; 97 | if (patch) 98 | *patch = ((const struct editorconfig_handle*)h)->ver.patch; 99 | } 100 | 101 | /* 102 | * See header file 103 | */ 104 | EDITORCONFIG_EXPORT 105 | void editorconfig_handle_set_version(editorconfig_handle h, int major, 106 | int minor, int patch) 107 | { 108 | if (major >= 0) 109 | ((struct editorconfig_handle*)h)->ver.major = major; 110 | 111 | if (minor >= 0) 112 | ((struct editorconfig_handle*)h)->ver.minor = minor; 113 | 114 | if (patch >= 0) 115 | ((struct editorconfig_handle*)h)->ver.patch = patch; 116 | } 117 | 118 | /* 119 | * See header file 120 | */ 121 | EDITORCONFIG_EXPORT 122 | void editorconfig_handle_set_conf_file_name(editorconfig_handle h, 123 | const char* conf_file_name) 124 | { 125 | ((struct editorconfig_handle*)h)->conf_file_name = conf_file_name; 126 | } 127 | 128 | /* 129 | * See header file 130 | */ 131 | EDITORCONFIG_EXPORT 132 | const char* editorconfig_handle_get_conf_file_name(const editorconfig_handle h) 133 | { 134 | return ((const struct editorconfig_handle*)h)->conf_file_name; 135 | } 136 | 137 | EDITORCONFIG_EXPORT 138 | void editorconfig_handle_get_name_value(const editorconfig_handle h, int n, 139 | const char** name, const char** value) 140 | { 141 | struct editorconfig_name_value* name_value = &(( 142 | const struct editorconfig_handle*)h)->name_values[n]; 143 | 144 | if (name) 145 | *name = name_value->name; 146 | 147 | if (value) 148 | *value = name_value->value; 149 | } 150 | 151 | EDITORCONFIG_EXPORT 152 | int editorconfig_handle_get_name_value_count(const editorconfig_handle h) 153 | { 154 | return ((const struct editorconfig_handle*)h)->name_value_count; 155 | } 156 | -------------------------------------------------------------------------------- /src/lib/editorconfig_handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef EDITORCONFIG_HANDLE_H__ 28 | #define EDITORCONFIG_HANDLE_H__ 29 | 30 | #include "global.h" 31 | #include 32 | 33 | /*! 34 | * @brief A structure containing a name and its corresponding value. 35 | * @author EditorConfig Team 36 | */ 37 | struct editorconfig_name_value 38 | { 39 | /*! EditorConfig config item's name. */ 40 | char* name; 41 | /*! EditorConfig config item's value. */ 42 | char* value; 43 | }; 44 | 45 | /*! 46 | * @brief A structure that descripts version number. 47 | * @author EditorConfig Team 48 | */ 49 | struct editorconfig_version 50 | { 51 | /*! major version */ 52 | int major; 53 | /*! minor version */ 54 | int minor; 55 | /*! patch version */ 56 | int patch; 57 | }; 58 | 59 | struct editorconfig_handle 60 | { 61 | /*! 62 | * The file name of EditorConfig conf file. If this pointer is set to NULL, 63 | * the file name is set to ".editorconfig" by default. 64 | */ 65 | const char* conf_file_name; 66 | 67 | /*! 68 | * When a parsing error occured, this will point to a file that caused the 69 | * parsing error. 70 | */ 71 | char* err_file; 72 | 73 | /*! 74 | * version number it should act as. Set this to 0.0.0 to act like the 75 | * current version. 76 | */ 77 | struct editorconfig_version ver; 78 | 79 | /*! Pointer to a list of editorconfig_name_value structures containing 80 | * names and values of the parsed result */ 81 | struct editorconfig_name_value* name_values; 82 | 83 | /*! The total count of name_values structures pointed by name_values 84 | * pointer */ 85 | int name_value_count; 86 | }; 87 | 88 | #endif /* !EDITORCONFIG_HANDLE_H__ */ 89 | 90 | -------------------------------------------------------------------------------- /src/lib/global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef GLOBAL_H__ 28 | #define GLOBAL_H__ 29 | 30 | #include "config.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /* 38 | * Microsoft Visual C++ and some other Windows C Compilers requires exported 39 | * functions in shared library to be defined with __declspec(dllexport) 40 | * declarator. Also, gcc >= 4 supports hiding symbols that do not need to be 41 | * exported. 42 | */ 43 | #ifdef editorconfig_shared_EXPORTS /* We are building shared lib if defined */ 44 | # ifdef WIN32 45 | # ifdef __GNUC__ 46 | # define EDITORCONFIG_EXPORT __attribute__ ((dllexport)) 47 | # else /* __GNUC__ */ 48 | # define EDITORCONFIG_EXPORT __declspec(dllexport) 49 | # endif /* __GNUC__ */ 50 | # else /* WIN32 */ 51 | # if defined(__GNUC__) && __GNUC__ >= 4 52 | # define EDITORCONFIG_EXPORT __attribute__ ((visibility ("default"))) 53 | # define EDITORCONFIG_LOCAL __attribute__ ((visibility ("hidden"))) 54 | # endif /* __GNUC__ && __GNUC >= 4 */ 55 | # endif /* WIN32 */ 56 | #endif /* editorconfig_shared_EXPORTS */ 57 | 58 | /* 59 | * For other cases, just define EDITORCONFIG_EXPORT and EDITORCONFIG_LOCAL, to 60 | * make compilation successful 61 | */ 62 | #ifndef EDITORCONFIG_EXPORT 63 | # define EDITORCONFIG_EXPORT 64 | #endif 65 | #ifndef EDITORCONFIG_LOCAL 66 | # define EDITORCONFIG_LOCAL 67 | #endif 68 | 69 | /* a macro to set editorconfig_version struct */ 70 | #define SET_EDITORCONFIG_VERSION(editorconfig_ver, maj, min, submin) \ 71 | do { \ 72 | (editorconfig_ver)->major = (maj); \ 73 | (editorconfig_ver)->minor = (min); \ 74 | (editorconfig_ver)->patch = (submin); \ 75 | } while(0) 76 | 77 | #endif /* !GLOBAL_H__ */ 78 | 79 | -------------------------------------------------------------------------------- /src/lib/ini.c: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | The "inih" library is distributed under the New BSD license: 4 | 5 | Copyright (c) 2009, Brush Technology 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | * Neither the name of Brush Technology nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | Go to the project home page for more info: 31 | http://code.google.com/p/inih/ 32 | 33 | */ 34 | 35 | #include "global.h" 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include "ini.h" 42 | 43 | #define MAX_LINE 5000 44 | #define MAX_SECTION MAX_SECTION_NAME 45 | #define MAX_NAME MAX_PROPERTY_NAME 46 | 47 | /* Strip whitespace chars off end of given string, in place. Return s. */ 48 | static char* rstrip(char* s) 49 | { 50 | char* p = s + strlen(s); 51 | while (p > s && isspace(*--p)) 52 | *p = '\0'; 53 | return s; 54 | } 55 | 56 | /* Return pointer to first non-whitespace char in given string. */ 57 | static char* lskip(const char* s) 58 | { 59 | while (*s && isspace(*s)) 60 | s++; 61 | return (char*)s; 62 | } 63 | 64 | /* Return pointer to first char c or ';' comment in given string, or pointer to 65 | null at end of string if neither found. ';' must be prefixed by a whitespace 66 | character to register as a comment. */ 67 | static char* find_char_or_comment(const char* s, char c) 68 | { 69 | int was_whitespace = 0; 70 | while (*s && *s != c && !(was_whitespace && (*s == ';' || *s == '#'))) { 71 | was_whitespace = isspace(*s); 72 | s++; 73 | } 74 | return (char*)s; 75 | } 76 | 77 | static char* find_last_char_or_comment(const char* s, char c) 78 | { 79 | const char* last_char = s; 80 | int was_whitespace = 0; 81 | while (*s && !(was_whitespace && (*s == ';' || *s == '#'))) { 82 | if (*s == c) 83 | last_char = s; 84 | was_whitespace = isspace(*s); 85 | s++; 86 | } 87 | return (char*)last_char; 88 | } 89 | 90 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ 91 | static char* strncpy0(char* dest, const char* src, size_t size) 92 | { 93 | strncpy(dest, src, size); 94 | dest[size - 1] = '\0'; 95 | return dest; 96 | } 97 | 98 | /* See documentation in header file. */ 99 | EDITORCONFIG_LOCAL 100 | int ini_parse_file(FILE* file, 101 | int (*handler)(void*, const char*, const char*, 102 | const char*), 103 | void* user) 104 | { 105 | /* Uses a fair bit of stack (use heap instead if you need to) */ 106 | char line[MAX_LINE]; 107 | char section[MAX_SECTION+1] = ""; 108 | char prev_name[MAX_NAME+1] = ""; 109 | 110 | char* start; 111 | char* end; 112 | char* name; 113 | char* value; 114 | int lineno = 0; 115 | int error = 0; 116 | 117 | /* Scan through file line by line */ 118 | while (fgets(line, sizeof(line), file) != NULL) { 119 | lineno++; 120 | 121 | start = line; 122 | #if INI_ALLOW_BOM 123 | if (lineno == 1 && (unsigned char)start[0] == 0xEF && 124 | (unsigned char)start[1] == 0xBB && 125 | (unsigned char)start[2] == 0xBF) { 126 | start += 3; 127 | } 128 | #endif 129 | start = lskip(rstrip(start)); 130 | 131 | if (*start == ';' || *start == '#') { 132 | /* Per Python ConfigParser, allow '#' comments at start of line */ 133 | } 134 | #if INI_ALLOW_MULTILINE 135 | else if (*prev_name && *start && start > line) { 136 | /* Non-black line with leading whitespace, treat as continuation 137 | of previous name's value (as per Python ConfigParser). */ 138 | if (!handler(user, section, prev_name, start) && !error) 139 | error = lineno; 140 | } 141 | #endif 142 | else if (*start == '[') { 143 | /* A "[section]" line */ 144 | end = find_last_char_or_comment(start + 1, ']'); 145 | if (*end == ']') { 146 | *end = '\0'; 147 | /* Section name too long. Skipped. */ 148 | if (end - start - 1 > MAX_SECTION_NAME) 149 | continue; 150 | strncpy0(section, start + 1, sizeof(section)); 151 | *prev_name = '\0'; 152 | } 153 | else if (!error) { 154 | /* No ']' found on section line */ 155 | error = lineno; 156 | } 157 | } 158 | else if (*start && (*start != ';' || *start == '#')) { 159 | /* Not a comment, must be a name[=:]value pair */ 160 | end = find_char_or_comment(start, '='); 161 | if (*end != '=') { 162 | end = find_char_or_comment(start, ':'); 163 | } 164 | if (*end == '=' || *end == ':') { 165 | *end = '\0'; 166 | name = rstrip(start); 167 | value = lskip(end + 1); 168 | end = find_char_or_comment(value, '\0'); 169 | if (*end == ';' || *end == '#') 170 | *end = '\0'; 171 | rstrip(value); 172 | 173 | /* Either name or value is too long. Skip it. */ 174 | if (strlen(name) > MAX_PROPERTY_NAME || 175 | strlen(value) > MAX_PROPERTY_VALUE) 176 | continue; 177 | 178 | /* Valid name[=:]value pair found, call handler */ 179 | strncpy0(prev_name, name, sizeof(prev_name)); 180 | if (!handler(user, section, name, value) && !error) 181 | error = lineno; 182 | } 183 | else if (!error) { 184 | /* No '=' or ':' found on name[=:]value line */ 185 | error = lineno; 186 | } 187 | } 188 | } 189 | 190 | return error; 191 | } 192 | 193 | /* See documentation in header file. */ 194 | EDITORCONFIG_LOCAL 195 | int ini_parse(const char* filename, 196 | int (*handler)(void*, const char*, const char*, const char*), 197 | void* user) 198 | { 199 | FILE* file; 200 | int error; 201 | 202 | file = fopen(filename, "r"); 203 | if (!file) 204 | return -1; 205 | error = ini_parse_file(file, handler, user); 206 | fclose(file); 207 | return error; 208 | } 209 | -------------------------------------------------------------------------------- /src/lib/ini.h: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | The "inih" library is distributed under the New BSD license: 4 | 5 | Copyright (c) 2009, Brush Technology 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | * Neither the name of Brush Technology nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | Go to the project home page for more info: 31 | http://code.google.com/p/inih/ 32 | 33 | */ 34 | 35 | #ifndef INI_H__ 36 | #define INI_H__ 37 | 38 | #include "global.h" 39 | 40 | /* Make this header file easier to include in C++ code */ 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #include 46 | 47 | /* Parse given INI-style file. May have [section]s, name=value pairs 48 | (whitespace stripped), and comments starting with ';' (semicolon). Section 49 | is "" if name=value pair parsed before any section heading. name:value 50 | pairs are also supported as a concession to Python's ConfigParser. 51 | 52 | For each name=value pair parsed, call handler function with given user 53 | pointer as well as section, name, and value (data only valid for duration 54 | of handler call). Handler should return nonzero on success, zero on error. 55 | 56 | Returns 0 on success, line number of first error on parse error (doesn't 57 | stop on first error), or -1 on file open error. 58 | */ 59 | EDITORCONFIG_LOCAL 60 | int ini_parse(const char* filename, 61 | int (*handler)(void* user, const char* section, 62 | const char* name, const char* value), 63 | void* user); 64 | 65 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't 66 | close the file when it's finished -- the caller must do that. */ 67 | EDITORCONFIG_LOCAL 68 | int ini_parse_file(FILE* file, 69 | int (*handler)(void* user, const char* section, 70 | const char* name, const char* value), 71 | void* user); 72 | 73 | /* Nonzero to allow multi-line value parsing, in the style of Python's 74 | ConfigParser. If allowed, ini_parse() will call the handler with the same 75 | name for each subsequent line parsed. */ 76 | #ifndef INI_ALLOW_MULTILINE 77 | #define INI_ALLOW_MULTILINE 0 78 | #endif 79 | 80 | #define MAX_SECTION_NAME 4096 81 | #define MAX_PROPERTY_NAME 1024 82 | #define MAX_PROPERTY_VALUE 4096 83 | 84 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of 85 | the file. See http://code.google.com/p/inih/issues/detail?id=21 */ 86 | #ifndef INI_ALLOW_BOM 87 | #define INI_ALLOW_BOM 1 88 | #endif 89 | 90 | #ifdef __cplusplus 91 | } 92 | #endif 93 | 94 | #endif /* INI_H__ */ 95 | -------------------------------------------------------------------------------- /src/lib/misc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2012 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | 28 | #include "misc.h" 29 | 30 | #ifdef WIN32 31 | # include 32 | #endif 33 | 34 | #if !defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP) 35 | /* 36 | * strcasecmp function from FreeBSD 37 | * 38 | * Copyright (c) 1987, 1993 39 | * The Regents of the University of California. All rights reserved. 40 | * 41 | * Redistribution and use in source and binary forms, with or without 42 | * modification, are permitted provided that the following conditions 43 | * are met: 44 | * 1. Redistributions of source code must retain the above copyright 45 | * notice, this list of conditions and the following disclaimer. 46 | * 2. Redistributions in binary form must reproduce the above copyright 47 | * notice, this list of conditions and the following disclaimer in the 48 | * documentation and/or other materials provided with the distribution. 49 | * 4. Neither the name of the University nor the names of its contributors 50 | * may be used to endorse or promote products derived from this software 51 | * without specific prior written permission. 52 | * 53 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 | * SUCH DAMAGE. 64 | */ 65 | 66 | #include 67 | #include 68 | 69 | typedef unsigned char u_char; 70 | 71 | EDITORCONFIG_LOCAL 72 | int ec_strcasecmp(const char *s1, const char *s2) 73 | { 74 | const unsigned char 75 | *us1 = (const unsigned char*)s1, 76 | *us2 = (const unsigned char*)s2; 77 | 78 | while (tolower(*us1) == tolower(*us2++)) 79 | if (*us1++ == '\0') 80 | return (0); 81 | return (tolower(*us1) - tolower(*--us2)); 82 | } 83 | #endif /* !HAVE_STRCASECMP && !HAVE_STRICMP */ 84 | 85 | #ifndef HAVE_STRDUP 86 | /* 87 | * strdup function from FreeBSD 88 | * 89 | * Copyright (c) 1988, 1993 90 | * The Regents of the University of California. All rights reserved. 91 | * 92 | * Redistribution and use in source and binary forms, with or without 93 | * modification, are permitted provided that the following conditions 94 | * are met: 95 | * 1. Redistributions of source code must retain the above copyright 96 | * notice, this list of conditions and the following disclaimer. 97 | * 2. Redistributions in binary form must reproduce the above copyright 98 | * notice, this list of conditions and the following disclaimer in the 99 | * documentation and/or other materials provided with the distribution. 100 | * 4. Neither the name of the University nor the names of its contributors 101 | * may be used to endorse or promote products derived from this software 102 | * without specific prior written permission. 103 | * 104 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 105 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 106 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 107 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 108 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 109 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 110 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 111 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 112 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 113 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 114 | * SUCH DAMAGE. 115 | */ 116 | 117 | #include 118 | #include 119 | #include 120 | 121 | EDITORCONFIG_LOCAL 122 | char* ec_strdup(const char *str) 123 | { 124 | size_t len; 125 | char* copy; 126 | 127 | len = strlen(str) + 1; 128 | if ((copy = malloc(len)) == NULL) 129 | return (NULL); 130 | memcpy(copy, str, len); 131 | return (copy); 132 | } 133 | 134 | #endif /* !HAVE_STRDUP */ 135 | 136 | 137 | #ifndef HAVE_STRNDUP 138 | /* 139 | * strndup function from NetBSD 140 | * 141 | * $NetBSD: strndup.c,v 1.3 2007/01/14 23:41:24 cbiere Exp $ 142 | * 143 | * Copyright (c) 1988, 1993 144 | * The Regents of the University of California. All rights reserved. 145 | * 146 | * Redistribution and use in source and binary forms, with or without 147 | * modification, are permitted provided that the following conditions 148 | * are met: 149 | * 1. Redistributions of source code must retain the above copyright 150 | * notice, this list of conditions and the following disclaimer. 151 | * 2. Redistributions in binary form must reproduce the above copyright 152 | * notice, this list of conditions and the following disclaimer in the 153 | * documentation and/or other materials provided with the distribution. 154 | * 3. Neither the name of the University nor the names of its contributors 155 | * may be used to endorse or promote products derived from this software 156 | * without specific prior written permission. 157 | * 158 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 159 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 161 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 162 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 163 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 164 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 165 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 166 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 167 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 168 | * SUCH DAMAGE. 169 | */ 170 | 171 | #include "global.h" 172 | 173 | #include 174 | #include 175 | #include 176 | 177 | EDITORCONFIG_LOCAL 178 | char* ec_strndup(const char* str, size_t n) 179 | { 180 | size_t len; 181 | char* copy; 182 | 183 | for (len = 0; len < n && str[len]; len++) 184 | continue; 185 | 186 | if ((copy = malloc(len + 1)) == NULL) 187 | return (NULL); 188 | memcpy(copy, str, len); 189 | copy[len] = '\0'; 190 | return (copy); 191 | } 192 | 193 | #endif /* HAVE_STRNDUP */ 194 | 195 | /* 196 | * replace oldc with newc in the string str 197 | */ 198 | EDITORCONFIG_LOCAL 199 | char* str_replace(char* str, char oldc, char newc) 200 | { 201 | char* p; 202 | 203 | if (str == NULL) 204 | return NULL; 205 | 206 | for (p = str; *p != '\0'; p++) 207 | if (*p == oldc) 208 | *p = newc; 209 | 210 | return str; 211 | } 212 | 213 | #ifndef HAVE_STRLWR 214 | 215 | #include 216 | /* 217 | * convert the string to lowercase 218 | */ 219 | EDITORCONFIG_LOCAL 220 | char* ec_strlwr(char* str) 221 | { 222 | char* p; 223 | 224 | for (p = str; *p; ++p) 225 | *p = (char)tolower((unsigned char)*p); 226 | 227 | return str; 228 | } 229 | 230 | #endif /* !HAVE_STRLWR */ 231 | 232 | /* 233 | * is path an abosolute file path 234 | */ 235 | EDITORCONFIG_LOCAL 236 | _Bool is_file_path_absolute(const char* path) 237 | { 238 | if (!path) 239 | return 0; 240 | 241 | #if defined(UNIX) 242 | if (*path == '/') 243 | return 1; 244 | return 0; 245 | #elif defined(WIN32) 246 | return !PathIsRelative(path); 247 | #else 248 | # error "Either UNIX or WIN32 must be defined." 249 | #endif 250 | } 251 | -------------------------------------------------------------------------------- /src/lib/misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2019 EditorConfig Team 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef MISC_H__ 28 | #define MISC_H__ 29 | 30 | #include "global.h" 31 | 32 | #include 33 | 34 | #ifndef HAVE_STRCASECMP 35 | # ifdef HAVE_STRICMP 36 | # define strcasecmp stricmp 37 | # else /* HAVE_STRICMP */ 38 | EDITORCONFIG_LOCAL 39 | int ec_strcasecmp(const char *s1, const char *s2); 40 | # define strcasecmp ec_strcasecmp 41 | # endif /* HAVE_STRICMP */ 42 | #endif /* !HAVE_STRCASECMP */ 43 | #ifndef HAVE_STRDUP 44 | EDITORCONFIG_LOCAL 45 | char* ec_strdup(const char *str); 46 | # define strdup ec_strdup 47 | #endif 48 | #ifndef HAVE_STRNDUP 49 | EDITORCONFIG_LOCAL 50 | char* ec_strndup(const char* str, size_t n); 51 | # define strndup ec_strndup 52 | #endif 53 | EDITORCONFIG_LOCAL 54 | char* str_replace(char* str, char oldc, char newc); 55 | #ifndef HAVE_STRLWR 56 | EDITORCONFIG_LOCAL 57 | char* ec_strlwr(char* str); 58 | # define strlwr ec_strlwr 59 | #endif 60 | EDITORCONFIG_LOCAL 61 | _Bool is_file_path_absolute(const char* path); 62 | 63 | #endif /* !MISC_H__ */ 64 | -------------------------------------------------------------------------------- /src/lib/utarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 13 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 15 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | /* a dynamic array implementation using macros 25 | */ 26 | #ifndef UTARRAY_H 27 | #define UTARRAY_H 28 | 29 | #define UTARRAY_VERSION 2.1.0 30 | 31 | #include /* size_t */ 32 | #include /* memset, etc */ 33 | #include /* exit */ 34 | 35 | #ifdef __GNUC__ 36 | #define UTARRAY_UNUSED __attribute__((__unused__)) 37 | #else 38 | #define UTARRAY_UNUSED 39 | #endif 40 | 41 | #ifdef oom 42 | #error "The name of macro 'oom' has been changed to 'utarray_oom'. Please update your code." 43 | #define utarray_oom() oom() 44 | #endif 45 | 46 | #ifndef utarray_oom 47 | #define utarray_oom() exit(-1) 48 | #endif 49 | 50 | typedef void (ctor_f)(void *dst, const void *src); 51 | typedef void (dtor_f)(void *elt); 52 | typedef void (init_f)(void *elt); 53 | typedef struct { 54 | size_t sz; 55 | init_f *init; 56 | ctor_f *copy; 57 | dtor_f *dtor; 58 | } UT_icd; 59 | 60 | typedef struct { 61 | unsigned i,n;/* i: index of next available slot, n: num slots */ 62 | UT_icd icd; /* initializer, copy and destructor functions */ 63 | char *d; /* n slots of size icd->sz*/ 64 | } UT_array; 65 | 66 | #define utarray_init(a,_icd) do { \ 67 | memset(a,0,sizeof(UT_array)); \ 68 | (a)->icd = *(_icd); \ 69 | } while(0) 70 | 71 | #define utarray_done(a) do { \ 72 | if ((a)->n) { \ 73 | if ((a)->icd.dtor) { \ 74 | unsigned _ut_i; \ 75 | for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ 76 | (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ 77 | } \ 78 | } \ 79 | free((a)->d); \ 80 | } \ 81 | (a)->n=0; \ 82 | } while(0) 83 | 84 | #define utarray_new(a,_icd) do { \ 85 | (a) = (UT_array*)malloc(sizeof(UT_array)); \ 86 | if ((a) == NULL) { \ 87 | utarray_oom(); \ 88 | } \ 89 | utarray_init(a,_icd); \ 90 | } while(0) 91 | 92 | #define utarray_free(a) do { \ 93 | utarray_done(a); \ 94 | free(a); \ 95 | } while(0) 96 | 97 | #define utarray_reserve(a,by) do { \ 98 | if (((a)->i+(by)) > (a)->n) { \ 99 | char *utarray_tmp; \ 100 | while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ 101 | utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ 102 | if (utarray_tmp == NULL) { \ 103 | utarray_oom(); \ 104 | } \ 105 | (a)->d=utarray_tmp; \ 106 | } \ 107 | } while(0) 108 | 109 | #define utarray_push_back(a,p) do { \ 110 | utarray_reserve(a,1); \ 111 | if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ 112 | else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ 113 | } while(0) 114 | 115 | #define utarray_pop_back(a) do { \ 116 | if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ 117 | else { (a)->i--; } \ 118 | } while(0) 119 | 120 | #define utarray_extend_back(a) do { \ 121 | utarray_reserve(a,1); \ 122 | if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ 123 | else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ 124 | (a)->i++; \ 125 | } while(0) 126 | 127 | #define utarray_len(a) ((a)->i) 128 | 129 | #define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) 130 | #define _utarray_eltptr(a,j) ((a)->d + ((a)->icd.sz * (j))) 131 | 132 | #define utarray_insert(a,p,j) do { \ 133 | if ((j) > (a)->i) utarray_resize(a,j); \ 134 | utarray_reserve(a,1); \ 135 | if ((j) < (a)->i) { \ 136 | memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ 137 | ((a)->i - (j))*((a)->icd.sz)); \ 138 | } \ 139 | if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ 140 | else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ 141 | (a)->i++; \ 142 | } while(0) 143 | 144 | #define utarray_inserta(a,w,j) do { \ 145 | if (utarray_len(w) == 0) break; \ 146 | if ((j) > (a)->i) utarray_resize(a,j); \ 147 | utarray_reserve(a,utarray_len(w)); \ 148 | if ((j) < (a)->i) { \ 149 | memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ 150 | _utarray_eltptr(a,j), \ 151 | ((a)->i - (j))*((a)->icd.sz)); \ 152 | } \ 153 | if ((a)->icd.copy) { \ 154 | unsigned _ut_i; \ 155 | for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ 156 | (a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \ 157 | } \ 158 | } else { \ 159 | memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ 160 | utarray_len(w)*((a)->icd.sz)); \ 161 | } \ 162 | (a)->i += utarray_len(w); \ 163 | } while(0) 164 | 165 | #define utarray_resize(dst,num) do { \ 166 | unsigned _ut_i; \ 167 | if ((dst)->i > (unsigned)(num)) { \ 168 | if ((dst)->icd.dtor) { \ 169 | for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \ 170 | (dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \ 171 | } \ 172 | } \ 173 | } else if ((dst)->i < (unsigned)(num)) { \ 174 | utarray_reserve(dst, (num) - (dst)->i); \ 175 | if ((dst)->icd.init) { \ 176 | for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \ 177 | (dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \ 178 | } \ 179 | } else { \ 180 | memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \ 181 | } \ 182 | } \ 183 | (dst)->i = (num); \ 184 | } while(0) 185 | 186 | #define utarray_concat(dst,src) do { \ 187 | utarray_inserta(dst, src, utarray_len(dst)); \ 188 | } while(0) 189 | 190 | #define utarray_erase(a,pos,len) do { \ 191 | if ((a)->icd.dtor) { \ 192 | unsigned _ut_i; \ 193 | for (_ut_i = 0; _ut_i < (len); _ut_i++) { \ 194 | (a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \ 195 | } \ 196 | } \ 197 | if ((a)->i > ((pos) + (len))) { \ 198 | memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \ 199 | ((a)->i - ((pos) + (len))) * (a)->icd.sz); \ 200 | } \ 201 | (a)->i -= (len); \ 202 | } while(0) 203 | 204 | #define utarray_renew(a,u) do { \ 205 | if (a) utarray_clear(a); \ 206 | else utarray_new(a, u); \ 207 | } while(0) 208 | 209 | #define utarray_clear(a) do { \ 210 | if ((a)->i > 0) { \ 211 | if ((a)->icd.dtor) { \ 212 | unsigned _ut_i; \ 213 | for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ 214 | (a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \ 215 | } \ 216 | } \ 217 | (a)->i = 0; \ 218 | } \ 219 | } while(0) 220 | 221 | #define utarray_sort(a,cmp) do { \ 222 | qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ 223 | } while(0) 224 | 225 | #define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) 226 | 227 | #define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) 228 | #define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) 229 | #define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) 230 | #define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) 231 | #define utarray_eltidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1) 232 | 233 | /* last we pre-define a few icd for common utarrays of ints and strings */ 234 | static void utarray_str_cpy(void *dst, const void *src) { 235 | char **_src = (char**)src, **_dst = (char**)dst; 236 | *_dst = (*_src == NULL) ? NULL : strdup(*_src); 237 | } 238 | static void utarray_str_dtor(void *elt) { 239 | char **eltc = (char**)elt; 240 | if (*eltc != NULL) free(*eltc); 241 | } 242 | static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; 243 | static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL}; 244 | static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL}; 245 | 246 | 247 | #endif /* UTARRAY_H */ 248 | -------------------------------------------------------------------------------- /test.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [ValidateSet("pcre2","core")] 3 | [string] $proj = "core", 4 | 5 | [ValidateSet("ON","OFF")] 6 | [string] $static = "ON", 7 | 8 | [ValidateSet("Debug","Release")] 9 | [string] $config = "Release", 10 | 11 | [ValidateSet("x86","x64","arm64")] 12 | [string] $arch = "x64" 13 | ) 14 | 15 | $ErrorActionPreference="stop" 16 | 17 | 18 | $dest = "bin" 19 | 20 | if ((Test-Path $dest) -ne $true){ 21 | throw "Missing build path! Used init?" 22 | } 23 | 24 | $dest += "\$arch" 25 | 26 | if($static -eq "ON"){ 27 | $dest += "-static" 28 | } 29 | 30 | 31 | $bin = "$dest\build\bin" 32 | $dest += "\$proj" 33 | 34 | if ((Test-Path $dest) -ne $true){ 35 | throw "Missing build path! Used init?" 36 | } 37 | 38 | $env:Path += ";" + (Resolve-Path $bin) 39 | 40 | "Testing $proj" | Write-Host -ForegroundColor DarkGreen 41 | Push-Location $dest 42 | try { 43 | ctest -E utf_8_char -VV --output-on-failure . -C $config 44 | } finally { 45 | Pop-Location 46 | } 47 | --------------------------------------------------------------------------------