Mercurial > octave
diff libinterp/corefcn/load-path.cc @ 28953:dff830c84726
Add function "dir_encoding" to set a file encoding per directory (bug #49685).
* corefcn/load-path.h (load_path::read_dir_config): Add new function.
* corefcn/load-path.cc (load_path::read_dir_config): Add new function.
(load_path::add): Call read_dir_config on adding a new directory to the load
path.
* corefcn/input.h (input_system::dir_encoding, input_system::set_dir_encoding):
Add new functions. Add private unordered_map "m_dir_encoding".
* corefcn/input.cc (input_system::dir_encoding, input_system::set_dir_encoding):
Add new functions.
(base_reader, file_reader, input_reader): Add new constructors that accept an
encoding (use mfile_encoding by default). Add private property "m_encoding".
(load_path_dir): Static function to get the part of the directory that would
be added to the load path.
(Fdir_encoding): New function.
* corefcn/interpreter.cc (interpreter::chdir): Call load_path::read_dir_config.
* parse-tree/lex.h (lexer): Add new constructor that accepts an encoding.
* parse-tree/parse.h (parser): Add new constructor that accepts an encoding.
* parse-tree/oct-parse.yy (parse_fcn_file): Pass dir_encoding to parser.
* doc/interpreter/func.txi: Add docstring of function "dir_encoding" to manual.
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Fri, 18 Sep 2020 17:15:32 +0200 |
parents | 43ad651cf5a0 |
children | 02b97abbc6fc |
line wrap: on
line diff
--- a/libinterp/corefcn/load-path.cc Sat Oct 17 02:13:39 2020 -0700 +++ b/libinterp/corefcn/load-path.cc Fri Sep 18 17:15:32 2020 +0200 @@ -28,6 +28,7 @@ #endif #include <algorithm> +#include <cctype> #include "dir-ops.h" #include "file-ops.h" @@ -1084,6 +1085,8 @@ { if (fs.is_dir ()) { + read_dir_config (dir); + dir_info di (dir); if (at_end) @@ -1134,6 +1137,78 @@ } } + void + load_path::read_dir_config (const std::string& dir) const + { + // read file with directory configuration + std::string conf_file = dir + sys::file_ops::dir_sep_str () + + ".oct_config"; + + FILE* cfile = sys::fopen (conf_file, "rb"); + + if (! cfile) + { + // reset directory encoding + input_system& input_sys + = __get_input_system__ ("load_path::read_dir_config"); + + std::string enc_val = "delete"; + input_sys.set_dir_encoding (dir, enc_val); + return; + } + + unwind_action close_file ([cfile] (void) { fclose (cfile); }); + + // find line with character encoding and read it + bool eof = false; + const std::string enc_prop = "encoding"; + while (! eof) + { + std::string conf_str = octave_fgets (cfile, eof); + + // delete any preceeding whitespace + auto it = std::find_if_not (conf_str.begin (), conf_str.end (), + [] (unsigned char c) + { return std::isblank (c); }); + conf_str.erase (conf_str.begin (), it); + + // match identifier + if (conf_str.compare (0, enc_prop.size (), enc_prop) == 0) + { + // skip delimiter characters + size_t pos = conf_str.find_first_not_of (" \t=:", + enc_prop.size ()); + if (pos == std::string::npos) + continue; + + std::string enc_val = conf_str.substr (pos); + + // take alphanumeric and '-' characters + it = std::find_if_not (enc_val.begin (), enc_val.end (), + [] (unsigned char c) + { return std::isalnum (c) || c == '-'; }); + enc_val.erase(it, enc_val.end ()); + + if (enc_val.empty ()) + continue; + + // set encoding for this directory in input system + input_system& input_sys + = __get_input_system__ ("load_path::read_dir_config"); + input_sys.set_dir_encoding (dir, enc_val); + return; + } + } + + // reset directory encoding + input_system& input_sys + = __get_input_system__ ("load_path::read_dir_config"); + + std::string enc_val = "delete"; + input_sys.set_dir_encoding (dir, enc_val); + + } + bool load_path::is_package (const std::string& name) const {