diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2012-05-11 11:19:04 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2012-05-11 11:19:04 +0200 |
commit | b42d9a345e2b02a1b17fa61b22117fbf7b187a31 (patch) | |
tree | 9c8ea0116ae35cf8df86e958495fc46563d095dd | |
parent | 8062e4e9a4998cfa44002afd2435ff9083e092e8 (diff) |
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.
-rw-r--r-- | cli/cli.cxx | 19 | ||||
-rw-r--r-- | cli/options.cli | 6 | ||||
-rw-r--r-- | cli/options.cxx | 13 | ||||
-rw-r--r-- | cli/options.hxx | 4 | ||||
-rw-r--r-- | cli/options.ixx | 6 | ||||
-rw-r--r-- | cli/parser.cxx | 103 | ||||
-rw-r--r-- | cli/parser.hxx | 7 | ||||
-rw-r--r-- | doc/cli.1 | 3 | ||||
-rw-r--r-- | doc/cli.xhtml | 4 | ||||
-rw-r--r-- | tests/parser/driver.cxx | 3 |
10 files changed, 134 insertions, 34 deletions
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 <vector> +#include <string> #include <memory> // std::auto_ptr #include <fstream> #include <iostream> @@ -65,6 +67,19 @@ main (int argc, char* argv[]) return 1; } + // Extract include search paths. + // + parser::paths include_paths; + for (vector<string>::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<semantics::cli_unit> 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<std::string> --include-path | -I + { + "<dir>", + "Search <dir> for bracket-included (\cb{<>}) option files." + }; + std::string --output-dir | -o { "<dir>", 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 <dir> Search <dir> for bracket-included ('<>') option" << ::std::endl + << " files." << ::std::endl; + os << "--output-dir|-o <dir> Write the generated files to <dir> 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<std::string>, &options::include_path_ >; + _cli_options_map_["-I"] = + &::cli::thunk< options, std::vector<std::string>, &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<std::string>& + include_path () const; + const std::string& output_dir () const; @@ -477,6 +480,7 @@ class options public: bool help_; bool version_; + std::vector<std::string> 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<std::string>& 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 <unistd.h> // stat +#include <sys/types.h> // stat +#include <sys/stat.h> // stat + #include <fstream> #include <iostream> @@ -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<cli_unit> (p, 1, 1)); - root_->new_edge<cli_includes> (*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<cli_unit> new_cur (cur_, &n); - auto_restore<path const> 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<cli_unit> (p, 1, 1)); + root_->new_edge<cli_includes> (*cur_, n, ik, f); + include_map_[ap] = &n; + + auto_restore<cli_unit> new_cur (cur_, &n); + auto_restore<path const> new_path (path_, &p); + + ifstream ifs (p.string ().c_str ()); + if (ifs.is_open ()) { - lexer l (ifs, p.string ()); - auto_restore<lexer> new_lexer (lexer_, &l); + ifs.exceptions (ifstream::failbit | ifstream::badbit); + + try + { + lexer l (ifs, p.string ()); + auto_restore<lexer> 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<cli_includes> (*cur_, *it->second, ik, f); } - else - root_->new_edge<cli_includes> (*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 <map> #include <string> +#include <vector> #include <memory> // std::auto_ptr #include <istream> @@ -20,6 +21,10 @@ class lexer; class parser { public: + typedef std::vector<semantics::path> paths; + + parser (paths const& include_paths): include_paths_ (include_paths) {} + struct invalid_input {}; std::auto_ptr<semantics::cli_unit> @@ -76,6 +81,8 @@ private: bool outer = true); private: + paths const include_paths_; + bool valid_; semantics::path const* path_; @@ -67,6 +67,9 @@ Print usage information and exit\. .IP "\fB--version\fP" Print version and exit\. +.IP "\fB--include-path\fP|\fB-I\fP \fIdir\fP" +Search \fIdir\fP for bracket-included (\fB<>\fP) option files\. + .IP "\fB--output-dir\fP|\fB-o\fP \fIdir\fP" Write the generated files to \fIdir\fP instead of the current directory\. diff --git a/doc/cli.xhtml b/doc/cli.xhtml index fdcde80..1ac88b0 100644 --- a/doc/cli.xhtml +++ b/doc/cli.xhtml @@ -90,6 +90,10 @@ <dt><code><b>--version</b></code></dt> <dd>Print version and exit.</dd> + <dt><code><b>--include-path</b></code>|<code><b>-I</b></code> <i>dir</i></dt> + <dd>Search <i>dir</i> for bracket-included (<code><b><></b></code>) option + files.</dd> + <dt><code><b>--output-dir</b></code>|<code><b>-o</b></code> <i>dir</i></dt> <dd>Write the generated files to <i>dir</i> instead of the current directory.</dd> diff --git a/tests/parser/driver.cxx b/tests/parser/driver.cxx index 5f91564..bc963b5 100644 --- a/tests/parser/driver.cxx +++ b/tests/parser/driver.cxx @@ -29,7 +29,8 @@ main (int argc, char* argv[]) ifs.exceptions (ifstream::failbit | ifstream::badbit); ifs.open (path.string ().c_str ()); - parser p; + parser::paths include_paths; + parser p (include_paths); p.parse (ifs, path); } catch (semantics::invalid_path const& e) |