stamen

Stamen - static menu generator
git clone git://git.dimitrijedobrota.com/stamen.git
Log | Files | Refs | README | LICENSE

commit 45ebb3b798a9cf306ccfce512db8755e22cc472e
parent cd594065e953fe49c1ba109a1ceaf360f759a290
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Thu, 13 Jun 2024 21:43:46 +0200

Improve C++ interface with namespace

* Distintion between C and C++ interfaces
* Extract C++ interface from stamen.h into stamen.hpp
* Fix generation to reflect changes

Diffstat:
MCMakeLists.txt | 2+-
Mdemo/CMakeLists.txt | 16++++------------
Mdemo/dynamic.cpp | 6++++--
Mdemo/main.cpp | 4++--
Minclude/menu.h | 2+-
Minclude/stamen.h | 31++++++++++++-------------------
Ainclude/stamen.hpp | 21+++++++++++++++++++++
Msrc/CMakeLists.txt | 13++++++++-----
Asrc/c_bindings.cpp | 19+++++++++++++++++++
Msrc/generate.cpp | 39+++++++++++++++++++++++++--------------
Msrc/menu.cpp | 1-
Msrc/stamen.cpp | 15++++++++-------
12 files changed, 105 insertions(+), 64 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stamen - VERSION 1.0.0 + VERSION 1.0.1 DESCRIPTION "Static menu generator" LANGUAGES C CXX ) diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt @@ -9,12 +9,9 @@ add_custom_command( COMMENT "Generating menu files" ) -add_executable(demo - main.cpp - ${GENERATE_OUT}/demo_menu.cpp -) - +add_executable(demo main.cpp ${GENERATE_OUT}/demo_menu.cpp) target_link_libraries(demo stamen) +set_target_properties(demo PROPERTIES LINKER_LANGUAGE CXX) target_include_directories(demo PRIVATE ${GENERATE_OUT} ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(demo PROPERTIES @@ -23,8 +20,6 @@ set_target_properties(demo PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${GENERATE_OUT}" ) - - add_custom_command( OUTPUT ${GENERATE_OUT}/demo_menu.h ${GENERATE_OUT}/demo_menu.c COMMAND ${GENERATE_OUT}/stamen-generate ${GENERATE_OUT}/demo_menu.conf c @@ -32,12 +27,9 @@ add_custom_command( COMMENT "Generating cmenu files" ) -add_executable(cdemo - main.c - ${GENERATE_OUT}/demo_menu.c -) - +add_executable(cdemo main.c ${GENERATE_OUT}/demo_menu.c) target_link_libraries(cdemo stamen) +set_target_properties(cdemo PROPERTIES LINKER_LANGUAGE C) target_include_directories(cdemo PRIVATE ${GENERATE_OUT} ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(cdemo PROPERTIES diff --git a/demo/dynamic.cpp b/demo/dynamic.cpp @@ -1,7 +1,9 @@ +#include "stamen.hpp" #include <iostream> -#include <stamen.h> -const stamen::display_f stamen_display = stamen::builtin_display; +// need to link against stamen library +// in order to use stamen::builtin_display +const stamen::display_f &stamen::display = stamen::builtin_display; int finish(int) { exit(1); } diff --git a/demo/main.cpp b/demo/main.cpp @@ -4,8 +4,8 @@ #include <iostream> // need to link against stamen library -// in order to use stamen_builtin_display -const stamen::display_f stamen_display = stamen::builtin_display; +// in order to use stamen::builtin_display +const stamen::display_f &stamen::display = stamen::builtin_display; int operation1(int) { std::cout << "operation 1" << std::endl; diff --git a/include/menu.h b/include/menu.h @@ -1,7 +1,7 @@ #ifndef STAMEN_MENU_H #define STAMEN_MENU_H -#include "stamen.h" +#include "stamen.hpp" #include <cstring> #include <iostream> diff --git a/include/stamen.h b/include/stamen.h @@ -2,9 +2,8 @@ #define STAMEN_STAMEN_H #ifdef __cplusplus -#define EXTERNC extern "C" -#else -#define EXTERNC extern +extern "C" { +namespace stamen { #endif typedef int (*stamen_callback_f)(int); @@ -18,25 +17,19 @@ struct stamen_item_t { typedef int (*stamen_display_f)(const char *, const stamen_item_t[], int); extern const stamen_display_f stamen_display; -EXTERNC int stamen_dynamic(const char *code); -EXTERNC void stamen_read(const char *filename); -EXTERNC void stamen_insert(const char *code, stamen_callback_f callback); - -EXTERNC int stamen_builtin_display(const char *title, - const stamen_item_t itemv[], int size); -#ifdef __cplusplus -namespace stamen { +#if !defined __cplusplus || defined WITH_C_BINDINGS -using callback_f = stamen_callback_f; -using display_f = stamen_display_f; -using item_t = stamen_item_t; +int stamen_dynamic(const char *code); +void stamen_read(const char *filename); +void stamen_insert(const char *code, stamen_callback_f callback); +int stamen_builtin_display(const char *title, const stamen_item_t itemv[], + int size); -const auto dynamic = stamen_dynamic; -const auto read = stamen_read; -const auto insert = stamen_insert; -const auto builtin_display = stamen_builtin_display; +#endif +#ifdef __cplusplus } // namespace stamen +} // extern "C" #endif -#endif +#endif // STAMEN_STAMEN_H diff --git a/include/stamen.hpp b/include/stamen.hpp @@ -0,0 +1,21 @@ +#ifndef STAMEN_STAMEN_HPP +#define STAMEN_STAMEN_HPP + +#include "stamen.h" + +namespace stamen { + +using callback_f = stamen_callback_f; +using display_f = stamen_display_f; +using item_t = stamen_item_t; + +extern const display_f &display; + +int dynamic(const char *code); +void read(const char *filename); +void insert(const char *code, callback_f callback); +int builtin_display(const char *title, const item_t itemv[], int size); + +} // namespace stamen + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -1,12 +1,15 @@ -add_library(stamen-include INTERFACE) -target_include_directories(stamen-include INTERFACE ../include) +add_library(stamen STATIC stamen.cpp menu.cpp c_bindings.cpp) +target_include_directories(stamen PUBLIC ../include) +target_compile_definitions(stamen PRIVATE WITH_C_BINDINGS) +set_target_properties(stamen PROPERTIES LINKER_LANGUAGE CXX) -add_library(stamen stamen.cpp menu.cpp) -target_link_libraries(stamen PUBLIC stamen-include) set_target_properties(stamen PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} - PUBLIC_HEADER ../include/stamen.h + DEBUG_POSTFIX "d" + PUBLIC_HEADER "../include/stamen.h;../include/stamen.hpp" + MACOSX_RPATH ON + WINDOWS_EXPORT_ALL_SYMBOLS ON ) install(TARGETS stamen diff --git a/src/c_bindings.cpp b/src/c_bindings.cpp @@ -0,0 +1,19 @@ +#include "stamen.h" +#include "stamen.hpp" + +namespace stamen { + +int stamen_dynamic(const char *code) { return dynamic(code); } + +void stamen_read(const char *filename) { return read(filename); } + +void stamen_insert(const char *code, stamen_callback_f callback) { + return insert(code, callback); +} + +int stamen_builtin_display(const char *title, const stamen_item_t itemv[], + int size) { + return builtin_display(title, itemv, size); +} + +} // namespace stamen diff --git a/src/generate.cpp b/src/generate.cpp @@ -10,33 +10,44 @@ namespace stamen { class Generator { public: - static void generateInclude(std::ostream &os) { + static void generateInclude(std::ostream &os, bool cpp) { os << "#ifndef STAMEN_MENU_H\n"; os << "#define STAMEN_MENU_H\n\n"; - os << "#include <stamen.h>\n\n"; + + if (cpp) os << "#include \"stamen.hpp\"\n\n"; + else os << "#include \"stamen.h\"\n\n"; + for (const auto &[code, menu] : Menu::menu_lookup) { os << std::format("int {}(int);\n", menu.getCode()); } + os << "\n#endif\n"; } - static void generateSource(std::ostream &os) { - os << "#include <stamen.h>\n"; + static void generateSource(std::ostream &os, bool cpp) { + if (cpp) os << "#include \"stamen.hpp\"\n\n"; + else os << "#include \"stamen.h\"\n\n"; + os << "#include \"shared.h\"\n\n"; for (const auto &[code, menu] : Menu::menu_lookup) { os << std::format("int {}(int) {{\n", menu.getCode()); - os << std::format("\tstatic const stamen_item_t items[] = {{\n"); + if (cpp) os << "\tstatic const stamen::item_t items[] = "; + else os << "\tstatic const stamen_item_t items[] = "; + + os << "{\n"; for (int i = 0; i < menu.getSize(); i++) { - os << std::format("\t\t{{ {}, \"{}\" }},\n", menu.getCode(i), - menu.getPrompt(i)); + os << "\t\t{ " << menu.getCode(i); + os << ", \"" << menu.getPrompt(i) << "\" },\n"; } - os << std::format("\t}};\n"); + os << "\t};\n"; + + if (cpp) os << "\treturn stamen::display"; + else os << "\treturn stamen_display"; - os << std::format("\treturn stamen_display(\"{}\", items, " - "sizeof(items) / sizeof(items[0]));\n", - menu.getTitle()); - os << std::format("}}\n\n"); + os << std::format("(\"{}\"", menu.getTitle()); + os << ", items, sizeof(items) / sizeof(items[0]));\n"; + os << "}\n\n"; } } }; @@ -63,8 +74,8 @@ int main(const int argc, const char *argv[]) { std::string ext = cpp ? "pp" : ""; std::ofstream source(base + ".c" + ext), include(base + ".h" + ext); - Generator::generateSource(source); - Generator::generateInclude(include); + Generator::generateSource(source, cpp); + Generator::generateInclude(include, cpp); return 0; } diff --git a/src/menu.cpp b/src/menu.cpp @@ -1,5 +1,4 @@ #include "menu.h" -#include "stamen.h" #include <deque> #include <format> diff --git a/src/stamen.cpp b/src/stamen.cpp @@ -1,4 +1,4 @@ -#include "stamen.h" +#include "stamen.hpp" #include "menu.h" #include <cmath> @@ -7,16 +7,15 @@ #include <ostream> #include <variant> -using namespace stamen; +namespace stamen { -int stamen_dynamic(const char *code) { return Menu::dynamic(code); } -void stamen_read(const char *filename) { Menu::read(filename); } -void stamen_insert(const char *code, stamen_callback_f callback) { +int dynamic(const char *code) { return Menu::dynamic(code); } +void read(const char *filename) { Menu::read(filename); } +void insert(const char *code, callback_f callback) { Menu::insert(code, callback); } -int stamen_builtin_display(const char *title, const stamen_item_t itemv[], - int size) { +int builtin_display(const char *title, const item_t itemv[], int size) { const size_t digits = size_t(std::log10(size)) + 1; const auto items = std::span(itemv, size_t(size)); int choice = 0; @@ -56,3 +55,5 @@ int stamen_builtin_display(const char *title, const stamen_item_t itemv[], return 1; } + +} // namespace stamen