// SPDX-License-Identifier: LGPL-3.0-or-other // Copyright (C) 2021 Contributors to the SLS Detector Package #include "CommandLineOptions.h" #include "sls/ToString.h" #include "sls/logger.h" #include "sls/sls_detector_defs.h" #include "sls/versionAPI.h" #include #include CommandLineOptions::CommandLineOptions(AppType app) : appType_(app), optString_(buildOptString()), longOptions_(buildOptionList()) {} /** for testing */ ParsedOptions CommandLineOptions::parse(const std::vector &args) { std::vector argv; argv.reserve(args.size()); for (const auto &arg : args) { argv.push_back(const_cast(arg.c_str())); } int argc = static_cast(argv.size()); return parse(argc, argv.data()); } ParsedOptions CommandLineOptions::parse(int argc, char *argv[]) { CommonOptions base; MultiReceiverOptions multi; FrameSyncOptions frame; base.port = DEFAULT_TCP_RX_PORTNO; optind = 0; // reset getopt int opt, option_index = 0; bool help_or_version_requested = false; while ((opt = getopt_long(argc, argv, optString_.c_str(), longOptions_.data(), &option_index)) != -1) { switch (opt) { case 'v': case 'h': handleCommonOption(opt, optarg, base); help_or_version_requested = true; break; case 'p': case 'u': handleCommonOption(opt, optarg, base); break; case 'c': case 'n': case 't': handleAppSpecificOption(opt, optarg, base, multi, frame); break; default: throw sls::RuntimeError("Invalid arguments." + getHelpMessage()); } } // remaining arguments if (!help_or_version_requested && optind < argc) { // deprecated and current options => invalid if (base.port != DEFAULT_TCP_RX_PORTNO || multi.numReceivers != 1 || frame.numReceivers != 1 || multi.callbackEnabled != false || frame.printHeaders != false) { LOG(sls::logWARNING) << "Cannot use both deprecated options and " "the valid options simultaneously. Please " "move away from the deprecated options.\n"; } // unsupported deprecated arguments if (appType_ == AppType::SingleReceiver) { throw sls::RuntimeError("Invalid arguments." + getHelpMessage()); } // parse deprecated arguments std::vector args(argv, argv + argc); auto [p, n, o] = ParseDeprecated(args); // set options base.port = p; if (appType_ == AppType::MultiReceiver) { multi.numReceivers = n; multi.callbackEnabled = o; } else if (appType_ == AppType::FrameSynchronizer) { frame.numReceivers = n; frame.printHeaders = o; } } // Logging if (!help_or_version_requested) { LOG(sls::logINFO) << "TCP Port: " << base.port; if (appType_ == AppType::MultiReceiver) { LOG(sls::logINFO) << "Number of receivers: " << multi.numReceivers; LOG(sls::logINFO) << "Callback enabled: " << multi.callbackEnabled; } else if (appType_ == AppType::FrameSynchronizer) { LOG(sls::logINFO) << "Number of receivers: " << frame.numReceivers; LOG(sls::logINFO) << "Print headers: " << frame.printHeaders; } } switch (appType_) { case AppType::SingleReceiver: return base; case AppType::MultiReceiver: static_cast(multi) = base; return multi; case AppType::FrameSynchronizer: static_cast(frame) = base; return frame; default: throw sls::RuntimeError("Unknown AppType in CommandLineOptions::parse"); } } std::vector