File: main.cpp

package info (click to toggle)
gemmi 0.6.5%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 5,836 kB
  • sloc: cpp: 54,719; python: 4,743; ansic: 3,972; sh: 384; makefile: 73; f90: 42; javascript: 12
file content (195 lines) | stat: -rw-r--r-- 6,541 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// Copyright 2018 Global Phasing Ltd.
// Entry point for gemmi utility built as a single program with subcommands.

#include <stdio.h>
#include <cstring>

void print_version(const char* program_name, bool verbose);  // in options.h

int blobs_main(int argc, char** argv);
int cif2mtz_main(int argc, char** argv);
int cif2json_main(int argc, char** argv);
int cifdiff_main(int argc, char** argv);
int contact_main(int argc, char** argv);
int contents_main(int argc, char** argv);
int convert_main(int argc, char** argv);
int crd_main(int argc, char** argv);
int ecalc_main(int argc, char** argv);
int fprime_main(int argc, char** argv);
int grep_main(int argc, char** argv);
int h_main(int argc, char** argv);
int json2cif_main(int argc, char** argv);
int map_main(int argc, char** argv);
int map2sf_main(int argc, char** argv);
int mask_main(int argc, char** argv);
int merge_main(int argc, char** argv);
int mondiff_main(int argc, char** argv);
int mtz_main(int argc, char** argv);
int mtz2cif_main(int argc, char** argv);
int reindex_main(int argc, char** argv);
int residues_main(int argc, char** argv);
int rmsz_main(int argc, char** argv);
int align_main(int argc, char** argv);
int sf2map_main(int argc, char** argv);
int sfcalc_main(int argc, char** argv);
int sg_main(int argc, char** argv);
int tags_main(int argc, char** argv);
int validate_main(int argc, char** argv);
int wcn_main(int argc, char** argv);
int xds2mtz_main(int argc, char** argv);

namespace {

typedef int (*main_type)(int argc, char** argv);

struct SubCmd {
  const char* cmd;
  main_type func;
  const char* desc;
};

#define CMD(s, desc) { #s, &s##_main, desc }
static SubCmd subcommands[] = {
  CMD(align, "sequence alignment (global, pairwise, affine gap penalty)"),
  CMD(blobs, "list unmodelled electron density blobs"),
  CMD(cif2mtz, "convert structure factor mmCIF to MTZ"),
  CMD(cif2json, "translate (mm)CIF to (mm)JSON"),
  CMD(cifdiff, "compare tags in two (mm)CIF files"),
  CMD(contact, "searches for contacts (neighbouring atoms)"),
  CMD(contents, "info about content of a coordinate file (pdb, mmCIF, ...)"),
  CMD(convert, "convert file (CIF - JSON, mmCIF - PDB) or modify structure"),
  CMD(crd, "prepare topology file (.crd) for Refmac"),
  CMD(ecalc, "calculate normalized amplitudes E"),
  CMD(fprime, "calculate anomalous scattering factors f' and f\""),
  CMD(grep, "search for tags in CIF file(s)"),
  CMD(h, "add or remove hydrogen atoms"),
  CMD(json2cif, "translate mmJSON to mmCIF"),
  CMD(map, "print info or modify a CCP4 map"),
  CMD(map2sf, "transform CCP4 map to map coefficients (in MTZ or mmCIF)"),
  CMD(mask, "make a bulk-solvent mask in the CCP4 format"),
  CMD(merge, "merge intensities from multi-record reflection file"),
  CMD(mondiff, "compare two monomer CIF files"),
  CMD(mtz, "print info about MTZ reflection file"),
  CMD(mtz2cif, "convert MTZ to structure factor mmCIF"),
  CMD(reindex, "reindex MTZ file"),
  CMD(residues, "list residues from a coordinate file"),
  CMD(rmsz, "validate geometry using monomer library"),
  CMD(sf2map, "transform map coefficients (from MTZ or mmCIF) to map"),
  CMD(sfcalc, "calculate structure factors from a model"),
  CMD(sg, "info about space groups"),
  CMD(tags, "list tags from CIF file(s)"),
  CMD(validate, "validate CIF 1.1 syntax"),
  CMD(wcn, "calculate local density / contact numbers (WCN, CN, ACN, LDM)"),
  CMD(xds2mtz, "convert XDS_ASCII to MTZ"),
};

void print_usage() {
  print_version("gemmi", /*verbose=*/false);
  printf("Command-line utility that accompanies the GEMMI library,\n"
         "which is a joint project of CCP4 and Global Phasing Ltd.\n"
         "Licence: Mozilla Public License 2.0. Copyright Global Phasing Ltd.\n"
         "https://github.com/project-gemmi/gemmi\n\n"
         "Usage: gemmi [--version] [--help] <command> [<args>]\n\n"
         "Commands:\n");
  for (SubCmd& sub : subcommands)
    printf(" %-13s %s\n", sub.cmd, sub.desc);
}

bool eq(const char* a, const char* b) { return std::strcmp(a, b) == 0; }

main_type get_subcommand_function(const char* cmd) {
  for (SubCmd& sub : subcommands)
    if (eq(cmd, sub.cmd))
      return sub.func;
  return nullptr;
}

} // anonymous namespace

#if defined(_WIN32) && defined(_UNICODE)
#include <vector>
#include "gemmi/utf.hpp"

extern "C"
int wmain(int argc, wchar_t** argv_)
#else
int main(int argc, char** argv)
#endif
{
  if (argc < 2) {
    print_usage();
    return 1;
  }
#if defined(_WIN32) && defined(_UNICODE)
  std::vector<std::string> utf8_args(argc);
  std::vector<char*> argv(argc);
  for (int i = 0; i < argc; ++i) {
    utf8_args[i] = gemmi::wchar_to_UTF8(argv_[i]);
    argv[i] = &utf8_args[i][0];
  }
#endif
  bool verbose = false;
  bool version = false;
  bool help = false;
  int command = 0;
  int wrong_option = 0;
  for (int i = 1; i < argc && wrong_option == 0; ++i) {
    const char* arg = argv[i];
    if (arg[0] == '-' && arg[1] == '-') {          // long options
      if (eq(arg+2, "version"))
        version = true;
      else if (eq(arg+2, "help"))
        help = true;
      else if (eq(arg+2, "verbose"))
        verbose = true;
      else
        wrong_option = i;
    } else if (arg[0] == '-' && arg[1] != '-') {   // short options
      for (int j = 1; arg[j] != '\0'; ++j) {
        if (arg[j] == 'V')
          version = true;
        else if (arg[j] == 'h')
          help = true;
        else if (arg[j] == 'v')
          verbose = true;
        else
          wrong_option = i;
      }
    } else {                                       // not options
      if (eq(arg, "help")) {
        help = true;
      } else if (eq(arg, "version")) {
        version = true;
      } else {
        command = i;
        break;
      }
    }
  }
  if (wrong_option != 0) {
    printf("Invalid option '%s'. See 'gemmi --help'.\n", argv[wrong_option]);
    return 1;
  }
  if (version) {
    print_version("gemmi", verbose);
    return 0;
  }
  if (command == 0) {  // handles both "gemmi" and "gemmi --help"
    print_usage();
    return 0;
  }
  // call function
  main_type func = get_subcommand_function(argv[command]);
  if (!func) {
    printf("'%s' is not a gemmi command. See 'gemmi --help'.\n", argv[command]);
    return 1;
  }
  if (verbose)
    printf("Note: Option -v/--verbose before subcommand has no effect.\n");
  if (help) {  // if we are here, command != 0
    char help_str[] = "--help";
    char* args[] = { argv[0], argv[command], help_str };
    return (*func)(3, args);
  }
  return (*func)(argc - command, &argv[command]);
}