Skip to content

Commit

Permalink
Use c++17 filesystem (#1027)
Browse files Browse the repository at this point in the history
* Use {:g} for printing the units for the tests of the unit parser

Co-authored-by: Ioannis Magkanaris <ioannis.magkanaris@epfl.ch>
  • Loading branch information
alkino and iomaganaris authored Apr 18, 2023
1 parent 6d963c6 commit 3b148fc
Show file tree
Hide file tree
Showing 15 changed files with 113 additions and 201 deletions.
12 changes: 7 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <vector>

#include <CLI/CLI.hpp>
#include <filesystem>

#include "ast/program.hpp"
#include "codegen/codegen_acc_visitor.hpp"
Expand Down Expand Up @@ -51,6 +52,7 @@
* \brief Main NMODL code generation program
*/

namespace fs = std::filesystem;
using namespace nmodl;
using namespace codegen;
using namespace visitor;
Expand All @@ -62,7 +64,7 @@ int main(int argc, const char* argv[]) {
Version::to_string())};

/// list of mod files to process
std::vector<std::string> mod_files;
std::vector<fs::path> mod_files;

/// true if debug logger statements should be shown
std::string verbose("info");
Expand Down Expand Up @@ -261,8 +263,8 @@ int main(int argc, const char* argv[]) {

CLI11_PARSE(app, argc, argv);

utils::make_path(output_dir);
utils::make_path(scratch_dir);
fs::create_directories(output_dir);
fs::create_directories(scratch_dir);

if (sympy_opt) {
nmodl::pybind_wrappers::EmbeddedPythonLoader::get_instance()
Expand All @@ -281,9 +283,9 @@ int main(int argc, const char* argv[]) {
};

for (const auto& file: mod_files) {
logger->info("Processing {}", file);
logger->info("Processing {}", file.string());

const auto modfile = utils::remove_extension(utils::base_name(file));
const auto modfile = file.stem().string();

/// create file path for nmodl file
auto filepath = [scratch_dir, modfile](const std::string& suffix) {
Expand Down
42 changes: 22 additions & 20 deletions src/parser/nmodl_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
* Lesser General Public License. See top-level LICENSE file for details.
*************************************************************************/

#include <filesystem>
#include <fstream>
#include <sstream>

#include "lexer/nmodl_lexer.hpp"
#include "parser/nmodl_driver.hpp"
#include "utils/logger.hpp"

namespace fs = std::filesystem;

namespace nmodl {
namespace parser {

Expand All @@ -30,9 +33,9 @@ std::shared_ptr<ast::Program> NmodlDriver::parse_stream(std::istream& in) {
return astRoot;
}

std::shared_ptr<ast::Program> NmodlDriver::parse_file(const std::string& filename,
std::shared_ptr<ast::Program> NmodlDriver::parse_file(const fs::path& filename,
const location* loc) {
std::ifstream in(filename.c_str());
std::ifstream in(filename);
if (!in.good()) {
std::ostringstream oss;
if (loc == nullptr) {
Expand All @@ -47,26 +50,25 @@ std::shared_ptr<ast::Program> NmodlDriver::parse_file(const std::string& filenam
}

auto current_stream_name = stream_name;
stream_name = filename;
auto absolute_path = utils::cwd() + utils::pathsep + filename;
stream_name = filename.string();
auto absolute_path = fs::absolute(filename);
{
const auto last_slash = filename.find_last_of(utils::pathsep);
if (utils::file_is_abs(filename)) {
const auto path_prefix = filename.substr(0, last_slash + 1);
if (filename.is_absolute()) {
const auto path_prefix = filename.parent_path();
library.push_current_directory(path_prefix);
absolute_path = filename;
} else if (last_slash == std::string::npos) {
library.push_current_directory(utils::cwd());
absolute_path = filename.string();
} else if (!filename.has_parent_path()) {
library.push_current_directory(fs::current_path());
} else {
const auto path_prefix = filename.substr(0, last_slash + 1);
const auto path = utils::cwd() + utils::pathsep + path_prefix;
const auto path_prefix = filename.parent_path();
const auto path = fs::absolute(path_prefix);
library.push_current_directory(path);
}
}

open_files.emplace(absolute_path, loc);
open_files.emplace(absolute_path.string(), loc);
parse_stream(in);
open_files.erase(absolute_path);
open_files.erase(absolute_path.string());
library.pop_current_directory();
stream_name = current_stream_name;

Expand All @@ -79,24 +81,24 @@ std::shared_ptr<ast::Program> NmodlDriver::parse_string(const std::string& input
return astRoot;
}

std::shared_ptr<ast::Include> NmodlDriver::parse_include(const std::string& name,
std::shared_ptr<ast::Include> NmodlDriver::parse_include(const fs::path& name,
const location& loc) {
if (name.empty()) {
parse_error(loc, "empty filename");
}

// Try to find directory containing the file to import
const auto directory_path = library.find_file(name);
const auto directory_path = fs::path{library.find_file(name)};

// Complete path of file (directory + filename).
std::string absolute_path = name;
auto absolute_path = name;

if (!directory_path.empty()) {
absolute_path = directory_path + std::string(1, utils::pathsep) + name;
absolute_path = directory_path / name;
}

// Detect recursive inclusion.
auto already_included = open_files.find(absolute_path);
auto already_included = open_files.find(absolute_path.string());
if (already_included != open_files.end()) {
std::ostringstream oss;
oss << name << ": recursive inclusion.\n";
Expand All @@ -113,7 +115,7 @@ std::shared_ptr<ast::Include> NmodlDriver::parse_include(const std::string& name

program.swap(astRoot);
auto filename_node = std::shared_ptr<ast::String>(
new ast::String(std::string(1, '"') + name + std::string(1, '"')));
new ast::String(fmt::format("\"{}\"", name.string())));
return std::shared_ptr<ast::Include>(new ast::Include(filename_node, program->get_blocks()));
}

Expand Down
6 changes: 4 additions & 2 deletions src/parser/nmodl_driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* \brief Parser implementations
*/

#include <filesystem>
#include <string>
#include <unordered_map>

Expand Down Expand Up @@ -110,10 +111,11 @@ class NmodlDriver {
* \param loc optional location when \a filename is dictated
* by an `INCLUDE` NMODL directive.
*/
std::shared_ptr<ast::Program> parse_file(const std::string& filename,
std::shared_ptr<ast::Program> parse_file(const std::filesystem::path& filename,
const location* loc = nullptr);
//// parse file specified in nmodl include directive
std::shared_ptr<ast::Include> parse_include(const std::string& filename, const location& loc);
std::shared_ptr<ast::Include> parse_include(const std::filesystem::path& filename,
const location& loc);

void set_verbose(bool b) {
verbose = b;
Expand Down
7 changes: 1 addition & 6 deletions src/units/units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
* \brief Units processing while being processed from lexer and parser
*/

namespace {
constexpr std::size_t output_precision{8};
}

namespace nmodl {
namespace units {

Expand Down Expand Up @@ -314,10 +310,9 @@ void UnitTable::print_units_sorted(std::ostream& units_details) const {
table.end());
std::sort(sorted_elements.begin(), sorted_elements.end());
for (const auto& it: sorted_elements) {
units_details << fmt::format("{} {:.{}f}: {}\n",
units_details << fmt::format("{} {:g}: {}\n",
it.first,
it.second->get_factor(),
output_precision,
fmt::join(it.second->get_dimensions(), " "));
}
}
Expand Down
77 changes: 0 additions & 77 deletions src/utils/common_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,83 +25,6 @@
namespace nmodl {
namespace utils {

bool is_dir_exist(const std::string& path) {
struct stat info {};
if (stat(path.c_str(), &info) != 0) {
return false;
}
return (info.st_mode & S_IFDIR) != 0;
}

bool file_exists(const std::string& path) {
struct stat info {};
return stat(path.c_str(), &info) == 0;
}

bool file_is_abs(const std::string& path) {
#ifdef IS_WINDOWS
return path.find(":\\") != std::string::npos;
#else
return path.find(pathsep) == 0;
#endif
}

std::string cwd() {
std::array<char, MAXPATHLEN + 1> cwd{};
if (nullptr == getcwd(cwd.data(), MAXPATHLEN + 1)) {
throw std::runtime_error("working directory name too long");
}
return {cwd.data()};
}
bool make_path(const std::string& path) {
mode_t mode = 0755; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
int ret = mkdir(path.c_str(), mode);
if (ret == 0) {
return true;
}

switch (errno) {
case ENOENT:
// parent didn't exist, try to create it
{
auto const pos = path.find_last_of('/');
if (pos == std::string::npos) {
return false;
}
if (!make_path(path.substr(0, pos))) {
return false;
}
}
// now, try to create again
return 0 == mkdir(path.c_str(), mode);

case EEXIST:
// done!
return is_dir_exist(path);

default:
auto msg = "Can not create directory " + path;
throw std::runtime_error(msg);
}
}

TempFile::TempFile(std::string path)
: path_(std::move(path)) {
std::ofstream output(path_);
}

TempFile::TempFile(std::string path, const std::string& content)
: path_(std::move(path)) {
std::ofstream output(path_);
output << content;
}

TempFile::~TempFile() {
if (remove(path_.c_str()) != 0) {
perror("Cannot delete temporary file");
}
}

std::string generate_random_string(const int len, UseNumbersInString use_numbers) {
std::string s(len, 0);
constexpr std::size_t number_of_numbers{10};
Expand Down
48 changes: 0 additions & 48 deletions src/utils/common_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,62 +40,14 @@ bool is_last(Iter iter, const Cont& cont) {
return ((iter != cont.end()) && (next(iter) == cont.end()));
}

/// Given full file path, returns only name of the file
template <class T>
T base_name(T const& path, T const& delims = "/\\") {
return path.substr(path.find_last_of(delims) + 1);
}

/// Given the file name, returns name of the file without extension
template <class T>
T remove_extension(T const& filename) {
typename T::size_type const p(filename.find_last_of('.'));
return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
}

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
/// The character used by the operating system to separate pathname components
static constexpr char pathsep{'\\'};
/// The character conventionally used by the operating system to separate search path components
static constexpr char envpathsep{';'};
/// Maximum size of a directory path
static constexpr int max_path_len{_MAX_DIR};
#else
/// The character used by the operating system to separate pathname components
static constexpr char pathsep{'/'};
/// The character conventionally used by the operating system to separate search path components
static constexpr char envpathsep{':'};
/// Maximum size of a directory path
static constexpr int max_path_len{MAXPATHLEN};
#endif

/// Given directory path, create sub-directories
bool make_path(const std::string& path);

/// Check if directory with given path exists
bool is_dir_exist(const std::string& path);

/// Check if specified file path exists
bool file_exists(const std::string& path);

/// Check if specified file path is absolute
bool file_is_abs(const std::string& path);

/// get current working directory
std::string cwd();

/**
* \brief Create an empty file which is then removed when the C++ object is destructed
*/
struct TempFile {
explicit TempFile(std::string path);
TempFile(std::string path, const std::string& content);
~TempFile();

private:
std::string path_;
};

/// Enum to wrap bool variable to select if random string
/// should have numbers or not
enum UseNumbersInString : bool { WithNumbers = true, WithoutNumbers = false };
Expand Down
Loading

0 comments on commit 3b148fc

Please sign in to comment.