Browse Source

[3516] Added sectioning in both python and c++ system messages tools

Francis Dupont 10 years ago
parent
commit
f2b1aad25d
2 changed files with 93 additions and 34 deletions
  1. 51 12
      tools/system_messages.cc
  2. 42 22
      tools/system_messages.py

+ 51 - 12
tools/system_messages.cc

@@ -45,6 +45,7 @@ typedef std::vector<std::string> lines_type;
 struct Details {
 struct Details {
     std::string text;
     std::string text;
     lines_type description;
     lines_type description;
+    std::string sname;
     std::string filename;
     std::string filename;
 };
 };
 
 
@@ -137,7 +138,11 @@ const std::string FILE_HEADER =
   </chapter>\n\
   </chapter>\n\
 \n\
 \n\
   <chapter id=\"messages\">\n\
   <chapter id=\"messages\">\n\
-    <title>Kea Log Messages</title>\n\
+    <title>Kea Log Messages</title>\n";
+
+// This is output one for each module. $M substitution token is the name.
+const std::string SECTION_HEADER = "  <section id=\"$M\">\n\
+    <title>$M Module</title>\n\
     <para>\n\
     <para>\n\
       <variablelist>\n";
       <variablelist>\n";
 
 
@@ -153,19 +158,24 @@ $D</para></listitem>\n\
 
 
 // A description may contain blank lines intended to separate
 // A description may contain blank lines intended to separate
 // paragraphs.  If so, each blank line is replaced by the following.
 // paragraphs.  If so, each blank line is replaced by the following.
-const std::string SEC_BLANK = "</para><para>";
+const std::string BLANK = "</para><para>";
 
 
 // The separator is copied to the output verbatim after each message except
 // The separator is copied to the output verbatim after each message except
 // the last.
 // the last.
 const std::string SEPARATOR = "";
 const std::string SEPARATOR = "";
 
 
 // The trailier is copied to the output verbatim after the last message.
 // The trailier is copied to the output verbatim after the last message.
-const std::string FILE_TRAILER =
+const std::string SECTION_TRAILER =
 "      </variablelist>\n\
 "      </variablelist>\n\
     </para>\n\
     </para>\n\
-  </chapter>\n\
+  </section>";
+
+// The trailier is copied to the output verbatim after the last section.
+const std::string FILE_TRAILER =
+"  </chapter>\n\
 </book>";
 </book>";
 
 
+
 /// Report an error and exit
 /// Report an error and exit
 void reportError(const std::string& filename, const std::string& what)
 void reportError(const std::string& filename, const std::string& what)
 {
 {
@@ -224,7 +234,7 @@ lines_type replaceBlankLines(const lines_type lines)
     lines_type result;
     lines_type result;
     for (lines_type::const_iterator l = lines.begin(); l != lines.end(); ++l) {
     for (lines_type::const_iterator l = lines.begin(); l != lines.end(); ++l) {
         if (l->empty()) {
         if (l->empty()) {
-            result.push_back(SEC_BLANK);
+            result.push_back(BLANK);
         } else {
         } else {
             result.push_back(*l);
             result.push_back(*l);
         }
         }
@@ -242,9 +252,16 @@ void printSeparator() {
     std::cout << SEPARATOR << "\n";
     std::cout << SEPARATOR << "\n";
 }
 }
 
 
+void printSectionHeader(const std::string& sname)
+{
+    // In the section name, replace "<" and ">" with XML-safe versions and
+    // substitute into the data.
+    std::cout << replaceShell(SECTION_HEADER, 'M', replaceTag(sname));
+}
+
 void printMessage(const std::string& msgid)
 void printMessage(const std::string& msgid)
 {
 {
-    //In the message ID, replace "<" and ">" with XML-safe versions and
+    // In the message ID, replace "<" and ">" with XML-safe versions and
     // substitute into the data.
     // substitute into the data.
     const std::string m0 = ID_MESSAGE;
     const std::string m0 = ID_MESSAGE;
     const std::string m1 = replaceShell(m0, 'I', replaceTag(msgid));
     const std::string m1 = replaceShell(m0, 'I', replaceTag(msgid));
@@ -274,6 +291,10 @@ void printMessage(const std::string& msgid)
     std::cout << replaceShell(m2, 'D', m3) << "\n";
     std::cout << replaceShell(m2, 'D', m3) << "\n";
 }
 }
 
 
+void printSectionTrailer() {
+    std::cout << SECTION_TRAILER << "\n";
+}
+
 void printTrailer() {
 void printTrailer() {
     std::cout << FILE_TRAILER << "\n";
     std::cout << FILE_TRAILER << "\n";
 }
 }
@@ -330,6 +351,7 @@ lines_type removeEmptyLeadingTrailing(lines_type lines)
     return retlines;
     return retlines;
 }
 }
 
 
+
 /// Add the current message ID and associated information to the global
 /// Add the current message ID and associated information to the global
 /// dictionary.  If a message with that ID already exists, loop appending
 /// dictionary.  If a message with that ID already exists, loop appending
 /// suffixes of the form "(n)" to it until one is found that doesn't.
 /// suffixes of the form "(n)" to it until one is found that doesn't.
@@ -367,6 +389,8 @@ void addToDictionary(const std::string& msgid,
     Details details;
     Details details;
     details.text = msgtext;
     details.text = msgtext;
     details.description = removeEmptyLeadingTrailing(desc);
     details.description = removeEmptyLeadingTrailing(desc);
+    size_t underscore = msgid.find_first_of('_');
+    details.sname = msgid.substr(0, underscore);
     details.filename = filename;
     details.filename = filename;
     dictionary.insert(std::pair<const std::string, Details>(key, details));
     dictionary.insert(std::pair<const std::string, Details>(key, details));
 }
 }
@@ -439,7 +463,6 @@ void processFileContent(const std::string& filename,
     }
     }
 }
 }
 
 
-
 /// Processes a file by reading it in and stripping out all comments and
 /// Processes a file by reading it in and stripping out all comments and
 /// and directives.  Leading and trailing blank lines in the file are removed
 /// and directives.  Leading and trailing blank lines in the file are removed
 /// and the remainder passed for message processing.
 /// and the remainder passed for message processing.
@@ -518,6 +541,7 @@ void processAllFiles(const boost::filesystem::path& root)
     }
     }
 }
 }
 
 
+
 void usage(char* progname)
 void usage(char* progname)
 {
 {
     std::cerr << "Usage: " << progname <<
     std::cerr << "Usage: " << progname <<
@@ -548,6 +572,8 @@ int main(int argc, char* argv[])
             }
             }
             fout.open(argv[0], std::ofstream::out | std::ofstream::trunc);
             fout.open(argv[0], std::ofstream::out | std::ofstream::trunc);
             std::cout.rdbuf(fout.rdbuf());
             std::cout.rdbuf(fout.rdbuf());
+            --argc;
+            ++argv;
         }
         }
     }
     }
 
 
@@ -570,15 +596,28 @@ int main(int argc, char* argv[])
 
 
     // Now just print out everything we've read (in alphabetical order).
     // Now just print out everything we've read (in alphabetical order).
     bool first = true;
     bool first = true;
+    std::string sname;
     printHeader();
     printHeader();
     for (dictionary_type::iterator it = dictionary.begin();
     for (dictionary_type::iterator it = dictionary.begin();
          it != dictionary.end();
          it != dictionary.end();
          ++it) {
          ++it) {
-         if (!first) {
+        if (sname.compare(it->second.sname) != 0) {
-             printSeparator();
+            if (!sname.empty()) {
-         }
+                printSectionTrailer();
-         first = false;
+                printSeparator();
-         printMessage(it->first);
+            }
+            sname = it->second.sname;
+            printSectionHeader(sname);
+            first = true;
+        }
+        if (!first) {
+            printSeparator();
+        }
+        first = false;
+        printMessage(it->first);
+    }
+    if (!sname.empty()) {
+        printSectionTrailer();
     }
     }
     printTrailer();
     printTrailer();
     exit(0);
     exit(0);

+ 42 - 22
tools/system_messages.py

@@ -57,7 +57,7 @@ dictionary = {}
 # illustration to make the structure clearer.)  The text of these section is:
 # illustration to make the structure clearer.)  The text of these section is:
 
 
 # Header - this is output before anything else.
 # Header - this is output before anything else.
-FILE_HEADER="""<?xml version="1.0" encoding="UTF-8"?>
+FILE_HEADER = """<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
 <!ENTITY mdash  "&#x2014;" >
 <!ENTITY mdash  "&#x2014;" >
@@ -119,10 +119,14 @@ FILE_HEADER="""<?xml version="1.0" encoding="UTF-8"?>
 
 
   <chapter id="messages">
   <chapter id="messages">
     <title>Kea Log Messages</title>
     <title>Kea Log Messages</title>
-    <para>
-      <variablelist>
 """
 """
 
 
+# This is output one for each module. $M substitution token is the name.
+SECTION_HEADER = """  <section id="$M">
+    <title>$M Module</title>
+    <para>
+      <variablelist>"""
+
 # This is output once for each message.  The string contains substitution
 # This is output once for each message.  The string contains substitution
 # tokens: $I is replaced by the message identification, $T by the message text,
 # tokens: $I is replaced by the message identification, $T by the message text,
 # and $D by the message description.
 # and $D by the message description.
@@ -133,18 +137,21 @@ $D
 </para></listitem>
 </para></listitem>
 </varlistentry>"""
 </varlistentry>"""
 
 
-# A description may contain blank lines intended to separate paragraphs.  If so,
+# A description may contain blank lines intended to separate
-# each blank line is replaced by the following.
+# paragraphs.  If so, each blank line is replaced by the following.
-SEC_BLANK = "</para><para>"
+BLANK = "</para><para>"
 
 
-# The separator is copied to the output verbatim after each message except
+# The separator is copied to the output verbatim after each message or
-# the last.
+# section except the last.
 SEPARATOR = ""
 SEPARATOR = ""
 
 
-# The trailier is copied to the output verbatim after the last message.
+# The trailer is copied to the output verbatim after the last message.
-FILE_TRAILER = """      </variablelist>
+SECTION_TRAILER = """      </variablelist>
     </para>
     </para>
-  </chapter>
+  </section>"""
+
+# The trailer is copied to the output verbatim after the last section.
+FILE_TRAILER = """  </chapter>
 </book>"""
 </book>"""
 
 
 
 
@@ -156,7 +163,6 @@ def reportError(filename, what):
     sys.exit(1)
     sys.exit(1)
 
 
 
 
-
 def replaceTag(string):
 def replaceTag(string):
     """Replaces the '<' and '>' in text about to be inserted into the template
     """Replaces the '<' and '>' in text about to be inserted into the template
        sections above with &lt; and &gt; to avoid problems with message text
        sections above with &lt; and &gt; to avoid problems with message text
@@ -166,8 +172,6 @@ def replaceTag(string):
     string2 = string1.replace(">", "&gt;")
     string2 = string1.replace(">", "&gt;")
     return string2
     return string2
 
 
-
-
 def replaceBlankLines(lines):
 def replaceBlankLines(lines):
     """Replaces blank lines in an array with the contents of the 'blank'
     """Replaces blank lines in an array with the contents of the 'blank'
        section.
        section.
@@ -175,14 +179,13 @@ def replaceBlankLines(lines):
     result = []
     result = []
     for l in lines:
     for l in lines:
         if len(l) == 0:
         if len(l) == 0:
-            result.append(SEC_BLANK)
+            result.append(BLANK)
         else:
         else:
             result.append(l)
             result.append(l)
 
 
     return result
     return result
 
 
 
 
-
 # Printing functions
 # Printing functions
 def printHeader():
 def printHeader():
     print(FILE_HEADER)
     print(FILE_HEADER)
@@ -190,6 +193,13 @@ def printHeader():
 def printSeparator():
 def printSeparator():
     print(SEPARATOR)
     print(SEPARATOR)
 
 
+def printSectionHeader(sname):
+    # In the section name, replace "<" and ">" with XML-safe versions and
+    # substitute into the data.
+    m = SECTION_HEADER.replace("$M", replaceTag(sname));
+
+    print(m)
+
 def printMessage(msgid):
 def printMessage(msgid):
     # In the message ID, replace "<" and ">" with XML-safe versions and
     # In the message ID, replace "<" and ">" with XML-safe versions and
     # substitute into the data.
     # substitute into the data.
@@ -210,11 +220,13 @@ def printMessage(msgid):
 
 
     print(m3)
     print(m3)
 
 
+def printSectionTrailer():
+    print(SECTION_TRAILER)
+
 def printTrailer():
 def printTrailer():
     print(FILE_TRAILER)
     print(FILE_TRAILER)
 
 
 
 
-
 def removeEmptyLeadingTrailing(lines):
 def removeEmptyLeadingTrailing(lines):
     """Removes leading and trailing empty lines.
     """Removes leading and trailing empty lines.
 
 
@@ -259,7 +271,6 @@ def removeEmptyLeadingTrailing(lines):
     return retlines
     return retlines
 
 
 
 
-
 def addToDictionary(msgid, msgtext, desc, filename):
 def addToDictionary(msgid, msgtext, desc, filename):
     """Add the current message ID and associated information to the global
     """Add the current message ID and associated information to the global
        dictionary.  If a message with that ID already exists, loop appending
        dictionary.  If a message with that ID already exists, loop appending
@@ -269,6 +280,7 @@ def addToDictionary(msgid, msgtext, desc, filename):
        msgid        Message ID
        msgid        Message ID
        msgtext      Message text
        msgtext      Message text
        desc         Message description
        desc         Message description
+       sname        Section name (part before the first _ of the ID)
        filename     File from which the message came.  Currently this is
        filename     File from which the message came.  Currently this is
                     not used, but a future enhancement may wish to include the
                     not used, but a future enhancement may wish to include the
                     name of the message file in the messages manual.
                     name of the message file in the messages manual.
@@ -287,13 +299,14 @@ def addToDictionary(msgid, msgtext, desc, filename):
     # add everything into a subdictionary which is then added to the main
     # add everything into a subdictionary which is then added to the main
     # one.
     # one.
     details = {}
     details = {}
+    words = re.split("_", msgid)
     details['text'] = msgtext
     details['text'] = msgtext
     details['description'] = removeEmptyLeadingTrailing(desc)
     details['description'] = removeEmptyLeadingTrailing(desc)
+    details['sname'] = words[0]
     details['filename'] = filename
     details['filename'] = filename
     dictionary[msgid] = details
     dictionary[msgid] = details
 
 
 
 
-
 def processFileContent(filename, lines):
 def processFileContent(filename, lines):
     """Processes file content.  Messages and descriptions are identified and
     """Processes file content.  Messages and descriptions are identified and
        added to a dictionary (keyed by message ID).  If the key already exists,
        added to a dictionary (keyed by message ID).  If the key already exists,
@@ -349,7 +362,6 @@ def processFileContent(filename, lines):
         addToDictionary(msgid, msgtext, description, filename)
         addToDictionary(msgid, msgtext, description, filename)
 
 
 
 
-
 def processFile(filename):
 def processFile(filename):
     """Processes a file by reading it in and stripping out all comments and
     """Processes a file by reading it in and stripping out all comments and
        and directives.  Leading and trailing blank lines in the file are removed
        and directives.  Leading and trailing blank lines in the file are removed
@@ -371,7 +383,6 @@ def processFile(filename):
     processFileContent(filename, lines)
     processFileContent(filename, lines)
 
 
 
 
-
 def processAllFiles(root):
 def processAllFiles(root):
     """Iterates through all files in the tree starting at the given root and
     """Iterates through all files in the tree starting at the given root and
        calls processFile for all .mes files found.
        calls processFile for all .mes files found.
@@ -410,11 +421,20 @@ if __name__ == "__main__":
     processAllFiles(args[0])
     processAllFiles(args[0])
 
 
     # Now just print out everything we've read (in alphabetical order).
     # Now just print out everything we've read (in alphabetical order).
-    count = 1
+    sname = ""
     printHeader()
     printHeader()
     for msgid in sorted(dictionary):
     for msgid in sorted(dictionary):
+        if dictionary[msgid]['sname'] != sname:
+            if sname != "":
+               printSectionTrailer()
+               printSeparator()
+            sname = dictionary[msgid]['sname']
+            printSectionHeader(sname)
+            count = 1
         if count > 1:
         if count > 1:
             printSeparator()
             printSeparator()
         count = count + 1
         count = count + 1
         printMessage(msgid)
         printMessage(msgid)
+    if sname !="":
+        printSectionTrailer()
     printTrailer()
     printTrailer()