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