in compiler/cpp/src/thrift/main.cc [1077:1312]
int main(int argc, char** argv) {
int i;
std::string out_path;
bool out_path_is_absolute = false;
// Setup time string
time_t now = time(nullptr);
g_time_str = ctime(&now);
// Check for necessary arguments, you gotta have at least a filename and
// an output language flag
if (argc < 2) {
usage();
}
vector<string> generator_strings;
string old_thrift_include_path;
string new_thrift_include_path;
string old_input_file;
// Set the current path to a dummy value to make warning messages clearer.
g_curpath = "arguments";
// Hacky parameter handling... I didn't feel like using a library sorry!
for (i = 1; i < argc - 1; i++) {
char* arg;
arg = strtok(argv[i], " ");
while (arg != nullptr) {
// Treat double dashes as single dashes
if (arg[0] == '-' && arg[1] == '-') {
++arg;
}
if (strcmp(arg, "-help") == 0) {
help();
} else if (strcmp(arg, "-version") == 0) {
version();
exit(0);
} else if (strcmp(arg, "-debug") == 0) {
g_debug = 1;
} else if (strcmp(arg, "-nowarn") == 0) {
g_warn = 0;
} else if (strcmp(arg, "-strict") == 0) {
g_strict = 255;
g_warn = 2;
} else if (strcmp(arg, "-v") == 0 || strcmp(arg, "-verbose") == 0) {
g_verbose = 1;
} else if (strcmp(arg, "-r") == 0 || strcmp(arg, "-recurse") == 0) {
gen_recurse = true;
} else if (strcmp(arg, "-allow-neg-keys") == 0) {
g_allow_neg_field_keys = true;
} else if (strcmp(arg, "-allow-64bit-consts") == 0) {
g_allow_64bit_consts = true;
} else if (strcmp(arg, "-gen") == 0) {
arg = argv[++i];
if (arg == nullptr) {
fprintf(stderr, "Missing generator specification\n");
usage();
}
generator_strings.emplace_back(arg);
} else if (strcmp(arg, "-I") == 0) {
// An argument of "-I\ asdf" is invalid and has unknown results
arg = argv[++i];
if (arg == nullptr) {
fprintf(stderr, "Missing Include directory\n");
usage();
}
g_incl_searchpath.emplace_back(arg);
} else if ((strcmp(arg, "-o") == 0) || (strcmp(arg, "-out") == 0)) {
out_path_is_absolute = (strcmp(arg, "-out") == 0) ? true : false;
arg = argv[++i];
if (arg == nullptr) {
fprintf(stderr, "-o: missing output directory\n");
usage();
}
out_path = arg;
#ifdef _WIN32
// strip out trailing \ on Windows
std::string::size_type last = out_path.length() - 1;
if (out_path[last] == '\\') {
out_path.erase(last);
}
#endif
if (!check_is_directory(out_path.c_str()))
return -1;
} else if (strcmp(arg, "-audit") == 0) {
g_audit = true;
arg = argv[++i];
if (arg == nullptr) {
fprintf(stderr, "Missing old thrift file name for audit operation\n");
usage();
}
char old_thrift_file_rp[THRIFT_PATH_MAX];
// cppcheck-suppress uninitvar
if (saferealpath(arg, old_thrift_file_rp) == nullptr) {
failure("Could not open input file with realpath: %s", arg);
}
old_input_file = string(old_thrift_file_rp);
} else if (strcmp(arg, "-audit-nofatal") == 0) {
g_audit_fatal = false;
} else if (strcmp(arg, "-Iold") == 0) {
arg = argv[++i];
if (arg == nullptr) {
fprintf(stderr, "Missing Include directory for old thrift file\n");
usage();
}
old_thrift_include_path = string(arg);
} else if (strcmp(arg, "-Inew") == 0) {
arg = argv[++i];
if (arg == nullptr) {
fprintf(stderr, "Missing Include directory for new thrift file\n");
usage();
}
new_thrift_include_path = string(arg);
} else {
fprintf(stderr, "Unrecognized option: %s\n", arg);
usage();
}
// Tokenize more
arg = strtok(nullptr, " ");
}
}
// display help
if ((strcmp(argv[argc - 1], "-help") == 0) || (strcmp(argv[argc - 1], "--help") == 0)) {
help();
}
// if you're asking for version, you have a right not to pass a file
if ((strcmp(argv[argc - 1], "-version") == 0) || (strcmp(argv[argc - 1], "--version") == 0)) {
version();
exit(0);
}
// Initialize global types
initGlobals();
if (g_audit) {
// Audit operation
if (old_input_file.empty()) {
fprintf(stderr, "Missing file name of old thrift file for audit\n");
usage();
}
char new_thrift_file_rp[THRIFT_PATH_MAX];
if (argv[i] == nullptr) {
fprintf(stderr, "Missing file name of new thrift file for audit\n");
usage();
}
// cppcheck-suppress uninitvar
if (saferealpath(argv[i], new_thrift_file_rp) == nullptr) {
failure("Could not open input file with realpath: %s", argv[i]);
}
string new_input_file(new_thrift_file_rp);
t_program new_program(new_input_file);
t_program old_program(old_input_file);
audit(&new_program, &old_program, new_thrift_include_path, old_thrift_include_path);
} else {
// Generate options
// You gotta generate something!
if (generator_strings.empty()) {
fprintf(stderr, "No output language(s) specified\n");
usage();
}
// Real-pathify it
char rp[THRIFT_PATH_MAX];
if (argv[i] == nullptr) {
fprintf(stderr, "Missing file name\n");
usage();
}
// cppcheck-suppress uninitvar
if (saferealpath(argv[i], rp) == nullptr) {
failure("Could not open input file with realpath: %s", argv[i]);
}
string input_file(rp);
// Instance of the global parse tree
t_program* program = new t_program(input_file);
if (out_path.size()) {
program->set_out_path(out_path, out_path_is_absolute);
}
// Compute the cpp include prefix.
// infer this from the filename passed in
string input_filename = argv[i];
string include_prefix;
string::size_type last_slash = string::npos;
if ((last_slash = input_filename.rfind("/")) != string::npos) {
include_prefix = input_filename.substr(0, last_slash);
}
program->set_include_prefix(include_prefix);
// Parse it!
std::set<std::string> known_includes;
parse(program, nullptr, known_includes);
// The current path is not really relevant when we are doing generation.
// Reset the variable to make warning messages clearer.
g_curpath = "generation";
// Reset yylineno for the heck of it. Use 1 instead of 0 because
// That is what shows up during argument parsing.
yylineno = 1;
// Generate it!
generate(program, generator_strings);
delete program;
}
// Clean up. Who am I kidding... this program probably orphans heap memory
// all over the place, but who cares because it is about to exit and it is
// all referenced and used by this wacky parse tree up until now anyways.
clearGlobals();
// Finished
if (g_return_failure && g_audit_fatal) {
exit(2);
}
if (g_generator_failure) {
exit(3);
}
// Finished
return 0;
}