stamenStatic Menu Generator |
git clone git://git.dimitrijedobrota.com/stamen.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
generate.cpp (4222B)
0 #include <format> 1 #include <fstream> 2 #include <iostream> 3 #include <string> 4 5 #include "poafloc/poafloc.hpp" 6 #include "stamen/menu.hpp" 7 #include "stamen/stamen.hpp" 8 9 struct arguments_t 10 { 11 std::string config; 12 std::string display; 13 std::string header = "shared.h"; 14 bool cpp = false; 15 bool user = false; 16 }; 17 18 void generate_include(std::ostream& ost) 19 { 20 ost << "#ifndef STAMEN_MENU_H\n"; 21 ost << "#define STAMEN_MENU_H\n\n"; 22 23 for (const auto& [code, menu] : stamen::menu::menu_lookup) 24 { 25 ost << std::format("int {}(size_t);\n", menu.get_code()); 26 } 27 28 ost << "\n#endif\n"; 29 } 30 31 void generate_source(std::ostream& ost, const arguments_t& args) 32 { 33 ost << std::format("#include \"{}\"\n", args.header); 34 if (args.user) 35 { 36 if (args.cpp) ost << "#include \"stamen.hpp\"\n\n"; 37 else ost << "#include \"stamen.h\"\n\n"; 38 } 39 else 40 { 41 if (args.cpp) ost << "#include <stamen/stamen.hpp>\n\n"; 42 else ost << "#include <stamen/stamen.h>\n\n"; 43 } 44 45 ost << std::format("extern int {}(const char *title, ", args.display); 46 if (args.cpp) ost << "const stamen::item_t itemv[], size_t size);\n\n"; 47 else ost << "const stamen_item_t itemv[], size_t size);\n\n"; 48 49 for (const auto& [code, menu] : stamen::menu::menu_lookup) 50 { 51 ost << std::format("int {}(size_t /* unused */) {{\n", menu.get_code()); 52 53 if (args.cpp) ost << "\tstatic const stamen::item_t items[] = "; 54 else ost << "\tstatic const stamen_item_t items[] = "; 55 56 ost << "{\n"; 57 for (auto i = 0UL; i < menu.get_size(); i++) 58 { 59 ost << "\t\t{ " << menu.get_code(i); 60 ost << ", \"" << menu.get_prompt(i) << "\" },\n"; 61 } 62 ost << "\t};\n"; 63 64 ost << std::format("\treturn {}(\"{}\"", args.display, menu.get_title()); 65 ost << ", items, sizeof(items) / sizeof(items[0]));\n"; 66 ost << "}\n\n"; 67 } 68 } 69 70 int parse_opt(int key, const char* arg, poafloc::Parser* parser) 71 { 72 auto* arguments = static_cast<arguments_t*>(parser->input()); 73 switch (key) 74 { 75 case 'd': 76 arguments->display = arg; 77 break; 78 case 'h': 79 arguments->header = arg; 80 break; 81 case 'u': 82 arguments->user = true; 83 break; 84 case 666: 85 arguments->cpp = false; 86 break; 87 case 777: 88 arguments->cpp = true; 89 break; 90 case poafloc::ARG: 91 if (!arguments->config.empty()) 92 { 93 poafloc::failure(parser, 0, 0, "Too many arguments"); 94 poafloc::help(parser, stderr, poafloc::STD_USAGE); 95 } 96 arguments->config = arg; 97 break; 98 case poafloc::NO_ARGS: 99 poafloc::failure(parser, 0, 0, "Missing an argument"); 100 poafloc::help(parser, stderr, poafloc::STD_USAGE); 101 break; 102 case poafloc::END: 103 if (arguments->display.empty()) 104 { 105 if (arguments->cpp) arguments->display = "stamen::builtin_display"; 106 else arguments->display = "stamen_builtin_display"; 107 } 108 break; 109 default: 110 break; 111 } 112 return 0; 113 } 114 115 static const poafloc::option_t options[] { 116 {nullptr, 0, nullptr, 0, "Output mode", 1}, 117 {"c", 666, nullptr, 0, "Generate files for C"}, 118 {"cpp", 777, nullptr, 0, "Generate files for C++"}, 119 {nullptr, 0, nullptr, 0, "Output settings", 2}, 120 {"display", 'd', "FUNC", 0, "Set display function to be called"}, 121 {"user", 'u', nullptr, 0, "Include user stamen headers"}, 122 {"header", 'h', "HDR", 0, "Header with free functions, default: shared.h"}, 123 {nullptr, 0, nullptr, 0, "Informational Options", -1}, 124 {nullptr}, 125 }; 126 127 static const poafloc::arg_t arg { 128 options, 129 parse_opt, 130 "config_file", 131 "", 132 }; 133 134 int main(int argc, char* argv[]) 135 { 136 arguments_t args; 137 138 if (poafloc::parse(&arg, argc, argv, 0, &args) != 0) 139 { 140 std::cerr << "There was an error while parsing arguments"; 141 return 1; 142 } 143 144 const auto& config = args.config; 145 stamen::menu::read(config.c_str()); 146 147 const std::string::size_type pos = args.config.rfind('.'); 148 const std::string ext = args.cpp ? "pp" : ""; 149 const std::string base = 150 pos != std::string::npos ? config.substr(0, pos) : config; 151 152 std::ofstream include(base + ".h" + ext); 153 generate_include(include); 154 155 std::ofstream source(base + ".c" + ext); 156 generate_source(source, args); 157 158 return 0; 159 }