Browse Source

[trac764] add -d output_dir option to log message compiler/message

Jelte Jansen 14 years ago
parent
commit
2f08899852

+ 41 - 8
src/lib/log/compiler/message.cc

@@ -85,6 +85,7 @@ usage() {
         "-h       Print this message and exit\n" <<
         "-h       Print this message and exit\n" <<
         "-v       Print the program version and exit\n" <<
         "-v       Print the program version and exit\n" <<
         "-p       Output python source instead of C++ ones\n" <<
         "-p       Output python source instead of C++ ones\n" <<
+        "-d <dir> Place output files in given directory\n" <<
         "\n" <<
         "\n" <<
         "<message-file> is the name of the input message file.\n";
         "<message-file> is the name of the input message file.\n";
 }
 }
@@ -249,14 +250,21 @@ writeClosingNamespace(ostream& output, const vector<string>& ns) {
 /// \param file Name of the message file. The source code is written to a file
 /// \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.
 ///     file of the same name but with a .py suffix.
 /// \param dictionary The dictionary holding the message definitions.
 /// \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
 /// \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.
 ///     python file/module works as implicit namespace as well.
 
 
 void
 void
-writePythonFile(const string& file, MessageDictionary& dictionary) {
+writePythonFile(const string& file, MessageDictionary& dictionary,
+                const char* output_directory) {
     Filename message_file(file);
     Filename message_file(file);
     Filename python_file(Filename(message_file.name()).useAsDefault(".py"));
     Filename python_file(Filename(message_file.name()).useAsDefault(".py"));
+    if (output_directory) {
+        python_file.setDirectory(output_directory);
+    }
 
 
     // Open the file for writing
     // Open the file for writing
     ofstream pyfile(python_file.fullName().c_str());
     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
 /// \param ns Namespace in which the definitions are to be placed.  An empty
 /// string indicates no namespace.
 /// string indicates no namespace.
 /// \param dictionary Dictionary holding the message definitions.
 /// \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
 void
 writeHeaderFile(const string& file, const vector<string>& ns_components,
 writeHeaderFile(const string& file, const vector<string>& ns_components,
-                MessageDictionary& dictionary)
+                MessageDictionary& dictionary, const char* output_directory)
 {
 {
     Filename message_file(file);
     Filename message_file(file);
     Filename header_file(Filename(message_file.name()).useAsDefault(".h"));
     Filename header_file(Filename(message_file.name()).useAsDefault(".h"));
+    if (output_directory) {
+        header_file.setDirectory(output_directory);
+    }
 
 
     // Text to use as the sentinels.
     // Text to use as the sentinels.
     string sentinel_text = sentinel(header_file);
     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_
 /// 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
 /// 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.
 /// 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
 void
 writeProgramFile(const string& file, const vector<string>& ns_components,
 writeProgramFile(const string& file, const vector<string>& ns_components,
-                 MessageDictionary& dictionary)
+                 MessageDictionary& dictionary,
+                 const char* output_directory)
 {
 {
     Filename message_file(file);
     Filename message_file(file);
     Filename program_file(Filename(message_file.name()).useAsDefault(".cc"));
     Filename program_file(Filename(message_file.name()).useAsDefault(".cc"));
+    if (output_directory) {
+        program_file.setDirectory(output_directory);
+    }
 
 
     // Open the output file for writing
     // Open the output file for writing
     ofstream ccfile(program_file.fullName().c_str());
     ofstream ccfile(program_file.fullName().c_str());
@@ -496,15 +522,20 @@ warnDuplicates(MessageReader& reader) {
 int
 int
 main(int argc, char* argv[]) {
 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
     optind = 1;             // Ensure we start a new scan
     int  opt;               // Value of the option
     int  opt;               // Value of the option
 
 
     bool doPython = false;
     bool doPython = false;
+    const char *output_directory = NULL;
 
 
     while ((opt = getopt(argc, argv, soptions)) != -1) {
     while ((opt = getopt(argc, argv, soptions)) != -1) {
         switch (opt) {
         switch (opt) {
+            case 'd':
+                output_directory = optarg;
+                break;
+
             case 'p':
             case 'p':
                 doPython = true;
                 doPython = true;
                 break;
                 break;
@@ -552,7 +583,7 @@ main(int argc, char* argv[]) {
             }
             }
 
 
             // Write the whole python file
             // Write the whole python file
-            writePythonFile(message_file, dictionary);
+            writePythonFile(message_file, dictionary, output_directory);
         } else {
         } else {
             // Get the namespace into which the message definitions will be put and
             // Get the namespace into which the message definitions will be put and
             // split it into components.
             // split it into components.
@@ -560,10 +591,12 @@ main(int argc, char* argv[]) {
                 splitNamespace(reader.getNamespace());
                 splitNamespace(reader.getNamespace());
 
 
             // Write the header file.
             // 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
             // 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.
         // Finally, warn of any duplicates encountered.

+ 12 - 0
src/lib/util/filename.cc

@@ -132,6 +132,18 @@ Filename::useAsDefault(const string& name) const {
     return (retstring);
     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 log
 } // namespace isc
 } // namespace isc

+ 3 - 0
src/lib/util/filename.h

@@ -86,6 +86,9 @@ public:
         return (directory_);
         return (directory_);
     }
     }
 
 
+    /// \return Set directory for the file
+    void setDirectory(const std::string& new_directory);
+
     /// \return Name of Given File Name
     /// \return Name of Given File Name
     std::string name() const {
     std::string name() const {
         return (name_);
         return (name_);

+ 37 - 0
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("/s/t/u", fname.useAsDefault("/s/t/u"));
     EXPECT_EQ("/a/b/c", fname.useAsDefault(""));
     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(""));
+}