stamen

Static 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>
5 #include "poafloc/poafloc.hpp"
6 #include "stamen/menu.hpp"
7 #include "stamen/stamen.hpp"
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 };
18 void generate_include(std::ostream& ost)
19 {
20 ost << "#ifndef STAMEN_MENU_H\n";
21 ost << "#define STAMEN_MENU_H\n\n";
23 for (const auto& [code, menu] : stamen::menu::menu_lookup)
24 {
25 ost << std::format("int {}(size_t);\n", menu.get_code());
26 }
28 ost << "\n#endif\n";
29 }
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 }
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";
49 for (const auto& [code, menu] : stamen::menu::menu_lookup)
50 {
51 ost << std::format("int {}(size_t /* unused */) {{\n", menu.get_code());
53 if (args.cpp) ost << "\tstatic const stamen::item_t items[] = ";
54 else ost << "\tstatic const stamen_item_t items[] = ";
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";
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 }
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())
105 if (arguments->cpp) arguments->display = "stamen::builtin_display";
106 else arguments->display = "stamen_builtin_display";
108 break;
109 default:
110 break;
112 return 0;
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 };
127 static const poafloc::arg_t arg {
128 options,
129 parse_opt,
130 "config_file",
131 "",
132 };
134 int main(int argc, char* argv[])
136 arguments_t args;
138 if (poafloc::parse(&arg, argc, argv, 0, &args) != 0)
140 std::cerr << "There was an error while parsing arguments";
141 return 1;
144 const auto& config = args.config;
145 stamen::menu::read(config.c_str());
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;
152 std::ofstream include(base + ".h" + ext);
153 generate_include(include);
155 std::ofstream source(base + ".c" + ext);
156 generate_source(source, args);
158 return 0;