stamen

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

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 }