CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
casm_functions.cc
Go to the documentation of this file.
2 #include "casm/clex/PrimClex.hh"
4 #include "casm/external/gzstream/gzstream.h"
6 
7 namespace CASM {
8 
19  char *_argv[],
20  PrimClex *_primclex,
21  fs::path _root,
22  const Logging &_logging) :
23  Logging(_logging),
24  argc(_argc),
25  argv(_argv),
26  primclex(_primclex),
27  root(_root),
28  log(Logging::log()),
30  parse_result(0),
31  m_free_p(false) {
32  _init();
33  }
34 
43  CommandArgs::CommandArgs(std::string _args,
44  PrimClex *_primclex,
45  fs::path _root,
46  const Logging &_logging) :
47  Logging(_logging),
48  primclex(_primclex),
49  root(_root),
50  log(Logging::log()),
51  err_log(Logging::err_log()) {
52 
53  // parse _args -> argc, argv
54  parse_result = wordexp(_args.c_str(), &m_p, 0);
55  if(parse_result) {
56  err_log << "Error parsing query: '" << _args << "'" << std::endl;
57  err_log << "wordexp() error: " << parse_result << std::endl;
58  switch(parse_result) {
59  case 1: {
60  err_log << "Check for illegal unescaped characters: |, &, ;, <, >, (, ), {, }" << std::endl;
61  break;
62  }
63  default: {
64  err_log << "Check 'man wordexp' for error code meaning" << std::endl;
65  }
66  }
67  return;
68  }
69 
70  m_free_p = true;
71  argc = m_p.we_wordc;
72  argv = m_p.we_wordv;
73 
74  _init();
75  }
76 
78  if(m_free_p) {
79  wordfree(&m_p);
80  }
81  }
82 
84 
85  // set project 'root' if not already set
86  if(root.empty()) {
87  root = find_casmroot(fs::current_path());
88  }
89 
90  // set 'command'
91  command = (argc > 1) ? std::string(argv[1]) : "";
92 
93  // check if 'help' command
94  std::vector<std::string> help_commands {
95  "help",
96  "-h",
97  "--help",
98  "version",
99  "--version",
100  "status",
101  "format"
102  };
103  is_help = contains(help_commands, command);
104 
105  // check if LOG should be written
106  write_log = !(is_help || root.empty() || command == "init");
107 
108  }
109 
112  static CommandMap command_map {
113  {"version", version_command},
114  {"--version", version_command},
115  {"status", status_command},
116  {"format", format_command},
117  {"init", init_command},
118  {"settings", settings_command},
119  {"sym", sym_command},
120  {"composition", composition_command},
121  {"ref", ref_command},
122  {"update", update_command},
123  {"enum", enum_command},
124  {"super", super_command},
125  {"select", select_command},
126  {"bset", bset_command},
127  {"perturb", perturb_command},
128  {"run", run_command},
129  {"rm", rm_command},
130  {"query", query_command},
131  {"files", files_command},
132  {"import", import_command},
133  {"monte", monte_command},
134  {"view", view_command},
135  {"help", help_command}
136  };
137 
138  return command_map;
139  }
140 
141  namespace api_impl {
142 
143  std::string date_time() {
144  auto t = std::time(nullptr);
145  char str[255];
146  strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
147  return std::string(str);
148  };
149 
150  void write_LOG_begin(const CommandArgs &args) {
151 
152  // If not a 'version', or 'help' command, write to LOG
153  fs::ofstream log(args.root / "LOG", std::ofstream::out | std::ofstream::app);
154  log << "# " << date_time() << std::endl;
155 
156  // record whoami@hostname
157 
158  std::string whoami, hostname;
159  {
160  FILE *fp;
161  char path[PATH_MAX];
162  fp = popen("whoami", "r");
163  while(fgets(path, PATH_MAX, fp) != NULL) {
164  whoami = std::string(path);
165  whoami.resize(whoami.size() - 1);
166  }
167  }
168  {
169  FILE *fp;
170  char path[PATH_MAX];
171  fp = popen("hostname", "r");
172  while(fgets(path, PATH_MAX, fp) != NULL) {
173  hostname = std::string(path);
174  hostname.resize(hostname.size() - 1);
175  }
176  }
177  log << "# " << whoami << "@" << hostname << "\n";
178 
179  // record CASM version number
180  log << "# " << version() << "\n";
181 
182  // record command arguments
183  for(int i = 0; i < args.argc; i++) {
184  log << args.argv[i] << " ";
185  }
186  log << "\n";
187  log.close();
188  }
189 
190  void write_LOG_end(const CommandArgs &args, int retcode) {
191  fs::ofstream log(args.root / "LOG", std::ofstream::out | std::ofstream::app);
192  log << "# return: " << retcode << " runtime(s): " << args.log.time_s() << "\n\n";
193  log.close();
194  }
195 
196  }
197 
199  int casm_api(const CommandArgs &args) {
200 
201  if(args.argc == 1) {
202  help_command(args);
203  return ERR_INVALID_ARG;
204  }
205 
206  auto it = command_map().find(args.command);
207  if(it != command_map().end()) {
208 
209  if(args.write_log) {
211  }
212 
213  args.log.restart_clock();
214  int retcode = it->second(args);
215  if(args.write_log) {
216  api_impl::write_LOG_end(args, retcode);
217  }
218  return retcode;
219  }
220  else {
221  help_command(args);
222  return ERR_INVALID_ARG;
223  }
224  }
225 
226  /*
228  int casm_api(const CommandArgs &args, fs::path working_dir) {
229  fs::path prev = fs::current_path();
230  fs::current_path(working_dir);
231  int res;
232 
233  try {
234  res = casm_api(args);
235  }
236  catch(...) {
237  fs::current_path(prev);
238  throw;
239  }
240  return res;
241  }
242  */
243 
244 
245 
255  PrimClex &make_primclex_if_not(const CommandArgs &args, std::unique_ptr<PrimClex> &uniq_primclex) {
256  return make_primclex_if_not(args, uniq_primclex, args.log);
257  }
258 
269  PrimClex &make_primclex_if_not(const CommandArgs &args, std::unique_ptr<PrimClex> &uniq_primclex, Log &status_log) {
270  if(!args.primclex) {
271  uniq_primclex.reset(new PrimClex(args.root, status_log));
272  return *uniq_primclex;
273  }
274  return *args.primclex;
275  }
276 
287  std::ostream &make_ostream_if(bool output, std::ostream &sout, std::unique_ptr<std::ostream> &fout, fs::path out_path, bool gzip) {
288 
289  if(output) {
290  if(out_path.string() == "STDOUT") {
291  return sout;
292  }
293 
294  out_path = fs::absolute(out_path);
295 
296  if(gzip) {
297  fout.reset(new gz::ogzstream(out_path.string().c_str()));
298  return *fout;
299  }
300 
301  fout.reset(new fs::ofstream(out_path));
302  return *fout;
303  }
304  else {
305  return sout;
306  }
307 
308  }
309 
311  int help_command(const CommandArgs &args) {
312  args.log.custom("casm usage");
313  args.log << "\n";
314 
315  args.log << "casm [--version] <command> [options] [args]" << std::endl << std::endl;
316  args.log << "available commands:" << std::endl;
317 
318  std::vector<std::string> subcom;
319  for(auto it = command_map().begin(); it != command_map().end(); ++it) {
320  std::string s = it->first;
321  // check for --version
322  if(s[0] != '-') {
323  subcom.push_back(std::string(" ") + s);
324  }
325  }
326 
327  std::sort(subcom.begin(), subcom.end());
328  for(auto it = subcom.begin(); it != subcom.end(); ++it) {
329  args.log << *it << "\n";
330  }
331  args.log << "\n";
332 
333  args.log << "For help using a command: 'casm <command> --help'" << std::endl << std::endl;
334  args.log << "For step by step help use: 'casm status -n'" << std::endl << std::endl;
335 
336  return 0;
337  };
338 
339  int version_command(const CommandArgs &args) {
340  args.log << "casm version: " << version() << std::endl;
341  return 0;
342  }
343 
344 
345 
346 
347 }
Data structure holding basic CASM command info.
int update_command(const CommandArgs &args)
Definition: update.cc:62
int enum_command(const CommandArgs &args)
Definition: enum.cc:51
std::string date_time()
#define ERR_INVALID_ARG
int rm_command(const CommandArgs &args)
Definition: rm.cc:44
PrimClex * primclex
Definition: settings.cc:101
int select_command(const CommandArgs &args)
Definition: select.cc:168
int files_command(const CommandArgs &args)
Definition: files.cc:47
int view_command(const CommandArgs &args)
Definition: view.cc:26
~CommandArgs()
CommandArgs destructor.
Main CASM namespace.
Definition: complete.cpp:8
int init_command(const CommandArgs &args)
Definition: init.cc:28
Log & log
Definition: settings.cc:105
bool m_free_p
Used when parsing std::string args -> argc, argv.
fs::path find_casmroot(const fs::path &cwd)
int super_command(const CommandArgs &args)
Definition: super.cc:103
int query_command(const CommandArgs &args)
Definition: query.cc:81
void custom(const std::string &what)
Definition: Log.hh:96
CommandMap & command_map()
Return static CommandMap containing all CASM API commands.
int import_command(const CommandArgs &args)
Definition: import.cc:95
int status_command(const CommandArgs &args)
Definition: status.cc:389
double time_s() const
Definition: Log.cc:21
int run_command(const CommandArgs &args)
Definition: run.cc:35
int bset_command(const CommandArgs &args)
Definition: bset.cc:36
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:52
int monte_command(const CommandArgs &args)
Definition: monte.cc:106
int ref_command(const CommandArgs &args)
Definition: ref.cc:161
CommandArgs(int _argc, char *_argv[], PrimClex *_primclex, fs::path _root, const Logging &logging)
CommandArgs constructor.
std::map< std::string, Command > CommandMap
std::ostream & make_ostream_if(bool output, std::ostream &sout, std::unique_ptr< std::ostream > &fout, fs::path out_path, bool gzip)
Return a reference to proper std::ostream.
int perturb_command(const CommandArgs &args)
Definition: perturb.cc:35
int help_command(const CommandArgs &args)
Print CASM help info to args.log.
void write_LOG_end(const CommandArgs &args, int retcode)
PrimClex & make_primclex_if_not(const CommandArgs &args, std::unique_ptr< PrimClex > &uniq_primclex)
If !_primclex, construct new PrimClex stored in uniq_primclex, then return reference to existing or c...
int sym_command(const CommandArgs &args)
Definition: sym.cc:32
int version_command(const CommandArgs &args)
int format_command(const CommandArgs &args)
Definition: format.cc:44
Log & err_log
Definition: settings.cc:106
const std::string & version()
Definition: autoversion.cc:14
Definition: Log.hh:9
int parse_result
stores error codes when attempting to parse std::string _args -> argc, argv
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value) ...
Definition: algorithm.hh:66
void restart_clock()
Definition: Log.cc:9
int settings_command(const CommandArgs &args)
Definition: settings.cc:257
void write_LOG_begin(const CommandArgs &args)
Log & err_log() const
Definition: Log.hh:263
int casm_api(const CommandArgs &args)
Executes CASM commands specified by args.
int composition_command(const CommandArgs &args)
Definition: composition.cc:69