Fix gcc-8 warnings about strings
authorMark Abraham <mark.j.abraham@gmail.com>
Thu, 27 Sep 2018 18:41:49 +0000 (20:41 +0200)
committerMark Abraham <mark.j.abraham@gmail.com>
Mon, 1 Oct 2018 18:08:41 +0000 (20:08 +0200)
A bunch of slightly risky string handling is now safer or simpler.

Refs #2645

Change-Id: I0e02a34ecf7be16135e406ba2aaefab8a6e6ba39

48 files changed:
cmake/gmxCFlags.cmake
src/gromacs/CMakeLists.txt
src/gromacs/awh/read-params.cpp
src/gromacs/essentialdynamics/edsam.cpp
src/gromacs/ewald/pme-load-balancing.cpp
src/gromacs/fileio/checkpoint.cpp
src/gromacs/fileio/groio.cpp
src/gromacs/fileio/pdbio.cpp
src/gromacs/fileio/readinp.cpp
src/gromacs/fileio/readinp.h
src/gromacs/fileio/warninp.cpp
src/gromacs/fileio/warninp.h
src/gromacs/fileio/xvgr.cpp
src/gromacs/gmxana/gmx_anadock.cpp
src/gromacs/gmxana/gmx_chi.cpp
src/gromacs/gmxana/gmx_covar.cpp
src/gromacs/gmxana/gmx_density.cpp
src/gromacs/gmxana/gmx_densorder.cpp
src/gromacs/gmxana/gmx_hydorder.cpp
src/gromacs/gmxana/gmx_make_ndx.cpp
src/gromacs/gmxana/gmx_traj.cpp
src/gromacs/gmxana/gmx_trjconv.cpp
src/gromacs/gmxana/gmx_tune_pme.cpp
src/gromacs/gmxana/gmx_wham.cpp
src/gromacs/gmxana/powerspect.cpp
src/gromacs/gmxpreprocess/fflibutil.cpp
src/gromacs/gmxpreprocess/grompp.cpp
src/gromacs/gmxpreprocess/pdb2top.cpp
src/gromacs/gmxpreprocess/readpull.cpp
src/gromacs/gmxpreprocess/readrot.cpp
src/gromacs/gmxpreprocess/solvate.cpp
src/gromacs/gmxpreprocess/specbond.cpp
src/gromacs/gmxpreprocess/toppush.cpp
src/gromacs/mdlib/mdebin.cpp
src/gromacs/mdlib/sim_util.cpp
src/gromacs/mdrun/logging.cpp
src/gromacs/mdrunutility/handlerestart.cpp
src/gromacs/mdtypes/inputrec.cpp
src/gromacs/utility/fatalerror.cpp
src/gromacs/utility/fatalerror.h
src/gromacs/utility/futil.cpp
src/gromacs/utility/futil.h
src/gromacs/utility/niceheader.cpp
src/gromacs/utility/path.cpp
src/gromacs/utility/path.h
src/gromacs/utility/sysinfo.cpp
src/gromacs/utility/sysinfo.h
src/gromacs/utility/tests/path.cpp

index fec8adf4223fcd6ad90a77352b1edd462e99f5e7..4cce7cf7a137fee52c1e5f42c63eace0ea35b0aa 100644 (file)
@@ -117,6 +117,8 @@ macro (gmx_c_flags)
             if(CYGWIN)
                 GMX_TEST_CFLAG(CFLAGS_WARN_SUBSCRIPT "-Wno-char-subscripts" GMXC_CFLAGS)
             endif()
+            GMX_TEST_CFLAG(CFLAGS_STRINGOP_TRUNCATION "-Werror=stringop-truncation" GMXC_CFLAGS)
+            GMX_TEST_CFLAG(CFLAGS_FORMAT_OVERFLOW "-Werror=format-overflow" GMXC_CFLAGS)
         endif()
         # new in gcc 4.5
         GMX_TEST_CFLAG(CFLAGS_EXCESS_PREC "-fexcess-precision=fast" GMXC_CFLAGS_RELEASE)
@@ -140,6 +142,11 @@ macro (gmx_c_flags)
                 GMX_TEST_CXXFLAG(CXXFLAGS_WARN_UNDEF "-Wundef" GMXC_CXXFLAGS)
             endif()
             GMX_TEST_CFLAG(CXXFLAGS_WARN_REL "-Wno-array-bounds" GMXC_CXXFLAGS_RELEASE_ONLY)
+            GMX_TEST_CXXFLAG(CXXFLAGS_STRINGOP_TRUNCATION "-Wstringop-truncation" GMXC_CXXFLAGS)
+            if (CXXFLAGS_STRINGOP_TRUNCATION)
+                set(CXXFLAGS_NO_STRINGOP_TRUNCATION "-Wno-stringop-truncation")
+            endif()
+            GMX_TEST_CXXFLAG(CXXFLAGS_FORMAT_OVERFLOW "-Wformat-overflow" GMXC_CXXFLAGS)
         endif()
         # new in gcc 4.5
         GMX_TEST_CXXFLAG(CXXFLAGS_EXCESS_PREC "-fexcess-precision=fast" GMXC_CXXFLAGS_RELEASE)
index 7f9093399ba8fd3afac773cd2bb3315f7cf80ea2..b2ee7eb1664bf396cbb1c2afbc2e236155a3ad23 100644 (file)
@@ -44,6 +44,11 @@ set_property(GLOBAL PROPERTY GMX_INSTALLED_HEADERS)
 set_property(GLOBAL PROPERTY GMX_AVX_512_SOURCE)
 
 add_library(libgromacs_external OBJECT "")
+if(CMAKE_COMPILER_IS_GNUCXX)
+    # Keep quiet about e.g. linearalgebra module
+    target_compile_options(libgromacs_external PRIVATE ${CXXFLAGS_NO_STRINGOP_TRUNCATION})
+endif()
+
 add_library(libgromacs_generated OBJECT "")
 if (BUILD_SHARED_LIBS)
     set_target_properties(libgromacs_external PROPERTIES POSITION_INDEPENDENT_CODE true)
index 353ec243505ccf3763bb49db1fd693ad172921ae..db83a07584c0700c7e19a63785aa95b4990582c5 100644 (file)
@@ -54,6 +54,7 @@
 #include "gromacs/utility/cstringutil.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 #include "biasparams.h"
 #include "biassharing.h"
@@ -87,31 +88,30 @@ const char *eawhcoordprovider_names[eawhcoordproviderNR+1] = {
  * \param[in,out] wi         Struct for bookeeping warnings.
  * \param[in] bComment       True if comments should be printed.
  */
-static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
+static void readDimParams(std::vector<t_inpfile> *inp, const std::string &prefix,
                           AwhDimParams *dimParams, const pull_params_t *pull_params,
                           warninp_t wi, bool bComment)
 {
-    char                    warningmsg[STRLEN];
-
+    std::string opt;
     if (bComment)
     {
         printStringNoNewline(inp, "The provider of the reaction coordinate, currently only pull is supported");
     }
-    char opt[STRLEN];
-    sprintf(opt, "%s-coord-provider", prefix);
+
+    opt = prefix + "-coord-provider";
     dimParams->eCoordProvider = get_eeenum(inp, opt, eawhcoordprovider_names, wi);
 
     if (bComment)
     {
         printStringNoNewline(inp, "The coordinate index for this dimension");
     }
-    sprintf(opt, "%s-coord-index", prefix);
+    opt = prefix + "-coord-index";
     int coordIndexInput;
     coordIndexInput = get_eint(inp, opt, 1, wi);
     if (coordIndexInput <  1)
     {
         gmx_fatal(FARGS, "Failed to read a valid coordinate index for %s. "
-                  "Note that the pull coordinate indexing starts at 1.", opt);
+                  "Note that the pull coordinate indexing starts at 1.", opt.c_str());
     }
 
     /* The pull coordinate indices start at 1 in the input file, at 0 internally */
@@ -131,8 +131,9 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
     }
     if (pull_params->coord[dimParams->coordIndex].rate != 0)
     {
-        sprintf(warningmsg, "Setting pull-coord%d-rate (%g) is incompatible with AWH biasing this coordinate", coordIndexInput, pull_params->coord[dimParams->coordIndex].rate);
-        warning_error(wi, warningmsg);
+        auto message = formatString("Setting pull-coord%d-rate (%g) is incompatible with AWH biasing this coordinate",
+                                    coordIndexInput, pull_params->coord[dimParams->coordIndex].rate);
+        warning_error(wi, message);
     }
 
     /* Grid params for each axis */
@@ -143,18 +144,18 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
         printStringNoNewline(inp, "Start and end values for each coordinate dimension");
     }
 
-    sprintf(opt, "%s-start", prefix);
+    opt               = prefix + "-start";
     dimParams->origin = get_ereal(inp, opt, 0., wi);
 
-    sprintf(opt, "%s-end", prefix);
+    opt            = prefix + "-end";
     dimParams->end = get_ereal(inp, opt, 0., wi);
 
     if (gmx_within_tol(dimParams->end - dimParams->origin, 0, GMX_REAL_EPS))
     {
-        sprintf(warningmsg, "The given interval length given by %s-start (%g) and %s-end (%g) is zero. "
-                "This will result in only one point along this axis in the coordinate value grid.",
-                prefix, dimParams->origin, prefix, dimParams->end);
-        warning(wi, warningmsg);
+        auto message = formatString("The given interval length given by %s-start (%g) and %s-end (%g) is zero. "
+                                    "This will result in only one point along this axis in the coordinate value grid.",
+                                    prefix.c_str(), dimParams->origin, prefix.c_str(), dimParams->end);
+        warning(wi, message);
     }
     /* Check that the requested interval is in allowed range */
     if (eGeom == epullgDIST)
@@ -163,7 +164,7 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
         {
             gmx_fatal(FARGS, "%s-start (%g) or %s-end (%g) set to a negative value. With pull geometry distance coordinate values are non-negative. "
                       "Perhaps you want to use geometry %s instead?",
-                      prefix, dimParams->origin, prefix, dimParams->end, EPULLGEOM(epullgDIR));
+                      prefix.c_str(), dimParams->origin, prefix.c_str(), dimParams->end, EPULLGEOM(epullgDIR));
         }
     }
     else if (eGeom == epullgANGLE || eGeom == epullgANGLEAXIS)
@@ -171,7 +172,7 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
         if (dimParams->origin < 0 || dimParams->end > 180)
         {
             gmx_fatal(FARGS, "%s-start (%g) and %s-end (%g) are outside of the allowed range 0 to 180 deg for pull geometries %s and %s ",
-                      prefix, dimParams->origin, prefix, dimParams->end, EPULLGEOM(epullgANGLE), EPULLGEOM(epullgANGLEAXIS));
+                      prefix.c_str(), dimParams->origin, prefix.c_str(), dimParams->end, EPULLGEOM(epullgANGLE), EPULLGEOM(epullgANGLEAXIS));
         }
     }
     else if (eGeom == epullgDIHEDRAL)
@@ -179,7 +180,7 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
         if (dimParams->origin < -180 || dimParams->end > 180)
         {
             gmx_fatal(FARGS, "%s-start (%g) and %s-end (%g) are outside of the allowed range -180 to 180 deg for pull geometry %s. ",
-                      prefix, dimParams->origin, prefix, dimParams->end, EPULLGEOM(epullgDIHEDRAL));
+                      prefix.c_str(), dimParams->origin, prefix.c_str(), dimParams->end, EPULLGEOM(epullgDIHEDRAL));
         }
     }
 
@@ -187,7 +188,7 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
     {
         printStringNoNewline(inp, "The force constant for this coordinate (kJ/mol/nm^2 or kJ/mol/rad^2)");
     }
-    sprintf(opt, "%s-force-constant", prefix);
+    opt = prefix + "-force-constant";
     dimParams->forceConstant = get_ereal(inp, opt, 0, wi);
     if (dimParams->forceConstant <= 0)
     {
@@ -198,16 +199,17 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
     {
         printStringNoNewline(inp, "Estimated diffusion constant (nm^2/ps or rad^2/ps)");
     }
-    sprintf(opt, "%s-diffusion", prefix);
+    opt                  = prefix + "-diffusion";
     dimParams->diffusion = get_ereal(inp, opt, 0, wi);
 
     if (dimParams->diffusion <= 0)
     {
         const double diffusion_default = 1e-5;
-        sprintf(warningmsg, "%s not explicitly set by user."
-                " You can choose to use a default value (%g nm^2/ps or rad^2/ps) but this may very well be non-optimal for your system!",
-                opt, diffusion_default);
-        warning(wi, warningmsg);
+        auto         message           = formatString
+                ("%s not explicitly set by user. You can choose to use a default "
+                "value (%g nm^2/ps or rad^2/ps) but this may very well be "
+                "non-optimal for your system!", opt.c_str(), diffusion_default);
+        warning(wi, message);
         dimParams->diffusion = diffusion_default;
     }
 
@@ -215,13 +217,13 @@ static void readDimParams(std::vector<t_inpfile> *inp, const char *prefix,
     {
         printStringNoNewline(inp, "Diameter that needs to be sampled around a point before it is considered covered.");
     }
-    sprintf(opt, "%s-cover-diameter", prefix);
+    opt = prefix + "-cover-diameter";
     dimParams->coverDiameter = get_ereal(inp, opt, 0, wi);
 
     if (dimParams->coverDiameter < 0)
     {
         gmx_fatal(FARGS, "%s (%g) cannot be negative.",
-                  opt, dimParams->coverDiameter);
+                  opt.c_str(), dimParams->coverDiameter);
     }
 }
 
@@ -255,68 +257,65 @@ static void checkInputConsistencyAwhBias(const AwhBiasParams &awhBiasParams,
  * \param[in,out] wi             Struct for bookeeping warnings.
  * \param[in]     bComment       True if comments should be printed.
  */
-static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBiasParams, const char *prefix,
+static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBiasParams, const std::string &prefix,
                              const t_inputrec *ir, warninp_t wi, bool bComment)
 {
-    char       opt[STRLEN], prefixdim[STRLEN];
-    char       warningmsg[STRLEN];
-
     if (bComment)
     {
         printStringNoNewline(inp, "Estimated initial PMF error (kJ/mol)");
     }
-    sprintf(opt, "%s-error-init", prefix);
 
+    std::string opt = prefix + "-error-init";
     /* We allow using a default value here without warning (but warn the user if the diffusion constant is not set). */
     awhBiasParams->errorInitial = get_ereal(inp, opt, 10, wi);
     if (awhBiasParams->errorInitial <= 0)
     {
-        gmx_fatal(FARGS, "%s needs to be > 0.", opt);
+        gmx_fatal(FARGS, "%s needs to be > 0.", opt.c_str());
     }
 
     if (bComment)
     {
         printStringNoNewline(inp, "Growth rate of the reference histogram determining the bias update size: exp-linear or linear");
     }
-    sprintf(opt, "%s-growth", prefix);
+    opt                    = prefix + "-growth";
     awhBiasParams->eGrowth = get_eeenum(inp, opt, eawhgrowth_names, wi);
 
     if (bComment)
     {
         printStringNoNewline(inp, "Start the simulation by equilibrating histogram towards the target distribution: no or yes");
     }
-    sprintf(opt, "%s-equilibrate-histogram", prefix);
+    opt = prefix + "-equilibrate-histogram";
     awhBiasParams->equilibrateHistogram = (get_eeenum(inp, opt, yesno_names, wi) != 0);
     if (awhBiasParams->equilibrateHistogram && awhBiasParams->eGrowth != eawhgrowthEXP_LINEAR)
     {
-        sprintf(warningmsg, "Option %s will only have an effect for histogram growth type '%s'.",
-                opt, EAWHGROWTH(eawhgrowthEXP_LINEAR));
-        warning(wi, warningmsg);
+        auto message = formatString("Option %s will only have an effect for histogram growth type '%s'.",
+                                    opt.c_str(), EAWHGROWTH(eawhgrowthEXP_LINEAR));
+        warning(wi, message);
     }
 
     if (bComment)
     {
         printStringNoNewline(inp, "Target distribution type: constant, cutoff, boltzmann or local-boltzmann");
     }
-    sprintf(opt, "%s-target", prefix);
+    opt                    = prefix + "-target";
     awhBiasParams->eTarget = get_eeenum(inp, opt, eawhtarget_names, wi);
 
     if ((awhBiasParams->eTarget == eawhtargetLOCALBOLTZMANN) &&
         (awhBiasParams->eGrowth == eawhgrowthEXP_LINEAR))
     {
-        sprintf(warningmsg, "Target type '%s' combined with histogram growth type '%s' is not "
-                "expected to give stable bias updates. You probably want to use growth type "
-                "'%s' instead.",
-                EAWHTARGET(eawhtargetLOCALBOLTZMANN), EAWHGROWTH(eawhgrowthEXP_LINEAR),
-                EAWHGROWTH(eawhgrowthLINEAR));
-        warning(wi, warningmsg);
+        auto message = formatString("Target type '%s' combined with histogram growth type '%s' is not "
+                                    "expected to give stable bias updates. You probably want to use growth type "
+                                    "'%s' instead.",
+                                    EAWHTARGET(eawhtargetLOCALBOLTZMANN), EAWHGROWTH(eawhgrowthEXP_LINEAR),
+                                    EAWHGROWTH(eawhgrowthLINEAR));
+        warning(wi, message);
     }
 
     if (bComment)
     {
         printStringNoNewline(inp, "Boltzmann beta scaling factor for target distribution types 'boltzmann' and 'boltzmann-local'");
     }
-    sprintf(opt, "%s-target-beta-scaling", prefix);
+    opt = prefix + "-target-beta-scaling";
     awhBiasParams->targetBetaScaling = get_ereal(inp, opt, 0, wi);
 
     switch (awhBiasParams->eTarget)
@@ -326,14 +325,14 @@ static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBias
             if (awhBiasParams->targetBetaScaling < 0 || awhBiasParams->targetBetaScaling > 1)
             {
                 gmx_fatal(FARGS, "%s = %g is not useful for target type %s.",
-                          opt, awhBiasParams->targetBetaScaling, EAWHTARGET(awhBiasParams->eTarget));
+                          opt.c_str(), awhBiasParams->targetBetaScaling, EAWHTARGET(awhBiasParams->eTarget));
             }
             break;
         default:
             if (awhBiasParams->targetBetaScaling != 0)
             {
                 gmx_fatal(FARGS, "Value for %s (%g) set explicitly but will not be used for target type %s.",
-                          opt, awhBiasParams->targetBetaScaling, EAWHTARGET(awhBiasParams->eTarget));
+                          opt.c_str(), awhBiasParams->targetBetaScaling, EAWHTARGET(awhBiasParams->eTarget));
             }
             break;
     }
@@ -342,7 +341,7 @@ static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBias
     {
         printStringNoNewline(inp, "Free energy cutoff value for target distribution type 'cutoff'");
     }
-    sprintf(opt, "%s-target-cutoff", prefix);
+    opt = prefix + "-target-cutoff";
     awhBiasParams->targetCutoff = get_ereal(inp, opt, 0, wi);
 
     switch (awhBiasParams->eTarget)
@@ -351,14 +350,14 @@ static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBias
             if (awhBiasParams->targetCutoff <= 0)
             {
                 gmx_fatal(FARGS, "%s = %g is not useful for target type %s.",
-                          opt, awhBiasParams->targetCutoff, EAWHTARGET(awhBiasParams->eTarget));
+                          opt.c_str(), awhBiasParams->targetCutoff, EAWHTARGET(awhBiasParams->eTarget));
             }
             break;
         default:
             if (awhBiasParams->targetCutoff != 0)
             {
                 gmx_fatal(FARGS, "Value for %s (%g) set explicitly but will not be used for target type %s.",
-                          opt, awhBiasParams->targetCutoff, EAWHTARGET(awhBiasParams->eTarget));
+                          opt.c_str(), awhBiasParams->targetCutoff, EAWHTARGET(awhBiasParams->eTarget));
             }
             break;
     }
@@ -367,14 +366,14 @@ static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBias
     {
         printStringNoNewline(inp, "Initialize PMF and target with user data: no or yes");
     }
-    sprintf(opt, "%s-user-data", prefix);
+    opt = prefix + "-user-data";
     awhBiasParams->bUserData = get_eeenum(inp, opt, yesno_names, wi);
 
     if (bComment)
     {
         printStringNoNewline(inp, "Group index to share the bias with, 0 means not shared");
     }
-    sprintf(opt, "%s-share-group", prefix);
+    opt = prefix + "-share-group";
     awhBiasParams->shareGroup = get_eint(inp, opt, 0, wi);
     if (awhBiasParams->shareGroup < 0)
     {
@@ -385,13 +384,13 @@ static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBias
     {
         printStringNoNewline(inp, "Dimensionality of the coordinate");
     }
-    sprintf(opt, "%s-ndim", prefix);
+    opt                 = prefix + "-ndim";
     awhBiasParams->ndim = get_eint(inp, opt, 0, wi);
 
     if (awhBiasParams->ndim <= 0 ||
         awhBiasParams->ndim > c_biasMaxNumDim)
     {
-        gmx_fatal(FARGS, "%s-ndim (%d) needs to be > 0 and at most %d\n", prefix,  awhBiasParams->ndim, c_biasMaxNumDim);
+        gmx_fatal(FARGS, "%s (%d) needs to be > 0 and at most %d\n", opt.c_str(),  awhBiasParams->ndim, c_biasMaxNumDim);
     }
     if (awhBiasParams->ndim > 2)
     {
@@ -402,7 +401,7 @@ static void read_bias_params(std::vector<t_inpfile> *inp, AwhBiasParams *awhBias
     for (int d = 0; d < awhBiasParams->ndim; d++)
     {
         bComment = bComment && d == 0;
-        sprintf(prefixdim, "%s-dim%d", prefix, d + 1);
+        std::string prefixdim = prefix + formatString("-dim%d", d + 1);
         readDimParams(inp, prefixdim, &awhBiasParams->dimParams[d], ir->pull, wi, bComment);
     }
 
@@ -470,21 +469,18 @@ static void checkInputConsistencyAwh(const AwhParams &awhParams,
 
 AwhParams *readAndCheckAwhParams(std::vector<t_inpfile> *inp, const t_inputrec *ir, warninp_t wi)
 {
-    char       opt[STRLEN], prefix[STRLEN], prefixawh[STRLEN];
-
-    AwhParams *awhParams;
+    AwhParams  *awhParams;
     snew(awhParams, 1);
-
-    sprintf(prefix, "%s", "awh");
+    std::string opt;
 
     /* Parameters common for all biases */
 
     printStringNoNewline(inp, "The way to apply the biasing potential: convolved or umbrella");
-    sprintf(opt, "%s-potential", prefix);
+    opt                   = "awh-potential";
     awhParams->ePotential = get_eeenum(inp, opt, eawhpotential_names, wi);
 
     printStringNoNewline(inp, "The random seed used for sampling the umbrella center in the case of umbrella type potential");
-    sprintf(opt, "%s-seed", prefix);
+    opt             = "awh-seed";
     awhParams->seed = get_eint(inp, opt, -1, wi);
     if (awhParams->seed == -1)
     {
@@ -493,48 +489,44 @@ AwhParams *readAndCheckAwhParams(std::vector<t_inpfile> *inp, const t_inputrec *
     }
 
     printStringNoNewline(inp, "Data output interval in number of steps");
-    sprintf(opt, "%s-nstout", prefix);
+    opt               = "awh-nstout";
     awhParams->nstOut = get_eint(inp, opt, 100000, wi);
     if (awhParams->nstOut <= 0)
     {
-        char buf[STRLEN];
-        sprintf(buf, "Not writing AWH output with AWH (%s = %d) does not make sense",
-                opt, awhParams->nstOut);
-        warning_error(wi, buf);
+        auto message = formatString("Not writing AWH output with AWH (%s = %d) does not make sense",
+                                    opt.c_str(), awhParams->nstOut);
+        warning_error(wi, message);
     }
     /* This restriction can be removed by changing a flag of print_ebin() */
     if (ir->nstenergy == 0 || awhParams->nstOut % ir->nstenergy != 0)
     {
-        char buf[STRLEN];
-        sprintf(buf, "%s (%d) should be a multiple of nstenergy (%d)",
-                opt, awhParams->nstOut, ir->nstenergy);
-        warning_error(wi, buf);
+        auto message = formatString("%s (%d) should be a multiple of nstenergy (%d)",
+                                    opt.c_str(), awhParams->nstOut, ir->nstenergy);
+        warning_error(wi, message);
     }
 
     printStringNoNewline(inp, "Coordinate sampling interval in number of steps");
-    sprintf(opt, "%s-nstsample", prefix);
+    opt = "awh-nstsample";
     awhParams->nstSampleCoord = get_eint(inp, opt, 10, wi);
 
     printStringNoNewline(inp, "Free energy and bias update interval in number of samples");
-    sprintf(opt, "%s-nsamples-update", prefix);
+    opt = "awh-nsamples-update";
     awhParams->numSamplesUpdateFreeEnergy = get_eint(inp, opt, 10, wi);
     if (awhParams->numSamplesUpdateFreeEnergy <= 0)
     {
-        char buf[STRLEN];
-        sprintf(buf, "%s needs to be an integer > 0", opt);
-        warning_error(wi, buf);
+        warning_error(wi, opt + " needs to be an integer > 0");
     }
 
     printStringNoNewline(inp, "When true, biases with share-group>0 are shared between multiple simulations");
-    sprintf(opt, "%s-share-multisim", prefix);
+    opt = "awh-share-multisim";
     awhParams->shareBiasMultisim = (get_eeenum(inp, opt, yesno_names, wi) != 0);
 
     printStringNoNewline(inp, "The number of independent AWH biases");
-    sprintf(opt, "%s-nbias", prefix);
+    opt                = "awh-nbias";
     awhParams->numBias = get_eint(inp, opt, 1, wi);
     if (awhParams->numBias <= 0)
     {
-        gmx_fatal(FARGS, "%s needs to be an integer > 0", opt);
+        gmx_fatal(FARGS, "%s needs to be an integer > 0", opt.c_str());
     }
 
     /* Read the parameters specific to each AWH bias */
@@ -542,8 +534,8 @@ AwhParams *readAndCheckAwhParams(std::vector<t_inpfile> *inp, const t_inputrec *
 
     for (int k = 0; k < awhParams->numBias; k++)
     {
-        bool bComment = (k == 0);
-        sprintf(prefixawh, "%s%d", prefix, k + 1);
+        bool        bComment  = (k == 0);
+        std::string prefixawh = formatString("awh%d", k + 1);
         read_bias_params(inp, &awhParams->awhBiasParams[k], prefixawh, ir, wi, bComment);
     }
 
@@ -728,13 +720,12 @@ static void checkInputConsistencyInterval(const AwhParams *awhParams, warninp_t
             /* Warn if the pull initial coordinate value is not in the grid */
             if (!valueIsInInterval(origin, end, period, coordValueInit))
             {
-                char       warningmsg[STRLEN];
-                sprintf(warningmsg, "The initial coordinate value (%.8g) for pull coordinate index %d falls outside "
+                auto message = formatString
+                        ("The initial coordinate value (%.8g) for pull coordinate index %d falls outside "
                         "of the sampling nterval awh%d-dim%d-start (%.8g) to awh%d-dim%d-end (%.8g). "
                         "This can lead to large initial forces pulling the coordinate towards the sampling interval.",
-                        coordValueInit, coordIndex + 1,
-                        k + 1, d + 1, origin, k + 1, d + 1, end);
-                warning(wi, warningmsg);
+                        coordValueInit, coordIndex + 1, k + 1, d + 1, origin, k + 1, d + 1, end);
+                warning(wi, message);
             }
         }
     }
index db1b4d12de9b6a7bc4862ccb470d3d6a476b1141..c6e428b337ffc8dc8fca57f22b0f5ba15d7e0a4f 100644 (file)
@@ -2421,7 +2421,7 @@ static void init_edsamstate(const gmx_edsam &ed, edsamhistory_t *EDstate)
 
 
 /* Adds 'buf' to 'str' */
-static void add_to_string(char **str, char *buf)
+static void add_to_string(char **str, const char *buf)
 {
     int len;
 
@@ -2432,7 +2432,7 @@ static void add_to_string(char **str, char *buf)
 }
 
 
-static void add_to_string_aligned(char **str, char *buf)
+static void add_to_string_aligned(char **str, const char *buf)
 {
     char buf_aligned[STRLEN];
 
@@ -2443,13 +2443,10 @@ static void add_to_string_aligned(char **str, char *buf)
 
 static void nice_legend(const char ***setname, int *nsets, char **LegendStr, const char *value, const char *unit, char EDgroupchar)
 {
-    char tmp[STRLEN], tmp2[STRLEN];
-
-
-    sprintf(tmp, "%c %s", EDgroupchar, value);
-    add_to_string_aligned(LegendStr, tmp);
-    sprintf(tmp2, "%s (%s)", tmp, unit);
-    (*setname)[*nsets] = gmx_strdup(tmp2);
+    auto tmp = gmx::formatString("%c %s", EDgroupchar, value);
+    add_to_string_aligned(LegendStr, tmp.c_str());
+    tmp               += gmx::formatString(" (%s)", unit);
+    (*setname)[*nsets] = gmx_strdup(tmp.c_str());
     (*nsets)++;
 }
 
index 491a2771f4db79f930020cb95e57b776e97b73a0..6aad33b9ef5320b0410f1636c8ffe40c5268402b 100644 (file)
@@ -77,6 +77,7 @@
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/logger.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/strconvert.h"
 
 #include "pme-internal.h"
 
@@ -431,28 +432,21 @@ static void print_grid(FILE *fp_err, FILE *fp_log,
                        const pme_setup_t *set,
                        double cycles)
 {
-    char buf[STRLEN], buft[STRLEN];
-
+    auto buf = gmx::formatString("%-11s%10s pme grid %d %d %d, coulomb cutoff %.3f",
+                                 pre, desc,
+                                 set->grid[XX], set->grid[YY], set->grid[ZZ], set->rcut_coulomb);
     if (cycles >= 0)
     {
-        sprintf(buft, ": %.1f M-cycles", cycles*1e-6);
+        buf += gmx::formatString(": %.1f M-cycles", cycles*1e-6);
     }
-    else
-    {
-        buft[0] = '\0';
-    }
-    sprintf(buf, "%-11s%10s pme grid %d %d %d, coulomb cutoff %.3f%s",
-            pre,
-            desc, set->grid[XX], set->grid[YY], set->grid[ZZ], set->rcut_coulomb,
-            buft);
     if (fp_err != nullptr)
     {
-        fprintf(fp_err, "\r%s\n", buf);
+        fprintf(fp_err, "\r%s\n", buf.c_str());
         fflush(fp_err);
     }
     if (fp_log != nullptr)
     {
-        fprintf(fp_log, "%s\n", buf);
+        fprintf(fp_log, "%s\n", buf.c_str());
     }
 }
 
@@ -475,20 +469,18 @@ static void print_loadbal_limited(FILE *fp_err, FILE *fp_log,
                                   int64_t step,
                                   pme_load_balancing_t *pme_lb)
 {
-    char buf[STRLEN], sbuf[22];
-
-    sprintf(buf, "step %4s: the %s limits the PME load balancing to a coulomb cut-off of %.3f",
-            gmx_step_str(step, sbuf),
-            pmelblim_str[pme_lb->elimited],
-            pme_lb->setup[pme_loadbal_end(pme_lb)-1].rcut_coulomb);
+    auto buf = gmx::formatString("step %4s: the %s limits the PME load balancing to a coulomb cut-off of %.3f",
+                                 gmx::int64ToString(step).c_str(),
+                                 pmelblim_str[pme_lb->elimited],
+                                 pme_lb->setup[pme_loadbal_end(pme_lb)-1].rcut_coulomb);
     if (fp_err != nullptr)
     {
-        fprintf(fp_err, "\r%s\n", buf);
+        fprintf(fp_err, "\r%s\n", buf.c_str());
         fflush(fp_err);
     }
     if (fp_log != nullptr)
     {
-        fprintf(fp_log, "%s\n", buf);
+        fprintf(fp_log, "%s\n", buf.c_str());
     }
 }
 
index b401426d240b02e164c86f502e307ecccf11d9ff..60a60e60ec2df37aa75a79e587dd0f64243bc8cf 100644 (file)
@@ -1855,13 +1855,12 @@ void write_checkpoint(const char *fn, gmx_bool bNumberAndKeep,
     snew(fntemp, std::strlen(fn));
     std::strcpy(fntemp, fn);
 #endif
-    char timebuf[STRLEN];
-    gmx_format_current_time(timebuf, STRLEN);
+    std::string timebuf = gmx_format_current_time();
 
     if (fplog)
     {
         fprintf(fplog, "Writing checkpoint, step %s at %s\n\n",
-                gmx_step_str(step, buf), timebuf);
+                gmx_step_str(step, buf), timebuf.c_str());
     }
 
     /* Get offsets for open files */
@@ -1964,7 +1963,7 @@ void write_checkpoint(const char *fn, gmx_bool bNumberAndKeep,
     };
     std::strcpy(headerContents.version, gmx_version());
     std::strcpy(headerContents.fprog, gmx::getProgramContext().fullBinaryPath());
-    std::strcpy(headerContents.ftime, timebuf);
+    std::strcpy(headerContents.ftime, timebuf.c_str());
     if (DOMAINDECOMP(cr))
     {
         copy_ivec(domdecCells, headerContents.dd_nc);
@@ -2575,7 +2574,7 @@ void read_checkpoint_part_and_step(const char  *filename,
 
     if (filename == nullptr ||
         !gmx_fexist(filename) ||
-        (!(fp = gmx_fio_open(filename, "r"))))
+        ((fp = gmx_fio_open(filename, "r")) == nullptr))
     {
         *simulation_part = 0;
         *step            = 0;
index 5ee1805b3945dc17f4aa4a3f8f12539ed4e1c925..5c7112f7ed31c2e08bd2f1a52005f36fae191d96 100644 (file)
@@ -455,7 +455,6 @@ void write_hconf_indexed_p(FILE *out, const char *title, const t_atoms *atoms,
                            int nx, const int index[],
                            const rvec *x, const rvec *v, const matrix box)
 {
-    char resnm[6], nm[6];
     int  ai, i, resind, resnr;
 
     fprintf(out, "%s\n", (title && title[0]) ? title : gmx::bromacs().c_str());
@@ -468,28 +467,29 @@ void write_hconf_indexed_p(FILE *out, const char *title, const t_atoms *atoms,
         ai = index[i];
 
         resind = atoms->atom[ai].resind;
-        std::strncpy(resnm, " ??? ", sizeof(resnm)-1);
+        std::string resnm;
         if (resind < atoms->nres)
         {
-            std::strncpy(resnm, *atoms->resinfo[resind].name, sizeof(resnm)-1);
+            resnm = *atoms->resinfo[resind].name;
             resnr = atoms->resinfo[resind].nr;
         }
         else
         {
-            std::strncpy(resnm, " ??? ", sizeof(resnm)-1);
+            resnm = " ??? ";
             resnr = resind + 1;
         }
 
+        std::string nm;
         if (atoms->atom)
         {
-            std::strncpy(nm, *atoms->atomname[ai], sizeof(nm)-1);
+            nm = *atoms->atomname[i];
         }
         else
         {
-            std::strncpy(nm, " ??? ", sizeof(nm)-1);
+            nm = " ??? ";
         }
 
-        fprintf(out, "%5d%-5.5s%5.5s%5d", resnr%100000, resnm, nm, (ai+1)%100000);
+        fprintf(out, "%5d%-5.5s%5.5s%5d", resnr%100000, resnm.c_str(), nm.c_str(), (ai+1)%100000);
         /* next fprintf uses built format string */
         if (v)
         {
index 48dc48d246f23fce6caaa61b380b46a185440db9..26dfd28c149fbbd6e03b99943f26cd922ea82e31 100644 (file)
@@ -97,21 +97,20 @@ static void xlate_atomname_pdb2gmx(char *name)
     }
 }
 
-static void xlate_atomname_gmx2pdb(char *name)
+// Deliberately taking a copy of name to return it later
+static std::string xlate_atomname_gmx2pdb(std::string name)
 {
-    int  i, length;
-    char temp;
-
-    length = std::strlen(name);
+    size_t length = name.size();
     if (length > 3 && std::isdigit(name[length-1]))
     {
-        temp = name[length-1];
-        for (i = length-1; i > 0; --i)
+        char temp = name[length-1];
+        for (size_t i = length-1; i > 0; --i)
         {
             name[i] = name[i-1];
         }
         name[0] = temp;
     }
+    return name;
 }
 
 
@@ -311,7 +310,6 @@ void write_pdbfile_indexed(FILE *out, const char *title,
                            bool usePqrFormat)
 {
     gmx_conect_t     *gc = static_cast<gmx_conect_t *>(conect);
-    char              resnm[6], nm[6];
     int               i, ii;
     int               resind, resnr;
     enum PDB_record   type;
@@ -372,13 +370,11 @@ void write_pdbfile_indexed(FILE *out, const char *title,
             lastchainnum    = chainnum;
         }
 
-        strncpy(resnm, *atoms->resinfo[resind].name, sizeof(resnm)-1);
-        resnm[sizeof(resnm)-1] = 0;
-        strncpy(nm, *atoms->atomname[i], sizeof(nm)-1);
-        nm[sizeof(nm)-1] = 0;
+        std::string resnm = *atoms->resinfo[resind].name;
+        std::string nm    = *atoms->atomname[i];
 
         /* rename HG12 to 2HG1, etc. */
-        xlate_atomname_gmx2pdb(nm);
+        nm    = xlate_atomname_gmx2pdb(nm);
         resnr = atoms->resinfo[resind].nr;
         resic = atoms->resinfo[resind].ic;
         if (chainid != ' ')
@@ -420,9 +416,9 @@ void write_pdbfile_indexed(FILE *out, const char *title,
             gmx_fprintf_pdb_atomline(out,
                                      type,
                                      i+1,
-                                     nm,
+                                     nm.c_str(),
                                      altloc,
-                                     resnm,
+                                     resnm.c_str(),
                                      ch,
                                      resnr,
                                      resic,
@@ -434,7 +430,7 @@ void write_pdbfile_indexed(FILE *out, const char *title,
             if (atoms->pdbinfo && atoms->pdbinfo[i].bAnisotropic)
             {
                 fprintf(out, "ANISOU%5d  %-4.4s%4.4s%c%4d%c %7d%7d%7d%7d%7d%7d\n",
-                        (i+1)%100000, nm, resnm, ch, resnr,
+                        (i+1)%100000, nm.c_str(), resnm.c_str(), ch, resnr,
                         (resic == '\0') ? ' ' : resic,
                         atoms->pdbinfo[i].uij[0], atoms->pdbinfo[i].uij[1],
                         atoms->pdbinfo[i].uij[2], atoms->pdbinfo[i].uij[3],
@@ -446,8 +442,8 @@ void write_pdbfile_indexed(FILE *out, const char *title,
             gmx_fprintf_pqr_atomline(out,
                                      type,
                                      i+1,
-                                     nm,
-                                     resnm,
+                                     nm.c_str(),
+                                     resnm.c_str(),
                                      ch,
                                      resnr,
                                      10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ],
@@ -815,18 +811,17 @@ gmx_bool is_dummymass(const char *nm)
 
 static void gmx_conect_addline(gmx_conect_t *con, char *line)
 {
-    int  n, ai, aj;
-    char format[32], form2[32];
+    int         n, ai, aj;
 
-    sprintf(form2, "%%*s");
-    sprintf(format, "%s%%d", form2);
-    if (sscanf(line, format, &ai) == 1)
+    std::string form2  = "%%*s";
+    std::string format = form2 + "%%d";
+    if (sscanf(line, format.c_str(), &ai) == 1)
     {
         do
         {
-            std::strcat(form2, "%*s");
-            sprintf(format, "%s%%d", form2);
-            n = sscanf(line, format, &aj);
+            form2 += "%*s";
+            format = form2 + "%%d";
+            n      = sscanf(line, format.c_str(), &aj);
             if (n == 1)
             {
                 srenew(con->conect, ++con->nconect);
index bc3d674192fc29700e2ec811b12a454e1b701d72..0e170aea55e7c448c4c4fa43d7d8a423933f581e 100644 (file)
@@ -369,6 +369,12 @@ int get_eint(std::vector<t_inpfile> *inp, const char *name, int def,
     }
 }
 
+int get_eint(std::vector<t_inpfile> *inp, const std::string &name, int def,
+             warninp_t wi)
+{
+    return get_eint(inp, name.c_str(), def, wi);
+}
+
 /* Note that sanitizing the trailing part of inp[ii].value was the responsibility of read_inpfile() */
 int64_t get_eint64(std::vector<t_inpfile> *inp,
                    const char *name, int64_t def,
@@ -399,6 +405,13 @@ int64_t get_eint64(std::vector<t_inpfile> *inp,
     }
 }
 
+int64_t get_eint64(std::vector<t_inpfile> *inp,
+                   const std::string &name, int64_t def,
+                   warninp_t wi)
+{
+    return get_eint64(inp, name.c_str(), def, wi);
+}
+
 /* Note that sanitizing the trailing part of inp[ii].value was the responsibility of read_inpfile() */
 double get_ereal(std::vector<t_inpfile> *inp, const char *name, double def,
                  warninp_t wi)
@@ -428,6 +441,12 @@ double get_ereal(std::vector<t_inpfile> *inp, const char *name, double def,
     }
 }
 
+double get_ereal(std::vector<t_inpfile> *inp, const std::string &name, double def,
+                 warninp_t wi)
+{
+    return get_ereal(inp, name.c_str(), def, wi);
+}
+
 /* Note that sanitizing the trailing part of inp[ii].value was the responsibility of read_inpfile() */
 const char *get_estr(std::vector<t_inpfile> *inp, const char *name, const char *def)
 {
@@ -456,6 +475,11 @@ const char *get_estr(std::vector<t_inpfile> *inp, const char *name, const char *
     }
 }
 
+const char *get_estr(std::vector<t_inpfile> *inp, const std::string &name, const char *def)
+{
+    return get_estr(inp, name.c_str(), def);
+}
+
 /* Note that sanitizing the trailing part of inp[ii].value was the responsibility of read_inpfile() */
 int get_eeenum(std::vector<t_inpfile> *inp, const char *name, const char **defs,
                warninp_t wi)
@@ -509,6 +533,12 @@ int get_eeenum(std::vector<t_inpfile> *inp, const char *name, const char **defs,
     return i;
 }
 
+int get_eeenum(std::vector<t_inpfile> *inp, const std::string &name, const char **defs,
+               warninp_t wi)
+{
+    return get_eeenum(inp, name.c_str(), defs, wi);
+}
+
 int get_eenum(std::vector<t_inpfile> *inp, const char *name, const char **defs)
 {
     return get_eeenum(inp, name, defs, nullptr);
index 7a1e1f3216171c35385c2a69609514b61c740d51..6fb6d2111de03250abca27307e439225773d609b 100644 (file)
@@ -135,19 +135,30 @@ void mark_einp_set(gmx::ArrayRef<t_inpfile> inp, const char *name);
 
 int get_eint(std::vector<t_inpfile> *inp, const char *name, int def,
              warninp_t wi);
+int get_eint(std::vector<t_inpfile> *inp, const std::string &name, int def,
+             warninp_t wi);
 
 int64_t get_eint64(std::vector<t_inpfile> *inp,
                    const char *name, int64_t def,
-                   warninp_t /*wi*/);
+                   warninp_t wi);
+int64_t get_eint64(std::vector<t_inpfile> *inp,
+                   const std::string &name, int64_t def,
+                   warninp_t wi);
 
 double get_ereal(std::vector<t_inpfile> *inp, const char *name, double def,
                  warninp_t wi);
+double get_ereal(std::vector<t_inpfile> *inp, const std::string &name, double def,
+                 warninp_t wi);
 
 const char *get_estr(std::vector<t_inpfile> *inp, const char *name, const char *def);
+const char *get_estr(std::vector<t_inpfile> *inp, const std::string &name, const char *def);
 
 int get_eeenum(std::vector<t_inpfile> *inp, const char *name, const char **defs,
                warninp_t wi);
 /* defs must be NULL terminated */
+int get_eeenum(std::vector<t_inpfile> *inp, const std::string &name, const char **defs,
+               warninp_t wi);
+/* defs must be NULL terminated */
 
 int get_eenum(std::vector<t_inpfile> *inp, const char *name, const char **defs);
 /* defs must be NULL terminated */
index 1ce7e3f47d86235369a8d8d75ad7a2de99600ef0..bcdfcd5f8b89c670b4105acdc87d75fa4fadf066 100644 (file)
@@ -208,6 +208,11 @@ void warning_error_and_exit(warninp_t wi, const char *s, int f_errno, const char
     check_warning_error_impl(wi, f_errno, file, line);
 }
 
+void warning_error_and_exit(warninp_t wi, const std::string &s, int f_errno, const char *file, int line)
+{
+    warning_error_and_exit(wi, s.c_str(), f_errno, file, line);
+}
+
 gmx_bool warning_errors_exist(warninp_t wi)
 {
     return (wi->nwarn_error > 0);
index 117ea59ee65603b484dc0e46ace3bc97be685953..57949b440aa31d59f43a72fe433c7e2037d03f2b 100644 (file)
@@ -114,6 +114,8 @@ warning_error(warninp_t wi, const std::string &s);
  * This is intended for use where there is no way to produce a data
  * structure that would prevent execution from segfaulting. */
 [[noreturn]] void warning_error_and_exit(warninp_t wi, const char *s, int f_errno, const char *file, int line);
+//! \copydoc warning_error_and_exit(warninp_t, const char *, int, const char *, int);
+[[noreturn]] void warning_error_and_exit(warninp_t wi, const std::string &s, int f_errno, const char *file, int line);
 
 gmx_bool warning_errors_exist(warninp_t wi);
 /* Return whether any error-level warnings were issued to wi. */
index fdd7a573f66549ec9876a60e214845ea38df04d6..86deb5740150ce7b65ff0daac3ba238ef6d7d48f 100644 (file)
@@ -239,8 +239,7 @@ void xvgr_header(FILE *fp, const char *title, const std::string &xaxis,
 
     if (output_env_get_print_xvgr_codes(oenv))
     {
-        gmx_format_current_time(buf, STRLEN);
-        fprintf(fp, "# This file was created %s", buf);
+        fprintf(fp, "# This file was created %s", gmx_format_current_time().c_str());
         try
         {
             gmx::BinaryInformationSettings settings;
index f9fa53e03340a32fc4b5e11e933acf7bd5872274..b8ca3f8ade54898a61b88ec460c73e65f85965de 100644 (file)
@@ -40,6 +40,8 @@
 #include <cstdlib>
 #include <cstring>
 
+#include <string>
+
 #include "gromacs/commandline/pargs.h"
 #include "gromacs/fileio/confio.h"
 #include "gromacs/fileio/xvgr.h"
@@ -51,6 +53,7 @@
 #include "gromacs/utility/cstringutil.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/futil.h"
+#include "gromacs/utility/path.h"
 #include "gromacs/utility/pleasecite.h"
 #include "gromacs/utility/smalloc.h"
 
@@ -97,24 +100,21 @@ static t_pdbfile *read_pdbf(const char *fn)
     return pdbf;
 }
 
-static t_pdbfile **read_em_all(const char *fn, int *npdbf)
+static t_pdbfile **read_em_all(const std::string &fn, int *npdbf)
 {
     t_pdbfile **pdbf = nullptr;
     int         i, maxpdbf;
-    char        buf[256], name[256];
     gmx_bool    bExist;
 
-    std::strcpy(buf, fn);
-    buf[std::strlen(buf)-4] = '\0';
     maxpdbf                 = 100;
     snew(pdbf, maxpdbf);
     i = 0;
     do
     {
-        sprintf(name, "%s_%d.pdb", buf, i+1);
-        if ((bExist = gmx_fexist(name)))
+        auto newFilename = gmx::Path::concatenateBeforeExtension(fn, gmx::formatString("_%d", i+1));
+        if ((bExist = gmx_fexist(newFilename)))
         {
-            pdbf[i]        = read_pdbf(name);
+            pdbf[i]        = read_pdbf(newFilename.c_str());
             pdbf[i]->index = i+1;
             i++;
             if (i >= maxpdbf)
index eaa94f475b78df3f04e41c39ef492763a8498377..2dc33d2b1951dbaad6c45decc44662fc25cb7a45 100644 (file)
@@ -61,6 +61,7 @@
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/futil.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 static gmx_bool bAllowed(real phi, real psi)
 {
@@ -480,7 +481,7 @@ static void histogramming(FILE *log, int nbin, gmx_residuetype_t *rt,
     int      ***his_aa, *histmp;
     int         i, j, k, m, n, nn, Dih, nres, hindex, angle;
     gmx_bool    bBfac, bOccup;
-    char        hisfile[256], hhisfile[256], sshisfile[256], title[256], *ss_str = nullptr;
+    char        hisfile[256], hhisfile[256], title[256], *ss_str = nullptr;
     char      **leg;
     const char *residue_name;
     int         rt_size;
@@ -784,7 +785,7 @@ static void histogramming(FILE *log, int nbin, gmx_residuetype_t *rt,
                 {
                     for (k = 0; (k < 3); k++)
                     {
-                        sprintf(sshisfile, "%s-%s.xvg", hisfile, sss[k]);
+                        std::string sshisfile = gmx::formatString("%s-%s.xvg", hisfile, sss[k]);
                         ssfp[k] = gmx_ffopen(sshisfile, "w");
                     }
                 }
index e0420438a200f19028f1c96c11f784304afec667..6b4ee55e3ee49e6e71ed51b1c72497b9cd243ee6 100644 (file)
@@ -131,7 +131,6 @@ int gmx_covar(int argc, char *argv[])
     int               d, dj, nfit;
     int              *index, *ifit;
     gmx_bool          bDiffMass1, bDiffMass2;
-    char              timebuf[STRLEN];
     t_rgb             rlo, rmi, rhi;
     real             *eigenvectors;
     gmx_output_env_t *oenv;
@@ -590,8 +589,7 @@ int gmx_covar(int argc, char *argv[])
 
     out = gmx_ffopen(logfile, "w");
 
-    gmx_format_current_time(timebuf, STRLEN);
-    fprintf(out, "Covariance analysis log, written %s\n", timebuf);
+    fprintf(out, "Covariance analysis log, written %s\n", gmx_format_current_time().c_str());
 
     fprintf(out, "Program: %s\n", argv[0]);
     gmx_getcwd(str, STRLEN);
index 7914cd93c5d5afb5fbd0e7b2ad17dc175aca9d2d..a50fece7de3ad6aebc5d57f638ce6b3bb021ddc7 100644 (file)
@@ -89,7 +89,7 @@ static int get_electrons(t_electron **eltab, const char *fn)
     int   nr;        /* number of atomstypes to read */
     int   i;
 
-    if (!(in = gmx_ffopen(fn, "r")))
+    if ((in = gmx_ffopen(fn, "r")) == nullptr)
     {
         gmx_fatal(FARGS, "Couldn't open %s. Exiting.\n", fn);
     }
index cdc9d9b1dc3b9b095662d16fdd74651adc8b6794..2518095ca8e5529f74acfa0a6a162feb35161384 100644 (file)
@@ -558,8 +558,8 @@ static void writesurftoxpms(t_interf ***surf1, t_interf ***surf2, int tblocks, i
         yticks[j] += bw;
     }
 
-    xpmfile1 = gmx_ffopen(outfiles[0].c_str(), "w");
-    xpmfile2 = gmx_ffopen(outfiles[1].c_str(), "w");
+    xpmfile1 = gmx_ffopen(outfiles[0], "w");
+    xpmfile2 = gmx_ffopen(outfiles[1], "w");
 
     max1 = max2 = 0.0;
     min1 = min2 = zbins*bwz;
@@ -615,8 +615,8 @@ static void writeraw(t_interf ***int1, t_interf ***int2, int tblocks,
     FILE *raw1, *raw2;
     int   i, j, n;
 
-    raw1 = gmx_ffopen(fnms[0].c_str(), "w");
-    raw2 = gmx_ffopen(fnms[1].c_str(), "w");
+    raw1 = gmx_ffopen(fnms[0], "w");
+    raw2 = gmx_ffopen(fnms[1], "w");
     try
     {
         gmx::BinaryInformationSettings settings;
index 403fd5ae95227457466d9a2fb78923905721797a..44e84d3480e9c3f20e01798efcc077fb20d1e1ca 100644 (file)
@@ -475,8 +475,8 @@ static void writesurftoxpms(real ***surf, int tblocks, int xbins, int ybins, rea
         yticks[j] += bw;
     }
 
-    xpmfile1 = gmx_ffopen(outfiles[0].c_str(), "w");
-    xpmfile2 = gmx_ffopen(outfiles[1].c_str(), "w");
+    xpmfile1 = gmx_ffopen(outfiles[0], "w");
+    xpmfile2 = gmx_ffopen(outfiles[1], "w");
 
     max1 = max2 = 0.0;
     min1 = min2 = 1000.00;
@@ -533,8 +533,8 @@ static void writeraw(real ***surf, int tblocks, int xbins, int ybins,
     FILE *raw1, *raw2;
     int   i, j, n;
 
-    raw1 = gmx_ffopen(fnms[0].c_str(), "w");
-    raw2 = gmx_ffopen(fnms[1].c_str(), "w");
+    raw1 = gmx_ffopen(fnms[0], "w");
+    raw2 = gmx_ffopen(fnms[1], "w");
     fprintf(raw1, "#Legend\n#TBlock\n#Xbin Ybin Z t\n");
     fprintf(raw2, "#Legend\n#TBlock\n#Xbin Ybin Z t\n");
     for (n = 0; n < tblocks; n++)
index a127313153f81bcc8c34fd8c19c287125c841fab..a1ece34082621009d40c838364865a44fc426472 100644 (file)
@@ -1165,7 +1165,7 @@ static void edit_index(int natoms, const t_atoms *atoms, const rvec *x, t_blocka
     static char   **atnames, *ostring;
     static gmx_bool bFirst = TRUE;
     char            inp_string[STRLEN], *string;
-    char            gname[STRLEN], gname1[STRLEN], gname2[STRLEN];
+    char            gname[STRLEN*3], gname1[STRLEN], gname2[STRLEN];
     int             i, i0, i1, sel_nr, sel_nr2, newgroup;
     int             nr, nr1, nr2, *index, *index1, *index2;
     gmx_bool        bAnd, bOr, bPrintOnce;
index 1ecb1ecf16dc3647243b5298b49eaa6dadab62d9..606abcadff6e716b699335ac4451fd8ee69aed7e 100644 (file)
@@ -64,6 +64,7 @@
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/futil.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 static void low_print_data(FILE *fp, real time, rvec x[], int n, const int *index,
                            const gmx_bool bDim[], const char *sffmt)
@@ -669,7 +670,7 @@ int gmx_traj(int argc, char *argv[])
     t_block          *mols;
     gmx_bool          bTop, bOX, bOXT, bOV, bOF, bOB, bOT, bEKT, bEKR, bCV, bCF;
     gmx_bool          bDim[4], bDum[4], bVD;
-    char              sffmt[STRLEN], sffmt6[STRLEN];
+    char              sffmt[STRLEN];
     const char       *box_leg[6] = { "XX", "YY", "ZZ", "YX", "ZX", "ZY" };
     gmx_output_env_t *oenv;
 
@@ -735,7 +736,7 @@ int gmx_traj(int argc, char *argv[])
     {
         sprintf(sffmt, "\t%%g");
     }
-    sprintf(sffmt6, "%s%s%s%s%s%s", sffmt, sffmt, sffmt, sffmt, sffmt, sffmt);
+    std::string sffmt6 = gmx::formatString("%s%s%s%s%s%s", sffmt, sffmt, sffmt, sffmt, sffmt, sffmt);
 
     bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC,
                          &xtop, nullptr, topbox,
@@ -979,7 +980,7 @@ int gmx_traj(int argc, char *argv[])
         if (bOB && fr.bBox)
         {
             fprintf(outb, "\t%g", fr.time);
-            fprintf(outb, sffmt6,
+            fprintf(outb, sffmt6.c_str(),
                     fr.box[XX][XX], fr.box[YY][YY], fr.box[ZZ][ZZ],
                     fr.box[YY][XX], fr.box[ZZ][XX], fr.box[ZZ][YY]);
             fprintf(outb, "\n");
index 28112a30f1e6579189b45e38492021547cd5b2ef..cd8c673f4b6271cb5c8cfa279553b0417cb15fa6 100644 (file)
@@ -905,7 +905,7 @@ int gmx_trjconv(int argc, char *argv[])
     char              out_file2[256], *charpt;
     char             *outf_base = nullptr;
     const char       *outf_ext  = nullptr;
-    char              top_title[256], title[256], timestr[32], stepstr[32], filemode[5];
+    char              top_title[256], timestr[32], stepstr[32], filemode[5];
     gmx_output_env_t *oenv;
 
     t_filenm          fnm[] = {
@@ -1777,6 +1777,7 @@ int gmx_trjconv(int argc, char *argv[])
                             mk_filenm(outf_base, ftp2ext(ftp), nzero, file_nr, out_file2);
                         }
 
+                        std::string title;
                         switch (ftp)
                         {
                             case efTNG:
@@ -1858,7 +1859,7 @@ int gmx_trjconv(int argc, char *argv[])
                                 {
                                     std::strcpy(stepstr, "");
                                 }
-                                snprintf(title, 256, "%s%s%s", top_title, timestr, stepstr);
+                                title = gmx::formatString("%s%s%s", top_title, timestr, stepstr);
                                 if (bSeparate || bSplitHere)
                                 {
                                     out = gmx_ffopen(out_file2, "w");
@@ -1866,7 +1867,7 @@ int gmx_trjconv(int argc, char *argv[])
                                 switch (ftp)
                                 {
                                     case efGRO:
-                                        write_hconf_p(out, title, &useatoms,
+                                        write_hconf_p(out, title.c_str(), &useatoms,
                                                       frout.x, frout.bV ? frout.v : nullptr, frout.box);
                                         break;
                                     case efPDB:
@@ -1882,14 +1883,14 @@ int gmx_trjconv(int argc, char *argv[])
                                         {
                                             model_nr++;
                                         }
-                                        write_pdbfile(out, title, &useatoms, frout.x,
+                                        write_pdbfile(out, title.c_str(), &useatoms, frout.x,
                                                       frout.ePBC, frout.box, ' ', model_nr, gc, TRUE);
                                         break;
                                     case efG96:
                                         const char *outputTitle = "";
                                         if (bSeparate || bTDump)
                                         {
-                                            outputTitle = title;
+                                            outputTitle = title.c_str();
                                             if (bTPS)
                                             {
                                                 frout.bAtoms = TRUE;
@@ -1902,7 +1903,7 @@ int gmx_trjconv(int argc, char *argv[])
                                         {
                                             if (outframe == 0)
                                             {
-                                                outputTitle = title;
+                                                outputTitle = title.c_str();
                                             }
                                             frout.bAtoms = FALSE;
                                             frout.bStep  = TRUE;
index 3378600db8b1c1415368b85aa29518a5e27ab1b3..d166421130c3b0fcbf76ab05687603fc82f5e8eb 100644 (file)
@@ -1129,7 +1129,6 @@ static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes,
                     int nPMEnodes, int nr, gmx_bool bKeepStderr)
 {
     char        numstring[STRLEN];
-    char        newfilename[STRLEN];
     const char *fn = nullptr;
     int         i;
     const char *opt;
@@ -1153,12 +1152,12 @@ static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes,
             {
                 sprintf(numstring, "_%d", nr);
             }
-            sprintf(newfilename, "%s_no%d_np%d_npme%d%s", opt2fn("-bg", nfile, fnm), k, nnodes, nPMEnodes, numstring);
+            std::string newfilename = gmx::formatString("%s_no%d_np%d_npme%d%s", opt2fn("-bg", nfile, fnm), k, nnodes, nPMEnodes, numstring);
             if (gmx_fexist(opt2fn("-bg", nfile, fnm)))
             {
-                fprintf(stdout, "renaming log file to %s\n", newfilename);
+                fprintf(stdout, "renaming log file to %s\n", newfilename.c_str());
                 make_backup(newfilename);
-                rename(opt2fn("-bg", nfile, fnm), newfilename);
+                rename(opt2fn("-bg", nfile, fnm), newfilename.c_str());
             }
         }
         else if (std::strcmp(opt, "-err") == 0)
@@ -1171,14 +1170,14 @@ static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes,
             {
                 sprintf(numstring, "_%d", nr);
             }
-            sprintf(newfilename, "%s_no%d_np%d_npme%d%s", fn, k, nnodes, nPMEnodes, numstring);
+            std::string newfilename = gmx::formatString("%s_no%d_np%d_npme%d%s", fn, k, nnodes, nPMEnodes, numstring);
             if (gmx_fexist(fn))
             {
                 if (bKeepStderr)
                 {
-                    fprintf(stdout, "Saving stderr output in %s\n", newfilename);
+                    fprintf(stdout, "Saving stderr output in %s\n", newfilename.c_str());
                     make_backup(newfilename);
-                    rename(fn, newfilename);
+                    rename(fn, newfilename.c_str());
                 }
                 else
                 {
index a47e10c4e3b5d6ac8b86a17c8e78db574eb2fc3a..0366a635322838fd4d6b9ba8dae70bc523e54a5a 100644 (file)
@@ -1849,7 +1849,7 @@ static void read_wham_in(const char *fn, char ***filenamesRet, int *nfilesRet,
 //! Open a file or a pipe to a gzipped file
 static FILE *open_pdo_pipe(const char *fn, t_UmbrellaOptions *opt, gmx_bool *bPipeOpen)
 {
-    char            Buffer[1024], gunzip[1024], *Path = nullptr;
+    char            Buffer[2048], gunzip[1024], *Path = nullptr;
     FILE           *pipe   = nullptr;
     static gmx_bool bFirst = true;
 
index 7a46d73334e11c8357bfab1914115dc34d1eeb61..bf9b4a334949bf2376fb2144f37853665f1e2f2e 100644 (file)
@@ -98,8 +98,8 @@ void powerspectavg(real ***intftab, int tsteps, int xbins, int ybins,
     }
     /*Print out average energy-spectrum to outfiles[0] and outfiles[1];*/
 
-    datfile1 = gmx_ffopen(outfiles[0].c_str(), "w");
-    datfile2 = gmx_ffopen(outfiles[1].c_str(), "w");
+    datfile1 = gmx_ffopen(outfiles[0], "w");
+    datfile2 = gmx_ffopen(outfiles[1], "w");
 
 /*Filling dat files with spectral data*/
     fprintf(datfile1, "%s\n", "kx\t ky\t\tPower(kx,ky)");
index 42c7ad87c43a03ccea4ec575593ccff6c9dd0d70..55d9afd0a2dc6235a49e327b66073d18df1951c7 100644 (file)
@@ -168,5 +168,5 @@ FILE *fflib_open(const std::string &file)
 {
     std::string fileFullPath = gmx::findLibraryFile(file);
     fprintf(stderr, "Opening force field file %s\n", fileFullPath.c_str());
-    return gmx_ffopen(fileFullPath.c_str(), "r");
+    return gmx_ffopen(fileFullPath, "r");
 }
index cf374683c3105092bd0a36b7c6ceeb9f577bfd9a..bef728f7ac844880183b5eec383d17d02826cd6b 100644 (file)
@@ -1506,26 +1506,33 @@ static void checkDecoupledModeAccuracy(const gmx_mtop_t *mtop,
 
     if (haveDecoupledMode)
     {
-        char modeMessage[STRLEN];
-        sprintf(modeMessage, "There are atoms at both ends of an angle, connected by constraints and with masses that differ by more than a factor of %g. This means that there are likely dynamic modes that are only very weakly coupled.",
-                massFactorThreshold);
-        char buf[STRLEN];
+        std::string message = gmx::formatString(
+                    "There are atoms at both ends of an angle, connected by constraints "
+                    "and with masses that differ by more than a factor of %g. This means "
+                    "that there are likely dynamic modes that are only very weakly coupled.",
+                    massFactorThreshold);
         if (ir->cutoff_scheme == ecutsVERLET)
         {
-            sprintf(buf, "%s To ensure good equipartitioning, you need to either not use constraints on all bonds (but, if possible, only on bonds involving hydrogens) or use integrator = %s or decrease one or more tolerances: verlet-buffer-tolerance <= %g, LINCS iterations >= %d, LINCS order >= %d or SHAKE tolerance <= %g",
-                    modeMessage,
-                    ei_names[eiSD1],
-                    bufferToleranceThreshold,
-                    lincsIterationThreshold, lincsOrderThreshold,
-                    shakeToleranceThreshold);
+            message += gmx::formatString(
+                        " To ensure good equipartitioning, you need to either not use "
+                        "constraints on all bonds (but, if possible, only on bonds involving "
+                        "hydrogens) or use integrator = %s or decrease one or more tolerances: "
+                        "verlet-buffer-tolerance <= %g, LINCS iterations >= %d, LINCS order "
+                        ">= %d or SHAKE tolerance <= %g",
+                        ei_names[eiSD1],
+                        bufferToleranceThreshold,
+                        lincsIterationThreshold, lincsOrderThreshold,
+                        shakeToleranceThreshold);
         }
         else
         {
-            sprintf(buf, "%s To ensure good equipartitioning, we suggest to switch to the %s cutoff-scheme, since that allows for better control over the Verlet buffer size and thus over the energy drift.",
-                    modeMessage,
-                    ecutscheme_names[ecutsVERLET]);
+            message += gmx::formatString(
+                        " To ensure good equipartitioning, we suggest to switch to the %s "
+                        "cutoff-scheme, since that allows for better control over the Verlet "
+                        "buffer size and thus over the energy drift.",
+                        ecutscheme_names[ecutsVERLET]);
         }
-        warning(wi, buf);
+        warning(wi, message);
     }
 }
 
index 8ed41d9f45fd068737e8543a8929420b13acb7f8..9eb8dcba84e1826263077449f88baa0ccf65d1e0 100644 (file)
@@ -224,7 +224,7 @@ choose_ff_impl(const char *ffsel,
                 // TODO: Use a C++ API without such an intermediate/fixed-length buffer.
                 char  buf[STRLEN];
                 /* We don't use fflib_open, because we don't want printf's */
-                FILE *fp = gmx_ffopen(docFileName.c_str(), "r");
+                FILE *fp = gmx_ffopen(docFileName, "r");
                 get_a_line(fp, buf, STRLEN);
                 gmx_ffclose(fp);
                 desc.emplace_back(buf);
index db4f6a601cf49106692fc8a3fc604bc479b22ba4..faa4c4af13cf6fd73919b5ab3dd6ef5456050a24 100644 (file)
@@ -358,10 +358,10 @@ char **read_pullparams(std::vector<t_inpfile> *inp,
                        &pcrd->group[4], &pcrd->group[5], &idum);
         if (nscan != pcrd->ngroup)
         {
-            sprintf(wbuf, "%s should contain %d pull group indices with geometry %s",
-                    buf, pcrd->ngroup, epullg_names[pcrd->eGeom]);
+            auto message = gmx::formatString("%s should contain %d pull group indices with geometry %s",
+                                             buf, pcrd->ngroup, epullg_names[pcrd->eGeom]);
             set_warning_line(wi, nullptr, -1);
-            warning_error(wi, wbuf);
+            warning_error(wi, message);
         }
         for (int g = 0; g < pcrd->ngroup; g++)
         {
index 954b20488596ee4790951ca66115d6067c5b106f..1b423b01c5c2262e6b43f9cd661e77c1ac108c90 100644 (file)
@@ -36,6 +36,8 @@
  */
 #include "gmxpre.h"
 
+#include <string>
+
 #include "gromacs/fileio/readinp.h"
 #include "gromacs/fileio/trrio.h"
 #include "gromacs/fileio/warninp.h"
@@ -48,7 +50,9 @@
 #include "gromacs/utility/cstringutil.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/futil.h"
+#include "gromacs/utility/path.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 static const char *RotStr = "Enforced rotation:";
 
@@ -202,7 +206,7 @@ extern char **read_rotparams(std::vector<t_inpfile> *inp, t_rot *rot,
 
 
 /* Check whether the box is unchanged */
-static void check_box_unchanged(matrix f_box, matrix box, char fn[], warninp_t wi)
+static void check_box_unchanged(matrix f_box, matrix box, const char fn[], warninp_t wi)
 {
     int      i, ii;
     bool     bSame = TRUE;
@@ -237,20 +241,9 @@ extern void set_reference_positions(
 {
     int              g, i, ii;
     t_rotgrp        *rotg;
-    gmx_trr_header_t header;    /* Header information of reference file */
-    char             base[STRLEN], extension[STRLEN], reffile[STRLEN];
-    char            *extpos;
+    gmx_trr_header_t header;   /* Header information of reference file */
     rvec             f_box[3]; /* Box from reference file */
 
-
-    /* Base name and extension of the reference file: */
-    strncpy(base, fn, STRLEN - 1);
-    base[STRLEN-1] = '\0';
-    extpos         = strrchr(base, '.');
-    strcpy(extension, extpos+1);
-    *extpos = '\0';
-
-
     for (g = 0; g < rot->ngrp; g++)
     {
         rotg = &rot->grp[g];
@@ -258,7 +251,8 @@ extern void set_reference_positions(
         snew(rotg->x_ref, rotg->nat);
 
         /* Construct the name for the file containing the reference positions for this group: */
-        sprintf(reffile, "%s.%d.%s", base, g, extension);
+        std::string reffileString = gmx::Path::concatenateBeforeExtension(fn, gmx::formatString(".%d", g));
+        const char *reffile       = reffileString.c_str();
 
         /* If the base filename for the reference position files was explicitly set by
          * the user, we issue a fatal error if the group file can not be found */
index 5306a44ce16c6493e2cb6c8ad7db530f5e2c0201..59764a9f70c99de9848d6b57063d6fe6fd3ef865 100644 (file)
@@ -747,7 +747,7 @@ static void update_top(t_atoms *atoms, int firstSolventResidueIndex, matrix box,
                        gmx_atomprop_t aps)
 {
     FILE        *fpin, *fpout;
-    char         buf[STRLEN], buf2[STRLEN], *temp;
+    char         buf[STRLEN*2], buf2[STRLEN], *temp;
     const char  *topinout;
     int          line;
     bool         bSystem;
index cd72daf5e4e0928c66f0a4c657368ee93d9a44e7..a7e9ee784ac78f40d7a36002fe3dc04980a28838 100644 (file)
@@ -280,19 +280,19 @@ int mk_specbonds(t_atoms *pdba, rvec x[], bool bInteractive,
                 e = std::min(b+MAXCOL, nspec-1);
                 for (i = b; (i < e); i++)
                 {
-                    sprintf(buf, "%s%d", *pdba->atomname[sgp[i]], sgp[i]+1);
-                    fprintf(stderr, "%8s", buf);
+                    std::string buf = gmx::formatString("%s%d", *pdba->atomname[sgp[i]], sgp[i]+1);
+                    fprintf(stderr, "%8s", buf.c_str());
                 }
                 fprintf(stderr, "\n");
                 /* print matrix */
                 e = std::min(b+MAXCOL, nspec);
                 for (i = b+1; (i < nspec); i++)
                 {
-                    sprintf(buf, "%s%d", *pdba->resinfo[pdba->atom[sgp[i]].resind].name,
-                            pdba->resinfo[specp[i]].nr);
-                    fprintf(stderr, "%8s", buf);
-                    sprintf(buf, "%s%d", *pdba->atomname[sgp[i]], sgp[i]+1);
-                    fprintf(stderr, "%8s", buf);
+                    std::string buf = gmx::formatString("%s%d", *pdba->resinfo[pdba->atom[sgp[i]].resind].name,
+                                                        pdba->resinfo[specp[i]].nr);
+                    fprintf(stderr, "%8s", buf.c_str());
+                    buf = gmx::formatString("%s%d", *pdba->atomname[sgp[i]], sgp[i]+1);
+                    fprintf(stderr, "%8s", buf.c_str());
                     e2 = std::min(i, e);
                     for (j = b; (j < e2); j++)
                     {
index 8acd507abf4ac2a528c94b2df98cf5852254d3f3..04e5c38a2d735e030a114957dfe5245e6805fa6f 100644 (file)
@@ -44,6 +44,7 @@
 #include <cstring>
 
 #include <algorithm>
+#include <string>
 
 #include "gromacs/fileio/warninp.h"
 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
@@ -61,6 +62,7 @@
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 void generate_nbparams(int comb, int ftype, t_params *plist, gpp_atomtype_t atype,
                        warninp_t wi)
@@ -68,7 +70,6 @@ void generate_nbparams(int comb, int ftype, t_params *plist, gpp_atomtype_t atyp
     int   i, j, k = -1, nf;
     int   nr, nrfp;
     real  c, bi, bj, ci, cj, ci0, ci1, ci2, cj0, cj1, cj2;
-    char  errbuf[STRLEN];
 
     /* Lean mean shortcuts */
     nr   = get_atomtype_ntypes(atype);
@@ -146,8 +147,8 @@ void generate_nbparams(int comb, int ftype, t_params *plist, gpp_atomtype_t atyp
 
                     break;
                 default:
-                    sprintf(errbuf, "No such combination rule %d", comb);
-                    warning_error_and_exit(wi, errbuf, FARGS);
+                    auto message = gmx::formatString("No such combination rule %d", comb);
+                    warning_error_and_exit(wi, message, FARGS);
             }
             if (plist->nr != k)
             {
@@ -182,9 +183,9 @@ void generate_nbparams(int comb, int ftype, t_params *plist, gpp_atomtype_t atyp
 
             break;
         default:
-            sprintf(errbuf, "Invalid nonbonded type %s",
-                    interaction_function[ftype].longname);
-            warning_error(wi, errbuf);
+            auto message = gmx::formatString("Invalid nonbonded type %s",
+                                             interaction_function[ftype].longname);
+            warning_error(wi, message);
     }
 }
 
@@ -239,7 +240,6 @@ void push_at (t_symtab *symtab, gpp_atomtype_t at, t_bond_atomtype bat,
     double     m, q;
     double     c[MAXFORCEPARAM];
     char       tmpfield[12][100]; /* Max 12 fields of width 100 */
-    char       errbuf[STRLEN];
     t_atom    *atom;
     t_param   *param;
     int        atomnr;
@@ -443,8 +443,8 @@ void push_at (t_symtab *symtab, gpp_atomtype_t at, t_bond_atomtype bat,
             break;
 
         default:
-            sprintf(errbuf, "Invalid function type %d in push_at", nb_funct);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString("Invalid function type %d in push_at", nb_funct);
+            warning_error_and_exit(wi, message, FARGS);
     }
     for (j = nfp0; (j < MAXFORCEPARAM); j++)
     {
@@ -475,8 +475,8 @@ void push_at (t_symtab *symtab, gpp_atomtype_t at, t_bond_atomtype bat,
     }
     if (j == eptNR)
     {
-        sprintf(errbuf, "Invalid particle type %s", ptype);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Invalid particle type %s", ptype);
+        warning_error_and_exit(wi, message, FARGS);
     }
     pt = xl[j].ptype;
 
@@ -496,20 +496,20 @@ void push_at (t_symtab *symtab, gpp_atomtype_t at, t_bond_atomtype bat,
 
     if ((nr = get_atomtype_type(type, at)) != NOTSET)
     {
-        sprintf(errbuf, "Overriding atomtype %s", type);
-        warning(wi, errbuf);
+        auto message = gmx::formatString("Overriding atomtype %s", type);
+        warning(wi, message);
         if ((nr = set_atomtype(nr, at, symtab, atom, type, param, batype_nr,
                                atomnr)) == NOTSET)
         {
-            sprintf(errbuf, "Replacing atomtype %s failed", type);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString("Replacing atomtype %s failed", type);
+            warning_error_and_exit(wi, message, FARGS);
         }
     }
     else if ((add_atomtype(at, symtab, atom, type, param,
                            batype_nr, atomnr)) == NOTSET)
     {
-        sprintf(errbuf, "Adding atomtype %s failed", type);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Adding atomtype %s failed", type);
+        warning_error_and_exit(wi, message, FARGS);
     }
     else
     {
@@ -538,7 +538,6 @@ static void push_bondtype(t_params     *       bt,
 {
     int      nr   = bt->nr;
     int      nrfp = NRFP(ftype);
-    char     errbuf[STRLEN];
 
     /* If bAllowRepeat is TRUE, we allow multiple entries as long as they
        are on directly _adjacent_ lines.
@@ -593,18 +592,22 @@ static void push_bondtype(t_params     *       bt,
                      */
                     if (!isContinuationOfBlock && !haveErrored)
                     {
-                        warning_error(wi, "Encountered a second block of parameters for dihedral type 9 for the same atoms, with either different parameters and/or the first block has multiple lines. This is not supported.");
+                        warning_error(wi, "Encountered a second block of parameters for dihedral "
+                                      "type 9 for the same atoms, with either different parameters "
+                                      "and/or the first block has multiple lines. This is not supported.");
                         haveErrored = true;
                     }
                 }
                 else if (!haveWarned)
                 {
-                    sprintf(errbuf, "Overriding %s parameters.%s",
+                    auto message = gmx::formatString
+                            ("Overriding %s parameters.%s",
                             interaction_function[ftype].longname,
                             (ftype == F_PDIHS) ?
-                            "\nUse dihedraltype 9 to allow several multiplicity terms. Only consecutive lines are combined. Non-consective lines overwrite each other."
+                            "\nUse dihedraltype 9 to allow several multiplicity terms. Only consecutive "
+                            "lines are combined. Non-consective lines overwrite each other."
                             : "");
-                    warning(wi, errbuf);
+                    warning(wi, message);
 
                     fprintf(stderr, "  old:                                         ");
                     for (int j = 0; (j < nrfp); j++)
@@ -689,7 +692,6 @@ void push_bt(directive d, t_params bt[], int nral,
     /* One force parameter more, so we can check if we read too many */
     double      c[MAXFORCEPARAM+1];
     t_param     p;
-    char        errbuf[STRLEN];
 
     if ((bat && at) || (!bat && !at))
     {
@@ -700,8 +702,8 @@ void push_bt(directive d, t_params bt[], int nral,
     if ((nn = sscanf(line, formal[nral],
                      alc[0], alc[1], alc[2], alc[3], alc[4], alc[5])) != nral+1)
     {
-        sprintf(errbuf, "Not enough atomtypes (%d instead of %d)", nn-1, nral);
-        warning_error(wi, errbuf);
+        auto message = gmx::formatString("Not enough atomtypes (%d instead of %d)", nn-1, nral);
+        warning_error(wi, message);
         return;
     }
 
@@ -743,13 +745,13 @@ void push_bt(directive d, t_params bt[], int nral,
     {
         if (at && ((p.a[i] = get_atomtype_type(alc[i], at)) == NOTSET))
         {
-            sprintf(errbuf, "Unknown atomtype %s\n", alc[i]);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString("Unknown atomtype %s\n", alc[i]);
+            warning_error_and_exit(wi, message, FARGS);
         }
         else if (bat && ((p.a[i] = get_bond_atomtype_type(alc[i], bat)) == NOTSET))
         {
-            sprintf(errbuf, "Unknown bond_atomtype %s\n", alc[i]);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString("Unknown bond_atomtype %s\n", alc[i]);
+            warning_error_and_exit(wi, message, FARGS);
         }
     }
     for (i = 0; (i < nrfp); i++)
@@ -802,7 +804,6 @@ void push_dihedraltype(directive d, t_params bt[],
     double       c[MAXFORCEPARAM];
     t_param      p;
     bool         bAllowRepeat;
-    char         errbuf[STRLEN];
 
     /* This routine accepts dihedraltypes defined from either 2 or 4 atoms.
      *
@@ -843,8 +844,8 @@ void push_dihedraltype(directive d, t_params bt[],
     }
     else
     {
-        sprintf(errbuf, "Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn-1);
-        warning_error(wi, errbuf);
+        auto message = gmx::formatString("Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn-1);
+        warning_error(wi, message);
         return;
     }
 
@@ -914,8 +915,8 @@ void push_dihedraltype(directive d, t_params bt[],
         {
             if ((p.a[i] = get_bond_atomtype_type(alc[i], bat)) == NOTSET)
             {
-                sprintf(errbuf, "Unknown bond_atomtype %s", alc[i]);
-                warning_error_and_exit(wi, errbuf, FARGS);
+                auto message = gmx::formatString("Unknown bond_atomtype %s", alc[i]);
+                warning_error_and_exit(wi, message, FARGS);
             }
         }
     }
@@ -945,7 +946,6 @@ void push_nbt(directive d, t_nbparam **nbt, gpp_atomtype_t atype,
     int         ai, aj;
     t_nbparam  *nbp;
     bool        bId;
-    char        errbuf[STRLEN];
 
     if (sscanf (pline, "%s%s%d", a0, a1, &f) != 3)
     {
@@ -957,10 +957,10 @@ void push_nbt(directive d, t_nbparam **nbt, gpp_atomtype_t atype,
 
     if (ftype != nb_funct)
     {
-        sprintf(errbuf, "Trying to add %s while the default nonbond type is %s",
-                interaction_function[ftype].longname,
-                interaction_function[nb_funct].longname);
-        warning_error(wi, errbuf);
+        auto message = gmx::formatString("Trying to add %s while the default nonbond type is %s",
+                                         interaction_function[ftype].longname,
+                                         interaction_function[nb_funct].longname);
+        warning_error(wi, message);
         return;
     }
 
@@ -1010,8 +1010,8 @@ void push_nbt(directive d, t_nbparam **nbt, gpp_atomtype_t atype,
     }
     else
     {
-        sprintf(errbuf, "Number of force parameters for nonbonded interactions is %d", nrfp);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Number of force parameters for nonbonded interactions is %d", nrfp);
+        warning_error_and_exit(wi, message, FARGS);
     }
     for (i = 0; (i < nrfp); i++)
     {
@@ -1021,13 +1021,13 @@ void push_nbt(directive d, t_nbparam **nbt, gpp_atomtype_t atype,
     /* Put the parameters in the matrix */
     if ((ai = get_atomtype_type (a0, atype)) == NOTSET)
     {
-        sprintf(errbuf, "Atomtype %s not found", a0);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Atomtype %s not found", a0);
+        warning_error_and_exit(wi, message, FARGS);
     }
     if ((aj = get_atomtype_type (a1, atype)) == NOTSET)
     {
-        sprintf(errbuf, "Atomtype %s not found", a1);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Atomtype %s not found", a1);
+        warning_error_and_exit(wi, message, FARGS);
     }
     nbp = &(nbt[std::max(ai, aj)][std::min(ai, aj)]);
 
@@ -1040,8 +1040,8 @@ void push_nbt(directive d, t_nbparam **nbt, gpp_atomtype_t atype,
         }
         if (!bId)
         {
-            sprintf(errbuf, "Overriding non-bonded parameters,");
-            warning(wi, errbuf);
+            auto message = gmx::formatString("Overriding non-bonded parameters,");
+            warning(wi, message);
             fprintf(stderr, "  old:");
             for (i = 0; i < nrfp; i++)
             {
@@ -1069,7 +1069,6 @@ push_cmaptype(directive d, t_params bt[], int nral, gpp_atomtype_t at,
     int          nxcmap, nycmap, ncmap, read_cmap, sl, nct;
     char         s[20], alc[MAXATOMLIST+2][20];
     t_param      p;
-    char         errbuf[STRLEN];
 
     /* Keep the compiler happy */
     read_cmap = 0;
@@ -1080,8 +1079,8 @@ push_cmaptype(directive d, t_params bt[], int nral, gpp_atomtype_t at,
     /* Here we can only check for < 8 */
     if ((nn = sscanf(line, formal, alc[0], alc[1], alc[2], alc[3], alc[4], alc[5], alc[6], alc[7], &nchar_consumed)) < nral+3)
     {
-        sprintf(errbuf, "Incorrect number of atomtypes for cmap (%d instead of 5)", nn-1);
-        warning_error(wi, errbuf);
+        auto message = gmx::formatString("Incorrect number of atomtypes for cmap (%d instead of 5)", nn-1);
+        warning_error(wi, message);
         return;
     }
     start += nchar_consumed;
@@ -1093,8 +1092,8 @@ push_cmaptype(directive d, t_params bt[], int nral, gpp_atomtype_t at,
     /* Check for equal grid spacing in x and y dims */
     if (nxcmap != nycmap)
     {
-        sprintf(errbuf, "Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
-        warning_error(wi, errbuf);
+        auto message = gmx::formatString("Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
+        warning_error(wi, message);
     }
 
     ncmap  = nxcmap*nycmap;
@@ -1125,8 +1124,8 @@ push_cmaptype(directive d, t_params bt[], int nral, gpp_atomtype_t at,
         }
         else
         {
-            sprintf(errbuf, "Error in reading cmap parameter for angle %s %s %s %s %s", alc[0], alc[1], alc[2], alc[3], alc[4]);
-            warning_error(wi, errbuf);
+            auto message = gmx::formatString("Error in reading cmap parameter for angle %s %s %s %s %s", alc[0], alc[1], alc[2], alc[3], alc[4]);
+            warning_error(wi, message);
         }
 
     }
@@ -1170,13 +1169,13 @@ push_cmaptype(directive d, t_params bt[], int nral, gpp_atomtype_t at,
     {
         if (at && ((p.a[i] = get_bond_atomtype_type(alc[i], bat)) == NOTSET))
         {
-            sprintf(errbuf, "Unknown atomtype %s\n", alc[i]);
-            warning_error(wi, errbuf);
+            auto message = gmx::formatString("Unknown atomtype %s\n", alc[i]);
+            warning_error(wi, message);
         }
         else if (bat && ((p.a[i] = get_bond_atomtype_type(alc[i], bat)) == NOTSET))
         {
-            sprintf(errbuf, "Unknown bond_atomtype %s\n", alc[i]);
-            warning_error(wi, errbuf);
+            auto message = gmx::formatString("Unknown bond_atomtype %s\n", alc[i]);
+            warning_error(wi, message);
         }
 
         /* Assign a grid number to each cmap_type */
@@ -1189,8 +1188,8 @@ push_cmaptype(directive d, t_params bt[], int nral, gpp_atomtype_t at,
     /* Check for the correct number of atoms (again) */
     if (bt[F_CMAP].nct != nct)
     {
-        sprintf(errbuf, "Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].nc);
-        warning_error(wi, errbuf);
+        auto message = gmx::formatString("Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].nc);
+        warning_error(wi, message);
     }
 
     /* Is this correct?? */
@@ -1215,12 +1214,13 @@ static void push_atom_now(t_symtab *symtab, t_atoms *at, int atomnr,
     int           j, resind = 0, resnr;
     unsigned char ric;
     int           nr = at->nr;
-    char          errbuf[STRLEN];
 
     if (((nr == 0) && (atomnr != 1)) || (nr && (atomnr != at->nr+1)))
     {
-        sprintf(errbuf, "Atoms in the .top are not numbered consecutively from 1 (rather, atomnr = %d, while at->nr = %d)", atomnr, at->nr);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString
+                ("Atoms in the .top are not numbered consecutively from 1 (rather, "
+                "atomnr = %d, while at->nr = %d)", atomnr, at->nr);
+        warning_error_and_exit(wi, message, FARGS);
     }
 
     j = strlen(resnumberic) - 1;
@@ -1233,9 +1233,9 @@ static void push_atom_now(t_symtab *symtab, t_atoms *at, int atomnr,
         ric = resnumberic[j];
         if (j == 0 || !isdigit(resnumberic[j-1]))
         {
-            sprintf(errbuf, "Invalid residue number '%s' for atom %d",
-                    resnumberic, atomnr);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString("Invalid residue number '%s' for atom %d",
+                                             resnumberic, atomnr);
+            warning_error_and_exit(wi, message, FARGS);
         }
     }
     resnr = strtol(resnumberic, nullptr, 10);
@@ -1314,7 +1314,6 @@ void push_atom(t_symtab *symtab, t_block *cgs,
                   resnumberic[STRLEN], resname[STRLEN], name[STRLEN], check[STRLEN];
     double        m, q, mb, qb;
     real          m0, q0, mB, qB;
-    char          errbuf[STRLEN];
 
     /* Make a shortcut for writing in this molecule  */
     nr = at->nr;
@@ -1329,8 +1328,8 @@ void push_atom(t_symtab *symtab, t_block *cgs,
     sscanf(id, "%d", &atomnr);
     if ((type  = get_atomtype_type(ctype, atype)) == NOTSET)
     {
-        sprintf(errbuf, "Atomtype %s not found", ctype);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Atomtype %s not found", ctype);
+        warning_error_and_exit(wi, message, FARGS);
     }
     ptype = get_atomtype_ptype(type, atype);
 
@@ -1356,8 +1355,8 @@ void push_atom(t_symtab *symtab, t_block *cgs,
             {
                 if ((typeB = get_atomtype_type(ctypeB, atype)) == NOTSET)
                 {
-                    sprintf(errbuf, "Atomtype %s not found", ctypeB);
-                    warning_error_and_exit(wi, errbuf, FARGS);
+                    auto message = gmx::formatString("Atomtype %s not found", ctypeB);
+                    warning_error_and_exit(wi, message, FARGS);
                 }
                 qB = get_atomtype_qA(typeB, atype);
                 mB = get_atomtype_massA(typeB, atype);
@@ -1391,7 +1390,6 @@ void push_molt(t_symtab *symtab, int *nmol, t_molinfo **mol, char *line,
     char       type[STRLEN];
     int        nrexcl, i;
     t_molinfo *newmol;
-    char       errbuf[STRLEN];
 
     if ((sscanf(line, "%s%d", type, &nrexcl)) != 2)
     {
@@ -1404,8 +1402,8 @@ void push_molt(t_symtab *symtab, int *nmol, t_molinfo **mol, char *line,
     {
         if (strcmp(*((*mol)[i].name), type) == 0)
         {
-            sprintf(errbuf, "moleculetype %s is redefined", type);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString("moleculetype %s is redefined", type);
+            warning_error_and_exit(wi, message, FARGS);
         }
         i++;
     }
@@ -1525,7 +1523,6 @@ static bool default_cmap_params(t_params bondtype[],
     int        i, nparam_found;
     int        ct;
     bool       bFound = FALSE;
-    char       errbuf[STRLEN];
 
     nparam_found = 0;
     ct           = 0;
@@ -1557,9 +1554,9 @@ static bool default_cmap_params(t_params bondtype[],
     /* If we did not find a matching type for this cmap torsion */
     if (!bFound)
     {
-        sprintf(errbuf, "Unknown cmap torsion between atoms %d %d %d %d %d",
-                p->a[0]+1, p->a[1]+1, p->a[2]+1, p->a[3]+1, p->a[4]+1);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
+                                         p->a[0]+1, p->a[1]+1, p->a[2]+1, p->a[3]+1, p->a[4]+1);
+        warning_error_and_exit(wi, message, FARGS);
     }
 
     *nparam_def = nparam_found;
@@ -1742,7 +1739,6 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
     t_param      param, *param_defA, *param_defB;
     bool         bFoundA = FALSE, bFoundB = FALSE, bDef, bPert, bSwapParity = FALSE;
     int          nparam_defA, nparam_defB;
-    char         errbuf[STRLEN];
 
     nparam_defA = nparam_defB = 0;
 
@@ -1798,10 +1794,10 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
                 case F_VSITE3OUT:
                     break;
                 default:
-                    sprintf(errbuf, "Negative function types only allowed for %s and %s",
-                            interaction_function[F_VSITE3FAD].longname,
-                            interaction_function[F_VSITE3OUT].longname);
-                    warning_error_and_exit(wi, errbuf, FARGS);
+                    auto message = gmx::formatString("Negative function types only allowed for %s and %s",
+                                                     interaction_function[F_VSITE3FAD].longname,
+                                                     interaction_function[F_VSITE3OUT].longname);
+                    warning_error_and_exit(wi, message, FARGS);
             }
         }
     }
@@ -1812,30 +1808,31 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
     {
         if (aa[i] < 1 || aa[i] > at->nr)
         {
-            sprintf(errbuf, "Atom index (%d) in %s out of bounds (1-%d).\n"
+            auto message = gmx::formatString
+                    ("Atom index (%d) in %s out of bounds (1-%d).\n"
                     "This probably means that you have inserted topology section \"%s\"\n"
                     "in a part belonging to a different molecule than you intended to.\n"
                     "In that case move the \"%s\" section to the right molecule.",
                     aa[i], dir2str(d), at->nr, dir2str(d), dir2str(d));
-            warning_error_and_exit(wi, errbuf, FARGS);
+            warning_error_and_exit(wi, message, FARGS);
         }
         for (j = i+1; (j < nral); j++)
         {
             GMX_ASSERT(j < MAXATOMLIST + 1, "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
             if (aa[i] == aa[j])
             {
-                sprintf(errbuf, "Duplicate atom index (%d) in %s", aa[i], dir2str(d));
+                auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
                 if (ftype == F_ANGRES)
                 {
                     /* Since the angle restraints uses 2 pairs of atoms to
                      * defines an angle between vectors, it can be useful
                      * to use one atom twice, so we only issue a note here.
                      */
-                    warning_note(wi, errbuf);
+                    warning_note(wi, message);
                 }
                 else
                 {
-                    warning_error(wi, errbuf);
+                    warning_error(wi, message);
                 }
             }
         }
@@ -1924,9 +1921,10 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
 
             if (bPert && *bWarn_copy_A_B)
             {
-                sprintf(errbuf,
-                        "Some parameters for bonded interaction involving perturbed atoms are specified explicitly in state A, but not B - copying A to B");
-                warning(wi, errbuf);
+                auto message = gmx::formatString("Some parameters for bonded interaction involving "
+                                                 "perturbed atoms are specified explicitly in "
+                                                 "state A, but not B - copying A to B");
+                warning(wi, message);
                 *bWarn_copy_A_B = FALSE;
             }
 
@@ -1949,9 +1947,11 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
         if ((nread != 0) && (nread != EOF) && (nread != NRFP(ftype)) &&
             !(ftype == F_LJC14_Q && nread == 1))
         {
-            sprintf(errbuf, "Incorrect number of parameters - found %d, expected %d or %d for %s (after the function type).",
+            auto message = gmx::formatString
+                    ("Incorrect number of parameters - found %d, expected %d "
+                    "or %d for %s (after the function type).",
                     nread, NRFPA(ftype), NRFP(ftype), interaction_function[ftype].longname);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            warning_error_and_exit(wi, message, FARGS);
         }
 
         for (j = 0; (j < nread); j++)
@@ -1979,18 +1979,18 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
         {
             if ((nparam_defA != nparam_defB) || ((nparam_defA > 1 || nparam_defB > 1) && (param_defA != param_defB)))
             {
-                sprintf(errbuf,
-                        "Cannot automatically perturb a torsion with multiple terms to different form.\n"
-                        "Please specify perturbed parameters manually for this torsion in your topology!");
-                warning_error(wi, errbuf);
+                auto message =
+                    gmx::formatString("Cannot automatically perturb a torsion with multiple terms to different form.\n"
+                                      "Please specify perturbed parameters manually for this torsion in your topology!");
+                warning_error(wi, message);
             }
         }
 
         if (nread > 0 && nread < NRFPA(ftype))
         {
             /* Issue an error, do not use defaults */
-            sprintf(errbuf, "Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
-            warning_error(wi, errbuf);
+            auto message = gmx::formatString("Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
+            warning_error(wi, message);
         }
 
         if (nread == 0 || nread == EOF)
@@ -2019,8 +2019,8 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
                     }
                     else
                     {
-                        sprintf(errbuf, "No default %s types", interaction_function[ftype].longname);
-                        warning_error(wi, errbuf);
+                        auto message = gmx::formatString("No default %s types", interaction_function[ftype].longname);
+                        warning_error(wi, message);
                     }
                 }
             }
@@ -2050,9 +2050,9 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
 
                 if (bPert)
                 {
-                    sprintf(errbuf, "No default %s types for perturbed atoms, "
-                            "using normal values", interaction_function[ftype].longname);
-                    warning(wi, errbuf);
+                    auto message = gmx::formatString("No default %s types for perturbed atoms, "
+                                                     "using normal values", interaction_function[ftype].longname);
+                    warning(wi, message);
                 }
             }
         }
@@ -2061,18 +2061,18 @@ void push_bond(directive d, t_params bondtype[], t_params bond[],
     if ((ftype == F_PDIHS || ftype == F_ANGRES || ftype == F_ANGRESZ)
         && param.c[5] != param.c[2])
     {
-        sprintf(errbuf, "%s multiplicity can not be perturbed %f!=%f",
-                interaction_function[ftype].longname,
-                param.c[2], param.c[5]);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
+                                         interaction_function[ftype].longname,
+                                         param.c[2], param.c[5]);
+        warning_error_and_exit(wi, message, FARGS);
     }
 
     if (IS_TABULATED(ftype) && param.c[2] != param.c[0])
     {
-        sprintf(errbuf, "%s table number can not be perturbed %d!=%d",
-                interaction_function[ftype].longname,
-                gmx::roundToInt(param.c[0]), gmx::roundToInt(param.c[2]));
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("%s table number can not be perturbed %d!=%d",
+                                         interaction_function[ftype].longname,
+                                         gmx::roundToInt(param.c[0]), gmx::roundToInt(param.c[2]));
+        warning_error_and_exit(wi, message, FARGS);
     }
 
     /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
@@ -2134,7 +2134,6 @@ void push_cmap(directive d, t_params bondtype[], t_params bond[],
     int      i, j, ftype, nral, nread, ncmap_params;
     int      cmap_type;
     int      aa[MAXATOMLIST+1];
-    char     errbuf[STRLEN];
     bool     bFound;
     t_param  param;
 
@@ -2160,20 +2159,21 @@ void push_cmap(directive d, t_params bondtype[], t_params bond[],
     {
         if (aa[i] < 1 || aa[i] > at->nr)
         {
-            sprintf(errbuf, "Atom index (%d) in %s out of bounds (1-%d).\n"
+            auto message = gmx::formatString
+                    ("Atom index (%d) in %s out of bounds (1-%d).\n"
                     "This probably means that you have inserted topology section \"%s\"\n"
                     "in a part belonging to a different molecule than you intended to.\n"
                     "In that case move the \"%s\" section to the right molecule.",
                     aa[i], dir2str(d), at->nr, dir2str(d), dir2str(d));
-            warning_error_and_exit(wi, errbuf, FARGS);
+            warning_error_and_exit(wi, message, FARGS);
         }
 
         for (j = i+1; (j < nral); j++)
         {
             if (aa[i] == aa[j])
             {
-                sprintf(errbuf, "Duplicate atom index (%d) in %s", aa[i], dir2str(d));
-                warning_error(wi, errbuf);
+                auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
+                warning_error(wi, message);
             }
         }
     }
@@ -2201,9 +2201,9 @@ void push_cmap(directive d, t_params bondtype[], t_params bond[],
     else
     {
         /* This is essentially the same check as in default_cmap_params() done one more time */
-        sprintf(errbuf, "Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
-                param.a[0]+1, param.a[1]+1, param.a[2]+1, param.a[3]+1, param.a[4]+1);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
+                                         param.a[0]+1, param.a[1]+1, param.a[2]+1, param.a[3]+1, param.a[4]+1);
+        warning_error_and_exit(wi, message, FARGS);
     }
 }
 
@@ -2218,7 +2218,6 @@ void push_vsitesn(directive d, t_params bond[],
     int    *atc    = nullptr;
     double *weight = nullptr, weight_tot;
     t_param param;
-    char    errbuf[STRLEN];
 
     /* default force parameters  */
     for (j = 0; (j < MAXATOMLIST); j++)
@@ -2235,9 +2234,9 @@ void push_vsitesn(directive d, t_params bond[],
     ptr += n;
     if (ret == 0)
     {
-        sprintf(errbuf, "Expected an atom index in section \"%s\"",
-                dir2str(d));
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Expected an atom index in section \"%s\"",
+                                         dir2str(d));
+        warning_error_and_exit(wi, message, FARGS);
     }
 
     param.a[0] = a - 1;
@@ -2277,14 +2276,16 @@ void push_vsitesn(directive d, t_params bond[],
                     ptr       += n;
                     if (weight[nj] < 0)
                     {
-                        sprintf(errbuf, "No weight or negative weight found for vsiten constructing atom %d (atom index %d)",
+                        auto message = gmx::formatString
+                                ("No weight or negative weight found for vsiten "
+                                "constructing atom %d (atom index %d)",
                                 nj+1, atc[nj]+1);
-                        warning_error_and_exit(wi, errbuf, FARGS);
+                        warning_error_and_exit(wi, message, FARGS);
                     }
                     break;
                 default:
-                    sprintf(errbuf, "Unknown vsiten type %d", type);
-                    warning_error_and_exit(wi, errbuf, FARGS);
+                    auto message = gmx::formatString("Unknown vsiten type %d", type);
+                    warning_error_and_exit(wi, message, FARGS);
             }
             weight_tot += weight[nj];
             nj++;
@@ -2294,9 +2295,9 @@ void push_vsitesn(directive d, t_params bond[],
 
     if (nj == 0)
     {
-        sprintf(errbuf, "Expected more than one atom index in section \"%s\"",
-                dir2str(d));
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("Expected more than one atom index in section \"%s\"",
+                                         dir2str(d));
+        warning_error_and_exit(wi, message, FARGS);
     }
 
     if (weight_tot == 0)
@@ -2322,7 +2323,6 @@ void push_mol(int nrmols, t_molinfo mols[], char *pline, int *whichmol,
               warninp_t wi)
 {
     char type[STRLEN];
-    char errbuf[STRLEN];
 
     if (sscanf(pline, "%s%d", type, nrcopies) != 2)
     {
@@ -2364,8 +2364,12 @@ void push_mol(int nrmols, t_molinfo mols[], char *pline, int *whichmol,
         // avoid matching case-insensitive when we have multiple matches
         if (nrci > 1)
         {
-            sprintf(errbuf, "For moleculetype '%s' in [ system ] %d case insensitive matches, but %d case sensitive matches were found. Check the case of the characters in the moleculetypes.", type, nrci, nrcs);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString
+                    ("For moleculetype '%s' in [ system ] %d case insensitive "
+                    "matches, but %d case sensitive matches were found. Check "
+                    "the case of the characters in the moleculetypes.",
+                    type, nrci, nrcs);
+            warning_error_and_exit(wi, message, FARGS);
         }
         if (nrci == 1)
         {
@@ -2374,8 +2378,8 @@ void push_mol(int nrmols, t_molinfo mols[], char *pline, int *whichmol,
         }
         else
         {
-            sprintf(errbuf, "No such moleculetype %s", type);
-            warning_error_and_exit(wi, errbuf, FARGS);
+            auto message = gmx::formatString("No such moleculetype %s", type);
+            warning_error_and_exit(wi, message, FARGS);
         }
     }
 }
@@ -2414,7 +2418,6 @@ void push_excl(char *line, t_block2 *b2, warninp_t wi)
     int  i, j;
     int  n;
     char base[STRLEN], format[STRLEN];
-    char errbuf[STRLEN];
 
     if (sscanf(line, "%d", &i) == 0)
     {
@@ -2449,8 +2452,8 @@ void push_excl(char *line, t_block2 *b2, warninp_t wi)
             }
             else
             {
-                sprintf(errbuf, "Invalid Atomnr j: %d, b2->nr: %d\n", j, b2->nr);
-                warning_error_and_exit(wi, errbuf, FARGS);
+                auto message = gmx::formatString("Invalid Atomnr j: %d, b2->nr: %d\n", j, b2->nr);
+                warning_error_and_exit(wi, message, FARGS);
             }
         }
     }
@@ -2497,7 +2500,6 @@ void merge_excl(t_blocka *excl, t_block2 *b2, warninp_t wi)
     int     i, k;
     int     j;
     int     nra;
-    char    errbuf[STRLEN];
 
     if (!b2->nr)
     {
@@ -2505,9 +2507,9 @@ void merge_excl(t_blocka *excl, t_block2 *b2, warninp_t wi)
     }
     else if (b2->nr != excl->nr)
     {
-        sprintf(errbuf, "DEATH HORROR: b2->nr = %d, while excl->nr = %d",
-                b2->nr, excl->nr);
-        warning_error_and_exit(wi, errbuf, FARGS);
+        auto message = gmx::formatString("DEATH HORROR: b2->nr = %d, while excl->nr = %d",
+                                         b2->nr, excl->nr);
+        warning_error_and_exit(wi, message, FARGS);
     }
 
     /* First copy all entries from excl to b2 */
@@ -2639,7 +2641,6 @@ static void generate_LJCpairsNB(t_molinfo *mol, int nb_funct, t_params *nbp, war
     t_blocka *excl;
     bool      bExcl;
     t_param   param;
-    char      errbuf[STRLEN];
 
     n    = mol->atoms.nr;
     atom = mol->atoms.atom;
@@ -2674,8 +2675,10 @@ static void generate_LJCpairsNB(t_molinfo *mol, int nb_funct, t_params *nbp, war
             {
                 if (nb_funct != F_LJ)
                 {
-                    sprintf(errbuf, "Can only generate non-bonded pair interactions for Van der Waals type Lennard-Jones");
-                    warning_error_and_exit(wi, errbuf, FARGS);
+                    auto message = gmx::formatString
+                            ("Can only generate non-bonded pair interactions "
+                            "for Van der Waals type Lennard-Jones");
+                    warning_error_and_exit(wi, message, FARGS);
                 }
                 param.a[0] = i;
                 param.a[1] = j;
@@ -2714,7 +2717,6 @@ static void decouple_atoms(t_atoms *atoms, int atomtype_decouple,
                            const char *mol_name, warninp_t wi)
 {
     int  i;
-    char errbuf[STRLEN];
 
     for (i = 0; i < atoms->nr; i++)
     {
@@ -2724,9 +2726,13 @@ static void decouple_atoms(t_atoms *atoms, int atomtype_decouple,
 
         if (atom->qB != atom->q || atom->typeB != atom->type)
         {
-            sprintf(errbuf, "Atom %d in molecule type '%s' has different A and B state charges and/or atom types set in the topology file as well as through the mdp option '%s'. You can not use both these methods simultaneously.",
+            auto message = gmx::formatString
+                    ("Atom %d in molecule type '%s' has different A and B state "
+                    "charges and/or atom types set in the topology file as well "
+                    "as through the mdp option '%s'. You can not use both "
+                    "these methods simultaneously.",
                     i + 1, mol_name, "couple-moltype");
-            warning_error_and_exit(wi, errbuf, FARGS);
+            warning_error_and_exit(wi, message, FARGS);
         }
 
         if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamVDW)
index 2a4f072a25b45f1607ca44abbe8e3e1b9d9c669b..169fe40e2d6fe20dcf21c5124db799826650a294 100644 (file)
@@ -42,6 +42,8 @@
 #include <cstdlib>
 #include <cstring>
 
+#include <string>
+
 #include "gromacs/awh/awh.h"
 #include "gromacs/fileio/enxio.h"
 #include "gromacs/fileio/gmxfio.h"
@@ -68,6 +70,7 @@
 #include "gromacs/utility/arraysize.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 static const char *conrmsd_nm[] = { "Constr. rmsd", "Constr.2 rmsd" };
 
@@ -687,14 +690,11 @@ extern FILE *open_dhdl(const char *filename, const t_inputrec *ir,
     FILE       *fp;
     const char *dhdl = "dH/d\\lambda", *deltag = "\\DeltaH", *lambda = "\\lambda",
     *lambdastate     = "\\lambda state";
-    char        title[STRLEN], label_x[STRLEN], label_y[STRLEN];
-    int         i, nps, nsets, nsets_de, nsetsbegin;
+    int         i, nsets, nsets_de, nsetsbegin;
     int         n_lambda_terms = 0;
     t_lambda   *fep            = ir->fepvals; /* for simplicity */
     t_expanded *expand         = ir->expandedvals;
-    char      **setname;
-    char        buf[STRLEN], lambda_vec_str[STRLEN], lambda_name_str[STRLEN];
-    int         bufplace = 0;
+    char        lambda_vec_str[STRLEN], lambda_name_str[STRLEN];
 
     int         nsets_dhdl = 0;
     int         s          = 0;
@@ -710,34 +710,35 @@ extern FILE *open_dhdl(const char *filename, const t_inputrec *ir,
         }
     }
 
+    std::string title, label_x, label_y;
     if (fep->n_lambda == 0)
     {
-        sprintf(title, "%s", dhdl);
-        sprintf(label_x, "Time (ps)");
-        sprintf(label_y, "%s (%s %s)",
-                dhdl, unit_energy, "[\\lambda]\\S-1\\N");
+        title   = gmx::formatString("%s", dhdl);
+        label_x = gmx::formatString("Time (ps)");
+        label_y = gmx::formatString("%s (%s %s)",
+                                    dhdl, unit_energy, "[\\lambda]\\S-1\\N");
     }
     else
     {
-        sprintf(title, "%s and %s", dhdl, deltag);
-        sprintf(label_x, "Time (ps)");
-        sprintf(label_y, "%s and %s (%s %s)",
-                dhdl, deltag, unit_energy, "[\\8l\\4]\\S-1\\N");
+        title   = gmx::formatString("%s and %s", dhdl, deltag);
+        label_x = gmx::formatString("Time (ps)");
+        label_y = gmx::formatString("%s and %s (%s %s)",
+                                    dhdl, deltag, unit_energy, "[\\8l\\4]\\S-1\\N");
     }
     fp = gmx_fio_fopen(filename, "w+");
-    xvgr_header(fp, title, label_x, label_y, exvggtXNY, oenv);
+    xvgr_header(fp, title.c_str(), label_x, label_y, exvggtXNY, oenv);
 
+    std::string buf;
     if (!(ir->bSimTemp))
     {
-        bufplace = sprintf(buf, "T = %g (K) ",
-                           ir->opts.ref_t[0]);
+        buf = gmx::formatString("T = %g (K) ", ir->opts.ref_t[0]);
     }
     if ((ir->efep != efepSLOWGROWTH) && (ir->efep != efepEXPANDED))
     {
         if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
         {
             /* compatibility output */
-            sprintf(&(buf[bufplace]), "%s = %.4f", lambda, fep->init_lambda);
+            buf += gmx::formatString("%s = %.4f", lambda, fep->init_lambda);
         }
         else
         {
@@ -745,12 +746,12 @@ extern FILE *open_dhdl(const char *filename, const t_inputrec *ir,
                                 lambda_vec_str);
             print_lambda_vector(fep, fep->init_fep_state, TRUE, TRUE,
                                 lambda_name_str);
-            sprintf(&(buf[bufplace]), "%s %d: %s = %s",
-                    lambdastate, fep->init_fep_state,
-                    lambda_name_str, lambda_vec_str);
+            buf += gmx::formatString("%s %d: %s = %s",
+                                     lambdastate, fep->init_fep_state,
+                                     lambda_name_str, lambda_vec_str);
         }
     }
-    xvgr_subtitle(fp, buf, oenv);
+    xvgr_subtitle(fp, buf.c_str(), oenv);
 
 
     nsets_dhdl = 0;
@@ -783,30 +784,28 @@ extern FILE *open_dhdl(const char *filename, const t_inputrec *ir,
                              dhdl.xvg file) */
         write_pV     = TRUE;
     }
-    snew(setname, nsetsextend);
+    std::vector<std::string> setname(nsetsextend);
 
     if (expand->elmcmove > elmcmoveNO)
     {
         /* state for the fep_vals, if we have alchemical sampling */
-        sprintf(buf, "%s", "Thermodynamic state");
-        setname[s] = gmx_strdup(buf);
-        s         += 1;
+        setname[s++] = "Thermodynamic state";
     }
 
     if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
     {
+        std::string energy;
         switch (fep->edHdLPrintEnergy)
         {
             case edHdLPrintEnergyPOTENTIAL:
-                sprintf(buf, "%s (%s)", "Potential Energy", unit_energy);
+                energy = gmx::formatString("%s (%s)", "Potential Energy", unit_energy);
                 break;
             case edHdLPrintEnergyTOTAL:
             case edHdLPrintEnergyYES:
             default:
-                sprintf(buf, "%s (%s)", "Total Energy", unit_energy);
+                energy = gmx::formatString("%s (%s)", "Total Energy", unit_energy);
         }
-        setname[s] = gmx_strdup(buf);
-        s         += 1;
+        setname[s++] = energy;
     }
 
     if (fep->dhdl_derivatives == edhdlderivativesYES)
@@ -815,11 +814,11 @@ extern FILE *open_dhdl(const char *filename, const t_inputrec *ir,
         {
             if (fep->separate_dvdl[i])
             {
-
+                std::string derivative;
                 if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
                 {
                     /* compatibility output */
-                    sprintf(buf, "%s %s %.4f", dhdl, lambda, fep->init_lambda);
+                    derivative = gmx::formatString("%s %s %.4f", dhdl, lambda, fep->init_lambda);
                 }
                 else
                 {
@@ -828,11 +827,10 @@ extern FILE *open_dhdl(const char *filename, const t_inputrec *ir,
                     {
                         lam = fep->all_lambda[i][fep->init_fep_state];
                     }
-                    sprintf(buf, "%s %s = %.4f", dhdl, efpt_singular_names[i],
-                            lam);
+                    derivative = gmx::formatString("%s %s = %.4f", dhdl, efpt_singular_names[i],
+                                                   lam);
                 }
-                setname[s] = gmx_strdup(buf);
-                s         += 1;
+                setname[s++] = derivative;
             }
         }
     }
@@ -861,40 +859,32 @@ extern FILE *open_dhdl(const char *filename, const t_inputrec *ir,
         for (i = fep->lambda_start_n; i < fep->lambda_stop_n; i++)
         {
             print_lambda_vector(fep, i, FALSE, FALSE, lambda_vec_str);
+            std::string buf;
             if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
             {
                 /* for compatible dhdl.xvg files */
-                nps = sprintf(buf, "%s %s %s", deltag, lambda, lambda_vec_str);
+                buf = gmx::formatString("%s %s %s", deltag, lambda, lambda_vec_str);
             }
             else
             {
-                nps = sprintf(buf, "%s %s to %s", deltag, lambda, lambda_vec_str);
+                buf = gmx::formatString("%s %s to %s", deltag, lambda, lambda_vec_str);
             }
 
             if (ir->bSimTemp)
             {
                 /* print the temperature for this state if doing simulated annealing */
-                sprintf(&buf[nps], "T = %g (%s)",
-                        ir->simtempvals->temperatures[s-(nsetsbegin)],
-                        unit_temp_K);
+                buf += gmx::formatString("T = %g (%s)",
+                                         ir->simtempvals->temperatures[s-(nsetsbegin)],
+                                         unit_temp_K);
             }
-            setname[s] = gmx_strdup(buf);
-            s++;
+            setname[s++] = buf;
         }
         if (write_pV)
         {
-            sprintf(buf, "pV (%s)", unit_energy);
-            setname[nsetsextend-1] = gmx_strdup(buf);  /* the first entry after
-                                                          nsets */
+            setname[s++] = gmx::formatString("pV (%s)", unit_energy);
         }
 
-        xvgr_legend(fp, nsetsextend, setname, oenv);
-
-        for (s = 0; s < nsetsextend; s++)
-        {
-            sfree(setname[s]);
-        }
-        sfree(setname);
+        xvgrLegend(fp, setname, oenv);
     }
 
     return fp;
index bacae53329d169663bac25741f9dce5efd7ce1ba..fb6aaf634fa68dae6c0a6e52d1c85f045ea447ac 100644 (file)
 #include "gromacs/utility/logger.h"
 #include "gromacs/utility/pleasecite.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/strconvert.h"
 #include "gromacs/utility/sysinfo.h"
 
 #include "nbnxn_gpu.h"
@@ -130,9 +131,7 @@ void print_time(FILE                     *out,
                 const t_commrec          *cr)
 {
     time_t finish;
-    char   timebuf[STRLEN];
     double dt, elapsed_seconds, time_per_step;
-    char   buf[48];
 
 #if !GMX_THREAD_MPI
     if (!PAR(cr))
@@ -140,7 +139,8 @@ void print_time(FILE                     *out,
     {
         fprintf(out, "\r");
     }
-    fprintf(out, "step %s", gmx_step_str(step, buf));
+    fputs("step ", out);
+    fputs(gmx::int64ToString(step).c_str(), out);
     fflush(out);
 
     if ((step >= ir->nstlist))
@@ -155,10 +155,9 @@ void print_time(FILE                     *out,
             if (dt >= 300)
             {
                 finish = static_cast<time_t>(seconds_since_epoch + dt);
-                gmx_ctime_r(&finish, timebuf, STRLEN);
-                sprintf(buf, "%s", timebuf);
-                buf[strlen(buf)-1] = '\0';
-                fprintf(out, ", will finish %s", buf);
+                auto timebuf = gmx_ctime_r(&finish);
+                fputs(", will finish ", out);
+                fputs(timebuf.c_str(), out);
             }
             else
             {
@@ -186,27 +185,18 @@ void print_time(FILE                     *out,
 void print_date_and_time(FILE *fplog, int nodeid, const char *title,
                          double the_time)
 {
-    char   time_string[STRLEN];
-
     if (!fplog)
     {
         return;
     }
 
-    {
-        int    i;
-        char   timebuf[STRLEN];
-        time_t temp_time = static_cast<time_t>(the_time);
+    time_t temp_time = static_cast<time_t>(the_time);
 
-        gmx_ctime_r(&temp_time, timebuf, STRLEN);
-        for (i = 0; timebuf[i] >= ' '; i++)
-        {
-            time_string[i] = timebuf[i];
-        }
-        time_string[i] = '\0';
-    }
+    auto   timebuf = gmx_ctime_r(&temp_time);
+    // Retain only the characters before the first space
+    timebuf.erase(std::find(timebuf.begin(), timebuf.end(), ' '), timebuf.end());
 
-    fprintf(fplog, "%s on rank %d %s\n", title, nodeid, time_string);
+    fprintf(fplog, "%s on rank %d %s\n", title, nodeid, timebuf.c_str());
 }
 
 void print_start(FILE *fplog, const t_commrec *cr,
index 8343e98d8a80d98a0dffd221d15fde4d9c4cb210..f4157c62fdb63ec7abf105e7d69fab6aa64f4543 100644 (file)
@@ -60,7 +60,6 @@ static void gmx_log_setup(gmx::BinaryInformationSettings settings,
 {
     int    pid;
     char   host[256];
-    char   timebuf[STRLEN];
 
     GMX_RELEASE_ASSERT(fplog != nullptr, "Log file must be already open");
     gmx_fatal_set_log_file(fplog);
@@ -68,12 +67,11 @@ static void gmx_log_setup(gmx::BinaryInformationSettings settings,
     /* Get some machine parameters */
     gmx_gethostname(host, 256);
     pid = gmx_getpid();
-    gmx_format_current_time(timebuf, STRLEN);
 
     fprintf(fplog,
             "Log file opened on %s"
             "Host: %s  pid: %d  rank ID: %d  number of ranks:  %d\n",
-            timebuf, host, pid, rankIndex, numRanks);
+            gmx_format_current_time().c_str(), host, pid, rankIndex, numRanks);
     try
     {
         settings.extendedInfo(true);
index be922b2fc552ff80ac189b64ba5791d1a04fe177..4dc32ba506fd62898e3fcb2bc16e176e60f117b5 100644 (file)
@@ -113,7 +113,7 @@ read_checkpoint_data(const char *filename, int *simulation_part,
 
     if (SIMMASTER(cr))
     {
-        if (!gmx_fexist(filename) || (!(fp = gmx_fio_open(filename, "r")) ))
+        if (!gmx_fexist(filename) || ((fp = gmx_fio_open(filename, "r")) == nullptr ))
         {
             *simulation_part = 0;
             /* We have already warned the user that no checkpoint file existed before, don't
index d2b8c224cb91947ffea42bf364eb468cb4a8c515..28aeecd0bdf4d6643abf477a6ae7bcbe1f9f78d6 100644 (file)
@@ -57,6 +57,7 @@
 #include "gromacs/utility/smalloc.h"
 #include "gromacs/utility/snprintf.h"
 #include "gromacs/utility/strconvert.h"
+#include "gromacs/utility/stringutil.h"
 #include "gromacs/utility/textwriter.h"
 #include "gromacs/utility/txtdump.h"
 
@@ -653,7 +654,7 @@ static void pr_pull(FILE *fp, int indent, const pull_params_t *pull)
     }
 }
 
-static void pr_awh_bias_dim(FILE *fp, int indent, gmx::AwhDimParams *awhDimParams, char *prefix)
+static void pr_awh_bias_dim(FILE *fp, int indent, gmx::AwhDimParams *awhDimParams, const char *prefix)
 {
     pr_indent(fp, indent);
     indent++;
@@ -670,7 +671,7 @@ static void pr_awh_bias_dim(FILE *fp, int indent, gmx::AwhDimParams *awhDimParam
     PR("cover-diameter", awhDimParams->coverDiameter);
 }
 
-static void pr_awh_bias(FILE *fp, int indent, gmx::AwhBiasParams *awhBiasParams, char *prefix)
+static void pr_awh_bias(FILE *fp, int indent, gmx::AwhBiasParams *awhBiasParams, const char *prefix)
 {
     char opt[STRLEN];
 
@@ -703,30 +704,18 @@ static void pr_awh_bias(FILE *fp, int indent, gmx::AwhBiasParams *awhBiasParams,
 
 static void pr_awh(FILE *fp, int indent, gmx::AwhParams *awhParams)
 {
-    int  k;
-    char opt[STRLEN], prefix[STRLEN];
-
-    sprintf(prefix, "%s", "awh");
-
-    sprintf(opt, "%s-potential", prefix);
-    PS(opt, EAWHPOTENTIAL(awhParams->ePotential));
-    sprintf(opt, "%s-seed", prefix);
-    PI(opt, awhParams->seed);
-    sprintf(opt, "%s-nstout", prefix);
-    PI(opt, awhParams->nstOut);
-    sprintf(opt, "%s-nstsample", prefix);
-    PI(opt, awhParams->nstSampleCoord);
-    sprintf(opt, "%s-nsamples-update", prefix);
-    PI(opt, awhParams->numSamplesUpdateFreeEnergy);
-    sprintf(opt, "%s-share-bias-multisim", prefix);
-    PS(opt, EBOOL(awhParams->shareBiasMultisim));
-    sprintf(opt, "%s-nbias", prefix);
-    PI(opt, awhParams->numBias);
-
-    for (k = 0; k < awhParams->numBias; k++)
-    {
-        sprintf(prefix, "awh%d", k + 1);
-        pr_awh_bias(fp, indent, &awhParams->awhBiasParams[k], prefix);
+    PS("awh-potential", EAWHPOTENTIAL(awhParams->ePotential));
+    PI("awh-seed", awhParams->seed);
+    PI("awh-nstout", awhParams->nstOut);
+    PI("awh-nstsample", awhParams->nstSampleCoord);
+    PI("awh-nsamples-update", awhParams->numSamplesUpdateFreeEnergy);
+    PS("awh-share-bias-multisim", EBOOL(awhParams->shareBiasMultisim));
+    PI("awh-nbias", awhParams->numBias);
+
+    for (int k = 0; k < awhParams->numBias; k++)
+    {
+        auto prefix = gmx::formatString("awh%d", k + 1);
+        pr_awh_bias(fp, indent, &awhParams->awhBiasParams[k], prefix.c_str());
     }
 }
 
index bfb27986b821845294971f2c2c104735611eeaa0..37234b54b4576c4ca22c824de49aed023ecef7ba 100644 (file)
@@ -54,6 +54,7 @@
 #include "gromacs/utility/futil.h"
 #include "gromacs/utility/mutex.h"
 #include "gromacs/utility/programcontext.h"
+#include "gromacs/utility/stringutil.h"
 
 #if GMX_MPI
 #include "gromacs/utility/basenetwork.h"
@@ -97,17 +98,17 @@ void gmx_fatal_set_log_file(FILE *fp)
     log_file = fp;
 }
 
-static void default_error_handler(const char *title, const char *msg,
+static void default_error_handler(const char *title, const std::string &msg,
                                   const char *file, int line)
 {
     if (log_file)
     {
         gmx::internal::printFatalErrorHeader(log_file, title, nullptr, file, line);
-        gmx::internal::printFatalErrorMessageLine(log_file, msg, 0);
+        gmx::internal::printFatalErrorMessageLine(log_file, msg.c_str(), 0);
         gmx::internal::printFatalErrorFooter(log_file);
     }
     gmx::internal::printFatalErrorHeader(stderr, title, nullptr, file, line);
-    gmx::internal::printFatalErrorMessageLine(stderr, msg, 0);
+    gmx::internal::printFatalErrorMessageLine(stderr, msg.c_str(), 0);
     gmx::internal::printFatalErrorFooter(stderr);
 }
 
@@ -152,14 +153,12 @@ static const char *gmx_strerror(const char *key)
     return gmx::getErrorCodeString(gmx::eeUnknownError);
 }
 
-static void call_error_handler(const char *key, const char *file, int line, const char *msg)
+static void call_error_handler(const char *key, const char *file, int line, const std::string &msg)
 {
-    if (msg == nullptr)
-    {
-        msg = "Empty gmx_fatal message (bug).";
-    }
     Lock lock(error_mutex);
-    gmx_error_handler(gmx_strerror(key), msg, file, line);
+    gmx_error_handler(gmx_strerror(key),
+                      msg.empty() ? "Empty gmx_fatal message (bug)." : msg,
+                      file, line);
 }
 
 void gmx_exit_on_fatal_error(ExitType exitType, int returnValue)
@@ -213,8 +212,7 @@ void gmx_fatal_mpi_va(int /*f_errno*/, const char *file, int line,
 {
     if (bMaster)
     {
-        char msg[STRLEN];
-        vsprintf(msg, fmt, ap);
+        std::string msg = gmx::formatStringV(fmt, ap);
         call_error_handler("fatal", file, line, msg);
     }
 
@@ -234,7 +232,7 @@ void gmx_fatal(int f_errno, const char *file, int line, gmx_fmtstr const char *f
     va_end(ap);
 }
 
-void _gmx_error(const char *key, const char *msg, const char *file, int line)
+void _gmx_error(const char *key, const std::string &msg, const char *file, int line)
 {
     call_error_handler(key, file, line, msg);
     gmx_exit_on_fatal_error(ExitType_Abort, 1);
index 0f5ce2b50731e50e18143a91a4521d3dee55d8ad..df73d6a9d891288c979e3eacb336ce671164e8b2 100644 (file)
@@ -84,7 +84,7 @@ void
 gmx_fatal_set_log_file(FILE *fp);
 
 /** Function pointer type for fatal error handler callback. */
-typedef void (*gmx_error_handler_t)(const char *title, const char *msg, const char *file, int line);
+typedef void (*gmx_error_handler_t)(const char *title, const std::string &msg, const char *file, int line);
 
 /*! \brief
  * Sets an error handler for gmx_fatal() and other fatal error routines.
@@ -179,7 +179,7 @@ gmx_fatal(int fatal_errno, const char *file, int line, gmx_fmtstr const char *fm
 #define FARGS 0, __FILE__, __LINE__
 
 /** Implementation for gmx_error(). */
-[[noreturn]] void _gmx_error(const char *key, const char *msg, const char *file, int line);
+[[noreturn]] void _gmx_error(const char *key, const std::string &msg, const char *file, int line);
 /*! \brief
  * Alternative fatal error routine with canned messages.
  *
index 38533a71369774a9623b7b36f6495203a772f572..0e960c315e414788c6b1731ca46b3d42c73bdca5 100644 (file)
@@ -45,6 +45,8 @@
 #include <cstdlib>
 #include <cstring>
 
+#include <tuple>
+
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -286,10 +288,10 @@ gmx_off_t gmx_ftell(FILE *stream)
 #endif
 }
 
-int gmx_truncate(const char *filename, gmx_off_t length)
+int gmx_truncate(const std::string &filename, gmx_off_t length)
 {
 #if GMX_NATIVE_WINDOWS
-    FILE *fp = fopen(filename, "rb+");
+    FILE *fp = fopen(filename.c_str(), "rb+");
     if (fp == NULL)
     {
         return -1;
@@ -302,18 +304,16 @@ int gmx_truncate(const char *filename, gmx_off_t length)
     fclose(fp);
     return rc;
 #else
-    return truncate(filename, length);
+    return truncate(filename.c_str(), length);
 #endif
 }
 
-static FILE *uncompress(const char *fn, const char *mode)
+static FILE *uncompress(const std::string &fn, const char *mode)
 {
-    FILE *fp;
-    char  buf[256];
-
-    sprintf(buf, "uncompress -c < %s", fn);
-    fprintf(stderr, "Going to execute '%s'\n", buf);
-    if ((fp = popen(buf, mode)) == nullptr)
+    FILE       *fp;
+    std::string buf = "uncompress -c < " + fn;
+    fprintf(stderr, "Going to execute '%s'\n", buf.c_str());
+    if ((fp = popen(buf.c_str(), mode)) == nullptr)
     {
         gmx_open(fn);
     }
@@ -322,14 +322,13 @@ static FILE *uncompress(const char *fn, const char *mode)
     return fp;
 }
 
-static FILE *gunzip(const char *fn, const char *mode)
+static FILE *gunzip(const std::string &fn, const char *mode)
 {
-    FILE *fp;
-    char  buf[256];
-
-    sprintf(buf, "gunzip -c < %s", fn);
-    fprintf(stderr, "Going to execute '%s'\n", buf);
-    if ((fp = popen(buf, mode)) == nullptr)
+    FILE       *fp;
+    std::string buf = "gunzip -c < ";
+    buf += fn;
+    fprintf(stderr, "Going to execute '%s'\n", buf.c_str());
+    if ((fp = popen(buf.c_str(), mode)) == nullptr)
     {
         gmx_open(fn);
     }
@@ -338,20 +337,20 @@ static FILE *gunzip(const char *fn, const char *mode)
     return fp;
 }
 
-gmx_bool gmx_fexist(const char *fname)
+gmx_bool gmx_fexist(const std::string &fname)
 {
     FILE *test;
 
-    if (fname == nullptr)
+    if (fname.empty())
     {
         return FALSE;
     }
-    test = fopen(fname, "r");
+    test = fopen(fname.c_str(), "r");
     if (test == nullptr)
     {
         /*Windows doesn't allow fopen of directory - so we need to check this seperately */
         #if GMX_NATIVE_WINDOWS
-        DWORD attr = GetFileAttributes(fname);
+        DWORD attr = GetFileAttributes(fname.c_str());
         return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
         #else
         return FALSE;
@@ -364,36 +363,19 @@ gmx_bool gmx_fexist(const char *fname)
     }
 }
 
-static char *backup_fn(const char *file)
+static std::string backup_fn(const std::string &file)
 {
-    int          i, count = 1;
-    char        *directory, *fn;
-    char        *buf;
+    int          count = 1;
 
-    smalloc(buf, GMX_PATH_MAX);
-
-    for (i = strlen(file)-1; ((i > 0) && (file[i] != DIR_SEPARATOR)); i--)
+    std::string  directory, fn, buf;
+    std::tie(directory, fn) = gmx::Path::getParentPathAndBasename(file);
+    if (directory.empty())
     {
-        ;
-    }
-    /* Must check whether i > 0, i.e. whether there is a directory
-     * in the file name. In that case we overwrite the / sign with
-     * a '\0' to end the directory string .
-     */
-    if (i > 0)
-    {
-        directory    = gmx_strdup(file);
-        directory[i] = '\0';
-        fn           = gmx_strdup(file+i+1);
-    }
-    else
-    {
-        directory    = gmx_strdup(".");
-        fn           = gmx_strdup(file);
+        directory = ".";
     }
     do
     {
-        sprintf(buf, "%s/#%s.%d#", directory, fn, count);
+        buf = gmx::formatString("%s/#%s.%d#", directory.c_str(), fn.c_str(), count);
         count++;
     }
     while ((count <= s_maxBackupCount) && gmx_fexist(buf));
@@ -405,16 +387,13 @@ static char *backup_fn(const char *file)
          * Gromacs command-line interface. */
         gmx_fatal(FARGS, "Won't make more than %d backups of %s for you.\n"
                   "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
-                  s_maxBackupCount, fn);
+                  s_maxBackupCount, fn.c_str());
     }
 
-    sfree(directory);
-    sfree(fn);
-
     return buf;
 }
 
-void make_backup(const char *name)
+void make_backup(const std::string &name)
 {
     if (s_maxBackupCount <= 0)
     {
@@ -422,31 +401,29 @@ void make_backup(const char *name)
     }
     if (gmx_fexist(name))
     {
-        char *backup = backup_fn(name);
-        if (rename(name, backup) == 0)
+        auto backup = backup_fn(name);
+        if (rename(name.c_str(), backup.c_str()) == 0)
         {
             fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
-                    name, backup);
+                    name.c_str(), backup.c_str());
         }
         else
         {
-            fprintf(stderr, "\nSorry couldn't backup %s to %s\n", name, backup);
+            fprintf(stderr, "\nSorry couldn't backup %s to %s\n", name.c_str(), backup.c_str());
         }
-        sfree(backup);
     }
 }
 
-FILE *gmx_ffopen(const char *file, const char *mode)
+FILE *gmx_ffopen(const std::string &file, const char *mode)
 {
 #ifdef SKIP_FFOPS
     return fopen(file, mode);
 #else
-    FILE    *ff      = nullptr;
-    char    *bufsize = nullptr, *ptr;
+    FILE    *ff = nullptr;
     gmx_bool bRead;
     int      bs;
 
-    if (file == nullptr)
+    if (file.empty())
     {
         return nullptr;
     }
@@ -459,13 +436,14 @@ FILE *gmx_ffopen(const char *file, const char *mode)
     bRead = (mode[0] == 'r' && mode[1] != '+');
     if (!bRead || gmx_fexist(file))
     {
-        if ((ff = fopen(file, mode)) == nullptr)
+        if ((ff = fopen(file.c_str(), mode)) == nullptr)
         {
             gmx_file(file);
         }
         /* Check whether we should be using buffering (default) or not
          * (for debugging)
          */
+        const char *bufsize = nullptr;
         if (bUnbuffered || ((bufsize = getenv("GMX_LOG_BUFFER")) != nullptr))
         {
             /* Check whether to use completely unbuffered */
@@ -483,6 +461,7 @@ FILE *gmx_ffopen(const char *file, const char *mode)
             }
             else
             {
+                char *ptr;
                 snew(ptr, bs+8);
                 if (setvbuf(ff, ptr, _IOFBF, bs) != 0)
                 {
@@ -495,17 +474,17 @@ FILE *gmx_ffopen(const char *file, const char *mode)
     {
         std::string compressedFileName = file;
         compressedFileName += ".Z";
-        if (gmx_fexist(compressedFileName.c_str()))
+        if (gmx_fexist(compressedFileName))
         {
-            ff = uncompress(compressedFileName.c_str(), mode);
+            ff = uncompress(compressedFileName, mode);
         }
         else
         {
             compressedFileName  = file;
             compressedFileName += ".gz";
-            if (gmx_fexist(compressedFileName.c_str()))
+            if (gmx_fexist(compressedFileName))
             {
-                ff = gunzip(compressedFileName.c_str(), mode);
+                ff = gunzip(compressedFileName, mode);
             }
             else
             {
index 6d6cc03ec53e2f632691bf8917dd97f4ef9a2666..ee6a25e8d2c5083de4efa0b817996a29304f5c00 100644 (file)
@@ -95,12 +95,12 @@ void gmx_set_max_backup_count(int count);
  * Note that this returns `TRUE` even if \p fname is a directory instead of a
  * file.
  */
-gmx_bool gmx_fexist(const char *fname);
+gmx_bool gmx_fexist(const std::string &fname);
 
 /*! \brief
  * Makes a backup of file if the file exists.
  */
-void make_backup(const char *file);
+void make_backup(const std::string &file);
 
 /*! \brief
  * Opens a file, with \Gromacs-specific additions.
@@ -115,7 +115,7 @@ void make_backup(const char *file);
  * overwriting it.
  * A fatal error results if the file cannot be opened, for whatever reason.
  */
-FILE *gmx_ffopen(const char *file, const char *mode);
+FILE *gmx_ffopen(const std::string &file, const char *mode);
 
 /** Closes a file opened with gmx_ffopen(). */
 int gmx_ffclose(FILE *fp);
@@ -135,7 +135,7 @@ int gmx_fseek(FILE *stream, gmx_off_t offset, int whence);
 gmx_off_t gmx_ftell(FILE *stream);
 
 /** OS-independent truncate(). */
-int gmx_truncate(const char *filename, gmx_off_t length);
+int gmx_truncate(const std::string &filename, gmx_off_t length);
 
 namespace gmx
 {
index 64b0713d5c39fbd6cb57ef3bd705ccf09bf85852..d45c010e52a20d30e902def986aacb640f80d0d3 100644 (file)
@@ -55,7 +55,6 @@ void niceHeader(TextWriter *writer, const char *fn, char commentChar)
     int            uid;
     char           userbuf[256];
     char           hostbuf[256];
-    char           timebuf[256];
 
     /* Write a nice header for an output file */
     writer->writeLine(formatString("%c", commentChar));
@@ -64,11 +63,10 @@ void niceHeader(TextWriter *writer, const char *fn, char commentChar)
     uid  = gmx_getuid();
     gmx_getusername(userbuf, 256);
     gmx_gethostname(hostbuf, 256);
-    gmx_format_current_time(timebuf, 256);
 
     writer->writeLine(formatString("%c\tBy user: %s (%d)", commentChar, userbuf, uid));
     writer->writeLine(formatString("%c\tOn host: %s", commentChar, hostbuf));
-    writer->writeLine(formatString("%c\tAt date: %s", commentChar, timebuf));
+    writer->writeLine(formatString("%c\tAt date: %s", commentChar, gmx_format_current_time().c_str()));
     writer->writeLine(formatString("%c", commentChar));
 }
 
index d9bde1c1f8532edf75d144046207adac314d9d28..c1da7e4c939a475cb6bbed1295ab6e49851a8c30 100644 (file)
@@ -54,6 +54,7 @@
 
 #include <algorithm>
 #include <string>
+#include <utility>
 
 #include <sys/stat.h>
 
@@ -276,6 +277,18 @@ std::string Path::getParentPath(const std::string &path)
     return path.substr(0, pos);
 }
 
+std::pair<std::string, std::string> Path::getParentPathAndBasename(const std::string &path)
+{
+    /* Expects that the path doesn't contain "." or "..". If used on a path for
+     * which this isn't guaranteed realpath needs to be called first. */
+    size_t pos = path.find_last_of(cDirSeparators);
+    if (pos == std::string::npos)
+    {
+        return std::make_pair(std::string(), path);
+    }
+    return std::make_pair(path.substr(0, pos), path.substr(pos+1));
+}
+
 std::string Path::getFilename(const std::string &path)
 {
     size_t pos = path.find_last_of(cDirSeparators);
index 09d6724a76baac9dccdf70bb01eeb79a43dc2127..b6774068a67ad4167eab2d54f29023d38162e7e7 100644 (file)
@@ -64,8 +64,18 @@ class Path
         static std::string join(const std::string &path1,
                                 const std::string &path2,
                                 const std::string &path3);
+        //! Return a path using directory separators that suit the execution OS.
         static std::string normalize(const std::string &path);
+        /*! \brief Returns the part of the path before the last
+         * directory separator, if any.
+         *
+         * Path must not contain '.' or '..' elements. */
         static std::string getParentPath(const std::string &path);
+        /*! \brief Returns the parts of the path before and after the
+         * last directory separator, if any.
+         *
+         * Path must not contain '.' or '..' elements. */
+        static std::pair<std::string, std::string> getParentPathAndBasename(const std::string &path);
         static std::string getFilename(const std::string &path);
         static bool hasExtension(const std::string &path);
         static std::string stripExtension(const std::string &path);
index 604756df252ef85c48eae3256628f057e890f8c8..f7c0fae21051b7084373f29752b54ffc868888fc 100644 (file)
@@ -48,6 +48,8 @@
 #include <cstring>
 #include <ctime>
 
+#include <array>
+
 #include <sys/types.h>
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
@@ -132,32 +134,32 @@ int gmx_getusername(char *buf, size_t len)
     return -1;
 }
 
-char *
-gmx_ctime_r(const time_t *clock, char *buf, size_t len)
+std::string
+gmx_ctime_r(const time_t *clock)
 {
 #ifdef _MSC_VER
-    /* Windows */
-    ctime_s(buf, len, clock);
+    std::array<char, 1024> buf;
+    ctime_s(buf.data(), buf.size(), clock);
+    return std::string(buf.begin(), buf.end());
 #elif GMX_NATIVE_WINDOWS
     char *tmpbuf = ctime(clock);
-    strncpy(buf, tmpbuf, len-1);
-    buf[len-1] = '\0';
+    return tmpbuf;
 #elif (defined(__sun))
     /*Solaris*/
-    ctime_r(clock, buf);
+    std::array<char, 1024> buf;
+    ctime_r(clock, buf.data());
+    return std::string(buf.begin(), buf.end());
 #else
-    char tmpbuf[30];
-    ctime_r(clock, tmpbuf);
-    strncpy(buf, tmpbuf, len-1);
-    buf[len-1] = '\0';
+    std::array<char, 1024> buf;
+    ctime_r(clock, buf.data());
+    return std::string(buf.begin(), buf.end());
 #endif
-    return buf;
 }
 
-void gmx_format_current_time(char *buf, size_t len)
+std::string gmx_format_current_time()
 {
     time_t clock = time(nullptr);
-    gmx_ctime_r(&clock, buf, len);
+    return gmx_ctime_r(&clock);
 }
 
 int gmx_set_nice(int level)
index c7a29d00087fe67ecd79003247ac8feda0c645b5..fc32046f3652b9f5785436783f3b8c79bb63391a 100644 (file)
@@ -48,6 +48,8 @@
 #include <stddef.h>
 #include <time.h>
 
+#include <string>
+
 /*! \addtogroup module_utility
  * \{
  */
@@ -92,18 +94,16 @@ int gmx_getusername(char *buf, size_t len);
 /*! \brief
  * Portable version of ctime_r.
  *
- * Does not throw.
+ * \throws std::bad_alloc when out of memory.
  */
-char *gmx_ctime_r(const time_t *clock, char *buf, size_t len);
+std::string
+gmx_ctime_r(const time_t *clock);
 /*! \brief
  * Gets the current time as a string.
  *
- * \param[out] buf  Buffer to receive the string.
- * \param[in]  len  Length of buffer \p buf (26 characters should be sufficient).
- *
- * Does not throw.
+ * \throws std::bad_alloc when out of memory.
  */
-void gmx_format_current_time(char *buf, size_t len);
+std::string gmx_format_current_time();
 
 /*! \brief
  * Wrapper for nice().
index f612c36d288dd37386787a04049e75a60b0a01b5..786f4235b97351ecb0dfb53ee94e4ae4ba2bdf91 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2016, by the GROMACS development team, led by
+ * Copyright (c) 2016,2018, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -43,6 +43,8 @@
 
 #include "gromacs/utility/path.h"
 
+#include <utility>
+
 #include <gtest/gtest.h>
 
 namespace
@@ -76,4 +78,75 @@ TEST(PathTest, ConcatenateBeforeExtensionWorks)
     EXPECT_STREQ("complex.dir/traj34", gmx::Path::concatenateBeforeExtension("complex.dir/traj", "34").c_str());
 }
 
+TEST(PathTest, GetParentPathWorks)
+{
+    {
+        auto result = gmx::Path::getParentPath("");
+        EXPECT_EQ("", result);
+    }
+    {
+        auto result = gmx::Path::getParentPath("file.txt");
+        EXPECT_EQ("", result);
+    }
+    {
+        auto result = gmx::Path::getParentPath("dir/file.txt");
+        EXPECT_EQ("dir", result);
+    }
+    {
+        auto result = gmx::Path::getParentPath("windowsdir\\file.txt");
+        EXPECT_EQ("windowsdir", result);
+    }
+    {
+        auto result = gmx::Path::getParentPath("dir/anotherdir/file.txt");
+        EXPECT_EQ("dir/anotherdir", result);
+    }
+    {
+        auto result = gmx::Path::getParentPath("dir");
+        EXPECT_EQ("", result);
+    }
+    {
+        auto result = gmx::Path::getParentPath("dir/anotherdir");
+        EXPECT_EQ("dir", result);
+    }
+}
+
+TEST(PathTest, GetParentPathAndBasenameWorks)
+{
+    {
+        auto result = gmx::Path::getParentPathAndBasename("");
+        EXPECT_EQ("", std::get<0>(result));
+        EXPECT_EQ("", std::get<1>(result));
+    }
+    {
+        auto result = gmx::Path::getParentPathAndBasename("file.txt");
+        EXPECT_EQ("", std::get<0>(result));
+        EXPECT_EQ("file.txt", std::get<1>(result));
+    }
+    {
+        auto result = gmx::Path::getParentPathAndBasename("dir/file.txt");
+        EXPECT_EQ("dir", std::get<0>(result));
+        EXPECT_EQ("file.txt", std::get<1>(result));
+    }
+    {
+        auto result = gmx::Path::getParentPathAndBasename("windowsdir\\file.txt");
+        EXPECT_EQ("windowsdir", std::get<0>(result));
+        EXPECT_EQ("file.txt", std::get<1>(result));
+    }
+    {
+        auto result = gmx::Path::getParentPathAndBasename("dir/anotherdir/file.txt");
+        EXPECT_EQ("dir/anotherdir", std::get<0>(result));
+        EXPECT_EQ("file.txt", std::get<1>(result));
+    }
+    {
+        auto result = gmx::Path::getParentPathAndBasename("dir");
+        EXPECT_EQ("", std::get<0>(result));
+        EXPECT_EQ("dir", std::get<1>(result));
+    }
+    {
+        auto result = gmx::Path::getParentPathAndBasename("dir/anotherdir");
+        EXPECT_EQ("dir", std::get<0>(result));
+        EXPECT_EQ("anotherdir", std::get<1>(result));
+    }
+}
+
 } // namespace