diff --git a/Units/parser-cmake.r/cmake-comments.d/expected.tags b/Units/parser-cmake.r/cmake-comments.d/expected.tags
new file mode 100644
index 0000000000..98726ff297
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-comments.d/expected.tags
@@ -0,0 +1,3 @@
+another_good_target input.cmake /^add_library(another_good_target# <-- target$/;" t
+good_target input.cmake /^ good_target# this is legal comment placement set(NO_TAG foo)$/;" t
+tag_this input.cmake /^]]set(tag_this)$/;" v
diff --git a/Units/parser-cmake.r/cmake-comments.d/input.cmake b/Units/parser-cmake.r/cmake-comments.d/input.cmake
new file mode 100644
index 0000000000..e10a1642c1
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-comments.d/input.cmake
@@ -0,0 +1,17 @@
+# this is a test of comments set(DO_NOT_TAG "foo")
+
+#[[
+multi-linecomments
+option(DO_NOT_TAG "foo" OFF)
+] not the end
+]]set(tag_this)
+
+add_custom_target(# comment set(NO_TAG "foo")
+ # anothe rline comment
+ good_target# this is legal comment placement set(NO_TAG foo)
+ ALL)
+
+add_library(another_good_target# <-- target
+ SHARED # set(NO_TAG bar)
+ gmock-all.cc
+ )
diff --git a/Units/parser-cmake.r/cmake-function.d/expected.tags b/Units/parser-cmake.r/cmake-function.d/expected.tags
new file mode 100644
index 0000000000..2fc7474cab
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-function.d/expected.tags
@@ -0,0 +1,5 @@
+Bfunctiontag_this_2 input.cmake /^ function( Bfunctiontag_this_2 ${BAR})$/;" f
+cxx_shared_library input.cmake /^function(cxx_shared_library name cxx_flags)$/;" f
+d_ALSO_Tag_this input.cmake /^ d_ALSO_Tag_this$/;" f
+eLastlyTagThis_ input.cmake /^eLastlyTagThis_ "hello")$/;" f
+tag_this1 input.cmake /^function(tag_this1)$/;" f
diff --git a/Units/parser-cmake.r/cmake-function.d/input.cmake b/Units/parser-cmake.r/cmake-function.d/input.cmake
new file mode 100644
index 0000000000..902d0602b5
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-function.d/input.cmake
@@ -0,0 +1,19 @@
+function(tag_this1)
+endfunction(tag_this1)
+ function( Bfunctiontag_this_2 ${BAR})
+
+function(cxx_shared_library name cxx_flags)
+ cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
+endfunction()
+
+ FUNCTION (
+ d_ALSO_Tag_this
+ true)
+
+Function(
+eLastlyTagThis_ "hello")
+
+function(${not_this} foo)
+function(not-this foo)
+function(not.this foo)
+function(1notthis foo)
diff --git a/Units/parser-cmake.r/cmake-macro.d/expected.tags b/Units/parser-cmake.r/cmake-macro.d/expected.tags
new file mode 100644
index 0000000000..36f38b98d8
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-macro.d/expected.tags
@@ -0,0 +1,5 @@
+Bmacrotag_this_2 input.cmake /^ macro( Bmacrotag_this_2 ${BAR})$/;" m
+cxx_shared_library input.cmake /^macro(cxx_shared_library name cxx_flags)$/;" m
+d_ALSO_Tag_this input.cmake /^ d_ALSO_Tag_this$/;" m
+eLastlyTagThis_ input.cmake /^eLastlyTagThis_ "hello")$/;" m
+tag_this1 input.cmake /^macro(tag_this1)$/;" m
diff --git a/Units/parser-cmake.r/cmake-macro.d/input.cmake b/Units/parser-cmake.r/cmake-macro.d/input.cmake
new file mode 100644
index 0000000000..692b985d19
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-macro.d/input.cmake
@@ -0,0 +1,19 @@
+macro(tag_this1)
+endmacro(tag_this1)
+ macro( Bmacrotag_this_2 ${BAR})
+
+macro(cxx_shared_library name cxx_flags)
+ cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
+endmacro()
+
+ MACRO (
+ d_ALSO_Tag_this
+ true)
+
+Macro(
+eLastlyTagThis_ "hello")
+
+macro(${not_this} foo)
+macro(not-this foo)
+macro(not.this foo)
+macro(1not_this foo)
diff --git a/Units/parser-cmake.r/cmake-option.d/expected.tags b/Units/parser-cmake.r/cmake-option.d/expected.tags
new file mode 100644
index 0000000000..12c8d643b9
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-option.d/expected.tags
@@ -0,0 +1,5 @@
+1_tag_this input.cmake /^option(1_tag_this foo)$/;" D
+B-option-tag_this_2 input.cmake /^option(B-option-tag_this_2 ${BAR})$/;" D
+c_TAG_THIS input.cmake /^ option ( c_TAG_THIS but_not_this)$/;" D
+d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" D
+e.LastlyTagThis input.cmake /^e.LastlyTagThis "hello")$/;" D
diff --git a/Units/parser-cmake.r/cmake-option.d/input.cmake b/Units/parser-cmake.r/cmake-option.d/input.cmake
new file mode 100644
index 0000000000..c7f2fa9b8b
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-option.d/input.cmake
@@ -0,0 +1,15 @@
+option(1_tag_this foo)
+option(B-option-tag_this_2 ${BAR})
+
+ option ( c_TAG_THIS but_not_this)
+
+ OPTION (
+ d-ALSO-Tag.this
+ true)
+
+Option(
+e.LastlyTagThis "hello")
+
+option(${not_this} foo)
+option(${ not_this } foo)
+option(not~this foo)
diff --git a/Units/parser-cmake.r/cmake-project.d/expected.tags b/Units/parser-cmake.r/cmake-project.d/expected.tags
new file mode 100644
index 0000000000..2f696efce4
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-project.d/expected.tags
@@ -0,0 +1,5 @@
+1_tag_this input.cmake /^project(1_tag_this)$/;" p
+B-project-tag_this_2 input.cmake /^project(B-project-tag_this_2 ${BAR})$/;" p
+c_TAG_THIS input.cmake /^ project ( c_TAG_THIS but_not_this)$/;" p
+d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" p
+e.LastlyTagThis input.cmake /^e.LastlyTagThis "hello")$/;" p
diff --git a/Units/parser-cmake.r/cmake-project.d/input.cmake b/Units/parser-cmake.r/cmake-project.d/input.cmake
new file mode 100644
index 0000000000..88407ff688
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-project.d/input.cmake
@@ -0,0 +1,15 @@
+project(1_tag_this)
+project(B-project-tag_this_2 ${BAR})
+
+ project ( c_TAG_THIS but_not_this)
+
+ PROJECT (
+ d-ALSO-Tag.this
+ )
+
+Project(
+e.LastlyTagThis "hello")
+
+project(${not_this})
+project(${ not_this })
+project(not/this)
diff --git a/Units/parser-cmake.r/cmake-simple.d/expected.tags b/Units/parser-cmake.r/cmake-simple.d/expected.tags
new file mode 100644
index 0000000000..a463ac6f14
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-simple.d/expected.tags
@@ -0,0 +1,6 @@
+BUILD_GMOCK input.cmake /^option(BUILD_GMOCK "Builds the googlemock subproject" ON)$/;" D
+BUILD_GTEST input.cmake /^option(BUILD_GTEST "Builds the googletest subproject" OFF)$/;" D
+CMAKE_INSTALL_BINDIR input.cmake /^ set(CMAKE_INSTALL_BINDIR "bin" CACHE STRING "User executables (bin)")$/;" v
+CMAKE_INSTALL_INCLUDEDIR input.cmake /^ set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "C header files (include)")$/;" v
+CMAKE_INSTALL_LIBDIR input.cmake /^ set(CMAKE_INSTALL_LIBDIR "lib${LIB_SUFFIX}" CACHE STRING "Object code libraries (lib)")$/;" v
+googletest-distribution input.cmake /^project( googletest-distribution )$/;" p
diff --git a/Units/parser-cmake.r/cmake-simple.d/input.cmake b/Units/parser-cmake.r/cmake-simple.d/input.cmake
new file mode 100644
index 0000000000..5e231141dd
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-simple.d/input.cmake
@@ -0,0 +1,34 @@
+# taken from https://github.com/google/googletest/blob/master/CMakeLists.txt
+cmake_minimum_required(VERSION 2.6.4)
+
+if (POLICY CMP0048)
+ cmake_policy(SET CMP0048 NEW)
+endif (POLICY CMP0048)
+
+project( googletest-distribution )
+
+enable_testing()
+
+include(CMakeDependentOption)
+if (CMAKE_VERSION VERSION_LESS 2.8.5)
+ set(CMAKE_INSTALL_BINDIR "bin" CACHE STRING "User executables (bin)")
+ set(CMAKE_INSTALL_LIBDIR "lib${LIB_SUFFIX}" CACHE STRING "Object code libraries (lib)")
+ set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "C header files (include)")
+ mark_as_advanced(CMAKE_INSTALL_BINDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR)
+else()
+ include(GNUInstallDirs)
+endif()
+
+option(BUILD_GTEST "Builds the googletest subproject" OFF)
+
+#Note that googlemock target already builds googletest
+option(BUILD_GMOCK "Builds the googlemock subproject" ON)
+
+cmake_dependent_option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON "BUILD_GTEST OR BUILD_GMOCK" OFF)
+cmake_dependent_option(INSTALL_GMOCK "Enable installation of googlemock. (Projects embedding googlemock may want to turn this OFF.)" ON "BUILD_GMOCK" OFF)
+
+if(BUILD_GMOCK)
+ add_subdirectory( googlemock )
+elseif(BUILD_GTEST)
+ add_subdirectory( googletest )
+endif()
diff --git a/Units/parser-cmake.r/cmake-target.d/expected.tags b/Units/parser-cmake.r/cmake-target.d/expected.tags
new file mode 100644
index 0000000000..5e58d31811
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-target.d/expected.tags
@@ -0,0 +1,15 @@
+1_tag_this input.cmake /^add_custom_target(1_tag_this)$/;" t
+1_tag_this input.cmake /^add_executable(1_tag_this)$/;" t
+1_tag_this input.cmake /^add_library(1_tag_this)$/;" t
+B-add_custom_target-tag_this_2 input.cmake /^add_custom_target(B-add_custom_target-tag_this_2 ${BAR})$/;" t
+B-add_executable-tag_this_2 input.cmake /^add_executable(B-add_executable-tag_this_2 ${BAR})$/;" t
+B-add_library-tag_this_2 input.cmake /^add_library(B-add_library-tag_this_2 ${BAR})$/;" t
+c_TAG_THIS input.cmake /^ add_custom_target ( c_TAG_THIS but_not_this)$/;" t
+c_TAG_THIS input.cmake /^ add_executable ( c_TAG_THIS but_not_this)$/;" t
+c_TAG_THIS input.cmake /^ add_library ( c_TAG_THIS but_not_this)$/;" t
+d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" t
+d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this $/;" t
+d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" t
+e.LastlyTagThis input.cmake /^e.LastlyTagThis "CustomTarget")$/;" t
+e.LastlyTagThis input.cmake /^e.LastlyTagThis "Executable")$/;" t
+e.LastlyTagThis input.cmake /^e.LastlyTagThis "Library")$/;" t
diff --git a/Units/parser-cmake.r/cmake-target.d/input.cmake b/Units/parser-cmake.r/cmake-target.d/input.cmake
new file mode 100644
index 0000000000..32e27e326d
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-target.d/input.cmake
@@ -0,0 +1,49 @@
+add_custom_target(1_tag_this)
+add_custom_target(B-add_custom_target-tag_this_2 ${BAR})
+
+ add_custom_target ( c_TAG_THIS but_not_this)
+
+ ADD_CUSTOM_TARGET (
+ d-ALSO-Tag.this
+ )
+
+Add_Custom_target(
+e.LastlyTagThis "CustomTarget")
+
+add_custom_target(${not_this})
+add_custom_target(${ not_this })
+add_custom_target(not/this)
+
+
+add_executable(1_tag_this)
+add_executable(B-add_executable-tag_this_2 ${BAR})
+
+ add_executable ( c_TAG_THIS but_not_this)
+
+ ADD_EXECUTABLE (
+ d-ALSO-Tag.this
+ )
+
+Add_Executable(
+e.LastlyTagThis "Executable")
+
+add_executable(${not_this})
+add_executable(${ not_this })
+add_executable(not/this)
+
+
+add_library(1_tag_this)
+add_library(B-add_library-tag_this_2 ${BAR})
+
+ add_library ( c_TAG_THIS but_not_this)
+
+ ADD_LIBRARY (
+ d-ALSO-Tag.this
+ )
+
+Add_Library(
+e.LastlyTagThis "Library")
+
+add_library(${not_this})
+add_library(${ not_this })
+add_library(not/this)
diff --git a/Units/parser-cmake.r/cmake-variable.d/expected.tags b/Units/parser-cmake.r/cmake-variable.d/expected.tags
new file mode 100644
index 0000000000..ed82fa930c
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-variable.d/expected.tags
@@ -0,0 +1,5 @@
+1_tag_this input.cmake /^set(1_tag_this foo)$/;" v
+B-set-tag_this_2 input.cmake /^set(B-set-tag_this_2 ${BAR})$/;" v
+c_TAG_THIS input.cmake /^ set ( c_TAG_THIS but_not_this)$/;" v
+d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" v
+e.LastlyTagThis input.cmake /^e.LastlyTagThis "hello")$/;" v
diff --git a/Units/parser-cmake.r/cmake-variable.d/input.cmake b/Units/parser-cmake.r/cmake-variable.d/input.cmake
new file mode 100644
index 0000000000..950566187a
--- /dev/null
+++ b/Units/parser-cmake.r/cmake-variable.d/input.cmake
@@ -0,0 +1,13 @@
+set(1_tag_this foo)
+set(B-set-tag_this_2 ${BAR})
+
+ set ( c_TAG_THIS but_not_this)
+
+ SET (
+ d-ALSO-Tag.this
+ true)
+
+Set(
+e.LastlyTagThis "hello")
+
+set(${not_this} foo)
diff --git a/docs/news.rst b/docs/news.rst
index 91a8f493a4..ef770a2c75 100644
--- a/docs/news.rst
+++ b/docs/news.rst
@@ -42,6 +42,7 @@ The following parsers have been added:
* Automake
* AutoIt
* Clojure
+* CMake *optlib*
* CSS
* Ctags option library *optlib*
* CUDA
diff --git a/main/parsers.h b/main/parsers.h
index 4fc8ffbcea..49664eca54 100644
--- a/main/parsers.h
+++ b/main/parsers.h
@@ -47,6 +47,7 @@
BasicParser, \
BetaParser, \
ClojureParser, \
+ CMakeParser, \
CParser, \
CppParser, \
CPreProParser, \
diff --git a/makefiles/translator_input.mak b/makefiles/translator_input.mak
index 757f989222..3ca00217ca 100644
--- a/makefiles/translator_input.mak
+++ b/makefiles/translator_input.mak
@@ -1,8 +1,9 @@
# -*- makefile -*-
TRANSLATOR_INPUT = \
- optlib/RSpec.ctags \
+ optlib/RSpec.ctags \
+ optlib/cmake.ctags \
optlib/ctags-optlib.ctags \
- optlib/elm.ctags \
+ optlib/elm.ctags \
optlib/gdbinit.ctags \
optlib/man.ctags \
optlib/markdown.ctags \
diff --git a/optlib/cmake.c b/optlib/cmake.c
new file mode 100644
index 0000000000..b6b553dfee
--- /dev/null
+++ b/optlib/cmake.c
@@ -0,0 +1,203 @@
+/*
+ * Generated by ./misc/optlib2c from optlib/cmake.ctags, Don't edit this manually.
+ */
+#include "general.h"
+#include "parse.h"
+#include "routines.h"
+
+
+static void initializeCMakeParser (const langType language CTAGS_ATTR_UNUSED)
+{
+
+ addLanguageRegexTable (language, "main");
+ addLanguageRegexTable (language, "variable");
+ addLanguageRegexTable (language, "function");
+ addLanguageRegexTable (language, "macro");
+ addLanguageRegexTable (language, "target");
+ addLanguageRegexTable (language, "option");
+ addLanguageRegexTable (language, "project");
+ addLanguageRegexTable (language, "commentBegin");
+ addLanguageRegexTable (language, "commentMultiline");
+ addLanguageRegexTable (language, "skipComment");
+ addLanguageRegexTable (language, "skipWhiteSpace");
+ addLanguageRegexTable (language, "skipToName");
+ addLanguageRegexTable (language, "nextToken");
+
+ addLanguageTagMultiTableRegex (language, "main",
+ "^[^sSfFmMaAoOpP# \t\n][^ #\t\n]*[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^set[ \t]*\\(",
+ "", "", "{icase}{tenter=variable}", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^function[ \t]*\\(",
+ "", "", "{icase}{tenter=function}", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^macro[ \t]*\\(",
+ "", "", "{icase}{tenter=macro}", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^add_(custom_target|executable|library)[ \t]*\\(",
+ "", "", "{icase}{tenter=target}", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^option[ \t]*\\(",
+ "", "", "{icase}{tenter=option}", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^project[ \t]*\\(",
+ "", "", "{icase}{tenter=project}", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^[^ \t\n]+[ \t\n]*",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "main",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "variable",
+ "^([A-Za-z0-9_.-]+)[ \t\n\\)]+",
+ "\\1", "v", "{tleave}", NULL);
+ addLanguageTagMultiTableRegex (language, "variable",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "variable",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "variable",
+ "^([A-Za-z0-9_.-]+)(#)",
+ "\\1", "v", "{tleave}{_advanceTo=2start}", NULL);
+ addLanguageTagMultiTableRegex (language, "function",
+ "^([A-Za-z_][A-Za-z0-9_]*)[ \t\n\\)]+",
+ "\\1", "f", "{tleave}", NULL);
+ addLanguageTagMultiTableRegex (language, "function",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "function",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "function",
+ "^([A-Za-z_][A-Za-z0-9_]*)(#)",
+ "\\1", "f", "{tleave}{_advanceTo=2start}", NULL);
+ addLanguageTagMultiTableRegex (language, "macro",
+ "^([A-Za-z_][A-Za-z0-9_]*)[ \t\n\\)]+",
+ "\\1", "m", "{tleave}", NULL);
+ addLanguageTagMultiTableRegex (language, "macro",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "macro",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "macro",
+ "^([A-Za-z_][A-Za-z0-9_]*)(#)",
+ "\\1", "m", "{tleave}{_advanceTo=2start}", NULL);
+ addLanguageTagMultiTableRegex (language, "target",
+ "^([A-Za-z0-9_.-]+)[ \t\n\\)]+",
+ "\\1", "t", "{tleave}", NULL);
+ addLanguageTagMultiTableRegex (language, "target",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "target",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "target",
+ "^([A-Za-z0-9_.-]+)(#)",
+ "\\1", "t", "{tleave}{_advanceTo=2start}", NULL);
+ addLanguageTagMultiTableRegex (language, "option",
+ "^([A-Za-z0-9_.-]+)[ \t\n\\)]+",
+ "\\1", "D", "{tleave}", NULL);
+ addLanguageTagMultiTableRegex (language, "option",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "option",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "option",
+ "^([A-Za-z0-9_.-]+)(#)",
+ "\\1", "D", "{tleave}{_advanceTo=2start}", NULL);
+ addLanguageTagMultiTableRegex (language, "project",
+ "^([A-Za-z0-9_.-]+)([# \t\n\\)])",
+ "\\1", "p", "{tleave}{_advanceTo=2start}", NULL);
+ addLanguageTagMultiTableRegex (language, "project",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "project",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "commentBegin",
+ "^\\[\\[",
+ "", "", "{tjump=commentMultiline}", NULL);
+ addLanguageTagMultiTableRegex (language, "commentBegin",
+ "^[^\n]*[ \t\n]*",
+ "", "", "{tleave}", NULL);
+ addLanguageTagMultiTableRegex (language, "commentMultiline",
+ "^\\]\\][ \t\n]*",
+ "", "", "{tleave}", NULL);
+ addLanguageTagMultiTableRegex (language, "commentMultiline",
+ "^.[^]]*",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "skipComment",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "skipWhiteSpace",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "skipToName",
+ "^[ \t\n]+",
+ "", "", "", NULL);
+ addLanguageTagMultiTableRegex (language, "skipToName",
+ "^#",
+ "", "", "{tenter=commentBegin}", NULL);
+ addLanguageTagMultiTableRegex (language, "nextToken",
+ "^[^ \t\n]+[ \t\n]*",
+ "", "", "", NULL);
+}
+
+extern parserDefinition* CMakeParser (void)
+{
+ static const char *const extensions [] = {
+ "cmake",
+ NULL
+ };
+
+ static const char *const aliases [] = {
+ NULL
+ };
+
+ static const char *const patterns [] = {
+ "CMakeLists.txt",
+ NULL
+ };
+
+ static kindDefinition CMakeKindTable [] = {
+ {
+ true, 'f', "function", "functions",
+ },
+ {
+ true, 'm', "macro", "macros",
+ },
+ {
+ true, 't', "target", "targets",
+ },
+ {
+ true, 'v', "variable", "variable definitions",
+ },
+ {
+ true, 'D', "option", "options specified with -D",
+ },
+ {
+ true, 'p', "project", "projects",
+ },
+ };
+
+ parserDefinition* const def = parserNew ("CMake");
+
+ def->enabled = true;
+ def->extensions = extensions;
+ def->patterns = patterns;
+ def->aliases = aliases;
+ def->method = METHOD_NOT_CRAFTED|METHOD_REGEX;
+ def->kindTable = CMakeKindTable;
+ def->kindCount = ARRAY_SIZE(CMakeKindTable);
+ def->initialize = initializeCMakeParser;
+
+ return def;
+}
diff --git a/optlib/cmake.ctags b/optlib/cmake.ctags
new file mode 100644
index 0000000000..7d7414cc95
--- /dev/null
+++ b/optlib/cmake.ctags
@@ -0,0 +1,167 @@
+#
+# cmake.ctags --- multitable regex parser for CMake's files
+#
+# Copyright (c) 2018, 128 Technology, Inc.
+#
+# Author: Hadriel Kaplan (hadrielk@yahoo.com)
+#
+# This source code is released for free distribution under the terms of the
+# GNU General Public License version 2 or (at your option) any later version.
+#
+#
+# Overview:
+#
+# This universal-ctags optlib option file defines the parser for tagging
+# CMake files. It supports tagging the following:
+#
+# - cmake function and macro names
+# - build target, executable, and library target names
+# - cmake variables and options
+# - cmake project names
+#
+# Caveats:
+#
+# Names that are ${} references to variables are not tagged.
+#
+# For example, given the following:
+#
+# set(PROJECT_NAME_STR ${PROJECT_NAME})
+# add_executable( ${PROJECT_NAME_STR} ... )
+# add_custom_target( ${PROJECT_NAME_STR}_tests ... )
+# add_library( sharedlib ... )
+#
+# the variable 'PROJECT_NAME_STR' and target 'sharedlib' will both be tagged,
+# but the other targets will not be.
+#
+#
+# References:
+#
+# - https://cmake.org/cmake/help/latest/manual/cmake-language.7.html
+#
+
+--langdef=CMake
+--map-CMake=+.cmake
+--map-CMake=+(CMakeLists.txt)
+
+#
+# Kinds
+#
+--kinddef-CMake=f,function,functions
+--kinddef-CMake=m,macro,macros
+--kinddef-CMake=t,target,targets
+--kinddef-CMake=v,variable,variable definitions
+--kinddef-CMake=D,option,options specified with -D
+--kinddef-CMake=p,project,projects
+
+#
+# Tables
+#
+--_tabledef-CMake=main
+--_tabledef-CMake=variable
+--_tabledef-CMake=function
+--_tabledef-CMake=macro
+--_tabledef-CMake=target
+--_tabledef-CMake=option
+--_tabledef-CMake=project
+
+#
+# comment
+#
+--_tabledef-CMake=commentBegin
+--_tabledef-CMake=commentMultiline
+
+--_mtable-regex-CMake=commentBegin/\[\[//{tjump=commentMultiline}
+--_mtable-regex-CMake=commentBegin/[^\n]*[ \t\n]*//{tleave}
+
+--_mtable-regex-CMake=commentMultiline/\]\][ \t\n]*//{tleave}
+--_mtable-regex-CMake=commentMultiline/.[^]]*//
+
+--_tabledef-CMake=skipComment
+--_mtable-regex-CMake=skipComment/#//{tenter=commentBegin}
+
+#
+# Utilities
+#
+--_tabledef-CMake=skipWhiteSpace
+--_tabledef-CMake=skipToName
+--_tabledef-CMake=nextToken
+
+--_mtable-regex-CMake=skipWhiteSpace/[ \t\n]+//
+
+--_mtable-extend-CMake=skipToName+skipWhiteSpace
+--_mtable-extend-CMake=skipToName+skipComment
+
+--_mtable-regex-CMake=nextToken/[^ \t\n]+[ \t\n]*//
+
+#
+# main
+#
+# This first regex entry may seem odd - it's purely for improving performance, by
+# matching tokens with leading characters that could not possibly match a later regex,
+# and just skipping the whole token (and trailing whitespace). This one regex line
+# improved performance by an order of magnitude.
+--_mtable-regex-CMake=main/[^sSfFmMaAoOpP# \t\n][^ #\t\n]*[ \t\n]+//
+--_mtable-extend-CMake=main+skipComment
+--_mtable-regex-CMake=main/set[ \t]*\(//{icase}{tenter=variable}
+--_mtable-regex-CMake=main/function[ \t]*\(//{icase}{tenter=function}
+--_mtable-regex-CMake=main/macro[ \t]*\(//{icase}{tenter=macro}
+--_mtable-regex-CMake=main/add_(custom_target|executable|library)[ \t]*\(//{icase}{tenter=target}
+--_mtable-regex-CMake=main/option[ \t]*\(//{icase}{tenter=option}
+--_mtable-regex-CMake=main/project[ \t]*\(//{icase}{tenter=project}
+--_mtable-extend-CMake=main+nextToken
+--_mtable-extend-CMake=main+skipWhiteSpace
+
+
+#
+# Each of the following basically work the same way, and only differ in the
+# exact pattern allowed to be their name, and the Kind they add. Note that they
+# capture a required trailing '[ \t\n\)]' or '#', to verify the full name token
+# matched the name's pattern, but then we advanceTo=2start for the next round,
+# so that we don't go past a potential '#' comment token but instead match it
+# again in the main table as a comment. The odds of a comment '#' immediately
+# following the name is very low, so we split it into its own check and do it
+# last in each table - this improves real-world performance ~10%, because in
+# the common case we can capture the whitespace at the same time as the name,
+# and not have to skip it again in the 'main' table.
+#
+
+#
+# variable
+#
+--_mtable-regex-CMake=variable/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/v/{tleave}
+--_mtable-extend-CMake=variable+skipToName
+--_mtable-regex-CMake=variable/([A-Za-z0-9_.-]+)(#)/\1/v/{tleave}{_advanceTo=2start}
+
+#
+# function
+#
+--_mtable-regex-CMake=function/([A-Za-z_][A-Za-z0-9_]*)[ \t\n\)]+/\1/f/{tleave}
+--_mtable-extend-CMake=function+skipToName
+--_mtable-regex-CMake=function/([A-Za-z_][A-Za-z0-9_]*)(#)/\1/f/{tleave}{_advanceTo=2start}
+
+#
+# macro
+#
+--_mtable-regex-CMake=macro/([A-Za-z_][A-Za-z0-9_]*)[ \t\n\)]+/\1/m/{tleave}
+--_mtable-extend-CMake=macro+skipToName
+--_mtable-regex-CMake=macro/([A-Za-z_][A-Za-z0-9_]*)(#)/\1/m/{tleave}{_advanceTo=2start}
+
+#
+# target
+#
+--_mtable-regex-CMake=target/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/t/{tleave}
+--_mtable-extend-CMake=target+skipToName
+--_mtable-regex-CMake=target/([A-Za-z0-9_.-]+)(#)/\1/t/{tleave}{_advanceTo=2start}
+
+#
+# option
+#
+--_mtable-regex-CMake=option/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/D/{tleave}
+--_mtable-extend-CMake=option+skipToName
+--_mtable-regex-CMake=option/([A-Za-z0-9_.-]+)(#)/\1/D/{tleave}{_advanceTo=2start}
+
+#
+# project
+#
+--_mtable-regex-CMake=project/([A-Za-z0-9_.-]+)([# \t\n\)])/\1/p/{tleave}{_advanceTo=2start}
+--_mtable-extend-CMake=project+skipToName
diff --git a/win32/ctags_vs2013.vcxproj b/win32/ctags_vs2013.vcxproj
index c026e88bac..4508ae70cf 100644
--- a/win32/ctags_vs2013.vcxproj
+++ b/win32/ctags_vs2013.vcxproj
@@ -140,6 +140,7 @@
+
diff --git a/win32/ctags_vs2013.vcxproj.filters b/win32/ctags_vs2013.vcxproj.filters
index 5ef4986123..91e25a3b58 100644
--- a/win32/ctags_vs2013.vcxproj.filters
+++ b/win32/ctags_vs2013.vcxproj.filters
@@ -174,6 +174,9 @@
Source Files\optlib
+
+ Source Files\optlib
+
Source Files\optlib