diff -pruN 43.2-1/debian/changelog 43.2-1ubuntu1/debian/changelog
--- 43.2-1/debian/changelog	2023-01-13 14:31:54.000000000 +0000
+++ 43.2-1ubuntu1/debian/changelog	2023-01-13 14:43:39.000000000 +0000
@@ -1,3 +1,14 @@
+gnome-text-editor (43.2-1ubuntu1) lunar; urgency=medium
+
+  * Merge with Debian. Remaining changes:
+    - Add patch to keep using bundled editorconfig-core library.
+      The library isn't approved for unbundled use in Ubuntu main yet.
+      See bug 1984104
+    - Build-Depend on libpcre3-dev as required by the bundled
+      editorconfig-core library
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Fri, 13 Jan 2023 09:43:39 -0500
+
 gnome-text-editor (43.2-1) unstable; urgency=medium
 
   * New upstream release
@@ -16,6 +27,17 @@ gnome-text-editor (43.1-2) unstable; urg
 
  -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 11 Oct 2022 13:57:17 -0400
 
+gnome-text-editor (43.1-1ubuntu1) kinetic; urgency=medium
+
+  * Merge with Debian (LP: #1991713). Remaining change:
+    - Build-Depend on libpcre3-dev as required by the bundled
+      editorconfig-core library
+  * Add patch to keep using bundled editorconfig-core library.
+    The library isn't approved for unbundled use in Ubuntu main yet.
+    See bug 1984104
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Fri, 07 Oct 2022 08:28:32 -0400
+
 gnome-text-editor (43.1-1) unstable; urgency=medium
 
   * New upstream release
@@ -63,6 +85,20 @@ gnome-text-editor (43~alpha1-1) unstable
 
  -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 09 Aug 2022 10:57:09 -0400
 
+gnome-text-editor (42.2-1ubuntu2) kinetic; urgency=medium
+
+  * Add debian/links to install short gted alias (LP: #1987556)
+  * Build-Depend on libpcre3-dev. This change should be dropped for 43
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 06 Sep 2022 09:31:39 -0400
+
+gnome-text-editor (42.2-1ubuntu1) kinetic; urgency=medium
+
+  * Use an ubuntu version number to block version 43 which
+    requires editorconfig-core to be in main. See bug 1984104
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 09 Aug 2022 11:01:12 -0400
+
 gnome-text-editor (42.2-1) unstable; urgency=medium
 
   * Team upload
diff -pruN 43.2-1/debian/control 43.2-1ubuntu1/debian/control
--- 43.2-1/debian/control	2023-01-13 14:31:54.000000000 +0000
+++ 43.2-1ubuntu1/debian/control	2023-01-13 14:43:39.000000000 +0000
@@ -5,7 +5,8 @@
 Source: gnome-text-editor
 Section: gnome
 Priority: optional
-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
 Uploaders: Jeremy Bicha <jbicha@ubuntu.com>
 Build-Depends: debhelper-compat (= 13),
                appstream-util <!nocheck>,
@@ -20,6 +21,7 @@ Build-Depends: debhelper-compat (= 13),
                libgtk-4-dev (>= 4.7),
                libgtksourceview-5-dev (>= 5.5.0),
                libicu-dev,
+               libpcre3-dev,
                meson (>= 0.59.1)
 Standards-Version: 4.6.1
 Rules-Requires-Root: no
diff -pruN 43.2-1/debian/control.in 43.2-1ubuntu1/debian/control.in
--- 43.2-1/debian/control.in	2023-01-13 14:31:54.000000000 +0000
+++ 43.2-1ubuntu1/debian/control.in	2023-01-13 14:43:39.000000000 +0000
@@ -1,7 +1,8 @@
 Source: gnome-text-editor
 Section: gnome
 Priority: optional
-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
 Uploaders: @GNOME_TEAM@
 Build-Depends: debhelper-compat (= 13),
                appstream-util <!nocheck>,
@@ -16,6 +17,7 @@ Build-Depends: debhelper-compat (= 13),
                libgtk-4-dev (>= 4.7),
                libgtksourceview-5-dev (>= 5.5.0),
                libicu-dev,
+               libpcre3-dev,
                meson (>= 0.59.1)
 Standards-Version: 4.6.1
 Rules-Requires-Root: no
diff -pruN 43.2-1/debian/copyright 43.2-1ubuntu1/debian/copyright
--- 43.2-1/debian/copyright	2023-01-13 14:31:54.000000000 +0000
+++ 43.2-1ubuntu1/debian/copyright	2023-01-13 14:43:39.000000000 +0000
@@ -54,11 +54,124 @@ Files: src/editor-print-operation.*
 Copyright: 2015 Paolo Borelli
 License: GPL-3+
 
+Files: src/editorconfig/libeditorconfig/ec_glob.*
+Copyright: 2014 Hong Xu <hong AT topbug DOT net>
+License: BSD-2-clause
+
+Files: src/editorconfig/libeditorconfig/ini.*
+Copyright: 2009 Brush Technology
+License: BSD-3-clause
+
+Files: src/editorconfig/libeditorconfig/misc.c
+Copyright: 1987, 1993 The Regents of the University of California.
+           1988, 1993 The Regents of the University of California.
+           2011-2012 EditorConfig Team
+License: BSD-4-Clause-UC
+
 Files: src/modelines/modeline-parser.*
 Copyright: 2005-2007 Steve Frécinaux
            2020 Christian Hergert
 License: GPL-2+
 
+Files: src/editorconfig/libeditorconfig/utarray.h
+Copyright: 2008-2014 Troy D. Hanson
+License: BSD-revised
+
+License: BSD-revised
+ 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.
+
+License: BSD-2-clause
+ 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.
+
+License: BSD-3-clause
+ 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.
+
+License: BSD-4-Clause-UC
+ 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. All advertising materials mentioning features or use of this
+    software must display the following acknowledgement: This product
+    includes software developed by the University of California,
+    Berkeley and its contributors.
+ 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.
+
 License: CC0-1.0
  To the extent possible under law, the author(s) have dedicated all copyright
  and related and neighboring rights to this software to the public domain
@@ -104,6 +217,20 @@ License: GPL-3+
  On Debian systems, the complete text of the GNU General
  Public License can be found in `/usr/share/common-licenses/GPL-3'.
 
+License: LGPL-2+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+ .
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+ .
+ On Debian systems, the complete text of the GNU Lesser General Public
+ License version 2 can be found in "/usr/share/common-licenses/LGPL-2".
+
 License: LGPL-2.1+
  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
diff -pruN 43.2-1/debian/patches/Revert-build-switch-to-libeditorconfig.patch 43.2-1ubuntu1/debian/patches/Revert-build-switch-to-libeditorconfig.patch
--- 43.2-1/debian/patches/Revert-build-switch-to-libeditorconfig.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.2-1ubuntu1/debian/patches/Revert-build-switch-to-libeditorconfig.patch	2023-01-13 14:43:39.000000000 +0000
@@ -0,0 +1,2883 @@
+From: Jeremy Bicha <jeremy.bicha@canonical.com>
+Date: Tue, 4 Oct 2022 15:49:18 -0400
+Subject: Revert "build: switch to libeditorconfig"
+
+This reverts commit 6ea5bbae19acdcce45044ad91b7b28f8a7e5870d.
+---
+ meson.build                                        |   1 -
+ src/editorconfig/editorconfig-glib.c               |   2 +-
+ src/editorconfig/libeditorconfig/ec_glob.c         | 371 ++++++++++++++
+ src/editorconfig/libeditorconfig/ec_glob.h         |  43 ++
+ src/editorconfig/libeditorconfig/editorconfig.c    | 547 +++++++++++++++++++++
+ src/editorconfig/libeditorconfig/editorconfig.h    |  37 ++
+ .../libeditorconfig/editorconfig/editorconfig.h    | 309 ++++++++++++
+ .../editorconfig/editorconfig_handle.h             | 193 ++++++++
+ .../libeditorconfig/editorconfig_handle.c          | 155 ++++++
+ .../libeditorconfig/editorconfig_handle.h          |  89 ++++
+ src/editorconfig/libeditorconfig/global.h          |  80 +++
+ src/editorconfig/libeditorconfig/ini.c             | 200 ++++++++
+ src/editorconfig/libeditorconfig/ini.h             |  93 ++++
+ src/editorconfig/libeditorconfig/meson.build       |  41 ++
+ src/editorconfig/libeditorconfig/misc.c            | 250 ++++++++++
+ src/editorconfig/libeditorconfig/misc.h            |  62 +++
+ src/editorconfig/libeditorconfig/utarray.h         | 232 +++++++++
+ src/editorconfig/meson.build                       |   2 +
+ src/meson.build                                    |   3 +-
+ 19 files changed, 2707 insertions(+), 3 deletions(-)
+ create mode 100644 src/editorconfig/libeditorconfig/ec_glob.c
+ create mode 100644 src/editorconfig/libeditorconfig/ec_glob.h
+ create mode 100644 src/editorconfig/libeditorconfig/editorconfig.c
+ create mode 100644 src/editorconfig/libeditorconfig/editorconfig.h
+ create mode 100644 src/editorconfig/libeditorconfig/editorconfig/editorconfig.h
+ create mode 100644 src/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
+ create mode 100644 src/editorconfig/libeditorconfig/editorconfig_handle.c
+ create mode 100644 src/editorconfig/libeditorconfig/editorconfig_handle.h
+ create mode 100644 src/editorconfig/libeditorconfig/global.h
+ create mode 100644 src/editorconfig/libeditorconfig/ini.c
+ create mode 100644 src/editorconfig/libeditorconfig/ini.h
+ create mode 100644 src/editorconfig/libeditorconfig/meson.build
+ create mode 100644 src/editorconfig/libeditorconfig/misc.c
+ create mode 100644 src/editorconfig/libeditorconfig/misc.h
+ create mode 100644 src/editorconfig/libeditorconfig/utarray.h
+
+diff --git a/meson.build b/meson.build
+index 3fdf52e..cf6e050 100644
+--- a/meson.build
++++ b/meson.build
+@@ -44,7 +44,6 @@ libglib_dep = dependency('gio-2.0', version: glib_req)
+ libgtk_dep = dependency('gtk4', version: gtk_req)
+ libgtksourceview_dep = dependency('gtksourceview-5', version: gtksourceview_req)
+ libadwaita_dep = dependency('libadwaita-1', version: '>= 1.2.alpha')
+-libeditorconfig_dep = dependency('editorconfig')
+ 
+ # Specify minimum library versions
+ glib_major = glib_req_version.split('.')[0].to_int()
+diff --git a/src/editorconfig/editorconfig-glib.c b/src/editorconfig/editorconfig-glib.c
+index 18354bf..c12f160 100644
+--- a/src/editorconfig/editorconfig-glib.c
++++ b/src/editorconfig/editorconfig-glib.c
+@@ -22,7 +22,7 @@
+ 
+ #include "config.h"
+ 
+-#include <editorconfig/editorconfig.h>
++#include <editorconfig.h>
+ 
+ #include "editorconfig-glib.h"
+ 
+diff --git a/src/editorconfig/libeditorconfig/ec_glob.c b/src/editorconfig/libeditorconfig/ec_glob.c
+new file mode 100644
+index 0000000..86b57ad
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/ec_glob.c
+@@ -0,0 +1,371 @@
++/*
++ * Copyright 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.
++*/
++
++#include "global.h"
++
++#include <ctype.h>
++#include <string.h>
++#include <pcre.h>
++
++#include "utarray.h"
++#include "misc.h"
++
++#include "ec_glob.h"
++
++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  300
++/*
++ * Whether the string matches the given glob pattern
++ */
++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;
++    const char *              error_msg;
++    int                       erroffset;
++    pcre *                    re;
++    int                       rc;
++    int *                     pcre_result;
++    size_t                    pcre_result_len;
++    char                      l_pattern[2 * PATTERN_MAX];
++    _Bool                     are_brace_paired;
++    UT_array *                nums;     /* number ranges */
++    int                       ret = 0;
++
++    if (pattern == NULL || string == NULL || (strlen (pattern) > PATTERN_MAX))
++      return -1;
++
++    strcpy(l_pattern, pattern);
++    p_pcre = pcre_str + 1;
++    pcre_str_end = pcre_str + 2 * PATTERN_MAX;
++
++    {
++        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;
++            if (*c == '{')
++                ++ left_count;
++        }
++
++        are_brace_paired = (right_count == left_count);
++    }
++
++    /* used to search for {num1..num2} case */
++    re = pcre_compile("^\\{[\\+\\-]?\\d+\\.\\.[\\+\\-]?\\d+\\}$", 0,
++            &error_msg, &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 '?':
++            *(p_pcre ++) = '.';
++            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, ']');
++
++                    strcat(p_pcre, "\\");
++                    strncat(p_pcre, c, right_bracket - c);
++                    strcat(p_pcre, "\\]");
++                    p_pcre += strlen(p_pcre);
++                    c = right_bracket;
++                    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_brace_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;
++                    int                 pcre_res[3];
++
++                    /* Check the case of {num1..num2} */
++                    rc = pcre_exec(re, NULL, c, (int) (cc - c + 1), 0, 0,
++                            pcre_res, 3);
++
++                    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 = atoi(c + 1);
++                    pair.num2 = 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_brace_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 ++) = '$';
++
++    pcre_free(re); /* ^\\d+\\.\\.\\d+$ */
++
++    re = pcre_compile(pcre_str, 0, &error_msg, &erroffset, NULL);
++
++    if (!re)        /* failed to compile */
++    {
++      utarray_free(nums);
++      return -1;
++    }
++
++    pcre_result_len = 3 * (utarray_len(nums) + 1);
++    pcre_result = (int *) calloc(pcre_result_len, sizeof(int_pair));
++    rc = pcre_exec(re, NULL, string, (int) strlen(string), 0, 0,
++            pcre_result, pcre_result_len);
++
++    if (rc < 0)     /* failed to match */
++    {
++        if (rc == PCRE_ERROR_NOMATCH)
++            ret = EC_GLOB_NOMATCH;
++        else
++            ret = rc;
++
++        pcre_free(re);
++        free(pcre_result);
++        utarray_free(nums);
++
++        return ret;
++    }
++
++    /* Whether the numbers are in the desired range? */
++    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);
++        num = 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;
++
++    pcre_free(re);
++    free(pcre_result);
++    utarray_free(nums);
++
++    return ret;
++}
+diff --git a/src/editorconfig/libeditorconfig/ec_glob.h b/src/editorconfig/libeditorconfig/ec_glob.h
+new file mode 100644
+index 0000000..7da19df
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/ec_glob.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright 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.
++*/
++
++#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);
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* !__EC_GLOB_H__ */
+diff --git a/src/editorconfig/libeditorconfig/editorconfig.c b/src/editorconfig/libeditorconfig/editorconfig.c
+new file mode 100644
+index 0000000..5042c20
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/editorconfig.c
+@@ -0,0 +1,547 @@
++/*
++ * Copyright 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 speical 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];
++
++    if (strlen (name) > (MAX_PROPERTY_NAME - 1))
++      return -1;
++
++    /* 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(strcpy(name_lwr, 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 '/' */
++    pattern = (char*)malloc(
++            strlen(hfparam->editorconfig_file_dir) * sizeof(char) +
++            sizeof("**/") + strlen(section) * sizeof(char));
++    if (!pattern)
++        return 0;
++    strcpy(pattern, hfparam->editorconfig_file_dir);
++
++    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.
++ */
++static void 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;
++    }
++
++    if (directory != NULL) {
++        *directory = strndup(absolute_path,
++                (size_t)(path_char - absolute_path));
++    }
++    if (filename != NULL) {
++        *filename = strndup(path_char+1, strlen(path_char)-1);
++    }
++}
++
++/*
++ * 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.
++ */
++static char** get_filenames(const char* path, const char* filename)
++{
++    char* currdir;
++    char* currdir1;
++    char** files;
++    int slashes = count_slashes(path);
++    int i;
++
++    files = (char**) calloc(slashes+1, sizeof(char*));
++
++    currdir = strdup(path);
++    for (i = slashes - 1; i >= 0; --i) {
++        currdir1 = currdir;
++        split_file_path(&currdir, NULL, currdir1);
++        free(currdir1);
++        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;
++}
++
++/*
++ * 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.";
++    default:
++        break;
++    }
++
++    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;
++    int                                 err_num;
++    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);
++
++    /* return an error if file path is not absolute */
++    if (!is_file_path_absolute(full_filename)) {
++        return EDITORCONFIG_PARSE_NOT_FULL_PATH;
++    }
++
++#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);
++    for (config_file = config_files; *config_file != NULL; config_file++) {
++        split_file_path(&hfp.editorconfig_file_dir, NULL, *config_file);
++        if ((err_num = ini_parse(*config_file, ini_handler, &hfp)) != 0 &&
++                /* ignore error caused by I/O, maybe caused by non exist file */
++                err_num != -1) {
++            eh->err_file = strdup(*config_file);
++            free(*config_file);
++            free(hfp.full_filename);
++            free(hfp.editorconfig_file_dir);
++            return err_num;
++        }
++
++        free(hfp.editorconfig_file_dir);
++        free(*config_file);
++    }
++
++    /* 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(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(config_files);
++        return EDITORCONFIG_PARSE_MEMORY_ERROR;
++    }
++
++    free(hfp.full_filename);
++    free(config_files);
++
++    return 0;
++}
++
++/*
++ * See header file
++ */
++EDITORCONFIG_EXPORT
++void editorconfig_get_version(int* major, int* minor, int* patch)
++{
++    if (major)
++        *major = editorconfig_VERSION_MAJOR;
++    if (minor)
++        *minor = editorconfig_VERSION_MINOR;
++    if (patch)
++        *patch = editorconfig_VERSION_PATCH;
++}
++
++/*
++ * See header file
++ */
++EDITORCONFIG_EXPORT
++const char* editorconfig_get_version_suffix(void)
++{
++    return editorconfig_VERSION_SUFFIX;
++}
+diff --git a/src/editorconfig/libeditorconfig/editorconfig.h b/src/editorconfig/libeditorconfig/editorconfig.h
+new file mode 100644
+index 0000000..f0fa957
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/editorconfig.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright 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.
++ */
++
++#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__ */
++
+diff --git a/src/editorconfig/libeditorconfig/editorconfig/editorconfig.h b/src/editorconfig/libeditorconfig/editorconfig/editorconfig.h
+new file mode 100644
+index 0000000..a4ae1ad
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/editorconfig/editorconfig.h
+@@ -0,0 +1,309 @@
++/*
++ * Copyright 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.
++ */
++/*!
++ * @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
++ */
++
++/*!
++ * @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.
++ *
++ * @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>
++ *
++ * Property names are case insensitive and all property names are lowercased when parsing.
++ */
++
++/*!
++ * @file editorconfig/editorconfig.h
++ * @brief Header file of EditorConfig.
++ *
++ * Related page: @ref editorconfig-format
++ *
++ * @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__ */
++
+diff --git a/src/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h b/src/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
+new file mode 100644
+index 0000000..35f4be9
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
+@@ -0,0 +1,193 @@
++/*
++ * Copyright 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.
++ */
++
++/*!
++ * @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__ */
++
+diff --git a/src/editorconfig/libeditorconfig/editorconfig_handle.c b/src/editorconfig/libeditorconfig/editorconfig_handle.c
+new file mode 100644
+index 0000000..e000398
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/editorconfig_handle.c
+@@ -0,0 +1,155 @@
++/*
++ * Copyright 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;
++}
+diff --git a/src/editorconfig/libeditorconfig/editorconfig_handle.h b/src/editorconfig/libeditorconfig/editorconfig_handle.h
+new file mode 100644
+index 0000000..f36f342
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/editorconfig_handle.h
+@@ -0,0 +1,89 @@
++/*
++ * Copyright 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.
++ */
++
++#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__ */
++
+diff --git a/src/editorconfig/libeditorconfig/global.h b/src/editorconfig/libeditorconfig/global.h
+new file mode 100644
+index 0000000..235693f
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/global.h
+@@ -0,0 +1,80 @@
++/*
++ * Copyright 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.
++ */
++
++#ifndef __GLOBAL_H__
++#define __GLOBAL_H__
++
++#ifdef HAVE_CONFIG_H
++# include "config.h"
++#endif
++
++#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__ */
++
+diff --git a/src/editorconfig/libeditorconfig/ini.c b/src/editorconfig/libeditorconfig/ini.c
+new file mode 100644
+index 0000000..08fc0ea
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/ini.c
+@@ -0,0 +1,200 @@
++/* inih -- simple .INI file parser
++
++The "inih" library is distributed under the New BSD license:
++
++Copyright 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 200
++#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 - 1);
++    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] = "";
++    char prev_name[MAX_NAME] = "";
++
++    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';
++                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);
++
++                /* 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;
++}
+diff --git a/src/editorconfig/libeditorconfig/ini.h b/src/editorconfig/libeditorconfig/ini.h
+new file mode 100644
+index 0000000..321da46
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/ini.h
+@@ -0,0 +1,93 @@
++/* inih -- simple .INI file parser
++
++The "inih" library is distributed under the New BSD license:
++
++Copyright 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 500
++#define MAX_PROPERTY_NAME 500
++
++/* 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__ */
+diff --git a/src/editorconfig/libeditorconfig/meson.build b/src/editorconfig/libeditorconfig/meson.build
+new file mode 100644
+index 0000000..108e1eb
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/meson.build
+@@ -0,0 +1,41 @@
++libeditorconfig_sources = [
++  'ec_glob.c',
++  'editorconfig.c',
++  'editorconfig_handle.c',
++  'ini.c',
++  'misc.c',
++]
++
++libeditorconfig_deps = [
++  dependency('libpcre')
++]
++
++# FIXME: Actually test these
++libeditorconfig_args = [
++  '-DHAVE_STRCASECMP',
++  '-DHAVE_STRICMP',
++  '-DHAVE_STRDUP',
++  '-DHAVE_STRNDUP',
++  '-Deditorconfig_VERSION_MAJOR=0',
++  '-Deditorconfig_VERSION_MINOR=0',
++  '-Deditorconfig_VERSION_PATCH=0',
++  '-Deditorconfig_VERSION_SUFFIX=0',
++]
++
++if host_machine.system() == 'windows'
++  libeditorconfig_args += ['-DWIN32']
++else
++  libeditorconfig_args += ['-DUNIX']
++endif
++
++libeditorconfig = static_library('editorconfig',
++  libeditorconfig_sources,
++  dependencies: libeditorconfig_deps,
++        c_args: libeditorconfig_args,
++           pic: true,
++)
++
++libeditorconfig_dep = declare_dependency(
++            link_with: libeditorconfig,
++  include_directories: include_directories('.'),
++)
+diff --git a/src/editorconfig/libeditorconfig/misc.c b/src/editorconfig/libeditorconfig/misc.c
+new file mode 100644
+index 0000000..143d618
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/misc.c
+@@ -0,0 +1,250 @@
++/*
++ * Copyright 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 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 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 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
++}
+diff --git a/src/editorconfig/libeditorconfig/misc.h b/src/editorconfig/libeditorconfig/misc.h
+new file mode 100644
+index 0000000..f735544
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/misc.h
+@@ -0,0 +1,62 @@
++/*
++ * Copyright 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.
++ */
++
++#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__ */
+diff --git a/src/editorconfig/libeditorconfig/utarray.h b/src/editorconfig/libeditorconfig/utarray.h
+new file mode 100644
+index 0000000..e4fdf77
+--- /dev/null
++++ b/src/editorconfig/libeditorconfig/utarray.h
+@@ -0,0 +1,232 @@
++/*
++Copyright 2008-2014, 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 1.9.9
++
++#ifdef __GNUC__
++#define _UNUSED_ __attribute__ ((__unused__)) 
++#else
++#define _UNUSED_ 
++#endif
++
++#include <stddef.h>  /* size_t */
++#include <string.h>  /* memset, etc */
++#include <stdlib.h>  /* exit */
++
++#define oom() exit(-1)
++
++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) {                                                      \
++      size_t _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));                                      \
++  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)) {                                               \
++    while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); }     \
++    if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom();  \
++  }                                                                           \
++} 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) ((char*)((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) {                                                        \
++    size_t _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 {                                          \
++  size_t _ut_i;                                                               \
++  if (dst->i > (size_t)(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 < (size_t)(num)) {                                        \
++    utarray_reserve(dst,num-dst->i);                                          \
++    if ((dst)->icd.init) {                                                    \
++      for(_ut_i=dst->i; _ut_i < 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) {                                                        \
++    size_t _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) {                                                      \
++      size_t _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) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(size_t)(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) free(*eltc);
++}
++static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor};
++static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL};
++static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL};
++
++
++#endif /* UTARRAY_H */
+diff --git a/src/editorconfig/meson.build b/src/editorconfig/meson.build
+index ec4fe2e..4279920 100644
+--- a/src/editorconfig/meson.build
++++ b/src/editorconfig/meson.build
+@@ -1,3 +1,5 @@
++subdir('libeditorconfig')
++
+ editor_deps += [libeditorconfig_dep]
+ 
+ editor_sources += files([
+diff --git a/src/meson.build b/src/meson.build
+index 1294321..10056f4 100644
+--- a/src/meson.build
++++ b/src/meson.build
+@@ -96,7 +96,8 @@ subdir('editorconfig')
+ 
+ editor = executable('gnome-text-editor', editor_sources + editor_enums + [build_ident_h],
+   include_directories: [include_directories('..'),
+-                        include_directories('editorconfig')],
++                        include_directories('editorconfig'),
++                        include_directories('editorconfig/libeditorconfig')],
+                c_args: editor_c_args,
+          dependencies: editor_deps,
+               install: true,
diff -pruN 43.2-1/debian/patches/series 43.2-1ubuntu1/debian/patches/series
--- 43.2-1/debian/patches/series	2023-01-13 14:31:54.000000000 +0000
+++ 43.2-1ubuntu1/debian/patches/series	2023-01-13 14:43:39.000000000 +0000
@@ -0,0 +1 @@
+Revert-build-switch-to-libeditorconfig.patch
