ARB
arb_calc_pvp.cxx
Go to the documentation of this file.
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 
15 using namespace std;
16 
17 class CLI : virtual Noncopyable {
18  bool helpWanted;
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 
106 public:
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 
137 static 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 
169 int 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 }
#define arb_assert(cond)
Definition: arb_assert.h:245
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
static void show_help()
Definition: db_server.cxx:242
const char * get_SAI_name() const
const char * get_treename() const
GB_ERROR TREE_load_to_db(GBDATA *gb_main, const char *treefile, const char *tree_name)
Definition: TreeRead.cxx:701
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
STL namespace.
#define EXIT_SUCCESS
Definition: arb_a2ps.c:154
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1916
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
GB_ERROR GB_save_as(GBDATA *gbd, const char *path, const char *savetype)
#define false
Definition: ureadseq.h:13
#define FIXED_ARGS_WANTED
static void error(const char *msg)
Definition: mkptypes.cxx:96
const char * get_database() const
GB_ERROR PVP_calculate(GBDATA *gb_main, const char *ali_name, const char *tree_name, const char *target_SAI_name)
Definition: pvp.cxx:17
#define EXIT_FAILURE
Definition: arb_a2ps.c:157
bool shall_delete_tree() const
const char * get_aliname() const
void show_help_if_useful() const
fputs(TRACE_PREFIX, stderr)
const char * get_treeimport_filename() const
const char * get_database_savename() const
CLI(int argc, const char **argv)
int main(int argc, char **argv)
bool help_wanted() const
#define NULp
Definition: cxxforward.h:116
GBDATA * GBT_find_tree(GBDATA *gb_main, const char *tree_name)
Definition: adtree.cxx:993
GB_transaction ta(gb_var)
GBDATA * gb_main
Definition: adname.cxx:32
bool shall_import_tree() const
static GB_ERROR calc_pvp(const CLI &args)
GB_ERROR get_error() const
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655