source: trunk/TOOLS/arb_calc_pvp.cxx

Last change on this file was 16919, checked in by westram, 7 years ago
File size: 6.5 KB
Line 
1// ============================================================= //
2//                                                               //
3//   File      : arb_calc_pvp.cxx                                //
4//   Purpose   : calculate PVP from CLI                          //
5//                                                               //
6//   Coded by Ralf Westram (coder@reallysoft.de) in April 2018   //
7//   http://www.arb-home.de/                                     //
8//                                                               //
9// ============================================================= //
10
11#include <pvp.h>
12#include <TreeRead.h>
13#include <string>
14
15using namespace std;
16
17class CLI : virtual Noncopyable {
18    bool     helpWanted;
19    GB_ERROR error;
20
21    // data from optional CLI arguments:
22    string savename; // if non-empty -> used as savename
23    string treefile; // if non-empty -> tree gets imported
24    bool   tree_delete;
25    string sainame; // if non-empty -> used as SAI name
26
27    // non-optional CLI arguments:
28    int fixed_args;
29#define FIXED_ARGS_WANTED 3
30    string database;
31    string treename;
32    string aliname;
33
34    static inline const char *getarg(int& argc, const char**& argv) {
35        return argc>0 ? (--argc,*argv++) : NULp;
36    }
37    inline const char *expect_arg(int& argc, const char**& argv) {
38        const char *arg = getarg(argc, argv);
39        if (!arg) {
40            error = "expected argument missing";
41            arg   = "";
42        }
43        return arg;
44    }
45    void show_help() const {
46        fputs("\n"
47              "arb_calc_pvp -- calculate positional variability SAI\n"
48              "Usage: arb_calc_pvp [switches] <database> <treename> <aliname>\n"
49              "\n"
50              "switches:\n"
51              "--savename <dbname>        save database with different name\n"
52              "                           (default is to overwrite input <database>)\n"
53              "--tree-import <treefile>   load tree from <treefile> + store in database as <treename>\n"
54              "                           (default: use tree existing in database)\n"
55              "--tree-delete              delete tree <treename> (before saving database)\n"
56              "--sainame <sai>            use alternate SAI name (default: POS_VAR_BY_PARSIMONY)\n"
57              "\n"
58              ,stderr);
59    }
60
61
62    void handle_fixed_argument(const char *arg) {
63        arb_assert(!error);
64
65        if (arg) {
66            switch (fixed_args) {
67                case 0: database = arg; break;
68                case 1: treename = arg; break;
69                case 2: aliname  = arg; break;
70
71                default:
72                    error = GBS_global_string("too many arguments ('%s')", arg);
73                    break;
74            }
75
76            if (!error) ++fixed_args;
77        }
78        else { // done with parsing CLI -> check missing
79            if (fixed_args != FIXED_ARGS_WANTED) {
80                const char *miss = NULp;
81                switch (fixed_args) {
82                    case 0: miss = "database"; break;
83                    case 1: miss = "treename"; break;
84                    case 2: miss = "aliname"; break;
85                    default: arb_assert(0); break;
86                }
87                error = GBS_global_string("Mandatory argument <%s> has not been provided", miss);
88            }
89        }
90    }
91
92    void parse(int& argc, const char**& argv) {
93        const char *arg = getarg(argc, argv);
94        if (arg) {
95            if      (strcmp(arg, "--savename")    == 0) savename = expect_arg(argc, argv);
96            else if (strcmp(arg, "--tree-import") == 0) treefile = expect_arg(argc, argv);
97            else if (strcmp(arg, "--tree-delete") == 0) tree_delete = true;
98            else if (strcmp(arg, "--sainame")     == 0) sainame = expect_arg(argc, argv);
99
100            else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) helpWanted = true;
101
102            else handle_fixed_argument(arg);
103        }
104    }
105
106public:
107    CLI(int argc, const char **argv) :
108        helpWanted(false),
109        error(NULp),
110        tree_delete(false),
111        fixed_args(0)
112    {
113        --argc; ++argv;
114        while (!error && argc>0 && !helpWanted) {
115            parse(argc, argv);
116        }
117        if (!error && !helpWanted) handle_fixed_argument(NULp);
118    }
119
120    bool help_wanted() const { return helpWanted; }
121    void show_help_if_useful() const { if (helpWanted) show_help(); }
122    GB_ERROR get_error() const { return error; }
123
124    const char *get_database() const { return database.c_str(); }
125    const char *get_treename() const { return treename.c_str(); }
126    const char *get_aliname()  const { return aliname.c_str(); }
127
128    const char *get_database_savename() const { return savename.empty() ? get_database() : savename.c_str(); }
129    const char *get_SAI_name() const { return sainame.empty() ? "POS_VAR_BY_PARSIMONY" : sainame.c_str(); }
130
131    bool shall_import_tree() const { return !treefile.empty(); }
132    const char *get_treeimport_filename() const { arb_assert(shall_import_tree()); return treefile.c_str(); }
133
134    bool shall_delete_tree() const { return tree_delete; }
135};
136
137static GB_ERROR calc_pvp(const CLI& args) {
138    GB_shell    shell;
139    const char *dbname  = args.get_database();
140    GBDATA     *gb_main = GB_open(dbname, "rw");
141    GB_ERROR    error   = NULp;
142
143    if (!gb_main) {
144        error = GB_await_error();
145    }
146    else {
147        if (!error && args.shall_import_tree()) {
148            error = TREE_load_to_db(gb_main, args.get_treeimport_filename(), args.get_treename());
149        }
150        if (!error) {
151            error = PVP_calculate(gb_main, args.get_aliname(), args.get_treename(), args.get_SAI_name());
152        }
153        if (!error && args.shall_delete_tree()) {
154            GB_transaction ta(gb_main);
155
156            GBDATA *gb_tree    = GBT_find_tree(gb_main, args.get_treename());
157            if (gb_tree) error = GB_delete(gb_tree);
158        }
159        if (!error) {
160            error = GB_save_as(gb_main, args.get_database_savename(), "b");
161        }
162
163        GB_close(gb_main);
164    }
165
166    return error;
167}
168
169int main(int argc, char **argv) {
170    GB_ERROR error = NULp;
171    CLI      args(argc, const_cast<const char**>(argv));
172
173    if (!error) error = args.get_error();
174
175    if (!error && args.help_wanted()) {
176        args.show_help_if_useful();
177        return EXIT_FAILURE;
178    }
179
180    if (!error) error = calc_pvp(args);
181
182    if (error) {
183        args.show_help_if_useful();
184        fprintf(stderr, "Error in arb_calc_pvp: %s\n", error);
185        return EXIT_FAILURE;
186    }
187    return EXIT_SUCCESS;
188}
Note: See TracBrowser for help on using the repository browser.