diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c index d6c39d082..df17a5518 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c @@ -152,12 +152,12 @@ int main(int argc, char *argv[]) { strcpy(version, APIXILINXCTB); #endif LOG(logINFO, ("SLS Detector Server Version: %s\n", version)); - exit(EXIT_SUCCESS); + return EXIT_SUCCESS; case 'p': if (sscanf(optarg, "%d", &portno) != 1) { LOG(logERROR, ("Cannot scan port argument\n%s", helpMessage)); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } LOG(logINFO, ("Detected port: %d\n", portno)); break; @@ -188,7 +188,7 @@ int main(int argc, char *argv[]) { ignoreConfigFileFlag = 1; #else LOG(logERROR, ("No server config files for this detector\n")); - exit(EXIT_FAILURE); + return EXIT_FAILURE; #endif break; @@ -196,11 +196,11 @@ int main(int argc, char *argv[]) { #if !defined(VIRTUAL) && !defined(EIGERD) LOG(logERROR, ("Cannot set master via the detector server for this " "detector\n")); - exit(EXIT_FAILURE); + return EXIT_FAILURE; #elif defined(GOTTHARD2D) || defined(EIGERD) || defined(MYTHEN3D) if (sscanf(optarg, "%d", &masterCommandLine) != 1) { LOG(logERROR, ("Cannot scan master argument\n%s", helpMessage)); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } if (masterCommandLine == 1) { LOG(logINFO, ("Detector Master mode\n")); @@ -209,7 +209,7 @@ int main(int argc, char *argv[]) { } #else LOG(logERROR, ("No master implemented for this detector server\n")); - exit(EXIT_FAILURE); + return EXIT_FAILURE; #endif break; @@ -217,7 +217,7 @@ int main(int argc, char *argv[]) { #ifdef EIGERD if (sscanf(optarg, "%d", &topCommandLine) != 1) { LOG(logERROR, ("Cannot scan top argument\n%s", helpMessage)); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } if (topCommandLine == 1) { LOG(logINFO, ("Detector Top mode\n")); @@ -226,16 +226,16 @@ int main(int argc, char *argv[]) { } #else LOG(logERROR, ("No top implemented for this detector server\n")); - exit(EXIT_FAILURE); + return EXIT_FAILURE; #endif break; case 'h': printf("%s", helpMessage); - exit(EXIT_SUCCESS); + return EXIT_SUCCESS; default: printf("\n%s", helpMessage); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } } @@ -376,5 +376,5 @@ int main(int argc, char *argv[]) { #endif } LOG(logINFO, ("Goodbye!\n")); - return 0; + return EXIT_SUCCESS; } diff --git a/slsDetectorSoftware/src/CmdApp.cpp b/slsDetectorSoftware/src/CmdApp.cpp index facb584a8..946b4f9c2 100644 --- a/slsDetectorSoftware/src/CmdApp.cpp +++ b/slsDetectorSoftware/src/CmdApp.cpp @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) { c.call(parser.command(), parser.arguments(), parser.detector_id(), action, std::cout, parser.receiver_id()); } catch (sls::RuntimeError &e) { - exit(EXIT_FAILURE); + return EXIT_FAILURE; } - exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } \ No newline at end of file diff --git a/slsReceiverSoftware/CMakeLists.txt b/slsReceiverSoftware/CMakeLists.txt index 543ff7467..46d80970b 100755 --- a/slsReceiverSoftware/CMakeLists.txt +++ b/slsReceiverSoftware/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES src/Arping.cpp src/MasterAttributes.cpp src/MasterFileUtility.cpp + src/CommandLineOptions.cpp ) set(PUBLICHEADERS @@ -51,6 +52,10 @@ target_link_libraries(slsReceiverObject slsProjectWarnings #don't propagate warnigns ) +target_compile_definitions(slsReceiverObject + PRIVATE $<$:SLS_USE_TESTS> +) + # HDF5 if (SLS_USE_HDF5) if (HDF5_FOUND) @@ -86,6 +91,7 @@ set_target_properties(slsReceiverStatic PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin PUBLIC_HEADER "${PUBLICHEADERS}" ) + list(APPEND RECEIVER_LIBRARY_TARGETS slsReceiverStatic) diff --git a/slsReceiverSoftware/include/sls/Receiver.h b/slsReceiverSoftware/include/sls/Receiver.h index eb7c4b214..0a3a83482 100644 --- a/slsReceiverSoftware/include/sls/Receiver.h +++ b/slsReceiverSoftware/include/sls/Receiver.h @@ -13,22 +13,12 @@ class Receiver : private virtual slsDetectorDefs { public: /** * Constructor - * Starts up a Receiver server. Reads configuration file, options, and - * assembles a Receiver using TCP and UDP detector interfaces + * Starts up a Receiver server. + * Assembles a Receiver using TCP and UDP detector interfaces * throws an exception in case of failure - * @param argc from command line - * @param argv from command line + * @param port TCP/IP port number */ - Receiver(int argc, char *argv[]); - - /** - * Constructor - * Starts up a Receiver server. Reads configuration file, options, and - * assembles a Receiver using TCP and UDP detector interfaces - * throws an exception in case of failure - * @param tcpip_port_no TCP/IP port number - */ - Receiver(uint16_t tcpip_port_no = 1954); + Receiver(uint16_t port = 1954); ~Receiver(); diff --git a/slsReceiverSoftware/src/CommandLineOptions.cpp b/slsReceiverSoftware/src/CommandLineOptions.cpp new file mode 100644 index 000000000..517b591fd --- /dev/null +++ b/slsReceiverSoftware/src/CommandLineOptions.cpp @@ -0,0 +1,347 @@ +// 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; + + while ((opt = getopt_long(argc, argv, optString_.c_str(), + longOptions_.data(), &option_index)) != -1) { + switch (opt) { + case 'v': + case 'h': + handleCommonOption(opt, optarg, base); + return base; // exit after version/help + 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 (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 + 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