From af9321c4d84e7fb663b4dc9497434f97666ca334 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 11 Mar 2021 06:46:14 -0500 Subject: [PATCH 01/31] correct output --- src/utils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index 4b9cc8a5f6..d34e5794ab 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)); } } From 423772b1fae1c985c6a8d3f5a4a6db69e3b221f2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 11 Mar 2021 06:46:40 -0500 Subject: [PATCH 02/31] avoid strtok() when processing the "partition" command --- src/input.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) 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); } } From 832574066399cd9e38c91b9d1e9f8dd05ec96bd2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 11 Mar 2021 06:46:53 -0500 Subject: [PATCH 03/31] add test for partition command --- unittest/commands/test_simple_commands.cpp | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) 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(); From 882b221a1778118c4fd5b8d166f84d2648f5b5ae Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 13 Mar 2021 17:35:49 -0500 Subject: [PATCH 04/31] rename arg,narg,maxarg to avoid shadowing in command() function --- src/read_data.cpp | 30 +++++++++++++++--------------- src/read_data.h | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/read_data.cpp b/src/read_data.cpp index e8eb90dcb1..98d47d5d93 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]; @@ -1760,9 +1760,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 +1787,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 +1812,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 +1839,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 +1868,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 +1894,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; 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; From e6def05178b00a65277c3552701309c9bd13826f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 13 Mar 2021 17:36:22 -0500 Subject: [PATCH 05/31] refactor parse_coeffs() function to avoid calling strtok() --- src/read_data.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/read_data.cpp b/src/read_data.cpp index 98d47d5d93..4f7cf544a9 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -2053,7 +2053,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 +2069,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; } } } From 9c13361a17706508be371df66b3fa6acb149282b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 13 Mar 2021 18:33:42 -0500 Subject: [PATCH 06/31] avoid calling strtok() in group command --- src/group.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/group.cpp b/src/group.cpp index e523fd9cf2..01e5a83060 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -303,18 +303,21 @@ void Group::assign(int narg, char **arg) else if (category == MOLECULE) tattribute = atom->molecule; else if (category == ID) tattribute = atom->tag; - char *ptr; + char *ptr,*end; tagint start,stop,delta; for (int iarg = 2; iarg < narg; iarg++) { delta = 1; - if (strchr(arg[iarg],':')) { - ptr = strtok(arg[iarg],":"); + ptr = arg[iarg]; + end = ptr + strlen(ptr)+1; + if (strchr(ptr,':')) { + ptr[strcspn(ptr,":")] = '\0'; start = utils::tnumeric(FLERR,ptr,false,lmp); - ptr = strtok(nullptr,":"); + ptr += strlen(ptr)+1; + if (strchr(ptr,':')) ptr[strcspn(ptr,":")] = '\0'; stop = utils::tnumeric(FLERR,ptr,false,lmp); - ptr = strtok(nullptr,":"); - if (ptr) delta = utils::tnumeric(FLERR,ptr,false,lmp); + ptr += strlen(ptr)+1; + if (ptr < end) delta = utils::tnumeric(FLERR,ptr,false,lmp); } else { start = stop = utils::tnumeric(FLERR,arg[iarg],false,lmp); } From 3183c4bdb7c18fda8ab9d2098355e73ddd7c522c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 13 Mar 2021 19:12:43 -0500 Subject: [PATCH 07/31] avoid calling strtok() when reading per-atom data in data files --- src/atom.cpp | 71 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/src/atom.cpp b/src/atom.cpp index fe260309e2..959bf39ddb 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -1114,13 +1114,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 +1217,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 +1572,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 +1617,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 +1630,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 +1652,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; + } } } From 11386097c63916b81db20fb1d6527eac3c9dcc29 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 13 Mar 2021 21:00:09 -0500 Subject: [PATCH 08/31] avoid strtok() when reading variables from file --- src/variable.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/variable.cpp b/src/variable.cpp index 556633c4e0..5d23b4d1b5 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -5117,8 +5117,10 @@ int VarReader::read_scalar(char *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 + str += strspn(" \t\n\r\f"); // strip whitespace + str[strcspn(str," \t\n\r\f")] = '\0'; n = strlen(str) + 1; + if (n == 1) continue; // skip if blank break; } } @@ -5160,8 +5162,10 @@ int VarReader::read_peratom() 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 + str += strspn(" \t\n\r\f"); // strip whitespace + str[strcspn(str," \t\n\r\f")] = '\0'; n = strlen(str) + 1; + if (n == 1) continue; // skip if blank break; } } From 14abdade03587462060c03e0873cd2f9ca92c5b4 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 14 Mar 2021 10:44:27 -0400 Subject: [PATCH 09/31] ValueTokenizer will throw a "Not enough tokens" exception, if trying to get the next value without one present --- src/tokenizer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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; } From 194a551590dffbc4e1c4db8eb4d2883143e98181 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 14 Mar 2021 10:45:07 -0400 Subject: [PATCH 10/31] complete refactor of file/atomfile variable parsing code --- src/variable.cpp | 51 ++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/variable.cpp b/src/variable.cpp index 5d23b4d1b5..79543f9a71 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" @@ -5112,19 +5113,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 - str += strspn(" \t\n\r\f"); // strip whitespace - str[strcspn(str," \t\n\r\f")] = '\0'; - n = strlen(str) + 1; - if (n == 1) continue; // skip if blank + 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); @@ -5157,22 +5156,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 - str += strspn(" \t\n\r\f"); // strip whitespace - str[strcspn(str," \t\n\r\f")] = '\0'; - n = strlen(str) + 1; - if (n == 1) continue; // skip if blank + 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; @@ -5187,9 +5184,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; } From 3642dcfedbe8cecd884e451a718d5d5723325341 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 14 Mar 2021 15:35:12 -0400 Subject: [PATCH 11/31] use ValueTokenizer for parsing fix property/atom sections of data files --- src/fix_property_atom.cpp | 73 ++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/src/fix_property_atom.cpp b/src/fix_property_atom.cpp index f18888bbfc..3210211c44 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; From a6e6f43d5534d8f305e896b0a3a4e22b26ef9e98 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 14 Mar 2021 15:36:09 -0400 Subject: [PATCH 12/31] write a comment to the custom data file section with the column assignment --- src/fix_property_atom.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/fix_property_atom.cpp b/src/fix_property_atom.cpp index 3210211c44..56add7a0d1 100644 --- a/src/fix_property_atom.cpp +++ b/src/fix_property_atom.cpp @@ -327,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 ------------------------------------------------------------------------- */ @@ -336,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); + } } /* ---------------------------------------------------------------------- From 4c17217ad21fe9f5966a78ba641fc5bf444aa3ce Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 14 Mar 2021 17:28:03 -0400 Subject: [PATCH 13/31] add unit tests for the exceptions thrown by ValueTokenizer when data is missing --- unittest/utils/test_tokenizer.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/unittest/utils/test_tokenizer.cpp b/unittest/utils/test_tokenizer.cpp index 74eeaac832..a7cf33f8d3 100644 --- a/unittest/utils/test_tokenizer.cpp +++ b/unittest/utils/test_tokenizer.cpp @@ -170,3 +170,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); +} From 11ff1fecf931f4cd2552708ab579fcec86e4904b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 14 Mar 2021 19:10:44 -0400 Subject: [PATCH 14/31] use ValueTokenizer to parse group range selector string with strict syntax check --- src/group.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/group.cpp b/src/group.cpp index 01e5a83060..08b037f51a 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 @@ -303,23 +304,24 @@ void Group::assign(int narg, char **arg) else if (category == MOLECULE) tattribute = atom->molecule; else if (category == ID) tattribute = atom->tag; - char *ptr,*end; tagint start,stop,delta; for (int iarg = 2; iarg < narg; iarg++) { delta = 1; - ptr = arg[iarg]; - end = ptr + strlen(ptr)+1; - if (strchr(ptr,':')) { - ptr[strcspn(ptr,":")] = '\0'; - start = utils::tnumeric(FLERR,ptr,false,lmp); - ptr += strlen(ptr)+1; - if (strchr(ptr,':')) ptr[strcspn(ptr,":")] = '\0'; - stop = utils::tnumeric(FLERR,ptr,false,lmp); - ptr += strlen(ptr)+1; - if (ptr < end) 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+$")) { + start = stop; + } 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"); From b13e5fa23400bd61a44b931be2a9664ced38c2b2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 09:36:49 -0400 Subject: [PATCH 15/31] simplify using std::string and utils::strdup(); get rid of strtok() --- src/dump_atom.cpp | 15 +++--------- src/dump_local.cpp | 61 ++++++++++++++++------------------------------ 2 files changed, 25 insertions(+), 51 deletions(-) diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp index effb7c7ed3..77f9455f15 100644 --- a/src/dump_atom.cpp +++ b/src/dump_atom.cpp @@ -47,20 +47,13 @@ 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"); + else format = utils::strdup(TAGINT_FORMAT " %d %g %g %g %d %d %d"); } // setup boundary string diff --git a/src/dump_local.cpp b/src/dump_local.cpp index 58a047cf97..00879c33d5 100644 --- a/src/dump_local.cpp +++ b/src/dump_local.cpp @@ -103,21 +103,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 +159,29 @@ 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] == INT && format_int_user) + vformat[i] = utils::strdup(std::string(format_int_user) + " "); + else if (vtype[i] == DOUBLE && format_float_user) + vformat[i] = utils::strdup(std::string(format_float_user) + " "); + else vformat[i] = utils::strdup(word + " "); } // setup boundary string @@ -241,9 +224,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; From ffb86eb2abce2091118c56b914fb5df5c3b9d307 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 11:27:27 -0400 Subject: [PATCH 16/31] fix bug --- src/dump_atom.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp index 77f9455f15..ab043e67c8 100644 --- a/src/dump_atom.cpp +++ b/src/dump_atom.cpp @@ -51,9 +51,8 @@ void DumpAtom::init_style() if (format_line_user) { format = utils::strdup(std::string(format_line_user) + "\n"); } else { - char *str; - if (image_flag == 0) format = utils::strdup(TAGINT_FORMAT " %d %g %g %g"); - else format = utils::strdup(TAGINT_FORMAT " %d %g %g %g %d %d %d"); + 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 From 23e4078b4e96b80f8b285c06b103c574fdf3bdaa Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 11:27:57 -0400 Subject: [PATCH 17/31] use enumerator constants from base class --- src/dump_local.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/dump_local.cpp b/src/dump_local.cpp index 00879c33d5..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; } @@ -177,11 +175,12 @@ void DumpLocal::init_style() if (format_column_user[i]) vformat[i] = utils::strdup(std::string(format_column_user[i]) + " "); - else if (vtype[i] == INT && format_int_user) + else if (vtype[i] == Dump::INT && format_int_user) vformat[i] = utils::strdup(std::string(format_int_user) + " "); - else if (vtype[i] == DOUBLE && format_float_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 @@ -334,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]); @@ -369,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++; } @@ -389,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()) { From dbf7b9c24ae07fc431eda8ede20fe97a7616ae95 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 11:28:25 -0400 Subject: [PATCH 18/31] simplify and get rid of strtok() --- src/dump_custom.cpp | 83 ++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 46 deletions(-) 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 From 63110fd588d1b8e1348fb4591e604ed4be085e20 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 12:02:38 -0400 Subject: [PATCH 19/31] replace use of strtok() with Tokenizer class --- src/dump_image.cpp | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) 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; } From a6a2879807254e1fd0efd274a276114eea57f72e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 12:02:58 -0400 Subject: [PATCH 20/31] add a few more tokenizer test cases for added use cases. --- unittest/utils/test_tokenizer.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/unittest/utils/test_tokenizer.cpp b/unittest/utils/test_tokenizer.cpp index a7cf33f8d3..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(""); From ece243320865050b01571be244ddb046f9662dd2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 15:31:25 -0400 Subject: [PATCH 21/31] use utils::strdup() for duplicating strings --- src/atom.cpp | 27 +++++++-------------------- src/atom_vec.cpp | 7 ++----- src/atom_vec_hybrid.cpp | 10 +++------- src/body.cpp | 4 +--- src/comm.cpp | 23 +++++++---------------- src/utils.cpp | 4 +--- 6 files changed, 21 insertions(+), 54 deletions(-) diff --git a/src/atom.cpp b/src/atom.cpp index 959bf39ddb..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; @@ -2427,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"); @@ -2438,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/utils.cpp b/src/utils.cpp index d34e5794ab..66bc053542 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -554,9 +554,7 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, 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(arg[iarg]); newarg++; } } From f835d5e69e498f50839f150cc93e433380302a33 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 20:50:26 -0400 Subject: [PATCH 22/31] refactor utils::expand_args() --- src/utils.cpp | 140 ++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 72 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index 66bc053542..2cb57cba5b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -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,99 +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"); } - earg[newarg] = utils::strdup(arg[iarg]); + earg[newarg] = utils::strdup(word); newarg++; } } From 154ae864696284638d09d6f982fec64d4fca00ca Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 21:42:43 -0400 Subject: [PATCH 23/31] fix bug --- src/group.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/group.cpp b/src/group.cpp index 08b037f51a..3ed2f15281 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -312,7 +312,7 @@ void Group::assign(int narg, char **arg) ValueTokenizer values(arg[iarg],":"); start = values.next_tagint(); if (utils::strmatch(arg[iarg],"^\\d+$")) { - start = stop; + stop = start; } else if (utils::strmatch(arg[iarg],"^\\d+:\\d+$")) { stop = values.next_tagint(); } else if (utils::strmatch(arg[iarg],"^\\d+:\\d+:\\d+$")) { From 68b6296f90c4687c423958006aa7c5f679665239 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 15 Mar 2021 21:53:27 -0400 Subject: [PATCH 24/31] accept negative numbers for group definition by id --- src/group.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/group.cpp b/src/group.cpp index 3ed2f15281..844c1d92e5 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -311,11 +311,11 @@ void Group::assign(int narg, char **arg) try { ValueTokenizer values(arg[iarg],":"); start = values.next_tagint(); - if (utils::strmatch(arg[iarg],"^\\d+$")) { + if (utils::strmatch(arg[iarg],"^-?\\d+$")) { stop = start; - } else if (utils::strmatch(arg[iarg],"^\\d+:\\d+$")) { + } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+$")) { stop = values.next_tagint(); - } else if (utils::strmatch(arg[iarg],"^\\d+:\\d+:\\d+$")) { + } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+:\\d+$")) { stop = values.next_tagint(); delta = values.next_tagint(); } else throw TokenizerException("Syntax error",""); From 3d67d1eee9dcdc58b38e243f7ffa0aca43b61147 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 16 Mar 2021 00:50:10 -0400 Subject: [PATCH 25/31] simplify --- src/variable.cpp | 8 ++------ src/write_coeff.cpp | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/variable.cpp b/src/variable.cpp index 79543f9a71..1af4a4728a 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -186,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); @@ -196,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; 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); From 2f8770971ce4cfe3c959c34da273f7307f26b66c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 16 Mar 2021 01:15:32 -0400 Subject: [PATCH 26/31] make use of utils::strdup() and simplify --- src/run.cpp | 4 +-- src/thermo.cpp | 67 ++++++++++++++++---------------------------------- src/update.cpp | 4 +-- 3 files changed, 23 insertions(+), 52 deletions(-) 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/thermo.cpp b/src/thermo.cpp index 7e14fe37c0..eb4cc0f5ff 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 @@ -127,12 +125,12 @@ Thermo::Thermo(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) int nvalues = utils::expand_args(FLERR,narg-1,&arg[1],0,earg,lmp); if (earg != &arg[1]) expand = 1; - line = new char[256+nvalues*64]; - line[0] = '\0'; + std::string concat; for (int iarg = 0; iarg < nvalues; iarg++) { - strcat(line,earg[iarg]); - strcat(line," "); + concat += earg[iarg]; + concat += " "; } + line = utils::strdup(concat); line[strlen(line)-1] = '\0'; // if wildcard expansion occurred, free earg memory from exapnd_args() @@ -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/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)) { From 5d5fc4a04d437416c2192a266c2746baab857544 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 16 Mar 2021 08:35:06 -0400 Subject: [PATCH 27/31] simplify by using utils::strdup() --- src/read_data.cpp | 10 ++-------- src/read_dump.cpp | 16 ++++------------ src/region.cpp | 25 ++++++------------------- src/region_intersect.cpp | 10 +++------- src/region_union.cpp | 10 +++------- src/text_file_reader.cpp | 5 +---- 6 files changed, 19 insertions(+), 57 deletions(-) diff --git a/src/read_data.cpp b/src/read_data.cpp index 4f7cf544a9..bc214fbb09 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -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; 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/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); From b7759b0cdbc24309ea4b4d9cf4449b7d973e4128 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 16 Mar 2021 09:15:49 -0400 Subject: [PATCH 28/31] use ValueTokenizer instead of sscanf() for safer parsing of custom processor grids --- src/procmap.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) 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); } From 1ef1a7d865728676ee6ba85dc876d2b7234b86e1 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 16 Mar 2021 09:39:28 -0400 Subject: [PATCH 29/31] simplify using std::string --- src/library.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) 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()); } /* ---------------------------------------------------------------------- */ From eb90fcecb12d51a716a1b389c4557d059e7a5321 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 16 Mar 2021 09:39:45 -0400 Subject: [PATCH 30/31] simplify using utils::strdup() --- src/modify.cpp | 8 ++------ src/output.cpp | 8 ++------ src/pair_coul_streitz.cpp | 4 +--- 3 files changed, 5 insertions(+), 15 deletions(-) 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++; } } From cf19197f79d6b7f4a9a37c9ef91f868c2e2fcd94 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 16 Mar 2021 10:03:22 -0400 Subject: [PATCH 31/31] revert change causing memory corruption. we need extra space in the allocated string buffer. --- src/thermo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/thermo.cpp b/src/thermo.cpp index eb4cc0f5ff..01dd9e0750 100644 --- a/src/thermo.cpp +++ b/src/thermo.cpp @@ -125,12 +125,12 @@ Thermo::Thermo(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) int nvalues = utils::expand_args(FLERR,narg-1,&arg[1],0,earg,lmp); if (earg != &arg[1]) expand = 1; - std::string concat; + line = new char[256+nvalues*64]; + line[0] = '\0'; for (int iarg = 0; iarg < nvalues; iarg++) { - concat += earg[iarg]; - concat += " "; + strcat(line,earg[iarg]); + strcat(line," "); } - line = utils::strdup(concat); line[strlen(line)-1] = '\0'; // if wildcard expansion occurred, free earg memory from exapnd_args()