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