LCOV - code coverage report
Current view: top level - otsdaq-mu2e-tracker/tools - otsdaq_import_tracker_test_stand.cc (source / functions) Coverage Total Hit
Test: mu2edaq.info.cleaned Lines: 0.0 % 805 0
Test Date: 2026-09-10 01:53:42 Functions: 0.0 % 125 0

            Line data    Source code
       1              : #include "otsdaq/MessageFacility/MessageFacility.h"
       2              : 
       3              : #include <dirent.h>
       4              : #include <cassert>
       5              : #include <fstream>
       6              : #include <iostream>
       7              : #include <memory>
       8              : #include <string>
       9              : 
      10              : #include "otsdaq/Macros/StringMacros.h"
      11              : 
      12              : // Shared test utilities
      13              : #include "otsdaq/Macros/TestUtilities.h"
      14              : 
      15              : ///
      16              : /// @file otsdaq_import_tracker_test_stand.cc
      17              : /// @brief
      18              : /// Extracts the function definitions in the tracker Ui folder into
      19              : ///             the otsdaq-mu2e-tracker/otsdaq-mu2e-tracker/FEInterfaces/ folder (or any folder)
      20              : ///
      21              : ///     Warning! it will overwrite files in the output folder with the same names!
      22              : ///
      23              : /// usage:
      24              : /// otsdaq_import_tracker_test_stand <import Ui path> <export FEInterface path>
      25              : ///
      26              : /// Created by rrivera, December 2025
      27              : ///
      28              : 
      29              : using namespace ots;
      30              : 
      31              : //==============================================================================
      32              : /// @brief Modifies the source code string for the FEInterface as follows:
      33              : ///             - Replaces instances of the fDtc with getDTC()
      34              : /// @param source the source code to modify
      35              : /// @param isHeader whether the source is a header file
      36              : /// @param outputFile
      37            0 : std::string modifySource(std::string& source, bool isHeader = false)
      38              : {
      39              :         std::vector<std::pair<std::string, std::string>> replacements = {
      40              :             {"fDtc", "getDTC()"},
      41              :             {"getDTC()ID", "fDtcID"},  // fix accidental replacement of member variable
      42              : 
      43              :             {"TrkSpiData_t", "trkdaq::TrkSpiData_t"},
      44              :             {"roc_data_t", "DTCLib::roc_data_t"},
      45              :             {"DTC_Link_ID", "DTCLib::DTC_Link_ID"},
      46              :             {"DTC_SubEvent", "DTCLib::DTC_SubEvent"},
      47              :             {"DTC_EventWindowTag", "DTCLib::DTC_EventWindowTag"},
      48              :             {"roc_address_t", "DTCLib::roc_address_t"},
      49              :             {"DTC_LinkEnableMode", "DTCLib::DTC_LinkEnableMode"},
      50              :             {"DTC_Link_ALL", "DTCLib::DTC_Link_ALL"},
      51              :             {"EventMode()", "((((int64_t)fOnSpill) << 32) | ((int64_t)fEventMode))"},
      52              :             {"DTC_ROC_Links", "DTCLib::DTC_ROC_Links"},
      53              :             {"ControlRoc_DeviceID_t", "trkdaq::ControlRoc_DeviceID_t"},
      54              :             {"TrkSpiDataNWords", "trkdaq::TrkSpiDataNWords"},
      55              : 
      56              :             // {"RocRegisters", "trkdaq::RocRegisters"},
      57              :             {"trkdaq::RocRegisters", "RocRegisters"},
      58              :             {"Gettrkdaq::RocRegisters", "GetRocRegisters"},  // fix accidental replacement
      59              :             {"GetConvertedtrkdaq::RocRegisters",
      60              :              "GetConvertedRocRegisters"},  // fix accidental replacement
      61              : 
      62              :             {"roc_fw_data_t", "trkdaq::roc_fw_data_t"},
      63              :             {"roc_fw_version_t", "trkdaq::roc_fw_version_t"},
      64              :             {"RocFwData_t", "trkdaq::RocFwData_t"},
      65              :             {"ControlRoc_DigiRW_Input_t", "trkdaq::ControlRoc_DigiRW_Input_t"},
      66              :             {"ControlRoc_DigiRW_Output_t", "trkdaq::ControlRoc_DigiRW_Output_t"},
      67              :             {"ControlRoc_Read_Input_t0", "trkdaq::ControlRoc_Read_Input_t0"},
      68              :             {"ControlRoc_Read_Output_t0", "trkdaq::ControlRoc_Read_Output_t0"},
      69              :             {"ControlRoc_Rates_t", "trkdaq::ControlRoc_Rates_t"},
      70              :             {"REG_", "trkdaq::REG_"},
      71              : 
      72              :             {"trkdaq::REG_STATUS", "REG_STATUS"},
      73              : 
      74              :             {"roc_serial_t", "std::string"},
      75              : 
      76              :             {"vector", "std::vector"},
      77              :             {"string", "std::string"},
      78              :             {"to_std::string", "std::to_string"},  // fix accidental replacement
      79              :             {"ifstream", "std::ifstream"},
      80              :             {"ofstream", "std::ofstream"},
      81              :             {"fstream", "std::fstream"},
      82              :             {"std::istd::fstream", "std::ifstream"},  // fix accidental replacement
      83              :             {"cout", "std::cout"},
      84              :             {"endl", "std::endl"},
      85              :             {"stringstream", "std::stringstream"},
      86              :             {"hex", "std::hex"},
      87              :             {"dec", "std::dec"},
      88              : 
      89              :             {"override", ""},
      90              : 
      91              :             {"trkdaq::trkdaq::", "trkdaq::"},
      92              :             {"std::std::std::", "std::"},
      93              :             {"std::std::", "std::"},
      94              :             {"DTCLib::DTCLib::", "DTCLib::"},
      95            0 :         };
      96              :         std::vector<std::pair<std::string, std::string>> functionReplacements = {
      97              :             {"ConfigureJA", "Ui_base_ConfigureJA"},
      98              :             {"InitEmulatedCFOReadoutMode", "Ui_base_InitEmulatedCFOReadoutMode"},
      99              :             {"InitExternalCFOReadoutMode", "Ui_base_InitExternalCFOReadoutMode"},
     100              :             {"ResetLinks", "Ui_base_ResetLinks"},
     101              :             {"SetLinkMask", "Ui_base_SetLinkMask"},
     102              : 
     103              :             {"ResetLink", "Ui_ResetLink"},
     104              : 
     105              :             {"Ui_base_Ui_ResetLinks", "Ui_base_ResetLinks"},  // fix accidental replacement
     106              : 
     107              :             {"InitReadout", "Ui_InitReadout"},
     108              :             {"InitRocReadoutMode", "Ui_InitRocReadoutMode"},
     109              :             {"LaunchRunPlanEmulatedCfo", "Ui_LaunchRunPlanEmulatedCfo"},
     110              :             {"ReadRegister", "Ui_ReadRegister"},
     111              :             {"ReadSpiData", "Ui_ReadSpiData"},
     112              :             {"RocConfigurePatternMode", "Ui_RocConfigurePatternMode"},
     113              :             {"ResetRoc", "Ui_ResetRoc"},
     114              :             {"RocSetDataVersion", "Ui_RocSetDataVersion"},
     115              :             {"ReadSubevents", "Ui_ReadSubevents"},
     116              :             {"ReadROCBlockEnsured", "Ui_ReadROCBlockEnsured"},
     117              :             {"ReadDeviceID", "Ui_ReadDeviceID"},
     118              :             {"ReadSerialNumber", "Ui_ReadSerialNumber"},
     119              :             {"FindAlignment", "Ui_FindAlignment"},
     120              :             {"FindAlignments", "Ui_FindAlignments"},
     121              :             {"SetBit", "Ui_SetBit"},
     122              :             {"SetupCfoInterface", "Ui_SetupCfoInterface"},
     123              :             {"ValidateDigiPatterns", "Ui_ValidateDigiPatterns"},
     124              :             {"ValidateFixedPatterns", "Ui_ValidateFixedPatterns"},
     125              :             {"ValidateVarPatterns", "Ui_ValidateVarPatterns"},
     126              :             {"MonicaDigiClear", "Ui_MonicaDigiClear"},
     127              :             {"MonicaVarLinkConfig", "Ui_MonicaVarLinkConfig"},
     128              :             {"MonicaVarPatternConfig", "Ui_MonicaVarPatternConfig"},
     129              :             {"GetRocRegisters", "Ui_GetRocRegisters"},
     130              :             {"ProgramAndQueryThreshold", "Ui_ProgramAndQueryThreshold"},
     131              :             {"FindThreshold", "Ui_FindThreshold"},
     132              :             {"RocBlockRead", "Ui_RocBlockRead"},
     133              : 
     134              :             {"PrintBuffer", "Ui_print_PrintBuffer"},
     135              :             {"PrintRocRegister", "Ui_print_PrintRocRegister"},
     136              :             {"PrintRocRegister2", "Ui_print_PrintRocRegister2"},
     137              :             {"Ui_print_Ui_print_", "Ui_print_"},  // fix accidental replacement
     138              : 
     139              :             {"ControlRoc_ReadSpi", "Ui_ControlRoc_ControlRoc_ReadSpi"},
     140              :             {"ConvertSpiData", "Ui_ControlRoc_ConvertSpiData"},
     141              :             {"ControlRoc_Ui_ReadDeviceID", "Ui_ControlRoc_ControlRoc_ReadDeviceID"},
     142              :             {"ControlRoc_ReadGitCommit", "Ui_ControlRoc_ControlRoc_ReadGitCommit"},
     143              :             {"ControlRoc_SetThreshold", "Ui_ControlRoc_ControlRoc_SetThreshold"},
     144              :             {"ControlRoc_ReadThresholds", "Ui_ControlRoc_ControlRoc_ReadThresholds"},
     145              :             {"ControlRoc_ReadSettings", "Ui_ControlRoc_ControlRoc_ReadSettings"},
     146              :             {"ControlRoc_PrintThresholds", "Ui_ControlRoc_ControlRoc_PrintThresholds"},
     147              : 
     148              :             {"SpiWriteRecord", "Ui_ProgramRoc_SpiWriteRecord"},
     149              :             {"SpiLoadImage", "Ui_ProgramRoc_SpiLoadImage"},
     150              :             {"SpiIapIndex", "Ui_ProgramRoc_SpiIapIndex"},
     151              :             {"SpiWriteDirectory", "Ui_ProgramRoc_SpiWriteDirectory"},
     152              :             {"SpiClearMemory", "Ui_ProgramRoc_SpiClearMemory"},
     153              : 
     154            0 :         };
     155              : 
     156            0 :         for(const auto& [oldStr, newStr] : replacements)
     157              :         {
     158            0 :                 size_t pos = 0;
     159            0 :                 while((pos = source.find(oldStr, pos)) != std::string::npos)
     160              :                 {
     161            0 :                         source.replace(pos, oldStr.length(), newStr);
     162            0 :                         pos += newStr.length();
     163              :                 }
     164              :         }
     165            0 :         if(!isHeader)
     166              :         {
     167            0 :                 for(const auto& [oldStr, newStr] : functionReplacements)
     168              :                 {
     169            0 :                         size_t pos = 0;
     170            0 :                         while((pos = source.find(oldStr, pos)) != std::string::npos)
     171              :                         {
     172            0 :                                 source.replace(pos, oldStr.length(), newStr);
     173            0 :                                 pos += newStr.length();
     174              :                         }
     175              :                 }
     176              :         }
     177            0 :         return source;
     178            0 : }  // end modifySource()
     179              : 
     180              : //==============================================================================
     181              : /// @brief Returns true if the function arguments in the function header are simple enough
     182              : /// (i.e. int, string) for converting to FE macros
     183              : ///             Also fills in the argTypes, argNames, argDefaults, outputTypes, outputNames
     184              : /// vectors.
     185              : /// @param functionHeader the full function header
     186            0 : bool validateArgsForFEMacro(const std::string&        functionHeader,
     187              :                             const std::string&        returnVal,
     188              :                             std::vector<std::string>& argTypes,
     189              :                             std::vector<std::string>& argNames,
     190              :                             std::vector<std::string>& argDefaults,
     191              :                             std::vector<std::string>& outputTypes,
     192              :                             std::vector<std::string>& outputNames,
     193              :                             bool                      ignoreAllowedTypes = false)
     194              : {
     195            0 :         size_t argTypePos = functionHeader.find('(');
     196            0 :         if(argTypePos == std::string::npos)
     197              :         {
     198            0 :                 __SS__ << "ERROR: could not find '(' in function header: " << functionHeader
     199            0 :                        << __E__;
     200            0 :                 __SS_THROW__;
     201            0 :         }
     202            0 :         size_t argEndPos = functionHeader.find(')', argTypePos);
     203            0 :         if(argEndPos == std::string::npos)
     204              :         {
     205            0 :                 __SS__ << "ERROR: could not find ')' in function header: " << functionHeader
     206            0 :                        << __E__;
     207            0 :                 __SS_THROW__;
     208            0 :         }
     209              : 
     210              :         // decide if there is an output return valu
     211              :         // for now, only handle void return type with no outputs
     212            0 :         if(!ignoreAllowedTypes && returnVal != "void" && returnVal != "int" &&
     213            0 :            returnVal != "unsigned int" && returnVal != "std::string" && returnVal != "bool" &&
     214            0 :            returnVal != "double" && returnVal != "float" &&
     215            0 :            returnVal != "std::vector<DTCLib::roc_data_t>" &&
     216            0 :            returnVal != "std::vector<std::string>" && returnVal != "std::vector<uint32_t>" &&
     217            0 :            returnVal != "std::vector<float>" && returnVal != "size_t" &&
     218            0 :            returnVal != "uint16_t" && returnVal != "uint32_t")
     219              :         {
     220            0 :                 __COUT_ERR__ << "- Return type '" << returnVal
     221            0 :                              << "' is not supported for FE Macro conversion in function header: "
     222            0 :                              << functionHeader << std::endl;
     223            0 :                 return false;
     224              :         }
     225            0 :         if(returnVal != "void")
     226              :         {
     227            0 :                 outputTypes.push_back(returnVal);
     228            0 :                 outputNames.push_back("Result");
     229              :         }
     230              :         else  // indicate no return value
     231              :         {
     232            0 :                 outputTypes.push_back("void");
     233            0 :                 outputNames.push_back("");
     234              :         }
     235              : 
     236              :         std::string argList =
     237            0 :             functionHeader.substr(argTypePos + 1, argEndPos - argTypePos - 1);
     238            0 :         __COUTTV__(argList);
     239              : 
     240              :         // remove any comments from argList
     241              :         while(1)
     242              :         {
     243            0 :                 size_t commentPos = argList.find("//");
     244            0 :                 if(commentPos == std::string::npos)
     245            0 :                         break;
     246            0 :                 size_t endOfLinePos = argList.find('\n', commentPos);
     247            0 :                 if(endOfLinePos == std::string::npos)
     248            0 :                         endOfLinePos = argList.size();
     249            0 :                 argList.erase(commentPos, endOfLinePos - commentPos);
     250            0 :         }  // end comment removal loop
     251              : 
     252              :         // split by commas
     253            0 :         std::vector<std::string> args = StringMacros::getVectorFromString(argList, {','});
     254            0 :         for(const auto& arg : args)
     255              :         {
     256            0 :                 __COUTTV__(arg);
     257              : 
     258            0 :                 if(!arg.size())
     259            0 :                         break;  // skip empty args (possible for no args)
     260              : 
     261              :                 std::vector<std::string> argParts = StringMacros::getVectorFromString(
     262            0 :                     arg, {' ', '\t', '\n'}, {} /* whitespace */);
     263            0 :                 if(argParts.size() < 2)
     264              :                 {
     265            0 :                         __COUT_ERR__ << "Could not parse argument '"
     266            0 :                                      << StringMacros::vectorToString(argParts)
     267            0 :                                      << "' in function header: " << functionHeader << std::endl;
     268            0 :                         return false;
     269              :                 }
     270              : 
     271            0 :                 size_t      i                   = 0;
     272            0 :                 bool        foundEquals         = false;
     273            0 :                 bool        isConst             = false;
     274            0 :                 bool        isOutputByReference = false;
     275            0 :                 std::string argType;
     276            0 :                 for(const auto& part : argParts)
     277              :                 {
     278            0 :                         __COUTT__ << "pre-part " << part << " i=" << i << std::endl;
     279              : 
     280            0 :                         if(part.size() == 0)
     281            0 :                                 continue;  // skip empty parts
     282              : 
     283            0 :                         if(part.size() && (part == " " || part == "\t" || part == "\n"))
     284            0 :                                 continue;  // skip whitespace parts
     285              : 
     286            0 :                         __COUTT__ << "part " << part << " i=" << i << std::endl;
     287              : 
     288            0 :                         if(i == 0)
     289              :                         {
     290            0 :                                 argType = part;  // first part is type
     291            0 :                                 __COUTTV__(argType);
     292            0 :                                 if(argType == "const")
     293              :                                 {
     294            0 :                                         isConst = true;
     295            0 :                                         continue;
     296              :                                 }
     297            0 :                                 __COUTTV__(argType);
     298              : 
     299              :                                 // check if argType is simple enough
     300            0 :                                 if(!ignoreAllowedTypes && argType != "int" && argType != "uint" &&
     301            0 :                                    argType != "unsigned int" && argType != "std::string" &&
     302            0 :                                    argType != "bool" && argType != "double" && argType != "float" &&
     303            0 :                                    argType != "DTCLib::DTC_Link_ID" &&
     304            0 :                                    (argType != "DTCLib::DTC_Link_ID&" || !isConst) &&
     305            0 :                                    argType != "DTCLib::roc_address_t&" && argType != "std::ostream&" &&
     306            0 :                                    (argType != "std::vector<DTCLib::roc_data_t>&" || isConst) &&
     307            0 :                                    (argType != "std::vector<uint16_t>&" || isConst) &&
     308            0 :                                    (argType != "std::vector<uint16_t>*" || isConst) &&
     309            0 :                                    argType != "size_t" && argType != "uint16_t" && argType != "uint32_t")
     310              :                                 {
     311            0 :                                         __COUT_ERR__ << "- Argument type '" << (isConst ? "const " : "")
     312            0 :                                                      << argType
     313              :                                                      << "' is not supported for FE Macro conversion in "
     314            0 :                                                         "function header: "
     315            0 :                                                      << functionHeader << std::endl;
     316            0 :                                         return false;
     317              :                                 }
     318            0 :                                 __COUTTV__(argType);
     319              : 
     320              :                                 // do not add "const," since FE Macro must set parameter to pass (and
     321              :                                 // argType search cannot overload const/no-const anyway)
     322              :                                 //  if(isConst)
     323              :                                 //      argType = "const " + argType;
     324              : 
     325            0 :                                 if(argType == "std::vector<uint16_t>&" ||
     326            0 :                                    argType == "std::vector<uint16_t>*" || argType == "std::ostream&" ||
     327            0 :                                    argType == "std::vector<roc_data_t>&")
     328              :                                 {
     329            0 :                                         __COUTT__ << " -- Treating " << argType << " as output parameter."
     330            0 :                                                   << std::endl;
     331            0 :                                         isOutputByReference = true;
     332              :                                 }
     333              : 
     334            0 :                                 if(isOutputByReference)
     335            0 :                                         argTypes.push_back(
     336            0 :                                             std::string("out") +
     337            0 :                                             (argType[argType.size() - 1] == '*'
     338              :                                                  ? "*"
     339            0 :                                                  : ""));  // mark as output by reference or by pointer
     340              :                                 else
     341            0 :                                         argTypes.push_back(argType);
     342            0 :                                 __COUTTV__(argTypes.back());
     343              :                         }
     344            0 :                         else if(i == 1)
     345              :                         {
     346            0 :                                 if(part.find('=') != std::string::npos)
     347              :                                 {
     348            0 :                                         foundEquals = true;
     349              : 
     350            0 :                                         __COUTT__ << "Found default value in name part: " << part
     351            0 :                                                   << std::endl;
     352            0 :                                         auto equalParts = StringMacros::getVectorFromString(part, {'='});
     353            0 :                                         if(equalParts.size() != 2)
     354              :                                         {
     355            0 :                                                 __COUT_ERR__ << "Could not parse argument with = in '"
     356            0 :                                                              << StringMacros::vectorToString(argParts)
     357            0 :                                                              << "' in function header: " << functionHeader
     358            0 :                                                              << std::endl;
     359            0 :                                                 return false;
     360              :                                         }
     361            0 :                                         argNames.push_back(equalParts[0]);  // second part is name
     362              : 
     363            0 :                                         if(equalParts[1].size() == 0)  // case is 'name= Default'
     364              :                                         {
     365            0 :                                                 __COUTT__ << "No default value YET after = in name part: " << part
     366            0 :                                                           << std::endl;
     367              :                                         }
     368              :                                         else
     369              :                                         {
     370            0 :                                                 __COUTT__ << "Found default value after = in name part: " << part
     371            0 :                                                           << std::endl;
     372            0 :                                                 argDefaults.push_back(equalParts[1]);  // default value
     373            0 :                                                 __COUTTV__(argDefaults.back());
     374              :                                         }
     375            0 :                                 }
     376              :                                 else
     377              :                                 {
     378            0 :                                         __COUTT__ << "No default value in name part: " << part << std::endl;
     379            0 :                                         argNames.push_back(part);  // second part is name
     380              :                                 }
     381            0 :                                 __COUTTV__(argNames.back());
     382              : 
     383            0 :                                 if(isOutputByReference)
     384              :                                 {
     385            0 :                                         outputTypes.push_back(argType);
     386            0 :                                         outputNames.push_back(argNames.back());
     387              :                                 }
     388              :                         }
     389            0 :                         else if(i > 1 && !foundEquals)  // possible 'name =Default' here
     390              :                         {
     391            0 :                                 if(part.size() > 1 && part[0] == '=')  // handle case of no spaces around
     392              :                                                                        // =
     393              :                                 {
     394            0 :                                         argDefaults.push_back(part.substr(1));  // fourth part is default
     395              :                                                                                 // value
     396            0 :                                         __COUTTV__(argDefaults.back());
     397              :                                 }
     398            0 :                                 else if(part == "=")
     399              :                                 {
     400            0 :                                         foundEquals = true;  // next part is default value
     401            0 :                                         __COUTTV__(foundEquals);
     402              :                                 }
     403              :                                 else
     404              :                                 {
     405            0 :                                         __COUT_ERR__ << "Could not parse argument missing = in '"
     406            0 :                                                      << StringMacros::vectorToString(argParts)
     407            0 :                                                      << "' in function header: " << functionHeader
     408            0 :                                                      << std::endl;
     409            0 :                                         return false;
     410              :                                 }
     411            0 :                         }
     412            0 :                         else if(i > 1 && foundEquals)  // fourth part is default value
     413              :                         {
     414            0 :                                 if(argDefaults.size() < argNames.size())
     415              :                                 {
     416            0 :                                         argDefaults.push_back(part);
     417            0 :                                         __COUTTV__(argDefaults.back());
     418              :                                 }
     419              :                                 else
     420              :                                 {
     421            0 :                                         __COUT_ERR__
     422            0 :                                             << "Could not parse argument with multiple default values in '"
     423            0 :                                             << StringMacros::vectorToString(argParts)
     424            0 :                                             << "' in function header: " << functionHeader << std::endl;
     425            0 :                                         return false;
     426              :                                 }
     427              :                         }
     428              : 
     429            0 :                         ++i;
     430              :                 }  // end art parts loop
     431              : 
     432            0 :                 if(argDefaults.size() < argNames.size())
     433              :                 {
     434            0 :                         argDefaults.push_back("");  // no default value
     435            0 :                         __COUTTV__(argDefaults.back());
     436              :                 }
     437            0 :                 else if(argDefaults.size() > argNames.size())
     438              :                 {
     439            0 :                         __COUT_ERR__ << "Could not parse argument with multiple default values in '"
     440            0 :                                      << StringMacros::vectorToString(argParts)
     441            0 :                                      << "' in function header: " << functionHeader << std::endl;
     442            0 :                         return false;
     443              :                 }
     444            0 :         }  // end main arg loop
     445              : 
     446              :         // if here, all args are simple enough
     447            0 :         __COUTTV__(StringMacros::vectorToString(argTypes));
     448            0 :         __COUTTV__(StringMacros::vectorToString(argNames));
     449            0 :         __COUTTV__(StringMacros::vectorToString(argDefaults));
     450            0 :         __COUTTV__(StringMacros::vectorToString(outputTypes));
     451            0 :         __COUTTV__(StringMacros::vectorToString(outputNames));
     452              : 
     453            0 :         return true;
     454            0 : }  // end validateArgsForFEMacro()
     455              : 
     456              : //==============================================================================
     457              : /// @brief Extracts the declared function header from the full function header
     458              : /// @param functionHeader the full function header
     459              : /// @param sourceFile the source file the function is from
     460            0 : std::string getDeclaredFunctionHeader(const std::string& functionHeader,
     461              :                                       const std::string& sourceFile)
     462              : {
     463              :         // general case
     464            0 :         size_t parenPos = functionHeader.find('(');
     465            0 :         if(parenPos == std::string::npos)
     466              :         {
     467            0 :                 __SS__ << "ERROR: could not find '(' in function header: " << functionHeader
     468            0 :                        << __E__;
     469            0 :                 __SS_THROW__;
     470            0 :         }
     471            0 :         std::string beforeParen = functionHeader.substr(0, parenPos);
     472            0 :         __COUTTV__(beforeParen);
     473              : 
     474              :         // get arg list to match when finding declaration in header file
     475            0 :         std::vector<std::string> argTypes, argNames, argDefaults, outputTypes, outputNames;
     476              :         {  // extract arg types (do not modify types, since comparing against unmodified
     477              :            // header)
     478            0 :                 if(!validateArgsForFEMacro(functionHeader,
     479              :                                            "void" /* dummy return val arg */,
     480              :                                            argTypes,
     481              :                                            argNames,
     482              :                                            argDefaults,
     483              :                                            outputTypes,
     484              :                                            outputNames,
     485              :                                            true /* ignoreAllowedTypes */))
     486              :                 {
     487            0 :                         __SS__ << "ERROR: could not validate args for function header: "
     488            0 :                                << functionHeader << __E__;
     489            0 :                         __SS_THROW__;
     490            0 :                 }
     491              :         }
     492              : 
     493              :         // find in file the function name
     494            0 :         std::ifstream in(sourceFile);
     495            0 :         if(!in)
     496              :         {
     497            0 :                 __SS__ << "\n\nERROR! Could not open file at " << sourceFile
     498            0 :                        << " - error: " << errno << " - " << strerror(errno) << __E__;
     499            0 :                 __SS_THROW__;
     500            0 :         }
     501              :         std::string fileContents((std::istreambuf_iterator<char>(in)),
     502            0 :                                  std::istreambuf_iterator<char>());
     503              :         // fileContents now contains the full contents of sourceFile
     504            0 :         size_t funcNamePos = 0;
     505              :         while(1)  // search for function name loop in header
     506              :         {
     507            0 :                 funcNamePos = fileContents.find(beforeParen, funcNamePos + 1);
     508            0 :                 if(funcNamePos == std::string::npos)
     509              :                 {
     510            0 :                         __SS__ << "\nERROR: could not find function name '" << beforeParen
     511            0 :                                << "' in source file: " << sourceFile << __E__;
     512            0 :                         __SS_THROW__;
     513            0 :                 }
     514            0 :                 __COUTTV__(fileContents.substr(funcNamePos, 50));
     515              :                 // make sure found instance is not a comment or header with similar name
     516            0 :                 size_t prevNewLine = fileContents.rfind("\n", funcNamePos);
     517            0 :                 size_t prevComment = fileContents.rfind("//", funcNamePos);
     518            0 :                 if(prevComment != std::string::npos && prevNewLine != std::string::npos &&
     519              :                    prevComment > prevNewLine)
     520              :                 {
     521            0 :                         __COUTT__ << "Found function name in comment, continuing search..."
     522            0 :                                   << std::endl;
     523            0 :                         continue;  // then found function name is in comment
     524            0 :                 }
     525              : 
     526              :                 // make sure next character is whitespace or '(' for arg list
     527            0 :                 size_t charAfterFuncNamePos = funcNamePos + beforeParen.size();
     528            0 :                 if(charAfterFuncNamePos >= fileContents.size() ||
     529            0 :                    (fileContents[charAfterFuncNamePos] != ' ' &&
     530            0 :                     fileContents[charAfterFuncNamePos] != '\t' &&
     531            0 :                     fileContents[charAfterFuncNamePos] != '\n' &&
     532            0 :                     fileContents[charAfterFuncNamePos] != '('))
     533              :                 {
     534            0 :                         __COUTT__
     535            0 :                             << "Found function name as part of another word, continuing search..."
     536            0 :                             << std::endl;
     537            0 :                         continue;  // then found function name is part of another word
     538            0 :                 }
     539              : 
     540              :                 // make sure there is an arg list after function name
     541            0 :                 size_t nextNewline     = fileContents.find("\n", funcNamePos);
     542            0 :                 size_t nextParenthesis = fileContents.find("(", funcNamePos);
     543              : 
     544            0 :                 if(nextParenthesis == std::string::npos ||
     545            0 :                    (nextNewline != std::string::npos && nextParenthesis > nextNewline))
     546              :                 {
     547            0 :                         __COUTT__ << "Found function name without arg list, continuing search..."
     548            0 :                                   << std::endl;
     549            0 :                         continue;  // then found function name is not a function definition
     550            0 :                 }
     551              : 
     552              :                 // make sure all arg types exist to match function definition (Note: arg name
     553              :                 // mismatch is allowed in C++)
     554            0 :                 size_t argEndPos = fileContents.find(')', nextParenthesis);
     555            0 :                 if(argEndPos == std::string::npos)
     556              :                 {
     557            0 :                         __COUTT__ << "Found function name without arg list end, continuing search..."
     558            0 :                                   << std::endl;
     559            0 :                         continue;  // then found function name is not a function definition
     560            0 :                 }
     561            0 :                 size_t argTypePos    = nextParenthesis;
     562            0 :                 size_t maxArgTypePos = nextParenthesis;
     563            0 :                 bool   mismatch      = false;
     564            0 :                 for(const auto& argType : argTypes)  // input arg types confirmation loop
     565              :                 {
     566            0 :                         if(argType.find("out") == 0)  // skip output by reference args
     567            0 :                                 continue;
     568            0 :                         size_t foundArgTypePos = argTypePos;
     569              :                         while(1)
     570              :                         {
     571            0 :                                 foundArgTypePos = fileContents.find(argType, argTypePos);
     572            0 :                                 if(foundArgTypePos == std::string::npos || foundArgTypePos > argEndPos)
     573              :                                 {
     574            0 :                                         __COUTT__ << "Could not find input arg type '" << argType
     575            0 :                                                   << "' in function definition, continuing search..."
     576            0 :                                                   << std::endl;
     577            0 :                                         mismatch = true;
     578            0 :                                         break;  // then found function name is not the correct function
     579              :                                                 // definition
     580              :                                 }
     581            0 :                                 __COUTTV__(argType);
     582            0 :                                 size_t charAfterPos = foundArgTypePos + argType.size();
     583              :                                 // make sure it is clean argType match (i.e. not part of another word)
     584              :                                 //      must be , or whitespace or end before and after
     585            0 :                                 if(foundArgTypePos != nextParenthesis)
     586              :                                 {
     587            0 :                                         char charBefore = fileContents[foundArgTypePos - 1];
     588            0 :                                         if(charBefore != ',' && charBefore != ' ' && charBefore != '\t' &&
     589            0 :                                            charBefore != '\n' && charBefore != '(' && charBefore != ':')
     590              :                                         {
     591            0 :                                                 __COUTT__ << "Found input arg type '" << argType
     592            0 :                                                           << "' as part of another word, continuing search..."
     593            0 :                                                           << fileContents.substr(foundArgTypePos - 1, 20)
     594            0 :                                                           << std::endl;
     595            0 :                                                 argTypePos = charAfterPos;
     596            0 :                                                 continue;  // then keep looking for the argType
     597            0 :                                         }
     598              :                                 }
     599              : 
     600            0 :                                 if(charAfterPos < fileContents.size())
     601              :                                 {
     602            0 :                                         char charAfter = fileContents[charAfterPos];
     603            0 :                                         if(charAfter != ',' && charAfter != ' ' && charAfter != '\t' &&
     604            0 :                                            charAfter != '\n' && charAfter != ')')
     605              :                                         {
     606            0 :                                                 __COUTT__ << "Found input arg type '" << argType
     607            0 :                                                           << "' as part of another word, continuing search..."
     608            0 :                                                           << fileContents.substr(foundArgTypePos - 1, 20)
     609            0 :                                                           << std::endl;
     610            0 :                                                 argTypePos = charAfterPos;
     611            0 :                                                 continue;  // then keep looking for the argType
     612            0 :                                         }
     613              :                                 }
     614            0 :                                 break;  // argType found cleanly
     615            0 :                         }           // end argType find loop
     616            0 :                         argTypePos = fileContents.find(',', foundArgTypePos + argType.size());
     617            0 :                         __COUTTV__(argTypePos);
     618            0 :                         if(argTypePos == std::string::npos || argTypePos > argEndPos)
     619            0 :                                 argTypePos = argEndPos;  // move to end of arg list if no more
     620              :                         else
     621            0 :                                 __COUTTV__(fileContents.substr(argTypePos, 20));
     622            0 :                         maxArgTypePos = argTypePos;
     623            0 :                         __COUTTV__(maxArgTypePos);
     624            0 :                         __COUTTV__(fileContents.substr(maxArgTypePos, 20));
     625              :                 }  // end input arg types confirmation loop
     626            0 :                 if(mismatch)
     627            0 :                         continue;
     628              : 
     629            0 :                 argTypePos   = nextParenthesis;
     630            0 :                 mismatch     = false;
     631            0 :                 bool isFirst = true;
     632            0 :                 for(const auto& argType : outputTypes)  // output arg types confirmation loop
     633              :                 {
     634            0 :                         if(isFirst)
     635              :                         {
     636            0 :                                 isFirst = false;
     637            0 :                                 continue;  // skip return value
     638              :                         }
     639            0 :                         size_t foundArgTypePos = argTypePos;
     640              :                         while(1)
     641              :                         {
     642            0 :                                 foundArgTypePos = fileContents.find(argType, argTypePos);
     643            0 :                                 if(foundArgTypePos == std::string::npos || foundArgTypePos > argEndPos)
     644              :                                 {
     645            0 :                                         __COUTT__ << "Could not find output arg type '" << argType
     646            0 :                                                   << "' in function definition, continuing search..."
     647            0 :                                                   << std::endl;
     648            0 :                                         mismatch = true;
     649            0 :                                         break;  // then found function name is not the correct function
     650              :                                                 // definition
     651              :                                 }
     652            0 :                                 __COUTTV__(argType);
     653              : 
     654            0 :                                 size_t charAfterPos = foundArgTypePos + argType.size();
     655              :                                 // make sure it is clean argType match (i.e. not part of another word)
     656              :                                 //      must be , or whitespace or end before and after
     657            0 :                                 if(foundArgTypePos != nextParenthesis)
     658              :                                 {
     659            0 :                                         char charBefore = fileContents[foundArgTypePos - 1];
     660            0 :                                         if(charBefore != ',' && charBefore != ' ' && charBefore != '\t' &&
     661            0 :                                            charBefore != '\n' && charBefore != '(')
     662              :                                         {
     663            0 :                                                 __COUTT__ << "Found input arg type '" << argType
     664            0 :                                                           << "' as part of another word, continuing search..."
     665            0 :                                                           << fileContents.substr(foundArgTypePos - 1, 20)
     666            0 :                                                           << std::endl;
     667            0 :                                                 argTypePos = charAfterPos;
     668            0 :                                                 continue;  // then keep looking for the argType
     669            0 :                                         }
     670              :                                 }
     671            0 :                                 if(charAfterPos < fileContents.size())
     672              :                                 {
     673            0 :                                         char charAfter = fileContents[charAfterPos];
     674            0 :                                         if(charAfter != ',' && charAfter != ' ' && charAfter != '\t' &&
     675            0 :                                            charAfter != '\n' && charAfter != ')')
     676              :                                         {
     677            0 :                                                 __COUTT__ << "Found input arg type '" << argType
     678            0 :                                                           << "' as part of another word, continuing search..."
     679            0 :                                                           << fileContents.substr(foundArgTypePos - 1, 20)
     680            0 :                                                           << std::endl;
     681            0 :                                                 argTypePos = charAfterPos;
     682            0 :                                                 continue;  // then keep looking for the argType
     683            0 :                                         }
     684              :                                 }
     685            0 :                                 break;  // argType found cleanly
     686            0 :                         }           // end argType find loop
     687            0 :                         argTypePos = fileContents.find(',', foundArgTypePos + argType.size());
     688            0 :                         __COUTTV__(argTypePos);
     689            0 :                         if(argTypePos == std::string::npos || argTypePos > argEndPos)
     690            0 :                                 argTypePos = argEndPos;  // move to end of arg list if no more
     691              :                         else
     692            0 :                                 __COUTTV__(fileContents.substr(argTypePos, 20));
     693            0 :                         if(argTypePos > maxArgTypePos)
     694              :                         {
     695            0 :                                 maxArgTypePos = argTypePos;
     696            0 :                                 __COUTTV__(maxArgTypePos);
     697            0 :                                 __COUTTV__(fileContents.substr(maxArgTypePos, 20));
     698              :                         }
     699              :                 }  // end output arg types confirmation loop
     700            0 :                 if(mismatch)
     701            0 :                         continue;
     702              : 
     703            0 :                 __COUTTV__(maxArgTypePos);
     704            0 :                 __COUTTV__(fileContents.substr(maxArgTypePos, 20));
     705              : 
     706              :                 // confirm no more parameters exist that would indicate overload function mismatch
     707            0 :                 size_t nextComma = fileContents.find(',', maxArgTypePos);
     708            0 :                 if(nextComma != std::string::npos && nextComma < argEndPos)
     709              :                 {
     710            0 :                         __COUTT__ << "Found extra arg type after expected types, continuing search..."
     711            0 :                                   << std::endl;
     712            0 :                         continue;  // then found function name is not the correct function definition
     713            0 :                 }
     714              : 
     715              :                 // else found function name is valid, so break out of search loop
     716            0 :                 break;
     717            0 :         }  // end search for function name loop
     718              : 
     719              :         // find semicolon after function name
     720            0 :         size_t semicolonPos = funcNamePos;
     721              :         while(1)
     722              :         {
     723            0 :                 semicolonPos = fileContents.find(';', semicolonPos + 1);
     724            0 :                 if(semicolonPos == std::string::npos)
     725              :                 {
     726            0 :                         __SS__ << "ERROR: could not find ';' after function name in source file: "
     727            0 :                                << beforeParen << " in file " << sourceFile << __E__;
     728            0 :                         __SS_THROW__;
     729            0 :                 }
     730              : 
     731              :                 // ignore semicolons in comments
     732            0 :                 size_t prevNewLine = fileContents.rfind("\n", semicolonPos);
     733            0 :                 size_t prevComment = fileContents.rfind("//", semicolonPos);
     734            0 :                 if(prevComment == std::string::npos ||
     735            0 :                    (prevNewLine != std::string::npos && prevComment < prevNewLine))
     736              :                         break;  // then ; is not in comment
     737              :                                 // else is in comment, so continue searching
     738            0 :         }               // end search for semicolon loop
     739              : 
     740              :         // extract declared function header
     741              :         std::string declaredFunctionHeader =
     742            0 :             fileContents.substr(funcNamePos, semicolonPos - funcNamePos);
     743            0 :         __COUTTV__(declaredFunctionHeader);
     744            0 :         return declaredFunctionHeader;
     745            0 : }  // end getDeclaredFunctionHeader()
     746              : 
     747              : //==============================================================================
     748              : /// @brief Imports the tracker test stand UI files and modifies them for the FEInterface
     749              : /// @param argc
     750              : /// @param argv
     751            0 : void ImportTrackerTestStand(int argc, char* argv[])
     752              : {
     753            0 :         std::cout << "=================================================\n";
     754            0 :         std::cout << "=======     ImportTrackerTestStand    ===========\n";
     755            0 :         std::cout << "=================================================\n";
     756            0 :         __COUT__ << "\nImporting Tracker Test Stand!" << std::endl;
     757              : 
     758            0 :         __COUT_INFO__
     759            0 :             << "\n\nusage: two argumenst:\n\t <import Ui path> <export FEInterface path> \n\n"
     760            0 :             << std::endl;
     761              : 
     762            0 :         __COUT_INFO__ << "argc = " << argc << std::endl;
     763            0 :         for(int i = 0; i < argc; i++)
     764            0 :                 __COUT_INFO__ << "argv[" << i << "] = " << argv[i] << std::endl;
     765              : 
     766            0 :         if(argc != 3)
     767              :         {
     768            0 :                 __COUT_ERR__ << "Error! Must provide two parameters.\n\n" << std::endl;
     769            0 :                 return;
     770              :         }
     771              : 
     772            0 :         std::string importPath = argv[1];
     773            0 :         __COUTV__(importPath);
     774            0 :         std::string exportPath = argv[2];
     775            0 :         __COUTV__(exportPath);
     776              : 
     777              :         DIR* dpi;
     778            0 :         if((dpi = opendir(importPath.c_str())) == 0)
     779              :         {
     780            0 :                 __COUT_ERR__ << "ERROR:(" << errno
     781            0 :                              << ").  Can't open Ui directory for import: " << importPath
     782            0 :                              << std::endl;
     783            0 :                 exit(0);
     784              :         }
     785            0 :         closedir(dpi);
     786              : 
     787              :         DIR* dpo;
     788            0 :         if((dpo = opendir(exportPath.c_str())) == 0)
     789              :         {
     790            0 :                 __COUT_ERR__ << "ERROR:(" << errno
     791            0 :                              << ").  Can't open FEInterface directory for export: " << exportPath
     792            0 :                              << std::endl;
     793            0 :                 exit(0);
     794              :         }
     795            0 :         closedir(dpo);
     796              : 
     797              :         // return;
     798              : 
     799              :         std::vector<std::pair<std::string /* file */, std::string /* error message */>>
     800            0 :             importErrors;
     801              : 
     802              :         // usually at otsdaq-mu2e-tracker/otsdaq-mu2e-tracker/Ui/DtcInterface.cc
     803              :         std::vector<std::string> filesToImport       = {"DtcInterfaceBase.cc",
     804              :                                                         "DtcInterface.cc",
     805              :                                                         "DtcInterface_print.cc",
     806              :                                                         "DtcInterface_ProgramRoc.cc",
     807            0 :                                                         "DtcInterface_ControlRoc.cc"};
     808              :         std::vector<std::string> headerFilesToImport = {"DtcInterfaceBase.hh",
     809              :                                                         "DtcInterface.hh",
     810              :                                                         "DtcInterface.hh",
     811              :                                                         "DtcInterface.hh",
     812            0 :                                                         "DtcInterface.hh"};
     813              :         std::vector<std::string> prepend             = {
     814            0 :         "Ui_base", "Ui", "Ui_print", "Ui_ProgramRoc", "Ui_ControlRoc"};
     815            0 :         for(size_t i = 0; i < filesToImport.size(); i++)
     816              :         {
     817            0 :                 std::string importFile = importPath + "/" + filesToImport[i];
     818            0 :                 __COUTV__(importFile);
     819            0 :                 __COUTV__(prepend[i]);
     820              :                 try
     821              :                 {
     822            0 :                         std::ifstream in(importFile);
     823            0 :                         if(!in)
     824              :                         {
     825            0 :                                 __SS__ << "\n\nERROR! Could not open file at " << importFile
     826            0 :                                        << ". Error: " << errno << " - " << strerror(errno) << __E__;
     827            0 :                                 __SS_THROW__;
     828            0 :                         }
     829              :                         // modify import file to be consistent by path location (inserted in comments
     830              :                         // and printouts, which can cause git diffs), starting from
     831              :                         // otsdaq-mu2e-tracker/
     832            0 :                         size_t tpos = importFile.rfind("otsdaq-mu2e-tracker");  // find last instance
     833            0 :                         if(tpos == std::string::npos)
     834            0 :                                 importFile = "otsdaq-mu2e-tracker/" + importFile;
     835              :                         else
     836            0 :                                 importFile = importFile.substr(tpos);
     837              : 
     838              :                         std::string fileContents((std::istreambuf_iterator<char>(in)),
     839            0 :                                                  std::istreambuf_iterator<char>());
     840              :                         // fileContents now contains the full contents of importFile
     841              : 
     842              :                         std::string outputFilePath =
     843            0 :                             exportPath + "/ROCTrackerInterface_" + prepend[i] + ".cc";
     844            0 :                         std::ofstream outputFile(outputFilePath);
     845            0 :                         if(!outputFile.is_open())
     846              :                         {
     847            0 :                                 __SS__ << "\n\nERROR! Could not open output file at " << outputFilePath
     848            0 :                                        << __E__;
     849            0 :                                 __SS_THROW__;
     850            0 :                         }
     851              :                         std::string outputHeaderPath =
     852            0 :                             exportPath + "/ROCTrackerInterface_" + prepend[i] + ".hxx";
     853            0 :                         std::ofstream outputHeaderFile(outputHeaderPath);
     854            0 :                         if(!outputHeaderFile.is_open())
     855              :                         {
     856            0 :                                 __SS__ << "\n\nERROR! Could not open header output file at "
     857            0 :                                        << outputHeaderPath << __E__;
     858            0 :                                 __SS_THROW__;
     859            0 :                         }
     860            0 :                         std::string outputFeMacroDeclarePath = exportPath + "/ROCTrackerInterface_" +
     861            0 :                                                                prepend[i] + "_declareFEMacros.hxx";
     862            0 :                         std::ofstream outputFeMacroDeclareFile(outputFeMacroDeclarePath);
     863            0 :                         if(!outputFeMacroDeclareFile.is_open())
     864              :                         {
     865            0 :                                 __SS__ << "\n\nERROR! Could not open FE Macro declaration output file at "
     866            0 :                                        << outputFeMacroDeclarePath << __E__;
     867            0 :                                 __SS_THROW__;
     868            0 :                         }
     869            0 :                         std::string outputFeMacroPath = exportPath + "/ROCTrackerInterface_" +
     870            0 :                                                         prepend[i] + "_registerFEMacros.icc";
     871            0 :                         std::ofstream outputFeMacroRegisterFile(outputFeMacroPath);
     872            0 :                         if(!outputFeMacroRegisterFile.is_open())
     873              :                         {
     874            0 :                                 __SS__
     875              :                                     << "\n\nERROR! Could not open FE Macro registration output file at "
     876            0 :                                     << outputFeMacroPath << __E__;
     877            0 :                                 __SS_THROW__;
     878            0 :                         }
     879              :                         std::string outputFeMacroDefinePath =
     880            0 :                             exportPath + "/ROCTrackerInterface_" + prepend[i] + "_defineFEMacros.cc";
     881            0 :                         std::ofstream outputFeMacroDefineFile(outputFeMacroDefinePath);
     882            0 :                         if(!outputFeMacroDefineFile.is_open())
     883              :                         {
     884            0 :                                 __SS__
     885              :                                     << "\n\nERROR! Could not open FE Macro registration output file at "
     886            0 :                                     << outputFeMacroDefinePath << __E__;
     887            0 :                                 __SS_THROW__;
     888            0 :                         }
     889              : 
     890            0 :                         std::stringstream headerInstructionsSs, headerIncludes;
     891              : 
     892              :                         //////////////// source file header
     893            0 :                         outputFile << "\n// clang-format off\n";
     894              :                         outputFile << "\n//"
     895              :                                       "--------------------------------------------------------------"
     896            0 :                                       "---------------\n";
     897              :                         headerInstructionsSs << "/// This file was auto-generated from " << importFile
     898            0 :                                              << "\n";
     899            0 :                         headerInstructionsSs << "/// Do not modify this file directly.\n";
     900            0 :                         headerInstructionsSs << "///\n";
     901              :                         headerInstructionsSs << "/// To modify, edit " << importFile
     902            0 :                                              << " and re-run the import tool:\n";
     903            0 :                         headerInstructionsSs << "///\n";
     904              :                         headerInstructionsSs << "///   otsdaq_import_tracker_test_stand   "
     905            0 :                                              << importPath << "   " << exportPath << "\n";
     906            0 :                         headerInstructionsSs << "///\n";
     907            0 :                         outputFile << headerInstructionsSs.str();
     908              :                         outputFile << "//"
     909              :                                       "--------------------------------------------------------------"
     910            0 :                                       "---------------\n";
     911              : 
     912              :                         headerIncludes
     913              :                             << "\n\n#include "
     914            0 :                                "\"otsdaq-mu2e-tracker/FEInterfaces/ROCTrackerInterface.h\"\n\n";
     915            0 :                         headerIncludes << "\n#include <TString.h>  // includes ROOT's Form\n";
     916            0 :                         headerIncludes << "\n#include <filesystem>\n";
     917              : 
     918            0 :                         headerIncludes << "\n\nusing namespace ots;\n";
     919            0 :                         headerIncludes << "\n#undef __MF_SUBJECT__\n";
     920            0 :                         headerIncludes << "#define __MF_SUBJECT__ \"FE-ROCTrackerInterface\"\n";
     921              : 
     922            0 :                         headerIncludes << "\n\n";
     923            0 :                         outputFile << headerIncludes.str();
     924              : 
     925              :                         //////////////// header file header
     926            0 :                         outputHeaderFile << "\n// clang-format off\n";
     927              :                         outputHeaderFile << "\n//"
     928              :                                             "--------------------------------------------------------"
     929            0 :                                             "----------------\n";
     930            0 :                         outputHeaderFile << headerInstructionsSs.str();
     931              :                         outputHeaderFile << "//"
     932              :                                             "--------------------------------------------------------"
     933            0 :                                             "----------------\n";
     934            0 :                         outputHeaderFile << "\n\n";
     935              : 
     936              :                         //////////////// FE macro declare file header
     937            0 :                         outputFeMacroDeclareFile << "\n// clang-format off\n";
     938              :                         outputFeMacroDeclareFile << "\n//"
     939              :                                                     "------------------------------------------------"
     940            0 :                                                     "------------------------\n";
     941            0 :                         outputFeMacroDeclareFile << headerInstructionsSs.str();
     942              :                         outputFeMacroDeclareFile << "//"
     943              :                                                     "------------------------------------------------"
     944            0 :                                                     "------------------------\n";
     945            0 :                         outputFeMacroDeclareFile << "\n\n";
     946              : 
     947              :                         //////////////// FE macro register source file header
     948            0 :                         outputFeMacroRegisterFile << "\n// clang-format off\n";
     949              :                         outputFeMacroRegisterFile << "\n//"
     950              :                                                      "-----------------------------------------------"
     951            0 :                                                      "-------------------------\n";
     952            0 :                         outputFeMacroRegisterFile << headerInstructionsSs.str();
     953              :                         outputFeMacroRegisterFile << "//"
     954              :                                                      "-----------------------------------------------"
     955            0 :                                                      "-------------------------\n";
     956            0 :                         outputFeMacroRegisterFile << "\n\n";
     957              : 
     958              :                         //////////////// FE macro deinition source file header
     959            0 :                         outputFeMacroDefineFile << "\n// clang-format off\n";
     960              :                         outputFeMacroDefineFile << "\n//"
     961              :                                                    "-------------------------------------------------"
     962            0 :                                                    "-----------------------\n";
     963            0 :                         outputFeMacroDefineFile << headerInstructionsSs.str();
     964              :                         outputFeMacroDefineFile << "//"
     965              :                                                    "-------------------------------------------------"
     966            0 :                                                    "-----------------------\n";
     967            0 :                         outputFeMacroDefineFile << headerIncludes.str();
     968              : 
     969            0 :                         const std::string functionNeedle = " DtcInterface::";
     970              :                         //-----------------------------------------------------------------------------
     971              :                         // search for each function definition
     972            0 :                         size_t pos = 0;
     973              :                         while(true)
     974              :                         {
     975              :                                 // find the next function definition
     976            0 :                                 size_t funcPos = fileContents.find(" DtcInterface::", pos);
     977            0 :                                 pos            = funcPos +
     978            0 :                                       functionNeedle.size();  // move past this point for next search
     979            0 :                                 if(funcPos == std::string::npos)
     980              :                                 {
     981            0 :                                         __COUTT__ << "No more functions found at " << funcPos << std::endl;
     982            0 :                                         break;  // no more functions found
     983              :                                 }
     984              : 
     985            0 :                                 __COUT__ << "===========> Considering next DtcInterface:: pos = "
     986            0 :                                          << (fileContents.substr(funcPos, 50)) << __E__;
     987              : 
     988            0 :                                 size_t endFuncPos = fileContents.find(")", funcPos);
     989            0 :                                 if(endFuncPos == std::string::npos)
     990              :                                 {
     991            0 :                                         __COUTT__ << "Malformed function found at " << funcPos << std::endl;
     992            0 :                                         continue;  // malformed function definition, so skip
     993            0 :                                 }
     994              : 
     995            0 :                                 __COUTV__(fileContents.substr(endFuncPos, 50));
     996              : 
     997              :                                 // find the opening brace of the function body
     998            0 :                                 size_t bracePos = fileContents.find("{", endFuncPos);
     999            0 :                                 if(bracePos == std::string::npos)
    1000              :                                 {
    1001            0 :                                         __COUTT__ << "Malformed function found at " << funcPos << std::endl;
    1002            0 :                                         continue;  // malformed function definition, so skip
    1003            0 :                                 }
    1004              : 
    1005            0 :                                 __COUTV__(fileContents.substr(bracePos, 50));
    1006              : 
    1007              :                                 std::string functionHeader =
    1008            0 :                                     fileContents.substr(funcPos + functionNeedle.size(),
    1009            0 :                                                         bracePos - (funcPos + functionNeedle.size()));
    1010              : 
    1011              :                                 // enforce that there are no special characters in function header between
    1012              :                                 // funcPos and bracePos
    1013            0 :                                 if(functionHeader.find("{") != std::string::npos ||
    1014            0 :                                    functionHeader.find("}") != std::string::npos ||
    1015            0 :                                    functionHeader.find("[") != std::string::npos ||
    1016            0 :                                    functionHeader.find("]") != std::string::npos ||
    1017            0 :                                    functionHeader.find(";") != std::string::npos)
    1018              :                                 {
    1019            0 :                                         __COUTT__ << "Malformed function found at " << funcPos << std::endl;
    1020            0 :                                         continue;  // malformed function definition, so skip
    1021            0 :                                 }
    1022            0 :                                 __COUTV__(functionHeader);
    1023              : 
    1024              :                                 // find the matching closing brace
    1025            0 :                                 int    braceCount = 1;
    1026            0 :                                 size_t endPos     = bracePos + 1;
    1027            0 :                                 bool   inComment  = false;
    1028            0 :                                 bool   inString   = false;
    1029            0 :                                 while(endPos < fileContents.size() && braceCount > 0)
    1030              :                                 {
    1031            0 :                                         if(fileContents[endPos] == '{' && !inComment && !inString)
    1032              :                                         {
    1033            0 :                                                 braceCount++;
    1034            0 :                                                 __COUTT__ << "braceCount=" << braceCount
    1035            0 :                                                           << fileContents.substr(endPos - 49, 50);
    1036              :                                         }
    1037            0 :                                         else if(fileContents[endPos] == '}' && !inComment && !inString)
    1038              :                                         {
    1039            0 :                                                 braceCount--;
    1040            0 :                                                 __COUTT__ << "braceCount=" << braceCount
    1041            0 :                                                           << fileContents.substr(endPos - 49, 50);
    1042              :                                         }
    1043            0 :                                         else if(fileContents[endPos] == '/' &&
    1044            0 :                                                 fileContents[endPos + 1] == '/')
    1045              :                                         {
    1046            0 :                                                 inComment = true;
    1047            0 :                                                 __COUTT__ << "inComment start"
    1048            0 :                                                           << fileContents.substr(endPos - 49, 50);
    1049              :                                         }
    1050            0 :                                         else if(fileContents[endPos] == '\n' && inComment)
    1051              :                                         {
    1052            0 :                                                 inComment = false;
    1053            0 :                                                 __COUTT__ << "inComment end"
    1054            0 :                                                           << fileContents.substr(endPos - 49, 50);
    1055              :                                         }
    1056            0 :                                         else if(fileContents[endPos] == '"' && !inComment)
    1057              :                                         {
    1058            0 :                                                 inString = !inString;  // toggle string state
    1059            0 :                                                 __COUTT__ << "inString toggle to " << inString
    1060            0 :                                                           << fileContents.substr(endPos - 49, 50);
    1061              :                                         }
    1062            0 :                                         endPos++;
    1063              :                                 }
    1064            0 :                                 __COUTV__(fileContents.substr(endPos - 50, 50));
    1065            0 :                                 if(braceCount != 0)
    1066              :                                 {
    1067            0 :                                         __COUTT__ << "Malformed function found at " << funcPos << " to "
    1068            0 :                                                   << endPos << std::endl;
    1069            0 :                                         continue;  // malformed function definition, so skip
    1070            0 :                                 }
    1071              : 
    1072              :                                 // extract the function definition
    1073              :                                 std::string functionDef =
    1074            0 :                                     fileContents.substr(bracePos, endPos - bracePos);
    1075              : 
    1076              :                                 // update position for next search
    1077            0 :                                 pos = endPos;
    1078              : 
    1079              :                                 // eliminate special functions that should not be imported
    1080            0 :                                 if(functionDef.find("fgInstance") != std::string::npos)
    1081              :                                 {
    1082            0 :                                         __COUTT__ << "Eliminated function def found at " << funcPos << " to "
    1083            0 :                                                   << endPos << std::endl;
    1084            0 :                                         continue;  // malformed function definition, so skip
    1085            0 :                                 }
    1086              : 
    1087              :                                 // prepend the specified string
    1088            0 :                                 __COUT__ << "Found: " + prepend[i] + "_" + functionHeader;
    1089              : 
    1090            0 :                                 size_t startFunc = fileContents.rfind('\n', funcPos);
    1091            0 :                                 if(startFunc == std::string::npos)
    1092              :                                 {
    1093            0 :                                         __COUTT__ << "Malformed function found at startFunc=" << startFunc
    1094            0 :                                                   << " from " << funcPos << std::endl;
    1095            0 :                                         continue;  // malformed function definition, so skip
    1096            0 :                                 }
    1097              :                                 std::string functionReturnVal =
    1098            0 :                                     fileContents.substr(startFunc + 1, funcPos - (startFunc + 1));
    1099            0 :                                 __COUTTV__(functionReturnVal);
    1100            0 :                                 functionReturnVal = StringMacros::trim(functionReturnVal);
    1101            0 :                                 __COUTV__(functionReturnVal);
    1102            0 :                                 if(functionReturnVal.size() == 0)
    1103              :                                 {
    1104            0 :                                         __COUTT__ << "Ignoring constructors/destructors functions."
    1105            0 :                                                   << std::endl;
    1106            0 :                                         continue;  // malformed function definition, so skip
    1107            0 :                                 }
    1108            0 :                                 __COUTTV__(startFunc);
    1109              : 
    1110              :                                 // accept as comment lines with "// "
    1111            0 :                                 --startFunc;  // move before newline of function definition
    1112            0 :                                 std::string functionComment = "";
    1113              :                                 while(true)
    1114              :                                 {
    1115            0 :                                         size_t startComment1 = fileContents.rfind("//", startFunc);
    1116            0 :                                         size_t startComment2 = fileContents.rfind("\n", startFunc);
    1117            0 :                                         __COUTTV__(startComment1);
    1118            0 :                                         __COUTTV__(startComment2);
    1119              : 
    1120            0 :                                         if(startComment1 == std::string::npos ||
    1121            0 :                                            startComment1 < startComment2)
    1122              :                                         {
    1123            0 :                                                 __COUTT__ << "No more comments found at " << startComment1 << " "
    1124            0 :                                                           << fileContents.substr(startFunc - 48, 50) << std::endl;
    1125            0 :                                                 break;  // no more comments found
    1126              :                                         }
    1127            0 :                                         __COUTT__ << "Comment found at " << startComment1 << " "
    1128            0 :                                                   << fileContents.substr(startFunc - 48, 50) << std::endl;
    1129              : 
    1130            0 :                                         if(fileContents[startComment1 + 2] == ' ')  // is a comment line
    1131              :                                         {
    1132              :                                                 // remove excess white space (from double comment)
    1133            0 :                                                 while(fileContents[startFunc] == ' ')
    1134            0 :                                                         --startFunc;
    1135              : 
    1136              :                                                 functionComment =
    1137            0 :                                                     "/" +
    1138            0 :                                                     fileContents.substr(startComment1,
    1139            0 :                                                                         startFunc - startComment1 + 1) +
    1140            0 :                                                     "\n" + functionComment;
    1141              :                                         }
    1142              :                                         // else //is a comment line to ignore
    1143              : 
    1144            0 :                                         startFunc = startComment1 - 2;  // move before this comment line
    1145            0 :                                 }                                   // end comment extraction loop
    1146              : 
    1147            0 :                                 __COUTTV__(functionComment);
    1148            0 :                                 __COUTTV__(functionDef);
    1149              : 
    1150              :                                 // output the function prototype to header file
    1151              :                                 std::string declaredFunctionHeader = getDeclaredFunctionHeader(
    1152            0 :                                     functionHeader, importPath + "/" + headerFilesToImport[i]);
    1153              :                                 outputHeaderFile
    1154            0 :                                     << modifySource(functionReturnVal) << " " << prepend[i] << "_"
    1155            0 :                                     << modifySource(declaredFunctionHeader, true /* isHeader */) << ";\n";
    1156              : 
    1157              :                                 // output the extracted function to source file
    1158              :                                 outputFile << "//"
    1159              :                                               "=========================================================="
    1160            0 :                                               "====================\n";
    1161            0 :                                 modifySource(functionHeader, true /* isHeader */);
    1162            0 :                                 outputFile << "///\t" << prepend[i] << "_"
    1163            0 :                                            << functionHeader.substr(0, functionHeader.find('('))
    1164            0 :                                            << "()\n";
    1165            0 :                                 outputFile << functionComment;
    1166            0 :                                 outputFile << headerInstructionsSs.str();
    1167              :                                 outputFile << functionReturnVal << " ROCTrackerInterface"
    1168            0 :                                            << "::" << prepend[i] << "_"
    1169            0 :                                            << functionHeader.substr(
    1170              :                                                   0,
    1171            0 :                                                   functionHeader.size() -
    1172              :                                                       1 /* removing trailing white space */)
    1173            0 :                                            << "\n";
    1174            0 :                                 outputFile << modifySource(functionDef);
    1175            0 :                                 outputFile << " // end " << prepend[i] << "_"
    1176            0 :                                            << functionHeader.substr(0, functionHeader.find('('))
    1177            0 :                                            << "()\n\n";
    1178              : 
    1179              :                                 // if args are simple (int, string), then output the FE Macro declaration,
    1180              :                                 // registration, and definition
    1181            0 :                                 std::vector<std::string> argTypes, argNames, argDefaults, outputTypes,
    1182            0 :                                     outputNames;
    1183            0 :                                 __COUT__ << "Validating args for FE Macro... " << declaredFunctionHeader
    1184            0 :                                          << std::endl;
    1185            0 :                                 if(validateArgsForFEMacro(declaredFunctionHeader,
    1186              :                                                           functionReturnVal,
    1187              :                                                           argTypes,
    1188              :                                                           argNames,
    1189              :                                                           argDefaults,
    1190              :                                                           outputTypes,
    1191              :                                                           outputNames))
    1192              :                                 {
    1193            0 :                                         __COUT__ << "Valid FE Macro! " << prepend[i] << "_"
    1194            0 :                                                  << functionHeader.substr(0, functionHeader.find('('))
    1195            0 :                                                  << std::endl;
    1196              :                                         // --------------------------------------------
    1197              :                                         // FE Macro declaration ----------------
    1198              :                                         outputFeMacroDeclareFile
    1199            0 :                                             << "void FEMacro_" << prepend[i] << "_"
    1200            0 :                                             << functionHeader.substr(0, functionHeader.find('('))
    1201            0 :                                             << "(__ARGS__);\n";
    1202              : 
    1203              :                                         // --------------------------------------------
    1204              :                                         // FE Macro registration ----------------
    1205            0 :                                         outputFeMacroRegisterFile << "\n";
    1206              :                                         outputFeMacroRegisterFile
    1207            0 :                                             << "    registerFEMacroFunction(\"" << prepend[i] << " "
    1208            0 :                                             << functionHeader.substr(0, functionHeader.find('(')) << "\",\n";
    1209              :                                         outputFeMacroRegisterFile
    1210              :                                             << "                            "
    1211            0 :                                                "static_cast<FEVInterface::frontEndMacroFunction_t>(\n";
    1212              :                                         outputFeMacroRegisterFile
    1213              :                                             << "                                "
    1214              :                                                "&ROCTrackerInterface::FEMacro_"
    1215            0 :                                             << prepend[i] << "_"
    1216            0 :                                             << functionHeader.substr(0, functionHeader.find('(')) << "),\n";
    1217              :                                         outputFeMacroRegisterFile
    1218            0 :                                             << "                            std::vector<std::string>{";
    1219            0 :                                         for(size_t o = 0, ocount = 0; o < argNames.size();
    1220              :                                             o++)  // input args loop
    1221              :                                         {
    1222            0 :                                                 if((argTypes[o].size() == 3 || argTypes[o].size() == 4) &&
    1223            0 :                                                    argTypes[o].find("out") == 0)
    1224            0 :                                                         continue;  // skip output by reference/pointer args
    1225              : 
    1226            0 :                                                 if(argNames[o] == "Link" || argNames[o] == "LinkMask")
    1227            0 :                                                         continue;  // skip link args (take from ROC member variable)
    1228              : 
    1229            0 :                                                 if(ocount > 0)
    1230            0 :                                                         outputFeMacroRegisterFile << ", ";
    1231            0 :                                                 outputFeMacroRegisterFile << "\"" << argNames[o];
    1232              : 
    1233            0 :                                                 if(argDefaults[o].size())
    1234            0 :                                                         outputFeMacroRegisterFile << " (Default = " << argDefaults[o]
    1235            0 :                                                                                   << ")";
    1236            0 :                                                 outputFeMacroRegisterFile << "\"";
    1237            0 :                                                 ++ocount;
    1238              :                                         }  // end input args loop
    1239            0 :                                         outputFeMacroRegisterFile << "},          // inputs parameters\n";
    1240              :                                         outputFeMacroRegisterFile
    1241            0 :                                             << "                            std::vector<std::string>{";
    1242            0 :                                         for(size_t o = 0, ocount = 0; o < outputNames.size();
    1243              :                                             o++)  // output args loop
    1244              :                                         {
    1245            0 :                                                 if(outputTypes[o] == "void")
    1246            0 :                                                         continue;  // no output to declare
    1247              : 
    1248            0 :                                                 if(ocount > 0)
    1249            0 :                                                         outputFeMacroRegisterFile << ", ";
    1250            0 :                                                 outputFeMacroRegisterFile << "\"" << outputNames[o] << "\"";
    1251            0 :                                                 ++ocount;
    1252              :                                         }  // end output args loop
    1253            0 :                                         outputFeMacroRegisterFile << "},  // output parameters\n";
    1254              :                                         outputFeMacroRegisterFile << "                            1);  // "
    1255            0 :                                                                      "requiredUserPermissions\n";
    1256              : 
    1257              :                                         // --------------------------------------------
    1258              :                                         // FE Macro definition ----------------
    1259            0 :                                         outputFeMacroDefineFile << "\n";
    1260              :                                         outputFeMacroDefineFile << "//"
    1261              :                                                                    "========================================="
    1262            0 :                                                                    "=====================================\n";
    1263              :                                         outputFeMacroDefineFile
    1264            0 :                                             << "/// FE Macro to call " << prepend[i] << "_"
    1265            0 :                                             << functionHeader.substr(0, functionHeader.find('(')) << "()\n";
    1266            0 :                                         outputFeMacroDefineFile << "///\n";
    1267            0 :                                         outputFeMacroDefineFile << headerInstructionsSs.str();
    1268              :                                         outputFeMacroDefineFile
    1269            0 :                                             << "void ROCTrackerInterface::FEMacro_" << prepend[i] << "_"
    1270            0 :                                             << functionHeader.substr(0, functionHeader.find('('))
    1271            0 :                                             << "(__ARGS__)";
    1272              :                                         outputFeMacroDefineFile <<
    1273            0 :                                             R"(
    1274              : {
    1275              :         __FE_COUT__ << "# of input args = " << argsIn.size() << __E__;
    1276              :         __FE_COUT__ << "# of output args = " << argsOut.size() << __E__;
    1277              :         for(auto& argIn : argsIn)
    1278              :                 __FE_COUT__ << argIn.first << ": " << argIn.second << __E__;
    1279              : 
    1280              : )";
    1281              : 
    1282            0 :                                         for(size_t o = 0; o < argNames.size(); o++)  // declare input args
    1283              :                                         {
    1284            0 :                                                 if((argTypes[o].size() == 3 || argTypes[o].size() == 4) &&
    1285            0 :                                                    argTypes[o].find("out") == 0)
    1286            0 :                                                         continue;  // skip output by reference/pointer args
    1287              : 
    1288            0 :                                                 if(argTypes[o].find('&') !=
    1289              :                                                    std::string::npos)  // remove the & from output by reference
    1290              :                                                                        // args
    1291              :                                                         outputFeMacroDefineFile
    1292            0 :                                                             << "\t" << argTypes[o].substr(0, argTypes[o].size() - 1)
    1293            0 :                                                             << " " << argNames[o] << " = ";
    1294              :                                                 else
    1295            0 :                                                         outputFeMacroDefineFile << "\t" << argTypes[o] << " "
    1296            0 :                                                                                 << argNames[o] << " = ";
    1297              : 
    1298            0 :                                                 if(argNames[o] ==
    1299              :                                                    "Link")  // for link args, take from ROC member variable
    1300              :                                                 {
    1301              :                                                         outputFeMacroDefineFile
    1302            0 :                                                             << "ROCCoreVInterface::getLinkID();\n";
    1303              :                                                 }
    1304            0 :                                                 else if(argNames[o] == "LinkMask")  // for link mask args, take
    1305              :                                                                                     // from ROC member variable
    1306              :                                                 {
    1307              :                                                         // nibble based link mask
    1308              :                                                         outputFeMacroDefineFile
    1309            0 :                                                             << "1 << (ROCCoreVInterface::getLinkID() * 4);\n";
    1310              :                                                 }
    1311              :                                                 else  // normal input arg
    1312              :                                                 {
    1313              :                                                         outputFeMacroDefineFile << "__GET_ARG_IN__"
    1314            0 :                                                                                 << "(\"" << argNames[o];
    1315              : 
    1316            0 :                                                         if(argDefaults[o].size())
    1317              :                                                                 outputFeMacroDefineFile
    1318            0 :                                                                     << " (Default = " << argDefaults[o] << ")";
    1319              : 
    1320            0 :                                                         if(argTypes[o].find('&') !=
    1321              :                                                            std::string::npos)  // remove the & from output by
    1322              :                                                                                // reference args
    1323              :                                                                 outputFeMacroDefineFile
    1324              :                                                                     << "\""
    1325              :                                                                     << ", "
    1326            0 :                                                                     << argTypes[o].substr(0, argTypes[o].size() - 1);
    1327              :                                                         else
    1328              :                                                                 outputFeMacroDefineFile << "\""
    1329            0 :                                                                                         << ", " << argTypes[o];
    1330              : 
    1331            0 :                                                         if(argDefaults[o].size())
    1332            0 :                                                                 outputFeMacroDefineFile << ", " << argDefaults[o];
    1333              : 
    1334            0 :                                                         outputFeMacroDefineFile << ");\n";
    1335              :                                                 }
    1336              :                                         }  // end declare input args loop
    1337              : 
    1338            0 :                                         outputFeMacroDefineFile << "\n";
    1339            0 :                                         for(size_t o = 0; o < outputNames.size(); o++)  // declare output args
    1340              :                                         {
    1341            0 :                                                 if(outputTypes[o] == "void")
    1342            0 :                                                         continue;  // no output to declare
    1343              : 
    1344            0 :                                                 if(outputTypes[o].find('&') !=
    1345              :                                                    std::string::npos)  // remove the & from output by reference
    1346              :                                                                        // args
    1347              :                                                 {
    1348            0 :                                                         if(outputTypes[o] ==
    1349              :                                                            "std::ostream&")  // special case for ostream
    1350              :                                                                 outputFeMacroDefineFile << "\t"
    1351              :                                                                                         << "std::stringstream"
    1352            0 :                                                                                         << " " << outputNames[o] << ";\n";
    1353              :                                                         else
    1354              :                                                                 outputFeMacroDefineFile
    1355              :                                                                     << "\t"
    1356            0 :                                                                     << outputTypes[o].substr(0, outputTypes[o].size() - 1)
    1357            0 :                                                                     << " " << outputNames[o] << ";\n";
    1358              :                                                 }
    1359            0 :                                                 else if(outputTypes[o].find('*') !=
    1360              :                                                         std::string::npos)  // remove the * from output by
    1361              :                                                                             // reference args
    1362              :                                                         outputFeMacroDefineFile
    1363              :                                                             << "\t"
    1364            0 :                                                             << outputTypes[o].substr(0, outputTypes[o].size() - 1)
    1365            0 :                                                             << " " << outputNames[o] << ";\n";
    1366              :                                                 else
    1367            0 :                                                         outputFeMacroDefineFile << "\t" << outputTypes[o] << " "
    1368            0 :                                                                                 << outputNames[o] << ";\n";
    1369              :                                         }  // end declare output args loop
    1370              : 
    1371            0 :                                         outputFeMacroDefineFile << "\n";
    1372            0 :                                         if(outputNames.size() && functionReturnVal != "void")
    1373            0 :                                                 outputFeMacroDefineFile << "\t" << outputNames[0] << " =\n\t";
    1374              :                                         outputFeMacroDefineFile
    1375              :                                             << "\t"
    1376              :                                             << "trackerDTC_->"
    1377              :                                             // << "\t" << prepend[i] << "_"
    1378            0 :                                             << functionHeader.substr(0, functionHeader.find('(')) << "(";
    1379              : 
    1380            0 :                                         for(size_t o = 0; o < argNames.size(); o++)
    1381              :                                         {
    1382            0 :                                                 if(o > 0)
    1383            0 :                                                         outputFeMacroDefineFile << ", ";
    1384            0 :                                                 if(argTypes[o] ==
    1385              :                                                    "out*")  // needed to pass as pointer for output result
    1386            0 :                                                         outputFeMacroDefineFile << "&";
    1387            0 :                                                 outputFeMacroDefineFile << argNames[o];
    1388              :                                         }
    1389            0 :                                         outputFeMacroDefineFile << ");\n\n";
    1390              : 
    1391            0 :                                         for(size_t o = 0; o < outputNames.size(); o++)  // set output args
    1392              :                                         {
    1393            0 :                                                 if(outputTypes[o] == "void")
    1394            0 :                                                         continue;  // no output to set
    1395              : 
    1396              :                                                 // handle special output types
    1397            0 :                                                 if(outputTypes[o].find("std::vector") != std::string::npos)
    1398              :                                                         outputFeMacroDefineFile
    1399            0 :                                                             << "\t__SET_ARG_OUT__(\"" << outputNames[o]
    1400            0 :                                                             << "\", StringMacros::vectorToString(" << outputNames[o]
    1401            0 :                                                             << "));\n";
    1402            0 :                                                 else if(outputTypes[o] ==
    1403              :                                                         "std::ostream&")  // special case for ostream
    1404              :                                                 {
    1405              :                                                         outputFeMacroDefineFile << "\t__COUT_MULTI__(2, "
    1406            0 :                                                                                 << outputNames[o] << ".str());\n";
    1407              :                                                         outputFeMacroDefineFile << "\t__SET_ARG_OUT__(\""
    1408            0 :                                                                                 << outputNames[o] << "\", "
    1409            0 :                                                                                 << outputNames[o] << ".str());\n";
    1410              :                                                 }
    1411              :                                                 else  // normal output type
    1412              :                                                         outputFeMacroDefineFile << "\t__SET_ARG_OUT__(\""
    1413            0 :                                                                                 << outputNames[o] << "\", "
    1414            0 :                                                                                 << outputNames[o] << ");\n";
    1415              :                                         }  // end set output args loop
    1416            0 :                                         outputFeMacroDefineFile << "\n";
    1417              : 
    1418              :                                         outputFeMacroDefineFile
    1419            0 :                                             << "} // end FEMacro_" << prepend[i] << "_"
    1420            0 :                                             << functionHeader.substr(0, functionHeader.find('(')) << "()\n";
    1421              :                                 }  // end outputing FE Macro definition, registration, declaration
    1422              : 
    1423              :                                 // flush output files so progress can be debugged if needed
    1424            0 :                                 outputFile.flush();
    1425            0 :                                 outputHeaderFile.flush();
    1426            0 :                                 outputFeMacroDeclareFile.flush();
    1427            0 :                                 outputFeMacroRegisterFile.flush();
    1428            0 :                                 outputFeMacroDefineFile.flush();
    1429              : 
    1430              :                                 // break; //for debugging, only do one function per file
    1431            0 :                         }  // end main function search loop
    1432              : 
    1433            0 :                         outputFile << "// clang-format on\n";
    1434            0 :                         outputHeaderFile << "// clang-format on\n";
    1435            0 :                         outputFeMacroDeclareFile << "// clang-format on\n";
    1436            0 :                         outputFeMacroRegisterFile << "// clang-format on\n";
    1437            0 :                         outputFeMacroDefineFile << "// clang-format on\n";
    1438              : 
    1439            0 :                         outputFile.close();
    1440            0 :                         outputHeaderFile.close();
    1441            0 :                         outputFeMacroDeclareFile.close();
    1442            0 :                         outputFeMacroRegisterFile.close();
    1443            0 :                         outputFeMacroDefineFile.close();
    1444              : 
    1445            0 :                         __COUT_INFO__ << "Successfully wrote output file at " << outputFilePath
    1446            0 :                                       << std::endl;
    1447            0 :                         __COUT_INFO__ << "Successfully wrote header file at " << outputHeaderPath
    1448            0 :                                       << std::endl;
    1449            0 :                         __COUT_INFO__ << "Successfully wrote FE Macro declaration file at "
    1450            0 :                                       << outputFeMacroDeclarePath << std::endl;
    1451            0 :                         __COUT_INFO__ << "Successfully wrote FE Macro registration file at "
    1452            0 :                                       << outputFeMacroPath << std::endl;
    1453            0 :                         __COUT_INFO__ << "Successfully wrote FE Macro define file at "
    1454            0 :                                       << outputFeMacroDefinePath << std::endl;
    1455            0 :                 }
    1456            0 :                 catch(const std::runtime_error& e)
    1457              :                 {
    1458            0 :                         importErrors.push_back(
    1459            0 :                             std::make_pair(importFile,
    1460            0 :                                            prepend[i] + " " + importFile +
    1461            0 :                                                std::string(" std::runtime_error: ") + e.what()));
    1462            0 :                 }
    1463            0 :                 catch(const std::exception& e)
    1464              :                 {
    1465            0 :                         importErrors.push_back(std::make_pair(importFile,
    1466            0 :                                                               prepend[i] + " " + importFile +
    1467            0 :                                                                   std::string(" std::exception: ") +
    1468            0 :                                                                   e.what()));
    1469            0 :                 }
    1470            0 :                 catch(...)
    1471              :                 {
    1472            0 :                         importErrors.push_back(std::make_pair(
    1473              :                             importFile,
    1474            0 :                             prepend[i] + " " + importFile + " Unknown exception occurred."));
    1475            0 :                 }
    1476            0 :         }  // end main import loop
    1477              : 
    1478            0 :         if(importErrors.size())
    1479              :         {
    1480            0 :                 __COUT_ERR__ << "There were " << importErrors.size()
    1481            0 :                              << " errors found while importing. See below:\n"
    1482            0 :                              << std::endl;
    1483            0 :                 for(auto& importErr : importErrors)
    1484            0 :                         __COUT_ERR__ << "\t" << importErr.first << ": " << importErr.second
    1485            0 :                                      << std::endl;
    1486            0 :                 __COUT_ERR__ << "End of errors.\n\n" << std::endl;
    1487              :         }
    1488              :         else
    1489            0 :                 __COUT_INFO__ << "There were NO ERRORS found while loading and exporting groups."
    1490            0 :                               << __E__;
    1491            0 :         std::cout << "Import of Tracker Test Stand complete!\n";
    1492              : 
    1493            0 : }  // end ImportTrackerTestStand()
    1494              : 
    1495              : //==============================================================================
    1496            0 : int main(int argc, char* argv[])
    1497              : {
    1498              :         //==============================================================================
    1499              :         // Define environment variables
    1500              :         //      Note: normally these environment variables are set by ots script
    1501              : 
    1502            0 :         test::util::check_and_make_envs();
    1503              : 
    1504              :         ////////////////////////////////////////////////////
    1505              : 
    1506            0 :         INIT_MF("ImportTrackerTestStand");
    1507            0 :         ImportTrackerTestStand(argc, argv);
    1508            0 :         return 0;
    1509              : }  // end main()
    1510              : // BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1