diff --git a/src/atom.cpp b/src/atom.cpp index fe260309e2..a4fe74e6dd 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -341,11 +341,8 @@ void Atom::settings(Atom *old) map_style = old->map_style; sortfreq = old->sortfreq; userbinsize = old->userbinsize; - if (old->firstgroupname) { - int n = strlen(old->firstgroupname) + 1; - firstgroupname = new char[n]; - strcpy(firstgroupname,old->firstgroupname); - } + if (old->firstgroupname) + firstgroupname = utils::strdup(old->firstgroupname); } /* ---------------------------------------------------------------------- @@ -532,9 +529,7 @@ void Atom::add_peratom(const char *name, void *address, memory->srealloc(peratom,maxperatom*sizeof(PerAtom),"atom:peratom"); } - int n = strlen(name) + 1; - peratom[nperatom].name = new char[n]; - strcpy(peratom[nperatom].name,name); + peratom[nperatom].name = utils::strdup(name); peratom[nperatom].address = address; peratom[nperatom].datatype = datatype; peratom[nperatom].cols = cols; @@ -582,9 +577,7 @@ void Atom::add_peratom_vary(const char *name, void *address, memory->srealloc(peratom,maxperatom*sizeof(PerAtom),"atom:peratom"); } - int n = strlen(name) + 1; - peratom[nperatom].name = new char[n]; - strcpy(peratom[nperatom].name,name); + peratom[nperatom].name = utils::strdup(name); peratom[nperatom].address = address; peratom[nperatom].datatype = datatype; peratom[nperatom].cols = -1; @@ -815,9 +808,7 @@ void Atom::modify_params(int narg, char **arg) delete [] firstgroupname; firstgroupname = nullptr; } else { - int n = strlen(arg[iarg+1]) + 1; - firstgroupname = new char[n]; - strcpy(firstgroupname,arg[iarg+1]); + firstgroupname = utils::strdup(arg[iarg+1]); sortfreq = 0; } iarg += 2; @@ -1114,13 +1105,13 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); - values[0] = strtok(buf," \t\n\r\f"); - if (values[0] == nullptr) - error->all(FLERR,"Incorrect atom format in data file"); - for (m = 1; m < nwords; m++) { - values[m] = strtok(nullptr," \t\n\r\f"); - if (values[m] == nullptr) + for (m = 0; m < nwords; m++) { + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + if (strlen(buf) == 0) error->all(FLERR,"Incorrect atom format in data file"); + values[m] = buf; + buf += strlen(buf)+1; } int imx = 0, imy = 0, imz = 0; @@ -1217,9 +1208,12 @@ void Atom::data_vels(int n, char *buf, tagint id_offset) for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); - values[0] = strtok(buf," \t\n\r\f"); - for (j = 1; j < nwords; j++) - values[j] = strtok(nullptr," \t\n\r\f"); + for (j = 0; j < nwords; j++) { + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + values[j] = buf; + buf += strlen(buf)+1; + } tagdata = ATOTAGINT(values[0]) + id_offset; if (tagdata <= 0 || tagdata > map_tag_max) @@ -1569,9 +1563,12 @@ void Atom::data_bonus(int n, char *buf, AtomVec *avec_bonus, tagint id_offset) for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); - values[0] = strtok(buf," \t\n\r\f"); - for (j = 1; j < nwords; j++) - values[j] = strtok(nullptr," \t\n\r\f"); + for (j = 0; j < nwords; j++) { + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + values[j] = buf; + buf += strlen(buf)+1; + } tagdata = ATOTAGINT(values[0]) + id_offset; if (tagdata <= 0 || tagdata > map_tag_max) @@ -1611,8 +1608,10 @@ void Atom::data_bodies(int n, char *buf, AtomVec *avec_body, tagint id_offset) // else skip values for (int i = 0; i < n; i++) { - if (i == 0) tagdata = ATOTAGINT(strtok(buf," \t\n\r\f")) + id_offset; - else tagdata = ATOTAGINT(strtok(nullptr," \t\n\r\f")) + id_offset; + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + tagdata = utils::tnumeric(FLERR,buf,false,lmp) + id_offset; + buf += strlen(buf)+1; if (tagdata <= 0 || tagdata > map_tag_max) error->one(FLERR,"Invalid atom ID in Bodies section of data file"); @@ -1622,8 +1621,15 @@ void Atom::data_bodies(int n, char *buf, AtomVec *avec_body, tagint id_offset) else error->one(FLERR,"Duplicate atom ID in Bodies section of data file"); - ninteger = utils::inumeric(FLERR,strtok(nullptr," \t\n\r\f"),false,lmp); - ndouble = utils::inumeric(FLERR,strtok(nullptr," \t\n\r\f"),false,lmp); + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + ninteger = utils::inumeric(FLERR,buf,false,lmp); + buf += strlen(buf)+1; + + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + ndouble = utils::inumeric(FLERR,buf,false,lmp); + buf += strlen(buf)+1; if ((m = map(tagdata)) >= 0) { if (ninteger > maxint) { @@ -1637,17 +1643,29 @@ void Atom::data_bodies(int n, char *buf, AtomVec *avec_body, tagint id_offset) dvalues = new double[maxdouble]; } - for (j = 0; j < ninteger; j++) - ivalues[j] = utils::inumeric(FLERR,strtok(nullptr," \t\n\r\f"),false,lmp); - for (j = 0; j < ndouble; j++) - dvalues[j] = utils::numeric(FLERR,strtok(nullptr," \t\n\r\f"),false,lmp); + for (j = 0; j < ninteger; j++) { + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + ivalues[j] = utils::inumeric(FLERR,buf,false,lmp); + buf += strlen(buf)+1; + } + + for (j = 0; j < ndouble; j++) { + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + dvalues[j] = utils::numeric(FLERR,buf,false,lmp); + buf += strlen(buf)+1; + } avec_body->data_body(m,ninteger,ndouble,ivalues,dvalues); } else { nvalues = ninteger + ndouble; // number of values to skip - for (j = 0; j < nvalues; j++) - strtok(nullptr," \t\n\r\f"); + for (j = 0; j < nvalues; j++) { + buf += strspn(buf," \t\n\r\f"); + buf[strcspn(buf," \t\n\r\f")] = '\0'; + buf += strlen(buf)+1; + } } } @@ -2400,9 +2418,7 @@ int Atom::add_custom(const char *name, int flag) nivector++; iname = (char **) memory->srealloc(iname,nivector*sizeof(char *), "atom:iname"); - int n = strlen(name) + 1; - iname[index] = new char[n]; - strcpy(iname[index],name); + iname[index] = utils::strdup(name); ivector = (int **) memory->srealloc(ivector,nivector*sizeof(int *), "atom:ivector"); memory->create(ivector[index],nmax,"atom:ivector"); @@ -2411,9 +2427,7 @@ int Atom::add_custom(const char *name, int flag) ndvector++; dname = (char **) memory->srealloc(dname,ndvector*sizeof(char *), "atom:dname"); - int n = strlen(name) + 1; - dname[index] = new char[n]; - strcpy(dname[index],name); + dname[index] = utils::strdup(name); dvector = (double **) memory->srealloc(dvector,ndvector*sizeof(double *), "atom:dvector"); memory->create(dvector[index],nmax,"atom:dvector"); diff --git a/src/atom_vec.cpp b/src/atom_vec.cpp index 4406ac5f23..7d7cfa4878 100644 --- a/src/atom_vec.cpp +++ b/src/atom_vec.cpp @@ -154,11 +154,8 @@ void AtomVec::store_args(int narg, char **arg) nargcopy = narg; if (nargcopy) argcopy = new char*[nargcopy]; else argcopy = nullptr; - for (int i = 0; i < nargcopy; i++) { - int n = strlen(arg[i]) + 1; - argcopy[i] = new char[n]; - strcpy(argcopy[i],arg[i]); - } + for (int i = 0; i < nargcopy; i++) + argcopy[i] = utils::strdup(arg[i]); } /* ---------------------------------------------------------------------- diff --git a/src/atom_vec_hybrid.cpp b/src/atom_vec_hybrid.cpp index 8679b7383d..6ddb72a1bf 100644 --- a/src/atom_vec_hybrid.cpp +++ b/src/atom_vec_hybrid.cpp @@ -109,8 +109,7 @@ void AtomVecHybrid::process_args(int narg, char **arg) if (strcmp(arg[iarg],keywords[i]) == 0) error->all(FLERR,"Atom style hybrid cannot use same atom style twice"); styles[nstyles] = atom->new_avec(arg[iarg],1,dummy); - keywords[nstyles] = new char[strlen(arg[iarg])+1]; - strcpy(keywords[nstyles],arg[iarg]); + keywords[nstyles] = utils::strdup(arg[iarg]); jarg = iarg + 1; while (jarg < narg && !known_style(arg[jarg])) jarg++; styles[nstyles]->process_args(jarg-iarg-1,&arg[iarg+1]); @@ -601,13 +600,10 @@ void AtomVecHybrid::build_styles() allstyles = new char*[nallstyles]; - int n; nallstyles = 0; #define ATOM_CLASS -#define AtomStyle(key,Class) \ - n = strlen(#key) + 1; \ - allstyles[nallstyles] = new char[n]; \ - strcpy(allstyles[nallstyles],#key); \ +#define AtomStyle(key,Class) \ + allstyles[nallstyles] = utils::strdup(#key); \ nallstyles++; #include "style_atom.h" // IWYU pragma: keep #undef AtomStyle diff --git a/src/body.cpp b/src/body.cpp index 35d6e53753..89bb2fc1d9 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -20,9 +20,7 @@ using namespace LAMMPS_NS; Body::Body(LAMMPS *lmp, int /*narg*/, char **arg) : Pointers(lmp) { - int n = strlen(arg[0]) + 1; - style = new char[n]; - strcpy(style,arg[0]); + style = utils::strdup(arg[0]); icp = nullptr; dcp = nullptr; } diff --git a/src/comm.cpp b/src/comm.cpp index 8e119744fc..6d3f72d9c0 100644 --- a/src/comm.cpp +++ b/src/comm.cpp @@ -149,16 +149,11 @@ void Comm::copy_arrays(Comm *oldcomm) memcpy(cutusermulti,oldcomm->cutusermulti,atom->ntypes+1); } - if (customfile) { - int n = strlen(oldcomm->customfile) + 1; - customfile = new char[n]; - strcpy(customfile,oldcomm->customfile); - } - if (outfile) { - int n = strlen(oldcomm->outfile) + 1; - outfile = new char[n]; - strcpy(outfile,oldcomm->outfile); - } + if (customfile) + customfile = utils::strdup(oldcomm->customfile); + + if (outfile) + outfile = utils::strdup(oldcomm->outfile); } /* ---------------------------------------------------------------------- @@ -391,9 +386,7 @@ void Comm::set_processors(int narg, char **arg) if (iarg+3 > narg) error->all(FLERR,"Illegal processors command"); gridflag = CUSTOM; delete [] customfile; - int n = strlen(arg[iarg+2]) + 1; - customfile = new char[n]; - strcpy(customfile,arg[iarg+2]); + customfile = utils::strdup(arg[iarg+2]); iarg += 1; } else error->all(FLERR,"Illegal processors command"); @@ -453,9 +446,7 @@ void Comm::set_processors(int narg, char **arg) } else if (strcmp(arg[iarg],"file") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal processors command"); delete [] outfile; - int n = strlen(arg[iarg+1]) + 1; - outfile = new char[n]; - strcpy(outfile,arg[iarg+1]); + outfile = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal processors command"); diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp index effb7c7ed3..ab043e67c8 100644 --- a/src/dump_atom.cpp +++ b/src/dump_atom.cpp @@ -47,20 +47,12 @@ void DumpAtom::init_style() // format = copy of default or user-specified line format // default depends on image flags - delete [] format; + delete[] format; if (format_line_user) { - int n = strlen(format_line_user) + 2; - format = new char[n]; - strcpy(format,format_line_user); - strcat(format,"\n"); + format = utils::strdup(std::string(format_line_user) + "\n"); } else { - char *str; - if (image_flag == 0) str = (char *) TAGINT_FORMAT " %d %g %g %g"; - else str = (char *) TAGINT_FORMAT " %d %g %g %g %d %d %d"; - int n = strlen(str) + 2; - format = new char[n]; - strcpy(format,str); - strcat(format,"\n"); + if (image_flag == 0) format = utils::strdup(TAGINT_FORMAT " %d %g %g %g\n"); + else format = utils::strdup(TAGINT_FORMAT " %d %g %g %g %d %d %d\n"); } // setup boundary string diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index 07e51ce54a..53bc9449a0 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -150,39 +150,38 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) : ntypes = atom->ntypes; typenames = new char*[ntypes+1]; - for (int itype = 1; itype <= ntypes; itype++) { - typenames[itype] = new char[2]; - strcpy(typenames[itype],"C"); - } + for (int itype = 1; itype <= ntypes; itype++) + typenames[itype] = utils::strdup("C"); // setup format strings vformat = new char*[nfield]; + std::string cols; - format_default = new char[4*nfield+1]; - format_default[0] = '\0'; - + cols.clear(); for (int i = 0; i < nfield; i++) { - if (vtype[i] == Dump::INT) strcat(format_default,"%d "); - else if (vtype[i] == Dump::DOUBLE) strcat(format_default,"%g "); - else if (vtype[i] == Dump::STRING) strcat(format_default,"%s "); - else if (vtype[i] == Dump::BIGINT) strcat(format_default,BIGINT_FORMAT " "); + if (vtype[i] == Dump::INT) cols += "%d "; + else if (vtype[i] == Dump::DOUBLE) cols += "%g "; + else if (vtype[i] == Dump::STRING) cols += "%s "; + else if (vtype[i] == Dump::BIGINT) cols += BIGINT_FORMAT " "; vformat[i] = nullptr; } + cols.resize(cols.size()-1); + format_default = utils::strdup(cols); format_column_user = new char*[nfield]; for (int i = 0; i < nfield; i++) format_column_user[i] = nullptr; // setup column string - int n = 0; - for (int iarg = 0; iarg < nfield; iarg++) n += strlen(earg[iarg]) + 2; - columns = new char[n]; - columns[0] = '\0'; + cols.clear(); for (int iarg = 0; iarg < nfield; iarg++) { - strcat(columns,earg[iarg]); - if (iarg+1 < nfield) strcat(columns," "); + cols += earg[iarg]; + cols += " "; } + // remove trailing blank and copy + cols.resize(cols.size()-1); + columns = utils::strdup(cols); } /* ---------------------------------------------------------------------- */ @@ -263,44 +262,36 @@ void DumpCustom::init_style() // format = copy of default or user-specified line format delete [] format; - char *str; - if (format_line_user) str = format_line_user; - else str = format_default; - - int n = strlen(str) + 1; - format = new char[n]; - strcpy(format,str); + if (format_line_user) format = utils::strdup(format_line_user); + else format = utils::strdup(format_default); // tokenize the format string and add space at end of each format element // if user-specified int/float format exists, use it instead // if user-specified column format exists, use it instead // lo priority = line, medium priority = int/float, hi priority = column - char *ptr; - for (int i = 0; i < nfield; i++) { - if (i == 0) ptr = strtok(format," \0"); - else ptr = strtok(nullptr," \0"); - if (ptr == nullptr) error->all(FLERR,"Dump_modify format line is too short"); + auto words = utils::split_words(format); + if ((int) words.size() < nfield) + error->all(FLERR,"Dump_modify format line is too short"); + + int i=0; + for (auto word : words) { delete [] vformat[i]; - if (format_column_user[i]) { - vformat[i] = new char[strlen(format_column_user[i]) + 2]; - strcpy(vformat[i],format_column_user[i]); - } else if (vtype[i] == Dump::INT && format_int_user) { - vformat[i] = new char[strlen(format_int_user) + 2]; - strcpy(vformat[i],format_int_user); - } else if (vtype[i] == Dump::DOUBLE && format_float_user) { - vformat[i] = new char[strlen(format_float_user) + 2]; - strcpy(vformat[i],format_float_user); - } else if (vtype[i] == Dump::BIGINT && format_bigint_user) { - vformat[i] = new char[strlen(format_bigint_user) + 2]; - strcpy(vformat[i],format_bigint_user); - } else { - vformat[i] = new char[strlen(ptr) + 2]; - strcpy(vformat[i],ptr); - } + if (format_column_user[i]) + vformat[i] = utils::strdup(std::string(format_column_user[i]) + " "); + else if (vtype[i] == Dump::INT && format_int_user) + vformat[i] = utils::strdup(std::string(format_int_user) + " "); + else if (vtype[i] == Dump::DOUBLE && format_float_user) + vformat[i] = utils::strdup(std::string(format_float_user) + " "); + else if (vtype[i] == Dump::BIGINT && format_bigint_user) + vformat[i] = utils::strdup(std::string(format_int_user) + " "); + else vformat[i] = utils::strdup(word + " "); - if (i+1 < nfield) vformat[i] = strcat(vformat[i]," "); + // remove trailing blank on last column's format + if (i == nfield-1) vformat[i][strlen(vformat[i])-1] = '\0'; + + ++i; } // setup boundary string diff --git a/src/dump_image.cpp b/src/dump_image.cpp index 9fc05aaf71..69ebad9c52 100644 --- a/src/dump_image.cpp +++ b/src/dump_image.cpp @@ -31,6 +31,7 @@ #include "memory.h" #include "modify.h" #include "molecule.h" +#include "tokenizer.h" #include "variable.h" #include @@ -1207,32 +1208,19 @@ int DumpImage::modify_param(int narg, char **arg) int nlo,nhi; utils::bounds(FLERR,arg[1],1,atom->ntypes,nlo,nhi,error); - // ptrs = list of ncount colornames separated by '/' + // get list of colors + auto colors = Tokenizer(arg[2],"/").as_vector(); + const int ncolors = colors.size(); - int ncount = 1; - char *nextptr; - char *ptr = arg[2]; - while ((nextptr = strchr(ptr,'/'))) { - ptr = nextptr + 1; - ncount++; - } - char **ptrs = new char*[ncount+1]; - ncount = 0; - ptrs[ncount++] = strtok(arg[2],"/"); - while ((ptrs[ncount++] = strtok(nullptr,"/"))); - ncount--; - - // assign each of ncount colors in round-robin fashion to types + // assign colors in round-robin fashion to types int m = 0; for (int i = nlo; i <= nhi; i++) { - colortype[i] = image->color2rgb(ptrs[m%ncount]); + colortype[i] = image->color2rgb(colors[m%ncolors].c_str()); if (colortype[i] == nullptr) error->all(FLERR,"Invalid color in dump_modify command"); m++; } - - delete [] ptrs; return 3; } diff --git a/src/dump_local.cpp b/src/dump_local.cpp index 58a047cf97..beb9236d63 100644 --- a/src/dump_local.cpp +++ b/src/dump_local.cpp @@ -26,8 +26,6 @@ using namespace LAMMPS_NS; -enum{INT,DOUBLE}; - #define ONEFIELD 32 #define DELTA 1048576 @@ -93,8 +91,8 @@ DumpLocal::DumpLocal(LAMMPS *lmp, int narg, char **arg) : format_default[0] = '\0'; for (int i = 0; i < size_one; i++) { - if (vtype[i] == INT) strcat(format_default,"%d "); - else if (vtype[i] == DOUBLE) strcat(format_default,"%g "); + if (vtype[i] == Dump::INT) strcat(format_default,"%d "); + else if (vtype[i] == Dump::DOUBLE) strcat(format_default,"%g "); vformat[i] = nullptr; } @@ -103,21 +101,16 @@ DumpLocal::DumpLocal(LAMMPS *lmp, int narg, char **arg) : // setup column string - int n = 0; - for (int iarg = 0; iarg < nfield; iarg++) n += strlen(earg[iarg]) + 2; - columns = new char[n]; - columns[0] = '\0'; + std::string cols; for (int iarg = 0; iarg < nfield; iarg++) { - strcat(columns,earg[iarg]); - strcat(columns," "); + cols += earg[iarg]; + cols += " "; } + columns = utils::strdup(cols); // setup default label string - char *str = (char *) "ENTRIES"; - n = strlen(str) + 1; - label = new char[n]; - strcpy(label,str); + label = utils::strdup("ENTRIES"); // if wildcard expansion occurred, free earg memory from exapnd_args() @@ -164,41 +157,30 @@ void DumpLocal::init_style() // format = copy of default or user-specified line format delete [] format; - char *str; - if (format_line_user) str = format_line_user; - else str = format_default; - - int n = strlen(str) + 1; - format = new char[n]; - strcpy(format,str); + if (format_line_user) format = utils::strdup(format_line_user); + else format = utils::strdup(format_default); // tokenize the format string and add space at end of each format element // if user-specified int/float format exists, use it instead // if user-specified column format exists, use it instead // lo priority = line, medium priority = int/float, hi priority = column - char *ptr; - for (int i = 0; i < size_one; i++) { - if (i == 0) ptr = strtok(format," \0"); - else ptr = strtok(nullptr," \0"); - if (ptr == nullptr) error->all(FLERR,"Dump_modify format line is too short"); + auto words = utils::split_words(format); + if ((int) words.size() < size_one) + error->all(FLERR,"Dump_modify format line is too short"); + + int i=0; + for (auto word : words) { delete [] vformat[i]; - if (format_column_user[i]) { - vformat[i] = new char[strlen(format_column_user[i]) + 2]; - strcpy(vformat[i],format_column_user[i]); - } else if (vtype[i] == INT && format_int_user) { - vformat[i] = new char[strlen(format_int_user) + 2]; - strcpy(vformat[i],format_int_user); - } else if (vtype[i] == DOUBLE && format_float_user) { - vformat[i] = new char[strlen(format_float_user) + 2]; - strcpy(vformat[i],format_float_user); - } else { - vformat[i] = new char[strlen(ptr) + 2]; - strcpy(vformat[i],ptr); - } - - vformat[i] = strcat(vformat[i]," "); + if (format_column_user[i]) + vformat[i] = utils::strdup(std::string(format_column_user[i]) + " "); + else if (vtype[i] == Dump::INT && format_int_user) + vformat[i] = utils::strdup(std::string(format_int_user) + " "); + else if (vtype[i] == Dump::DOUBLE && format_float_user) + vformat[i] = utils::strdup(std::string(format_float_user) + " "); + else vformat[i] = utils::strdup(word + " "); + ++i; } // setup boundary string @@ -241,9 +223,7 @@ int DumpLocal::modify_param(int narg, char **arg) if (strcmp(arg[0],"label") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); delete [] label; - int n = strlen(arg[1]) + 1; - label = new char[n]; - strcpy(label,arg[1]); + label = utils::strdup(arg[1]); return 2; } return 0; @@ -353,7 +333,7 @@ int DumpLocal::convert_string(int n, double *mybuf) } for (j = 0; j < size_one; j++) { - if (vtype[j] == INT) + if (vtype[j] == Dump::INT) offset += sprintf(&sbuf[offset],vformat[j],static_cast (mybuf[m])); else offset += sprintf(&sbuf[offset],vformat[j],mybuf[m]); @@ -388,7 +368,7 @@ void DumpLocal::write_lines(int n, double *mybuf) int m = 0; for (i = 0; i < n; i++) { for (j = 0; j < size_one; j++) { - if (vtype[j] == INT) fprintf(fp,vformat[j],static_cast (mybuf[m])); + if (vtype[j] == Dump::INT) fprintf(fp,vformat[j],static_cast (mybuf[m])); else fprintf(fp,vformat[j],mybuf[m]); m++; } @@ -408,13 +388,13 @@ void DumpLocal::parse_fields(int narg, char **arg) if (strcmp(arg[iarg],"index") == 0) { pack_choice[iarg] = &DumpLocal::pack_index; - vtype[iarg] = INT; + vtype[iarg] = Dump::INT; } else { int n; ArgInfo argi(arg[iarg],ArgInfo::COMPUTE|ArgInfo::FIX); computefixflag = 1; - vtype[iarg] = DOUBLE; + vtype[iarg] = Dump::DOUBLE; argindex[iarg] = argi.get_index1(); switch (argi.get_type()) { diff --git a/src/fix_property_atom.cpp b/src/fix_property_atom.cpp index f18888bbfc..56add7a0d1 100644 --- a/src/fix_property_atom.cpp +++ b/src/fix_property_atom.cpp @@ -17,6 +17,7 @@ #include "comm.h" #include "error.h" #include "memory.h" +#include "tokenizer.h" #include @@ -214,67 +215,51 @@ void FixPropertyAtom::read_data_section(char *keyword, int n, char *buf, atom->map_set(); } - next = strchr(buf,'\n'); - *next = '\0'; - int nwords = utils::trim_and_count_words(buf); - *next = '\n'; - - if (nwords != nvalue+1) - error->all(FLERR,fmt::format("Incorrect {} format in data file",keyword)); - - char **values = new char*[nwords]; - // loop over lines of atom info // tokenize the line into values - // if I own atom tag, unpack its values + // if I own atom tag, assign its values tagint map_tag_max = atom->map_tag_max; for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); + *next = '\0'; - values[0] = strtok(buf," \t\n\r\f"); - if (values[0] == nullptr) - error->all(FLERR,fmt::format("Too few lines in {} section of data file",keyword)); + try { + ValueTokenizer values(buf); + if (values.count() != nvalue+1) + error->all(FLERR,fmt::format("Incorrect format in {} section " + "of data file: {}",keyword,buf)); - int format_ok = 1; - for (j = 1; j < nwords; j++) { - values[j] = strtok(nullptr," \t\n\r\f"); - if (values[j] == nullptr) format_ok = 0; - } - if (!format_ok) - error->all(FLERR,fmt::format("Incorrect {} format in data file",keyword)); + itag = values.next_tagint() + id_offset; + if (itag <= 0 || itag > map_tag_max) + error->all(FLERR,fmt::format("Invalid atom ID {} in {} section of " + "data file",itag, keyword)); - itag = ATOTAGINT(values[0]) + id_offset; - if (itag <= 0 || itag > map_tag_max) - error->all(FLERR,fmt::format("Invalid atom ID {} in {} section of " - "data file",itag, keyword)); + // assign words in line to per-atom vectors - // assign words in line to per-atom vectors - - if ((m = atom->map(itag)) >= 0) { - for (j = 0; j < nvalue; j++) { - if (style[j] == MOLECULE) { - atom->molecule[m] = utils::tnumeric(FLERR,values[j+1],false,lmp); - } else if (style[j] == CHARGE) { - atom->q[m] = utils::numeric(FLERR,values[j+1],false,lmp); - } else if (style[j] == RMASS) { - atom->rmass[m] = utils::numeric(FLERR,values[j+1],false,lmp); - } else if (style[j] == INTEGER) { - atom->ivector[index[j]][m] = utils::inumeric(FLERR,values[j+1], - false,lmp); - } else if (style[j] == DOUBLE) { - atom->dvector[index[j]][m] = utils::numeric(FLERR,values[j+1], - true,lmp); + if ((m = atom->map(itag)) >= 0) { + for (j = 0; j < nvalue; j++) { + if (style[j] == MOLECULE) { + atom->molecule[m] = values.next_tagint(); + } else if (style[j] == CHARGE) { + atom->q[m] = values.next_double(); + } else if (style[j] == RMASS) { + atom->rmass[m] = values.next_double(); + } else if (style[j] == INTEGER) { + atom->ivector[index[j]][m] = values.next_int(); + } else if (style[j] == DOUBLE) { + atom->dvector[index[j]][m] = values.next_double(); + } } } + } catch (TokenizerException &e) { + error->all(FLERR,fmt::format("Invalid format in {} section of data " + "file '{}': {}",keyword, buf,e.what())); } - buf = next + 1; } - delete [] values; - if (mapflag) { atom->map_delete(); atom->map_style = 0; @@ -342,8 +327,9 @@ void FixPropertyAtom::write_data_section_pack(int /*mth*/, double **buf) } /* ---------------------------------------------------------------------- - write section keyword for Mth data section to file - use Molecules or Charges if that is only field, else use fix ID + write a Molecules or Charges section if that is only field + manages by this fix instance. Otherwise write everything + to the section labeled by the fix ID only called by proc 0 ------------------------------------------------------------------------- */ @@ -351,7 +337,18 @@ void FixPropertyAtom::write_data_section_keyword(int /*mth*/, FILE *fp) { if (nvalue == 1 && style[0] == MOLECULE) fprintf(fp,"\nMolecules\n\n"); else if (nvalue == 1 && style[0] == CHARGE) fprintf(fp,"\nCharges\n\n"); - else fprintf(fp,"\n%s\n\n",id); + else { + fprintf(fp,"\n%s #",id); + // write column hint as comment + for (int i = 0; i < nvalue; ++i) { + if (style[i] == MOLECULE) fputs(" mol",fp); + else if (style[i] == CHARGE) fputs(" q",fp); + else if (style[i] == RMASS) fputs(" rmass",fp); + else if (style[i] == INTEGER) fprintf(fp," i_%s", atom->iname[index[i]]); + else if (style[i] == DOUBLE) fprintf(fp, " d_%s", atom->dname[index[i]]); + } + fputs("\n\n",fp); + } } /* ---------------------------------------------------------------------- diff --git a/src/group.cpp b/src/group.cpp index 9139847045..aa05ca6951 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -28,6 +28,7 @@ #include "modify.h" #include "output.h" #include "region.h" +#include "tokenizer.h" #include "variable.h" #include @@ -300,20 +301,24 @@ void Group::assign(int narg, char **arg) else if (category == MOLECULE) tattribute = atom->molecule; else if (category == ID) tattribute = atom->tag; - char *ptr; tagint start,stop,delta; for (int iarg = 2; iarg < narg; iarg++) { delta = 1; - if (strchr(arg[iarg],':')) { - ptr = strtok(arg[iarg],":"); - start = utils::tnumeric(FLERR,ptr,false,lmp); - ptr = strtok(nullptr,":"); - stop = utils::tnumeric(FLERR,ptr,false,lmp); - ptr = strtok(nullptr,":"); - if (ptr) delta = utils::tnumeric(FLERR,ptr,false,lmp); - } else { - start = stop = utils::tnumeric(FLERR,arg[iarg],false,lmp); + try { + ValueTokenizer values(arg[iarg],":"); + start = values.next_tagint(); + if (utils::strmatch(arg[iarg],"^-?\\d+$")) { + stop = start; + } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+$")) { + stop = values.next_tagint(); + } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+:\\d+$")) { + stop = values.next_tagint(); + delta = values.next_tagint(); + } else throw TokenizerException("Syntax error",""); + } catch (TokenizerException &e) { + error->all(FLERR,fmt::format("Incorrect range string " + "'{}': {}",arg[iarg],e.what())); } if (delta < 1) error->all(FLERR,"Illegal range increment value"); diff --git a/src/input.cpp b/src/input.cpp index df5cf0efbe..eeb211a6d1 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -1076,22 +1076,20 @@ void Input::partition() int ilo,ihi; utils::bounds(FLERR,arg[1],1,universe->nworlds,ilo,ihi,error); - // copy original line to copy, since will use strtok() on it - // ptr = start of 4th word + // new command starts at the 3rd argument, + // which must not be another partition command - strcpy(copy,line); - char *ptr = strtok(copy," \t\n\r\f"); - ptr = strtok(nullptr," \t\n\r\f"); - ptr = strtok(nullptr," \t\n\r\f"); - ptr += strlen(ptr) + 1; - ptr += strspn(ptr," \t\n\r\f"); + if (strcmp(arg[2],"partition") == 0) + error->all(FLERR,"Illegal partition command"); + + char *cmd = strstr(line,arg[2]); // execute the remaining command line on requested partitions if (yesflag) { - if (universe->iworld+1 >= ilo && universe->iworld+1 <= ihi) one(ptr); + if (universe->iworld+1 >= ilo && universe->iworld+1 <= ihi) one(cmd); } else { - if (universe->iworld+1 < ilo || universe->iworld+1 > ihi) one(ptr); + if (universe->iworld+1 < ilo || universe->iworld+1 > ihi) one(cmd); } } diff --git a/src/library.cpp b/src/library.cpp index 2a7bbf07b3..94f8dfa7a3 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -445,26 +445,14 @@ is passed to :cpp:func:`lammps_commands_string` for processing. void lammps_commands_list(void *handle, int ncmd, const char **cmds) { LAMMPS *lmp = (LAMMPS *) handle; - - int n = ncmd+1; - for (int i = 0; i < ncmd; i++) n += strlen(cmds[i]); - - char *str = (char *) lmp->memory->smalloc(n,"lib/commands/list:str"); - str[0] = '\0'; - n = 0; + std::string allcmds; for (int i = 0; i < ncmd; i++) { - strcpy(&str[n],cmds[i]); - n += strlen(cmds[i]); - if (str[n-1] != '\n') { - str[n] = '\n'; - str[n+1] = '\0'; - n++; - } + allcmds.append(cmds[i]); + if (allcmds.back() != '\n') allcmds.append(1,'\n'); } - lammps_commands_string(handle,str); - lmp->memory->sfree(str); + lammps_commands_string(handle,allcmds.c_str()); } /* ---------------------------------------------------------------------- */ diff --git a/src/modify.cpp b/src/modify.cpp index 0b6a6ca823..2c0fd434d6 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -995,18 +995,14 @@ void Modify::replace_fix(const char *replaceID, if (jfix >= 0) error->all(FLERR,"Replace_fix ID is already in use"); delete [] fix[ifix]->id; - int n = strlen(arg[0]) + 1; - fix[ifix]->id = new char[n]; - strcpy(fix[ifix]->id,arg[0]); + fix[ifix]->id = utils::strdup(arg[0]); int jgroup = group->find(arg[1]); if (jgroup == -1) error->all(FLERR,"Could not find replace_fix group ID"); fix[ifix]->igroup = jgroup; delete [] fix[ifix]->style; - n = strlen(arg[2]) + 1; - fix[ifix]->style = new char[n]; - strcpy(fix[ifix]->style,arg[2]); + fix[ifix]->style = utils::strdup(arg[2]); // invoke add_fix // it will find and overwrite the replaceID fix diff --git a/src/output.cpp b/src/output.cpp index 828796b873..988ef04409 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -766,12 +766,8 @@ void Output::create_restart(int narg, char **arg) delete [] restart2a; delete [] restart2b; restart_toggle = 0; - int n = strlen(arg[1]) + 3; - restart2a = new char[n]; - strcpy(restart2a,arg[1]); - n = strlen(arg[2]) + 1; - restart2b = new char[n]; - strcpy(restart2b,arg[2]); + restart2a = utils::strdup(arg[1]); + restart2b = utils::strdup(arg[2]); } // check for multiproc output and an MPI-IO filename diff --git a/src/pair_coul_streitz.cpp b/src/pair_coul_streitz.cpp index 0b6e6513a3..68790c0f03 100644 --- a/src/pair_coul_streitz.cpp +++ b/src/pair_coul_streitz.cpp @@ -164,9 +164,7 @@ void PairCoulStreitz::coeff(int narg, char **arg) if (strcmp(arg[i],elements[j]) == 0) break; map[i-2] = j; if (j == nelements) { - n = strlen(arg[i]) + 1; - elements[j] = new char[n]; - strcpy(elements[j],arg[i]); + elements[j] = utils::strdup(arg[i]); nelements++; } } diff --git a/src/procmap.cpp b/src/procmap.cpp index b8e6e02ed5..87ab415e5e 100644 --- a/src/procmap.cpp +++ b/src/procmap.cpp @@ -22,6 +22,7 @@ #include "error.h" #include "math_extra.h" #include "memory.h" +#include "tokenizer.h" #include "universe.h" #include @@ -300,12 +301,16 @@ void ProcMap::custom_grid(char *cfile, int nprocs, } } - int n = strlen(line) + 1; - MPI_Bcast(&n,1,MPI_INT,0,world); - MPI_Bcast(line,n,MPI_CHAR,0,world); - - int rv = sscanf(line,"%d %d %d",&procgrid[0],&procgrid[1],&procgrid[2]); - if (rv != 3) error->all(FLERR,"Processors custom grid file is inconsistent"); + MPI_Bcast(line,MAXLINE,MPI_CHAR,0,world); + try { + ValueTokenizer procs(line); + procgrid[0] = procs.next_int(); + procgrid[1] = procs.next_int(); + procgrid[2] = procs.next_int(); + } catch (TokenizerException &e) { + error->all(FLERR,fmt::format("Processors custom grid file " + "is inconsistent: {}", e.what())); + } int flag = 0; if (procgrid[0]*procgrid[1]*procgrid[2] != nprocs) flag = 1; @@ -324,10 +329,17 @@ void ProcMap::custom_grid(char *cfile, int nprocs, for (int i = 0; i < nprocs; i++) { if (!fgets(line,MAXLINE,fp)) error->one(FLERR,"Unexpected end of custom file"); - rv = sscanf(line,"%d %d %d %d", - &cmap[i][0],&cmap[i][1],&cmap[i][2],&cmap[i][3]); - if (rv != 4) - error->one(FLERR,"Processors custom grid file is inconsistent"); + + try { + ValueTokenizer pmap(line); + cmap[i][0] = pmap.next_int(); + cmap[i][1] = pmap.next_int(); + cmap[i][2] = pmap.next_int(); + cmap[i][3] = pmap.next_int(); + } catch (TokenizerException &e) { + error->one(FLERR,fmt::format("Processors custom grid file is " + "inconsistent: {}", e.what())); + } } fclose(fp); } diff --git a/src/read_data.cpp b/src/read_data.cpp index e8eb90dcb1..bc214fbb09 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -73,8 +73,8 @@ ReadData::ReadData(LAMMPS *lmp) : Pointers(lmp) keyword = new char[MAXLINE]; style = new char[MAXLINE]; buffer = new char[CHUNK*MAXLINE]; - narg = maxarg = 0; - arg = nullptr; + ncoeffarg = maxcoeffarg = 0; + coeffarg = nullptr; fp = nullptr; // customize for new sections @@ -98,7 +98,7 @@ ReadData::~ReadData() delete [] keyword; delete [] style; delete [] buffer; - memory->sfree(arg); + memory->sfree(coeffarg); for (int i = 0; i < nfix; i++) { delete [] fix_header[i]; @@ -278,14 +278,8 @@ void ReadData::command(int narg, char **arg) if (fix_index[nfix] < 0) error->all(FLERR,"Fix ID for read_data does not exist"); if (strcmp(arg[iarg+2],"NULL") == 0) fix_header[nfix] = nullptr; - else { - int n = strlen(arg[iarg+2]) + 1; - fix_header[nfix] = new char[n]; - strcpy(fix_header[nfix],arg[iarg+2]); - } - int n = strlen(arg[iarg+3]) + 1; - fix_section[nfix] = new char[n]; - strcpy(fix_section[nfix],arg[iarg+3]); + else fix_header[nfix] = utils::strdup(arg[iarg+2]); + fix_section[nfix] = utils::strdup(arg[iarg+3]); nfix++; iarg += 4; @@ -1760,9 +1754,9 @@ void ReadData::paircoeffs() next = strchr(buf,'\n'); *next = '\0'; parse_coeffs(buf,nullptr,1,2,toffset); - if (narg == 0) + if (ncoeffarg == 0) error->all(FLERR,"Unexpected empty line in PairCoeffs section"); - force->pair->coeff(narg,arg); + force->pair->coeff(ncoeffarg,coeffarg); buf = next + 1; } delete [] original; @@ -1787,9 +1781,9 @@ void ReadData::pairIJcoeffs() next = strchr(buf,'\n'); *next = '\0'; parse_coeffs(buf,nullptr,0,2,toffset); - if (narg == 0) + if (ncoeffarg == 0) error->all(FLERR,"Unexpected empty line in PairCoeffs section"); - force->pair->coeff(narg,arg); + force->pair->coeff(ncoeffarg,coeffarg); buf = next + 1; } delete [] original; @@ -1812,9 +1806,9 @@ void ReadData::bondcoeffs() next = strchr(buf,'\n'); *next = '\0'; parse_coeffs(buf,nullptr,0,1,boffset); - if (narg == 0) + if (ncoeffarg == 0) error->all(FLERR,"Unexpected empty line in BondCoeffs section"); - force->bond->coeff(narg,arg); + force->bond->coeff(ncoeffarg,coeffarg); buf = next + 1; } delete [] original; @@ -1839,8 +1833,8 @@ void ReadData::anglecoeffs(int which) if (which == 0) parse_coeffs(buf,nullptr,0,1,aoffset); else if (which == 1) parse_coeffs(buf,"bb",0,1,aoffset); else if (which == 2) parse_coeffs(buf,"ba",0,1,aoffset); - if (narg == 0) error->all(FLERR,"Unexpected empty line in AngleCoeffs section"); - force->angle->coeff(narg,arg); + if (ncoeffarg == 0) error->all(FLERR,"Unexpected empty line in AngleCoeffs section"); + force->angle->coeff(ncoeffarg,coeffarg); buf = next + 1; } delete [] original; @@ -1868,9 +1862,9 @@ void ReadData::dihedralcoeffs(int which) else if (which == 3) parse_coeffs(buf,"at",0,1,doffset); else if (which == 4) parse_coeffs(buf,"aat",0,1,doffset); else if (which == 5) parse_coeffs(buf,"bb13",0,1,doffset); - if (narg == 0) + if (ncoeffarg == 0) error->all(FLERR,"Unexpected empty line in DihedralCoeffs section"); - force->dihedral->coeff(narg,arg); + force->dihedral->coeff(ncoeffarg,coeffarg); buf = next + 1; } delete [] original; @@ -1894,8 +1888,8 @@ void ReadData::impropercoeffs(int which) *next = '\0'; if (which == 0) parse_coeffs(buf,nullptr,0,1,ioffset); else if (which == 1) parse_coeffs(buf,"aa",0,1,ioffset); - if (narg == 0) error->all(FLERR,"Unexpected empty line in ImproperCoeffs section"); - force->improper->coeff(narg,arg); + if (ncoeffarg == 0) error->all(FLERR,"Unexpected empty line in ImproperCoeffs section"); + force->improper->coeff(ncoeffarg,coeffarg); buf = next + 1; } delete [] original; @@ -2053,7 +2047,7 @@ void ReadData::skip_lines(bigint n) } /* ---------------------------------------------------------------------- - parse a line of coeffs into words, storing them in narg,arg + parse a line of coeffs into words, storing them in ncoeffarg,coeffarg trim anything from '#' onward word strings remain in line, are not copied if addstr != nullptr, add addstr as extra arg for class2 angle/dihedral/improper @@ -2069,33 +2063,38 @@ void ReadData::parse_coeffs(char *line, const char *addstr, char *ptr; if ((ptr = strchr(line,'#'))) *ptr = '\0'; - narg = 0; - char *word = strtok(line," \t\n\r\f"); - while (word) { - if (narg == maxarg) { - maxarg += DELTA; - arg = (char **) - memory->srealloc(arg,maxarg*sizeof(char *),"read_data:arg"); + ncoeffarg = 0; + char *word = line; + char *end = line + strlen(line)+1; + + while (word < end) { + word += strspn(word," \t\r\n\f"); + word[strcspn(word," \t\r\n\f")] = '\0'; + if (strlen(word) == 0) break; + if (ncoeffarg == maxcoeffarg) { + maxcoeffarg += DELTA; + coeffarg = (char **) + memory->srealloc(coeffarg,maxcoeffarg*sizeof(char *),"read_data:coeffarg"); } - if (addstr && narg == 1 && !islower(word[0])) arg[narg++] = (char *) addstr; - arg[narg++] = word; - if (addstr && narg == 2 && islower(word[0])) arg[narg++] = (char *) addstr; - if (dupflag && narg == 1) arg[narg++] = word; - word = strtok(nullptr," \t\n\r\f"); + if (addstr && ncoeffarg == 1 && !islower(word[0])) coeffarg[ncoeffarg++] = (char *) addstr; + coeffarg[ncoeffarg++] = word; + if (addstr && ncoeffarg == 2 && islower(word[0])) coeffarg[ncoeffarg++] = (char *) addstr; + if (dupflag && ncoeffarg == 1) coeffarg[ncoeffarg++] = word; + word += strlen(word)+1; } // to avoid segfaults on empty lines - if (narg == 0) return; + if (ncoeffarg == 0) return; if (noffset) { - int value = utils::inumeric(FLERR,arg[0],false,lmp); + int value = utils::inumeric(FLERR,coeffarg[0],false,lmp); sprintf(argoffset1,"%d",value+offset); - arg[0] = argoffset1; + coeffarg[0] = argoffset1; if (noffset == 2) { - value = utils::inumeric(FLERR,arg[1],false,lmp); + value = utils::inumeric(FLERR,coeffarg[1],false,lmp); sprintf(argoffset2,"%d",value+offset); - arg[1] = argoffset2; + coeffarg[1] = argoffset2; } } } diff --git a/src/read_data.h b/src/read_data.h index 84c098635a..68b40fc529 100644 --- a/src/read_data.h +++ b/src/read_data.h @@ -34,8 +34,8 @@ class ReadData : protected Pointers { int me,compressed; char *line,*keyword,*buffer,*style; FILE *fp; - char **arg; - int narg,maxarg; + char **coeffarg; + int ncoeffarg,maxcoeffarg; char argoffset1[8],argoffset2[8]; bigint id_offset, mol_offset; diff --git a/src/read_dump.cpp b/src/read_dump.cpp index 925760da6a..0282e2d039 100644 --- a/src/read_dump.cpp +++ b/src/read_dump.cpp @@ -64,9 +64,7 @@ ReadDump::ReadDump(LAMMPS *lmp) : Pointers(lmp) fields = nullptr; buf = nullptr; - int n = strlen("native") + 1; - readerstyle = new char[n]; - strcpy(readerstyle,"native"); + readerstyle = utils::strdup("native"); nreader = 0; readers = nullptr; @@ -182,9 +180,7 @@ void ReadDump::store_files(int nstr, char **str) // either all or none of files must have '%' wild-card for (int i = 0; i < nfile; i++) { - int n = strlen(str[i]) + 1; - files[i] = new char[n]; - strcpy(files[i],str[i]); + files[i] = utils::strdup(str[i]); if (i == 0) { if (strchr(files[i],'%')) multiproc = 1; @@ -1258,9 +1254,7 @@ int ReadDump::fields_and_keywords(int narg, char **arg) for (i = 0; i < nfield; i++) if (type == fieldtype[i]) break; if (i == nfield) error->all(FLERR,"Illegal read_dump command"); - int n = strlen(arg[iarg+2]) + 1; - fieldlabel[i] = new char[n]; - strcpy(fieldlabel[i],arg[iarg+2]); + fieldlabel[i] = utils::strdup(arg[iarg+2]); iarg += 3; } else if (strcmp(arg[iarg],"scaled") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); @@ -1277,9 +1271,7 @@ int ReadDump::fields_and_keywords(int narg, char **arg) } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); delete [] readerstyle; - int n = strlen(arg[iarg+1]) + 1; - readerstyle = new char[n]; - strcpy(readerstyle,arg[iarg+1]); + readerstyle = utils::strdup(arg[iarg+1]); iarg += 2; break; } else error->all(FLERR,"Illegal read_dump command"); diff --git a/src/region.cpp b/src/region.cpp index 2fe2d88cef..c442463d4f 100644 --- a/src/region.cpp +++ b/src/region.cpp @@ -33,13 +33,8 @@ Region::Region(LAMMPS *lmp, int /*narg*/, char **arg) : id(nullptr), style(nullptr), contact(nullptr), list(nullptr), xstr(nullptr), ystr(nullptr), zstr(nullptr), tstr(nullptr) { - int n = strlen(arg[0]) + 1; - id = new char[n]; - strcpy(id,arg[0]); - - n = strlen(arg[1]) + 1; - style = new char[n]; - strcpy(style,arg[1]); + id = utils::strdup(arg[0]); + style = utils::strdup(arg[1]); varshape = 0; xstr = ystr = zstr = tstr = nullptr; @@ -338,23 +333,17 @@ void Region::options(int narg, char **arg) if (strcmp(arg[iarg+1],"NULL") != 0) { if (strstr(arg[iarg+1],"v_") != arg[iarg+1]) error->all(FLERR,"Illegal region command"); - int n = strlen(&arg[iarg+1][2]) + 1; - xstr = new char[n]; - strcpy(xstr,&arg[iarg+1][2]); + xstr = utils::strdup(&arg[iarg+1][2]); } if (strcmp(arg[iarg+2],"NULL") != 0) { if (strstr(arg[iarg+2],"v_") != arg[iarg+2]) error->all(FLERR,"Illegal region command"); - int n = strlen(&arg[iarg+2][2]) + 1; - ystr = new char[n]; - strcpy(ystr,&arg[iarg+2][2]); + ystr = utils::strdup(&arg[iarg+2][2]); } if (strcmp(arg[iarg+3],"NULL") != 0) { if (strstr(arg[iarg+3],"v_") != arg[iarg+3]) error->all(FLERR,"Illegal region command"); - int n = strlen(&arg[iarg+3][2]) + 1; - zstr = new char[n]; - strcpy(zstr,&arg[iarg+3][2]); + zstr = utils::strdup(&arg[iarg+3][2]); } moveflag = 1; iarg += 4; @@ -363,9 +352,7 @@ void Region::options(int narg, char **arg) if (iarg+8 > narg) error->all(FLERR,"Illegal region command"); if (strstr(arg[iarg+1],"v_") != arg[iarg+1]) error->all(FLERR,"Illegal region command"); - int n = strlen(&arg[iarg+1][2]) + 1; - tstr = new char[n]; - strcpy(tstr,&arg[iarg+1][2]); + tstr = utils::strdup(&arg[iarg+1][2]); point[0] = utils::numeric(FLERR,arg[iarg+2],false,lmp); point[1] = utils::numeric(FLERR,arg[iarg+3],false,lmp); point[2] = utils::numeric(FLERR,arg[iarg+4],false,lmp); diff --git a/src/region_intersect.cpp b/src/region_intersect.cpp index fb2b6239b1..ad67dd1fe5 100644 --- a/src/region_intersect.cpp +++ b/src/region_intersect.cpp @@ -39,12 +39,9 @@ RegIntersect::RegIntersect(LAMMPS *lmp, int narg, char **arg) : list = new int[n]; nregion = 0; - int m,iregion; for (int iarg = 0; iarg < n; iarg++) { - m = strlen(arg[iarg+3]) + 1; - idsub[nregion] = new char[m]; - strcpy(idsub[nregion],arg[iarg+3]); - iregion = domain->find_region(idsub[nregion]); + idsub[nregion] = utils::strdup(arg[iarg+3]); + int iregion = domain->find_region(idsub[nregion]); if (iregion == -1) error->all(FLERR,"Region intersect region ID does not exist"); list[nregion++] = iregion; @@ -123,9 +120,8 @@ void RegIntersect::init() // re-build list of sub-regions in case other regions were deleted // error if a sub-region was deleted - int iregion; for (int ilist = 0; ilist < nregion; ilist++) { - iregion = domain->find_region(idsub[ilist]); + int iregion = domain->find_region(idsub[ilist]); if (iregion == -1) error->all(FLERR,"Region union region ID does not exist"); list[ilist] = iregion; diff --git a/src/region_union.cpp b/src/region_union.cpp index c4d38413db..144bc4828c 100644 --- a/src/region_union.cpp +++ b/src/region_union.cpp @@ -40,12 +40,9 @@ RegUnion::RegUnion(LAMMPS *lmp, int narg, char **arg) : Region(lmp, narg, arg), list = new int[n]; nregion = 0; - int m,iregion; for (int iarg = 0; iarg < n; iarg++) { - m = strlen(arg[iarg+3]) + 1; - idsub[nregion] = new char[m]; - strcpy(idsub[nregion],arg[iarg+3]); - iregion = domain->find_region(idsub[nregion]); + idsub[nregion] = utils::strdup(arg[iarg+3]); + int iregion = domain->find_region(idsub[nregion]); if (iregion == -1) error->all(FLERR,"Region union region ID does not exist"); list[nregion++] = iregion; @@ -117,9 +114,8 @@ void RegUnion::init() // re-build list of sub-regions in case other regions were deleted // error if a sub-region was deleted - int iregion; for (int ilist = 0; ilist < nregion; ilist++) { - iregion = domain->find_region(idsub[ilist]); + int iregion = domain->find_region(idsub[ilist]); if (iregion == -1) error->all(FLERR,"Region union region ID does not exist"); list[ilist] = iregion; diff --git a/src/run.cpp b/src/run.cpp index 29e42fa6bf..fedf020d9d 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -145,9 +145,7 @@ void Run::command(int narg, char **arg) commands = new char*[ncommands]; ncommands = 0; for (int i = first; i <= last; i++) { - int n = strlen(arg[i]) + 1; - commands[ncommands] = new char[n]; - strcpy(commands[ncommands],arg[i]); + commands[ncommands] = utils::strdup(arg[i]); ncommands++; } } diff --git a/src/text_file_reader.cpp b/src/text_file_reader.cpp index 19f15d8522..af27bfb16d 100644 --- a/src/text_file_reader.cpp +++ b/src/text_file_reader.cpp @@ -96,10 +96,7 @@ char *TextFileReader::next_line(int nparams) { if (ignore_comments && (ptr = strchr(line, '#'))) *ptr = '\0'; nwords = utils::count_words(line); - - if (nwords > 0) { - n = strlen(line); - } + if (nwords > 0) n = strlen(line); while (nwords == 0 || nwords < nparams) { char *ptr = fgets(&line[n], MAXLINE - n, fp); diff --git a/src/thermo.cpp b/src/thermo.cpp index 7e14fe37c0..01dd9e0750 100644 --- a/src/thermo.cpp +++ b/src/thermo.cpp @@ -84,9 +84,7 @@ Thermo::Thermo(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) { MPI_Comm_rank(world,&me); - int n = strlen(arg[0]) + 1; - style = new char[n]; - strcpy(style,arg[0]); + style = utils::strdup(arg[0]); // set thermo_modify defaults @@ -456,9 +454,7 @@ void Thermo::modify_params(int narg, char **arg) if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command"); if (index_temp < 0) error->all(FLERR,"Thermo style does not use temp"); delete [] id_compute[index_temp]; - int n = strlen(arg[iarg+1]) + 1; - id_compute[index_temp] = new char[n]; - strcpy(id_compute[index_temp],arg[iarg+1]); + id_compute[index_temp] = utils::strdup(arg[iarg+1]); int icompute = modify->find_compute(arg[iarg+1]); if (icompute < 0) @@ -496,15 +492,11 @@ void Thermo::modify_params(int narg, char **arg) if (index_press_scalar >= 0) { delete [] id_compute[index_press_scalar]; - int n = strlen(arg[iarg+1]) + 1; - id_compute[index_press_scalar] = new char[n]; - strcpy(id_compute[index_press_scalar],arg[iarg+1]); + id_compute[index_press_scalar] = utils::strdup(arg[iarg+1]); } if (index_press_vector >= 0) { delete [] id_compute[index_press_vector]; - int n = strlen(arg[iarg+1]) + 1; - id_compute[index_press_vector] = new char[n]; - strcpy(id_compute[index_press_vector],arg[iarg+1]); + id_compute[index_press_vector] = utils::strdup(arg[iarg+1]); } int icompute = modify->find_compute(arg[iarg+1]); @@ -579,41 +571,32 @@ void Thermo::modify_params(int narg, char **arg) if (strcmp(arg[iarg+1],"line") == 0) { delete [] format_line_user; - int n = strlen(arg[iarg+2]) + 1; - format_line_user = new char[n]; - strcpy(format_line_user,arg[iarg+2]); + format_line_user = utils::strdup(arg[iarg+2]); } else if (strcmp(arg[iarg+1],"int") == 0) { if (format_int_user) delete [] format_int_user; - int n = strlen(arg[iarg+2]) + 1; - format_int_user = new char[n]; - strcpy(format_int_user,arg[iarg+2]); + format_int_user = utils::strdup(arg[iarg+2]); if (format_bigint_user) delete [] format_bigint_user; - n = strlen(format_int_user) + 8; - format_bigint_user = new char[n]; // replace "d" in format_int_user with bigint format specifier - // use of &str[1] removes leading '%' from BIGINT_FORMAT string char *ptr = strchr(format_int_user,'d'); if (ptr == nullptr) error->all(FLERR, "Thermo_modify int format does not contain d character"); - char str[8]; - sprintf(str,"%s",BIGINT_FORMAT); + *ptr = '\0'; - sprintf(format_bigint_user,"%s%s%s",format_int_user,&str[1],ptr+1); + std::string fnew = fmt::format("{}{}{}",format_int_user, + std::string(BIGINT_FORMAT).substr(1), + ptr+1); + format_bigint_user = utils::strdup(fnew); *ptr = 'd'; } else if (strcmp(arg[iarg+1],"float") == 0) { if (format_float_user) delete [] format_float_user; - int n = strlen(arg[iarg+2]) + 1; - format_float_user = new char[n]; - strcpy(format_float_user,arg[iarg+2]); + format_float_user = utils::strdup(arg[iarg+2]); } else { int i = utils::inumeric(FLERR,arg[iarg+1],false,lmp) - 1; if (i < 0 || i >= nfield_initial+1) error->all(FLERR,"Illegal thermo_modify command"); if (format_column_user[i]) delete [] format_column_user[i]; - int n = strlen(arg[iarg+2]) + 1; - format_column_user[i] = new char[n]; - strcpy(format_column_user[i],arg[iarg+2]); + format_column_user[i] = utils::strdup(arg[iarg+2]); } iarg += 3; @@ -985,10 +968,8 @@ void Thermo::parse_fields(char *str) void Thermo::addfield(const char *key, FnPtr func, int typeflag) { - int n = strlen(key) + 1; delete[] keyword[nfield]; - keyword[nfield] = new char[n]; - strcpy(keyword[nfield],key); + keyword[nfield] = utils::strdup(key); vfunc[nfield] = func; vtype[nfield] = typeflag; nfield++; @@ -1008,9 +989,7 @@ int Thermo::add_compute(const char *id, int which) which == compute_which[icompute]) break; if (icompute < ncompute) return icompute; - int n = strlen(id) + 1; - id_compute[ncompute] = new char[n]; - strcpy(id_compute[ncompute],id); + id_compute[ncompute] = utils::strdup(id); compute_which[ncompute] = which; ncompute++; return ncompute-1; @@ -1022,9 +1001,7 @@ int Thermo::add_compute(const char *id, int which) int Thermo::add_fix(const char *id) { - int n = strlen(id) + 1; - id_fix[nfix] = new char[n]; - strcpy(id_fix[nfix],id); + id_fix[nfix] = utils::strdup(id); nfix++; return nfix-1; } @@ -1035,9 +1012,7 @@ int Thermo::add_fix(const char *id) int Thermo::add_variable(const char *id) { - int n = strlen(id) + 1; - id_variable[nvariable] = new char[n]; - strcpy(id_variable[nvariable],id); + id_variable[nvariable] = utils::strdup(id); nvariable++; return nvariable-1; } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 2cc0de72e1..18ed64e0ac 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -200,7 +200,7 @@ std::string ValueTokenizer::next_string() { if (has_next()) { std::string value = tokens.next(); return value; - } + } throw TokenizerException("Not enough tokens",""); return ""; } @@ -216,7 +216,7 @@ int ValueTokenizer::next_int() { } int value = atoi(current.c_str()); return value; - } + } throw TokenizerException("Not enough tokens",""); return 0; } @@ -232,7 +232,7 @@ bigint ValueTokenizer::next_bigint() { } bigint value = ATOBIGINT(current.c_str()); return value; - } + } throw TokenizerException("Not enough tokens",""); return 0; } @@ -248,7 +248,7 @@ tagint ValueTokenizer::next_tagint() { } tagint value = ATOTAGINT(current.c_str()); return value; - } + } throw TokenizerException("Not enough tokens",""); return 0; } @@ -264,7 +264,7 @@ double ValueTokenizer::next_double() { } double value = atof(current.c_str()); return value; - } + } throw TokenizerException("Not enough tokens",""); return 0.0; } diff --git a/src/update.cpp b/src/update.cpp index 7c4b6b888e..1f78e48bb3 100644 --- a/src/update.cpp +++ b/src/update.cpp @@ -301,9 +301,7 @@ void Update::set_units(const char *style) } else error->all(FLERR,"Illegal units command"); delete [] unit_style; - int n = strlen(style) + 1; - unit_style = new char[n]; - strcpy(unit_style,style); + unit_style = utils::strdup(style); // check if timestep was changed from default value if (!dt_default && (comm->me == 0)) { diff --git a/src/utils.cpp b/src/utils.cpp index 4b9cc8a5f6..2cb57cba5b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -418,13 +418,13 @@ void utils::bounds(const char *file, int line, const std::string &str, error->all(file,line,fmt::format("Invalid range string: {}",str)); if (nlo < nmin) - error->all(file,line,fmt::format("Numeric index {} is out of bounds" + error->all(file,line,fmt::format("Numeric index {} is out of bounds " "({}-{})",nlo,nmin,nmax)); else if (nhi > nmax) - error->all(file,line,fmt::format("Numeric index {} is out of bounds" + error->all(file,line,fmt::format("Numeric index {} is out of bounds " "({}-{})",nhi,nmin,nmax)); else if (nlo > nhi) - error->all(file,line,fmt::format("Numeric index {} is out of bounds" + error->all(file,line,fmt::format("Numeric index {} is out of bounds " "({}-{})",nlo,nmin,nhi)); } } @@ -443,16 +443,15 @@ template void utils::bounds<>(const char *, int, const std::string &, int utils::expand_args(const char *file, int line, int narg, char **arg, int mode, char **&earg, LAMMPS *lmp) { - int n,iarg,index,nlo,nhi,nmax,expandflag,icompute,ifix; - char *ptr1,*ptr2,*str; + int iarg; - ptr1 = nullptr; + char *ptr = nullptr; for (iarg = 0; iarg < narg; iarg++) { - ptr1 = strchr(arg[iarg],'*'); - if (ptr1) break; + ptr = strchr(arg[iarg],'*'); + if (ptr) break; } - if (!ptr1) { + if (!ptr) { earg = arg; return narg; } @@ -462,101 +461,96 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int maxarg = narg-iarg; earg = (char **) lmp->memory->smalloc(maxarg*sizeof(char *),"input:earg"); - int newarg = 0; + int newarg = 0, expandflag, nlo, nhi, nmax; + std::string id, wc, tail; + for (iarg = 0; iarg < narg; iarg++) { - expandflag = 0; + std::string word(arg[iarg]); - if (strncmp(arg[iarg],"c_",2) == 0 || - strncmp(arg[iarg],"f_",2) == 0) { + // only match compute/fix reference with a '*' wildcard + // number range in the first pair of square brackets - ptr1 = strchr(&arg[iarg][2],'['); - if (ptr1) { - ptr2 = strchr(ptr1,']'); - if (ptr2) { - *ptr2 = '\0'; - if (strchr(ptr1,'*')) { - if (arg[iarg][0] == 'c') { - *ptr1 = '\0'; - icompute = lmp->modify->find_compute(&arg[iarg][2]); - *ptr1 = '['; + if (strmatch(word,"^[cf]_\\w+\\[\\d*\\*\\d*\\]")) { - // check for global vector/array, peratom array, local array + // split off the compute/fix ID, the wildcard and trailing text + size_t first = word.find("["); + size_t second = word.find("]",first+1); + id = word.substr(2,first-2); + wc = word.substr(first+1,second-first-1); + tail = word.substr(second+1); - if (icompute >= 0) { - if (mode == 0 && lmp->modify->compute[icompute]->vector_flag) { - nmax = lmp->modify->compute[icompute]->size_vector; - expandflag = 1; - } else if (mode == 1 && lmp->modify->compute[icompute]->array_flag) { - nmax = lmp->modify->compute[icompute]->size_array_cols; - expandflag = 1; - } else if (lmp->modify->compute[icompute]->peratom_flag && - lmp->modify->compute[icompute]->size_peratom_cols) { - nmax = lmp->modify->compute[icompute]->size_peratom_cols; - expandflag = 1; - } else if (lmp->modify->compute[icompute]->local_flag && - lmp->modify->compute[icompute]->size_local_cols) { - nmax = lmp->modify->compute[icompute]->size_local_cols; - expandflag = 1; - } - } - } else if (arg[iarg][0] == 'f') { - *ptr1 = '\0'; - ifix = lmp->modify->find_fix(&arg[iarg][2]); - *ptr1 = '['; + if (word[0] == 'c') { + int icompute = lmp->modify->find_compute(id); - // check for global vector/array, peratom array, local array + // check for global vector/array, peratom array, local array - if (ifix >= 0) { - if (mode == 0 && lmp->modify->fix[ifix]->vector_flag) { - nmax = lmp->modify->fix[ifix]->size_vector; - expandflag = 1; - } else if (mode == 1 && lmp->modify->fix[ifix]->array_flag) { - nmax = lmp->modify->fix[ifix]->size_array_cols; - expandflag = 1; - } else if (lmp->modify->fix[ifix]->peratom_flag && - lmp->modify->fix[ifix]->size_peratom_cols) { - nmax = lmp->modify->fix[ifix]->size_peratom_cols; - expandflag = 1; - } else if (lmp->modify->fix[ifix]->local_flag && - lmp->modify->fix[ifix]->size_local_cols) { - nmax = lmp->modify->fix[ifix]->size_local_cols; - expandflag = 1; - } - } - } + if (icompute >= 0) { + Compute *compute = lmp->modify->compute[icompute]; + if (mode == 0 && compute->vector_flag) { + nmax = compute->size_vector; + expandflag = 1; + } else if (mode == 1 && compute->array_flag) { + nmax = compute->size_array_cols; + expandflag = 1; + } else if (compute->peratom_flag && compute->size_peratom_cols) { + nmax = compute->size_peratom_cols; + expandflag = 1; + } else if (compute->local_flag && compute->size_local_cols) { + nmax = compute->size_local_cols; + expandflag = 1; + } + } + } else if (word[0] == 'f') { + int ifix = lmp->modify->find_fix(id); + + // check for global vector/array, peratom array, local array + + if (ifix >= 0) { + Fix *fix = lmp->modify->fix[ifix]; + + if (mode == 0 && fix->vector_flag) { + nmax = fix->size_vector; + expandflag = 1; + } else if (mode == 1 && fix->array_flag) { + nmax = fix->size_array_cols; + expandflag = 1; + } else if (fix->peratom_flag && fix->size_peratom_cols) { + nmax = fix->size_peratom_cols; + expandflag = 1; + } else if (fix->local_flag && fix->size_local_cols) { + nmax = fix->size_local_cols; + expandflag = 1; } - *ptr2 = ']'; } } } if (expandflag) { - *ptr2 = '\0'; - bounds(file,line,ptr1+1,1,nmax,nlo,nhi,lmp->error); - *ptr2 = ']'; + + // expand wild card string to nlo/nhi numbers + utils::bounds(file,line,wc,1,nmax,nlo,nhi,lmp->error); + if (newarg+nhi-nlo+1 > maxarg) { maxarg += nhi-nlo+1; earg = (char **) lmp->memory->srealloc(earg,maxarg*sizeof(char *),"input:earg"); } - for (index = nlo; index <= nhi; index++) { - n = strlen(arg[iarg]) + 16; // 16 = space for large inserted integer - str = earg[newarg] = new char[n]; - strncpy(str,arg[iarg],ptr1+1-arg[iarg]); - sprintf(&str[ptr1+1-arg[iarg]],"%d",index); - strcat(str,ptr2); + + for (int index = nlo; index <= nhi; index++) { + // assemble and duplicate expanded string + earg[newarg] = utils::strdup(fmt::format("{}_{}[{}]{}",word[0], + id,index,tail)); newarg++; } } else { + // no expansion: duplicate original string if (newarg == maxarg) { maxarg++; earg = (char **) lmp->memory->srealloc(earg,maxarg*sizeof(char *),"input:earg"); } - n = strlen(arg[iarg]) + 1; - earg[newarg] = new char[n]; - strcpy(earg[newarg],arg[iarg]); + earg[newarg] = utils::strdup(word); newarg++; } } diff --git a/src/variable.cpp b/src/variable.cpp index 556633c4e0..1af4a4728a 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -31,6 +31,7 @@ #include "random_mars.h" #include "region.h" #include "thermo.h" +#include "tokenizer.h" #include "universe.h" #include "update.h" @@ -185,9 +186,7 @@ void Variable::set(int narg, char **arg) nlast = utils::inumeric(FLERR,arg[2],false,lmp); if (nlast <= 0) error->all(FLERR,"Illegal variable command"); if (narg == 4 && strcmp(arg[3],"pad") == 0) { - char digits[12]; - sprintf(digits,"%d",nlast); - pad[nvar] = strlen(digits); + pad[nvar] = fmt::format("{}",nlast).size(); } else pad[nvar] = 0; } else if (narg == 4 || (narg == 5 && strcmp(arg[4],"pad") == 0)) { nfirst = utils::inumeric(FLERR,arg[2],false,lmp); @@ -195,9 +194,7 @@ void Variable::set(int narg, char **arg) if (nfirst > nlast || nlast < 0) error->all(FLERR,"Illegal variable command"); if (narg == 5 && strcmp(arg[4],"pad") == 0) { - char digits[12]; - sprintf(digits,"%d",nlast); - pad[nvar] = strlen(digits); + pad[nvar] = fmt::format("{}",nlast).size(); } else pad[nvar] = 0; } else error->all(FLERR,"Illegal variable command"); num[nvar] = nlast; @@ -5112,17 +5109,17 @@ int VarReader::read_scalar(char *str) if (me == 0) { while (1) { - if (fgets(str,MAXLINE,fp) == nullptr) n = 0; - else n = strlen(str); - if (n == 0) break; // end of file - str[n-1] = '\0'; // strip newline - if ((ptr = strchr(str,'#'))) *ptr = '\0'; // strip comment - if (strtok(str," \t\n\r\f") == nullptr) continue; // skip if blank - n = strlen(str) + 1; + ptr = fgets(str,MAXLINE,fp); + if (!ptr) { n=0; break; } // end of file + ptr[strcspn(ptr,"#")] = '\0'; // strip comment + ptr += strspn(ptr," \t\n\r\f"); // strip leading whitespace + ptr[strcspn(ptr," \t\n\r\f")] = '\0'; // strip trailing whitespace + n = strlen(ptr) + 1; + if (n == 1) continue; // skip if blank line break; } + memmove(str,ptr,n); // move trimmed string back } - MPI_Bcast(&n,1,MPI_INT,0,world); if (n == 0) return 1; MPI_Bcast(str,n,MPI_CHAR,0,world); @@ -5155,20 +5152,20 @@ int VarReader::read_peratom() char str[MAXLINE]; if (me == 0) { while (1) { - if (fgets(str,MAXLINE,fp) == nullptr) n = 0; - else n = strlen(str); - if (n == 0) break; // end of file - str[n-1] = '\0'; // strip newline - if ((ptr = strchr(str,'#'))) *ptr = '\0'; // strip comment - if (strtok(str," \t\n\r\f") == nullptr) continue; // skip if blank - n = strlen(str) + 1; + ptr = fgets(str,MAXLINE,fp); + if (!ptr) { n=0; break; } // end of file + ptr[strcspn(ptr,"#")] = '\0'; // strip comment + ptr += strspn(ptr," \t\n\r\f"); // strip leading whitespace + ptr[strcspn(ptr," \t\n\r\f")] = '\0'; // strip trailing whitespace + n = strlen(ptr) + 1; + if (n == 1) continue; // skip if blank line break; } + memmove(str,ptr,n); // move trimmed string back } MPI_Bcast(&n,1,MPI_INT,0,world); if (n == 0) return 1; - MPI_Bcast(str,n,MPI_CHAR,0,world); bigint nlines = utils::bnumeric(FLERR,str,false,lmp); tagint map_tag_max = atom->map_tag_max; @@ -5183,9 +5180,17 @@ int VarReader::read_peratom() for (i = 0; i < nchunk; i++) { next = strchr(buf,'\n'); *next = '\0'; - int rv = sscanf(buf,TAGINT_FORMAT " %lg",&tag,&value); - if (tag <= 0 || tag > map_tag_max || rv != 2) - error->one(FLERR,"Invalid atom ID in variable file"); + try { + ValueTokenizer words(buf); + tag = words.next_bigint(); + value = words.next_double(); + } catch (TokenizerException &e) { + error->all(FLERR,fmt::format("Invalid atomfile line '{}': {}", + buf,e.what())); + } + if ((tag <= 0) || (tag > map_tag_max)) + error->all(FLERR,fmt::format("Invalid atom ID {} in variable " + "file", tag)); if ((m = atom->map(tag)) >= 0) vstore[m] = value; buf = next + 1; } diff --git a/src/write_coeff.cpp b/src/write_coeff.cpp index 8f1f6140ed..485bc3b29b 100644 --- a/src/write_coeff.cpp +++ b/src/write_coeff.cpp @@ -43,11 +43,7 @@ void WriteCoeff::command(int narg, char **arg) if (narg != 1) error->all(FLERR,"Illegal write_coeff command"); - int n = strlen(arg[0]) + 5; - char *file = new char[n]; - - strcpy(file,"tmp."); - strcat(file,arg[0]); + char *file = utils::strdup(fmt::format("tmp.{}",arg[0])); // initialize relevant styles lmp->init(); @@ -114,7 +110,7 @@ void WriteCoeff::command(int narg, char **arg) const char *section = (const char *)""; fputs(str,two); // style utils::sfgets(FLERR,str,256,one,file,error); // coeff - n = strlen(str); + int n = strlen(str); strcpy(coeff,str); coeff[n-1] = '\0'; utils::sfgets(FLERR,str,256,one,file,error); diff --git a/unittest/commands/test_simple_commands.cpp b/unittest/commands/test_simple_commands.cpp index 4fce58c668..5fdc1e912b 100644 --- a/unittest/commands/test_simple_commands.cpp +++ b/unittest/commands/test_simple_commands.cpp @@ -192,6 +192,29 @@ TEST_F(SimpleCommandsTest, Newton) ASSERT_EQ(lmp->force->newton_bond, 1); } +TEST_F(SimpleCommandsTest, Partition) +{ + if (!verbose) ::testing::internal::CaptureStdout(); + lmp->input->one("echo none"); + if (!verbose) ::testing::internal::GetCapturedStdout(); + TEST_FAILURE(".*ERROR: Illegal partition command .*", + lmp->input->one("partition xxx 1 echo none");); + TEST_FAILURE(".*ERROR: Numeric index 2 is out of bounds.*", + lmp->input->one("partition yes 2 echo none");); + + ::testing::internal::CaptureStdout(); + lmp->input->one("partition yes 1 print 'test'"); + auto text = ::testing::internal::GetCapturedStdout(); + if (verbose) std::cout << text; + ASSERT_THAT(text, StrEq("test\n")); + + ::testing::internal::CaptureStdout(); + lmp->input->one("partition no 1 print 'test'"); + text = ::testing::internal::GetCapturedStdout(); + if (verbose) std::cout << text; + ASSERT_THAT(text, StrEq("")); +} + TEST_F(SimpleCommandsTest, Quit) { ::testing::internal::CaptureStdout(); diff --git a/unittest/utils/test_tokenizer.cpp b/unittest/utils/test_tokenizer.cpp index 74eeaac832..de7472599c 100644 --- a/unittest/utils/test_tokenizer.cpp +++ b/unittest/utils/test_tokenizer.cpp @@ -102,7 +102,7 @@ TEST(Tokenizer, default_separators) ASSERT_EQ(t.count(), 2); } -TEST(Tokenizer, as_vector) +TEST(Tokenizer, as_vector1) { Tokenizer t(" \r\n test \t word \f"); std::vector list = t.as_vector(); @@ -110,6 +110,29 @@ TEST(Tokenizer, as_vector) ASSERT_THAT(list[1], Eq("word")); } +TEST(Tokenizer, as_vector2) +{ + auto list = Tokenizer("a\\b\\c","\\").as_vector(); + ASSERT_THAT(list[0], Eq("a")); + ASSERT_THAT(list[1], Eq("b")); + ASSERT_THAT(list[2], Eq("c")); + ASSERT_EQ(list.size(), 3); +} + +TEST(Tokenizer, as_vector3) +{ + auto list = Tokenizer ("a\\","\\").as_vector(); + ASSERT_THAT(list[0], Eq("a")); + ASSERT_EQ(list.size(), 1); +} + +TEST(Tokenizer, as_vector4) +{ + auto list = Tokenizer ("\\a","\\").as_vector(); + ASSERT_THAT(list[0], Eq("a")); + ASSERT_EQ(list.size(), 1); +} + TEST(ValueTokenizer, empty_string) { ValueTokenizer values(""); @@ -170,3 +193,31 @@ TEST(ValueTokenizer, not_contains) ValueTokenizer values("test word"); ASSERT_FALSE(values.contains("test2")); } + +TEST(ValueTokenizer, missing_int) +{ + ValueTokenizer values("10"); + ASSERT_EQ(values.next_int(), 10); + ASSERT_THROW(values.next_int(), TokenizerException); +} + +TEST(ValueTokenizer, missing_tagint) +{ + ValueTokenizer values("42"); + ASSERT_EQ(values.next_tagint(), 42); + ASSERT_THROW(values.next_tagint(), TokenizerException); +} + +TEST(ValueTokenizer, missing_bigint) +{ + ValueTokenizer values("42"); + ASSERT_EQ(values.next_bigint(), 42); + ASSERT_THROW(values.next_bigint(), TokenizerException); +} + +TEST(ValueTokenizer, missing_double) +{ + ValueTokenizer values("3.14"); + ASSERT_DOUBLE_EQ(values.next_double(), 3.14); + ASSERT_THROW(values.next_double(), TokenizerException); +}