diff --git a/src/DataTree.cc b/src/DataTree.cc index df018564ec058515d0171363404fe9294feee818..e97204f70dd89aa6ea72cd60f67c30c79b5e2d94 100644 --- a/src/DataTree.cc +++ b/src/DataTree.cc @@ -20,7 +20,6 @@ #include <cstdlib> #include <cassert> #include <iostream> -#include <regex> #include <algorithm> #include <iterator> #include <filesystem> @@ -962,17 +961,17 @@ DataTree::strsplit(string_view str, char delim) return result; } -string -DataTree::packageDir(const string &package) +filesystem::path +DataTree::packageDir(string_view package) { - regex pat{R"(\.)"}; - string dirname = "+" + regex_replace(package, pat, "/+"); - filesystem::create_directories(dirname); - return dirname; + filesystem::path d; + for (const auto &it : strsplit(move(package), '.')) + d /= "+" + it; + return d; } void -DataTree::writeToFileIfModified(stringstream &new_contents, const string &filename) +DataTree::writeToFileIfModified(stringstream &new_contents, const filesystem::path &filename) { ifstream old_file{filename, ios::in | ios::binary}; if (old_file.is_open() @@ -986,7 +985,7 @@ DataTree::writeToFileIfModified(stringstream &new_contents, const string &filena ofstream new_file{filename, ios::out | ios::binary}; if (!new_file.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } copy(istreambuf_iterator<char>{new_contents}, istreambuf_iterator<char>{}, diff --git a/src/DataTree.hh b/src/DataTree.hh index 8299a0ee4a830a7a6634a8660b704ec33e1c4f02..42305b15595bb296ad41717454d301f1ac07d55f 100644 --- a/src/DataTree.hh +++ b/src/DataTree.hh @@ -28,6 +28,8 @@ #include <cmath> #include <utility> #include <memory> +#include <filesystem> +#include <string_view> #include "SymbolTable.hh" #include "NumericalConstants.hh" @@ -109,7 +111,7 @@ protected: /* Writes the contents of “new_contents” to the file “filename”. However, if the file already exists and would not be modified by this operation, then do nothing. */ - static void writeToFileIfModified(stringstream &new_contents, const string &filename); + static void writeToFileIfModified(stringstream &new_contents, const filesystem::path &filename); private: constexpr static int constants_precision{16}; @@ -361,11 +363,10 @@ public: static vector<string> strsplit(string_view str, char delim); /*! Takes a MATLAB/Octave package name (possibly with several levels nested using dots), - and returns the name of the corresponding filesystem directory (which - is created by the function if it does not exist). + and returns the path to the corresponding filesystem directory. In practice the package nesting is used for the planner_objective (stored inside +objective subdir). */ - static string packageDir(const string &package); + static filesystem::path packageDir(string_view package); }; inline expr_t diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 096537a94a2395184cc7ae281855673ad784c517..93e9627e4ea41bf148f433181385ae562cdbb557 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -223,16 +223,16 @@ DynamicModel::writeDynamicPerBlockMFiles(const string &basename) const int nze_exo = blocks_derivatives_exo[blk].size(); int nze_exo_det = blocks_derivatives_exo_det[blk].size(); - string filename = packageDir(basename + ".block") + "/dynamic_" + to_string(blk+1) + ".m"; + filesystem::path filename {packageDir(basename) / "+block" / ("dynamic_" + to_string(blk+1) + ".m")}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } output << "%" << endl - << "% " << filename << " : Computes dynamic version of one block" << endl + << "% " << filename.string() << " : Computes dynamic version of one block" << endl << "%" << endl << "% Warning : this file is generated automatically by Dynare" << endl << "% from model file (.mod)" << endl << endl @@ -987,11 +987,11 @@ DynamicModel::printNonZeroHessianEquations(ostream &output) const void DynamicModel::writeDynamicBlockMFile(const string &basename) const { - string filename = packageDir(basename) + "/dynamic.m"; + filesystem::path filename {packageDir(basename) / "dynamic.m"}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -1102,7 +1102,7 @@ DynamicModel::writeDynamicBlockCFile(const string &basename, vector<filesystem:: output.close(); per_block_object_files.push_back(filename); - compileMEX("+" + basename, "dynamic", mexext, per_block_object_files, matlabroot, dynareroot); + compileMEX(packageDir(basename), "dynamic", mexext, per_block_object_files, matlabroot, dynareroot); } void @@ -1116,11 +1116,11 @@ DynamicModel::writeDynamicMWrapperFunction(const string &basename, const string else if (ending == "g3") name = "dynamic_resid_g1_g2_g3"; - string filename = packageDir(basename) + "/" + name + ".m"; + filesystem::path filename {packageDir(basename) / (name + ".m")}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -1164,11 +1164,11 @@ DynamicModel::writeDynamicMFileHelper(const string &basename, const ostringstream &init_s, const ostringstream &end_s, const ostringstream &s, const ostringstream &s_tt) const { - string filename = packageDir(basename) + "/" + name_tt + ".m"; + filesystem::path filename {packageDir(basename) / (name_tt + ".m")}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -1201,11 +1201,11 @@ DynamicModel::writeDynamicMFileHelper(const string &basename, << "end" << endl; output.close(); - filename = packageDir(basename) + "/" + name + ".m"; + filename = packageDir(basename) / (name + ".m"); output.open(filename, ios::out | ios::binary); if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -1245,11 +1245,11 @@ DynamicModel::writeDynamicMFileHelper(const string &basename, void DynamicModel::writeDynamicMCompatFile(const string &basename) const { - string filename = packageDir(basename) + "/dynamic.m"; + filesystem::path filename {packageDir(basename) / "dynamic.m"}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } int ntt { static_cast<int>(temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() + temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size()) }; @@ -1291,7 +1291,7 @@ DynamicModel::writeDynamicJacobianNonZeroEltsFile(const string &basename) const sort(nzij_current.begin(), nzij_current.end()); sort(nzij_fwrd.begin(), nzij_fwrd.end()); - ofstream output{"+" + basename + "/dynamic_g1_nz.m", ios::out | ios::binary}; + ofstream output{packageDir(basename) / "dynamic_g1_nz.m", ios::out | ios::binary}; output << "function [nzij_pred, nzij_current, nzij_fwrd] = dynamic_g1_nz()" << endl << "% Returns the coordinates of non-zero elements in the Jacobian, in column-major order, for each lead/lag (only for endogenous)" << endl; auto print_nzij = [&output](const vector<pair<int, int>> &nzij, const string &name) { @@ -3472,6 +3472,16 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool use_dll, model_dir /= "model"; if (use_dll) create_directories(model_dir / "src"); + if (!julia) + { + auto plusfolder {packageDir(basename)}; + /* The following is not a duplicate of the same call from + ModFile::writeMOutput(), because of planner_objective which needs its + +objective subdirectory */ + create_directories(plusfolder); + if (block && !use_dll) + create_directories(plusfolder / "+block"); + } create_directories(model_dir / "bytecode"); if (block) @@ -3543,7 +3553,22 @@ DynamicModel::writeSetAuxiliaryVariables(const string &basename, bool julia) con output << "end" << endl << "end" << endl; - writeToFileIfModified(output, julia ? basename + "DynamicSetAuxiliarySeries.jl" : packageDir(basename) + "/" + func_name + ".m"); + if (julia) + writeToFileIfModified(output, basename + "DynamicSetAuxiliarySeries.jl"); + else + { + /* Calling writeToFileIfModified() is useless here since we write inside + a subdirectory deleted at each preprocessor run. */ + filesystem::path filename {packageDir(basename) / (func_name + ".m")}; + ofstream output_file{filename, ios::out | ios::binary}; + if (!output_file.is_open()) + { + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; + exit(EXIT_FAILURE); + } + output_file << output.str(); + output_file.close(); + } } void diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index 7887c82fdbc7f7f4ea26080255c721f593838e75..92c9c75cd6f2bfe3da2335c310922a7fa72a2dd6 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -837,11 +837,11 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output, g3p_output] { writeParamsDerivativesFileHelper<output_type>() }; - string filename { julia ? basename + "DynamicParamsDerivs.jl" : packageDir(basename) + "/dynamic_params_derivs.m" }; + const filesystem::path filename {julia ? filesystem::path{basename + "DynamicParamsDerivs.jl"} : packageDir(basename) / "dynamic_params_derivs.m"}; ofstream paramsDerivsFile { filename, ios::out | ios::binary }; if (!paramsDerivsFile.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } diff --git a/src/ModFile.cc b/src/ModFile.cc index 6e989c090f5c0ec5e6bdd278956339f6beed8406..2225ffeb8a6924521cb8cf2af3b6f1009265caa0 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -782,6 +782,14 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global, const filesystem::path &matlabroot, const filesystem::path &dynareroot, bool onlymodel, bool gui, bool notime) const { + if (basename.empty()) + { + cerr << "ERROR: Missing file name" << endl; + exit(EXIT_FAILURE); + } + + auto plusfolder {DataTree::packageDir(basename)}; + bool hasModelChanged = !dynamic_model.isChecksumMatching(basename) || !check_model_changes; if (hasModelChanged) { @@ -793,7 +801,7 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global, it before deleting it (the renaming must occur in the same directory, otherwise it may file if the destination is not on the same filesystem). */ - if (filesystem::path plusfolder{"+" + basename}; exists(plusfolder)) + if (exists(plusfolder)) { if (exists(plusfolder / "+objective")) { @@ -811,18 +819,12 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global, filesystem::remove_all(basename + "/model/bytecode"); } - if (!basename.size()) - { - cerr << "ERROR: Missing file name" << endl; - exit(EXIT_FAILURE); - } - - filesystem::create_directory("+" + basename); - string fname = "+" + basename + "/driver.m"; + create_directory(plusfolder); + filesystem::path fname {plusfolder / "driver.m"}; ofstream mOutputFile{fname, ios::out | ios::binary}; if (!mOutputFile.is_open()) { - cerr << "ERROR: Can't open file " << fname << " for writing" << endl; + cerr << "ERROR: Can't open file " << fname.string() << " for writing" << endl; exit(EXIT_FAILURE); } diff --git a/src/ModelEquationBlock.cc b/src/ModelEquationBlock.cc index dfe4ef54d9cf1dd6a4aa4ada3a2469b35c7d93b5..d07fa0d0add82bfdc6168a750741f4ab2c512b9e 100644 --- a/src/ModelEquationBlock.cc +++ b/src/ModelEquationBlock.cc @@ -259,7 +259,22 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool julia) const if (julia) output << "end" << endl << "end" << endl; - writeToFileIfModified(output, julia ? basename + "SteadyState2.jl" : packageDir(basename) + "/steadystate.m"); + if (julia) + writeToFileIfModified(output, basename + "SteadyState2.jl"); + else + { + /* Calling writeToFileIfModified() is useless here since we write inside + a subdirectory deleted at each preprocessor run. */ + filesystem::path filename {packageDir(basename) / "steadystate.m"}; + ofstream output_file{filename, ios::out | ios::binary}; + if (!output_file.is_open()) + { + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; + exit(EXIT_FAILURE); + } + output_file << output.str(); + output_file.close(); + } } void @@ -407,11 +422,11 @@ Epilogue::writeEpilogueFile(const string &basename) const void Epilogue::writeStaticEpilogueFile(const string &basename) const { - string filename = packageDir(basename) + "/epilogue_static.m"; + filesystem::path filename {packageDir(basename) / "epilogue_static.m"}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -445,11 +460,11 @@ Epilogue::writeStaticEpilogueFile(const string &basename) const void Epilogue::writeDynamicEpilogueFile(const string &basename) const { - string filename = packageDir(basename) + "/epilogue_dynamic.m"; + filesystem::path filename {packageDir(basename) / "epilogue_dynamic.m"}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } diff --git a/src/ModelTree.hh b/src/ModelTree.hh index e2e2884983bf470e8d6a7a759c55bf15abd12f93..924257816453690bfe797ab5e0ba746b8ce40679 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -1031,7 +1031,7 @@ ModelTree::writeModelCFile(const string &basename, const string &mexext, output.close(); object_files.push_back(filename); - compileMEX("+" + basename, dynamic ? "dynamic" : "static", mexext, object_files, matlabroot, + compileMEX(packageDir(basename), dynamic ? "dynamic" : "static", mexext, object_files, matlabroot, dynareroot); } diff --git a/src/StaticModel.cc b/src/StaticModel.cc index f4d24f70692ce934e689e9d4c5036fdbf533e9c8..8db084783107037e7111083cffcd81d591467e5e 100644 --- a/src/StaticModel.cc +++ b/src/StaticModel.cc @@ -104,15 +104,15 @@ StaticModel::writeStaticPerBlockMFiles(const string &basename) const { BlockSimulationType simulation_type = blocks[blk].simulation_type; - string filename = packageDir(basename + ".block") + "/static_" + to_string(blk+1) + ".m"; + filesystem::path filename {packageDir(basename) / "+block" / ("static_" + to_string(blk+1) + ".m")}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } output << "%" << endl - << "% " << filename << " : Computes static version of one block" << endl + << "% " << filename.string() << " : Computes static version of one block" << endl << "%" << endl << "% Warning : this file is generated automatically by Dynare" << endl << "% from model file (.mod)" << endl << endl @@ -465,11 +465,11 @@ StaticModel::writeStaticMWrapperFunction(const string &basename, const string &e else if (ending == "g3") name = "static_resid_g1_g2_g3"; - string filename = packageDir(basename) + "/" + name + ".m"; + filesystem::path filename {packageDir(basename) / (name + ".m")}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -513,11 +513,11 @@ StaticModel::writeStaticMFileHelper(const string &basename, const ostringstream &init_s, const ostringstream &end_s, const ostringstream &s, const ostringstream &s_tt) const { - string filename = packageDir(basename) + "/" + name_tt + ".m"; + filesystem::path filename {packageDir(basename) / (name_tt + ".m")}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -545,11 +545,11 @@ StaticModel::writeStaticMFileHelper(const string &basename, << "end" << endl; output.close(); - filename = packageDir(basename) + "/" + name + ".m"; + filename = packageDir(basename) / (name + ".m"); output.open(filename, ios::out | ios::binary); if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -585,11 +585,11 @@ StaticModel::writeStaticMFileHelper(const string &basename, void StaticModel::writeStaticMCompatFile(const string &basename) const { - string filename = packageDir(basename) + "/static.m"; + filesystem::path filename {packageDir(basename) / "static.m"}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } int ntt { static_cast<int>(temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() + temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size()) }; @@ -845,6 +845,16 @@ StaticModel::writeStaticFile(const string &basename, bool block, bool use_dll, c model_dir /= "model"; if (use_dll) create_directories(model_dir / "src"); + if (!julia) + { + auto plusfolder {packageDir(basename)}; + /* The following is not a duplicate of the same call from + ModFile::writeMOutput(), because of planner_objective which needs its + +objective subdirectory */ + create_directories(plusfolder); + if (block && !use_dll) + create_directories(plusfolder / "+block"); + } create_directories(model_dir / "bytecode"); if (block) @@ -894,12 +904,12 @@ StaticModel::exoPresentInEqs() const void StaticModel::writeStaticBlockMFile(const string &basename) const { - string filename = packageDir(basename) + "/static.m"; + filesystem::path filename {packageDir(basename) / "static.m"}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } @@ -999,7 +1009,7 @@ StaticModel::writeStaticBlockCFile(const string &basename, vector<filesystem::pa output.close(); per_block_object_files.push_back(filename); - compileMEX("+" + basename, "static", mexext, per_block_object_files, matlabroot, dynareroot); + compileMEX(packageDir(basename), "static", mexext, per_block_object_files, matlabroot, dynareroot); } void @@ -1205,7 +1215,22 @@ StaticModel::writeSetAuxiliaryVariables(const string &basename, bool julia) cons output << "end" << endl << "end" << endl; - writeToFileIfModified(output, julia ? basename + "SetAuxiliaryVariables.jl" : packageDir(basename) + "/" + func_name + ".m"); + if (julia) + writeToFileIfModified(output, basename + "SetAuxiliaryVariables.jl"); + else + { + /* Calling writeToFileIfModified() is useless here since we write inside + a subdirectory deleted at each preprocessor run. */ + filesystem::path filename {packageDir(basename) / (func_name + ".m")}; + ofstream output_file{filename, ios::out | ios::binary}; + if (!output_file.is_open()) + { + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; + exit(EXIT_FAILURE); + } + output_file << output.str(); + output_file.close(); + } } void diff --git a/src/StaticModel.hh b/src/StaticModel.hh index dcc222f00f67d2c0792966c37a3d35362a5b1f04..4551ebd9fdf204b8f493d2912190a018576e573b 100644 --- a/src/StaticModel.hh +++ b/src/StaticModel.hh @@ -225,11 +225,11 @@ StaticModel::writeParamsDerivativesFile(const string &basename) const { writeParamsDerivativesFileHelper<output_type>() }; // g3p_output is ignored - string filename { julia ? basename + "StaticParamsDerivs.jl" : packageDir(basename) + "/static_params_derivs.m" }; + filesystem::path filename {julia ? filesystem::path{basename + "StaticParamsDerivs.jl"} : packageDir(basename) / "static_params_derivs.m"}; ofstream paramsDerivsFile { filename, ios::out | ios::binary }; if (!paramsDerivsFile.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } diff --git a/src/SubModel.cc b/src/SubModel.cc index adc91816b48d9a608cfa64aff64e0ed557cf34fa..a4d080948e619d3983222e2ea44e6e86316e925d 100644 --- a/src/SubModel.cc +++ b/src/SubModel.cc @@ -246,11 +246,11 @@ TrendComponentModelTable::writeOutput(const string &basename, ostream &output) c if (names.empty()) return; - string filename = "+" + basename + "/trend_component_ar_a0.m"; + const filesystem::path filename {DataTree::packageDir(basename) / "trend_component_ar_a0.m"}; ofstream ar_ec_output{filename, ios::out | ios::binary}; if (!ar_ec_output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } ar_ec_output << "function [AR, A0, A0star] = trend_component_ar_a0(model_name, params)" << endl @@ -427,11 +427,11 @@ VarModelTable::writeOutput(const string &basename, ostream &output) const if (names.empty()) return; - string filename = "+" + basename + "/varmatrices.m"; + const filesystem::path filename {DataTree::packageDir(basename) / "varmatrices.m"}; ofstream ar_output{filename, ios::out | ios::binary}; if (!ar_output.is_open()) { - cerr << "Error: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } ar_output << "function [ar, a0, constants] = varmatrices(model_name, params, reducedform)" << endl @@ -1751,11 +1751,11 @@ PacModelTable::writeTargetCoefficientsFile(const string &basename) const if (target_info.empty()) return; - string filename = DataTree::packageDir(basename) + "/pac_target_coefficients.m"; + filesystem::path filename {DataTree::packageDir(basename) / "pac_target_coefficients.m"}; ofstream output{filename, ios::out | ios::binary}; if (!output.is_open()) { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; exit(EXIT_FAILURE); } output << "function coeffs = pac_target_coefficients(model_name, params)" << endl;