[gnome-builder/wip/libide: 190/237] libide: used editorconfig-core-c implementation
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/libide: 190/237] libide: used editorconfig-core-c implementation
- Date: Tue, 17 Feb 2015 21:45:23 +0000 (UTC)
commit d9490d95e02e3a21a51eec26296366f5826f9f9a
Author: Christian Hergert <christian hergert me>
Date: Sat Feb 14 21:00:49 2015 -0800
libide: used editorconfig-core-c implementation
.gitignore | 2 +
libide/Makefile.am | 8 +-
libide/editorconfig/editorconfig-glib.c | 118 +++++
.../{editorconfig.h => editorconfig-glib.h} | 12 +-
libide/editorconfig/editorconfig.c | 369 -------------
.../editorconfig/ide-editorconfig-file-settings.c | 9 +-
libide/editorconfig/libeditorconfig/Makefile.am | 37 ++
libide/editorconfig/libeditorconfig/ec_glob.c | 367 +++++++++++++
libide/editorconfig/libeditorconfig/ec_glob.h | 43 ++
libide/editorconfig/libeditorconfig/editorconfig.c | 540 ++++++++++++++++++++
libide/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 ++++
libide/editorconfig/libeditorconfig/global.h | 80 +++
libide/editorconfig/libeditorconfig/ini.c | 200 ++++++++
libide/editorconfig/libeditorconfig/ini.h | 93 ++++
libide/editorconfig/libeditorconfig/misc.c | 250 +++++++++
libide/editorconfig/libeditorconfig/misc.h | 62 +++
libide/editorconfig/libeditorconfig/utarray.h | 232 +++++++++
libide/ide-file-settings.h | 2 +-
22 files changed, 2825 insertions(+), 382 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 65c9690..b329854 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
*.deps
+*.gch
*.gz
+*.la
*.libs
*.lo
*.log
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 1bb5f5c..5c942ad 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -1,3 +1,5 @@
+include libide/editorconfig/libeditorconfig/Makefile.am
+
noinst_LTLIBRARIES += libide.la
libide_la_public_sources = \
@@ -134,8 +136,8 @@ libide_la_public_sources = \
libide_la_SOURCES = \
$(libide_la_public_sources) \
- libide/editorconfig/editorconfig.c \
- libide/editorconfig/editorconfig.h \
+ libide/editorconfig/editorconfig-glib.c \
+ libide/editorconfig/editorconfig-glib.h \
libide/gconstructor.h \
libide/ide-async-helper.c \
libide/ide-async-helper.h \
@@ -151,6 +153,7 @@ libide_la_CFLAGS = \
-I$(top_srcdir)/libide/clang \
-I$(top_srcdir)/libide/directory \
-I$(top_srcdir)/libide/editorconfig \
+ -I$(top_srcdir)/libide/editorconfig/libeditorconfig \
-I$(top_srcdir)/libide/git \
-I$(top_srcdir)/libide/gsettings \
-I$(top_srcdir)/libide/local \
@@ -161,6 +164,7 @@ libide_la_LIBADD = \
$(CLANG_LDFLAGS) \
$(LIBIDE_LIBS) \
-lclang \
+ libeditorconfig.la \
$(NULL)
diff --git a/libide/editorconfig/editorconfig-glib.c b/libide/editorconfig/editorconfig-glib.c
new file mode 100644
index 0000000..c30a3c8
--- /dev/null
+++ b/libide/editorconfig/editorconfig-glib.c
@@ -0,0 +1,118 @@
+/* editorconfig-glib.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <editorconfig/editorconfig.h>
+
+#include "editorconfig-glib.h"
+
+static void
+_g_value_free (gpointer data)
+{
+ GValue *value = data;
+
+ g_value_unset (value);
+ g_free (value);
+}
+
+GHashTable *
+editorconfig_glib_read (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ editorconfig_handle handle = { 0 };
+ GHashTable *ret = NULL;
+ gchar *filename = NULL;
+ gint code;
+ gint count;
+ guint i;
+
+ filename = g_file_get_path (file);
+
+ if (!filename)
+ {
+ /*
+ * This sucks, but we need to basically rewrite editorconfig library
+ * to support this. Not out of the question, but it is for today.
+ */
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "only local files are currently supported");
+ return NULL;
+ }
+
+ handle = editorconfig_handle_init ();
+ code = editorconfig_parse (filename, handle);
+
+ switch (code)
+ {
+ case 0:
+ break;
+
+ case EDITORCONFIG_PARSE_NOT_FULL_PATH:
+ case EDITORCONFIG_PARSE_MEMORY_ERROR:
+ case EDITORCONFIG_PARSE_VERSION_TOO_NEW:
+ default:
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Failed to parse editorconfig.");
+ goto cleanup;
+ }
+
+ ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _g_value_free);
+
+ count = editorconfig_handle_get_name_value_count (handle);
+
+ for (i = 0; i < count; i++)
+ {
+ GValue *value;
+ const gchar *key = NULL;
+ const gchar *valuestr = NULL;
+
+ value = g_new0 (GValue, 1);
+
+ editorconfig_handle_get_name_value (handle, i, &key, &valuestr);
+
+ if ((g_strcmp0 (key, "tab_width") == 0) ||
+ (g_strcmp0 (key, "indent_size") == 0))
+ {
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, g_ascii_strtoll (valuestr, NULL, 10));
+ }
+ else if ((g_strcmp0 (key, "insert_final_newline") == 0) ||
+ (g_strcmp0 (key, "trim_trailing_whitespace") == 0))
+ {
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, g_str_equal (valuestr, "true"));
+ }
+ else
+ {
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, valuestr);
+ }
+
+ g_hash_table_replace (ret, g_strdup (key), value);
+ }
+
+cleanup:
+ editorconfig_handle_destroy (handle);
+ g_free (filename);
+
+ return ret;
+}
diff --git a/libide/editorconfig/editorconfig.h b/libide/editorconfig/editorconfig-glib.h
similarity index 63%
rename from libide/editorconfig/editorconfig.h
rename to libide/editorconfig/editorconfig-glib.h
index d3bda86..5f57530 100644
--- a/libide/editorconfig/editorconfig.h
+++ b/libide/editorconfig/editorconfig-glib.h
@@ -8,13 +8,13 @@
* all present and future rights to this code under copyright law.
*/
-#ifndef EDITORCONFIG_H
-#define EDITORCONFIG_H
+#ifndef EDITORCONFIG_GLIB_H
+#define EDITORCONFIG_GLIB_H
#include <gio/gio.h>
-GHashTable *editorconfig_read (GFile *file,
- GCancellable *cancellable,
- GError **error);
+GHashTable *editorconfig_glib_read (GFile *file,
+ GCancellable *cancellable,
+ GError **error);
-#endif /* EDITORCONFIG_H */
+#endif /* EDITORCONFIG_GLIB_H */
diff --git a/libide/editorconfig/ide-editorconfig-file-settings.c
b/libide/editorconfig/ide-editorconfig-file-settings.c
index 0ec4d26..da6883b 100644
--- a/libide/editorconfig/ide-editorconfig-file-settings.c
+++ b/libide/editorconfig/ide-editorconfig-file-settings.c
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <editorconfig.h>
+#include <editorconfig-glib.h>
#include <glib/gi18n.h>
#include "ide-editorconfig-file-settings.h"
@@ -63,7 +63,7 @@ ide_editorconfig_file_settings_init_worker (GTask *task,
g_assert (G_IS_FILE (file));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- ht = editorconfig_read (file, cancellable, &error);
+ ht = editorconfig_glib_read (file, cancellable, &error);
if (!ht)
{
@@ -82,9 +82,10 @@ ide_editorconfig_file_settings_init_worker (GTask *task,
if (g_str_equal (key, "indent_size"))
g_object_set_property (source_object, "indent_width", value);
else if (g_str_equal (key, "tab_width") ||
- g_str_equal (key, "trim_trailing_whitespace") ||
- g_str_equal (key, "insert_final_newline"))
+ g_str_equal (key, "trim_trailing_whitespace"))
g_object_set_property (source_object, key, value);
+ else if (g_str_equal (key, "insert_final_newline"))
+ g_object_set_property (source_object, "insert_trailing_newline", value);
else if (g_str_equal (key, "charset"))
g_object_set_property (source_object, "encoding", value);
else if (g_str_equal (key, "end_of_line"))
diff --git a/libide/editorconfig/libeditorconfig/Makefile.am b/libide/editorconfig/libeditorconfig/Makefile.am
new file mode 100644
index 0000000..79e6133
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/Makefile.am
@@ -0,0 +1,37 @@
+noinst_LTLIBRARIES += libeditorconfig.la
+
+libeditorconfig_la_SOURCES = \
+ libide/editorconfig/libeditorconfig/editorconfig.c \
+ libide/editorconfig/libeditorconfig/misc.c \
+ libide/editorconfig/libeditorconfig/ini.c \
+ libide/editorconfig/libeditorconfig/ec_glob.c \
+ libide/editorconfig/libeditorconfig/editorconfig_handle.c \
+ libide/editorconfig/libeditorconfig/editorconfig_handle.h \
+ libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h \
+ libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h \
+ libide/editorconfig/libeditorconfig/global.h \
+ libide/editorconfig/libeditorconfig/ec_glob.h \
+ libide/editorconfig/libeditorconfig/utarray.h \
+ libide/editorconfig/libeditorconfig/editorconfig.h \
+ libide/editorconfig/libeditorconfig/misc.h \
+ libide/editorconfig/libeditorconfig/ini.h \
+ $(NULL)
+
+libeditorconfig_la_LIBADD = \
+ -lpcre \
+ $(NULL)
+
+libeditorconfig_la_CFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/libide/editorconfig/libeditorconfig \
+ -D_GNU_SOURCE \
+ -DHAVE_STRCASECMP \
+ -DHAVE_STRICMP \
+ -DHAVE_STRDUP \
+ -DHAVE_STRNDUP \
+ -DUNIX \
+ -Deditorconfig_VERSION_MAJOR=0 \
+ -Deditorconfig_VERSION_MINOR=0 \
+ -Deditorconfig_VERSION_PATCH=0 \
+ -Deditorconfig_VERSION_SUFFIX=0 \
+ $(NULL)
diff --git a/libide/editorconfig/libeditorconfig/ec_glob.c b/libide/editorconfig/libeditorconfig/ec_glob.c
new file mode 100644
index 0000000..8fd4f32
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ec_glob.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2014 Hong Xu <hong AT topbug DOT net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#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];
+ int pattern_length = strlen(pattern);
+ _Bool are_brace_paired;
+ UT_array * nums; /* number ranges */
+ int ret = 0;
+
+ strcpy(l_pattern, pattern);
+ p_pcre = pcre_str + 1;
+ pcre_str_end = pcre_str + 2 * PATTERN_MAX;
+
+ {
+ 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 */
+ 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 */
+ {
+ int ret;
+ 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/libide/editorconfig/libeditorconfig/ec_glob.h b/libide/editorconfig/libeditorconfig/ec_glob.h
new file mode 100644
index 0000000..d83d7ab
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ec_glob.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Hong Xu <hong AT topbug DOT net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#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/libide/editorconfig/libeditorconfig/editorconfig.c
b/libide/editorconfig/libeditorconfig/editorconfig.c
new file mode 100644
index 0000000..9b5d91e
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "global.h"
+#include "editorconfig.h"
+#include "misc.h"
+#include "ini.h"
+#include "ec_glob.h"
+
+/* could be used to fast locate these properties in an
+ * array_editorconfig_name_value */
+typedef struct
+{
+ const editorconfig_name_value* indent_style;
+ const editorconfig_name_value* indent_size;
+ const editorconfig_name_value* tab_width;
+} special_property_name_value_pointers;
+
+typedef struct
+{
+ editorconfig_name_value* name_values;
+ int current_value_count;
+ int max_value_count;
+ special_property_name_value_pointers spnvp;
+} array_editorconfig_name_value;
+
+typedef struct
+{
+ char* full_filename;
+ char* editorconfig_file_dir;
+ array_editorconfig_name_value array_name_value;
+} handler_first_param;
+
+/*
+ * Set the special pointers for a name
+ */
+static void set_special_property_name_value_pointers(
+ const editorconfig_name_value* nv,
+ special_property_name_value_pointers* spnvp)
+{
+ /* set speical pointers */
+ if (!strcmp(nv->name, "indent_style"))
+ spnvp->indent_style = nv;
+ else if (!strcmp(nv->name, "indent_size"))
+ spnvp->indent_size = nv;
+ else if (!strcmp(nv->name, "tab_width"))
+ spnvp->tab_width = nv;
+}
+
+/*
+ * Set the name and value of a editorconfig_name_value structure
+ */
+static void set_name_value(editorconfig_name_value* nv, const char* name,
+ const char* value, special_property_name_value_pointers* spnvp)
+{
+ if (name)
+ nv->name = strdup(name);
+ if (value)
+ nv->value = strdup(value);
+ /* lowercase the value when the name is one of the following */
+ if (!strcmp(nv->name, "end_of_line") ||
+ !strcmp(nv->name, "indent_style") ||
+ !strcmp(nv->name, "indent_size") ||
+ !strcmp(nv->name, "insert_final_newline") ||
+ !strcmp(nv->name, "trim_trailing_whitespace") ||
+ !strcmp(nv->name, "charset"))
+ strlwr(nv->value);
+
+ /* set 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];
+ /* 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.";
+ }
+
+ 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);
+ 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/libide/editorconfig/libeditorconfig/editorconfig.h
b/libide/editorconfig/libeditorconfig/editorconfig.h
new file mode 100644
index 0000000..79076c3
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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/libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h
b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h
new file mode 100644
index 0000000..25b3a86
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2011-2013 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*!
+ * @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/libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
new file mode 100644
index 0000000..bd8ee43
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*!
+ * @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/libide/editorconfig/libeditorconfig/editorconfig_handle.c
b/libide/editorconfig/libeditorconfig/editorconfig_handle.c
new file mode 100644
index 0000000..76ea7eb
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig_handle.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "editorconfig_handle.h"
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+editorconfig_handle editorconfig_handle_init(void)
+{
+ editorconfig_handle h;
+
+ h = (editorconfig_handle)malloc(sizeof(struct editorconfig_handle));
+
+ if (!h)
+ return (editorconfig_handle)NULL;
+
+ memset(h, 0, sizeof(struct editorconfig_handle));
+
+ return h;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+int editorconfig_handle_destroy(editorconfig_handle h)
+{
+ int i;
+ struct editorconfig_handle* eh = (struct editorconfig_handle*)h;
+
+
+ if (h == NULL)
+ return 0;
+
+ /* free name_values */
+ for (i = 0; i < eh->name_value_count; ++i) {
+ free(eh->name_values[i].name);
+ free(eh->name_values[i].value);
+ }
+ free(eh->name_values);
+
+ /* free err_file */
+ if (eh->err_file)
+ free(eh->err_file);
+
+ /* free eh itself */
+ free(eh);
+
+ return 0;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_handle_get_err_file(const editorconfig_handle h)
+{
+ return ((const struct editorconfig_handle*)h)->err_file;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_get_version(const editorconfig_handle h, int* major,
+ int* minor, int* patch)
+{
+ if (major)
+ *major = ((const struct editorconfig_handle*)h)->ver.major;
+ if (minor)
+ *minor = ((const struct editorconfig_handle*)h)->ver.minor;
+ if (patch)
+ *patch = ((const struct editorconfig_handle*)h)->ver.patch;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_set_version(editorconfig_handle h, int major,
+ int minor, int patch)
+{
+ if (major >= 0)
+ ((struct editorconfig_handle*)h)->ver.major = major;
+
+ if (minor >= 0)
+ ((struct editorconfig_handle*)h)->ver.minor = minor;
+
+ if (patch >= 0)
+ ((struct editorconfig_handle*)h)->ver.patch = minor;
+}
+
+/*
+ * 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/libide/editorconfig/libeditorconfig/editorconfig_handle.h
b/libide/editorconfig/libeditorconfig/editorconfig_handle.h
new file mode 100644
index 0000000..812fc55
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig_handle.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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/libide/editorconfig/libeditorconfig/global.h b/libide/editorconfig/libeditorconfig/global.h
new file mode 100644
index 0000000..56ab59d
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/global.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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/libide/editorconfig/libeditorconfig/ini.c b/libide/editorconfig/libeditorconfig/ini.c
new file mode 100644
index 0000000..bf0517d
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ini.c
@@ -0,0 +1,200 @@
+/* inih -- simple .INI file parser
+
+The "inih" library is distributed under the New BSD license:
+
+Copyright (c) 2009, Brush Technology
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Brush Technology nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Go to the project home page for more info:
+http://code.google.com/p/inih/
+
+*/
+
+#include "global.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "ini.h"
+
+#define MAX_LINE 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);
+ 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/libide/editorconfig/libeditorconfig/ini.h b/libide/editorconfig/libeditorconfig/ini.h
new file mode 100644
index 0000000..053db05
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ini.h
@@ -0,0 +1,93 @@
+/* inih -- simple .INI file parser
+
+The "inih" library is distributed under the New BSD license:
+
+Copyright (c) 2009, Brush Technology
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Brush Technology nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Go to the project home page for more info:
+http://code.google.com/p/inih/
+
+*/
+
+#ifndef __INI_H__
+#define __INI_H__
+
+#include "global.h"
+
+/* Make this header file easier to include in C++ code */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+/* Parse given INI-style file. May have [section]s, name=value pairs
+ (whitespace stripped), and comments starting with ';' (semicolon). Section
+ is "" if name=value pair parsed before any section heading. name:value
+ pairs are also supported as a concession to Python's ConfigParser.
+
+ For each name=value pair parsed, call handler function with given user
+ pointer as well as section, name, and value (data only valid for duration
+ of handler call). Handler should return nonzero on success, zero on error.
+
+ Returns 0 on success, line number of first error on parse error (doesn't
+ stop on first error), or -1 on file open error.
+*/
+EDITORCONFIG_LOCAL
+int ini_parse(const char* filename,
+ int (*handler)(void* user, const char* section,
+ const char* name, const char* value),
+ void* user);
+
+/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
+ close the file when it's finished -- the caller must do that. */
+EDITORCONFIG_LOCAL
+int ini_parse_file(FILE* file,
+ int (*handler)(void* user, const char* section,
+ const char* name, const char* value),
+ void* user);
+
+/* Nonzero to allow multi-line value parsing, in the style of Python's
+ ConfigParser. If allowed, ini_parse() will call the handler with the same
+ name for each subsequent line parsed. */
+#ifndef INI_ALLOW_MULTILINE
+#define INI_ALLOW_MULTILINE 0
+#endif
+
+#define MAX_SECTION_NAME 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/libide/editorconfig/libeditorconfig/misc.c b/libide/editorconfig/libeditorconfig/misc.c
new file mode 100644
index 0000000..f02e3d6
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/misc.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "misc.h"
+
+#ifdef WIN32
+# include <Shlwapi.h>
+#endif
+
+#if !defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)
+/*
+ * strcasecmp function from FreeBSD
+ *
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+typedef unsigned char u_char;
+
+EDITORCONFIG_LOCAL
+int ec_strcasecmp(const char *s1, const char *s2)
+{
+ const unsigned char
+ *us1 = (const unsigned char*)s1,
+ *us2 = (const unsigned char*)s2;
+
+ while (tolower(*us1) == tolower(*us2++))
+ if (*us1++ == '\0')
+ return (0);
+ return (tolower(*us1) - tolower(*--us2));
+}
+#endif /* !HAVE_STRCASECMP && !HAVE_STRICMP */
+
+#ifndef HAVE_STRDUP
+/*
+ * strdup function from FreeBSD
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+EDITORCONFIG_LOCAL
+char* ec_strdup(const char *str)
+{
+ size_t len;
+ char* copy;
+
+ len = strlen(str) + 1;
+ if ((copy = malloc(len)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ return (copy);
+}
+
+#endif /* !HAVE_STRDUP */
+
+
+#ifndef HAVE_STRNDUP
+/*
+ * strndup function from NetBSD
+ *
+ * $NetBSD: strndup.c,v 1.3 2007/01/14 23:41:24 cbiere Exp $
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "global.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+EDITORCONFIG_LOCAL
+char* ec_strndup(const char* str, size_t n)
+{
+ size_t len;
+ char* copy;
+
+ for (len = 0; len < n && str[len]; len++)
+ continue;
+
+ if ((copy = malloc(len + 1)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ copy[len] = '\0';
+ return (copy);
+}
+
+#endif /* HAVE_STRNDUP */
+
+/*
+ * replace oldc with newc in the string str
+ */
+EDITORCONFIG_LOCAL
+char* str_replace(char* str, char oldc, char newc)
+{
+ char* p;
+
+ if (str == NULL)
+ return NULL;
+
+ for (p = str; *p != '\0'; p++)
+ if (*p == oldc)
+ *p = newc;
+
+ return str;
+}
+
+#ifndef HAVE_STRLWR
+
+#include <ctype.h>
+/*
+ * convert the string to lowercase
+ */
+EDITORCONFIG_LOCAL
+char* ec_strlwr(char* str)
+{
+ char* p;
+
+ for (p = str; *p; ++p)
+ *p = (char)tolower((unsigned char)*p);
+
+ return str;
+}
+
+#endif /* !HAVE_STRLWR */
+
+/*
+ * is path an abosolute file path
+ */
+EDITORCONFIG_LOCAL
+_Bool is_file_path_absolute(const char* path)
+{
+ if (!path)
+ return 0;
+
+#if defined(UNIX)
+ if (*path == '/')
+ return 1;
+ return 0;
+#elif defined(WIN32)
+ return !PathIsRelative(path);
+#else
+# error "Either UNIX or WIN32 must be defined."
+#endif
+}
diff --git a/libide/editorconfig/libeditorconfig/misc.h b/libide/editorconfig/libeditorconfig/misc.h
new file mode 100644
index 0000000..5e4b463
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/misc.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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/libide/editorconfig/libeditorconfig/utarray.h b/libide/editorconfig/libeditorconfig/utarray.h
new file mode 100644
index 0000000..dcddd72
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/utarray.h
@@ -0,0 +1,232 @@
+/*
+Copyright (c) 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/libide/ide-file-settings.h b/libide/ide-file-settings.h
index 59a7c1d..4aa608a 100644
--- a/libide/ide-file-settings.h
+++ b/libide/ide-file-settings.h
@@ -56,7 +56,7 @@ void ide_file_settings_set_insert_trailing_newline (IdeFileSet
gboolean
insert_trailing_newline);
void ide_file_settings_set_newline_type (IdeFileSettings *self,
GtkSourceNewlineType newline_type);
-void ide_file_settings_set_right_margin_position (IdeFileSettings *self,
+void ide_file_settings_set_right_margin_position (IdeFileSettings *self,
guint
right_margin_position);
void ide_file_settings_set_tab_width (IdeFileSettings *self,
guint tab_width);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]