From 2f088998525f389391efb86ac4e917174449df85 Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Mon, 4 Jul 2011 14:46:19 +0200 Subject: [trac764] add -d output_dir option to log message compiler/message --- src/lib/log/compiler/message.cc | 49 +++++++++++++++++++++++++++------ src/lib/util/filename.cc | 12 ++++++++ src/lib/util/filename.h | 3 ++ src/lib/util/tests/filename_unittest.cc | 37 +++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/lib/log/compiler/message.cc b/src/lib/log/compiler/message.cc index 68335dc35a..872921c133 100644 --- a/src/lib/log/compiler/message.cc +++ b/src/lib/log/compiler/message.cc @@ -85,6 +85,7 @@ usage() { "-h Print this message and exit\n" << "-v Print the program version and exit\n" << "-p Output python source instead of C++ ones\n" << + "-d Place output files in given directory\n" << "\n" << " is the name of the input message file.\n"; } @@ -249,14 +250,21 @@ writeClosingNamespace(ostream& output, const vector& ns) { /// \param file Name of the message file. The source code is written to a file /// file of the same name but with a .py suffix. /// \param dictionary The dictionary holding the message definitions. +/// \param output_directory if not null NULL, output files are written +/// to the given directory. If NULL, they are written to the current +/// working directory. /// /// \note We don't use the namespace as in C++. We don't need it, because /// python file/module works as implicit namespace as well. void -writePythonFile(const string& file, MessageDictionary& dictionary) { +writePythonFile(const string& file, MessageDictionary& dictionary, + const char* output_directory) { Filename message_file(file); Filename python_file(Filename(message_file.name()).useAsDefault(".py")); + if (output_directory) { + python_file.setDirectory(output_directory); + } // Open the file for writing ofstream pyfile(python_file.fullName().c_str()); @@ -291,13 +299,19 @@ writePythonFile(const string& file, MessageDictionary& dictionary) { /// \param ns Namespace in which the definitions are to be placed. An empty /// string indicates no namespace. /// \param dictionary Dictionary holding the message definitions. +/// \param output_directory if not null NULL, output files are written +/// to the given directory. If NULL, they are written to the current +/// working directory. void writeHeaderFile(const string& file, const vector& ns_components, - MessageDictionary& dictionary) + MessageDictionary& dictionary, const char* output_directory) { Filename message_file(file); Filename header_file(Filename(message_file.name()).useAsDefault(".h")); + if (output_directory) { + header_file.setDirectory(output_directory); + } // Text to use as the sentinels. string sentinel_text = sentinel(header_file); @@ -382,13 +396,25 @@ replaceNonAlphaNum(char c) { /// optimisation is done at link-time, not compiler-time. In this it _may_ /// decide to remove the initializer object because of a lack of references /// to it. But until BIND-10 is ported to Windows, we won't know. - +/// +/// \param file Name of the message file. The header file is written to a +/// file of the same name but with a .h suffix. +/// \param ns Namespace in which the definitions are to be placed. An empty +/// string indicates no namespace. +/// \param dictionary Dictionary holding the message definitions. +/// \param output_directory if not null NULL, output files are written +/// to the given directory. If NULL, they are written to the current +/// working directory. void writeProgramFile(const string& file, const vector& ns_components, - MessageDictionary& dictionary) + MessageDictionary& dictionary, + const char* output_directory) { Filename message_file(file); Filename program_file(Filename(message_file.name()).useAsDefault(".cc")); + if (output_directory) { + program_file.setDirectory(output_directory); + } // Open the output file for writing ofstream ccfile(program_file.fullName().c_str()); @@ -496,15 +522,20 @@ warnDuplicates(MessageReader& reader) { int main(int argc, char* argv[]) { - const char* soptions = "hvp"; // Short options + const char* soptions = "hvpd:"; // Short options optind = 1; // Ensure we start a new scan int opt; // Value of the option bool doPython = false; + const char *output_directory = NULL; while ((opt = getopt(argc, argv, soptions)) != -1) { switch (opt) { + case 'd': + output_directory = optarg; + break; + case 'p': doPython = true; break; @@ -552,7 +583,7 @@ main(int argc, char* argv[]) { } // Write the whole python file - writePythonFile(message_file, dictionary); + writePythonFile(message_file, dictionary, output_directory); } else { // Get the namespace into which the message definitions will be put and // split it into components. @@ -560,10 +591,12 @@ main(int argc, char* argv[]) { splitNamespace(reader.getNamespace()); // Write the header file. - writeHeaderFile(message_file, ns_components, dictionary); + writeHeaderFile(message_file, ns_components, dictionary, + output_directory); // Write the file that defines the message symbols and text - writeProgramFile(message_file, ns_components, dictionary); + writeProgramFile(message_file, ns_components, dictionary, + output_directory); } // Finally, warn of any duplicates encountered. diff --git a/src/lib/util/filename.cc b/src/lib/util/filename.cc index 1f2e5db43c..70e054dd72 100644 --- a/src/lib/util/filename.cc +++ b/src/lib/util/filename.cc @@ -132,6 +132,18 @@ Filename::useAsDefault(const string& name) const { return (retstring); } +void +Filename::setDirectory(const std::string& new_directory) { + directory_ = new_directory; + // append '/' if necessary + size_t sep = directory_.rfind('/'); + if (sep == std::string::npos || sep < directory_.size() - 1) { + directory_ += "/"; + } + // and regenerate the full name + full_name_ = directory_ + name_ + extension_; +} + } // namespace log } // namespace isc diff --git a/src/lib/util/filename.h b/src/lib/util/filename.h index 984ecb08d5..1fcbbc7e4d 100644 --- a/src/lib/util/filename.h +++ b/src/lib/util/filename.h @@ -86,6 +86,9 @@ public: return (directory_); } + /// \return Set directory for the file + void setDirectory(const std::string& new_directory); + /// \return Name of Given File Name std::string name() const { return (name_); diff --git a/src/lib/util/tests/filename_unittest.cc b/src/lib/util/tests/filename_unittest.cc index 33e6456413..c6706d6970 100644 --- a/src/lib/util/tests/filename_unittest.cc +++ b/src/lib/util/tests/filename_unittest.cc @@ -177,3 +177,40 @@ TEST_F(FilenameTest, UseAsDefault) { EXPECT_EQ("/s/t/u", fname.useAsDefault("/s/t/u")); EXPECT_EQ("/a/b/c", fname.useAsDefault("")); } + +TEST_F(FilenameTest, setDirectory) { + Filename fname("a.b"); + EXPECT_EQ("", fname.directory()); + EXPECT_EQ("a.b", fname.fullName()); + EXPECT_EQ("a.b", fname.expandWithDefault("")); + + fname.setDirectory("/just/some/dir/"); + EXPECT_EQ("/just/some/dir/", fname.directory()); + EXPECT_EQ("/just/some/dir/a.b", fname.fullName()); + EXPECT_EQ("/just/some/dir/a.b", fname.expandWithDefault("")); + + fname.setDirectory("/just/some/dir"); + EXPECT_EQ("/just/some/dir/", fname.directory()); + EXPECT_EQ("/just/some/dir/a.b", fname.fullName()); + EXPECT_EQ("/just/some/dir/a.b", fname.expandWithDefault("")); + + fname.setDirectory("/"); + EXPECT_EQ("/", fname.directory()); + EXPECT_EQ("/a.b", fname.fullName()); + EXPECT_EQ("/a.b", fname.expandWithDefault("")); + + fname.setDirectory(""); + EXPECT_EQ("/", fname.directory()); + EXPECT_EQ("/a.b", fname.fullName()); + EXPECT_EQ("/a.b", fname.expandWithDefault("")); + + fname = Filename("/first/a.b"); + EXPECT_EQ("/first/", fname.directory()); + EXPECT_EQ("/first/a.b", fname.fullName()); + EXPECT_EQ("/first/a.b", fname.expandWithDefault("")); + + fname.setDirectory("/just/some/dir"); + EXPECT_EQ("/just/some/dir/", fname.directory()); + EXPECT_EQ("/just/some/dir/a.b", fname.fullName()); + EXPECT_EQ("/just/some/dir/a.b", fname.expandWithDefault("")); +} -- cgit v1.2.3