From b42d9a345e2b02a1b17fa61b22117fbf7b187a31 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 11 May 2012 11:19:04 +0200 Subject: Add support for -I option Now quote-included ("") option files are searched for relative to the including file while bracket-included (<>) ones are search in the directories specified with -I. --- cli/cli.cxx | 19 ++++++++++- cli/options.cli | 6 ++++ cli/options.cxx | 13 +++++++ cli/options.hxx | 4 +++ cli/options.ixx | 6 ++++ cli/parser.cxx | 103 ++++++++++++++++++++++++++++++++++++++------------------ cli/parser.hxx | 7 ++++ 7 files changed, 125 insertions(+), 33 deletions(-) (limited to 'cli') diff --git a/cli/cli.cxx b/cli/cli.cxx index b8314e6..c0b1142 100644 --- a/cli/cli.cxx +++ b/cli/cli.cxx @@ -3,6 +3,8 @@ // copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC // license : MIT; see accompanying LICENSE file +#include +#include #include // std::auto_ptr #include #include @@ -65,6 +67,19 @@ main (int argc, char* argv[]) return 1; } + // Extract include search paths. + // + parser::paths include_paths; + for (vector::const_iterator i (ops.include_path ().begin ()); + i != ops.include_path ().end (); ++i) + { + // Invalid path exception is handled below. + // + include_paths.push_back (semantics::path (*i)); + } + + // Open the input file. + // file = scan.next (); semantics::path path (file); @@ -77,7 +92,9 @@ main (int argc, char* argv[]) ifs.exceptions (ifstream::failbit | ifstream::badbit); - parser p; + // Parse and generate. + // + parser p (include_paths); auto_ptr unit (p.parse (ifs, path)); generator g; diff --git a/cli/options.cli b/cli/options.cli index 1462385..074e7a9 100644 --- a/cli/options.cli +++ b/cli/options.cli @@ -17,6 +17,12 @@ class options bool --help {"Print usage information and exit."}; bool --version {"Print version and exit."}; + std::vector --include-path | -I + { + "", + "Search for bracket-included (\cb{<>}) option files." + }; + std::string --output-dir | -o { "", diff --git a/cli/options.cxx b/cli/options.cxx index 2d45b05..a720a2a 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -551,6 +551,7 @@ options:: options () : help_ (), version_ (), + include_path_ (), output_dir_ (), generate_modifier_ (), generate_specifier_ (), @@ -595,6 +596,7 @@ options (int& argc, ::cli::unknown_mode arg) : help_ (), version_ (), + include_path_ (), output_dir_ (), generate_modifier_ (), generate_specifier_ (), @@ -642,6 +644,7 @@ options (int start, ::cli::unknown_mode arg) : help_ (), version_ (), + include_path_ (), output_dir_ (), generate_modifier_ (), generate_specifier_ (), @@ -689,6 +692,7 @@ options (int& argc, ::cli::unknown_mode arg) : help_ (), version_ (), + include_path_ (), output_dir_ (), generate_modifier_ (), generate_specifier_ (), @@ -738,6 +742,7 @@ options (int start, ::cli::unknown_mode arg) : help_ (), version_ (), + include_path_ (), output_dir_ (), generate_modifier_ (), generate_specifier_ (), @@ -783,6 +788,7 @@ options (::cli::scanner& s, ::cli::unknown_mode arg) : help_ (), version_ (), + include_path_ (), output_dir_ (), generate_modifier_ (), generate_specifier_ (), @@ -827,6 +833,9 @@ print_usage (::std::ostream& os) os << "--version Print version and exit." << ::std::endl; + os << "--include-path|-I Search for bracket-included ('<>') option" << ::std::endl + << " files." << ::std::endl; + os << "--output-dir|-o Write the generated files to instead of the" << ::std::endl << " current directory." << ::std::endl; @@ -937,6 +946,10 @@ struct _cli_options_map_init &::cli::thunk< options, bool, &options::help_ >; _cli_options_map_["--version"] = &::cli::thunk< options, bool, &options::version_ >; + _cli_options_map_["--include-path"] = + &::cli::thunk< options, std::vector, &options::include_path_ >; + _cli_options_map_["-I"] = + &::cli::thunk< options, std::vector, &options::include_path_ >; _cli_options_map_["--output-dir"] = &::cli::thunk< options, std::string, &options::output_dir_ >; _cli_options_map_["-o"] = diff --git a/cli/options.hxx b/cli/options.hxx index 8042669..748e7bb 100644 --- a/cli/options.hxx +++ b/cli/options.hxx @@ -356,6 +356,9 @@ class options const bool& version () const; + const std::vector& + include_path () const; + const std::string& output_dir () const; @@ -477,6 +480,7 @@ class options public: bool help_; bool version_; + std::vector include_path_; std::string output_dir_; bool generate_modifier_; bool generate_specifier_; diff --git a/cli/options.ixx b/cli/options.ixx index 05c9f9a..34efe21 100644 --- a/cli/options.ixx +++ b/cli/options.ixx @@ -208,6 +208,12 @@ version () const return this->version_; } +inline const std::vector& options:: +include_path () const +{ + return this->include_path_; +} + inline const std::string& options:: output_dir () const { diff --git a/cli/parser.cxx b/cli/parser.cxx index 8289fce..55090d4 100644 --- a/cli/parser.cxx +++ b/cli/parser.cxx @@ -3,6 +3,10 @@ // copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC // license : MIT; see accompanying LICENSE file +#include // stat +#include // stat +#include // stat + #include #include @@ -267,56 +271,91 @@ include_decl () } else { - // For now we only support inclusion relative to the current file. + path p; + // If this is a quote include, then include relative to the current + // file. // - path p (path_->directory () / f); - p.normalize (); - - // Detect and ignore multiple inclusions. + if (ik == includes::quote) + { + p = path_->directory () / f; + p.normalize (); + } + // Otherwise search the include directories (-I). // - path ap (p); - ap.absolute (); - ap.normalize (); - - include_map::iterator it (include_map_.find (ap)); - if (it == include_map_.end ()) + else { - cli_unit& n (root_->new_node (p, 1, 1)); - root_->new_edge (*cur_, n, ik, f); - include_map_[ap] = &n; + struct stat s; + for (paths::const_iterator i (include_paths_.begin ()); + i != include_paths_.end (); ++i) + { + p = *i / f; + p.normalize (); + + // Check that the file exist without checking for permissions, etc. + // + if (stat (p.string ().c_str (), &s) == 0 && S_ISREG (s.st_mode)) + break; - auto_restore new_cur (cur_, &n); - auto_restore new_path (path_, &p); + p.clear (); + } - ifstream ifs (p.string ().c_str ()); - if (ifs.is_open ()) + if (p.empty ()) { - ifs.exceptions (ifstream::failbit | ifstream::badbit); + cerr << *path_ << ':' << t.line () << ':' << t.column () << ": " + << "error: file '" << f << "' not found in any of the " + << "include search directories (-I)" << endl; + valid_ = false; + } + } - try + if (valid_) + { + // Detect and ignore multiple inclusions. + // + path ap (p); + ap.absolute (); + ap.normalize (); + + include_map::iterator it (include_map_.find (ap)); + if (it == include_map_.end ()) + { + cli_unit& n (root_->new_node (p, 1, 1)); + root_->new_edge (*cur_, n, ik, f); + include_map_[ap] = &n; + + auto_restore new_cur (cur_, &n); + auto_restore new_path (path_, &p); + + ifstream ifs (p.string ().c_str ()); + if (ifs.is_open ()) { - lexer l (ifs, p.string ()); - auto_restore new_lexer (lexer_, &l); + ifs.exceptions (ifstream::failbit | ifstream::badbit); + + try + { + lexer l (ifs, p.string ()); + auto_restore new_lexer (lexer_, &l); - def_unit (); + def_unit (); - if (!l.valid ()) + if (!l.valid ()) + valid_ = false; + } + catch (std::ios_base::failure const&) + { + cerr << p << ": error: read failure" << endl; valid_ = false; + } } - catch (std::ios_base::failure const&) + else { - cerr << p << ": error: read failure" << endl; + cerr << p << ": error: unable to open in read mode" << endl; valid_ = false; } } else - { - cerr << p << ": error: unable to open in read mode" << endl; - valid_ = false; - } + root_->new_edge (*cur_, *it->second, ik, f); } - else - root_->new_edge (*cur_, *it->second, ik, f); } } diff --git a/cli/parser.hxx b/cli/parser.hxx index 34d3450..f7f6d68 100644 --- a/cli/parser.hxx +++ b/cli/parser.hxx @@ -8,6 +8,7 @@ #include #include +#include #include // std::auto_ptr #include @@ -20,6 +21,10 @@ class lexer; class parser { public: + typedef std::vector paths; + + parser (paths const& include_paths): include_paths_ (include_paths) {} + struct invalid_input {}; std::auto_ptr @@ -76,6 +81,8 @@ private: bool outer = true); private: + paths const include_paths_; + bool valid_; semantics::path const* path_; -- cgit v1.1