summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-05-11 11:19:04 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-05-11 11:19:04 +0200
commitb42d9a345e2b02a1b17fa61b22117fbf7b187a31 (patch)
tree9c8ea0116ae35cf8df86e958495fc46563d095dd
parent8062e4e9a4998cfa44002afd2435ff9083e092e8 (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.cxx19
-rw-r--r--cli/options.cli6
-rw-r--r--cli/options.cxx13
-rw-r--r--cli/options.hxx4
-rw-r--r--cli/options.ixx6
-rw-r--r--cli/parser.cxx103
-rw-r--r--cli/parser.hxx7
-rw-r--r--doc/cli.13
-rw-r--r--doc/cli.xhtml4
-rw-r--r--tests/parser/driver.cxx3
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_;
diff --git a/doc/cli.1 b/doc/cli.1
index 67c397d..4794ec8 100644
--- a/doc/cli.1
+++ b/doc/cli.1
@@ -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>&lt;></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)