Skip to content
Permalink
Browse files

Merge pull request #2498 from kodebach/highlevel_codegen

Highlevel codegen
  • Loading branch information...
markus2330 committed May 8, 2019
2 parents 9fb421b + 0ad7748 commit 7437307dc478b00c0063c6dfd06ee45eddbbcd09
Showing with 11,464 additions and 368 deletions.
  1. +1 −1 .travis.yml
  2. +14 −2 cmake/CMakeLists.txt
  3. +1 −1 cmake/ElektraCache.cmake
  4. +4 −0 cmake/ElektraConfig.cmake.in
  5. +1 −0 cmake/elektra.pc.in
  6. +9 −0 doc/news/_preparation_next_release.md
  7. +1 −0 examples/codegen/README.md
  8. +72 −0 examples/codegen/econf/README.md
  9. +45 −0 examples/codegen/econf/cmake/CMakeLists.txt
  10. BIN examples/codegen/econf/codegen_econf_example.conf
  11. +12 −0 examples/codegen/econf/pkgconfig/Makefile
  12. +71 −0 examples/codegen/econf/spec.ini
  13. +93 −0 examples/codegen/econf/src/application.c
  14. +65 −0 examples/codegen/tree/README.md
  15. +45 −0 examples/codegen/tree/cmake/CMakeLists.txt
  16. +12 −0 examples/codegen/tree/pkgconfig/Makefile
  17. +25 −0 examples/codegen/tree/spec.ini
  18. +67 −0 examples/codegen/tree/src/application.c
  19. +1 −1 examples/external/pkgconfig/Makefile
  20. +1 −6 examples/highlevel/cmake/CMakeLists.txt
  21. +7 −1 scripts/pre-commit-check-formatting
  22. +2 −2 scripts/reformat-source
  23. +8 −0 src/error/specification_highlevel
  24. +4 −0 src/include/CMakeLists.txt
  25. +30 −216 src/include/elektra.h
  26. +7 −0 src/include/kdb.h.in
  27. +1 −0 src/include/kdbconfig.h.in
  28. +5 −0 src/include/kdbmacros.h
  29. +3 −0 src/include/kdbprivate.h
  30. +6 −0 src/libs/highlevel/CMakeLists.txt
  31. +14 −0 src/libs/highlevel/elektra-codegen.pc.in
  32. +75 −21 src/libs/highlevel/elektra.c
  33. +51 −0 src/libs/highlevel/elektra_array_value.c
  34. +50 −0 src/libs/highlevel/elektra_value.c
  35. +1 −1 src/libs/tools/src/specreader.cpp
  36. +81 −3 src/plugins/c/c.c
  37. +2 −0 src/plugins/internalnotification/macros/create_type_tests.h
  38. +4 −0 src/plugins/ni/nickel-1.1.0/src/hash.c
  39. +1 −1 src/plugins/reference/README.md
  40. +10 −6 src/tools/kdb/CMakeLists.txt
  41. +12 −1 src/tools/kdb/cmdline.cpp
  42. +1 −0 src/tools/kdb/cmdline.hpp
  43. +2 −0 src/tools/kdb/factory.hpp
  44. +106 −0 src/tools/kdb/gen.cpp
  45. +45 −0 src/tools/kdb/gen.hpp
  46. +1,140 −0 src/tools/kdb/gen/elektragen.cpp
  47. +43 −0 src/tools/kdb/gen/elektragen.hpp
  48. +1,456 −0 src/tools/kdb/gen/mustache.hpp
  49. +192 −0 src/tools/kdb/gen/template.cpp
  50. +200 −0 src/tools/kdb/gen/template.hpp
  51. +26 −0 src/tools/kdb/gen/templates/CMakeLists.txt
  52. +120 −0 src/tools/kdb/gen/templates/collect.cpp
  53. +157 −0 src/tools/kdb/gen/templates/elektra.c.mustache
  54. +142 −0 src/tools/kdb/gen/templates/elektra.h.mustache
  55. +10 −0 src/tools/kdb/gen/templates/elektra/context.fun.h.mustache
  56. +13 −0 src/tools/kdb/gen/templates/elektra/context.tags.h.mustache
  57. +101 −0 src/tools/kdb/gen/templates/elektra/enum.c.mustache
  58. +28 −0 src/tools/kdb/gen/templates/elektra/enum.decl.h.mustache
  59. +151 −0 src/tools/kdb/gen/templates/elektra/keys.fun.h.mustache
  60. +93 −0 src/tools/kdb/gen/templates/elektra/keys.fun.struct.h.mustache
  61. +112 −0 src/tools/kdb/gen/templates/elektra/keys.fun.structref.h.mustache
  62. +19 −0 src/tools/kdb/gen/templates/elektra/keys.tags.h.mustache
  63. +54 −0 src/tools/kdb/gen/templates/elektra/struct.alloc.fields.c.mustache
  64. +201 −0 src/tools/kdb/gen/templates/elektra/struct.c.mustache
  65. +36 −0 src/tools/kdb/gen/templates/elektra/struct.decl.h.mustache
  66. +8 −6 src/tools/{gen → pythongen}/CMakeLists.txt
  67. +17 −11 src/tools/{gen → pythongen}/Makefile
  68. 0 src/tools/{gen → pythongen}/README.md
  69. +1 −1 src/tools/{gen/gen → pythongen/pythongen}
  70. 0 src/tools/{gen → pythongen}/setup.py.in
  71. 0 src/tools/{gen → pythongen}/support/__init__.py
  72. 0 src/tools/{gen → pythongen}/support/c.py
  73. 0 src/tools/{gen → pythongen}/support/c_elektra.py
  74. 0 src/tools/{gen → pythongen}/support/context.py
  75. 0 src/tools/{gen → pythongen}/support/cpp.py
  76. 0 src/tools/{gen → pythongen}/support/gen.py
  77. 0 src/tools/{gen → pythongen}/support/genopt.py
  78. 0 src/tools/{gen → pythongen}/support/kdb.py
  79. 0 src/tools/{gen → pythongen}/support/nested.py
  80. 0 src/tools/{gen → pythongen}/support/util.py
  81. +0 −1 src/tools/{gen → pythongen}/template/context_dynamic.hpp
  82. 0 src/tools/{gen → pythongen}/template/context_static.hpp
  83. 0 src/tools/{gen → pythongen}/template/genopt.c
  84. 0 src/tools/{gen → pythongen}/template/genopt.h
  85. +0 −1 src/tools/{gen → pythongen}/template/nested.hpp
  86. +3 −4 src/tools/{gen → pythongen}/template/template.h
  87. +0 −1 src/tools/{gen → pythongen}/template/template.hpp
  88. 0 src/tools/{gen → pythongen}/template/template.html
  89. 0 src/tools/{gen → pythongen}/template/template.man
  90. 0 src/tools/{gen → pythongen}/tests/Doxyfile
  91. 0 src/tools/{gen → pythongen}/tests/editor.ini
  92. 0 src/tools/{gen → pythongen}/tests/editor_context.cpp
  93. +0 −1 src/tools/{gen → pythongen}/tests/lift.c
  94. 0 src/tools/{gen → pythongen}/tests/lift.cpp
  95. 0 src/tools/{gen → pythongen}/tests/lift.ini
  96. 0 src/tools/{gen → pythongen}/tests/lift_context.cpp
  97. 0 src/tools/{gen → pythongen}/tests/lift_nested.cpp
  98. 0 src/tools/{gen → pythongen}/tests/location.cpp
  99. 0 src/tools/{gen → pythongen}/tests/location.ini
  100. 0 src/tools/{gen → pythongen}/tests/visit.ini
  101. 0 src/tools/{gen → pythongen}/tests/visit_context.cpp
  102. 0 src/tools/{gen → pythongen}/util/util.c
  103. +3 −6 src/tools/{gen → pythongen}/util/util.cpp
  104. +0 −58 tests/kdb/testkdb_highlevel.cpp
  105. +9 −1 tests/shell/CMakeLists.txt
  106. +213 −0 tests/shell/check_gen.sh
  107. +3 −4 tests/shell/external/example.sh
  108. +144 −0 tests/shell/external/example_codegen_econf.sh
  109. +132 −0 tests/shell/external/example_codegen_tree.sh
  110. +7 −7 tests/shell/external/example_highlevel.sh
  111. +3 −3 tests/shell/{check_gen.sh.disabled → external/pythongen.sh}
  112. +21 −0 tests/shell/gen/CMakeLists.txt
  113. +118 −0 tests/shell/gen/elektra/context.check.sh
  114. +16 −0 tests/shell/gen/elektra/context.data.ini.disabled
  115. +205 −0 tests/shell/gen/elektra/context.expected.c
  116. +432 −0 tests/shell/gen/elektra/context.expected.h
  117. 0 tests/shell/gen/elektra/context.params
  118. +93 −0 tests/shell/gen/elektra/empty.check.sh
  119. +2 −0 tests/shell/gen/elektra/empty.data.ini
  120. +190 −0 tests/shell/gen/elektra/empty.expected.c
  121. +227 −0 tests/shell/gen/elektra/empty.expected.h
  122. 0 tests/shell/gen/elektra/empty.params
  123. +124 −0 tests/shell/gen/elektra/enum.check.sh
  124. +58 −0 tests/shell/gen/elektra/enum.data.ini
  125. +601 −0 tests/shell/gen/elektra/enum.expected.c
  126. +479 −0 tests/shell/gen/elektra/enum.expected.h
  127. +1 −0 tests/shell/gen/elektra/enum.params
  128. +5 −0 tests/shell/gen/elektra/nodefault.data.ini
  129. 0 tests/shell/gen/elektra/nodefault.params
  130. +1 −0 tests/shell/gen/elektra/nodefault.stderr
  131. +5 −0 tests/shell/gen/elektra/notype.data.ini
  132. +190 −0 tests/shell/gen/elektra/notype.expected.c
  133. +227 −0 tests/shell/gen/elektra/notype.expected.h
  134. 0 tests/shell/gen/elektra/notype.params
  135. +120 −0 tests/shell/gen/elektra/simple.check.sh
  136. +22 −0 tests/shell/gen/elektra/simple.data.ini
  137. +200 −0 tests/shell/gen/elektra/simple.expected.c
  138. +452 −0 tests/shell/gen/elektra/simple.expected.h
  139. 0 tests/shell/gen/elektra/simple.params
  140. +111 −0 tests/shell/gen/elektra/struct.check.sh
  141. +58 −0 tests/shell/gen/elektra/struct.data.ini
  142. +663 −0 tests/shell/gen/elektra/struct.expected.c
  143. +938 −0 tests/shell/gen/elektra/struct.expected.h
  144. 0 tests/shell/gen/elektra/struct.params
  145. 0 tests/shell/gen/elektra/struct.stdout
@@ -199,7 +199,7 @@ matrix:
env:
- HASKELL=ON
# Use a minimal configuration for the haskell bindings to give it enough time to compile dependencies
- PLUGINS='resolver_fm_hpu_b;dump;dini;list;spec;haskell;typechecker;ini;sync;error;base64;regexdispatcher'
- PLUGINS='resolver_fm_hpu_b;dump;dini;list;spec;haskell;typechecker;ini;sync;error;base64;regexdispatcher;ni;c'
- BINDINGS=haskell
- TOOLS=kdb

@@ -4,11 +4,20 @@ include (CMakePackageConfigHelpers)

# cmake settings for use by find_package
if (BUILD_SHARED)
set (Elektra_LIBRARIES "elektra-core elektra-kdb")
set (Elektra_LIBRARIES "elektra-kdb elektra-core")
set (ElektraHighlevel_LIBRARIES "elektra-highlevel")
set (ElektraCodegen_LIBRARIES "elektra-highlevel elektra-opts elektra-invoke")
set (Elektra_BUILD_TYPE "shared")
elseif (BUILD_FULL)
set (Elektra_LIBRARIES "elektra-full")
set (ElektraHighlevel_LIBRARIES "elektra-full")
set (ElektraCodegen_LIBRARIES "elektra-full")
set (Elektra_BUILD_TYPE "full")
elseif (BUILD_STATIC)
set (Elektra_LIBRARIES "elektra-static")
set (ElektraHighlevel_LIBRARIES "elektra-static")
set (ElektraCodegen_LIBRARIES "elektra-static")
set (Elektra_BUILD_TYPE "static")
endif ()
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/ElektraConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ElektraConfig.cmake" @ONLY)

@@ -22,11 +31,14 @@ install (FILES "${CMAKE_CURRENT_BINARY_DIR}/ElektraConfig.cmake"

# pkg-config files
if (BUILD_SHARED)
set (PACKAGE_LIBS "-lelektra-core -lelektra-kdb")
set (PACKAGE_LIBS "-lelektra-kdb -lelektra-core")
set (PACKAGE_BUILD_TYPE "shared")
elseif (BUILD_FULL)
set (PACKAGE_LIBS "-lelektra-full")
set (PACKAGE_BUILD_TYPE "full")
elseif (BUILD_STATIC)
set (PACKAGE_LIBS "-lelektra-static")
set (PACKAGE_BUILD_TYPE "static")
endif ()
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/elektra.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/elektra.pc" @ONLY)

@@ -78,7 +78,7 @@ if (TOOLS MATCHES "NODEP")
endif ()

if (TOOLS MATCHES "ALL")
set (TOOLS_LIST gen race qt-gui gen-gpg-testkey)
set (TOOLS_LIST pythongen race qt-gui gen-gpg-testkey)
set (TOOLS_FORCE FORCE)
list (REMOVE_ITEM TOOLS
ALL)
@@ -20,6 +20,9 @@ endif()
set (Elektra_INCLUDE_DIRS "@CMAKE_INSTALL_PREFIX@/include/@TARGET_INCLUDE_FOLDER@")
set (Elektra_LIBRARIES @Elektra_LIBRARIES@)

set (ElektraHighlevel_LIBRARIES @ElektraHighlevel_LIBRARIES@)
set (ElektraCodegen_LIBRARIES @ElektraCodegen_LIBRARIES@)

find_path (Elektra_TEMPLATES_DIR
NAMES template.h
PATHS @CMAKE_INSTALL_PREFIX@/@TARGET_TEMPLATE_FOLDER@
@@ -39,6 +42,7 @@ set (ELEKTRA_VERSION_MINOR ${Elektra_VERSION_MINOR})
set (ELEKTRA_VERSION_MICRO ${Elektra_VERSION_MICRO})

# Set build type of Elektra
set (Elektra_BUILD_TYPE @Elektra_BUILD_TYPE@)
set (Elektra_SHARED @BUILD_SHARED@)
set (Elektra_FULL @BUILD_FULL@)
set (Elektra_STATIC @BUILD_STATIC@)
@@ -5,6 +5,7 @@ includedir=${prefix}/include/@TARGET_INCLUDE_FOLDER@
plugindir=${prefix}/lib@LIB_SUFFIX@/@TARGET_PLUGIN_FOLDER@
tool_execdir=${prefix}/@TARGET_TOOL_EXEC_FOLDER@
templatedir=${prefix}/@TARGET_TEMPLATE_FOLDER@
build_type=@PACKAGE_BUILD_TYPE@

Name: @PACKAGE_NAME@
Description: @PACKAGE_DESCRIPTION@
@@ -425,6 +425,15 @@ you up to date with the multi-language support provided by Elektra.

- <<TODO>>

### Code generation

`kdb gen` is now no longer an external tool implemented via python, but rather a first class command of the `kdb` tool. For now it only
supports code generation for use with the highlevel API. To try it just run `kdb gen elektra <parentKey> <outputName>`, where `<parentKey>`
is the parent key of the specification to use and `<outputName>` is some prefix for the output files. If you don't have your specification
mounted, use `kdb gen -F <plugin>:<file> elektra <parentKey> <outputName>` to load it from `<file>` using plugin `<plugin>`.

. _(Klemens Böswirth)_

## Scripts

- The `reformat-source` script now also formats `tests/shell/include_common.sh.in`. Additionally it ensures that the file is 1000 lines long,
@@ -0,0 +1 @@
# Code-generation Examples
@@ -0,0 +1,72 @@
# EConf example

This example application reads its configuration from the KDB using code-generated functions.
It then prints an EditorConfig file created from the configuration inside the KDB.

## Setup

### CMake

```sh
# execute in the current directory or replace $PWD accordingly
DIR=$PWD
mkdir "$DIR/cmake/build" && cd "$DIR/cmake/build"
cmake ..
cmake --build .
cd "$DIR"
sudo kdb mount -R noresolver codegen_econf_example.conf "spec/sw/example/econf/#0/current" specload "app=$DIR/cmake/build/application"
sudo kdb spec-mount "/sw/example/econf/#0/current"
```

### Pkgconfig

```sh
# execute in the current directory or replace $PWD accordingly
DIR=$PWD
cd "$DIR/pkgconfig/build"
make
cd "$DIR"
sudo kdb mount -R noresolver codegen_econf_example.conf "spec/sw/example/econf/#0/current" specload "app=$DIR/pkgconfig/application"
sudo kdb spec-mount "/sw/example/econf/#0/current"
```

## Running

To run the application, simply execute:

```sh
# execute in the current directory or replace $PWD accordingly
DIR=$PWD
# for CMake
LOC="cmake/build"
# for Pkgconfig
# LOC="pkgconfig"
"$DIR/$LOC/application"
```

## Configuration

The supported KDB configuration is described in `spec.ini`.

EditorConfig uses sections to match file patterns. In the KDB config, for each such section you should
create an entry in the array `format/#`. The pattern used to match files is given in `format/#/pattern`.

The other keynames used are similar to the keys used by EditorConfig, so they should be self-explanatory.
The values however are sometimes different, to fit Elektra's type system:

- then general `unset` option is not supported everywhere
- `format/#/indent/size` uses `0` instead of `tab`
- `format/#/tabwidth` allows `0`, but this is equivalent to `unset`.
- `1` and `0` are used for booleans instead of `true`/`false`
- `format/#/linelength` uses `0` instead of `off`
@@ -0,0 +1,45 @@
cmake_minimum_required (VERSION 3.0)

# ~~~
# you might need to change CMAKE_MODULE_PATH
# can also be done with ccmake
# set (CUSTOM_MODULE_PATH "/opt/local/share/cmake-3.0/Modules")
# set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CUSTOM_MODULE_PATH})
# ~~~

find_package (Elektra REQUIRED)

if (NOT KDB)
set (KDB kdb)
endif (NOT KDB)

if (ELEKTRA_FOUND)
message (STATUS "Elektra ${ELEKTRA_VERSION} found")

include_directories (${Elektra_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})

add_custom_command (OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/genelektra.c
${CMAKE_CURRENT_BINARY_DIR}/genelektra.h
COMMAND ${KDB}
ARGS gen
-F
"ni=${CMAKE_CURRENT_SOURCE_DIR}/../spec.ini"
elektra
"spec/sw/example/econf/#0/current"
"genelektra"
MAIN_DEPENDENCY ../spec.ini
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

add_executable (application ../src/application.c ${CMAKE_CURRENT_BINARY_DIR}/genelektra.c)
target_link_libraries (application ${ElektraCodegen_LIBRARIES})

if (CMAKE_VERSION VERSION_LESS "3.1")
target_compile_options (application PRIVATE "-std=c99")
else ()
set_property (TARGET application
PROPERTY C_STANDARD
99)
endif ()
else (ELEKTRA_FOUND)
message (FATAL_ERROR "Elektra not found")
endif (ELEKTRA_FOUND)
Binary file not shown.
@@ -0,0 +1,12 @@
KDB ?= kdb

application:../src/application.c genelektra.c
gcc ../src/application.c genelektra.c -std=c99 `pkg-config --cflags --libs elektra-codegen` -I. -o application -Wl,-rpath `pkg-config --variable=libdir elektra-codegen`

genelektra.c:../spec.ini
$(KDB) gen -F ni=../spec.ini elektra spec/sw/example/econf/#0/current genelektra

clean:
rm -f genelektra.c
rm -f genelektra.h
rm -f application
@@ -0,0 +1,71 @@
[]
mountpoint = codegen_econf_example.conf

[root]
type = boolean
default = 0

[format/#]
type = struct
default = ""
gen/struct/type = FormatConf
gen/struct/depth = 2

[format/#/pattern]
type = string
default = ""
gen/struct/field = filePattern

[format/#/indent/style]
type = enum
default = tab
check/enum = #1
check/enum/#0 = tab
check/enum/#1 = space
gen/enum/type = IndentStyle
gen/struct/field = indentStyle

[format/#/indent/size]
type = unsigned_long
default = 0
gen/struct/field = indentSize

[format/#/tabwidth]
type = unsigned_long
default = 8
gen/struct/field = tabWidth

[format/#/eol]
type = enum
default = native
check/enum = #3
check/enum/#0 = native
check/enum/#1 = lf
check/enum/#2 = cr
check/enum/#3 = crlf
gen/enum/type = LineEnd

[format/#/charset]
type = enum
default = utf-8
check/enum = #4
check/enum/#0 = latin1
check/enum/#1 = utf-8
check/enum/#2 = utf-16be
check/enum/#3 = utf-16le
check/enum/#4 = utf-8-bom
gen/enum/type = Charset

[format/#/trim]
type = boolean
default = 1

[format/#/eofnewline]
type = boolean
default = 1
gen/struct/field = eofNewline

[format/#/linelength]
type = unsigned_long
default = 0
gen/struct/field = maxLineLength
@@ -0,0 +1,93 @@
/**
* @file
*
* @brief
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*/

#include <genelektra.h>

#include <stdio.h>
#include <stdlib.h>

static void onFatalError (ElektraError * error)
{
fprintf (stderr, "ERROR: %s\n", elektraErrorDescription (error));
exit (EXIT_FAILURE);
}

void printFormatConf (const FormatConf * conf)
{
printf ("[%s]\n", conf->filePattern);
printf ("indent_style = %s\n", ELEKTRA_TO_STRING (EnumIndentStyle) (conf->indentStyle));
if (conf->indentSize == 0)
{
printf ("indent_size = tab\n");
}
else
{
printf ("indent_size = " ELEKTRA_UNSIGNED_LONG_F "\n", conf->indentSize);
}
if (conf->tabWidth > 0)
{
printf ("tab_width = " ELEKTRA_UNSIGNED_LONG_F "\n", conf->tabWidth);
}
if (conf->eol != LINE_END_NATIVE)
{
printf ("end_of_line = %s\n", ELEKTRA_TO_STRING (EnumLineEnd) (conf->eol));
}
printf ("charset = %s\n", ELEKTRA_TO_STRING (EnumCharset) (conf->charset));
printf ("trim_trailing_whitespace = %s\n", conf->trim ? "true" : "false");
printf ("insert_final_newline = %s\n", conf->eofNewline ? "true" : "false");
if (conf->maxLineLength == 0)
{
printf ("max_line_length = off\n");
}
else
{
printf ("max_line_length = " ELEKTRA_UNSIGNED_LONG_F "\n", conf->maxLineLength);
}
}

int main (int argc, const char ** argv)
{
specloadCheck (argc, argv);

ElektraError * error = NULL;
Elektra * elektra = NULL;
int rc = loadConfiguration (&elektra, &error);

if (rc == -1)
{
fprintf (stderr, "An error occurred while opening elektra: %s", elektraErrorDescription (error));
elektraErrorReset (&error);
return EXIT_FAILURE;
}

if (rc == 1)
{
// help mode
printHelpMessage (NULL, NULL);
return EXIT_SUCCESS;
}

elektraFatalErrorHandler (elektra, onFatalError);

kdb_boolean_t isRootFile = elektraGet (elektra, ELEKTRA_TAG_ROOT);

printf ("root = %s\n", isRootFile ? "true" : "false");

kdb_long_long_t formatCount = elektraSize (elektra, ELEKTRA_TAG_FORMAT);

for (kdb_long_long_t i = 0; i < formatCount; ++i)
{
FormatConf conf;
elektraGet2V (elektra, &conf, ELEKTRA_TAG_FORMAT, i);
printFormatConf (&conf);
}

elektraClose (elektra);

return EXIT_SUCCESS;
}
Oops, something went wrong.

0 comments on commit 7437307

Please sign in to comment.
You can’t perform that action at this time.