Commit 052a732c authored by kraus's avatar kraus

Merge branch '495-disable-unquoted-string-literals' into 'master'

Resolve "Disable unquoted string literals"

Closes #654 and #495

See merge request OPAL/src!491
parents 9b626590 b2e7eee1
......@@ -20,6 +20,7 @@
#include "Parser/Statement.h"
#include "Utilities/OpalException.h"
#include <boost/algorithm/string/join.hpp>
// Class AttributeHandler
// ------------------------------------------------------------------------
......@@ -94,6 +95,17 @@ void AttributeHandler::setReadOnly(bool flag) {
is_readonly = flag;
}
void AttributeHandler::setPredefinedValues(const std::set<std::string>& predefinedValues,
const std::string& defaultValue)
{
std::string validValues = " Valid values are " + boost::algorithm::join(predefinedValues, ", ") + ".";
if (defaultValue != "_HAS_NO_DEFAULT_") {
validValues += " Its default is " + defaultValue + ".";
}
std::string* help = const_cast<std::string*>(&itsHelp);
*help += validValues;
}
std::multimap<AttributeHandler::OwnerType, std::string> AttributeHandler::getOwner(const std::string &att) {
std::multimap<OwnerType, std::string> possibleOwners;
......
......@@ -23,6 +23,7 @@
#include "MemoryManagement/Pointer.h"
#include <string>
#include <map>
#include <set>
class Attribute;
class Statement;
......@@ -111,6 +112,9 @@ public:
// then [b]OpalException[/b] is thrown.
void setReadOnly(bool);
/// Add predefined strings values to the help
void setPredefinedValues(const std::set<std::string>&, const std::string&);
enum OwnerType {
ELEMENT,
COMMAND,
......
......@@ -207,7 +207,7 @@ namespace Expressions {
// When no string is seen, a ParseError is thrown with the message
// given as the second argument.
extern std::string parseString(Statement &, const char msg[]);
extern std::string parseStringValue(Statement &, const char msg[]);
// ARRAY EXPRESSION PARSERS.
......@@ -392,4 +392,4 @@ namespace Expressions {
// ======================================================================
};
#endif // OPAL_Expressions_HH
#endif // OPAL_Expressions_HH
\ No newline at end of file
......@@ -368,23 +368,18 @@ void MultiBunchHandler::setMode(const std::string& mbmode) {
<< " the limitation. The control parameter is set to "
<< coeffDBunches_m << endl;
mode_m = MB_MODE::AUTO;
} else
throw OpalException("MultiBunchHandler::setMode()",
"MBMODE name \"" + mbmode + "\" unknown.");
}
}
void MultiBunchHandler::setBinning(std::string binning) {
if ( binning.compare("BUNCH") == 0 ) {
*gmsg << "Use 'BUNCH' injection for binnning." << endl;
if ( binning.compare("BUNCH_BINNING") == 0 ) {
*gmsg << "Use 'BUNCH_BINNING' injection for binnning." << endl;
binning_m = MB_BINNING::BUNCH;
} else if ( binning.compare("GAMMA") == 0 ) {
*gmsg << "Use 'GAMMA' for binning." << endl;
} else if ( binning.compare("GAMMA_BINNING") == 0 ) {
*gmsg << "Use 'GAMMA_BINNING' for binning." << endl;
binning_m = MB_BINNING::GAMMA;
} else {
throw OpalException("MultiBunchHandler::setBinning()",
"MB_BINNING name \"" + binning + "\" unknown.");
}
}
......@@ -564,4 +559,4 @@ void MultiBunchHandler::updatePathLength(const std::vector<double>& lpaths) {
for (short b = 0; b < bunchCount_m; ++b) {
binfo_m[b].pathlength += lpaths[b];
}
}
}
\ No newline at end of file
......@@ -161,8 +161,7 @@ ParallelCyclotronTracker::ParallelCyclotronTracker(const Beamline &beamline,
stepper_m = stepper::INTEGRATOR::LF2;
} else if ( timeIntegrator == 2) {
stepper_m = stepper::INTEGRATOR::MTS;
} else
stepper_m = stepper::INTEGRATOR::UNDEFINED;
}
}
/**
......@@ -1220,11 +1219,6 @@ void ParallelCyclotronTracker::execute() {
std::placeholders::_4);
switch ( stepper_m ) {
case stepper::INTEGRATOR::RK4: {
*gmsg << "* 4th order Runge-Kutta integrator" << endl;
itsStepper_mp.reset(new RK4<function_t>(func));
break;
}
case stepper::INTEGRATOR::LF2: {
*gmsg << "* 2nd order Leap-Frog integrator" << endl;
itsStepper_mp.reset(new LF2<function_t>(func));
......@@ -1234,11 +1228,11 @@ void ParallelCyclotronTracker::execute() {
*gmsg << "* Multiple time stepping (MTS) integrator" << endl;
break;
}
case stepper::INTEGRATOR::UNDEFINED: {
default:
itsStepper_mp.reset(nullptr);
throw OpalException("ParallelCyclotronTracker::execute",
"Invalid name of TIMEINTEGRATOR in Track command");
case stepper::INTEGRATOR::RK4:
default: {
*gmsg << "* 4th order Runge-Kutta integrator" << endl;
itsStepper_mp.reset(new RK4<function_t>(func));
break;
}
}
......@@ -3515,4 +3509,4 @@ void ParallelCyclotronTracker::initPathLength() {
// we need to reset the path length of each bunch
itsDataSink->setMultiBunchInitialPathLengh(mbHandler_m.get());
}
}
}
\ No newline at end of file
......@@ -25,8 +25,9 @@
#include "Attributes/Real.h"
#include "Attributes/RealArray.h"
#include "Attributes/Reference.h"
#include "Attributes/opalstr.h"
#include "Attributes/String.h"
#include "Attributes/StringArray.h"
#include "Attributes/PredefinedString.h"
#include "Attributes/UpperCaseString.h"
#include "Attributes/UpperCaseStringArray.h"
#include "Attributes/TableRow.h"
......@@ -344,7 +345,8 @@ namespace Attributes {
AttributeBase *base = &attr.getBase();
std::string expr;
if(dynamic_cast<String *>(&attr.getHandler())
|| dynamic_cast<UpperCaseString *>(&attr.getHandler())) {
|| dynamic_cast<UpperCaseString *>(&attr.getHandler())
|| dynamic_cast<PredefinedString *>(&attr.getHandler())) {
expr = dynamic_cast<SValue<std::string> *>(base)->evaluate();
} else if(SValue<SRefAttr<std::string> > *ref =
dynamic_cast<SValue<SRefAttr<std::string> > *>(base)) {
......@@ -401,6 +403,42 @@ namespace Attributes {
}
// ----------------------------------------------------------------------
// Predefined string value.
Attribute makePredefinedString(const std::string &name,
const std::string &help,
const std::initializer_list<std::string>& predefinedStrings) {
return Attribute(new PredefinedString(name, help, predefinedStrings), nullptr);
}
Attribute
makePredefinedString(const std::string &name,
const std::string &help,
const std::initializer_list<std::string>& predefinedStrings,
const std::string &initial) {
return Attribute(new PredefinedString(name, help, predefinedStrings, initial),
new SValue<std::string>(Util::toUpper(initial)));
}
void setPredefinedString(Attribute &attr, const std::string &val) {
SValue<SRefAttr<std::string> > *ref;
std::string upperCaseVal = Util::toUpper(val);
if(dynamic_cast<const PredefinedString *>(&attr.getHandler())) {
attr.set(new SValue<std::string>(upperCaseVal));
} else if((attr.isBaseAllocated() == true) &&
(ref = dynamic_cast<SValue<SRefAttr<std::string> >*>(&attr.getBase()))) {
const SRefAttr<std::string> &value = ref->evaluate();
value.set(upperCaseVal);
} else {
throw OpalException("Attributes::setPredefinedString()", "Attribute \"" +
attr.getName() + "\" is not a supported string.");
}
}
// ----------------------------------------------------------------------
// Upper case string value.
......
......@@ -23,6 +23,7 @@
#include <list>
#include <string>
#include <vector>
#include <initializer_list>
class PlaceRep;
class RangeRep;
......@@ -139,6 +140,23 @@ namespace Attributes {
/// Set string value.
extern void setString(Attribute &attr, const std::string &val);
/// Make predefined string attribute.
// Initial value undefined.
extern Attribute makePredefinedString(const std::string &name,
const std::string &help,
const std::initializer_list<std::string>& predefinedStrings);
/// Make predefined string attribute.
// Initial value is defined.
extern Attribute
makePredefinedString(const std::string &name,
const std::string &help,
const std::initializer_list<std::string>& predefinedStrings,
const std::string &initial);
/// Set predefined string value.
extern void setPredefinedString(Attribute &attr, const std::string &val);
/// Make uppercase string attribute.
// Initial value undefined.
extern Attribute makeUpperCaseString(const std::string &name, const std::string &help);
......
......@@ -3,11 +3,12 @@ set (_SRCS
Bool.cpp
BoolArray.cpp
Place.cpp
PredefinedString.cpp
Range.cpp
Real.cpp
RealArray.cpp
Reference.cpp
opalstr.cpp
String.cpp
StringArray.cpp
TableRow.cpp
TokenList.cpp
......@@ -26,12 +27,13 @@ set (HDRS
Attributes.h
BoolArray.h
Bool.h
opalstr.h
Place.h
PredefinedString.h
Range.h
RealArray.h
Real.h
Reference.h
String.h
StringArray.h
TableRow.h
TokenListArray.h
......@@ -40,4 +42,4 @@ set (HDRS
UpperCaseStringArray.h
)
install (FILES ${HDRS} DESTINATION "${CMAKE_INSTALL_PREFIX}/include/Attributes")
install (FILES ${HDRS} DESTINATION "${CMAKE_INSTALL_PREFIX}/include/Attributes")
\ No newline at end of file
//
// Class PredefinedString
// This class is used to parse attributes of type string that should
// be contained in set of predefined strings.
//
// Copyright (c) 2021, Christof Metzger-Kraus, Open Sourcerer
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#include "Attributes/Attributes.h"
#include "Attributes/PredefinedString.h"
#include "AbstractObjects/Expressions.h"
#include "Utilities/ParseError.h"
#include "Utilities/Util.h"
using namespace Expressions;
namespace Attributes {
PredefinedString::PredefinedString(const std::string &name,
const std::string &help,
const std::initializer_list<std::string>& predefinedStrings,
const std::string& defaultValue):
AttributeHandler(name, help, 0)
{
for (const std::string& value: predefinedStrings) {
predefinedStrings_m.insert(Util::toUpper(value));
}
setPredefinedValues(predefinedStrings_m, defaultValue);
}
PredefinedString::~PredefinedString()
{}
const std::string &PredefinedString::getType() const {
static const std::string type("predefined string");
return type;
}
void PredefinedString::parse(Attribute &attr, Statement &stat, bool) const {
std::string value = Util::toUpper(parseStringValue(stat, "String value expected"));
if (predefinedStrings_m.count(value) == 0) {
throw ParseError("PredefinedString::parse", "Unsupported value '" + value + "'");
}
Attributes::setPredefinedString(attr, value);
}
};
\ No newline at end of file
//
// Class PredefinedString
// This class is used to parse attributes of type string that should
// be contained in set of predefined strings.
//
// Copyright (c) 2021, Christof Metzger-Kraus, Open Sourcerer
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#ifndef OPAL_PredefinedString_HH
#define OPAL_PredefinedString_HH
#include "AbstractObjects/Attribute.h"
#include "AbstractObjects/AttributeHandler.h"
#include <set>
namespace Attributes {
/// Parser for an attribute of type string.
class PredefinedString: public AttributeHandler {
public:
/// Constructor.
// Assign attribute name and help string.
PredefinedString(const std::string& name,
const std::string& help,
const std::initializer_list<std::string>& predefinedStrings,
const std::string& defaultValue = "_HAS_NO_DEFAULT_");
virtual ~PredefinedString();
/// Return attribute type string ``string''.
virtual const std::string &getType() const;
/// Parse the attribute.
virtual void parse(Attribute &, Statement &, bool) const;
private:
// Not implemented.
PredefinedString();
PredefinedString(const PredefinedString &);
void operator=(const PredefinedString &);
std::set<std::string> predefinedStrings_m;
};
};
#endif
\ No newline at end of file
......@@ -16,7 +16,7 @@
//
// ------------------------------------------------------------------------
#include "Attributes/opalstr.h"
#include "Attributes/String.h"
#include "AbstractObjects/Expressions.h"
#include "Expressions/SValue.h"
#include "Utilities/OpalException.h"
......@@ -46,7 +46,9 @@ namespace Attributes {
void String::parse(Attribute &attr, Statement &stat, bool) const {
attr.set(new SValue<std::string>(parseString(stat, "String value expected.")));
std::string result = parseStringValue(stat, "String value expected.");
attr.set(new SValue<std::string>(result));
}
};
};
\ No newline at end of file
......@@ -65,7 +65,7 @@ namespace Attributes {
}
array[index - 1] =
Expressions::parseString(statement, "String value expected.");
Expressions::parseStringValue(statement, "String value expected.");
Attributes::setStringArray(attr, array);
}
......
......@@ -44,7 +44,7 @@ namespace Attributes {
}
void UpperCaseString::parse(Attribute &attr, Statement &stat, bool) const {
Attributes::setUpperCaseString(attr, parseString(stat, "String value expected."));
Attributes::setUpperCaseString(attr, parseStringValue(stat, "String value expected."));
}
};
\ No newline at end of file
......@@ -64,7 +64,7 @@ namespace Attributes {
}
array[index - 1] =
Expressions::parseString(statement, "String value expected.");
Expressions::parseStringValue(statement, "String value expected.");
Attributes::setUpperCaseStringArray(attr, array);
}
......
......@@ -47,8 +47,8 @@ DumpEMFields::DumpEMFields() :
itsAttr[FILE_NAME] = Attributes::makeString
("FILE_NAME", "Name of the file to which field data is dumped");
itsAttr[COORDINATE_SYSTEM] = Attributes::makeUpperCaseString
("COORDINATE_SYSTEM", "Choose to use CARTESIAN (default) or CYLINDRICAL coordinates", "CARTESIAN");
itsAttr[COORDINATE_SYSTEM] = Attributes::makePredefinedString
("COORDINATE_SYSTEM", "Choose to use CARTESIAN or CYLINDRICAL coordinates", {"CARTESIAN", "CYLINDRICAL"}, "CARTESIAN");
itsAttr[X_START] = Attributes::makeReal
("X_START", "(Cartesian) Start point in the grid in x [m]");
......@@ -136,10 +136,6 @@ void DumpEMFields::parseCoordinateSystem() {
coordinates_m = CoordinateSystem::CYLINDRICAL;
} else if (coordStr == "CARTESIAN") {
coordinates_m = CoordinateSystem::CARTESIAN;
} else {
throw OpalException("DumpEMFields::parseCoordinateSystem",
"Failed to parse '" + coordStr +
"'. OPAL expected either CYLINDRICAL or CARTESIAN.");
}
}
......@@ -153,9 +149,9 @@ void DumpEMFields::execute() {
}
void DumpEMFields::buildGrid() {
std::vector<double> spacing(4);
std::vector<double> origin(4);
std::vector<int> gridSize(4);
std::vector<double> spacing(4);
std::vector<double> origin(4);
std::vector<int> gridSize(4);
parseCoordinateSystem();
if (coordinates_m == CoordinateSystem::CYLINDRICAL) {
......@@ -262,7 +258,7 @@ void DumpEMFields::writeFieldLine(Component* field,
Vector_t B(0., 0., 0.);
Vector_t point = pointIn;
if (coordinates_m == CoordinateSystem::CYLINDRICAL) {
// pointIn is r, phi, z
// pointIn is r, phi, z
point[0] = std::cos(pointIn[1])*pointIn[0];
point[1] = std::sin(pointIn[1])*pointIn[0];
}
......@@ -366,4 +362,4 @@ void DumpEMFields::print(std::ostream& os) const {
<< "* DT = " << Attributes::getReal(itsAttr[DT]) << " [ns]\n"
<< "* T_STEPS = " << Attributes::getReal(itsAttr[T_STEPS]) << '\n';
os << "* ********************************************************************************** " << std::endl;
}
}
\ No newline at end of file
......@@ -149,14 +149,14 @@ Option::Option():
"REMOTEPARTDEL times of the beam rms size, "
"its default values is 0 (no delete) ",remotePartDel);
itsAttr[PSDUMPFRAME] = Attributes::makeUpperCaseString
itsAttr[PSDUMPFRAME] = Attributes::makePredefinedString
("PSDUMPFRAME", "Controls the frame of phase space dump in "
"stat file and h5 file. If 'GLOBAL' OPAL will dump in the "
"lab (global) Cartesian frame; if 'BUNCH_MEAN' OPAL will "
"dump in the local Cartesian frame of the beam mean; "
"if 'REFERENCE' OPAL will dump in the local Cartesian "
"frame of the reference particle 0. Only available for "
"OPAL-cycl, its default value is 'GLOBAL'");
"stat file and h5 file. If 'GLOBAL' OPAL will dump in the "
"lab (global) Cartesian frame; if 'BUNCH_MEAN' OPAL will "
"dump in the local Cartesian frame of the beam mean; "
"if 'REFERENCE' OPAL will dump in the local Cartesian "
"frame of the reference particle 0. Only available for "
"OPAL-cycl.", {"BUNCH_MEAN", "REFERENCE", "GLOBAL"}, "GLOBAL");
itsAttr[SPTDUMPFREQ] = Attributes::makeReal
("SPTDUMPFREQ", "The frequency to dump single "
......@@ -203,9 +203,10 @@ Option::Option():
("CZERO", "If set to true a symmetric distribution is "
"created -> centroid == 0.0", cZero);
itsAttr[RNGTYPE] = Attributes::makeUpperCaseString
("RNGTYPE", "RANDOM (default), Quasi-random number "
"generators: HALTON, SOBOL, NIEDERREITER (Gsl ref manual 18.5)", rngtype);
itsAttr[RNGTYPE] = Attributes::makePredefinedString
("RNGTYPE", "Type of pseudo- or quasi-random number generator, "
"see also Quasi-Random Sequences, GSL reference manual.",
{"RANDOM", "HALTON", "SOBOL", "NIEDERREITER"}, rngtype);
itsAttr[CLOTUNEONLY] = Attributes::makeBool
("CLOTUNEONLY", "If set to true stop after "
......@@ -292,7 +293,7 @@ Option::Option(const std::string& name, Option* parent):
Attributes::setReal(itsAttr[PSDUMPFREQ], psDumpFreq);
Attributes::setReal(itsAttr[STATDUMPFREQ], statDumpFreq);
Attributes::setBool(itsAttr[PSDUMPEACHTURN], psDumpEachTurn);
Attributes::setUpperCaseString(itsAttr[PSDUMPFRAME], DumpFrameToString(psDumpFrame));
Attributes::setPredefinedString(itsAttr[PSDUMPFRAME], DumpFrameToString(psDumpFrame));
Attributes::setReal(itsAttr[SPTDUMPFREQ], sptDumpFreq);
Attributes::setReal(itsAttr[SCSOLVEFREQ], scSolveFreq);
Attributes::setReal(itsAttr[MTSSUBSTEPS], mtsSubsteps);
......@@ -307,7 +308,7 @@ Option::Option(const std::string& name, Option* parent):
Attributes::setReal(itsAttr[AUTOPHASE], autoPhase);
Attributes::setBool(itsAttr[CZERO], cZero);
Attributes::setBool(itsAttr[CLOTUNEONLY], cloTuneOnly);
Attributes::setUpperCaseString(itsAttr[RNGTYPE], std::string(rngtype));
Attributes::setPredefinedString(itsAttr[RNGTYPE], std::string(rngtype));
Attributes::setReal(itsAttr[NUMBLOCKS], numBlocks);
Attributes::setReal(itsAttr[RECYCLEBLOCKS], recycleBlocks);
Attributes::setReal(itsAttr[NLHS], nLHS);
......@@ -504,11 +505,6 @@ void Option::handlePsDumpFrame(const std::string& dumpFrame) {
psDumpFrame = BUNCH_MEAN;
} else if (dumpFrame == "REFERENCE") {
psDumpFrame = REFERENCE;
} else {
std::string msg = std::string("Did not recognise PSDUMPFRAME '")+\
dumpFrame+std::string("'. It should be one of 'GLOBAL',")+\
std::string(" 'BUNCH_MEAN' or 'REFERENCE'");
throw OpalException("Option::handlePsDumpFrame", msg);
}
}
......@@ -528,4 +524,4 @@ void Option::update(const std::vector<Attribute>& othersAttributes) {
for (int i = 0; i < SIZE; ++ i) {
itsAttr[i] = othersAttributes[i];
}
}
}
\ No newline at end of file
......@@ -369,9 +369,6 @@ void Cyclotron::setBFieldType() {
fieldType_m = BFieldType::BANDRF;
} else if (typeName_m == std::string("SYNCHROCYCLOTRON")) {
fieldType_m = BFieldType::SYNCHRO;
} else {
throw GeneralClassicException("Cyclotron::setBFieldType",
"TYPE " + typeName_m + " field reading function of CYCLOTRON is not defined!");
}
}
......@@ -958,7 +955,7 @@ void Cyclotron::getFieldFromFile_Ring(const double& scaleFactor) {
BP.Bfact = scaleFactor;
f = std::fopen(fmapfn_m.c_str(), "r");
CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP.rmin));
*gmsg << "* Minimal radius of measured field map: " << BP.rmin << " [mm]" << endl;
BP.rmin *= 0.001; // mm --> m
......@@ -1539,4 +1536,4 @@ void Cyclotron::getFieldFromFile_Synchrocyclotron(const double& scaleFactor) {
void Cyclotron::getDimensions(double& /*zBegin*/, double& /*zEnd*/) const
{ }
#undef CHECK_CYC_FSCANF_EOF
#undef CHECK_CYC_FSCANF_EOF
\ No newline at end of file
......@@ -159,7 +159,7 @@ std::string Vacuum::getResidualGasName() {
}
default: {
throw GeneralClassicException("Vacuum::getResidualGasName",
"Residual gas not found");
"Residual gas not set");
}
}
}
......@@ -409,4 +409,4 @@ void Vacuum::getPressureFromFile(const double& scaleFactor) {
std::fclose(f);
}
#undef CHECK_VAC_FSCANF_EOF
#undef CHECK_VAC_FSCANF_EOF
\ No newline at end of file
......@@ -22,8 +22,6 @@
#include "Parser/Token.h"
#include <iostream>
extern Inform *gmsg;
// Class Statement
// ------------------------------------------------------------------------
......@@ -229,4 +227,11 @@ void Statement::printWhere(Inform &msg, bool withToken) const {
} else {
msg << ":\n";
}
}
std::string Statement::str() const {
std::ostringstream str;
print(str);
return str.str();
}
\ No newline at end of file
......@@ -166,6 +166,7 @@ public:
// stream. If [b]withToken[/b] is true, print also the last token parsed.
virtual void printWhere(Inform &msg, bool withToken) const;
std::string str() const;
protected:
// Line number where statement begins.
......
......@@ -25,14 +25,13 @@
#include "Utilities/FormatError.h"
#include <cctype>
// Class StringStream
// ------------------------------------------------------------------------
StringStream::StringStream(const std::string &str):
TokenStream("expression"),
line(str + '\n'),
curr_char(0)
line_m(str + '\n'),
currentChar_m(0)
{}
......@@ -47,17 +46,17 @@ Token StringStream::readToken() {
}
while(true) {
if(curr_char >= line.length() || line[curr_char] == '\n') {
if(currentChar_m >= line_m.length() || line_m[currentChar_m] == '\n') {
return Token("string", 1, Token::IS_EOF, "EOF");
} else if(isspace(line[curr_char])) {
curr_char++;
} else if(isspace(line_m[currentChar_m])) {
currentChar_m++;
} else {
break;
}