Import Upstream version 0.12.5

This commit is contained in:
rtlhq 2022-11-16 20:09:17 +08:00
commit f783fc51e5
92 changed files with 8546 additions and 0 deletions

25
.editorconfig Normal file
View File

@ -0,0 +1,25 @@
root = true
[*]
charset = utf-8
end_of_line = LF
[*.[ch]]
indent_style = space
indent_size = 4
max_line_length = 80
[README.md]
max_line_length = 80
[CMakeLists.txt]
indent_style = space
indent_size = 4
max_line_length = 80
[*.sh]
indent_style = space
indent_size = 2
[*.yml]
indent_style = space
indent_size = 2
[*.ps1]
indent_style = space
indent_size = 4

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
# Generated by CMake
CMakeCache.txt
CMakeFiles
Makefile
cmake_install.cmake
install_manifest.txt
# conf file
/cmake_uninstall.cmake
# Generated by CPack
/CPackConfig.cmake
/CPackSourceConfig.cmake
/_CPack_Packages
# Generated by CTest
/Testing
CTestTestfile.cmake
# By `make package`
/editorconfig*.deb
/editorconfig*.rpm
/editorconfig*.sh
/editorconfig*.tar.Z
/editorconfig*.tar.gz
/editorconfig*.zip
# Generated by `make`
/bin
/lib
# Eclipse
.project
# Editor backup/temporary files
~*
*~
*.swp

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "tests"]
path = tests
url = https://github.com/editorconfig/editorconfig-core-test.git

36
.travis.yml Normal file
View File

@ -0,0 +1,36 @@
language: c
compiler:
- gcc
- clang
dist: xenial
addons:
apt:
packages:
- libpcre2-dev
# Settings to try
env:
- OPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_STATICALLY_LINKED_EXE=ON"
- OPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_STATICALLY_LINKED_EXE=OFF"
- OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DBUILD_STATICALLY_LINKED_EXE=ON"
- OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DBUILD_STATICALLY_LINKED_EXE=OFF"
# Run the Build script
script:
- mkdir _build
- cd _build
- cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS
- VERBOSE=1 cmake --build . --target install
# Run Tests
after_script:
- ctest -VV --output-on-failure .
# Notify the mailing list
notifications:
email:
on_success: change
on_failure: always

32
CHANGELOG Normal file
View File

@ -0,0 +1,32 @@
v0.12.4
- Add Windows build scripts.
- Updated AppVeyor to use new scripts.
v0.12.3
- Bump required minimum cmake version to 2.8.12.
- Support pcre2 and drop support for pcre.
v0.12.2
- Add support for pkgconfig.
- Memory leaks and crash fixes.
- Improve error messages.
- Add CI on AppVeyor.
v0.12.1
- Fix an issue that libeditorconfig calls exit()---this should not be
called in a library function. (#12)
- Bump required minimum cmake version to 2.8.7.
- Use GNU installation dirs for OS portability. (#13)
v0.12.0
New dependency: pcre
- The glob engine is rewritten to take the advantages of pcre;
- support nested curly braces;
- number range match support (e.g. {3...120} matches integers from 3 to 120);
- slashes in brackets are considered special.

122
CMakeLists.txt Normal file
View File

@ -0,0 +1,122 @@
# CMakeLists.txt for core testing in
# editorconfig-core-c.
#
# Copyright (c) 2011-2019 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
cmake_minimum_required(VERSION 3.5.1)
cmake_policy(VERSION 3.5.1)
project(editorconfig VERSION "0.12.5" LANGUAGES C)
set(PROJECT_VERSION_SUFFIX "")
include(GNUInstallDirs)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake_Modules")
# set default compilation directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
# uninstall target
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
# package target
set(HOME_URL "http://editorconfig.org")
set(MAILING_LIST "editorconfig@googlegroups.com")
set(CPACK_PACKAGE_VENDOR "EditorConfig Team")
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "editorconfig")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Mac OS X
set(CPACK_GENERATOR "STGZ;TGZ;TZ")
elseif(UNIX)
# UNIX should be checked before WIN32 since cygwin makes UNIX and WIN32
# both true
set(CPACK_GENERATOR "STGZ;TGZ;TZ;DEB;RPM")
elseif(WIN32)
set(CPACK_GENERATOR "ZIP;NSIS")
endif()
set(CPACK_MONOLITHIC_INSTALL 1)
set(CPACK_SOURCE_GENERATOR "TGZ;TBZ2")
set(CPACK_PACKAGE_CONTACT "EditorConfig <${MAILING_LIST}>")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.md)
set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
# get the architecture of Deb package. The name of the architecture is not
# always the same with ${CMAKE_SYSTEM_PROCESSOR}
if(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
execute_process(COMMAND dpkg --print-architecture
OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${arch}")
endif()
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${HOME_URL})
set(CPACK_NSIS_CONTACT ${CPACK_PACKAGE_CONTACT})
set(CPACK_NSIS_DISPLAY_NAME "EditorConfig Core")
set(CPACK_NSIS_PACKAGE_HOMEPAGE ${HOME_URL})
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "editorconfig")
set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
set(CPACK_RPM_PACKAGE_LICENSE "Simplified BSD license")
set(CPACK_RPM_PACKAGE_URL ${HOME_URL})
include(CPack)
add_subdirectory(src)
add_subdirectory(doc)
add_subdirectory(include)
# Testing. Type "make test" to run tests. Only do this if the test submodule is
# checked out.
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt)
enable_testing()
set(EDITORCONFIG_CMD "editorconfig_bin")
set(EDITORCONFIG_CMD_IS_TARGET TRUE)
# TRUE => use the given CMake target, here, "editorconfig_bin",
# rather than an executable file named "editorconfig_bin".
# Used by tests/CMakeLists.txt.
add_subdirectory(tests)
message(STATUS "Tests enabled")
else()
message(WARNING
" 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.")
endif()
# This is a way to find the EXE name for debugging. However, it issues a
# CMake warning under policy CMP0026.
#get_target_property(out_name editorconfig_bin LOCATION)
#message(STATUS "main: Editorconfig binary will be in -${out_name}-")

View File

@ -0,0 +1,42 @@
# Copyright (C) 2018 Sven Strickroth <email AT cs-ware DOT de>
# Copyright (C) 2007-2009 LuaDist.
# Created by Peter Kapec <kapecp@gmail.com>
# Redistribution and use of this file is allowed according to the terms of the MIT license.
# For details see the COPYRIGHT file distributed with LuaDist.
# Note:
# Searching headers and libraries is very simple and is NOT as powerful as scripts
# distributed with CMake, because LuaDist defines directories to search for.
# Everyone is encouraged to contact the author with improvements. Maybe this file
# becomes part of CMake distribution sometimes.
# - Find pcre2
# Find the native PCRE2 headers and libraries.
#
# PCRE2_INCLUDE_DIRS - where to find pcre.h, etc.
# PCRE2_LIBRARIES - List of libraries when using pcre.
# PCRE2_FOUND - True if pcre found.
# Look for the header file.
FIND_PATH(PCRE2_INCLUDE_DIR NAMES pcre2.h)
# Look for the library.
FIND_LIBRARY(PCRE2_LIBRARY_RELEASE NAMES pcre2-8)
FIND_LIBRARY(PCRE2_LIBRARY_DEBUG NAMES pcre2-8d)
# Handle the QUIETLY and REQUIRED arguments and set PCRE2_FOUND to TRUE if all listed variables are TRUE.
INCLUDE(FindPackageHandleStandardArgs)
INCLUDE(SelectLibraryConfigurations)
SELECT_LIBRARY_CONFIGURATIONS(PCRE2)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_INCLUDE_DIR)
# Copy the results to the output variables.
IF(PCRE2_FOUND)
SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
SET(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})
ELSE(PCRE2_FOUND)
SET(PCRE2_LIBRARIES)
SET(PCRE2_INCLUDE_DIRS)
ENDIF(PCRE2_FOUND)
MARK_AS_ADVANCED(PCRE2_INCLUDE_DIRS PCRE2_LIBRARIES)

11
CONTRIBUTING Normal file
View File

@ -0,0 +1,11 @@
Thanks for contributing EditorConfig C Core!
To contribute, please first read through README and https://editorconfig.org to roughly understand
what EditorConfig is for and the role of EditorConfig C Core.
To make code contribution, you'll need to first fork our git repository, make changes in your
repository, and create a pull request. This is pretty standard for most projects hosted on GitHub.
If you are new to GitHub, take a look at this tutorial:
https://akrabat.com/the-beginners-guide-to-contributing-to-a-github-project/
When you make changes, also please remember to update CONTRIBUTORS and CHANGELOG if applicable.

5
CONTRIBUTORS Normal file
View File

@ -0,0 +1,5 @@
Contributors to EditorConfig C Core:
Hong Xu
Trey Hunner
William Swanson

171
INSTALL.md Normal file
View File

@ -0,0 +1,171 @@
Runtime Dependency
==================
- [PCRE2][] (>= 10.00, since version 0.12.0)
Installing From a Binary Package
================================
Windows binary packages can be downloaded [here](http://sourceforge.net/projects/editorconfig/files/EditorConfig-C-Core/).
Windows users can also install EditorConfig core by [Chocolatey](http://chocolatey.org/packages/editorconfig.core).
Debian (Jessie and later): `apt-get install editorconfig`
ArchLinux: `pacman -S editorconfig-core-c`
Mac OS X users can `brew install editorconfig` with [Homebrew](http://brew.sh).
Generally Linux users can also install with [LinuxBrew](https://github.com/Homebrew/linuxbrew)
by `brew install editorconfig`.
Manually Install from Source
============================
**(To build on Windows: Since it's usually a lot harder to manually build on Windows, see the
section "Automated Build on Windows" for an easier way.)**
In principle, you should be able to build the source using any C compiler that
is C99 compliant (i.e., virtually any C compiler that is not archaic). Before
installing, you need to install the building tool [cmake][] (version >= 2.8.12)
and dependency [PCRE2][]. To install cmake and pcre with package manager:
- Arch Linux: `pacman -S cmake pcre2`
- Homebrew on OS X: `brew install cmake pcre2`
- Ubuntu/Debian: `apt-get install cmake libpcre2-dev`
Make sure cmake is in your PATH environment variable. on Windows, you also need
to build PCRE2 from source. If you want to build the MT version of this library,
after running `cmake .` in the PCRE2 source directory, please replace all
occurrence of "MD" with "MT" in the CMakeCache.txt.
Switch to the root directory of editorconfig and execute the following command:
cmake .
If successful, the project file will be generated. There are various options
could be used when generating the project file:
-DBUILD_DOCUMENTATION=[ON|OFF] Default: ON
If this option is on and doxygen is found, the html documentation and
man pages will be generated.
e.g. cmake -DBUILD_DOCUMENTATION=OFF .
-DBUILD_STATICALLY_LINKED_EXE=[ON|OFF] Default: OFF
If this option is on, the executable will be linked statically to all
libraries. On MSVC, this means that EditorConfig will be statically
linked to the executable. On GCC, this means all libraries (glibc and
EditorConfig) are statically linked to the executable.
e.g. cmake -DBUILD_STATICALLY_LINKED_EXE=ON .
-DINSTALL_HTML_DOC=[ON|OFF] Default: OFF
If this option is on and BUILD_DOCUMENTATION is on, html documentation
will be installed when execute "make install" or something similar.
e.g. cmake -DINSTALL_HTML_DOC=ON .
-DDOXYGEN_EXECUTABLE=/path/to/doxygen
If doxygen could not be found automatically and you need to generate
documentation, try to set this option to the path to doxygen.
e.g. cmake -DDOXYGEN_EXECUTABLE=/opt/doxygen/bin/doxygen .
-DMSVC_MD=[ON|OFF] Default: OFF
Use /MD instead of /MT flag when compiling with Microsoft Visual C++. This
option takes no effect when using compilers other than Microsoft Visual
C++. Note that the option chosen here must be consistent with PCRE2.
e.g. We want to use /MD instead of /MT when compiling with MSVC.
cmake -DMSVC_MD=ON .
On UNIX/Linux with gcc, the project file is often a Makefile, in which case you
can type "make" to compile editorconfig. If you are using a different compiler
or platform the compilation command may differ. For example, if you generate an
NMake Makefile and you want to use Microsoft Visual C++ to build editorconfig,
then the build command would be "nmake".
After the compilation succeeds, use the following command to install (require
root or admin privilege):
make install
This command will copy all the files you need to corresponding directories:
editorconfig libraries will be copied to PREFIX/lib and executables will be
copied to PREFIX/bin.
Note that you have to use ldconfig or change LD_LIBRARY_PATH to specify the
PREFIX/lib as one of the library searching directory on UNIX/Linux to make sure
that source files could be linked to the libraries and executables depending on
these libraries could be executed properly.
Automated Build on Windows
==========================
Requirements on Windows are [Visual Studio] 2013, 2015 or 2017, [cmake] 2.8.12 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.
Non-static build is currently not supported.
Download pcre2
--------------
You have to download and extract the pcre2 sources after checkout.
```powershell
~> ./init.ps1 [-pcre 10.32]
```
Arguments:
-pcre Optional; pcre2 version to download.
Build Library
-------------
To build pcre2 and editorconfig core library in one step use the `-init` and `-install` arguments at the same time.
```powershell
~> ./build.ps1 -init -install
```
The `-init` argument will generate the required cmake build files for Visual Studio. This is required after initial checkout or `CMakeLists.txt` changes.
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.
For the other arguments please see below.
```powershell
~> ./build.ps1 [-proj all | core | pcre2] [-init] [-install] [-vsver 15 | 14 | 12] [-arch x64 | x86] [-config Release | Debug]
```
Arguments:
-proj Optional; Project to build.
-init Optional; (Re)Generate cmake build files, required first time or on `CMakeLists.txt` changes.
-install Optional; Install to `bin/$(ARCH)-static/build` folder.
-vsver Optional; Visual Studio version (major version number) to use.
-arch Optional; Architecture to build for.
-config Optional; Debug or release build.
### Build pcre2 Library
```powershell
~> ./build.ps1 -proj pcre2 -init -install
```
### Build EditorConfig Core Library
```powershell
~> ./build.ps1 -proj core -init
```
### Run Tests
On Windows the test `utf_8_char` is disabled.
```powershell
~> ./test.ps1 [-arch x64 | x86] [-config Release | Debug]
```
Arguments:
-arch Optional; Architecture to build for.
-config Optional; Debug or release build.
[cmake]: https://cmake.org
[PCRE2]: https://pcre.org/
[Visual Studio]: https://visualstudio.microsoft.com

30
LICENSE Normal file
View File

@ -0,0 +1,30 @@
Unless otherwise stated, all files are distributed under the Simplified BSD
license. The inih(`src/lib/ini.c` and `src/lib/ini.h`) library is distributed
under the New BSD license. `src/lib/utarray.h` is distributed under the Revised
BSD License. The See LICENSE file for details. Some code in src/lib/misc.c is
distributed under their own license (see the source file for details).
Copyright (c) 2011-2013 EditorConfig Team, including Hong Xu and Trey Hunner
Copyright (c) 2014 Hong Xu <hong AT topbug DOT net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

65
README.md Normal file
View File

@ -0,0 +1,65 @@
[EditorConfig][]
================
[![Build Status](https://secure.travis-ci.org/editorconfig/editorconfig-core-c.svg?branch=master)](http://travis-ci.org/editorconfig/editorconfig-core-c)
[![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)
EditorConfig makes it easy to maintain the correct coding style when switching
between different text editors and between different projects. The
EditorConfig project maintains a file format and plugins for various text
editors which allow this file format to be read and used by those editors. For
information on the file format and supported text editors, see the
[EditorConfig website][EditorConfig].
Contributing
------------
This is the README file for the *EditorConfig C Core* codebase. This code
produces a program that accepts a filename as input and will look for
`.editorconfig` files with sections applicable to the given file, outputting
any properties found.
When developing an editor plugin for reading EditorConfig files, the
EditorConfig core code can be used to locate and parse these files. This means
the file locator, INI parser, and file globbing mechanisms can all be
maintained in one code base, resulting in less code repetition between plugins.
Installation
------------
See the [INSTALL.md][] file for instructions.
Getting Help
------------
For help with the EditorConfig C Core code, please write to our
[mailing list][]. Bugs and feature requests should be submitted to our
[issue tracker][]. If you find any security bugs, please send them privately to
`hong AT topbug DOT net` -- they need to be embargoed before fixed.
If you are writing a plugin a language that can import C libraries, you may
want to import and use the EditorConfig library directly. If you do use the
EditorConfig core as a C library, check the [documentation][] for latest stable
version for help. The documentation for latest development version is also
available [online][dev doc].
License
-------
Unless otherwise stated, all files are distributed under the Simplified BSD
license. The inih(`src/lib/ini.c` and `src/lib/ini.h`) library is distributed
under the New BSD license. `src/lib/utarray.h` is distributed under the Revised
BSD License. The See LICENSE file for details. Some code in `src/lib/misc.c` is
distributed under their own license (see the source file for details). See the
LICENSE file for details.
[EditorConfig]: http://editorconfig.org "EditorConfig Homepage"
[INSTALL.md]: https://github.com/editorconfig/editorconfig-core-c/blob/master/INSTALL.md
[mailing list]: http://groups.google.com/group/editorconfig "EditorConfig mailing list"
[issue tracker]: https://github.com/editorconfig/editorconfig-core-c/issues
[documentation]: http://docs.editorconfig.org/ "EditorConfig C Core documentation"
[downloads]: https://sourceforge.net/projects/editorconfig/files/EditorConfig-C-Core/
[dev doc]: http://docs.editorconfig.org/en/master "EditorConfig C Core latest development version documentation"

29
appveyor.yml Normal file
View File

@ -0,0 +1,29 @@
image:
- Visual Studio 2017
environment:
CONFIG: Release
VSVER: 15
matrix:
- ARCH: x86
- ARCH: x64
install:
- cmake --version
- git submodule update --init
# Download PCRE2 sources
- ps: ./init.ps1 -pcre 10.32
# Build and install PCRE2
- ps: ./build.ps1 -proj pcre2 -config $env:CONFIG -arch $env:ARCH -vsver $env:VSVER -init -install
build_script:
# Build and install editorconfig-core-c
- ps: ./build.ps1 -proj core -config $env:CONFIG -arch $env:ARCH -vsver $env:VSVER -init -install
test_script:
# Run the core tests
- ps: ./test.ps1 -proj core -config $env:CONFIG -arch $env:ARCH
on_failure:
- echo. && echo. && echo. && echo "Tests for editorconfig-core-c failed. Here is their detailed output:" && echo. && echo. && echo.
- type .\bin\x64-static\core\Testing\Temporary\LastTest.log

137
build.ps1 Normal file
View File

@ -0,0 +1,137 @@
param(
[ValidateSet("pcre2","core", "all")]
[string] $proj = "all",
[switch] $init,
[switch] $install,
[ValidateSet("ON","OFF")]
[string] $static = "ON",
[ValidateSet("Debug","Release")]
[string] $config = "Release",
[ValidateSet("x86","x64")]
[string] $arch = "x64",
[ValidateSet("15","14","12")]
[int] $vsver = 15
)
$ErrorActionPreference="stop"
function exec
{
param
(
[ScriptBlock] $ScriptBlock,
[int[]] $AllowedExitCodes = @(0)
)
$backupErrorActionPreference = $script:ErrorActionPreference
$script:ErrorActionPreference = "Continue"
try
{
& $ScriptBlock
if ($AllowedExitCodes -notcontains $LASTEXITCODE)
{
throw "Execution failed with exit code $LASTEXITCODE"
}
}
finally
{
$script:ErrorActionPreference = $backupErrorActionPreference
}
}
if ($proj -eq "all"){
.\build.ps1 -proj pcre2 -init:$init -install:$install -arch $arch -config $config -static $static
.\build.ps1 -proj core -init:$init -install:$install -arch $arch -config $config -static $static
return
}
$PREFIX="../build"
$dest = "bin"
if ((Test-Path $dest) -ne $true){
throw "Missing build path! Used init?"
}
$dest += "\$arch"
if($static -eq "ON"){
$dest += "-static"
}
$dest += "\$proj"
if ($init) {
"Generating $proj build files" | Write-Host -ForegroundColor DarkGreen
$gen = "Visual Studio "
switch ($vsver) {
15 {
$gen += "15 2017"
}
14 {
$gen += "14 2015"
}
12 {
$gen += "12 2013"
}
default {
throw "Visual Studio version $vsver not supported!"
}
}
if($arch -eq "x64"){
$gen += " Win64"
}
mkdir $dest -ErrorAction SilentlyContinue | Out-Null
Push-Location $dest
try {
switch ($proj) {
pcre2 {
$BUILD_SHARED_LIBS = "ON"
if ($static -eq "ON"){ $BUILD_SHARED_LIBS = "OFF"}
exec { cmake -G "$gen" -DCMAKE_INSTALL_PREFIX="$PREFIX" -DPCRE2_STATIC_RUNTIME="$static" `
-DBUILD_SHARED_LIBS="$BUILD_SHARED_LIBS" -DPCRE2_BUILD_PCRE2GREP="OFF" -DPCRE2_BUILD_TESTS="OFF" `
"../../pcre2" }
}
core {
$MSVC_MD = "ON"
if ($static -eq "ON"){ $MSVC_MD = "OFF"}
exec { cmake -G "$gen" -DCMAKE_INSTALL_PREFIX="$PREFIX" -DMSVC_MD="$MSVC_MD" -DPCRE2_STATIC="$static" `
"../../../." }
}
}
} finally {
Pop-Location
}
}
if ((Test-Path $dest) -ne $true){
throw "Missing build path! Used init?"
}
"Compiling $proj" | Write-Host -ForegroundColor DarkGreen
exec { cmake --build $dest `-- /p:Configuration=$config }
if ($install) {
"Installing $proj" | Write-Host -ForegroundColor DarkGreen
switch ($proj) {
pcre2 {
exec { cmake --build $dest --target install `-- /p:Configuration=$config }
}
core {
exec { cmake --build $dest --target install `-- /p:Configuration=$config }
}
}
}

56
cmake_uninstall.cmake.in Normal file
View File

@ -0,0 +1,56 @@
#
# Copyright (c) 2011-2012 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Suppress the warning from cmake 2.6 or higher (list command no longer ignores
# empty elements)
if(NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6)
cmake_policy(SET CMP0007 NEW)
endif(NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6)
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR
"Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
list(REVERSE files)
foreach(file ${files})
message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
if(EXISTS "$ENV{DESTDIR}${file}")
execute_process(
COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
OUTPUT_VARIABLE rm_out
RESULT_VARIABLE rm_retval)
if(NOT ${rm_retval} EQUAL 0)
message(FATAL_ERROR
"Problem when removing \"$ENV{DESTDIR}${file}\"")
endif(NOT ${rm_retval} EQUAL 0)
else(EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
endif(EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)

4
doc/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/Doxyfile
/Doxyfile_cmd
/html
/man

135
doc/CMakeLists.txt Normal file
View File

@ -0,0 +1,135 @@
#
# Copyright (c) 2011-2013 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
option(BUILD_DOCUMENTATION
"Use Doxygen to create the HTML and man page documentation" ON)
# Whether to install the html documentation. Only valid when
# BUILD_DOCUMENTATION is set to ON
option(INSTALL_HTML_DOC
"Install the generated html documentation" OFF)
if(BUILD_DOCUMENTATION)
find_package(Doxygen)
if(DOXYGEN_FOUND)
# Generating the main part of the doc. Although it generates
# editorconfig.3, we discard that file
set(DOC_MAN_SECTION 3)
set(DOC_GEN_HTML "YES")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/html/index.html
COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile"
MAIN_DEPENDENCY
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
DEPENDS
${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig.h
${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig_handle.h
${PROJECT_SOURCE_DIR}/logo/logo.png
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(EC_MANPAGE_DIR ${CMAKE_CURRENT_BINARY_DIR}/man)
set(EC_MANPAGE1_DIR ${EC_MANPAGE_DIR}/man1)
set(EC_MANPAGE3_DIR ${EC_MANPAGE_DIR}/man3)
set(EC_MANPAGE5_DIR ${EC_MANPAGE_DIR}/man5)
# Generating man page of editorconfig command. Although we have other
# .1s other than editorconfig.1, we ignore them
set(DOC_MAN_SECTION 1)
set(DOC_GEN_HTML "NO")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-1)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/man/man1/editorconfig.1
COMMAND
${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-1"
MAIN_DEPENDENCY
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
DEPENDS
${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig.h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Generating man page editorconfig-format.5. Although we have other
# .5s other than editorconfig-format.5, we ignore them
set(DOC_MAN_SECTION 5)
set(DOC_GEN_HTML "NO")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-5)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/man/man5/editorconfig-format.5
COMMAND
${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-5"
MAIN_DEPENDENCY
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
DEPENDS
${PROJECT_SOURCE_DIR}/include/editorconfig/editorconfig.h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# doc generation target
add_custom_target(doc ALL DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/html/index.html
${EC_MANPAGE1_DIR}/editorconfig.1
${EC_MANPAGE5_DIR}/editorconfig-format.5)
# install man pages
# Since we cannot avoid generating editorconfig.3 with doxygen, which
# is the manpage of the command line interface with a manpage number 3,
# we need to exclude it when installing man3. Same for
# editorconfig-format.3
install(DIRECTORY ${EC_MANPAGE3_DIR}
DESTINATION "${CMAKE_INSTALL_MANDIR}"
PATTERN editorconfig.3 EXCLUDE
PATTERN editorconfig-format.3 EXCLUDE
REGEX ._include_. EXCLUDE)
install(FILES
${EC_MANPAGE1_DIR}/editorconfig.1
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
install(FILES
${EC_MANPAGE5_DIR}/editorconfig-format.5
DESTINATION "${CMAKE_INSTALL_MANDIR}/man5")
# "make clean" should also clean generated docs
set_directory_properties(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "html;man")
if(INSTALL_HTML_DOC)
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/doc/editorconfig")
endif(INSTALL_HTML_DOC)
else(DOXYGEN_FOUND)
message(WARNING
" Doxygen is not found. Documentation will not be generated.")
endif(DOXYGEN_FOUND)
endif(BUILD_DOCUMENTATION)

2332
doc/Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

31
include/CMakeLists.txt Normal file
View File

@ -0,0 +1,31 @@
#
# Copyright (c) 2011-2012 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
install(FILES
editorconfig/editorconfig.h
editorconfig/editorconfig_handle.h
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/editorconfig")

View File

@ -0,0 +1,328 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*!
* @mainpage EditorConfig C Core Documentation
*
* This is the documentation of EditorConfig C Core. In this documentation, you
* could find the document of the @ref editorconfig and the document of
* EditorConfig Core C APIs in editorconfig.h and editorconfig_handle.h.
*/
/*!
* @page editorconfig EditorConfig Command
*
* @section usage Usage of the `editorconfig` command line tool
*
* Usage: editorconfig <em>[OPTIONS]</em> FILEPATH1 [FILEPATH2 FILEPATH3 ...]
*
* FILEPATH can be a hyphen (-) if you want to path(s) to be read from stdin.
* Hyphen can also be specified with other file names. In this way, both file
* paths from stdin and the paths specified on the command line will be used.
* If more than one path specified on the command line, or the paths are
* reading from stdin (even only one path is read from stdin), the output
* format would be INI format, instead of the simple "key=value" lines.
*
* @htmlonly
* <table cellpadding="5" cellspacing="5">
*
* <tr>
* <td><em>-f</em></td>
* <td>Specify conf filename other than ".editorconfig".</td>
* </tr>
*
* <tr>
* <td><em>-b</em></td>
* <td>Specify version (used by devs to test compatibility).</td>
* </tr>
*
* <tr>
* <td><em>-h</em> OR <em>--help</em></td>
* <td>Print this help message.</td>
* </tr>
*
* <tr>
* <td><em>--version</em></td>
* <td>Display version information.</td>
* </tr>
*
* </table>
* @endhtmlonly
* @manonly
*
* -f Specify conf filename other than ".editorconfig".
*
* -b Specify version (used by devs to test compatibility).
*
* -h OR --help Print this help message.
*
* --version Display version information.
*
* @endmanonly
*
* @section related Related Pages
*
* @ref editorconfig-format
* @manonly
* editorconfig-format(5)
* @endmanonly
*/
/*!
* @page editorconfig-format EditorConfig File Format
*
* @section format EditorConfig File Format
*
* EditorConfig files use an INI format that is compatible with the format used
* by Python ConfigParser Library, but [ and ] are allowed in the section names.
* The section names are filepath globs, similar to the format accepted by
* gitignore. Forward slashes (/) are used as path separators and semicolons (;)
* or octothorpes (#) are used for comments. Comments should go individual lines.
* EditorConfig files should be UTF-8 encoded, with either CRLF or LF line
* separators.
*
* Filename globs containing path separators (/) match filepaths in the same
* way as the filename globs used by .gitignore files. Backslashes (\\) are
* not allowed as path separators.
*
* A semicolon character (;) starts a line comment that terminates at the end
* of the line. Line comments and blank lines are ignored when parsing.
* Comments may be added to the ends of non-empty lines. An octothorpe
* character (#) may be used instead of a semicolon to denote the start of a
* comment.
*
* @section file-location Filename and Location
*
* When a filename is given to EditorConfig a search is performed in the
* directory of the given file and all parent directories for an EditorConfig
* file (named ".editorconfig" by default). All found EditorConfig files are
* searched for sections with section names matching the given filename. The
* search will stop if an EditorConfig file is found with the root property set
* to true or when reaching the root filesystem directory.
*
* Files are read top to bottom and the most recent rules found take
* precedence. If multiple EditorConfig files have matching sections, the rules
* from the closer EditorConfig file are read last, so properties in closer
* files take precedence.
*
* @section patterns Wildcard Patterns
*
* Section names in EditorConfig files are filename globs that support pattern
* matching through Unix shell-style wildcards. These filename globs recognize
* the following as special characters for wildcard matching:
*
* @htmlonly
* <table>
* <tr><td><code>*</code></td><td>Matches any string of characters, except path separators (<code>/</code>)</td></tr>
* <tr><td><code>**</code></td><td>Matches any string of characters</td></tr>
* <tr><td><code>?</code></td><td>Matches any single character</td></tr>
* <tr><td><code>[seq]</code></td><td>Matches any single character in <i>seq</i></td></tr>
* <tr><td><code>[!seq]</code></td><td>Matches any single character not in <i>seq</i></td></tr>
* <tr><td><code>{s1,s2,s3}</code></td><td>Matches any of the strings given (separated by commas, can be nested)</td></tr>
* <tr><td><code>{num1..num2}</code></td><td>Matches any integer numbers between num1 and num2, where num1 and num2 can be either positive or negative</td></tr>
* </table>
* @endhtmlonly
* @manonly
* * 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
*
* @endmanonly
*
* The backslash character (\) can be used to escape a character so it is not
* interpreted as a special character.
*
* The maximum length of a section name is 4096 characters. All sections
* exceeding this limit are ignored.
*
* @section properties Supported Properties
*
* EditorConfig file sections contain properties, which are name-value pairs
* separated by an equal sign (=). EditorConfig plugins will ignore unrecognized
* property names and properties with invalid values.
*
* Here is the list of all property names understood by EditorConfig and all valid values for these properties:
*
* <ul>
* <li><strong>indent_style</strong>: set to "tab" or "space" to use hard tabs or soft tabs respectively. The values are case insensitive.</li>
* <li><strong>indent_size</strong>: 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 <strong>indent_size</strong> will be set to the tab size, which should be tab_width if <strong>tab_width</strong> is specified, or the tab size set by editor if <strong>tab_width</strong> is not specified. The values are case insensitive.</li>
* <li><strong>tab_width</strong>: a whole number defining the number of columns used to represent a tab character. This defaults to the value of <strong>indent_size</strong> and should not usually need to be specified.</li>
* <li><strong>end_of_line</strong>: set to "lf", "cr", or "crlf" to control how line breaks are represented. The values are case insensitive.</li>
* <li><strong>charset</strong>: 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.</li>
* <li><strong>trim_trailing_whitespace</strong>: set to "true" to remove any whitespace characters preceeding newline characters and "false" to ensure it doesn't.</li>
* <li><strong>insert_final_newline</strong>: set to "true" ensure file ends with a newline when saving and "false" to ensure it doesn't.</li>
* <li><strong>root</strong>: special property that should be specified at the top of the file outside of any sections. Set to "true" to stop <code>.editorconfig</code> files search on current file. The value is case insensitive.</li>
* </ul>
*
* For any property, a value of "unset" is to remove the effect of that
* property, even if it has been set before. For example, add "indent_size =
* unset" to undefine indent_size property (and use editor default).
*
* Property names are case insensitive and all property names are lowercased
* when parsing. The maximum length of a property name is 50 characters and the
* maximum length of a property value is 255 characters. Any property beyond
* these limits would be ignored.
*/
/*!
* @file editorconfig/editorconfig.h
* @brief Header file of EditorConfig.
*
* Related page: @ref editorconfig-format
* @manonly
* editorconfig-format(5)
* @endmanonly
*
* @author EditorConfig Team
*/
#ifndef EDITORCONFIG_EDITORCONFIG_H__
#define EDITORCONFIG_EDITORCONFIG_H__
/* When included from a user program, EDITORCONFIG_EXPORT may not be defined,
* and we define it here*/
#ifndef EDITORCONFIG_EXPORT
# define EDITORCONFIG_EXPORT
#endif
#include <editorconfig/editorconfig_handle.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @brief Parse editorconfig files corresponding to the file path given by
* full_filename, and related information is input and output in h.
*
* An example is available at
* <a href=https://github.com/editorconfig/editorconfig-core/blob/master/src/bin/main.c>src/bin/main.c</a>
* in EditorConfig C Core source code.
*
* @param full_filename The full path of a file that is edited by the editor
* for which the parsing result is.
*
* @param h The @ref editorconfig_handle to be used and returned from this
* function (including the parsing result). The @ref editorconfig_handle should
* be created by editorconfig_handle_init().
*
* @retval 0 Everything is OK.
*
* @retval "Positive Integer" A parsing error occurs. The return value would be
* the line number of parsing error. err_file obtained from h by calling
* editorconfig_handle_get_err_file() will also be filled with the file path
* that caused the parsing error.
*
* @retval "Negative Integer" Some error occured. See below for the reason of
* the error for each return value.
*
* @retval EDITORCONFIG_PARSE_NOT_FULL_PATH The full_filename is not a full
* path name.
*
* @retval EDITORCONFIG_PARSE_MEMORY_ERROR A memory error occurs.
*
* @retval EDITORCONFIG_PARSE_VERSION_TOO_NEW The required version specified in
* @ref editorconfig_handle is greater than the current version.
*
*/
EDITORCONFIG_EXPORT
int editorconfig_parse(const char* full_filename, editorconfig_handle h);
/*!
* @brief Get the error message from the error number returned by
* editorconfig_parse().
*
* An example is available at
* <a href=https://github.com/editorconfig/editorconfig-core/blob/master/src/bin/main.c>src/bin/main.c</a>
* in EditorConfig C Core source code.
*
* @param err_num The error number that is used to obtain the error message.
*
* @return The error message corresponding to err_num.
*/
EDITORCONFIG_EXPORT
const char* editorconfig_get_error_msg(int err_num);
/*!
* editorconfig_parse() return value: the full_filename parameter of
* editorconfig_parse() is not a full path name
*/
#define EDITORCONFIG_PARSE_NOT_FULL_PATH (-2)
/*!
* editorconfig_parse() return value: a memory error occurs.
*/
#define EDITORCONFIG_PARSE_MEMORY_ERROR (-3)
/*!
* editorconfig_parse() return value: the required version specified in @ref
* editorconfig_handle is greater than the current version.
*/
#define EDITORCONFIG_PARSE_VERSION_TOO_NEW (-4)
/*!
* @brief Get the version number of EditorConfig.
*
* An example is available at
* <a href=https://github.com/editorconfig/editorconfig-core/blob/master/src/bin/main.c>src/bin/main.c</a>
* in EditorConfig C Core source code.
*
* @param major If not null, the integer pointed by major will be filled with
* the major version of EditorConfig.
*
* @param minor If not null, the integer pointed by minor will be filled with
* the minor version of EditorConfig.
*
* @param patch If not null, the integer pointed by patch will be filled
* with the patch version of EditorConfig.
*
* @return None.
*/
EDITORCONFIG_EXPORT
void editorconfig_get_version(int* major, int* minor, int* patch);
/*!
* @brief Get the version suffix.
*
* @return The version suffix, such as "-development" for a development
* version, empty string for a stable version.
*/
EDITORCONFIG_EXPORT
const char* editorconfig_get_version_suffix(void);
#ifdef __cplusplus
}
#endif
#endif /* !EDITORCONFIG_EDITORCONFIG_H__ */

View File

@ -0,0 +1,193 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*!
* @file editorconfig/editorconfig_handle.h
* @brief Header file of EditorConfig handle.
*
* @author EditorConfig Team
*/
#ifndef EDITORCONFIG_EDITORCONFIG_HANDLE_H__
#define EDITORCONFIG_EDITORCONFIG_HANDLE_H__
/* When included from a user program, EDITORCONFIG_EXPORT may not be defined,
* and we define it here*/
#ifndef EDITORCONFIG_EXPORT
# define EDITORCONFIG_EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @brief The editorconfig handle object type
*/
typedef void* editorconfig_handle;
/*!
* @brief Create and intialize a default editorconfig_handle object.
*
* @retval NULL Failed to create the editorconfig_handle object.
*
* @retval non-NULL The created editorconfig_handle object is returned.
*/
EDITORCONFIG_EXPORT
editorconfig_handle editorconfig_handle_init(void);
/*!
* @brief Destroy an editorconfig_handle object
*
* @param h The editorconfig_handle object needs to be destroyed.
*
* @retval zero The editorconfig_handle object is destroyed successfully.
*
* @retval non-zero Failed to destroy the editorconfig_handle object.
*/
EDITORCONFIG_EXPORT
int editorconfig_handle_destroy(editorconfig_handle h);
/*!
* @brief Get the err_file field of an editorconfig_handle object
*
* @param h The editorconfig_handle object whose err_file needs to be obtained.
*
* @retval NULL No error file exists.
*
* @retval non-NULL The pointer to the path of the file caused the parsing
* error is returned.
*/
EDITORCONFIG_EXPORT
const char* editorconfig_handle_get_err_file(editorconfig_handle h);
/*!
* @brief Get the version fields of an editorconfig_handle object.
*
* @param h The editorconfig_handle object whose version field need to be
* obtained.
*
* @param major If not null, the integer pointed by major will be filled with
* the major version field of the editorconfig_handle object.
*
* @param minor If not null, the integer pointed by minor will be filled with
* the minor version field of the editorconfig_handle object.
*
* @param patch If not null, the integer pointed by patch will be filled
* with the patch version field of the editorconfig_handle object.
*
* @return None.
*/
EDITORCONFIG_EXPORT
void editorconfig_handle_get_version(const editorconfig_handle h, int* major,
int* minor, int* patch);
/*!
* @brief Set the version fields of an editorconfig_handle object.
*
* @param h The editorconfig_handle object whose version fields need to be set.
*
* @param major If not less than 0, the major version field will be set to
* major. If this parameter is less than 0, the major version field of the
* editorconfig_handle object will remain unchanged.
*
* @param minor If not less than 0, the minor version field will be set to
* minor. If this parameter is less than 0, the minor version field of the
* editorconfig_handle object will remain unchanged.
*
* @param patch If not less than 0, the patch version field will be set to
* patch. If this parameter is less than 0, the patch version field of the
* editorconfig_handle object will remain unchanged.
*
* @return None.
*/
EDITORCONFIG_EXPORT
void editorconfig_handle_set_version(const editorconfig_handle h, int major,
int minor, int patch);
/*!
* @brief Set the conf_file_name field of an editorconfig_handle object.
*
* @param h The editorconfig_handle object whose conf_file_name field needs to
* be set.
*
* @param conf_file_name The new value of the conf_file_name field of the
* editorconfig_handle object.
*
* @return None.
*/
EDITORCONFIG_EXPORT
void editorconfig_handle_set_conf_file_name(editorconfig_handle h,
const char* conf_file_name);
/*!
* @brief Get the conf_file_name field of an editorconfig_handle object.
*
* @param h The editorconfig_handle object whose conf_file_name field needs to
* be obtained.
*
* @return The value of the conf_file_name field of the editorconfig_handle
* object.
*/
EDITORCONFIG_EXPORT
const char* editorconfig_handle_get_conf_file_name(const editorconfig_handle h);
/*!
* @brief Get the nth name and value fields of an editorconfig_handle object.
*
* @param h The editorconfig_handle object whose name and value fields need to
* be obtained.
*
* @param n The zero-based index of the name and value fields to be obtained.
*
* @param name If not null, *name will be set to point to the obtained name.
*
* @param value If not null, *value will be set to point to the obtained value.
*
* @return None.
*/
EDITORCONFIG_EXPORT
void editorconfig_handle_get_name_value(const editorconfig_handle h, int n,
const char** name, const char** value);
/*!
* @brief Get the count of name and value fields of an editorconfig_handle
* object.
*
* @param h The editorconfig_handle object whose count of name and value fields
* need to be obtained.
*
* @return the count of name and value fields of the editorconfig_handle
* object.
*/
EDITORCONFIG_EXPORT
int editorconfig_handle_get_name_value_count(const editorconfig_handle h);
#ifdef __cplusplus
}
#endif
#endif /* !EDITORCONFIG_EDITORCONFIG_HANDLE_H__ */

43
include/util.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2019 Hong Xu <hong@topbug.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Small useful inline functions.
*/
#ifndef UTIL_H__
#define UTIL_H__
/*
* An version of atoi that handles strings corresponding to integers that are
* out of range.
*/
static inline int ec_atoi(const char* str)
{
return (int) strtol(str, (char **) NULL, 10);
}
#endif /* !UTIL_H__ */

30
init.ps1 Normal file
View File

@ -0,0 +1,30 @@
param(
$pcre="10.32"
)
$ErrorActionPreference="Stop"
$dest = "bin"
if (Test-Path $dest){
Remove-Item $dest -Recurse -Force -Confirm:$false
}
New-Item $dest -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
#####################################################################
# pcre
#####################################################################
$url = "https://ftp.pcre.org/pub/pcre/pcre2-$($pcre).zip"
$output = "$dest\pcre-$($pcre).zip"
"Downloading pcre2 v$pcre sources" | Write-Host -ForegroundColor DarkGreen
Start-BitsTransfer -Source $url -Destination $output
"Extracting pcre2 v$pcre sources" | Write-Host -ForegroundColor DarkGreen
Expand-Archive -Path $output -DestinationPath $dest
Rename-Item -Path "$dest\pcre2-$($pcre)" -NewName "pcre2"
if(Test-Path "pcre-$($pcre).patch") {
"Applying pcre patches" | Write-Host -ForegroundColor DarkGreen
.\patch.ps1 -patch "pcre-$($pcre).patch" -path $dest\pcre2
}

BIN
logo/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

14
mk-src-archive.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
# Make a source archive for the current EditorConfig version.
if [ $# -ne 1 ]; then
echo "Usage: "$0" VERSION"
echo ""
echo "e.g. "$0" 0.10.0"
echo
exit
fi
curl -L https://raw.githubusercontent.com/Kentzo/git-archive-all/master/git_archive_all.py | python - editorconfig-core-c-$*.tar.gz
curl -L https://raw.githubusercontent.com/Kentzo/git-archive-all/master/git_archive_all.py | python - editorconfig-core-c-$*.zip

42
patch.ps1 Normal file
View File

@ -0,0 +1,42 @@
param(
$path,
$patch
)
$ErrorActionPreference="Stop"
$dest = "tools"
if ((Test-Path $dest) -ne $true){
New-Item $dest -ItemType Directory | Out-Null
}
#####################################################################
# patch
#####################################################################
if (-ne Test-Path "$dest\bin\patch.exe") {
$url = "http://gnuwin32.sourceforge.net/downlinks/patch-bin-zip.php"
$output = "$dest\patch.zip"
"Downloading patch binary" | Write-Host -ForegroundColor DarkGreen
Start-BitsTransfer -Source $url -Destination $output
"Extracting patch binary" | Write-Host -ForegroundColor DarkGreen
Expand-Archive -Path $output -DestinationPath $dest
@"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<!-- Make sure that UAC believes
that it does not require administrative privilege -->
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"@ | Out-File -FilePath $dest\bin\patch.exe.manifest -Encoding utf8
(Get-ChildItem $dest\bin\patch.exe).LastWriteTime = Get-Date
}
Get-Content $patch | & $dest\bin\patch.exe -d $path

1
src/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/auto

92
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,92 @@
#
# Copyright (c) 2011-2019 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
include(CheckFunctionExists)
include(CheckTypeSize)
option(BUILD_STATICALLY_LINKED_EXE
"Statically link all libraries when building the executable. This will also disable shared library."
OFF)
if(BUILD_STATICALLY_LINKED_EXE AND NOT WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
endif()
find_package(PCRE2 REQUIRED)
if(PCRE2_FOUND)
include_directories(BEFORE ${PCRE2_INCLUDE_DIRS})
option(PCRE2_STATIC "Turn this option ON when linking to PCRE2 static library" OFF)
endif()
# config.h will be generated in src/auto, we should include it.
include_directories(BEFORE
${CMAKE_CURRENT_BINARY_DIR}/auto)
check_function_exists(strcasecmp HAVE_STRCASECMP)
check_function_exists(strdup HAVE_STRDUP)
check_function_exists(stricmp HAVE_STRICMP)
check_function_exists(strndup HAVE_STRNDUP)
check_function_exists(strlwr HAVE_STRLWR)
check_type_size(_Bool HAVE__BOOL)
check_type_size("const char*" HAVE_CONST)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/auto/config.h)
include_directories(BEFORE
"${PROJECT_SOURCE_DIR}/include")
if(WIN32)
# MSVC_MD option
option(MSVC_MD
"Use /MD instead of /MT flag when compiling with Microsoft Visual C++. This option takes no effect when using compilers other than Microsoft Visual C++."
OFF)
endif()
# replace all /MD with /MT for msvc if MSVC_MD is off
if(MSVC AND NOT MSVC_MD)
foreach(flag_var
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)
endif()
# Use unsigned char to represent plain char
if(MSVC)
add_definitions("-J")
else()
add_definitions("-funsigned-char")
endif()
add_subdirectory(lib)
add_subdirectory(bin)

1
src/bin/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/editorconfig*

53
src/bin/CMakeLists.txt Normal file
View File

@ -0,0 +1,53 @@
#
# Copyright (c) 2011-2012 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
link_directories(${CMAKE_ARCHIVE_OUTPUT_DIR})
set(editorconfig_BINSRCS
main.c)
# targets
add_executable(editorconfig_bin ${editorconfig_BINSRCS})
if(BUILD_STATICALLY_LINKED_EXE)
target_link_libraries(editorconfig_bin editorconfig_static)
if(NOT WIN32)
# Add -static for linker if we want a statically linked executable
target_link_libraries(editorconfig_bin "-static")
# libpcre2 might be dynamically linked against pthreads (at least on Ubuntu Xenial)
target_link_libraries(editorconfig_bin "-pthread")
endif()
else(BUILD_STATICALLY_LINKED_EXE)
target_link_libraries(editorconfig_bin editorconfig_shared)
endif(BUILD_STATICALLY_LINKED_EXE)
set_target_properties(editorconfig_bin PROPERTIES
OUTPUT_NAME editorconfig
VERSION ${PROJECT_VERSION})
install(TARGETS editorconfig_bin
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")

277
src/bin/main.c Normal file
View File

@ -0,0 +1,277 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <editorconfig/editorconfig.h>
#include "util.h"
static void version(FILE* stream)
{
int major;
int minor;
int patch;
editorconfig_get_version(&major, &minor, &patch);
fprintf(stream,"EditorConfig C Core Version %d.%d.%d%s\n",
major, minor, patch, editorconfig_get_version_suffix());
}
static void usage(FILE* stream, const char* command)
{
fprintf(stream, "Usage: %s [OPTIONS] FILEPATH1 [FILEPATH2 FILEPATH3 ...]\n", command);
fprintf(stream, "FILEPATH can be a hyphen (-) if you want to path(s) to be read from stdin.\n");
fprintf(stream, "\n");
fprintf(stream, "-f Specify conf filename other than \".editorconfig\".\n");
fprintf(stream, "-b Specify version (used by devs to test compatibility).\n");
fprintf(stream, "-h OR --help Print this help message.\n");
fprintf(stream, "-v OR --version Display version information.\n");
}
/*
* Returns strdup(s) and exits if it fails.
*/
static char* xstrdup(const char* s)
{
char* new_s = strdup(s);
if (new_s == NULL)
{
fprintf(stderr, "Unable to allocate memory.\n");
exit(1);
}
return new_s;
}
int main(int argc, const char* argv[])
{
char* full_filename = NULL;
int err_num;
int i;
int name_value_count;
editorconfig_handle eh;
char** file_paths = NULL;
int path_count; /* the count of path input*/
/* Will be a EditorConfig file name if -f is specified on command line */
const char* conf_filename = NULL;
int version_major = -1;
int version_minor = -1;
int version_patch = -1;
/* File names read from stdin are put in this buffer temporarily */
char file_line_buffer[FILENAME_MAX + 1];
_Bool f_flag = 0;
_Bool b_flag = 0;
if (argc <= 1) {
version(stderr);
usage(stderr, argv[0]);
exit(1);
}
for (i = 1; i < argc; ++i) {
if (b_flag) {
char* pos;
int ver;
int ver_pos = 0;
char* argvi;
argvi = xstrdup(argv[i]);
b_flag = 0;
/* convert the argument -b into a version number */
pos = strtok(argvi, ".");
while (pos != NULL) {
ver = ec_atoi(pos);
switch(ver_pos) {
case 0:
version_major = ver;
break;
case 1:
version_minor = ver;
break;
case 2:
version_patch = ver;
break;
default:
fprintf(stderr, "Invalid version number: %s\n", argv[i]);
exit(1);
}
++ ver_pos;
pos = strtok(NULL, ".");
}
free(argvi);
} else if (f_flag) {
f_flag = 0;
conf_filename = argv[i];
} else if (strcmp(argv[i], "--version") == 0 ||
strcmp(argv[i], "-v") == 0) {
version(stdout);
exit(0);
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
version(stdout);
usage(stdout, argv[0]);
exit(0);
} else if (strcmp(argv[i], "-b") == 0)
b_flag = 1;
else if (strcmp(argv[i], "-f") == 0)
f_flag = 1;
else if (i < argc) {
/* If there are other args left, regard them as file names */
path_count = argc - i;
file_paths = (char**) malloc(path_count * sizeof(char*));
if (file_paths == NULL)
{
perror("Unable to allocate memory");
exit(2);
}
for (; i < argc; ++i)
file_paths[path_count + i - argc] = xstrdup(argv[i]);
} else {
usage(stderr, argv[0]);
exit(1);
}
}
if (!file_paths) { /* No filename is set */
usage(stderr, argv[0]);
exit(1);
}
/* Go through all the files in the argument list */
for (i = 0; i < path_count; ++i) {
int j;
full_filename = file_paths[i];
/* Print the file path first, with [], if more than one file is
* specified */
if (path_count > 1 && strcmp(full_filename, "-"))
printf("[%s]\n", full_filename);
if (!strcmp(full_filename, "-")) {
int len;
/* Read a line from stdin. If EOF encountered, continue */
if (!fgets(file_line_buffer, FILENAME_MAX + 1, stdin)) {
if (!feof(stdin))
perror("Failed to read stdin");
free(full_filename);
continue;
}
-- i;
/* trim the trailing space characters */
len = strlen(file_line_buffer) - 1;
while (len >= 0 && isspace(file_line_buffer[len]))
-- len;
if (len < 0) /* we meet a blank line */
continue;
file_line_buffer[len + 1] = '\0';
full_filename = file_line_buffer;
while (isspace(*full_filename))
++ full_filename;
full_filename = xstrdup(full_filename);
printf("[%s]\n", full_filename);
}
/* Initialize the EditorConfig handle */
eh = editorconfig_handle_init();
if (eh == NULL)
{
perror("Unable to create EditorConfig handle");
exit(3);
}
/* Set conf file name */
if (conf_filename)
editorconfig_handle_set_conf_file_name(eh, conf_filename);
/* Set the version to be compatible with */
editorconfig_handle_set_version(eh,
version_major, version_minor, version_patch);
/* parsing the editorconfig files */
err_num = editorconfig_parse(full_filename, eh);
free(full_filename);
if (err_num != 0) {
/* print error message */
fputs(editorconfig_get_error_msg(err_num), stderr);
if (err_num > 0)
fprintf(stderr, ":%d \"%s\"", err_num,
editorconfig_handle_get_err_file(eh));
fprintf(stderr, "\n");
exit(1);
}
/* print the result */
name_value_count = editorconfig_handle_get_name_value_count(eh);
for (j = 0; j < name_value_count; ++j) {
const char* name;
const char* value;
editorconfig_handle_get_name_value(eh, j, &name, &value);
printf("%s=%s\n", name, value);
}
if (editorconfig_handle_destroy(eh) != 0) {
fprintf(stderr, "Failed to destroy editorconfig_handle.\n");
exit(1);
}
}
free(file_paths);
exit(0);
}

81
src/config.h.in Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CONFIG_H__
#define CONFIG_H__
#ifndef UNIX
#cmakedefine UNIX
#endif
#ifndef WIN32
#cmakedefine WIN32
#endif
#cmakedefine HAVE_STRCASECMP
#cmakedefine HAVE_STRDUP
#cmakedefine HAVE_STRICMP
#cmakedefine HAVE_STRNDUP
#cmakedefine HAVE_STRLWR
#cmakedefine HAVE__BOOL
#cmakedefine HAVE_CONST
#ifndef HAVE_CONST
# define const
#endif
#cmakedefine CMAKE_COMPILER_IS_GNUCC
#cmakedefine MSVC
#cmakedefine PCRE2_STATIC
#define PCRE2_CODE_UNIT_WIDTH 8
/* For gcc, we define _GNU_SOURCE to use gcc extensions */
#ifdef CMAKE_COMPILER_IS_GNUCC
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif /* _GNU_SOURCE */
#endif /* CMAKE_COMPILER_IS_GNUCC */
#ifdef MSVC
# define _CRT_SECURE_NO_WARNINGS 1
# pragma warning(disable: 4996)
#endif
/* _Bool type */
#ifndef HAVE__BOOL
# define _Bool signed char
#endif
#define EC_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define EC_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define EC_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define EC_VERSION_SUFFIX "@PROJECT_VERSION_SUFFIX@"
#endif /* !CONFIG_H__ */

4
src/lib/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/editorconfig.dll
/editorconfig_static.lib
/libeditorconfig.so*
/libeditorconfig_static.a

117
src/lib/CMakeLists.txt Normal file
View File

@ -0,0 +1,117 @@
#
# Copyright (c) 2011-2019 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
set(editorconfig_LIBSRCS
ec_glob.c
editorconfig.c
editorconfig_handle.c
ini.c
misc.c
)
add_library(editorconfig_shared SHARED ${editorconfig_LIBSRCS})
target_include_directories(editorconfig_shared
INTERFACE $<INSTALL_INTERFACE:include>
)
set_target_properties(editorconfig_shared PROPERTIES
OUTPUT_NAME editorconfig
SOVERSION 0
VERSION ${PROJECT_VERSION})
# We need to link Shwapi since we use PathIsRelative
if(WIN32)
target_link_libraries(editorconfig_shared Shlwapi)
endif()
target_link_libraries(editorconfig_shared ${PCRE2_LIBRARIES})
if (BUILD_STATICALLY_LINKED_EXE)
# disable shared library build when static is enabled
set_target_properties(editorconfig_shared PROPERTIES
EXCLUDE_FROM_ALL 1)
endif()
add_library(editorconfig_static STATIC ${editorconfig_LIBSRCS})
target_include_directories(editorconfig_static
INTERFACE $<INSTALL_INTERFACE:include>
)
set_target_properties(editorconfig_static PROPERTIES
OUTPUT_NAME editorconfig_static
VERSION ${PROJECT_VERSION})
# We need to link Shwapi since we use PathIsRelative
if(WIN32)
target_link_libraries(editorconfig_static Shlwapi)
endif()
target_link_libraries(editorconfig_static ${PCRE2_LIBRARIES})
# EditorConfig package name for find_package() and the CMake package registry.
# On UNIX the system registry is usually just "lib/cmake/<package>".
# See cmake-package(7) for details.
set(config_package_name "EditorConfig")
set(editorconfig_CONFIG_NAME "${config_package_name}Config")
set(editorconfig_CONFIG_VERSION_NAME "${config_package_name}ConfigVersion")
set(editorconfig_CONFIG_EXPORT_NAME "${config_package_name}Targets")
set(editorconfig_CONFIG_INSTALL_LIBDIR
"${CMAKE_INSTALL_LIBDIR}/cmake/${config_package_name}")
install(TARGETS editorconfig_static
EXPORT ${editorconfig_CONFIG_EXPORT_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(NOT BUILD_STATICALLY_LINKED_EXE)
install(TARGETS editorconfig_shared
EXPORT ${editorconfig_CONFIG_EXPORT_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/editorconfig.pc.in
${CMAKE_CURRENT_BINARY_DIR}/editorconfig.pc
@ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/editorconfig.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
include(CMakePackageConfigHelpers)
configure_package_config_file(${editorconfig_CONFIG_NAME}.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_NAME}.cmake
INSTALL_DESTINATION ${editorconfig_CONFIG_INSTALL_LIBDIR})
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_VERSION_NAME}.cmake
COMPATIBILITY AnyNewerVersion)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_NAME}.cmake
${CMAKE_CURRENT_BINARY_DIR}/${editorconfig_CONFIG_VERSION_NAME}.cmake
DESTINATION ${editorconfig_CONFIG_INSTALL_LIBDIR})
install(EXPORT ${editorconfig_CONFIG_EXPORT_NAME}
DESTINATION ${editorconfig_CONFIG_INSTALL_LIBDIR})

View File

@ -0,0 +1,3 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@editorconfig_CONFIG_EXPORT_NAME@.cmake")

396
src/lib/ec_glob.c Normal file
View File

@ -0,0 +1,396 @@
/*
* Copyright (c) 2014-2019 Hong Xu <hong AT topbug DOT net>
* Copyright (c) 2018 Sven Strickroth <email AT cs-ware DOT de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "global.h"
#include <ctype.h>
#include <string.h>
#include <pcre2.h>
#define utarray_oom() { return -2; }
#include "utarray.h"
#include "misc.h"
#include "util.h"
#include "ec_glob.h"
/* Special characters */
const char ec_special_chars[] = "?[]\\*-{},";
typedef struct int_pair
{
int num1;
int num2;
} int_pair;
static const UT_icd ut_int_pair_icd = {sizeof(int_pair),NULL,NULL,NULL};
/* concatenate the string then move the pointer to the end */
#define STRING_CAT(p, string, end) do { \
size_t string_len = strlen(string); \
if (p + string_len >= end) \
return -1; \
strcat(p, string); \
p += string_len; \
} while(0)
#define PATTERN_MAX 4097
/*
* Whether the string matches the given glob pattern. Return 0 if successful, return -1 if a PCRE
* error or other regex error occurs, and return -2 if an OOM outside PCRE occurs.
*/
EDITORCONFIG_LOCAL
int ec_glob(const char *pattern, const char *string)
{
size_t i;
int_pair * p;
char * c;
char pcre_str[2 * PATTERN_MAX] = "^";
char * p_pcre;
char * pcre_str_end;
int brace_level = 0;
_Bool is_in_bracket = 0;
int error_code;
size_t erroffset;
pcre2_code * re;
int rc;
size_t * pcre_result;
pcre2_match_data * pcre_match_data;
char l_pattern[2 * PATTERN_MAX];
_Bool are_braces_paired = 1;
UT_array * nums; /* number ranges */
int ret = 0;
strcpy(l_pattern, pattern);
p_pcre = pcre_str + 1;
pcre_str_end = pcre_str + 2 * PATTERN_MAX;
/* Determine whether curly braces are paired */
{
int left_count = 0;
int right_count = 0;
for (c = l_pattern; *c; ++ c)
{
if (*c == '\\' && *(c+1) != '\0')
{
++ c;
continue;
}
if (*c == '}')
++ right_count;
else if (*c == '{')
++ left_count;
if (right_count > left_count)
{
are_braces_paired = 0;
break;
}
}
if (right_count != left_count)
are_braces_paired = 0;
}
/* used to search for {num1..num2} case */
re = pcre2_compile("^\\{[\\+\\-]?\\d+\\.\\.[\\+\\-]?\\d+\\}$", PCRE2_ZERO_TERMINATED, 0,
&error_code, &erroffset, NULL);
if (!re) /* failed to compile */
return -1;
utarray_new(nums, &ut_int_pair_icd);
for (c = l_pattern; *c; ++ c)
{
switch (*c)
{
case '\\': /* also skip the next one */
if (*(c+1) != '\0')
{
*(p_pcre ++) = *(c++);
*(p_pcre ++) = *c;
}
else
STRING_CAT(p_pcre, "\\\\", pcre_str_end);
break;
case '?':
STRING_CAT(p_pcre, "[^/]", pcre_str_end);
break;
case '*':
if (*(c+1) == '*') /* case of ** */
{
STRING_CAT(p_pcre, ".*", pcre_str_end);
++ c;
}
else /* case of * */
STRING_CAT(p_pcre, "[^\\/]*", pcre_str_end);
break;
case '[':
if (is_in_bracket) /* inside brackets, we really mean bracket */
{
STRING_CAT(p_pcre, "\\[", pcre_str_end);
break;
}
{
/* check whether we have slash within the bracket */
_Bool has_slash = 0;
char * cc;
for (cc = c; *cc && *cc != ']'; ++ cc)
{
if (*cc == '\\' && *(cc+1) != '\0')
{
++ cc;
continue;
}
if (*cc == '/')
{
has_slash = 1;
break;
}
}
/* if we have slash in the brackets, just do it literally */
if (has_slash)
{
char * right_bracket = strchr(c, ']');
if (!right_bracket) /* The right bracket may not exist */
right_bracket = c + strlen(c);
strcat(p_pcre, "\\");
strncat(p_pcre, c, right_bracket - c);
if (*right_bracket) /* right_bracket is a bracket */
strcat(p_pcre, "\\]");
p_pcre += strlen(p_pcre);
c = right_bracket;
if (!*c)
/* end of string, meaning that right_bracket is not a
* bracket. Then we go back one character to make the
* parsing end normally for the counter in the "for"
* loop. */
c -= 1;
break;
}
}
is_in_bracket = 1;
if (*(c+1) == '!') /* case of [!...] */
{
STRING_CAT(p_pcre, "[^", pcre_str_end);
++ c;
}
else
*(p_pcre ++) = '[';
break;
case ']':
is_in_bracket = 0;
*(p_pcre ++) = *c;
break;
case '-':
if (is_in_bracket) /* in brackets, - indicates range */
*(p_pcre ++) = *c;
else
STRING_CAT(p_pcre, "\\-", pcre_str_end);
break;
case '{':
if (!are_braces_paired)
{
STRING_CAT(p_pcre, "\\{", pcre_str_end);
break;
}
/* Check the case of {single}, where single can be empty */
{
char * cc;
_Bool is_single = 1;
for (cc = c + 1; *cc != '\0' && *cc != '}'; ++ cc)
{
if (*cc == '\\' && *(cc+1) != '\0')
{
++ cc;
continue;
}
if (*cc == ',')
{
is_single = 0;
break;
}
}
if (*cc == '\0')
is_single = 0;
if (is_single) /* escape the { and the corresponding } */
{
const char * double_dots;
int_pair pair;
pcre2_match_data * match_data = pcre2_match_data_create_from_pattern(re, NULL);
/* Check the case of {num1..num2} */
rc = pcre2_match(re, c, cc - c + 1, 0, 0, match_data, NULL);
pcre2_match_data_free(match_data);
if (rc < 0) /* not {num1..num2} case */
{
STRING_CAT(p_pcre, "\\{", pcre_str_end);
memmove(cc+1, cc, strlen(cc) + 1);
*cc = '\\';
break;
}
/* Get the range */
double_dots = strstr(c, "..");
pair.num1 = ec_atoi(c + 1);
pair.num2 = ec_atoi(double_dots + 2);
utarray_push_back(nums, &pair);
STRING_CAT(p_pcre, "([\\+\\-]?\\d+)", pcre_str_end);
c = cc;
break;
}
}
++ brace_level;
STRING_CAT(p_pcre, "(?:", pcre_str_end);
break;
case '}':
if (!are_braces_paired)
{
STRING_CAT(p_pcre, "\\}", pcre_str_end);
break;
}
-- brace_level;
*(p_pcre ++) = ')';
break;
case ',':
if (brace_level > 0) /* , inside {...} */
*(p_pcre ++) = '|';
else
STRING_CAT(p_pcre, "\\,", pcre_str_end);
break;
case '/':
// /**/ case, match both single / and /anything/
if (!strncmp(c, "/**/", 4))
{
STRING_CAT(p_pcre, "(\\/|\\/.*\\/)", pcre_str_end);
c += 3;
}
else
STRING_CAT(p_pcre, "\\/", pcre_str_end);
break;
default:
if (!isalnum(*c))
*(p_pcre ++) = '\\';
*(p_pcre ++) = *c;
}
}
*(p_pcre ++) = '$';
pcre2_code_free(re); /* ^\\d+\\.\\.\\d+$ */
re = pcre2_compile(pcre_str, PCRE2_ZERO_TERMINATED, 0, &error_code, &erroffset, NULL);
if (!re) /* failed to compile */
{
utarray_free(nums);
return -1;
}
pcre_match_data = pcre2_match_data_create_from_pattern(re, NULL);
rc = pcre2_match(re, string, strlen(string), 0, 0, pcre_match_data, NULL);
if (rc < 0) /* failed to match */
{
if (rc == PCRE2_ERROR_NOMATCH)
ret = EC_GLOB_NOMATCH;
else
ret = rc;
goto cleanup;
}
/* Whether the numbers are in the desired range? */
pcre_result = pcre2_get_ovector_pointer(pcre_match_data);
for(p = (int_pair *) utarray_front(nums), i = 1; p;
++ i, p = (int_pair *) utarray_next(nums, p))
{
const char * substring_start = string + pcre_result[2 * i];
size_t substring_length = pcre_result[2 * i + 1] - pcre_result[2 * i];
char * num_string;
int num;
/* we don't consider 0digits such as 010 as matched */
if (*substring_start == '0')
break;
num_string = strndup(substring_start, substring_length);
if (num_string == NULL) {
ret = -2;
goto cleanup;
}
num = ec_atoi(num_string);
free(num_string);
if (num < p->num1 || num > p->num2) /* not matched */
break;
}
if (p != NULL) /* numbers not matched */
ret = EC_GLOB_NOMATCH;
cleanup:
pcre2_code_free(re);
pcre2_match_data_free(pcre_match_data);
utarray_free(nums);
return ret;
}

47
src/lib/ec_glob.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2014-2019 Hong Xu <hong AT topbug DOT net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EC_GLOB_H__
#define EC_GLOB_H__
#include "global.h"
#define EC_GLOB_NOMATCH 1 /* Match failed. */
#ifdef __cplusplus
extern "C" {
#endif
EDITORCONFIG_LOCAL
int ec_glob(const char * pattern, const char * string);
/* Special characters. */
extern const char ec_special_chars[];
#ifdef __cplusplus
}
#endif
#endif /* !EC_GLOB_H__ */

623
src/lib/editorconfig.c Normal file
View File

@ -0,0 +1,623 @@
/*
* Copyright (c) 2011-2012 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "global.h"
#include "editorconfig.h"
#include "misc.h"
#include "ini.h"
#include "ec_glob.h"
/* could be used to fast locate these properties in an
* array_editorconfig_name_value */
typedef struct
{
const editorconfig_name_value* indent_style;
const editorconfig_name_value* indent_size;
const editorconfig_name_value* tab_width;
} special_property_name_value_pointers;
typedef struct
{
editorconfig_name_value* name_values;
int current_value_count;
int max_value_count;
special_property_name_value_pointers spnvp;
} array_editorconfig_name_value;
typedef struct
{
char* full_filename;
char* editorconfig_file_dir;
array_editorconfig_name_value array_name_value;
} handler_first_param;
/*
* Set the special pointers for a name
*/
static void set_special_property_name_value_pointers(
const editorconfig_name_value* nv,
special_property_name_value_pointers* spnvp)
{
/* set speical pointers */
if (!strcmp(nv->name, "indent_style"))
spnvp->indent_style = nv;
else if (!strcmp(nv->name, "indent_size"))
spnvp->indent_size = nv;
else if (!strcmp(nv->name, "tab_width"))
spnvp->tab_width = nv;
}
/*
* Set the name and value of a editorconfig_name_value structure
*/
static void set_name_value(editorconfig_name_value* nv, const char* name,
const char* value, special_property_name_value_pointers* spnvp)
{
if (name)
nv->name = strdup(name);
if (value)
nv->value = strdup(value);
/* lowercase the value when the name is one of the following */
if (!strcmp(nv->name, "end_of_line") ||
!strcmp(nv->name, "indent_style") ||
!strcmp(nv->name, "indent_size") ||
!strcmp(nv->name, "insert_final_newline") ||
!strcmp(nv->name, "trim_trailing_whitespace") ||
!strcmp(nv->name, "charset"))
strlwr(nv->value);
/* set special pointers */
set_special_property_name_value_pointers(nv, spnvp);
}
/*
* reset special property name value pointers
*/
static void reset_special_property_name_value_pointers(
array_editorconfig_name_value* aenv)
{
int i;
for (i = 0; i < aenv->current_value_count; ++ i)
set_special_property_name_value_pointers(
&aenv->name_values[i], &aenv->spnvp);
}
/*
* Find the editorconfig_name_value from name in a editorconfig_name_value
* array.
*/
static int find_name_value_from_name(const editorconfig_name_value* env,
int count, const char* name)
{
int i;
for (i = 0; i < count; ++i)
if (!strcmp(env[i].name, name)) /* found */
return i;
return -1;
}
/* initialize array_editorconfig_name_value */
static void array_editorconfig_name_value_init(
array_editorconfig_name_value* aenv)
{
memset(aenv, 0, sizeof(array_editorconfig_name_value));
}
static int array_editorconfig_name_value_add(
array_editorconfig_name_value* aenv,
const char* name, const char* value)
{
#define VALUE_COUNT_INITIAL 30
#define VALUE_COUNT_INCREASEMENT 10
int name_value_pos;
/* always use name_lwr but not name, since property names are case
* insensitive */
char name_lwr[MAX_PROPERTY_NAME+1] = {0};
/* For the first time we came here, aenv->name_values is NULL */
if (aenv->name_values == NULL) {
aenv->name_values = (editorconfig_name_value*)malloc(
sizeof(editorconfig_name_value) * VALUE_COUNT_INITIAL);
if (aenv->name_values == NULL)
return -1;
aenv->max_value_count = VALUE_COUNT_INITIAL;
aenv->current_value_count = 0;
}
/* name_lwr is the lowercase property name */
strlwr(strncpy(name_lwr, name, MAX_PROPERTY_NAME));
name_value_pos = find_name_value_from_name(
aenv->name_values, aenv->current_value_count, name_lwr);
if (name_value_pos >= 0) { /* current name has already been used */
free(aenv->name_values[name_value_pos].value);
set_name_value(&aenv->name_values[name_value_pos],
(const char*)NULL, value, &aenv->spnvp);
return 0;
}
/* if the space is not enough, allocate more before add the new name and
* value */
if (aenv->current_value_count >= aenv->max_value_count) {
editorconfig_name_value* new_values;
int new_max_value_count;
new_max_value_count = aenv->current_value_count +
VALUE_COUNT_INCREASEMENT;
new_values = (editorconfig_name_value*)realloc(aenv->name_values,
sizeof(editorconfig_name_value) * new_max_value_count);
if (new_values == NULL) /* error occured */
return -1;
aenv->name_values = new_values;
aenv->max_value_count = new_max_value_count;
/* reset special pointers */
reset_special_property_name_value_pointers(aenv);
}
set_name_value(&aenv->name_values[aenv->current_value_count],
name_lwr, value, &aenv->spnvp);
++ aenv->current_value_count;
return 0;
#undef VALUE_COUNT_INITIAL
#undef VALUE_COUNT_INCREASEMENT
}
static void array_editorconfig_name_value_clear(
array_editorconfig_name_value* aenv)
{
int i;
for (i = 0; i < aenv->current_value_count; ++i) {
free(aenv->name_values[i].name);
free(aenv->name_values[i].value);
}
free(aenv->name_values);
}
/*
* Accept INI property value and store known values in handler_first_param
* struct.
*/
static int ini_handler(void* hfp, const char* section, const char* name,
const char* value)
{
handler_first_param* hfparam = (handler_first_param*)hfp;
/* prepend ** to pattern */
char* pattern;
/* root = true, clear all previous values */
if (*section == '\0' && !strcasecmp(name, "root") &&
!strcasecmp(value, "true")) {
array_editorconfig_name_value_clear(&hfparam->array_name_value);
array_editorconfig_name_value_init(&hfparam->array_name_value);
return 1;
}
/* Pattern would be: /dir/of/editorconfig/file[double_star]/[section] if
* section does not contain '/', or /dir/of/editorconfig/file[section]
* if section starts with a '/', or /dir/of/editorconfig/file/[section] if
* section contains '/' but does not start with '/'.
*
* If the dir part has any special characters as defined by ec_glob.c, we
* need to escape them.
*/
pattern = (char*)malloc(
/* The 2 here is for possible escaping. */
strlen(hfparam->editorconfig_file_dir) * sizeof(char) * 2 +
sizeof("**/") + strlen(section) * sizeof(char));
if (!pattern)
return 0;
/* Escaping special characters in the directory part. */
char* ptr = hfparam->editorconfig_file_dir;
char* ptr_prev = ptr;
char* ptr_pattern = pattern;
for (; (ptr = strpbrk(ptr, ec_special_chars)) != NULL; ++ ptr, ptr_prev = ptr)
{
ptrdiff_t s = ptr - ptr_prev;
memcpy(ptr_pattern, ptr_prev, s * sizeof(char));
ptr_pattern += s;
*(ptr_pattern ++) = '\\'; /* escaping char */
*(ptr_pattern ++) = *ptr;
}
strcpy(ptr_pattern, ptr_prev);
if (strchr(section, '/') == NULL) /* No / is found, append '[star][star]/' */
strcat(pattern, "**/");
else if (*section != '/') /* The first char is not '/' but section contains
'/', append a '/' */
strcat(pattern, "/");
strcat(pattern, section);
if (ec_glob(pattern, hfparam->full_filename) == 0) {
if (array_editorconfig_name_value_add(&hfparam->array_name_value, name,
value)) {
free(pattern);
return 0;
}
}
free(pattern);
return 1;
}
/*
* Split an absolute file path into directory and filename parts.
*
* If absolute_path does not contain a path separator, set directory and
* filename to NULL pointers.
*
* Returns -1 if an OOM error occurs. Otherwise returns 0.
*/
static int split_file_path(char** directory, char** filename,
const char* absolute_path)
{
char* path_char = strrchr(absolute_path, '/');
if (path_char == NULL) {
if (directory)
*directory = NULL;
if (filename)
*filename = NULL;
return 0;
}
if (directory != NULL) {
*directory = strndup(absolute_path,
(size_t)(path_char - absolute_path));
if (*directory == NULL)
return -1;
}
if (filename != NULL) {
*filename = strndup(path_char+1, strlen(path_char)-1);
if (*filename == NULL) {
if (directory != NULL)
free(*directory);
return -1;
}
}
return 0;
}
/*
* Return the number of slashes in given filename
*/
static int count_slashes(const char* filename)
{
int slash_count;
for (slash_count = 0; *filename != '\0'; filename++) {
if (*filename == '/') {
slash_count++;
}
}
return slash_count;
}
/*
* Return an array of full filenames for files in every directory in and above
* the given path with the name of the relative filename given. Return NULL if
* failed (OOM).
*/
static char** get_filenames(const char* path, const char* filename)
{
char* currdir = NULL;
char** files;
int slashes = count_slashes(path);
int i;
files = (char**) calloc(slashes+1, sizeof(char*));
if (files == NULL)
goto failure_cleanup;
currdir = strdup(path);
if (currdir == NULL)
goto failure_cleanup;
for (i = slashes - 1; i >= 0; --i) {
char* currdir1 = currdir;
int err_split;
err_split = split_file_path(&currdir, NULL, currdir1);
free(currdir1);
if (err_split == -1)
goto failure_cleanup;
files[i] = malloc(strlen(currdir) + strlen(filename) + 2);
strcpy(files[i], currdir);
strcat(files[i], "/");
strcat(files[i], filename);
}
free(currdir);
files[slashes] = NULL;
return files;
failure_cleanup:
free(currdir);
if (files != NULL) {
for (i = 0; i < slashes; ++ i)
free(files[i]);
free(files);
}
return NULL;
}
/*
* Free the memory used by an array of strings that was created by
* get_filenames().
*/
static void free_filenames(char **filenames)
{
if (filenames != NULL) {
for (char** filename = filenames; *filename != NULL; filename++) {
free(*filename);
}
free(filenames);
}
}
/*
* version number comparison
*/
static int editorconfig_compare_version(
const struct editorconfig_version* v0,
const struct editorconfig_version* v1)
{
/* compare major */
if (v0->major > v1->major)
return 1;
else if (v0->major < v1->major)
return -1;
/* compare minor */
if (v0->minor > v1->minor)
return 1;
else if (v0->minor < v1->minor)
return -1;
/* compare patch */
if (v0->patch > v1->patch)
return 1;
else if (v0->patch < v1->patch)
return -1;
return 0;
}
EDITORCONFIG_EXPORT
const char* editorconfig_get_error_msg(int err_num)
{
if(err_num > 0)
return "Failed to parse file.";
switch(err_num) {
case 0:
return "No error occurred.";
case EDITORCONFIG_PARSE_NOT_FULL_PATH:
return "Input file must be a full path name.";
case EDITORCONFIG_PARSE_MEMORY_ERROR:
return "Memory error.";
case EDITORCONFIG_PARSE_VERSION_TOO_NEW:
return "Required version is greater than the current version.";
}
return "Unknown error.";
}
/*
* See the header file for the use of this function
*/
EDITORCONFIG_EXPORT
int editorconfig_parse(const char* full_filename, editorconfig_handle h)
{
handler_first_param hfp;
char** config_file;
char** config_files = NULL;
int err_num = 0;
int i;
struct editorconfig_handle* eh = (struct editorconfig_handle*)h;
struct editorconfig_version cur_ver;
struct editorconfig_version tmp_ver;
/* get current version */
editorconfig_get_version(&cur_ver.major, &cur_ver.minor,
&cur_ver.patch);
/* if version is set to 0.0.0, we set it to current version */
if (eh->ver.major == 0 &&
eh->ver.minor == 0 &&
eh->ver.patch == 0)
eh->ver = cur_ver;
if (editorconfig_compare_version(&eh->ver, &cur_ver) > 0)
return EDITORCONFIG_PARSE_VERSION_TOO_NEW;
if (eh->err_file) {
free(eh->err_file);
eh->err_file = NULL;
}
/* if eh->conf_file_name is NULL, we set ".editorconfig" as the default
* conf file name */
if (!eh->conf_file_name)
eh->conf_file_name = ".editorconfig";
if (eh->name_values) {
/* free name_values */
for (i = 0; i < eh->name_value_count; ++i) {
free(eh->name_values[i].name);
free(eh->name_values[i].value);
}
free(eh->name_values);
eh->name_values = NULL;
eh->name_value_count = 0;
}
memset(&hfp, 0, sizeof(hfp));
hfp.full_filename = strdup(full_filename);
if (hfp.full_filename == NULL) {
err_num = EDITORCONFIG_PARSE_MEMORY_ERROR;
goto cleanup;
}
/* return an error if file path is not absolute */
if (!is_file_path_absolute(full_filename)) {
err_num = EDITORCONFIG_PARSE_NOT_FULL_PATH;
goto cleanup;
}
#ifdef WIN32
/* replace all backslashes with slashes on Windows */
str_replace(hfp.full_filename, '\\', '/');
#endif
array_editorconfig_name_value_init(&hfp.array_name_value);
config_files = get_filenames(hfp.full_filename, eh->conf_file_name);
if (config_files == NULL) {
err_num = EDITORCONFIG_PARSE_MEMORY_ERROR;
goto cleanup;
}
for (config_file = config_files; *config_file != NULL; config_file++) {
int ini_err_num;
err_num = split_file_path(&hfp.editorconfig_file_dir, NULL, *config_file);
if (err_num == -1) {
err_num = EDITORCONFIG_PARSE_MEMORY_ERROR;
goto cleanup;
}
if ((ini_err_num = ini_parse(*config_file, ini_handler, &hfp)) != 0 &&
/* ignore error caused by I/O, maybe caused by non exist file */
ini_err_num != -1) {
/* No need to specifically deal with the return value of the strdup
of this line. If any error occurs for this strdup call,
eh->err_file would simply be NULL.*/
eh->err_file = strdup(*config_file);
err_num = ini_err_num;
goto cleanup;
}
free(hfp.editorconfig_file_dir);
hfp.editorconfig_file_dir = NULL;
}
/* value proprocessing */
/* For v0.9 */
SET_EDITORCONFIG_VERSION(&tmp_ver, 0, 9, 0);
if (editorconfig_compare_version(&eh->ver, &tmp_ver) >= 0) {
/* Set indent_size to "tab" if indent_size is not specified and
* indent_style is set to "tab". Only should be done after v0.9 */
if (hfp.array_name_value.spnvp.indent_style &&
!hfp.array_name_value.spnvp.indent_size &&
!strcmp(hfp.array_name_value.spnvp.indent_style->value, "tab"))
array_editorconfig_name_value_add(&hfp.array_name_value,
"indent_size", "tab");
/* Set indent_size to tab_width if indent_size is "tab" and tab_width is
* specified. This behavior is specified for v0.9 and up. */
if (hfp.array_name_value.spnvp.indent_size &&
hfp.array_name_value.spnvp.tab_width &&
!strcmp(hfp.array_name_value.spnvp.indent_size->value, "tab"))
array_editorconfig_name_value_add(&hfp.array_name_value, "indent_size",
hfp.array_name_value.spnvp.tab_width->value);
}
/* Set tab_width to indent_size if indent_size is specified. If version is
* not less than 0.9.0, we also need to check when the indent_size is set
* to "tab", we should not duplicate the value to tab_width */
if (hfp.array_name_value.spnvp.indent_size &&
!hfp.array_name_value.spnvp.tab_width &&
(editorconfig_compare_version(&eh->ver, &tmp_ver) < 0 ||
strcmp(hfp.array_name_value.spnvp.indent_size->value, "tab")))
array_editorconfig_name_value_add(&hfp.array_name_value, "tab_width",
hfp.array_name_value.spnvp.indent_size->value);
eh->name_value_count = hfp.array_name_value.current_value_count;
if (eh->name_value_count == 0) { /* no value is set, just return 0. */
free(hfp.full_filename);
free_filenames(config_files);
return 0;
}
eh->name_values = hfp.array_name_value.name_values;
eh->name_values = realloc( /* realloc to truncate the unused spaces */
eh->name_values,
sizeof(editorconfig_name_value) * eh->name_value_count);
if (eh->name_values == NULL) {
free(hfp.full_filename);
free_filenames(config_files);
return EDITORCONFIG_PARSE_MEMORY_ERROR;
}
cleanup:
free_filenames(config_files);
free(hfp.full_filename);
free(hfp.editorconfig_file_dir);
return err_num;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
void editorconfig_get_version(int* major, int* minor, int* patch)
{
if (major)
*major = EC_VERSION_MAJOR;
if (minor)
*minor = EC_VERSION_MINOR;
if (patch)
*patch = EC_VERSION_PATCH;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
const char* editorconfig_get_version_suffix(void)
{
return EC_VERSION_SUFFIX;
}

37
src/lib/editorconfig.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EDITORCONFIG_H__
#define EDITORCONFIG_H__
#include <editorconfig/editorconfig.h>
#include "editorconfig_handle.h"
typedef struct editorconfig_name_value editorconfig_name_value;
#endif /* !EDITORCONFIG_H__ */

View File

@ -0,0 +1,9 @@
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: editorconfig
Description: Library handling EditorConfig files, a file format defining coding styles in projects.
Version: @PROJECT_VERSION@
Libs: -L${libdir} -leditorconfig
Cflags: -I${includedir}

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2011-2012 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "editorconfig_handle.h"
/*
* See header file
*/
EDITORCONFIG_EXPORT
editorconfig_handle editorconfig_handle_init(void)
{
editorconfig_handle h;
h = (editorconfig_handle)malloc(sizeof(struct editorconfig_handle));
if (!h)
return (editorconfig_handle)NULL;
memset(h, 0, sizeof(struct editorconfig_handle));
return h;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
int editorconfig_handle_destroy(editorconfig_handle h)
{
int i;
struct editorconfig_handle* eh = (struct editorconfig_handle*)h;
if (h == NULL)
return 0;
/* free name_values */
for (i = 0; i < eh->name_value_count; ++i) {
free(eh->name_values[i].name);
free(eh->name_values[i].value);
}
free(eh->name_values);
/* free err_file */
if (eh->err_file)
free(eh->err_file);
/* free eh itself */
free(eh);
return 0;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
const char* editorconfig_handle_get_err_file(const editorconfig_handle h)
{
return ((const struct editorconfig_handle*)h)->err_file;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
void editorconfig_handle_get_version(const editorconfig_handle h, int* major,
int* minor, int* patch)
{
if (major)
*major = ((const struct editorconfig_handle*)h)->ver.major;
if (minor)
*minor = ((const struct editorconfig_handle*)h)->ver.minor;
if (patch)
*patch = ((const struct editorconfig_handle*)h)->ver.patch;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
void editorconfig_handle_set_version(editorconfig_handle h, int major,
int minor, int patch)
{
if (major >= 0)
((struct editorconfig_handle*)h)->ver.major = major;
if (minor >= 0)
((struct editorconfig_handle*)h)->ver.minor = minor;
if (patch >= 0)
((struct editorconfig_handle*)h)->ver.patch = patch;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
void editorconfig_handle_set_conf_file_name(editorconfig_handle h,
const char* conf_file_name)
{
((struct editorconfig_handle*)h)->conf_file_name = conf_file_name;
}
/*
* See header file
*/
EDITORCONFIG_EXPORT
const char* editorconfig_handle_get_conf_file_name(const editorconfig_handle h)
{
return ((const struct editorconfig_handle*)h)->conf_file_name;
}
EDITORCONFIG_EXPORT
void editorconfig_handle_get_name_value(const editorconfig_handle h, int n,
const char** name, const char** value)
{
struct editorconfig_name_value* name_value = &((
const struct editorconfig_handle*)h)->name_values[n];
if (name)
*name = name_value->name;
if (value)
*value = name_value->value;
}
EDITORCONFIG_EXPORT
int editorconfig_handle_get_name_value_count(const editorconfig_handle h)
{
return ((const struct editorconfig_handle*)h)->name_value_count;
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EDITORCONFIG_HANDLE_H__
#define EDITORCONFIG_HANDLE_H__
#include "global.h"
#include <editorconfig/editorconfig_handle.h>
/*!
* @brief A structure containing a name and its corresponding value.
* @author EditorConfig Team
*/
struct editorconfig_name_value
{
/*! EditorConfig config item's name. */
char* name;
/*! EditorConfig config item's value. */
char* value;
};
/*!
* @brief A structure that descripts version number.
* @author EditorConfig Team
*/
struct editorconfig_version
{
/*! major version */
int major;
/*! minor version */
int minor;
/*! patch version */
int patch;
};
struct editorconfig_handle
{
/*!
* The file name of EditorConfig conf file. If this pointer is set to NULL,
* the file name is set to ".editorconfig" by default.
*/
const char* conf_file_name;
/*!
* When a parsing error occured, this will point to a file that caused the
* parsing error.
*/
char* err_file;
/*!
* version number it should act as. Set this to 0.0.0 to act like the
* current version.
*/
struct editorconfig_version ver;
/*! Pointer to a list of editorconfig_name_value structures containing
* names and values of the parsed result */
struct editorconfig_name_value* name_values;
/*! The total count of name_values structures pointed by name_values
* pointer */
int name_value_count;
};
#endif /* !EDITORCONFIG_HANDLE_H__ */

78
src/lib/global.h Normal file
View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GLOBAL_H__
#define GLOBAL_H__
#include "config.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Microsoft Visual C++ and some other Windows C Compilers requires exported
* functions in shared library to be defined with __declspec(dllexport)
* declarator. Also, gcc >= 4 supports hiding symbols that do not need to be
* exported.
*/
#ifdef editorconfig_shared_EXPORTS /* We are building shared lib if defined */
# ifdef WIN32
# ifdef __GNUC__
# define EDITORCONFIG_EXPORT __attribute__ ((dllexport))
# else /* __GNUC__ */
# define EDITORCONFIG_EXPORT __declspec(dllexport)
# endif /* __GNUC__ */
# else /* WIN32 */
# if defined(__GNUC__) && __GNUC__ >= 4
# define EDITORCONFIG_EXPORT __attribute__ ((visibility ("default")))
# define EDITORCONFIG_LOCAL __attribute__ ((visibility ("hidden")))
# endif /* __GNUC__ && __GNUC >= 4 */
# endif /* WIN32 */
#endif /* editorconfig_shared_EXPORTS */
/*
* For other cases, just define EDITORCONFIG_EXPORT and EDITORCONFIG_LOCAL, to
* make compilation successful
*/
#ifndef EDITORCONFIG_EXPORT
# define EDITORCONFIG_EXPORT
#endif
#ifndef EDITORCONFIG_LOCAL
# define EDITORCONFIG_LOCAL
#endif
/* a macro to set editorconfig_version struct */
#define SET_EDITORCONFIG_VERSION(editorconfig_ver, maj, min, submin) \
do { \
(editorconfig_ver)->major = (maj); \
(editorconfig_ver)->minor = (min); \
(editorconfig_ver)->patch = (submin); \
} while(0)
#endif /* !GLOBAL_H__ */

208
src/lib/ini.c Normal file
View File

@ -0,0 +1,208 @@
/* inih -- simple .INI file parser
The "inih" library is distributed under the New BSD license:
Copyright (c) 2009, Brush Technology
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Brush Technology nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Go to the project home page for more info:
http://code.google.com/p/inih/
*/
#include "global.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "ini.h"
#define MAX_LINE 5000
#define MAX_SECTION MAX_SECTION_NAME
#define MAX_NAME MAX_PROPERTY_NAME
/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s)
{
char* p = s + strlen(s);
while (p > s && isspace(*--p))
*p = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s)
{
while (*s && isspace(*s))
s++;
return (char*)s;
}
/* Return pointer to first char c or ';' comment in given string, or pointer to
null at end of string if neither found. ';' must be prefixed by a whitespace
character to register as a comment. */
static char* find_char_or_comment(const char* s, char c)
{
int was_whitespace = 0;
while (*s && *s != c && !(was_whitespace && (*s == ';' || *s == '#'))) {
was_whitespace = isspace(*s);
s++;
}
return (char*)s;
}
static char* find_last_char_or_comment(const char* s, char c)
{
const char* last_char = s;
int was_whitespace = 0;
while (*s && !(was_whitespace && (*s == ';' || *s == '#'))) {
if (*s == c)
last_char = s;
was_whitespace = isspace(*s);
s++;
}
return (char*)last_char;
}
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
static char* strncpy0(char* dest, const char* src, size_t size)
{
strncpy(dest, src, size);
dest[size - 1] = '\0';
return dest;
}
/* See documentation in header file. */
EDITORCONFIG_LOCAL
int ini_parse_file(FILE* file,
int (*handler)(void*, const char*, const char*,
const char*),
void* user)
{
/* Uses a fair bit of stack (use heap instead if you need to) */
char line[MAX_LINE];
char section[MAX_SECTION+1] = "";
char prev_name[MAX_NAME+1] = "";
char* start;
char* end;
char* name;
char* value;
int lineno = 0;
int error = 0;
/* Scan through file line by line */
while (fgets(line, sizeof(line), file) != NULL) {
lineno++;
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
(unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
start += 3;
}
#endif
start = lskip(rstrip(start));
if (*start == ';' || *start == '#') {
/* Per Python ConfigParser, allow '#' comments at start of line */
}
#if INI_ALLOW_MULTILINE
else if (*prev_name && *start && start > line) {
/* Non-black line with leading whitespace, treat as continuation
of previous name's value (as per Python ConfigParser). */
if (!handler(user, section, prev_name, start) && !error)
error = lineno;
}
#endif
else if (*start == '[') {
/* A "[section]" line */
end = find_last_char_or_comment(start + 1, ']');
if (*end == ']') {
*end = '\0';
/* Section name too long. Skipped. */
if (end - start - 1 > MAX_SECTION_NAME)
continue;
strncpy0(section, start + 1, sizeof(section));
*prev_name = '\0';
}
else if (!error) {
/* No ']' found on section line */
error = lineno;
}
}
else if (*start && (*start != ';' || *start == '#')) {
/* Not a comment, must be a name[=:]value pair */
end = find_char_or_comment(start, '=');
if (*end != '=') {
end = find_char_or_comment(start, ':');
}
if (*end == '=' || *end == ':') {
*end = '\0';
name = rstrip(start);
value = lskip(end + 1);
end = find_char_or_comment(value, '\0');
if (*end == ';' || *end == '#')
*end = '\0';
rstrip(value);
/* Either name or value is too long. Skip it. */
if (strlen(name) > MAX_PROPERTY_NAME ||
strlen(value) > MAX_PROPERTY_VALUE)
continue;
/* Valid name[=:]value pair found, call handler */
strncpy0(prev_name, name, sizeof(prev_name));
if (!handler(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
/* No '=' or ':' found on name[=:]value line */
error = lineno;
}
}
}
return error;
}
/* See documentation in header file. */
EDITORCONFIG_LOCAL
int ini_parse(const char* filename,
int (*handler)(void*, const char*, const char*, const char*),
void* user)
{
FILE* file;
int error;
file = fopen(filename, "r");
if (!file)
return -1;
error = ini_parse_file(file, handler, user);
fclose(file);
return error;
}

94
src/lib/ini.h Normal file
View File

@ -0,0 +1,94 @@
/* inih -- simple .INI file parser
The "inih" library is distributed under the New BSD license:
Copyright (c) 2009, Brush Technology
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Brush Technology nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Go to the project home page for more info:
http://code.google.com/p/inih/
*/
#ifndef INI_H__
#define INI_H__
#include "global.h"
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's ConfigParser.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), or -1 on file open error.
*/
EDITORCONFIG_LOCAL
int ini_parse(const char* filename,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
EDITORCONFIG_LOCAL
int ini_parse_file(FILE* file,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
ConfigParser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed. */
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 0
#endif
#define MAX_SECTION_NAME 4096
#define MAX_PROPERTY_NAME 50
#define MAX_PROPERTY_VALUE 255
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file. See http://code.google.com/p/inih/issues/detail?id=21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
#endif
#ifdef __cplusplus
}
#endif
#endif /* INI_H__ */

250
src/lib/misc.c Normal file
View File

@ -0,0 +1,250 @@
/*
* Copyright (c) 2011-2012 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "misc.h"
#ifdef WIN32
# include <Shlwapi.h>
#endif
#if !defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)
/*
* strcasecmp function from FreeBSD
*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <string.h>
#include <ctype.h>
typedef unsigned char u_char;
EDITORCONFIG_LOCAL
int ec_strcasecmp(const char *s1, const char *s2)
{
const unsigned char
*us1 = (const unsigned char*)s1,
*us2 = (const unsigned char*)s2;
while (tolower(*us1) == tolower(*us2++))
if (*us1++ == '\0')
return (0);
return (tolower(*us1) - tolower(*--us2));
}
#endif /* !HAVE_STRCASECMP && !HAVE_STRICMP */
#ifndef HAVE_STRDUP
/*
* strdup function from FreeBSD
*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
EDITORCONFIG_LOCAL
char* ec_strdup(const char *str)
{
size_t len;
char* copy;
len = strlen(str) + 1;
if ((copy = malloc(len)) == NULL)
return (NULL);
memcpy(copy, str, len);
return (copy);
}
#endif /* !HAVE_STRDUP */
#ifndef HAVE_STRNDUP
/*
* strndup function from NetBSD
*
* $NetBSD: strndup.c,v 1.3 2007/01/14 23:41:24 cbiere Exp $
*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "global.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
EDITORCONFIG_LOCAL
char* ec_strndup(const char* str, size_t n)
{
size_t len;
char* copy;
for (len = 0; len < n && str[len]; len++)
continue;
if ((copy = malloc(len + 1)) == NULL)
return (NULL);
memcpy(copy, str, len);
copy[len] = '\0';
return (copy);
}
#endif /* HAVE_STRNDUP */
/*
* replace oldc with newc in the string str
*/
EDITORCONFIG_LOCAL
char* str_replace(char* str, char oldc, char newc)
{
char* p;
if (str == NULL)
return NULL;
for (p = str; *p != '\0'; p++)
if (*p == oldc)
*p = newc;
return str;
}
#ifndef HAVE_STRLWR
#include <ctype.h>
/*
* convert the string to lowercase
*/
EDITORCONFIG_LOCAL
char* ec_strlwr(char* str)
{
char* p;
for (p = str; *p; ++p)
*p = (char)tolower((unsigned char)*p);
return str;
}
#endif /* !HAVE_STRLWR */
/*
* is path an abosolute file path
*/
EDITORCONFIG_LOCAL
_Bool is_file_path_absolute(const char* path)
{
if (!path)
return 0;
#if defined(UNIX)
if (*path == '/')
return 1;
return 0;
#elif defined(WIN32)
return !PathIsRelative(path);
#else
# error "Either UNIX or WIN32 must be defined."
#endif
}

63
src/lib/misc.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2011-2019 EditorConfig Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MISC_H__
#define MISC_H__
#include "global.h"
#include <stddef.h>
#ifndef HAVE_STRCASECMP
# ifdef HAVE_STRICMP
# define strcasecmp stricmp
# else /* HAVE_STRICMP */
EDITORCONFIG_LOCAL
int ec_strcasecmp(const char *s1, const char *s2);
# define strcasecmp ec_strcasecmp
# endif /* HAVE_STRICMP */
#endif /* !HAVE_STRCASECMP */
#ifndef HAVE_STRDUP
EDITORCONFIG_LOCAL
char* ec_strdup(const char *str);
# define strdup ec_strdup
#endif
#ifndef HAVE_STRNDUP
EDITORCONFIG_LOCAL
char* ec_strndup(const char* str, size_t n);
# define strndup ec_strndup
#endif
EDITORCONFIG_LOCAL
char* str_replace(char* str, char oldc, char newc);
#ifndef HAVE_STRLWR
EDITORCONFIG_LOCAL
char* ec_strlwr(char* str);
# define strlwr ec_strlwr
#endif
EDITORCONFIG_LOCAL
_Bool is_file_path_absolute(const char* path);
#endif /* !MISC_H__ */

247
src/lib/utarray.h Normal file
View File

@ -0,0 +1,247 @@
/*
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* a dynamic array implementation using macros
*/
#ifndef UTARRAY_H
#define UTARRAY_H
#define UTARRAY_VERSION 2.1.0
#include <stddef.h> /* size_t */
#include <string.h> /* memset, etc */
#include <stdlib.h> /* exit */
#ifdef __GNUC__
#define UTARRAY_UNUSED __attribute__((__unused__))
#else
#define UTARRAY_UNUSED
#endif
#ifdef oom
#error "The name of macro 'oom' has been changed to 'utarray_oom'. Please update your code."
#define utarray_oom() oom()
#endif
#ifndef utarray_oom
#define utarray_oom() exit(-1)
#endif
typedef void (ctor_f)(void *dst, const void *src);
typedef void (dtor_f)(void *elt);
typedef void (init_f)(void *elt);
typedef struct {
size_t sz;
init_f *init;
ctor_f *copy;
dtor_f *dtor;
} UT_icd;
typedef struct {
unsigned i,n;/* i: index of next available slot, n: num slots */
UT_icd icd; /* initializer, copy and destructor functions */
char *d; /* n slots of size icd->sz*/
} UT_array;
#define utarray_init(a,_icd) do { \
memset(a,0,sizeof(UT_array)); \
(a)->icd = *(_icd); \
} while(0)
#define utarray_done(a) do { \
if ((a)->n) { \
if ((a)->icd.dtor) { \
unsigned _ut_i; \
for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
(a)->icd.dtor(utarray_eltptr(a,_ut_i)); \
} \
} \
free((a)->d); \
} \
(a)->n=0; \
} while(0)
#define utarray_new(a,_icd) do { \
(a) = (UT_array*)malloc(sizeof(UT_array)); \
if ((a) == NULL) { \
utarray_oom(); \
} \
utarray_init(a,_icd); \
} while(0)
#define utarray_free(a) do { \
utarray_done(a); \
free(a); \
} while(0)
#define utarray_reserve(a,by) do { \
if (((a)->i+(by)) > (a)->n) { \
char *utarray_tmp; \
while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \
utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \
if (utarray_tmp == NULL) { \
utarray_oom(); \
} \
(a)->d=utarray_tmp; \
} \
} while(0)
#define utarray_push_back(a,p) do { \
utarray_reserve(a,1); \
if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \
else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \
} while(0)
#define utarray_pop_back(a) do { \
if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \
else { (a)->i--; } \
} while(0)
#define utarray_extend_back(a) do { \
utarray_reserve(a,1); \
if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \
else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \
(a)->i++; \
} while(0)
#define utarray_len(a) ((a)->i)
#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL)
#define _utarray_eltptr(a,j) ((a)->d + ((a)->icd.sz * (j)))
#define utarray_insert(a,p,j) do { \
if ((j) > (a)->i) utarray_resize(a,j); \
utarray_reserve(a,1); \
if ((j) < (a)->i) { \
memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \
((a)->i - (j))*((a)->icd.sz)); \
} \
if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \
else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \
(a)->i++; \
} while(0)
#define utarray_inserta(a,w,j) do { \
if (utarray_len(w) == 0) break; \
if ((j) > (a)->i) utarray_resize(a,j); \
utarray_reserve(a,utarray_len(w)); \
if ((j) < (a)->i) { \
memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \
_utarray_eltptr(a,j), \
((a)->i - (j))*((a)->icd.sz)); \
} \
if ((a)->icd.copy) { \
unsigned _ut_i; \
for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \
(a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \
} \
} else { \
memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \
utarray_len(w)*((a)->icd.sz)); \
} \
(a)->i += utarray_len(w); \
} while(0)
#define utarray_resize(dst,num) do { \
unsigned _ut_i; \
if ((dst)->i > (unsigned)(num)) { \
if ((dst)->icd.dtor) { \
for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \
(dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \
} \
} \
} else if ((dst)->i < (unsigned)(num)) { \
utarray_reserve(dst, (num) - (dst)->i); \
if ((dst)->icd.init) { \
for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \
(dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \
} \
} else { \
memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \
} \
} \
(dst)->i = (num); \
} while(0)
#define utarray_concat(dst,src) do { \
utarray_inserta(dst, src, utarray_len(dst)); \
} while(0)
#define utarray_erase(a,pos,len) do { \
if ((a)->icd.dtor) { \
unsigned _ut_i; \
for (_ut_i = 0; _ut_i < (len); _ut_i++) { \
(a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \
} \
} \
if ((a)->i > ((pos) + (len))) { \
memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \
((a)->i - ((pos) + (len))) * (a)->icd.sz); \
} \
(a)->i -= (len); \
} while(0)
#define utarray_renew(a,u) do { \
if (a) utarray_clear(a); \
else utarray_new(a, u); \
} while(0)
#define utarray_clear(a) do { \
if ((a)->i > 0) { \
if ((a)->icd.dtor) { \
unsigned _ut_i; \
for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
(a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \
} \
} \
(a)->i = 0; \
} \
} while(0)
#define utarray_sort(a,cmp) do { \
qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \
} while(0)
#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp)
#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL)
#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))
#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL))
#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL)
#define utarray_eltidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1)
/* last we pre-define a few icd for common utarrays of ints and strings */
static void utarray_str_cpy(void *dst, const void *src) {
char **_src = (char**)src, **_dst = (char**)dst;
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
}
static void utarray_str_dtor(void *elt) {
char **eltc = (char**)elt;
if (*eltc != NULL) free(*eltc);
}
static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor};
static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL};
static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL};
#endif /* UTARRAY_H */

46
test.ps1 Normal file
View File

@ -0,0 +1,46 @@
param(
[ValidateSet("pcre2","core")]
[string] $proj = "core",
[ValidateSet("ON","OFF")]
[string] $static = "ON",
[ValidateSet("Debug","Release")]
[string] $config = "Release",
[ValidateSet("x86","x64")]
[string] $arch = "x64"
)
$ErrorActionPreference="stop"
$dest = "bin"
if ((Test-Path $dest) -ne $true){
throw "Missing build path! Used init?"
}
$dest += "\$arch"
if($static -eq "ON"){
$dest += "-static"
}
$bin = "$dest\build\bin"
$dest += "\$proj"
if ((Test-Path $dest) -ne $true){
throw "Missing build path! Used init?"
}
$env:Path += ";" + (Resolve-Path $bin)
"Testing $proj" | Write-Host -ForegroundColor DarkGreen
Push-Location $dest
try {
ctest -E utf_8_char -VV --output-on-failure . -C $config
} finally {
Pop-Location
}

11
tests/.editorconfig Normal file
View File

@ -0,0 +1,11 @@
[CMakeLists.txt]
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
[*.in]
trim_trailing_whitespace = false
[*.md]
indent_style = space
indent_size = 4

13
tests/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# Generated by CMake
CMakeCache.txt
CMakeFiles
Makefile
cmake_install.cmake
install_manifest.txt
# Generated by CTest
/Testing
CTestTestfile.cmake
# Eclipse
.project

91
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,91 @@
#
# Copyright (c) 2011-2018 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Don't check any language compiler. This project is for EditorConfig Core
# testing only.
project(editorconfig-core-test NONE)
# Where this file lives
set(tests_cmakelists_dir "${CMAKE_CURRENT_LIST_DIR}")
#message(STATUS "Tests are in ${tests_cmakelists_dir}")
# Only when we are using editorconfig-core-test independently should we check
# cmake version, set EDITORCONFIG_CMD as cache string, and enable_testing()
# here.
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
cmake_minimum_required(VERSION 3.5)
set(EDITORCONFIG_CMD "editorconfig" CACHE STRING "editorconfig command.")
enable_testing()
endif()
# The most common test function
function(new_ec_test name ec_file src_file regex)
add_test(${name} ${EDITORCONFIG_CMD} -f ${ec_file}
"${CMAKE_CURRENT_SOURCE_DIR}/${src_file}")
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION "${regex}")
endfunction()
# The tests that requires version specified
function(new_ec_test_version name ec_file src_file regex version)
add_test(${name} ${EDITORCONFIG_CMD} -b ${version} -f ${ec_file}
"${CMAKE_CURRENT_SOURCE_DIR}/${src_file}")
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION "${regex}")
endfunction()
# The tests that requires the full path EditorConfig files
function(new_ec_test_full_ec_file_path name ec_file src_file regex)
add_test(${name} ${EDITORCONFIG_CMD} -f ${ec_file} "${src_file}")
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION "${regex}")
endfunction()
# A test that returns multiple lines of output. CAUTION: filenames used in
# these tests may not contain semicolons.
function(new_ec_test_multiline name ec_file src_file regex)
#message(STATUS "Building multiline test ${name} with tests_cmakelists_dir ${tests_cmakelists_dir}")
#message(STATUS "List dir ${CMAKE_CURRENT_LIST_DIR}, source dir ${CMAKE_CURRENT_SOURCE_DIR}")
add_test(${name} "cmake"
"-D" "EDITORCONFIG_CMD=${EDITORCONFIG_CMD}"
# Since variables aren't autpmatically passed to the inner cmake
"-D" "ECARGS:LIST=-f;${ec_file};${CMAKE_CURRENT_SOURCE_DIR}/${src_file}"
# Note: the semicolons separate list elements.
"-P" "${tests_cmakelists_dir}/cmake/ec_sort.cmake")
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION
"^[\n]*${regex}$")
# Permit leading \n's because I can't always get rid of them using
# only CMake-provided facilities.
endfunction()
# First, make sure the test harness works.
add_subdirectory(meta)
# Then test the core.
add_subdirectory(glob)
add_subdirectory(properties)
add_subdirectory(parser)
add_subdirectory(filetree)
add_subdirectory(cli)

23
tests/LICENSE.txt Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2011-2018 EditorConfig Team
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

37
tests/README.md Normal file
View File

@ -0,0 +1,37 @@
This project is a series of testing for [EditorConfig Core][editorconfig]. Please have
[cmake][] installed before using this project.
### Use editorconfig-core-test independently
After installing cmake, switch to the root dir of this project, and execute:
cmake -DEDITORCONFIG_CMD=the_editorconfig_core_cmd_you_want_to_test .
After that, if testing files are generated successfully, execute `ctest .` to
start testings.
### Use editorconfig-core-test in your project as a git submodule
If you are using [git][] and cmake to manage your project, this method should
be suitable for you.
Suppose that you will add editorconfig-core-test repo as a
submodule in your root directory. First add editorconfig-core-test as a
gitsubmodule in your repo by execute:
git submodule add git://github.com/editorconfig/editorconfig-core-test.git tests
Then add the following lines to your project root `CMakeLists.txt`:
```cmake
enable_testing()
set(EDITORCONFIG_CMD the_editorconfig_core_path)
add_subdirectory(tests)
```
Now after executing `cmake .` in you project root dir, you should be able to
run the testings by executing `ctest .`.
[cmake]: http://www.cmake.org
[editorconfig]: http://editorconfig.org
[git]: http://git-scm.com

52
tests/cli/CMakeLists.txt Normal file
View File

@ -0,0 +1,52 @@
#
# Copyright (c) 2011-2018 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Tests for version switches
# test --version option returns version information
add_test(test_long_version_switch ${EDITORCONFIG_CMD} --version)
set_tests_properties(test_long_version_switch PROPERTIES
PASS_REGULAR_EXPRESSION
"^EditorConfig.* Version [0-9]+\\.[0-9]+\\.[0-9]+(-[a-z]+)?[ \t\n\r]$")
# test -v option returns version information
add_test(test_short_version_switch ${EDITORCONFIG_CMD} -v)
set_tests_properties(test_short_version_switch PROPERTIES
PASS_REGULAR_EXPRESSION
"^EditorConfig.* Version [0-9]+\\.[0-9]+\\.[0-9]+(-[a-z]+)?[ \t\n\r]$")
# Test for multiple input files
# when files are specified on command line. The files can appear in either
# order in the output, but each file's output line must be grouped with its
# file header. Handle this by listing both possibilities manually in the regex.
add_test(multiple_files_on_command_line ${EDITORCONFIG_CMD} -f cli.in
"${CMAKE_CURRENT_SOURCE_DIR}/file1.c"
"${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp")
set_tests_properties(multiple_files_on_command_line PROPERTIES
PASS_REGULAR_EXPRESSION
"^(\\[${CMAKE_CURRENT_SOURCE_DIR}/file1.c\\][ \t]*[\n\r]+key1=value1[ \t]*[\n\r]+\\[${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp\\][ \t]*[\n\r]+key2=value2)|(\\[${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp\\][ \t]*[\n\r]+key2=value2[ \t]*[\n\r]+\\[${CMAKE_CURRENT_SOURCE_DIR}/file1.c\\][ \t]*[\n\r]+key1=value1)[ \t\n\r]*$"
)

7
tests/cli/cli.in Normal file
View File

@ -0,0 +1,7 @@
root = true
[*.c]
key1 = value1
[*.cpp]
key2 = value2

44
tests/cmake/almostcat.cmake Executable file
View File

@ -0,0 +1,44 @@
# almostcat.cmake: print the file named in ${WHICH} to **stderr**. Puts an
# extra space at the beginning to suppress CMake's word wrapping. May add
# an extra \n at the end because that's what message() does.
# BSD-2-Clause
# Copyright 2018 Christopher White (cxw42 at GitHub; http://devwrench.com)
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.5)
if("${WHICH}" STREQUAL "")
message(FATAL_ERROR "No WHICH parameter specified")
return()
endif()
#message(FATAL_ERROR " Reading ${WHICH}") # Uncomment for debugging
file(READ "${WHICH}" contents)
# message() will give us an extra \n, so trim one if we can.
string(REGEX REPLACE "(\r\n|\r|\n)$" "" lines "${lines}")
# Print, with a leading space as noted above.
message(" ${contents}")

70
tests/cmake/ec_sort.cmake Executable file
View File

@ -0,0 +1,70 @@
# ec_sort.cmake: Run editorconfig and sort its output
# For use in editorconfig; see
# https://github.com/editorconfig/editorconfig/issues/375 .
# Call as, e.g.:
# cmake -D EDITORCONFIG_CMD="../editorconfig" -D ECARGS:LIST="-f;.editorconfig;foo" -P cmake/ec_sort.cmake
# EDITORCONFIG_CMD may also be list-valued. EDITORCONFIG_CMD and ECARGS
# are put together on the command line, in that order, and split by CMake.
# BSD-2-Clause
# Copyright 2018 Christopher White (cxw42 at GitHub; http://devwrench.com)
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.5)
# See documentation links at https://stackoverflow.com/q/12802377/2877364
set(tests_cmake_ec_sort_dir "${CMAKE_CURRENT_LIST_DIR}")
list(APPEND CMAKE_MODULE_PATH "${tests_cmake_ec_sort_dir}/../cmake")
include(runandsort)
# Required parameters are in variables: EDITORCONFIG_CMD and ECARGS
if("${EDITORCONFIG_CMD}" STREQUAL "")
message(FATAL_ERROR "No EDITORCONFIG_CMD parameter specified")
return()
endif()
if("${ECARGS}" STREQUAL "")
message(FATAL_ERROR "No ECARGS parameter specified")
return()
endif()
# Uncomment for debugging
#message(FATAL_ERROR " Running ${EDITORCONFIG_CMD} with ${ECARGS}")
run_and_sort(RETVAL lines RETVAL_FAILURE did_fail
CMDLINE ${EDITORCONFIG_CMD} ${ECARGS}
)
if(${did_fail})
message(FATAL_ERROR "${EDITORCONFIG_CMD} ${ECARGS} returned a nonzero exit code")
return()
endif()
# message() will give us an extra \n, so trim one if we can.
string(REGEX REPLACE "(\r\n|\r|\n)$" "" lines "${lines}")
# Output **to stderr**. If we used message(STATUS...), it would print to
# stdout but also emit a leading "--".
message("${lines}")

131
tests/cmake/runandsort.cmake Executable file
View File

@ -0,0 +1,131 @@
# runandsort.cmake: Run a program and sort its output
# For use in editorconfig; see
# https://github.com/editorconfig/editorconfig/issues/375 .
# BSD-2-Clause
# Copyright 2018 Christopher White (cxw42 at GitHub; http://devwrench.com)
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.5)
# Conventions:
# - "P_*" are parameters parsed using cmake_parse_arguments
# - Any parameter called "RETVAL", "RETVAL_*", or "*_NAME" should be given
# the name of a variable in the caller's scope into which to
# store results.
# Run a program with the given arguments, and return its sorted output as
# a string.
# CAUTION 1: May not produce correct output if any output line includes
# a semicolon, because that is a list separator in CMake.
# CAUTION 2: Depends on sort order of CMake; see discussion at
# https://gitlab.kitware.com/cmake/cmake/issues/18551
#
# Limitations:
# Any \x01 in the string will be corrupted - this routine uses those to work
# around CMake limitations.
# Arguments:
# RETVAL . . . . . . . The name of the variable to store the result in
# CMDLINE . . . . . . . The program to run, and any arguments
# RETVAL_FAILURE . . . . If present, a variable that will be set to TRUE
# if PGM returns a non-zero exit code.
# CAPTURE_STDERR . . . . If present, capture stderr instead of stdout
# TRIM_INITIAL_LEADING_SPACE If present, remove initial spaces from the
# first line. This is to work around a hack
# in almostcat.cmake.
#
# Returns:
# The sorted stdout of PGM, or the FAILURE string if PGM failed.
# PGM's stderr is ignored.
function(run_and_sort)
# Argument parsing
set(option_keywords CAPTURE_STDERR TRIM_INITIAL_LEADING_SPACE)
set(one_value_keywords RETVAL RETVAL_FAILURE)
set(multi_value_keywords CMDLINE ARGS)
cmake_parse_arguments(P "${option_keywords}" "${one_value_keywords}"
"${multi_value_keywords}" ${ARGN})
#message(STATUS "Running ${P_CMDLINE}")
execute_process(COMMAND ${P_CMDLINE}
RESULT_VARIABLE ep_retval
OUTPUT_VARIABLE ep_stdout
ERROR_VARIABLE ep_stderr
)
# Which one are we processing?
if(${P_CAPTURE_STDERR})
set(ep_out "${ep_stderr}")
else()
set(ep_out "${ep_stdout}")
endif()
#message(STATUS "Got stdout =${ep_stdout}=")
#message(STATUS "Got stderr =${ep_stderr}=")
# Early bail on failure
if(NOT("${ep_retval}" EQUAL "0"))
set(${P_RETVAL} "" PARENT_SCOPE)
if("${P_RETVAL_FAILURE}" MATCHES ".") # if we got a name
set(${P_RETVAL_FAILURE} TRUE PARENT_SCOPE)
endif()
return()
endif()
# Trim hack
if(${P_TRIM_INITIAL_LEADING_SPACE})
string(REGEX REPLACE "^[ ]+" "" ep_out "${ep_out}")
endif()
# Change all the semicolons in the output to \x01
string(ASCII 1 ONE)
string(REPLACE ";" "${ONE}" ep_out "${ep_out}")
#message(STATUS "After escaping =${ep_out}=")
# Normalize line endings, just in case
string(REGEX REPLACE "\r|\n|\r\n" "\n" ep_out "${ep_out}")
#message(STATUS "After line-endings =${ep_out}=")
# Turn the string into a list
string(REPLACE "\n" ";" ep_out "${ep_out}")
#message(STATUS "After listifying =${ep_out}=")
# Sort the list
list(SORT ep_out)
# Back to individual lines
string(REPLACE ";" "\n" ep_out "${ep_out}")
#message(STATUS "After back to lines =${ep_out}=")
# And back to semicolons. Note: I am not trying to reverse line endings.
string(REPLACE "${ONE}" ";" ep_out "${ep_out}")
#message(STATUS "After unescaping =${ep_out}=")
# Out to the caller
set(${P_RETVAL} "${ep_out}" PARENT_SCOPE)
#message(STATUS "Returned =${ep_out}=")
endfunction(run_and_sort)

View File

@ -0,0 +1,100 @@
#
# Copyright (c) 2011-2018 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
cmake_minimum_required(VERSION 3.5)
# Test for EditorConfig file in parent directory
new_ec_test(parent_directory parent_directory.in parent_directory/test.a "^key=value[ \t\n\r]*$")
# Test for EditorConfig file in parent directory and current directory
new_ec_test_multiline(parent_and_current_dir_ML
parent_directory.in parent_directory/test.b
"key1=value1[ \t]*[\n\r]+key2=value2[ \t\n\r]*")
# Test for file in parent directory and overloaded by file in current directory
new_ec_test(parent_dir_overload parent_directory.in parent_directory/test.c "^key=valueB[ \t\n\r]*$")
# Test for file in parent directory and overloaded by file in current directory and repeated in current directory
new_ec_test(parent_dir_overload_repeat parent_directory.in parent_directory/test.d "^key=value_c[ \t\n\r]*$")
# Test for file in parent directory and overloaded by file in current directory and repeated in current directory, with different patterns
new_ec_test(parent_dir_overload_repeat2 parent_directory.in parent_directory/test.e "^key=value_g[ \t\n\r]*$")
# Test that search stops at root EditorConfig file
new_ec_test(root_file root_file.in root_file/test.a "^[ \t\n\r]*$")
# Test that search stops at root EditorConfig file
new_ec_test(root_file_mixed_case root_file.in root_mixed/test.a "^child=true[ \t\n\r]*$")
# Test that search stops at root EditorConfig file
new_ec_test(root_pattern root_file.in root "^name=root[ \t\n\r]*$")
# Tests path separator match
new_ec_test(path_separator path_separator.in path/separator "^key1=value1[ \t\n\r]*$")
# Windows style path separator in the command line should work on Windows, but
# should not work on other systems (including Cygwin)
if(WIN32)
set(path_separator_backslash_in_cmd_line_regex "^key1=value1[ \t\n\r]*$")
else(WIN32)
set(path_separator_backslash_in_cmd_line_regex "^[ \t\n\r]*$")
endif(WIN32)
new_ec_test_full_ec_file_path(path_separator_backslash_in_cmd_line
path_separator.in "${CMAKE_CURRENT_SOURCE_DIR}\\\\path\\\\separator"
${path_separator_backslash_in_cmd_line_regex})
# Tests path separator match below top of path
new_ec_test(nested_path_separator path_separator.in nested/path/separator "^[ \t\n\r]*$")
# Tests path separator match top of path only
new_ec_test(top_level_path_separator path_separator.in top/of/path "^key2=value2[ \t\n\r]*$")
# Tests path separator match top of path only
new_ec_test(top_level_path_separator_neg path_separator.in not/top/of/path "^[ \t\n\r]*$")
# Test Windows-style path separator (backslash) does not work
new_ec_test(windows_separator path_separator.in windows/separator "^[ \t\n\r]*$")
# Test again that Windows-style path separator (backslash) does not work
new_ec_test(windows_separator2 path_separator.in windows/separator2 "^[ \t\n\r]*$")
# Globs with backslash in it but should be considered as file name on Non-Windows system
if((NOT WIN32) AND (NOT CYGWIN))
new_ec_test(backslash_not_on_windows path_separator.in "windows\\\\separator2" "^key4=value4[ \t\n\r]*$")
endif()
new_ec_test(path_with_special_chars path_with_special_chars.in "path_with_special_[chars/test.a" "^key=value[ \t\n\r]*$")
## " <-- resync the syntax highlighter
# Test the unset value with various common properties
new_ec_test(unset_charset unset.in unset/charset.txt "^charset=unset[ \t\n\r]*$")
new_ec_test(unset_end_of_line unset.in unset/end_of_line.txt "^end_of_line=unset[ \t\n\r]*$")
new_ec_test_multiline(unset_indent_size_ML unset.in unset/indent_size.txt
"indent_size=unset[ \t\n\r]*tab_width=unset[ \t\n\r]*")
new_ec_test(unset_indent_style unset.in unset/indent_style.txt "^indent_style=unset[ \t\n\r]*$")
new_ec_test(unset_insert_final_newline unset.in unset/insert_final_newline.txt "^insert_final_newline=unset[ \t\n\r]*$")
new_ec_test(unset_tab_width unset.in unset/tab_width.txt "^tab_width=unset[ \t\n\r]*$")
new_ec_test(unset_trim_trailing_whitespace unset.in unset/trim_trailing_whitespace.txt "^trim_trailing_whitespace=unset[ \t\n\r]*$")

View File

@ -0,0 +1,16 @@
root = true
[test.a]
key=value
[test.b]
key1=value1
[test.c]
key=valueA
[test.d]
key=value_a
[test.e]
key=value_e

View File

@ -0,0 +1,17 @@
[test.b]
key2=value2
[test.c]
key=valueB
[test.d]
key=value_b
[test.d]
key=value_c
[test.e]
key=value_f
[*.e]
key=value_g

View File

@ -0,0 +1,15 @@
; test for path separator
root=true
[path/separator]
key1=value1
[/top/of/path]
key2=value2
[windows\separator]
key3=value3
[windows\\separator2]
key4=value4

View File

@ -0,0 +1,4 @@
root = true
[test.a]
key=value

View File

@ -0,0 +1,7 @@
root = true
[test.a]
key=value
[root]
name=root

View File

@ -0,0 +1 @@
root = true

View File

@ -0,0 +1,5 @@
root = TrUe
ignore = false
[*.a]
child=true

22
tests/filetree/unset.in Normal file
View File

@ -0,0 +1,22 @@
root = true
[charset.txt]
charset=utf-8
[end_of_line.txt]
end_of_line=lf
[indent_size.txt]
indent_size=2
[indent_style.txt]
indent_style=space
[insert_final_newline.txt]
insert_final_newline=true
[tab_width.txt]
tab_width=4
[trim_trailing_whitespace.txt]
trim_trailing_whitespace=true

View File

@ -0,0 +1,21 @@
[charset.txt]
charset=unset
[end_of_line.txt]
end_of_line=unset
[indent_size.txt]
indent_size=unset
[indent_style.txt]
indent_style=unset
[insert_final_newline.txt]
insert_final_newline=unset
[tab_width.txt]
tab_width=unset
[trim_trailing_whitespace.txt]
trim_trailing_whitespace=unset

249
tests/glob/CMakeLists.txt Normal file
View File

@ -0,0 +1,249 @@
#
# Copyright (c) 2011-2018 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Tests for *
# matches a single characters
new_ec_test_multiline(star_single_ML star.in ace.c "key=value[ \t\n\r]+keyc=valuec[ \t\n\r]*")
# matches zero characters
new_ec_test_multiline(star_zero_ML star.in ae.c "key=value[ \t\n\r]+keyc=valuec[ \t\n\r]*")
# matches multiple characters
new_ec_test_multiline(star_multiple_ML star.in abcde.c "key=value[ \t\n\r]+keyc=valuec[ \t\n\r]*")
# does not match path separator
new_ec_test(star_over_slash star.in a/e.c "^[ \t\n\r]*keyc=valuec[ \t\n\r]*$")
# star after a slash
new_ec_test_multiline(star_after_slash_ML star.in Bar/foo.txt "keyb=valueb[ \t\n\r]+keyc=valuec[ \t\n\r]*")
# star matches a dot file after slash
new_ec_test_multiline(star_matches_dot_file_after_slash_ML star.in Bar/.editorconfig "keyb=valueb[ \t\n\r]+keyc=valuec[ \t\n\r]*")
# star matches a dot file
new_ec_test(star_matches_dot_file star.in .editorconfig "^keyc=valuec[ \t\n\r]*$")
# Tests for ?
# matches a single character
new_ec_test(question_single question.in some.c "^key=value[ \t\n\r]*$")
# does not match zero characters
new_ec_test(question_zero question.in som.c "^[ \t\n\r]*$")
# does not match multiple characters
new_ec_test(question_multiple question.in something.c "^[ \t\n\r]*$")
# Tests for [ and ]
# close bracket inside
new_ec_test(brackets_close_inside brackets.in ].g "^close_inside=true[ \t\n\r]*$")
# close bracket outside
new_ec_test(brackets_close_outside brackets.in b].g "^close_outside=true[ \t\n\r]*$")
# negative close bracket inside
new_ec_test(brackets_nclose_inside brackets.in c.g "^close_inside=false[ \t\n\r]*$")
# negative close bracket outside
new_ec_test(brackets_nclose_outside brackets.in c].g "^close_outside=false[ \t\n\r]*$")
# character choice
new_ec_test(brackets_choice brackets.in a.a "^choice=true[ \t\n\r]*$")
# character choice 2
new_ec_test(brackets_choice2 brackets.in c.a "^[ \t\n\r]*$")
# negative character choice
new_ec_test(brackets_nchoice brackets.in c.b "^choice=false[ \t\n\r]*$")
# negative character choice 2
new_ec_test(brackets_nchoice2 brackets.in a.b "^[ \t\n\r]*$")
# character range
new_ec_test(brackets_range brackets.in f.c "^range=true[ \t\n\r]*$")
# character range 2
new_ec_test(brackets_range2 brackets.in h.c "^[ \t\n\r]*$")
# negative character range
new_ec_test(brackets_nrange brackets.in h.d "^range=false[ \t\n\r]*$")
# negative character range 2
new_ec_test(brackets_nrange2 brackets.in f.d "^[ \t\n\r]*$")
# range and choice
new_ec_test(brackets_range_and_choice brackets.in e.e
"^range_and_choice=true[ \t\n\r]*$")
# character choice with a dash
new_ec_test(brackets_choice_with_dash brackets.in -.f
"^choice_with_dash=true[ \t\n\r]*$")
# slash inside brackets
new_ec_test(brackets_slash_inside1 brackets.in ab/cd.i
"^[ \t\n\r]*$")
new_ec_test(brackets_slash_inside2 brackets.in abecd.i
"^[ \t\n\r]*$")
new_ec_test(brackets_slash_inside3 brackets.in ab[e/]cd.i
"^slash_inside=true[ \t\n\r]*$")
new_ec_test(brackets_slash_inside4 brackets.in ab[/c
"^slash_half_open=true[ \t\n\r]*$")
# Tests for { and }
# word choice
new_ec_test(braces_word_choice1 braces.in test.py "^choice=true[ \t\n\r]*$")
new_ec_test(braces_word_choice2 braces.in test.js "^choice=true[ \t\n\r]*$")
new_ec_test(braces_word_choice3 braces.in test.html "^choice=true[ \t\n\r]*$")
new_ec_test(braces_word_choice4 braces.in test.pyc "^[ \t\n\r]*$")
# single choice
new_ec_test(braces_single_choice braces.in {single}.b "^choice=single[ \t\n\r]*$")
new_ec_test(braces_single_choice_negative braces.in .b "^[ \t\n\r]*$")
# empty choice
new_ec_test(braces_empty_choice braces.in {}.c "^empty=all[ \t\n\r]*$")
new_ec_test(braces_empty_choice_negative braces.in .c "^[ \t\n\r]*$")
# choice with empty word
new_ec_test(braces_empty_word1 braces.in a.d "^empty=word[ \t\n\r]*$")
new_ec_test(braces_empty_word2 braces.in ab.d "^empty=word[ \t\n\r]*$")
new_ec_test(braces_empty_word3 braces.in ac.d "^empty=word[ \t\n\r]*$")
new_ec_test(braces_empty_word4 braces.in a,.d "^[ \t\n\r]*$")
# choice with empty words
new_ec_test(braces_empty_words1 braces.in a.e "^empty=words[ \t\n\r]*$")
new_ec_test(braces_empty_words2 braces.in ab.e "^empty=words[ \t\n\r]*$")
new_ec_test(braces_empty_words3 braces.in ac.e "^empty=words[ \t\n\r]*$")
new_ec_test(braces_empty_words4 braces.in a,.e "^[ \t\n\r]*$")
# no closing brace
new_ec_test(braces_no_closing braces.in {.f "^closing=false[ \t\n\r]*$")
new_ec_test(braces_no_closing_negative braces.in .f "^[ \t\n\r]*$")
# nested braces
new_ec_test(braces_nested1 braces.in word,this}.g "^[ \t\n\r]*$")
new_ec_test(braces_nested2 braces.in {also,this}.g "^[ \t\n\r]*$")
new_ec_test(braces_nested3 braces.in word.g "^nested=true[ \t\n\r]*$")
new_ec_test(braces_nested4 braces.in {also}.g "^nested=true[ \t\n\r]*$")
new_ec_test(braces_nested5 braces.in this.g "^nested=true[ \t\n\r]*$")
# closing inside beginning
new_ec_test(braces_closing_in_beginning braces.in {},b}.h "^closing=inside[ \t\n\r]*$")
# missing closing braces
new_ec_test(braces_unmatched1 braces.in {{,b,c{d}.i "^unmatched=true[ \t\n\r]*$")
new_ec_test(braces_unmatched2 braces.in {.i "^[ \t\n\r]*$")
new_ec_test(braces_unmatched3 braces.in b.i "^[ \t\n\r]*$")
new_ec_test(braces_unmatched4 braces.in c{d.i "^[ \t\n\r]*$")
new_ec_test(braces_unmatched5 braces.in .i "^[ \t\n\r]*$")
# escaped comma
new_ec_test(braces_escaped_comma1 braces.in a,b.txt "^comma=yes[ \t\n\r]*$")
new_ec_test(braces_escaped_comma2 braces.in a.txt "^[ \t\n\r]*$")
new_ec_test(braces_escaped_comma3 braces.in cd.txt "^comma=yes[ \t\n\r]*$")
# escaped closing brace
new_ec_test(braces_escaped_brace1 braces.in e.txt "^closing=yes[ \t\n\r]*$")
new_ec_test(braces_escaped_brace2 braces.in }.txt "^closing=yes[ \t\n\r]*$")
new_ec_test(braces_escaped_brace3 braces.in f.txt "^closing=yes[ \t\n\r]*$")
# escaped backslash
new_ec_test(braces_escaped_backslash1 braces.in g.txt "^backslash=yes[ \t\n\r]*$")
if((NOT WIN32) AND (NOT CYGWIN)) # this case is impossible on Windows.
new_ec_test(braces_escaped_backslash2 braces.in \\\\.txt "^backslash=yes[ \t\n\r]*$")
endif()
new_ec_test(braces_escaped_backslash3 braces.in i.txt "^backslash=yes[ \t\n\r]*$")
# patterns nested in braces
new_ec_test(braces_patterns_nested1 braces.in some.j "^patterns=nested[ \t\n\r]*$")
new_ec_test(braces_patterns_nested2 braces.in abe.j "^patterns=nested[ \t\n\r]*$")
new_ec_test(braces_patterns_nested3 braces.in abf.j "^patterns=nested[ \t\n\r]*$")
new_ec_test(braces_patterns_nested4 braces.in abg.j "^[ \t\n\r]*$")
new_ec_test(braces_patterns_nested5 braces.in ace.j "^patterns=nested[ \t\n\r]*$")
new_ec_test(braces_patterns_nested6 braces.in acf.j "^patterns=nested[ \t\n\r]*$")
new_ec_test(braces_patterns_nested7 braces.in acg.j "^[ \t\n\r]*$")
new_ec_test(braces_patterns_nested8 braces.in abce.j "^patterns=nested[ \t\n\r]*$")
new_ec_test(braces_patterns_nested9 braces.in abcf.j "^patterns=nested[ \t\n\r]*$")
new_ec_test(braces_patterns_nested10 braces.in abcg.j "^[ \t\n\r]*$")
new_ec_test(braces_patterns_nested11 braces.in ae.j "^[ \t\n\r]*$")
new_ec_test(braces_patterns_nested12 braces.in .j "^[ \t\n\r]*$")
# numeric brace range
new_ec_test(braces_numeric_range1 braces.in 1 "^[ \t\n\r]*$")
new_ec_test(braces_numeric_range2 braces.in 3 "^number=true[ \t\n\r]*$")
new_ec_test(braces_numeric_range3 braces.in 15 "^number=true[ \t\n\r]*$")
new_ec_test(braces_numeric_range4 braces.in 60 "^number=true[ \t\n\r]*$")
new_ec_test(braces_numeric_range5 braces.in 5a "^[ \t\n\r]*$")
new_ec_test(braces_numeric_range6 braces.in 120 "^number=true[ \t\n\r]*$")
new_ec_test(braces_numeric_range7 braces.in 121 "^[ \t\n\r]*$")
new_ec_test(braces_numeric_range8 braces.in 060 "^[ \t\n\r]*$")
# alphabetical brace range: letters should not be considered for ranges
new_ec_test(braces_alpha_range1 braces.in {aardvark..antelope} "^words=a[ \t\n\r]*$")
new_ec_test(braces_alpha_range2 braces.in a "^[ \t\n\r]*$")
new_ec_test(braces_alpha_range3 braces.in aardvark "^[ \t\n\r]*$")
new_ec_test(braces_alpha_range4 braces.in agreement "^[ \t\n\r]*$")
new_ec_test(braces_alpha_range5 braces.in antelope "^[ \t\n\r]*$")
new_ec_test(braces_alpha_range6 braces.in antimatter "^[ \t\n\r]*$")
# Tests for **
# test EditorConfig files with UTF-8 characters larger than 127
new_ec_test(utf_8_char utf8char.in "中文.txt" "^key=value[ \t\n\r]*$")
# matches over path separator
new_ec_test(star_star_over_separator1 star_star.in a/z.c "^key1=value1[ \t\n\r]*$")
new_ec_test(star_star_over_separator2 star_star.in amnz.c "^key1=value1[ \t\n\r]*$")
new_ec_test(star_star_over_separator3 star_star.in am/nz.c "^key1=value1[ \t\n\r]*$")
new_ec_test(star_star_over_separator4 star_star.in a/mnz.c "^key1=value1[ \t\n\r]*$")
new_ec_test(star_star_over_separator5 star_star.in amn/z.c "^key1=value1[ \t\n\r]*$")
new_ec_test(star_star_over_separator6 star_star.in a/mn/z.c "^key1=value1[ \t\n\r]*$")
new_ec_test(star_star_over_separator7 star_star.in b/z.c "^key2=value2[ \t\n\r]*$")
new_ec_test(star_star_over_separator8 star_star.in b/mnz.c "^key2=value2[ \t\n\r]*$")
new_ec_test(star_star_over_separator9 star_star.in b/mn/z.c "^key2=value2[ \t\n\r]*$")
new_ec_test(star_star_over_separator10 star_star.in bmnz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator11 star_star.in bm/nz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator12 star_star.in bmn/z.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator13 star_star.in c/z.c "^key3=value3[ \t\n\r]*$")
new_ec_test(star_star_over_separator14 star_star.in cmn/z.c "^key3=value3[ \t\n\r]*$")
new_ec_test(star_star_over_separator15 star_star.in c/mn/z.c "^key3=value3[ \t\n\r]*$")
new_ec_test(star_star_over_separator16 star_star.in cmnz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator17 star_star.in cm/nz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator18 star_star.in c/mnz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator19 star_star.in d/z.c "^key4=value4[ \t\n\r]*$")
new_ec_test(star_star_over_separator20 star_star.in d/mn/z.c "^key4=value4[ \t\n\r]*$")
new_ec_test(star_star_over_separator21 star_star.in dmnz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator22 star_star.in dm/nz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator23 star_star.in d/mnz.c "^[ \t\n\r]*$")
new_ec_test(star_star_over_separator24 star_star.in dmn/z.c "^[ \t\n\r]*$")

63
tests/glob/braces.in Normal file
View File

@ -0,0 +1,63 @@
; test { and }
root=true
; word choice
[*.{py,js,html}]
choice=true
; single choice
[{single}.b]
choice=single
; empty choice
[{}.c]
empty=all
; choice with empty word
[a{b,c,}.d]
empty=word
; choice with empty words
[a{,b,,c,}.e]
empty=words
; no closing brace
[{.f]
closing=false
; nested braces
[{word,{also},this}.g]
nested=true
; closing inside beginning
[{},b}.h]
closing=inside
; opening inside beginning
[{{,b,c{d}.i]
unmatched=true
; escaped comma
[{a\,b,cd}.txt]
comma=yes
; escaped closing brace
[{e,\},f}.txt]
closing=yes
; escaped backslash
[{g,\\,i}.txt]
backslash=yes
; patterns nested in braces
[{some,a{*c,b}[ef]}.j]
patterns=nested
; numeric braces
[{3..120}]
number=true
; alphabetical
[{aardvark..antelope}]
words=a

51
tests/glob/brackets.in Normal file
View File

@ -0,0 +1,51 @@
; test [ and ]
root=true
; Character choice
[[ab].a]
choice=true
; Negative character choice
[[!ab].b]
choice=false
; Character range
[[d-g].c]
range=true
; Negative character range
[[!d-g].d]
range=false
; Range and choice
[[abd-g].e]
range_and_choice=true
; Choice with dash
[[-ab].f]
choice_with_dash=true
; Close bracket inside
[[\]ab].g]
close_inside=true
; Close bracket outside
[[ab]].g]
close_outside=true
; Negative close bracket inside
[[!\]ab].g]
close_inside=false
; Negative¬close bracket outside
[[!ab]].g]
close_outside=false
; Slash inside brackets
[ab[e/]cd.i]
slash_inside=true
; Slash after an half-open bracket
[ab[/c]
slash_half_open=true

7
tests/glob/question.in Normal file
View File

@ -0,0 +1,7 @@
; test ?
root=true
[som?.c]
key=value

12
tests/glob/star.in Normal file
View File

@ -0,0 +1,12 @@
; test *
root=true
[a*e.c]
key=value
[Bar/*]
keyb=valueb
[*]
keyc=valuec

15
tests/glob/star_star.in Normal file
View File

@ -0,0 +1,15 @@
; test **
root=true
[a**z.c]
key1=value1
[b/**z.c]
key2=value2
[c**/z.c]
key3=value3
[d/**/z.c]
key4=value4

6
tests/glob/utf8char.in Normal file
View File

@ -0,0 +1,6 @@
; test EditorConfig files with UTF-8 characters larger than 127
root = true
[中文.txt]
key = value

45
tests/meta/CMakeLists.txt Executable file
View File

@ -0,0 +1,45 @@
# tests/meta/CMakeLists.txt: Test of the test harness for editorconfig.
# BSD-2-Clause
# Copyright 2018 Christopher White (cxw42 at GitHub; http://devwrench.com)
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.5)
set(tests_meta_cmakelists_dir "${CMAKE_CURRENT_LIST_DIR}")
# Line separator regex, for convenience
set(L "[ \t\n\r]+")
message(STATUS "meta: Using editorconfig ${EDITORCONFIG_CMD}")
# Test run_and_sort()
add_test(meta_runandsort cmake -P "${tests_meta_cmakelists_dir}/sample.cmake")
set_tests_properties(meta_runandsort PROPERTIES PASS_REGULAR_EXPRESSION
"^[\n]*0${L}a;b${L}b;c${L}b;e${L}b;f${L}c;b;a${L}d${L}$")
# Have to permit leading \n's - I don't know how to get rid of them
# Test the new multiline macro on a simple case
new_ec_test_multiline(meta_multiline meta.in meta.c
"^[\n]*answer=42${L}$")

2
tests/meta/meta.in Executable file
View File

@ -0,0 +1,2 @@
[meta.c]
answer=42

31
tests/meta/sample.cmake Normal file
View File

@ -0,0 +1,31 @@
# sample.cmake: Tests run_and_sort to make sure it's working.
cmake_minimum_required(VERSION 3.5)
# See documentation links at https://stackoverflow.com/q/12802377/2877364
set( tests_meta_sample_dir "${CMAKE_CURRENT_LIST_DIR}" )
list( APPEND CMAKE_MODULE_PATH "${tests_meta_sample_dir}/../cmake" )
include( runandsort )
run_and_sort( RETVAL lines RETVAL_FAILURE did_fail
CAPTURE_STDERR TRIM_INITIAL_LEADING_SPACE # since we're using almostcat
CMDLINE "cmake" "-DWHICH:STRING=${tests_meta_sample_dir}/sample.txt"
"-P" "${tests_meta_sample_dir}/../cmake/almostcat.cmake"
) # Don't use cat(1) since we might be running on Windows
if( ${did_fail} )
message( FATAL_ERROR "Program returned a nonzero exit code" )
return()
endif()
# message() will give us an extra \n, so trim one if we can.
string( REGEX REPLACE "(\r\n|\r|\n)$" "" lines "${lines}" )
message( "${lines}" )
# This outputs to stderr, and prints nothing extra except for a \n at the end
# Note that message( STATUS "${lines}" ) doesn't work because it outputs a "--"
# before the actual content.
# You could also use execute_process( COMMAND "echo" "${lines}" )
# or cmake -E echo, but I think the message() call is good enough.

7
tests/meta/sample.txt Executable file
View File

@ -0,0 +1,7 @@
b;f
b;c
b;e
a;b
c;b;a
d
0

166
tests/parser/CMakeLists.txt Normal file
View File

@ -0,0 +1,166 @@
#
# Copyright (c) 2011-2018 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Basic parser tests
# test repeat sections
new_ec_test_multiline(repeat_sections_ML basic.in a.a "option1=value1[ \t]*[\n\r]+option2=value2[ \t\n\r]*")
new_ec_test_multiline(basic_cascade_ML basic.in b.b "option1=c[ \t]*[\n\r]+option2=b[ \t\n\r]*")
# Tests for whitespace parsing
# test no whitespaces in property assignment
new_ec_test(no_whitespace whitespace.in test1.c "^key=value[ \t\n\r]*$")
# test single spaces around equals sign
new_ec_test(single_spaces_around_equals whitespace.in test2.c
"^key=value[ \t\n\r]*$")
# test multiple spaces around equals sign
new_ec_test(multiple_spaces_around_equals whitespace.in test3.c
"^key=value[ \t\n\r]*$")
# test spaces before property name
new_ec_test(spaces_before_property_name whitespace.in test4.c
"^key=value[ \t\n\r]*$")
# test spaces before after property value
new_ec_test(spaces_after_property_value whitespace.in test5.c
"^key=value[ \t\n\r]*$")
# test blank lines between properties
new_ec_test_multiline(blank_lines_between_properties_ML whitespace.in test6.c
"key1=value1[ \t]*[\n\r]+key2=value2[ \t\n\r]*")
# test spaces in section name
new_ec_test(spaces_in_section_name whitespace.in " test 7 "
"^key=value[ \t\n\r]*$")
# test spaces before section name are ignored
new_ec_test(spaces_before_section_name whitespace.in test8.c
"^key=value[ \t\n\r]*$")
# test spaces after section name
new_ec_test(spaces_after_section_name whitespace.in test9.c "^key=value[ \t\n\r]*$")
# test spaces at beginning of line between properties
new_ec_test_multiline(spaces_before_middle_property_ML whitespace.in test10.c
"key1=value1[ \t]*[\n\r]+key2=value2[ \t]*[\n\r]+key3=value3[ \t\n\r]*")
# test colon seperator with no whitespaces in property assignment
new_ec_test(colon_sep_no_whitespace whitespace.in test1.d "^key=value[ \t\n\r]*$")
# test colon seperator with single spaces around equals sign
new_ec_test(colon_sep_single_spaces_around_equals whitespace.in test2.d
"^key=value[ \t\n\r]*$")
# test colon seperator with multiple spaces around equals sign
new_ec_test(colon_sep_multiple_spaces_around_equals whitespace.in test3.d
"^key=value[ \t\n\r]*$")
# test colon seperator with spaces before property name
new_ec_test(colon_sep_spaces_before_property_name whitespace.in test4.d
"^key=value[ \t\n\r]*$")
# test colon seperator with spaces before after property value
new_ec_test(colon_sep_spaces_after_property_value whitespace.in test5.d
"^key=value[ \t\n\r]*$")
# Tests for comment parsing
# test comments ignored after property name
new_ec_test(comments_after_property comments.in test1.c
"^key=value[ \t\n\r]*$")
# test comments ignored after section name
new_ec_test(comments_after_section comments.in test2.c
"^key=value[ \t\n\r]*$")
# test comments ignored before properties
new_ec_test(comment_before_props comments.in test3.c
"^key=value[ \t\n\r]*$")
# test comments ignored between properties
new_ec_test_multiline(comment_between_props_ML comments.in test4.c
"key1=value1[ \t]*[\n\r]+key2=value2[ \t\n\r]*")
# test semicolons at end of property value are included in value
new_ec_test(semicolon_in_property comments.in test5.c
"^key=value; not comment[ \t\n\r]*$")
# test escaped semicolons are included in property value
new_ec_test(escaped_semicolon_in_property comments.in test6.c
"^key=value ; not comment[ \t\n\r]*$")
# test escaped semicolons are included in section names
new_ec_test(escaped_semicolon_in_section comments.in "test;.c"
"^key=value[ \t\n\r]*$")
# test octothorpe comments ignored after property name
new_ec_test(octothorpe_comments_after_property comments.in test7.c
"^key=value[ \t\n\r]*$")
# test octothorpe comments ignored after section name
new_ec_test(octothorpe_comments_after_section comments.in test8.c
"^key=value[ \t\n\r]*$")
# test octothorpe comments ignored before properties
new_ec_test(octothorpe_comment_before_props comments.in test9.c
"^key=value[ \t\n\r]*$")
# test octothorpe comments ignored between properties
new_ec_test_multiline(octothorpe_comment_between_props_ML comments.in test10.c
"key1=value1[ \t]*[\n\r]+key2=value2[ \t\n\r]*")
# test octothorpe at end of property value are included in value
new_ec_test(octothorpe_in_property comments.in test11.c
"^key=value# not comment[ \t\n\r]*$")
# test escaped octothorpes are included in property value
new_ec_test(escaped_octothorpe_in_property comments.in test12.c
"^key=value # not comment[ \t\n\r]*$")
# test escaped octothorpes are included in section names
new_ec_test(escaped_octothorpe_in_section comments.in "test\#.c"
"^key=value[ \t\n\r]*$")
# test EditorConfig files with BOM at the head
new_ec_test(bom_at_head bom.in "a.c" "^key=value[ \t\n\r]*$")
# test EditorConfig files with CRLF line separators
new_ec_test(crlf_linesep crlf.in "a.c" "^key=value[ \t\n\r]*$")
# Test max property name and values
new_ec_test(max_property_name limits.in test1
"^00000000000000000000000000000000000000000000000001=50[ \t\n\r]*$")
new_ec_test(max_property_value limits.in test2
"^k255=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001[ \t\n\r]*$")
# Test max section names
new_ec_test(max_section_name_ok limits.in test3 "^key=value[ \t\n\r]*$")
new_ec_test(max_section_name_ignore limits.in test4 "^[ \t\n\r]*$")

16
tests/parser/basic.in Normal file
View File

@ -0,0 +1,16 @@
[*.a]
option1=value1
; repeat section
[*.a]
option2=value2
[*.b]
option1 = a
option2 = a
[b.b]
option2 = b
[*.b]
option1 = c

6
tests/parser/bom.in Normal file
View File

@ -0,0 +1,6 @@
; test EditorConfig files with BOM
root = true
[*]
key = value

57
tests/parser/comments.in Normal file
View File

@ -0,0 +1,57 @@
; test comments
root = true
[test1.c]
key=value ; Comment after property is ignored
[test2.c] ; Comment ignored, even with ] character
key=value
[test3.c]
; Comment before properties ignored
key=value
[test4.c]
key1=value1
; Comment between properties ignored
key2=value2
; Semicolon at end of value read as part of value
[test5.c]
key=value; not comment
; Escaped semicolon in value
[test6.c]
key=value \; not comment
; Escaped semicolon in section name
[test\;.c]
key=value
[test7.c]
key=value # Comment after property is ignored
[test8.c] # Comment ignored, even with ] character
key=value
[test9.c]
# Comment before properties ignored
key=value
[test10.c]
key1=value1
# Comment between properties ignored
key2=value2
# Octothorpe at end of value read as part of value
[test11.c]
key=value# not comment
# Escaped octothorpe in value
[test12.c]
key=value \# not comment
# Escaped octothorpe in section name
[test\#.c]
key=value

6
tests/parser/crlf.in Normal file
View File

@ -0,0 +1,6 @@
; test EditorConfig files with CRLF line separators
root = true
[*]
key = value

15
tests/parser/limits.in Normal file
View File

@ -0,0 +1,15 @@
root = true
[test1]
00000000000000000000000000000000000000000000000001=50
000000000000000000000000000000000000000000000000002=51
[test2]
k255=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
k256=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
[{test3,test0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003}]
key=value
[{test4,test00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004}]
key=value

View File

@ -0,0 +1,68 @@
; test whitespace usage
root = true
; no whitespace
[test1.c]
key=value
; spaces around equals
[test2.c]
key = value
; lots of space after equals
[test3.c]
key = value
; spaces before property name
[test4.c]
key=value
; spaces after property value
[test5.c]
key=value
; blank lines between properties
[test6.c]
key1=value1
key2=value2
; spaces in section name
[ test 7 ]
key=value
; spaces before section name
[test8.c]
key=value
; spaces after section name
[test9.c]
key=value
; spacing before middle property
[test10.c]
key1=value1
key2=value2
key3=value3
; colon separator with no spaces
[test1.d]
key:value
; colon separator with space after
[test2.d]
key: value
; colon separator with space before and after
[test3.d]
key : value
; colon separator with spaces before
[test4.d]
key:value
; colon seperator with spaces after property value
[test5.d]
key:value

View File

@ -0,0 +1,71 @@
#
# Copyright (c) 2011-2018 EditorConfig Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# test tab_width default
new_ec_test_multiline(tab_width_default_ML tab_width_default.in test.c
"indent_size=4[ \t]*[\n\r]+indent_style=space[ \t]*[\n\r]+tab_width=4[\t\n\r]*")
# Tab_width should not be set to any value if indent_size is "tab" and
# tab_width is not set
new_ec_test_multiline(tab_width_default_indent_size_tab_ML tab_width_default.in test2.c
"indent_size=tab[ \t]*[\n\r]+indent_style=tab[ \t\n\r]*")
# Test indent_size default. When indent_style is "tab", indent_size defaults to
# "tab".
new_ec_test_multiline(indent_size_default_ML indent_size_default.in test.c
"indent_size=tab[ \t]*[\n\r]+indent_style=tab[ \t\n\r]*")
# Test indent_size default. When indent_style is "tab", indent_size should have
# no default value for version prior than 0.9.0.
new_ec_test_version(indent_size_default_pre_0_9_0 indent_size_default.in test.c
"^indent_style=tab[ \t\n\r]*$" 0.8.0)
# Test indent_size default. When indent_style is "space", indent_size has no
# default value.
new_ec_test(indent_size_default_space indent_size_default.in test2.c
"^indent_style=space[ \t\n\r]*$")
# Test indent_size default. When indent_style is "tab" and tab_width is set,
# indent_size should default to tab_width
new_ec_test_multiline(indent_size_default_with_tab_width_ML
indent_size_default.in test3.c
"indent_size=2[ \t]*[\n\r]+indent_style=tab[ \t]*[\n\r]+tab_width=2[ \t\n\r]*")
# test that same property values are lowercased (v0.9.0 properties)
new_ec_test_multiline(lowercase_values1_ML lowercase_values.in test1.c
"end_of_line=crlf[ \t]*[\n\r]+indent_style=space[ \t\n\r]*")
# test that same property values are lowercased (v0.9.0 properties)
new_ec_test_multiline(lowercase_values2_ML lowercase_values.in test2.c
"charset=utf-8[ \t]*[\n\r]+insert_final_newline=true[ \t]*[\n\r]+trim_trailing_whitespace=false[ \t\n\r]*$")
# test that same property values are not lowercased
new_ec_test(lowercase_values3 lowercase_values.in test3.c
"^test_property=TestValue[ \t\n\r]*$")
# test that all property names are lowercased
new_ec_test(lowercase_names lowercase_names.in test.c
"^testproperty=testvalue[ \t\n\r]*$")

View File

@ -0,0 +1,11 @@
root = true
[test.c]
indent_style = tab
[test2.c]
indent_style = space
[test3.c]
indent_style = tab
tab_width = 2

View File

@ -0,0 +1,6 @@
; test that property names are lowercased
root = true
[test.c]
TestProperty = testvalue

View File

@ -0,0 +1,15 @@
; test property name lowercasing
root = true
[test1.c]
indent_style = Space
end_of_line = CRLF
[test2.c]
insert_final_newline = TRUE
trim_trailing_whitespace = False
charset = UTF-8
[test3.c]
test_property = TestValue

View File

@ -0,0 +1,9 @@
root = true
[test.c]
indent_style = space
indent_size = 4
[test2.c]
indent_style = tab
indent_size = tab