[boost-doc-zh commit] r236 - boost/tools/regression

  • From: codesite-noreply@xxxxxxxxxx
  • To: boost-doc-zh-notify@xxxxxxxxxxxxx
  • Date: Sun, 05 Apr 2009 15:24:24 +0000

Author: alai04
Date: Sun Apr  5 07:36:05 2009
New Revision: 236

Added:
   trunk/tools/regression/src/process_jam_log.py
   trunk/tools/regression/test/Jamfile.v2
   trunk/tools/regression/test/test-boost-build/
   trunk/tools/regression/test/test-boost-build/ignored_rc/
   trunk/tools/regression/test/test-boost-build/ignored_rc/ignored_rc.jam
   trunk/tools/regression/test/test-boost-build/ignored_rc/recognized_rc.jam
   trunk/tools/regression/test/test-boost-build/missing_dependencies/
trunk/tools/regression/test/test-boost-build/missing_dependencies/Jamfile.v2
   trunk/tools/regression/test/test-boost-build/missing_dependencies/lib/
trunk/tools/regression/test/test-boost-build/missing_dependencies/lib/Jamfile.v2 trunk/tools/regression/test/test-boost-build/missing_dependencies/lib/lib.cpp trunk/tools/regression/test/test-boost-build/missing_dependencies/test.cpp
   trunk/tools/regression/xsl_reports/boost_wide_report.py
   trunk/tools/regression/xsl_reports/boostbook_report.py
   trunk/tools/regression/xsl_reports/build_results.sh
   trunk/tools/regression/xsl_reports/email_maintainers.py
   trunk/tools/regression/xsl_reports/empty_expected_results.xml
   trunk/tools/regression/xsl_reports/make_snapshot.py
   trunk/tools/regression/xsl_reports/report.py
   trunk/tools/regression/xsl_reports/test/
   trunk/tools/regression/xsl_reports/test/common.py
   trunk/tools/regression/xsl_reports/test/expected_results.xml
   trunk/tools/regression/xsl_reports/test/generate_test_results.py
   trunk/tools/regression/xsl_reports/test/generate_test_results_v1.py
   trunk/tools/regression/xsl_reports/test/restrict_to_library.xsl
   trunk/tools/regression/xsl_reports/test/run_notes_regression.py
   trunk/tools/regression/xsl_reports/test/run_v1.py
   trunk/tools/regression/xsl_reports/test/test.py
   trunk/tools/regression/xsl_reports/test/test_boost_wide_report.py
   trunk/tools/regression/xsl_reports/test_results.xsd
   trunk/tools/regression/xsl_reports/utils/
   trunk/tools/regression/xsl_reports/utils/__init__.py
   trunk/tools/regression/xsl_reports/utils/accept_args.py
   trunk/tools/regression/xsl_reports/utils/char_translation_table.py
   trunk/tools/regression/xsl_reports/utils/check_existance.py
   trunk/tools/regression/xsl_reports/utils/checked_system.py
   trunk/tools/regression/xsl_reports/utils/libxslt.py
   trunk/tools/regression/xsl_reports/utils/log.py
   trunk/tools/regression/xsl_reports/utils/makedirs.py
   trunk/tools/regression/xsl_reports/utils/rename.py
   trunk/tools/regression/xsl_reports/utils/send_mail.py
   trunk/tools/regression/xsl_reports/utils/sourceforge.py
   trunk/tools/regression/xsl_reports/utils/tar.py
   trunk/tools/regression/xsl_reports/utils/zip.py
   trunk/tools/regression/xsl_reports/xsl/add_expected_results.xsl
   trunk/tools/regression/xsl_reports/xsl/common.xsl
   trunk/tools/regression/xsl_reports/xsl/issues_page.xsl
   trunk/tools/regression/xsl_reports/xsl/links_page.xsl
   trunk/tools/regression/xsl_reports/xsl/produce_expected_results.xsl
   trunk/tools/regression/xsl_reports/xsl/result_page.xsl
   trunk/tools/regression/xsl_reports/xsl/summary_page.xsl
   trunk/tools/regression/xsl_reports/xsl/test/
   trunk/tools/regression/xsl_reports/xsl/test/test_re_match.xml
   trunk/tools/regression/xsl_reports/xsl/test/test_re_match.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/add_expected_results.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/boostbook_log.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/common.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/dump_toolsets.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/expected_to_1_33_format.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/issues_page.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/links_page.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/produce_expected_results.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/result_page.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/runners.xsl
   trunk/tools/regression/xsl_reports/xsl/v2/summary_page.xsl
Removed:
   trunk/tools/regression/doc/instructions.html
Modified:
   trunk/tools/regression/doc/index.html
   trunk/tools/regression/doc/library_status.html
   trunk/tools/regression/src/collect_and_upload_logs.py
   trunk/tools/regression/src/compiler_status.cpp
   trunk/tools/regression/src/detail/tiny_xml.cpp
   trunk/tools/regression/src/detail/tiny_xml.hpp
   trunk/tools/regression/src/detail/tiny_xml_test.cpp
   trunk/tools/regression/src/detail/tiny_xml_test.txt
   trunk/tools/regression/src/library_status.cpp
   trunk/tools/regression/src/library_test.bat
   trunk/tools/regression/src/library_test_all.sh
   trunk/tools/regression/src/process_jam_log.cpp
   trunk/tools/regression/src/regression-logs.pl
   trunk/tools/regression/src/regression.py
   trunk/tools/regression/src/run.py
   trunk/tools/regression/src/smoke.py
   trunk/tools/regression/test/compile-fail~fail.cpp
   trunk/tools/regression/test/compile-fail~pass.cpp
   trunk/tools/regression/test/compile~fail.cpp
   trunk/tools/regression/test/compile~pass.cpp
   trunk/tools/regression/test/compile~warn.cpp
   trunk/tools/regression/test/run-fail~compile-fail.cpp
   trunk/tools/regression/test/run-fail~fail-warn.cpp
   trunk/tools/regression/test/run-fail~fail.cpp
   trunk/tools/regression/test/run-fail~pass.cpp
   trunk/tools/regression/test/run-fail~warn.cpp
   trunk/tools/regression/test/run~compile-fail.cpp
   trunk/tools/regression/test/run~fail-note.cpp
   trunk/tools/regression/test/run~fail-warn.cpp
   trunk/tools/regression/test/run~fail.cpp
   trunk/tools/regression/test/run~note.cpp
   trunk/tools/regression/test/run~pass.cpp
   trunk/tools/regression/test/run~warn-note.cpp
   trunk/tools/regression/test/run~warn.cpp
   trunk/tools/regression/test/test-cases/Huber2629/bjam.log
   trunk/tools/regression/test/test-cases/Huber2629/expected/results.xml
   trunk/tools/regression/test/test-cases/general/expected/results.xml
   trunk/tools/regression/test/test-cases/incremental/bjam.log
   trunk/tools/regression/test/test-cases/incremental/bjam.log.1
   trunk/tools/regression/test/test-cases/incremental/expected/results.xml
   trunk/tools/regression/test/test.bat
   trunk/tools/regression/test/test.py

Log:
boost/tools/regression

Modified: trunk/tools/regression/doc/index.html
==============================================================================
--- trunk/tools/regression/doc/index.html       (original)
+++ trunk/tools/regression/doc/index.html       Sun Apr  5 07:36:05 2009
@@ -1,46 +1,40 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
-
-<html xmlns="http://www.w3.org/1999/xhtml";>
-<head>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml";><head>
   <meta http-equiv="Content-Language" content="en-us" />
-  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
-  <link rel="stylesheet" type="text/css" href=
-  "../../../doc/html/boostbook.css" />
-
-  <title>Regression Test Reporting Tools</title>
-</head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <link rel="stylesheet" type="text/css" href="../../../doc/html/boostbook.css" />

+  <title>Regression Test Reporting Tools</title></head>
 <body>
-  <h1><img src="../../../boost.png" alt="boost.png (6897 bytes)" align=
-  "center" width="277" height="86" /> Regression Test Reporting Tools</h1>
+ <h1><img src="../../../boost.png" alt="boost.png (6897 bytes)" align="middle" height="86" width="277" /> Regression Test Reporting Tools</h1>

-  <p>Boost regression testing uses <a href=
-  "../../build/index.html">Boost.Build</a> to run the actual builds and
+ <p>Boost regression testing uses <a href="../../build/index.html">Boost.Build</a> to run the actual builds and
   tests. A separate set of tools is used to generate the actual status
-  reports.</p>
+ reports.<br />Boost 回归测试使用 <a href="../../build/index.html">Boost.Build</a> 来运行实际的构建和测试。一组独 立的工具集用于生成实际的状态报告。</p>

   <ul>
- <li><a href="instructions.html">Instructions</a> for running the regression
-    tests</li>
+ <li><a href="http://beta.boost.org/development/running_regression_tests.html";>Instructions</a>
+    for running the regression tests as part of the published regression
+ tests are available at the Boost web site.<br />运行回归测试的 <a href="http://beta.boost.org/development/running_regression_tests.html";>指令 </a>,作为发布的回归测试的一部分,可在 Boost 网站上找到。</li>
+
     <li><a href="../src/process_jam_log.cpp">process_jam_log.cpp</a> -
     Processes the bjam outputs, creating a file named test_log.xml for each
-    test encountered.</li>
-
-    <li><a href="../src/compiler_status.cpp">compiler_status.cpp</a> -
-    Generates HTML status tables from test_log.xml and other files.</li>
+ test encountered.<br /><a href="../src/process_jam_log.cpp">process_jam_log.cpp</a> - + 处理 bjam 的输出,为每个测试创建一个名为 test_log.xml 的文件。 </li><li><a href="../src/compiler_status.cpp">compiler_status.cpp</a> - + Generates HTML status tables from test_log.xml and other files.<br /><a href="../src/compiler_status.cpp">compiler_status.cpp</a> -
+    从 test_log.xml 和其它文件生成 HTML 的状态表格。</li>

<li><a href="../build/Jamfile.v2">Jamfile.v2</a> - Builds process_jam_log
-    and compiler_status executables.</li>
+ and compiler_status executables.<br /><a href="../build/Jamfile.v2">Jamfile.v2</a> - 构建 process_jam_log 和 compiler_status 可执行文件。</li>

<li><a href="library_status.html">Library Status</a> - Runs test programs
     for one or all boost libraries on your local installation and generates
     complete tables to show which combinations of libraries, compilers,
-    compiler settings pass and fail at your local installation.</li>
+ compiler settings pass and fail at your local installation.<br /><a href="library_status.html">Library Status</a> - 在你的本地安装处为一个或所 有 boost 库运行测试程序,并生成完整的表格来展示,在你的本地安装上,有哪些 库、编译器以及编译器设置的组合通过或不能通过测试。</li>
   </ul>
   <hr />

-  <p>Revised $Date: 2007-11-25 14:36:19 -0500 (Sun, 25 Nov 2007) $</p>
+  <p>Revised $Date: 2008-12-15 07:16:41 -0500 (Mon, 15 Dec 2008) $</p>

   <p>Copyright Beman Dawes 2003.</p>

@@ -48,7 +42,5 @@

   <p>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
-  copy at <a href=
-  "http://www.boost.org/LICENSE_1_0.txt";>www.boost.org/LICENSE_1_0.txt</a>)</p>
-</body>
-</html>
\ No newline at end of file
+ copy at <a href="http://www.boost.org/LICENSE_1_0.txt";>www.boost.org/LICENSE_1_0.txt</a>)</p>
+</body></html>
\ No newline at end of file

Modified: trunk/tools/regression/doc/library_status.html
==============================================================================
--- trunk/tools/regression/doc/library_status.html      (original)
+++ trunk/tools/regression/doc/library_status.html      Sun Apr  5 07:36:05 2009
@@ -1,64 +1,60 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
-
-<html xmlns="http://www.w3.org/1999/xhtml";>
-<head>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml";><head>
   <meta http-equiv="Content-Language" content="en-us" />
-  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
-  <link rel="stylesheet" type="text/css" href=
-  "../../../doc/html/boostbook.css" />
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <link rel="stylesheet" type="text/css" href="../../../doc/html/boostbook.css" />

-  <title>Libary Status</title>
-  <style type="text/css">
+
+  <title>Libary Status</title><style type="text/css">
 /*<![CDATA[*/
   span.c3 {color: #FF0000; font-style: italic}
   a.c2 {font-style: italic}
   td.c1 {font-style: italic}
   /*]]>*/
-  </style>
-</head>
+  </style></head>
+

 <body>
   <table border="0">
-    <tr>
-      <td><img border="0" src="../../../boost.png" width="277" height="86"
-      alt="boost.png (6897 bytes)" /></td>
+    <tbody><tr>
+ <td><img src="../../../boost.png" alt="boost.png (6897 bytes)" border="0" height="86" width="277" /></td>

       <td>
         <h1>Generating Library Status Tables</h1>
       </td>
     </tr>
-  </table>
+  </tbody></table>

- <h3>Purpose</h3>Any time one considers using a library as large and complex + <h3>Purpose 目的</h3>Any time one considers using a library as large and complex
   as the Boost libraries, he must have a way of validating the the library
   functions in his environment. This should be done when the library is
   installed and anytime questions are raised regarding its applicabililty
-  and/or its usage.
+ and/or its usage.<br />任何时候,如果一个人想使用象 Boost 库如此巨大而复 杂的库时,他都必须有办法在他的运行环境中验证这些库函数。当库安装好以后,或者 在使用时出现问题时,这些验证工作都是要做的。

   <p>The procedures described here permit a user to run any combination of
tests on any or all libraries and generate a set of convenient tables which
-  show which libraries pass which tests under what conditions.</p>
+ show which libraries pass which tests under what conditions.<br />这里所 讲述的过程,允许一个用户对任一个或所有库运行任意的测试组合,并生成一组简明的 表格,来展示哪些库在何种条件上通过了测试。</p>

- <h3>Preliminaries</h3>Generating these tables requires a couple of utility + <h3>Preliminaries 准备工作</h3>Generating these tables requires a couple of utility
   programs: <code>process_jam_log</code> and <code>library_status</code>.
   These can be built by moving to the directory
   <code>tools/regression/build</code> and invoking bjam. If all goes well
   these utility programs will be found in the directory
   <code>dist/bin</code>. From there they should be moved to a place in the
-  current path.
+ current path.<br />生成这些表格需要两个工具程 序:<code>process_jam_log</code> 和 <code>library_status</code>。可以通过进 入目录 <code>tools/regression/build</code> 并运行 bjam 来构建它们。如果一切 正常,这两个工具程序可以在目录 + <code>dist/bin</code> 下找到。它们应该被从那个目录移至当前 path 中的某 处。

-  <h3>Running Tests for One Library</h3>
+  <h3>Running Tests for One Library 对一个库运行测试</h3>

   <ol>
-    <li>Start from your command line environment.</li>
+ <li>Start from your command line environment.<br />从你的命令行环境开 始。</li>

-    <li>set the current directory to:../libs/&lt;library name&gt;/test</li>
+ <li>set the current directory to:../libs/&lt;library name&gt;/test<br />将当前目录设为:../libs/&lt;library name&gt;/test</li>

-    <li>Invoke one of the following:
+    <li>Invoke one of the following:<br />执行以下之一:

       <ul>
- <li><code>../../../tools/regression/library_test (*nix)</code>.</li>
+        <li><code>../../../tools/regression/library_test (*nix)</code></li>

         <li><code>..\..\..\tools\regression\library_test
         (windows)</code>.</li>
@@ -67,42 +63,43 @@

     <li>This will display short help message describing the how to set the
command line arguments for the compilers and variants you want to appear
-    in the final table.</li>
+ in the final table.<br />这时将显示简短的帮助信息,描述如何针对编译器以 及你希望出现在最终的表格中的不同版本设置命令行参数。</li>

<li>Setting these arguments requires rudimentary knowledge of bjam usage.
     Hopefully, if you've arrived at this page you've gained the required
-    knowledge during the installation and library build process.</li>
+ knowledge during the installation and library build process.<br />设置 这些参数需要有使用 bjam 的基本知识。我们希望,如果你能来到这一页,你应该已经 具备了库安装和构建所需的知识。</li>

-    <li>Rerun the abve command with the argument set accordingly.</li>
+ <li>Rerun the abve command with the argument set accordingly.<br />以相 应的参数重新运行上述命令。</li>

     <li>When the command terminates, there should be a file named
-    "library_status.html" in the current directory.</li>
+ "library_status.html" in the current directory.<br />当命令运行结束,在 当前目录会生成一个名为
+    "library_status.html" 的文件。</li>

-    <li>Display this file with any web browser.</li>
+ <li>Display this file with any web browser.<br />用任意的web浏览器显示 该文件。</li>
   </ol>There should appear a table similar to the following for the regex
-  library.
+  library.<br />这时将出现一个类似以下的表格,以下是针对 regex 库的。

-  <table border="1" cellspacing="0" cellpadding="5">
-    <tr>
+  <table border="1" cellpadding="5" cellspacing="0">
+    <tbody><tr>
       <td rowspan="4">Test Name</td>

-      <td align="center" colspan="4">msvc-7.1</td>
+      <td colspan="4" align="center">msvc-7.1</td>
     </tr>

     <tr>
-      <td align="center" colspan="2">debug</td>
+      <td colspan="2" align="center">debug</td>

-      <td align="center" colspan="2">release</td>
+      <td colspan="2" align="center">release</td>
     </tr>

     <tr>
       <td align="center">link-static</td>

-      <td align="center" rowspan="2">threading-multi</td>
+      <td rowspan="2" align="center">threading-multi</td>

       <td align="center">link-static</td>

-      <td align="center" rowspan="2">threading-multi</td>
+      <td rowspan="2" align="center">threading-multi</td>
     </tr>

     <tr>
@@ -116,14 +113,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-bad_expression_test.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-bad_expression_test.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-bad_expression_test.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-bad_expression_test.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -132,14 +127,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-captures-msvc-7.1-debug-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-captures-msvc-7.1-debug-threading-multi">
       <span class="c3">Fail</span></a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-captures-msvc-7.1-release-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-captures-msvc-7.1-release-threading-multi">
       <span class="c3">Fail</span></a></td>
     </tr>

@@ -148,14 +141,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-captures_test.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-captures_test.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-captures_test.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-captures_test.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -188,14 +179,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-object_cache_test.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-object_cache_test.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-object_cache_test.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-object_cache_test.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -204,14 +193,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-posix_api_check.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-posix_api_check.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-posix_api_check.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-posix_api_check.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -232,14 +219,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-recursion_test.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-recursion_test.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-recursion_test.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-recursion_test.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -248,14 +233,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_config_info.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_config_info.test-msvc-7.1-debug-threading-multi">
       Pass</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_config_info.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_config_info.test-msvc-7.1-release-threading-multi">
       Pass</a></td>
     </tr>

@@ -264,28 +247,24 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_dll_config_info.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_dll_config_info.test-msvc-7.1-debug-threading-multi">
       Pass</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_dll_config_info.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_dll_config_info.test-msvc-7.1-release-threading-multi">
       Pass</a></td>
     </tr>

     <tr>
       <td>regex_regress</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress.test-msvc-7.1-debug-link-static-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress.test-msvc-7.1-debug-link-static-threading-multi">
       Pass</a><sup>*</sup></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress.test-msvc-7.1-release-link-static-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress.test-msvc-7.1-release-link-static-threading-multi">
       Pass</a><sup>*</sup></td>

       <td class="c1" align="right">Missing</td>
@@ -296,14 +275,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress_dll.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress_dll.test-msvc-7.1-debug-threading-multi">
       Pass</a><sup>*</sup></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress_dll.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a href="links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress_dll.test-msvc-7.1-release-threading-multi">
       Pass</a><sup>*</sup></td>
     </tr>

@@ -336,14 +313,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-test_collate_info.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-test_collate_info.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-test_collate_info.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-test_collate_info.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -352,14 +327,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-unicode_iterator_test.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-unicode_iterator_test.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-unicode_iterator_test.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-unicode_iterator_test.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -368,14 +341,12 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_c.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_c.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_c.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_c.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>

@@ -384,24 +355,22 @@

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_cpp.test-msvc-7.1-debug-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_cpp.test-msvc-7.1-debug-threading-multi">
       Warn</a></td>

       <td class="c1" align="right">Missing</td>

-      <td align="right"><a class="c2" href=
-      
"links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_cpp.test-msvc-7.1-release-threading-multi">
+ <td align="right"><a class="c2" href="links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_cpp.test-msvc-7.1-release-threading-multi">
       Warn</a></td>
     </tr>
-  </table>
+  </tbody></table>

-  <p>This table was generated by invoking the following command line:</p>
+ <p>This table was generated by invoking the following command line:<br />这个表格是通过执行以下命令行生成的:</p>

   <p><code>../../../tools/regression/library_test --toolset=msvc-7.1
   variant=debug,release</code></p>

-  <p>from within the .../libs/regex/test directory.</p>
+ <p>from within the .../libs/regex/test directory.<br />运行的目录 是 .../libs/regex/test.</p>

   <p>This table shows the regex test results for both debug and release
versions of the library. Also it displays the fact that one of the tests is
@@ -411,20 +380,21 @@
   corresponding <code>Jamfile.v2</code> excludes this test for the given
   combination of compiler and build attributes. In this example, all tests
   were run with the same compiler. If additional compilers were used, they
-  would appear as more columns in the table.</p>
+ would appear as more columns in the table.<br />这个表格展示了对 regex 库 的调试版本和发布版本的测试结果。同时,它还显示了其中一个测试是特定以运行库的 静态链接/多线程版本来运行的。标记为 "Missing" 的单元格对应于因某种原因未运行 的测试。这是很有用的,因为对应的 <code>Jamfile.v2</code> 针对给定的编译器和 构建属性组合排除了这些测试。在这个例子中,所有测试都是在相同的编译器下运行 的。如果使用了其它编译器,则会在表格中增加一列来表示。</p>

   <p>The table above is just an illustration so the links don't actually
   point to anything. In the table you generated, the links will display a
   page describing any errors, warnings or other available information about
the tests. If the test passes, usually, there is no additional information
-  and hence no link.</p>
+ and hence no link.<br />以上表格只是一个示例,所以其中的链接实际上并没有 指向任何东西。在你生成的表格中,这些链接会显示一个描述错误、警告或其它有关该 项测试的可用信息的网页。通常,如果测试通过,则没有额外的信息,也就没有链接。 </p>

<p>The tables are cumulative. That is, if you run one set of tests now and
   tests with different attributes later, the table will contain all the
   results to date. The test results are stored in
   <code>../bin.v2/libs/test/&lt;library%gt;/...</code>. To reinitialize the
   test results to empty, delete the corresponding files in this
-  directory.</p>
+ directory.<br />表格是叠加的。即,如果你现在运行了一组测试,稍后再以不同 属性进行测试,则表格中会包含所有结果。测试结果保存在 + <code>../bin.v2/libs/test/&lt;library%gt;/...</code>. 要把测试结果重新清 空,请删除该目录下的相应文件。</p>

   <p>The procedure above assumes that the table are generated within the
   directory <code>../libs/&lt;library&gt;/test</code>. This is the most
@@ -436,11 +406,12 @@
have a special directory of performance tests which take a long time to run
   and hence are not suitable for running by official boost testers. Just
remember that library status table is generated in the directory from which
-  the <code>library_test</code> command is invoked.</p>
+ the <code>library_test</code> command is invoked.<br />以上过程假定了该表 格是在目录 <code>../libs/&lt;library&gt;/test</code> 中生成的。这是最为常见 的情形,因为这个目录包含了 <code>Jamfile.v2</code> 以及被正式的boost测试者所 使用的源代码。但是,这只是为了方便。这个表格可以在库中的其它目录生成。一种可 能性是,为 <code>../libs/%lt;library%gt;/example</code> 中的所有例子。或者你 可能有一个专门用于性能测试的目录,性能测试需要较长的运行时间,不适合由正式的 boost测试者运行。你只要记住,库的状态表格是在执行 <code>library_test</code> 命令的目录中生成的。</p>

-  <h3>Running Tests for All Libraries</h3>For those with *nix or cygwin
+ <h3>Running Tests for All Libraries 为所有库运行测试</h3>For those with *nix or cygwin
   command line shells, there is shell script that can be run from the boost
-  root directory:
+  root directory:<br />对于 *nix 或 cygwin
+  命令行 shells,有一个shell脚本可以从boost根目录直接运行:

   <p><code>tools/regression/library_test_all</code></p>

@@ -448,7 +419,8 @@
library. This script creates all the html files in all the test directories
   as well as an html page in the <code>status</code> directory named
   <code>library_status_summary.html</code>. This can be used to browse
-  through all test results for all test in all libraries.</p>
+ through all test results for all test in all libraries.<br />命令行参数与 针对一个库进行测试是一样的。这个脚本在所有测试目录中生成html文件,并在 status 目录中生成一个名为 + <code>library_status_summary.html</code> 的html页面。它可以用来浏览整个库 的所有测试结果。</p>
   <hr />

   <p>Copyright 2007 Robert Ramey. Distributed under the Boost Software
@@ -456,5 +428,4 @@
   http://www.boost.org/LICENSE_1_0.txt)</p>

   <p>Revised $Date: 2007-11-23 12:03:14 -0500 (Fri, 23 Nov 2007) $</p>
-</body>
-</html>
+</body></html>
\ No newline at end of file

Modified: trunk/tools/regression/src/collect_and_upload_logs.py
==============================================================================
--- trunk/tools/regression/src/collect_and_upload_logs.py       (original)
+++ trunk/tools/regression/src/collect_and_upload_logs.py Sun Apr 5 07:36:05 2009
@@ -1,500 +1,518 @@
-
-# Copyright (c) MetaCommunications, Inc. 2003-2007
-#
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or copy at
-# http://www.boost.org/LICENSE_1_0.txt)
-
-import xml.sax.saxutils
-import zipfile
-import ftplib
-import time
-import stat
-import xml.dom.minidom
-import xmlrpclib
-import httplib
-
-import os.path
-import string
-import sys
-
-
-def process_xml_file( input_file, output_file ):
-    utils.log( 'Processing test log "%s"' % input_file )
-
-    f = open( input_file, 'r' )
-    xml = f.readlines()
-    f.close()
-
-    for i in range( 0, len(xml)):
-        xml[i] = string.translate( xml[i], utils.char_translation_table )
-
-    output_file.writelines( xml )
-
-
-def process_test_log_files( output_file, dir, names ):
-    for file in names:
-        if os.path.basename( file ) == 'test_log.xml':
-            process_xml_file( os.path.join( dir, file ), output_file )
-
-
-def collect_test_logs( input_dirs, test_results_writer ):
-    __log__ = 1
-    utils.log( 'Collecting test logs ...' )
-    for input_dir in input_dirs:
-        utils.log( 'Walking directory "%s" ...' % input_dir )
- os.path.walk( input_dir, process_test_log_files, test_results_writer )
-
-dart_status_from_result = {
-    'succeed': 'passed',
-    'fail': 'failed',
-    'note': 'passed',
-    '': 'notrun'
-    }
-
-dart_project = {
-    'trunk': 'Boost_HEAD',
-    '': 'Boost_HEAD'
-    }
-
-dart_track = {
-    'full': 'Nightly',
-    'incremental': 'Continuous',
-    '': 'Experimental'
-    }
-
-ascii_only_table = ""
-for i in range(0,256):
-    if chr(i) == '\n' or chr(i) == '\r':
-        ascii_only_table += chr(i)
-    elif i < 32 or i >= 0x80:
-        ascii_only_table += '?'
-    else:
-        ascii_only_table += chr(i)
-
-class xmlrpcProxyTransport(xmlrpclib.Transport):
-    def __init__(self, proxy):
-        self.proxy = proxy
-    def make_connection(self, host):
-        self.realhost = host
-        return httplib.HTTP(self.proxy)
-    def send_request(self, connection, handler, request_body):
- connection.putrequest('POST','http://%s%s' % (self.realhost,handler))
-    def send_host(self, connection, host):
-        connection.putheader('Host',self.realhost)
-
-
-def publish_test_logs(
-    input_dirs,
- runner_id, tag, platform, comment_file, timestamp, user, source, run_type,
-    dart_server = None,
-    http_proxy = None,
-    **unused
-    ):
-    __log__ = 1
-    utils.log( 'Publishing test logs ...' )
-    dart_rpc = None
-    dart_dom = {}
-
-    def _publish_test_log_files_ ( unused, dir, names ):
-        for file in names:
-            if os.path.basename( file ) == 'test_log.xml':
- utils.log( 'Publishing test log "%s"' % os.path.join(dir,file) )
-                if dart_server:
- log_xml = open(os.path.join(dir,file)).read().translate(ascii_only_table)
-                    #~ utils.log( '--- XML:\n%s' % log_xml)
- #~ It seems possible to get an empty XML result file :-(
-                    if log_xml == "": continue
-                    log_dom = xml.dom.minidom.parseString(log_xml)
-                    test = {
- 'library': log_dom.documentElement.getAttribute('library'), - 'test-name': log_dom.documentElement.getAttribute('test-name'), - 'toolset': log_dom.documentElement.getAttribute('toolset')
-                        }
-                    if not test['test-name'] or test['test-name'] == '':
-                        test['test-name'] = 'unknown'
-                    if not test['toolset'] or test['toolset'] == '':
-                        test['toolset'] = 'unknown'
-                    if not dart_dom.has_key(test['toolset']):
- dart_dom[test['toolset']] = xml.dom.minidom.parseString(
-'''<?xml version="1.0" encoding="UTF-8"?>
-<DartSubmission version="2.0" createdby="collect_and_upload_logs.py">
-    <Site>%(site)s</Site>
-    <BuildName>%(buildname)s</BuildName>
-    <Track>%(track)s</Track>
-    <DateTimeStamp>%(datetimestamp)s</DateTimeStamp>
-</DartSubmission>
-'''                         % {
-                                'site': runner_id,
- 'buildname': "%s -- %s (%s)" % (platform,test['toolset'],run_type),
-                                'track': dart_track[run_type],
-                                'datetimestamp' : timestamp
-                            } )
-                    submission_dom = dart_dom[test['toolset']]
-                    for node in log_dom.documentElement.childNodes:
-                        if node.nodeType == xml.dom.Node.ELEMENT_NODE:
-                            if node.firstChild:
- log_data = xml.sax.saxutils.escape(node.firstChild.data)
-                            else:
-                                log_data = ''
- test_dom = xml.dom.minidom.parseString('''<?xml version="1.0" encoding="UTF-8"?>
-<Test>
-    <Name>.Test.Boost.%(tag)s.%(library)s.%(test-name)s.%(type)s</Name>
-    <Status>%(result)s</Status>
- <Measurement name="Toolset" type="text/string">%(toolset)s</Measurement> - <Measurement name="Timestamp" type="text/string">%(timestamp)s</Measurement>
-    <Measurement name="Log" type="text/text">%(log)s</Measurement>
-</Test>
-    '''                         % {
-                                    'tag': tag,
-                                    'library': test['library'],
-                                    'test-name': test['test-name'],
-                                    'toolset': test['toolset'],
-                                    'type': node.nodeName,
- 'result': dart_status_from_result[node.getAttribute('result')], - 'timestamp': node.getAttribute('timestamp'),
-                                    'log': log_data
-                                })
-                            submission_dom.documentElement.appendChild(
-                                test_dom.documentElement.cloneNode(1) )
-
-    for input_dir in input_dirs:
-        utils.log( 'Walking directory "%s" ...' % input_dir )
-        os.path.walk( input_dir, _publish_test_log_files_, None )
-    if dart_server:
-        try:
-            rpc_transport = None
-            if http_proxy:
-                rpc_transport = xmlrpcProxyTransport(http_proxy)
-            dart_rpc = xmlrpclib.ServerProxy(
-                'http://%s/%s/Command/' % (dart_server,dart_project[tag]),
-                rpc_transport )
-            for dom in dart_dom.values():
-                #~ utils.log('Dart XML: %s' % dom.toxml('utf-8'))
-                dart_rpc.Submit.put(xmlrpclib.Binary(dom.toxml('utf-8')))
-        except Exception, e:
-            utils.log('Dart server error: %s' % e)
-
-
-def upload_to_ftp( tag, results_file, ftp_proxy, debug_level ):
-    ftp_site = 'fx.meta-comm.com'
-    site_path = '/boost-regression'
- utils.log( 'Uploading log archive "%s" to ftp://%s%s/%s' % ( results_file, ftp_site, site_path, tag ) )
-
-    if not ftp_proxy:
-        ftp = ftplib.FTP( ftp_site )
-        ftp.set_debuglevel( debug_level )
-        ftp.login()
-    else:
- utils.log( ' Connecting through FTP proxy server "%s"' % ftp_proxy )
-        ftp = ftplib.FTP( ftp_proxy )
-        ftp.set_debuglevel( debug_level )
-        ftp.set_pasv (0) # turn off PASV mode
-        ftp.login( 'anonymous@%s' % ftp_site, 'anonymous@' )
-
-    ftp.cwd( site_path )
-    try:
-        ftp.cwd( tag )
-    except ftplib.error_perm:
-        for dir in tag.split( '/' ):
-            ftp.mkd( dir )
-            ftp.cwd( dir )
-
-    f = open( results_file, 'rb' )
-    ftp.storbinary( 'STOR %s' % os.path.basename( results_file ), f )
-    ftp.quit()
-
-
-def copy_comments( results_xml, comment_file ):
-    results_xml.startElement( 'comment', {} )
-
-    if os.path.exists( comment_file ):
-        utils.log( 'Reading comments file "%s"...' % comment_file )
-        f = open( comment_file, 'r' )
-        try:
-            results_xml.characters( f.read() )
-        finally:
-            f.close()
-    else:
- utils.log( 'Warning: comment file "%s" is not found.' % comment_file )
-
-    results_xml.endElement( 'comment' )
-
-
-def compress_file( file_path, archive_path ):
-    utils.log( 'Compressing "%s"...' % file_path )
-
-    try:
-        z = zipfile.ZipFile( archive_path, 'w', zipfile.ZIP_DEFLATED )
-        z.write( file_path, os.path.basename( file_path ) )
-        z.close()
-        utils.log( 'Done writing "%s".'% archive_path )
-    except Exception, msg:
-        utils.log( 'Warning: Compressing falied (%s)' % msg )
- utils.log( ' Trying to compress using a platform-specific tool...' )
-        try: import zip_cmd
-        except ImportError:
-            script_dir = os.path.dirname( os.path.abspath( sys.argv[0] ) )
- utils.log( 'Could not find \'zip_cmd\' module in the script directory (%s).' % script_dir )
-            raise Exception( 'Compressing failed!' )
-        else:
-            if os.path.exists( archive_path ):
-                os.unlink( archive_path )
-                utils.log( 'Removing stale "%s".' % archive_path )
-
-            zip_cmd.main( file_path, archive_path )
-            utils.log( 'Done compressing "%s".' % archive_path )
-
-
-def read_timestamp( file ):
-    if not os.path.exists( file ):
-        result = time.gmtime()
-        utils.log( 'Warning: timestamp file "%s" does not exist'% file )
-        utils.log( 'Using current UTC time (%s)' % result )
-        return result
-
-    return time.gmtime( os.stat( file ).st_mtime )
-
-
-def collect_logs(
-          results_dir
-        , runner_id
-        , tag
-        , platform
-        , comment_file
-        , timestamp_file
-        , user
-        , source
-        , run_type
-        , dart_server = None
-        , http_proxy = None
-        , revision = ''
-        , **unused
-        ):
-
- timestamp = time.strftime( '%Y-%m-%dT%H:%M:%SZ', read_timestamp( timestamp_file ) )
-
-    if dart_server:
-        publish_test_logs( [ results_dir ],
- runner_id, tag, platform, comment_file, timestamp, user, source, run_type,
-            dart_server = dart_server,
-            http_proxy = http_proxy )
-
-    results_file = os.path.join( results_dir, '%s.xml' % runner_id )
-    results_writer = open( results_file, 'w' )
-    utils.log( 'Collecting test logs into "%s"...' % results_file )
-
-    results_xml = xml.sax.saxutils.XMLGenerator( results_writer )
-    results_xml.startDocument()
-    results_xml.startElement(
-          'test-run'
-        , {
-              'tag':        tag
-            , 'platform':   platform
-            , 'runner':     runner_id
-            , 'timestamp':  timestamp
-            , 'source':     source
-            , 'run-type':   run_type
-            , 'revision':   revision
-            }
-        )
-
-    copy_comments( results_xml, comment_file )
-    collect_test_logs( [ results_dir ], results_writer )
-
-    results_xml.endElement( "test-run" )
-    results_xml.endDocument()
-    results_writer.close()
-    utils.log( 'Done writing "%s".' % results_file )
-
-    compress_file(
-          results_file
-        , os.path.join( results_dir,'%s.zip' % runner_id )
-        )
-
-
-def upload_logs(
-          results_dir
-        , runner_id
-        , tag
-        , user
-        , ftp_proxy
-        , debug_level
-        , send_bjam_log = False
-        , timestamp_file = None
-        , dart_server = None
-        , **unused
-        ):
-
-    logs_archive = os.path.join( results_dir, '%s.zip' % runner_id )
-    upload_to_ftp( tag, logs_archive, ftp_proxy, debug_level )
-    if send_bjam_log:
-        bjam_log_path = os.path.join( results_dir, 'bjam.log' )
-        if not timestamp_file:
-            timestamp_file = bjam_log_path
-
- timestamp = time.strftime( '%Y-%m-%d-%H-%M-%S', read_timestamp( timestamp_file ) ) - logs_archive = os.path.join( results_dir, '%s.%s.log.zip' % ( runner_id, timestamp ) )
-        compress_file( bjam_log_path, logs_archive )
- upload_to_ftp( '%s/logs' % tag, logs_archive, ftp_proxy, debug_level )
-
-
-def collect_and_upload_logs(
-          results_dir
-        , runner_id
-        , tag
-        , platform
-        , comment_file
-        , timestamp_file
-        , user
-        , source
-        , run_type
-        , revision = None
-        , ftp_proxy = None
-        , debug_level = 0
-        , send_bjam_log = False
-        , dart_server = None
-        , http_proxy = None
-        , **unused
-        ):
-
-    collect_logs(
-          results_dir
-        , runner_id
-        , tag
-        , platform
-        , comment_file
-        , timestamp_file
-        , user
-        , source
-        , run_type
-        , revision = revision
-        , dart_server = dart_server
-        , http_proxy = http_proxy
-        )
-
-    upload_logs(
-          results_dir
-        , runner_id
-        , tag
-        , user
-        , ftp_proxy
-        , debug_level
-        , send_bjam_log
-        , timestamp_file
-        , dart_server = dart_server
-        )
-
-
-def accept_args( args ):
-    args_spec = [
-          'locate-root='
-        , 'runner='
-        , 'tag='
-        , 'platform='
-        , 'comment='
-        , 'timestamp='
-        , 'source='
-        , 'run-type='
-        , 'user='
-        , 'ftp-proxy='
-        , 'proxy='
-        , 'debug-level='
-        , 'send-bjam-log'
-        , 'help'
-        , 'dart-server='
-        , 'revision='
-        ]
-
-    options = {
-          '--tag'           : 'trunk'
-        , '--platform'      : sys.platform
-        , '--comment'       : 'comment.html'
-        , '--timestamp'     : 'timestamp'
-        , '--user'          : None
-        , '--source'        : 'SVN'
-        , '--run-type'      : 'full'
-        , '--ftp-proxy'     : None
-        , '--proxy'         : None
-        , '--debug-level'   : 0
-        , '--dart-server'   : 'beta.boost.org:8081'
-        , '--revision'      : None
-
-        }
-
-    utils.accept_args( args_spec, args, options, usage )
-
-    return {
-          'results_dir'     : options[ '--locate-root' ]
-        , 'runner_id'       : options[ '--runner' ]
-        , 'tag'             : options[ '--tag' ]
-        , 'platform'        : options[ '--platform']
-        , 'comment_file'    : options[ '--comment' ]
-        , 'timestamp_file'  : options[ '--timestamp' ]
-        , 'user'            : options[ '--user' ]
-        , 'source'          : options[ '--source' ]
-        , 'run_type'        : options[ '--run-type' ]
-        , 'ftp_proxy'       : options[ '--ftp-proxy' ]
-        , 'http_proxy'      : options[ '--proxy' ]
-        , 'debug_level'     : int(options[ '--debug-level' ])
-        , 'send_bjam_log'   : options.has_key( '--send-bjam-log' )
-        , 'dart_server'     : options[ '--dart-server' ]
-        , 'revision   '     : options[ '--revision' ]
-        }
-
-
-commands = {
-      'collect-and-upload'  : collect_and_upload_logs
-    , 'collect-logs'        : collect_logs
-    , 'upload-logs'         : upload_logs
-    }
-
-def usage():
-    print 'Usage: %s [command] [options]' % os.path.basename( sys.argv[0] )
-    print    '''
-Commands:
-\t%s
-
-Options:
-\t--locate-root   directory to to scan for "test_log.xml" files
-\t--runner        runner ID (e.g. "Metacomm")
-\t--timestamp     path to a file which modification time will be used
-\t                as a timestamp of the run ("timestamp" by default)
-\t--comment       an HTML comment file to be inserted in the reports
-\t                ("comment.html" by default)
-\t--tag           the tag for the results ("trunk" by default)
-\t--user          SourceForge user name for a shell account (optional)
-\t--source        where Boost sources came from ("SVN" or "tarball";
-\t                "SVN" by default)
-\t--run-type      "incremental" or "full" ("full" by default)
-\t--send-bjam-log in addition to regular XML results, send in full bjam
-\t                log of the regression run
-\t--proxy         HTTP proxy server address and port (e.g.
-\t                'http://www.someproxy.com:3128', optional)
-\t--ftp-proxy     FTP proxy server (e.g. 'ftpproxy', optional)
-\t--debug-level   debugging level; controls the amount of debugging
-\t                output printed; 0 by default (no debug output)
-\t--dart-server   The dart server to send results to.
-''' % '\n\t'.join( commands.keys() )
-
-
-def main():
-    if len(sys.argv) > 1 and sys.argv[1] in commands:
-        command = sys.argv[1]
-        args = sys.argv[ 2: ]
-    else:
-        command = 'collect-and-upload'
-        args = sys.argv[ 1: ]
-
-    commands[ command ]( **accept_args( args ) )
-
-
-if __name__ != '__main__':  import utils
-else:
-    # in absense of relative import...
-    xsl_path = os.path.abspath( os.path.dirname( sys.argv[ 0 ] ) )
- while os.path.basename( xsl_path ) != 'xsl_reports': xsl_path = os.path.dirname( xsl_path )
-    sys.path.append( xsl_path )
-
-    import utils
-    main()
+
+# Copyright (c) MetaCommunications, Inc. 2003-2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import xml.sax.saxutils
+import zipfile
+import ftplib
+import time
+import stat
+import xml.dom.minidom
+import xmlrpclib
+import httplib
+
+import os.path
+import string
+import sys
+import re
+import urlparse
+
+
+def process_xml_file( input_file, output_file ):
+    utils.log( 'Processing test log "%s"' % input_file )
+
+    f = open( input_file, 'r' )
+    xml = f.readlines()
+    f.close()
+
+    for i in range( 0, len(xml)):
+        xml[i] = string.translate( xml[i], utils.char_translation_table )
+
+    output_file.writelines( xml )
+
+
+def process_test_log_files( output_file, dir, names ):
+    for file in names:
+        if os.path.basename( file ) == 'test_log.xml':
+            process_xml_file( os.path.join( dir, file ), output_file )
+
+
+def collect_test_logs( input_dirs, test_results_writer ):
+    __log__ = 1
+    utils.log( 'Collecting test logs ...' )
+    for input_dir in input_dirs:
+        utils.log( 'Walking directory "%s" ...' % input_dir )
+ os.path.walk( input_dir, process_test_log_files, test_results_writer )
+
+dart_status_from_result = {
+    'succeed': 'passed',
+    'fail': 'failed',
+    'note': 'passed',
+    '': 'notrun'
+    }
+
+dart_project = {
+    'trunk': 'Boost_HEAD',
+    '': 'Boost_HEAD'
+    }
+
+dart_track = {
+    'full': 'Nightly',
+    'incremental': 'Continuous',
+    '': 'Experimental'
+    }
+
+ascii_only_table = ""
+for i in range(0,256):
+    if chr(i) == '\n' or chr(i) == '\r':
+        ascii_only_table += chr(i)
+    elif i < 32 or i >= 0x80:
+        ascii_only_table += '?'
+    else:
+        ascii_only_table += chr(i)
+
+class xmlrpcProxyTransport(xmlrpclib.Transport):
+    def __init__(self, proxy):
+        self.proxy = proxy
+    def make_connection(self, host):
+        self.realhost = host
+        return httplib.HTTP(self.proxy)
+    def send_request(self, connection, handler, request_body):
+ connection.putrequest('POST','http://%s%s' % (self.realhost,handler))
+    def send_host(self, connection, host):
+        connection.putheader('Host',self.realhost)
+
+
+def publish_test_logs(
+    input_dirs,
+ runner_id, tag, platform, comment_file, timestamp, user, source, run_type,
+    dart_server = None,
+    http_proxy = None,
+    **unused
+    ):
+    __log__ = 1
+    utils.log( 'Publishing test logs ...' )
+    dart_rpc = None
+    dart_dom = {}
+
+    def _publish_test_log_files_ ( unused, dir, names ):
+        for file in names:
+            if os.path.basename( file ) == 'test_log.xml':
+ utils.log( 'Publishing test log "%s"' % os.path.join(dir,file) )
+                if dart_server:
+ log_xml = open(os.path.join(dir,file)).read().translate(ascii_only_table)
+                    #~ utils.log( '--- XML:\n%s' % log_xml)
+ #~ It seems possible to get an empty XML result file :-(
+                    if log_xml == "": continue
+                    log_dom = xml.dom.minidom.parseString(log_xml)
+                    test = {
+ 'library': log_dom.documentElement.getAttribute('library'), + 'test-name': log_dom.documentElement.getAttribute('test-name'), + 'toolset': log_dom.documentElement.getAttribute('toolset')
+                        }
+                    if not test['test-name'] or test['test-name'] == '':
+                        test['test-name'] = 'unknown'
+                    if not test['toolset'] or test['toolset'] == '':
+                        test['toolset'] = 'unknown'
+                    if not dart_dom.has_key(test['toolset']):
+ dart_dom[test['toolset']] = xml.dom.minidom.parseString(
+'''<?xml version="1.0" encoding="UTF-8"?>
+<DartSubmission version="2.0" createdby="collect_and_upload_logs.py">
+    <Site>%(site)s</Site>
+    <BuildName>%(buildname)s</BuildName>
+    <Track>%(track)s</Track>
+    <DateTimeStamp>%(datetimestamp)s</DateTimeStamp>
+</DartSubmission>
+'''                         % {
+                                'site': runner_id,
+ 'buildname': "%s -- %s (%s)" % (platform,test['toolset'],run_type),
+                                'track': dart_track[run_type],
+                                'datetimestamp' : timestamp
+                            } )
+                    submission_dom = dart_dom[test['toolset']]
+                    for node in log_dom.documentElement.childNodes:
+                        if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+                            if node.firstChild:
+ log_data = xml.sax.saxutils.escape(node.firstChild.data)
+                            else:
+                                log_data = ''
+ test_dom = xml.dom.minidom.parseString('''<?xml version="1.0" encoding="UTF-8"?>
+<Test>
+    <Name>.Test.Boost.%(tag)s.%(library)s.%(test-name)s.%(type)s</Name>
+    <Status>%(result)s</Status>
+ <Measurement name="Toolset" type="text/string">%(toolset)s</Measurement> + <Measurement name="Timestamp" type="text/string">%(timestamp)s</Measurement>
+    <Measurement name="Log" type="text/text">%(log)s</Measurement>
+</Test>
+    '''                         % {
+                                    'tag': tag,
+                                    'library': test['library'],
+                                    'test-name': test['test-name'],
+                                    'toolset': test['toolset'],
+                                    'type': node.nodeName,
+ 'result': dart_status_from_result[node.getAttribute('result')], + 'timestamp': node.getAttribute('timestamp'),
+                                    'log': log_data
+                                })
+                            submission_dom.documentElement.appendChild(
+                                test_dom.documentElement.cloneNode(1) )
+
+    for input_dir in input_dirs:
+        utils.log( 'Walking directory "%s" ...' % input_dir )
+        os.path.walk( input_dir, _publish_test_log_files_, None )
+    if dart_server:
+        try:
+            rpc_transport = None
+            if http_proxy:
+                rpc_transport = xmlrpcProxyTransport(http_proxy)
+            dart_rpc = xmlrpclib.ServerProxy(
+                'http://%s/%s/Command/' % (dart_server,dart_project[tag]),
+                rpc_transport )
+            for dom in dart_dom.values():
+                #~ utils.log('Dart XML: %s' % dom.toxml('utf-8'))
+                dart_rpc.Submit.put(xmlrpclib.Binary(dom.toxml('utf-8')))
+        except Exception, e:
+            utils.log('Dart server error: %s' % e)
+
+
+def upload_to_ftp( tag, results_file, ftp_proxy, debug_level, ftp_url ):
+
+    if not ftp_url:
+        ftp_host = 'boost.cowic.de'
+ ftp_url = ''.join(['ftp','://anonymous','@',ftp_host,'/boost/do-not-publish-this-url/results/']) + utils.log( 'Uploading log archive "%s" to %s/%s' % ( results_file, ftp_url, tag ) )
+
+    ftp_parts = urlparse.urlparse(ftp_url)
+    ftp_netloc = re.split('[@]',ftp_parts[1])
+    ftp_user = re.split('[:]',ftp_netloc[0])[0]
+    ftp_password = re.split('[:]',ftp_netloc[0]+':anonymous')[1]
+    ftp_site = re.split('[:]',ftp_netloc[1])[0]
+    ftp_path = ftp_parts[2]
+
+    if not ftp_proxy:
+        ftp = ftplib.FTP( ftp_site )
+        ftp.set_debuglevel( debug_level )
+        ftp.login( ftp_user, ftp_password )
+    else:
+ utils.log( ' Connecting through FTP proxy server "%s"' % ftp_proxy )
+        ftp = ftplib.FTP( ftp_proxy )
+        ftp.set_debuglevel( debug_level )
+        ftp.set_pasv (0) # turn off PASV mode
+        ftp.login( '%s@%s' % (ftp_user,ftp_site), ftp_password )
+
+    ftp.cwd( ftp_path )
+    try:
+        ftp.cwd( tag )
+    except ftplib.error_perm:
+        for dir in tag.split( '/' ):
+            ftp.mkd( dir )
+            ftp.cwd( dir )
+
+    f = open( results_file, 'rb' )
+    ftp.storbinary( 'STOR %s' % os.path.basename( results_file ), f )
+    ftp.quit()
+
+
+def copy_comments( results_xml, comment_file ):
+    results_xml.startElement( 'comment', {} )
+
+    if os.path.exists( comment_file ):
+        utils.log( 'Reading comments file "%s"...' % comment_file )
+        f = open( comment_file, 'r' )
+        try:
+            results_xml.characters( f.read() )
+        finally:
+            f.close()
+    else:
+ utils.log( 'Warning: comment file "%s" is not found.' % comment_file )
+
+    results_xml.endElement( 'comment' )
+
+
+def compress_file( file_path, archive_path ):
+    utils.log( 'Compressing "%s"...' % file_path )
+
+    try:
+        z = zipfile.ZipFile( archive_path, 'w', zipfile.ZIP_DEFLATED )
+        z.write( file_path, os.path.basename( file_path ) )
+        z.close()
+        utils.log( 'Done writing "%s".'% archive_path )
+    except Exception, msg:
+        utils.log( 'Warning: Compressing falied (%s)' % msg )
+ utils.log( ' Trying to compress using a platform-specific tool...' )
+        try: import zip_cmd
+        except ImportError:
+            script_dir = os.path.dirname( os.path.abspath( sys.argv[0] ) )
+ utils.log( 'Could not find \'zip_cmd\' module in the script directory (%s).' % script_dir )
+            raise Exception( 'Compressing failed!' )
+        else:
+            if os.path.exists( archive_path ):
+                os.unlink( archive_path )
+                utils.log( 'Removing stale "%s".' % archive_path )
+
+            zip_cmd.main( file_path, archive_path )
+            utils.log( 'Done compressing "%s".' % archive_path )
+
+
+def read_timestamp( file ):
+    if not os.path.exists( file ):
+        result = time.gmtime()
+        utils.log( 'Warning: timestamp file "%s" does not exist'% file )
+        utils.log( 'Using current UTC time (%s)' % result )
+        return result
+
+    return time.gmtime( os.stat( file ).st_mtime )
+
+
+def collect_logs(
+          results_dir
+        , runner_id
+        , tag
+        , platform
+        , comment_file
+        , timestamp_file
+        , user
+        , source
+        , run_type
+        , dart_server = None
+        , http_proxy = None
+        , revision = ''
+        , **unused
+        ):
+
+ timestamp = time.strftime( '%Y-%m-%dT%H:%M:%SZ', read_timestamp( timestamp_file ) )
+
+    if dart_server:
+        publish_test_logs( [ results_dir ],
+ runner_id, tag, platform, comment_file, timestamp, user, source, run_type,
+            dart_server = dart_server,
+            http_proxy = http_proxy )
+
+    results_file = os.path.join( results_dir, '%s.xml' % runner_id )
+    results_writer = open( results_file, 'w' )
+    utils.log( 'Collecting test logs into "%s"...' % results_file )
+
+    results_xml = xml.sax.saxutils.XMLGenerator( results_writer )
+    results_xml.startDocument()
+    results_xml.startElement(
+          'test-run'
+        , {
+              'tag':        tag
+            , 'platform':   platform
+            , 'runner':     runner_id
+            , 'timestamp':  timestamp
+            , 'source':     source
+            , 'run-type':   run_type
+            , 'revision':   revision
+            }
+        )
+
+    copy_comments( results_xml, comment_file )
+    collect_test_logs( [ results_dir ], results_writer )
+
+    results_xml.endElement( "test-run" )
+    results_xml.endDocument()
+    results_writer.close()
+    utils.log( 'Done writing "%s".' % results_file )
+
+    compress_file(
+          results_file
+        , os.path.join( results_dir,'%s.zip' % runner_id )
+        )
+
+
+def upload_logs(
+          results_dir
+        , runner_id
+        , tag
+        , user
+        , ftp_proxy
+        , debug_level
+        , send_bjam_log = False
+        , timestamp_file = None
+        , dart_server = None
+        , ftp_url = None
+        , **unused
+        ):
+
+    logs_archive = os.path.join( results_dir, '%s.zip' % runner_id )
+    upload_to_ftp( tag, logs_archive, ftp_proxy, debug_level, ftp_url )
+    if send_bjam_log:
+        bjam_log_path = os.path.join( results_dir, 'bjam.log' )
+        if not timestamp_file:
+            timestamp_file = bjam_log_path
+
+ timestamp = time.strftime( '%Y-%m-%d-%H-%M-%S', read_timestamp( timestamp_file ) ) + logs_archive = os.path.join( results_dir, '%s.%s.log.zip' % ( runner_id, timestamp ) )
+        compress_file( bjam_log_path, logs_archive )
+ upload_to_ftp( '%s/logs' % tag, logs_archive, ftp_proxy, debug_level, ftp_url )
+
+
+def collect_and_upload_logs(
+          results_dir
+        , runner_id
+        , tag
+        , platform
+        , comment_file
+        , timestamp_file
+        , user
+        , source
+        , run_type
+        , revision = None
+        , ftp_proxy = None
+        , debug_level = 0
+        , send_bjam_log = False
+        , dart_server = None
+        , http_proxy = None
+        , ftp_url = None
+        , **unused
+        ):
+
+    collect_logs(
+          results_dir
+        , runner_id
+        , tag
+        , platform
+        , comment_file
+        , timestamp_file
+        , user
+        , source
+        , run_type
+        , revision = revision
+        , dart_server = dart_server
+        , http_proxy = http_proxy
+        )
+
+    upload_logs(
+          results_dir
+        , runner_id
+        , tag
+        , user
+        , ftp_proxy
+        , debug_level
+        , send_bjam_log
+        , timestamp_file
+        , dart_server = dart_server
+        , ftp_url = ftp_url
+        )
+
+
+def accept_args( args ):
+    args_spec = [
+          'locate-root='
+        , 'runner='
+        , 'tag='
+        , 'platform='
+        , 'comment='
+        , 'timestamp='
+        , 'source='
+        , 'run-type='
+        , 'user='
+        , 'ftp-proxy='
+        , 'proxy='
+        , 'debug-level='
+        , 'send-bjam-log'
+        , 'help'
+        , 'dart-server='
+        , 'revision='
+        , 'ftp='
+        ]
+
+    options = {
+          '--tag'           : 'trunk'
+        , '--platform'      : sys.platform
+        , '--comment'       : 'comment.html'
+        , '--timestamp'     : 'timestamp'
+        , '--user'          : None
+        , '--source'        : 'SVN'
+        , '--run-type'      : 'full'
+        , '--ftp-proxy'     : None
+        , '--proxy'         : None
+        , '--debug-level'   : 0
+        , '--dart-server'   : 'beta.boost.org:8081'
+        , '--revision'      : None
+        , '--ftp'           : None
+
+        }
+
+    utils.accept_args( args_spec, args, options, usage )
+
+    return {
+          'results_dir'     : options[ '--locate-root' ]
+        , 'runner_id'       : options[ '--runner' ]
+        , 'tag'             : options[ '--tag' ]
+        , 'platform'        : options[ '--platform']
+        , 'comment_file'    : options[ '--comment' ]
+        , 'timestamp_file'  : options[ '--timestamp' ]
+        , 'user'            : options[ '--user' ]
+        , 'source'          : options[ '--source' ]
+        , 'run_type'        : options[ '--run-type' ]
+        , 'ftp_proxy'       : options[ '--ftp-proxy' ]
+        , 'http_proxy'      : options[ '--proxy' ]
+        , 'debug_level'     : int(options[ '--debug-level' ])
+        , 'send_bjam_log'   : options.has_key( '--send-bjam-log' )
+        , 'dart_server'     : options[ '--dart-server' ]
+        , 'revision'        : options[ '--revision' ]
+        , 'ftp'             : options[ '--ftp' ]
+        }
+
+
+commands = {
+      'collect-and-upload'  : collect_and_upload_logs
+    , 'collect-logs'        : collect_logs
+    , 'upload-logs'         : upload_logs
+    }
+
+def usage():
+    print 'Usage: %s [command] [options]' % os.path.basename( sys.argv[0] )
+    print    '''
+Commands:
+\t%s
+
+Options:
+\t--locate-root   directory to to scan for "test_log.xml" files
+\t--runner        runner ID (e.g. "Metacomm")
+\t--timestamp     path to a file which modification time will be used
+\t                as a timestamp of the run ("timestamp" by default)
+\t--comment       an HTML comment file to be inserted in the reports
+\t                ("comment.html" by default)
+\t--tag           the tag for the results ("trunk" by default)
+\t--user          SourceForge user name for a shell account (optional)
+\t--source        where Boost sources came from ("SVN" or "tarball";
+\t                "SVN" by default)
+\t--run-type      "incremental" or "full" ("full" by default)
+\t--send-bjam-log in addition to regular XML results, send in full bjam
+\t                log of the regression run
+\t--proxy         HTTP proxy server address and port (e.g.
+\t                'http://www.someproxy.com:3128', optional)
+\t--ftp-proxy     FTP proxy server (e.g. 'ftpproxy', optional)
+\t--debug-level   debugging level; controls the amount of debugging
+\t                output printed; 0 by default (no debug output)
+\t--dart-server   The dart server to send results to.
+\t--ftp           The ftp URL to upload results to.
+''' % '\n\t'.join( commands.keys() )
+
+
+def main():
+    if len(sys.argv) > 1 and sys.argv[1] in commands:
+        command = sys.argv[1]
+        args = sys.argv[ 2: ]
+    else:
+        command = 'collect-and-upload'
+        args = sys.argv[ 1: ]
+
+    commands[ command ]( **accept_args( args ) )
+
+
+if __name__ != '__main__':  import utils
+else:
+    # in absense of relative import...
+    xsl_path = os.path.abspath( os.path.dirname( sys.argv[ 0 ] ) )
+ while os.path.basename( xsl_path ) != 'xsl_reports': xsl_path = os.path.dirname( xsl_path )
+    sys.path.append( xsl_path )
+
+    import utils
+    main()

Modified: trunk/tools/regression/src/compiler_status.cpp
==============================================================================
--- trunk/tools/regression/src/compiler_status.cpp      (original)
+++ trunk/tools/regression/src/compiler_status.cpp      Sun Apr  5 07:36:05 2009
@@ -1,1037 +1,1104 @@
-// Generate Compiler Status HTML from jam regression test output -----------//
-
-//  Copyright Beman Dawes 2002.  Distributed under the Boost
-//  Software License, Version 1.0. (See accompanying file
-//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-//  See http://www.boost.org/tools/regression/ for documentation.
-
-/*******************************************************************************
-
-    This program was designed to work unchanged on all platforms and
- configurations. All output which is platform or configuration dependent
-    is obtained from external sources such as the .xml file from
-    process_jam_log execution, the tools/build/xxx-tools.jam files, or the
-    output of the config_info tests.
-
-    Please avoid adding platform or configuration dependencies during
-    program maintenance.
-
-*******************************************************************************/
-
-#include "boost/config.hpp"
-#include "boost/filesystem/operations.hpp"
-#include "boost/filesystem/fstream.hpp"
-#include "detail/tiny_xml.hpp"
-namespace fs = boost::filesystem;
-namespace xml = boost::tiny_xml;
-
-#include <cstdlib>  // for abort, exit
-#include <cctype>   // for toupper
-#include <string>
-#include <vector>
-#include <set>
-#include <map>
-#include <algorithm>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <stdexcept>
-#include <cassert>
-
-using std::string;
-
-const string pass_msg( "Pass" );
-const string warn_msg( "<i>Warn</i>" );
-const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
-const string note_msg( "<sup>*</sup>" );
-const string missing_residue_msg( "<i>Missing</i>" );
-
-const std::size_t max_compile_msg_size = 10000;
-
-namespace
-{
-  fs::path boost_root;  // boost-root complete path
- fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
-
-  bool compile_time;
-  bool run_time;
-  bool ignore_pass;
-  bool no_warn;
-  bool no_links;
-  bool boost_build_v2 = true;
-
-  fs::path jamfile_path;
-
-  fs::directory_iterator end_itr;
-
- // It's immportant for reliability that we find the same compilers for each
-  // test, and that they match the column header.  So save the names at the
-  // time column headings are generated.
-  std::vector<string> toolsets;
-
-  fs::ifstream jamfile;
-  fs::ofstream report;
-  fs::ofstream links_file;
-  string links_name;
-
-  fs::path notes_path;
-  string notes_html;
-
-  fs::path notes_map_path;
- typedef std::multimap< string, string > notes_map; // key is test_name-toolset,
-                                                // value is note bookmark
-  notes_map notes;
-
-  string specific_compiler; // if running on one toolset only
-
-  const string empty_string;
-
-  std::vector<int> error_count;
-
-  // prefix for library and test hyperlink prefix
-  string cvs_root ( "http://boost.cvs.sourceforge.net/"; );
-  string url_prefix_dir_view( cvs_root + "boost/boost" );
-  string url_prefix_checkout_view( cvs_root + "*checkout*/boost/boost" );
-  string url_suffix_text_view( "?view=markup&rev=HEAD" );
-
-// get revision number (as a string) if boost_root is svn working copy -----//
-
-  string revision( const fs::path & boost_root )
-  {
-    string rev;
-    fs::path entries( boost_root / ".svn" / "entries" );
-    fs::ifstream entries_file( entries );
-    if ( entries_file )
-    {
-      std::getline( entries_file, rev );
-      std::getline( entries_file, rev );
-      std::getline( entries_file, rev );
-      std::getline( entries_file, rev );  // revision number as a string
-    }
-    return rev;
-  }
-
-
-// build notes_bookmarks from notes HTML -----------------------------------//
-
-  void build_notes_bookmarks()
-  {
-    if ( notes_map_path.empty() ) return;
-    fs::ifstream notes_map_file( notes_map_path );
-    if ( !notes_map_file )
-    {
- std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl;
-      std::exit( 1 );
-    }
-    string line;
-    while( std::getline( notes_map_file, line ) )
-    {
-      string::size_type pos = 0;
-      if ( (pos = line.find( ',', pos )) == string::npos ) continue;
-      string key(line.substr( 0, pos ) );
-      string bookmark( line.substr( pos+1 ) );
-
-// std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n";
-      notes.insert( notes_map::value_type( key, bookmark ) );
-    }
-  }
-
-// load_notes_html ---------------------------------------------------------//
-
-  bool load_notes_html()
-  {
-    if ( notes_path.empty() ) return false;
-    fs::ifstream notes_file( notes_path );
-    if ( !notes_file )
-    {
- std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl;
-      std::exit( 1 );
-    }
-    string line;
-    bool in_body( false );
-    while( std::getline( notes_file, line ) )
-    {
- if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false;
-      if ( in_body ) notes_html += line;
-      else if ( line.find( "<body>" ) ) in_body = true;
-    }
-    return true;
-  }
-
-// relative path between two paths -----------------------------------------//
-
-  void relative_path( const fs::path & from, const fs::path & to,
-    fs::path & target )
-  {
-    if ( from.string().size() <= to.string().size() ) return;
-    target /= "..";
-    relative_path( from.branch_path(), to, target );
-    return;
-  }
-
-// extract object library name from target directory string ----------------//
-
-  string extract_object_library_name( const string & s )
-  {
-    string t( s );
-    string::size_type pos = t.find( "/build/" );
-    if ( pos != string::npos ) pos += 7;
-    else if ( (pos = t.find( "/test/" )) != string::npos ) pos += 6;
-    else return "";
-    return t.substr( pos, t.find( "/", pos ) - pos );
-  }
-
-// find_file ---------------------------------------------------------------//
-//  given a directory to recursively search
-
-  bool find_file( const fs::path & dir_path, const string & name,
-    fs::path & path_found, const string & ignore_dir_named="" )
-  {
-    if ( !fs::exists( dir_path ) ) return false;
-    for ( fs::directory_iterator itr( dir_path ); itr != end_itr; ++itr )
-      if ( fs::is_directory( *itr )
-        && itr->leaf() != ignore_dir_named )
-      {
-        if ( find_file( *itr, name, path_found ) ) return true;
-      }
-      else if ( itr->leaf() == name )
-      {
-        path_found = *itr;
-        return true;
-      }
-    return false;
-  }
-
-// platform_desc -----------------------------------------------------------//
-
-  string platform_desc()
-  {
-    string result = BOOST_PLATFORM;
-    result[0] = std::toupper( result[0] );
-    return result;
-  }
-
-// version_desc ------------------------------------------------------------//
-//  from locate-root/status/bin/config_info.test/xxx/.../config_info.output
-
-  string version_desc( const string & compiler_name )
-  {
-    string result;
-    fs::path dot_output_path;
-    if ( find_file( locate_root / "bin/boost/status/config_info.test"
-      / compiler_name, "config_info.output", dot_output_path )
-      || find_file( locate_root / "status/bin/config_info.test"
-      / compiler_name, "config_info.output", dot_output_path ) )
-    {
-      fs::ifstream file( dot_output_path );
-      if ( file )
-      {
-        if( std::getline( file, result ) )
-        {
-          string::size_type pos = result.find( "version " );
-          if ( pos != string::npos )
-          {
-            result.erase( 0, pos+8 );
-          }
-          else result.clear();
-        }
-      }
-    }
-    return result;
-  }
-
-// compiler_desc -----------------------------------------------------------//
-//  from boost-root/tools/build/xxx-tools.jam
-
-  string compiler_desc( const string & compiler_name )
-  {
-    string result;
-    fs::path tools_path( boost_root / "tools/build/v1" / (compiler_name
-      + "-tools.jam") );
-    if ( !fs::exists( tools_path ) )
- tools_path = boost_root / "tools/build" / (compiler_name + "-tools.jam");
-    fs::ifstream file( tools_path );
-    if ( file )
-    {
-      while( std::getline( file, result ) )
-      {
-        if ( result.substr( 0, 3 ) == "#//" )
-        {
-          result.erase( 0, 3 );
-          return result;
-        }
-      }
-      result.clear();
-    }
-    return result;
-  }
-
-// target_directory --------------------------------------------------------//
-//  this amounts to a request to find a unique leaf directory
-
-  fs::path target_directory( const fs::path & root )
-  {
-    if ( !fs::exists( root ) ) return fs::path("no-such-path");
-    fs::path child;
-    for ( fs::directory_iterator itr( root ); itr != end_itr; ++itr )
-    {
-      if ( fs::is_directory( *itr ) )
-      {
-        // SunCC creates an internal subdirectory everywhere it writes
-        // object files.  This confuses the target_directory() algorithm.
-        // This patch ignores the SunCC internal directory. Jens Maurer
-        if ( (*itr).leaf() == "SunWS_cache" ) continue;
- // SGI does something similar for template instantiations. Jens Maurer
-        if(  (*itr).leaf() == "ii_files" ) continue;
-
-        if ( child.empty() ) child = *itr;
-        else
-        {
- std::cout << "Warning: only first of two target possibilities will be reported for: \n "
-            << root.string() << ": " << child.leaf()
-            << " and " << (*itr).leaf() << "\n";
-        }
-      }
-    }
-    if ( child.empty() ) return root; // this dir has no children
-    return target_directory( child );
-  }
-
-// element_content ---------------------------------------------------------//
-
-  const string & element_content(
-    const xml::element & root, const string & name )
-  {
-    static string empty_string;
-    xml::element_list::const_iterator itr;
-    for ( itr = root.elements.begin();
-          itr != root.elements.end() && (*itr)->name != name;
-          ++itr ) {}
-    return itr != root.elements.end() ? (*itr)->content : empty_string;
-  }
-
-// find_element ------------------------------------------------------------//
-
-  const xml::element empty_element;
-
-  const xml::element & find_element(
-    const xml::element & root, const string & name )
-  {
-    xml::element_list::const_iterator itr;
-    for ( itr = root.elements.begin();
-          itr != root.elements.end() && (*itr)->name != name;
-          ++itr ) {}
-    return itr != root.elements.end() ? *((*itr).get()) : empty_element;
-  }
-
-// attribute_value ----------------------------------------------------------//
-
-const string & attribute_value( const xml::element & element,
-                                const string & attribute_name )
-{
-  static const string empty_string;
-  xml::attribute_list::const_iterator atr;
-  for ( atr = element.attributes.begin();
-        atr != element.attributes.end() && atr->name != attribute_name;
-        ++atr ) {}
-  return atr == element.attributes.end() ? empty_string : atr->value;
-}
-
-// find_bin_path -----------------------------------------------------------//
-
-// Takes a relative path from boost root to a Jamfile.
-// Returns the directory where the build targets from
-// that Jamfile are located. If not found, emits a warning
-// and returns empty path.
-const fs::path find_bin_path(const string& relative)
-{
-  fs::path bin_path;
-  if (boost_build_v2)
-  {
-    bin_path = locate_root / "bin.v2" / relative;
-    if (!fs::exists(bin_path))
-    {
-      std::cerr << "warning: could not find build results for '"
-                << relative << "'.\n";
-      std::cerr << "warning: tried directory "
-                << bin_path.native_directory_string() << "\n";
-      bin_path = "";
-    }
-  }
-  else
-  {
-    bin_path = locate_root / "bin/boost" / relative;
-    if (!fs::exists(bin_path))
-    {
-      bin_path = locate_root / "bin" / relative / "bin";
-      if (!fs::exists(bin_path))
-      {
-        bin_path = fs::path( locate_root / relative / "bin" );
-        if (!fs::exists(bin_path))
-        {
-          bin_path = fs::path( locate_root / "bin/boost/libs" /
-            relative.substr( relative.find( '/' )+1 ) );
-        }
-      }
-    }
-    if (!fs::exists(bin_path))
-    {
-      std::cerr << "warning: could not find build results for '"
-                << relative << "'.\n";
-      bin_path = "";
-    }
-  }
-  return bin_path;
-}
-
-
-// generate_report ---------------------------------------------------------//
-
-  // return 0 if nothing generated, 1 otherwise, except 2 if compiler msgs
-  int generate_report( const xml::element & db,
-                       const string & source_library_name,
-                       const string & test_type,
- const string & test_name, // possibly object library name
-                       const string & toolset,
-                       bool pass,
-                       bool always_show_run_output = false )
-  {
-    // compile msgs sometimes modified, so make a local copy
-    string compile( ((pass && no_warn)
-      ? empty_string :  element_content( db, "compile" )) );
-
- const string & link( pass ? empty_string : element_content( db, "link" ) );
-    const string & run( (pass && !always_show_run_output)
-      ? empty_string : element_content( db, "run" ) );
-    string lib( (pass ? empty_string : element_content( db, "lib" )) );
-
-    // some compilers output the filename even if there are no errors or
- // warnings; detect this if one line of output and it contains no space.
-    string::size_type pos = compile.find( '\n', 1 );
-    if ( pos != string::npos && compile.size()-pos <= 2
-        && compile.find( ' ' ) == string::npos ) compile.clear();
-
-    if ( lib.empty()
-      && (compile.empty() || test_type == "compile_fail")
-      && link.empty() && run.empty() ) return 0;
-
-    int result = 1; // some kind of msg for sure
-
-    // limit compile message length
-    if ( compile.size() > max_compile_msg_size )
-    {
-      compile.erase( max_compile_msg_size );
-      compile += "...\n   (remainder deleted because of excessive size)\n";
-    }
-
-    links_file << "<h2><a name=\""
-      << source_library_name << "-" << test_name << "-" << toolset << "\">"
- << source_library_name << " - " << test_name << " - " << toolset << "</a></h2>\n";
-
-    if ( !compile.empty() )
-    {
-      ++result;
-      links_file << "<h3>Compiler output:</h3><pre>"
-        << compile << "</pre>\n";
-    }
-    if ( !link.empty() )
-      links_file << "<h3>Linker output:</h3><pre>" << link << "</pre>\n";
-    if ( !run.empty() )
-      links_file << "<h3>Run output:</h3><pre>" << run << "</pre>\n";
-
-    // for an object library failure, generate a reference to the object
-    // library failure message, and (once only) generate the object
-    // library failure message itself
-    static std::set< string > failed_lib_target_dirs; // only generate once
-    if ( !lib.empty() )
-    {
-      if ( lib[0] == '\n' ) lib.erase( 0, 1 );
-      string object_library_name( extract_object_library_name( lib ) );
-
-      // changing the target directory naming scheme breaks
-      // extract_object_library_name()
-      assert( !object_library_name.empty() );
-      if ( object_library_name.empty() )
- std::cerr << "Failed to extract object library name from " << lib << "\n";
-
-      links_file << "<h3>Library build failure: </h3>\n"
-        "See <a href=\"#"
-        << source_library_name << "-"
-        << object_library_name << "-" << toolset << "\">"
-        << source_library_name << " - "
-        << object_library_name << " - " << toolset << "</a>";
-
- if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() )
-      {
-        failed_lib_target_dirs.insert( lib );
-        fs::path pth( locate_root / lib / "test_log.xml" );
-        fs::ifstream file( pth );
-        if ( file )
-        {
-          xml::element_ptr db = xml::parse( file, pth.string() );
- generate_report( *db, source_library_name, test_type, object_library_name, toolset, false );
-        }
-        else
-        {
-          links_file << "<h2><a name=\""
-            << object_library_name << "-" << toolset << "\">"
-            << object_library_name << " - " << toolset << "</a></h2>\n"
-            "test_log.xml not found\n";
-        }
-      }
-    }
-    return result;
-  }
-
- // add_notes --------------------------------------------------------------//
-
- void add_notes( const string & key, bool fail, string & sep, string & target )
-  {
-    notes_map::const_iterator itr = notes.lower_bound( key );
-    if ( itr != notes.end() && itr->first == key )
-    {
-      for ( ; itr != notes.end() && itr->first == key; ++itr )
-      {
-        string note_desc( itr->second[0] == '-'
-          ? itr->second.substr( 1 ) : itr->second );
-        if ( fail || itr->second[0] == '-' )
-        {
-          target += sep;
-          sep = ",";
-          target += "<a href=\"";
-          target += "#";
-          target += note_desc;
-          target += "\">";
-          target += note_desc;
-          target += "</a>";
-        }
-      }
-    }
-  }
-
- // get_notes -------------------------------------------------------------//
-
-  string get_notes( const string & toolset,
- const string & library, const string & test, bool fail )
-  {
-    string sep;
-    string target( "<sup>" );
-    add_notes( toolset + "/" + library + "/" + test, fail, sep, target );
-    add_notes( "*/" + library + "/" + test, fail, sep, target );
-    add_notes( toolset + "/" + library + "/*", fail, sep, target );
-    add_notes( "*/" + library + "/*", fail, sep, target );
-    if ( target == "<sup>" ) target.clear();
-    else target += "</sup>";
-    return target;
-  }
-
- // do_cell ---------------------------------------------------------------//
-
-  bool do_cell(
-    int compiler,
-    const string & lib_name,
-    const fs::path & test_dir,
-    const string & test_type,
-    const string & test_name,
-    const string & toolset,
-    string & target,
-    bool always_show_run_output )
-  // return true if any results except simple pass_msg
-  {
-    fs::path target_dir( target_directory( test_dir / toolset ) );
-    bool pass = false;
-
-    if ( !fs::exists( target_dir / "test_log.xml" ) )
-    {
-      std::cerr << "Missing jam_log.xml in target:\n "
-        << target_dir.string() << "\n";
-      target += "<td>" + missing_residue_msg + "</td>";
-      return true;
-    }
-
-    int anything_generated = 0;
-    bool note = false;
-
-    fs::path pth( target_dir / "test_log.xml" );
-    fs::ifstream file( pth );
-    if ( !file ) // could not open jam_log.xml
-    {
-      std::cerr << "Can't open jam_log.xml in target:\n "
-        << target_dir.string() << "\n";
-      target += "<td>" + missing_residue_msg + "</td>";
-      return false;
-    }
-
-    xml::element_ptr dbp = xml::parse( file, pth.string() );
-    const xml::element & db( *dbp );
-
-    std::string test_type_base( test_type );
-    if ( test_type_base == "run_pyd" ) test_type_base = "run";
-    else if ( test_type_base.size() > 5 )
-    {
-      const string::size_type trailer = test_type_base.size() - 5;
-      if ( test_type_base.substr( trailer ) == "_fail" )
-      {
-        test_type_base.erase( trailer );
-      }
-    }
- const xml::element & test_type_element( find_element( db, test_type_base ) );
-
-    pass = !test_type_element.name.empty()
-      && attribute_value( test_type_element, "result" ) != "fail";
-
-    if ( !no_links )
-    {
-      note = attribute_value( test_type_element, "result" ) == "note";
-
-      // generate bookmarked report of results, and link to it
-      anything_generated
- = generate_report( db, lib_name, test_type, test_name, toolset, pass,
-          always_show_run_output || note );
-    }
-
-    target += "<td>";
-
-    // generate the status table cell pass/warn/fail HTML
-    if ( anything_generated != 0 )
-    {
-      target += "<a href=\"";
-      target += links_name;
-      target += "#";
-      target += lib_name;
-      target += "-";
-      target += test_name;
-      target += "-";
-      target += toolset;
-      target += "\">";
-      target += pass
-        ? (anything_generated < 2 ? pass_msg : warn_msg)
-        : fail_msg;
-      target += "</a>";
-      if ( pass && note ) target += note_msg;
-    }
-    else  target += pass ? pass_msg : fail_msg;
-
-    // if notes, generate the superscript HTML
-    if ( !notes.empty() )
-      target += get_notes( toolset, lib_name, test_name, !pass );
-
-    // generate compile-time if requested
-    if ( compile_time )
-    {
- const xml::element & compile_element( find_element( db, "compile" ) );
-
-      if ( !compile_element.name.empty() )
-      {
-        string times = attribute_value( compile_element, "timings" );
-        if ( !times.empty() )
-        {
-          target += "<br>";
-          target += times.substr( 0, times.find( " " ) );
-        }
-      }
-    }
-
-    // generate run-time if requested
-    if ( run_time )
-    {
-      const xml::element & run_element( find_element( db, "run" ) );
-
-      if ( !run_element.name.empty() )
-      {
-        string times = attribute_value( run_element, "timings" );
-        if ( !times.empty() )
-        {
-          target += "<br>";
-          target += times.substr( 0, times.find( " " ) );
-        }
-      }
-    }
-
-    if ( !pass ) ++error_count[compiler];
-
-    target += "</td>";
-    return (anything_generated != 0) || !pass;
-  }
-
-// do_row ------------------------------------------------------------------//
-
-  void do_row(
-    const fs::path & test_dir, // locate_root / "status/bin/any_test.test"
-    const string & test_name, // "any_test"
-    string & target )
-  {
- // get library name, test-type, test-program path, etc., from the .xml file
-    string lib_name;
-    string test_path( test_name ); // test_name is default if missing .test
-    string test_type( "unknown" );
-    bool always_show_run_output( false );
-    fs::path xml_file_path;
-    if ( find_file( test_dir, "test_log.xml", xml_file_path ) )
-    {
-      fs::ifstream file( xml_file_path );
-      if ( file )
-      {
-        xml::element_ptr dbp = xml::parse( file, xml_file_path.string() );
-        const xml::element & db( *dbp );
-        test_path = attribute_value( db, "test-program" );
-        lib_name = attribute_value( db, "library" );
-        test_type = attribute_value( db, "test-type" );
-        always_show_run_output
-          = attribute_value( db, "show-run-output" ) == "true";
-      }
-    }
-
-    // generate the library name, test name, and test type table data
-    string::size_type row_start_pos = target.size();
- target += "<tr><td><a href=\"" + url_prefix_dir_view + "/libs/" + lib_name
-      + "\">"  + lib_name  + "</a></td>";
-    target += "<td><a href=\"" + url_prefix_checkout_view + "/" + test_path
-      + url_suffix_text_view + "\">" + test_name + "</a>";
-
-    if ( compile_time ) target += "<br> Compile time:";
-    if ( run_time ) target += "<br> Run time:";
-
-    target += "</td>";
-    target += "<td>" + test_type + "</td>";
-
-    bool no_warn_save = no_warn;
-    //if ( test_type.find( "fail" ) != string::npos ) no_warn = true;
-
-    // for each compiler, generate <td>...</td> html
-    bool anything_to_report = false;
-    int compiler = 0;
-    for ( std::vector<string>::const_iterator itr=toolsets.begin();
-      itr != toolsets.end(); ++itr, ++compiler )
-    {
- anything_to_report |= do_cell( compiler, lib_name, test_dir, test_type, test_name, *itr, target,
-        always_show_run_output );
-    }
-
-    target += "</tr>";
- if ( ignore_pass && !anything_to_report ) target.erase( row_start_pos );
-    no_warn = no_warn_save;
-  }
-
-// do_rows_for_sub_tree ----------------------------------------------------//
-
-  void do_rows_for_sub_tree(
-    const fs::path & bin_dir, std::vector<string> & results )
-  {
-    for ( fs::directory_iterator itr( bin_dir ); itr != end_itr; ++itr )
-    {
-      if ( fs::is_directory( *itr )
-        && itr->string().find( ".test" ) == (itr->string().size()-5) )
-      {
-        results.push_back( std::string() );
-        do_row( *itr,
-                itr->leaf().substr( 0, itr->leaf().size()-5 ),
-                results[results.size()-1] );
-      }
-    }
-  }
-
-// do_table_body -----------------------------------------------------------//
-
-  void do_table_body( const fs::path & bin_dir )
-  {
-    // rows are held in a vector so they can be sorted, if desired.
-    std::vector<string> results;
-
-    // do primary bin directory
-    do_rows_for_sub_tree( bin_dir, results );
-
-    // do subinclude bin directories
-    jamfile.clear();
-    jamfile.seekg(0);
-    string line;
-    while( std::getline( jamfile, line ) )
-    {
-      bool v2(false);
-      string::size_type pos( line.find( "subinclude" ) );
-      if ( pos == string::npos ) {
-        pos = line.find( "build-project" );
-        v2 = true;
-      }
-      if ( pos != string::npos
-        && line.find( '#' ) > pos )
-      {
-        if (v2)
-          pos = line.find_first_not_of( " \t./", pos+13 );
-        else
-          pos = line.find_first_not_of( " \t./", pos+10 );
-
-        if ( pos == string::npos ) continue;
-        string subinclude_bin_dir(
-          line.substr( pos, line.find_first_of( " \t", pos )-pos ) );
-
-        fs::path bin_path = find_bin_path(subinclude_bin_dir);
-        if (!bin_path.empty())
-          do_rows_for_sub_tree( bin_path, results );
-      }
-    }
-
-
-    std::sort( results.begin(), results.end() );
-
-    for ( std::vector<string>::iterator v(results.begin());
-      v != results.end(); ++v )
-      { report << *v << "\n"; }
-  }
-
-// do_table ----------------------------------------------------------------//
-
-  void do_table()
-  {
-    // Find test result locations, trying:
-    // - Boost.Build V1 location with ALL_LOCATE_TARGET
-    // - Boost.Build V2 location with top-lelve "build-dir"
-    // - Boost.Build V1 location without ALL_LOCATE_TARGET
-    string relative( fs::initial_path().string() );
-    relative.erase( 0, boost_root.string().size()+1 );
-    fs::path bin_path = find_bin_path(relative);
-
-    report << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n";
-
-    // generate the column headings
-
-    report << "<tr><td>Library</td><td>Test Name</td>\n"
- "<td><a href=\"compiler_status.html#test-type\">Test Type</a></td>\n";
-
-    fs::directory_iterator itr( bin_path );
-    while ( itr != end_itr
-      && ((itr->string().find( ".test" ) != (itr->string().size()-5))
-      || !fs::is_directory( *itr )))
-      ++itr; // bypass chaff
-    if ( itr != end_itr )
-    {
-      fs::directory_iterator compiler_itr( *itr );
-      if ( specific_compiler.empty() )
- std::clog << "Using " << itr->string() << " to determine compilers\n";
-      for (; compiler_itr != end_itr; ++compiler_itr )
-      {
-        if ( fs::is_directory( *compiler_itr )  // check just to be sure
- && compiler_itr->leaf() != "test" ) // avoid strange directory (Jamfile bug?)
-        {
-          if ( specific_compiler.size() != 0
-            && specific_compiler != compiler_itr->leaf() ) continue;
-          toolsets.push_back( compiler_itr->leaf() );
-          string desc( compiler_desc( compiler_itr->leaf() ) );
-          string vers( version_desc( compiler_itr->leaf() ) );
-          report << "<td>"
-               << (desc.size() ? desc : compiler_itr->leaf())
-               << (vers.size() ? (string( "<br>" ) + vers ) : string( "" ))
-               << "</td>\n";
-          error_count.push_back( 0 );
-        }
-      }
-    }
-
-    report << "</tr>\n";
-
-    // now the rest of the table body
-
-    do_table_body( bin_path );
-
-    // error total row
-
- report << "<tr> <td> &nbsp;</td><td>Number of Failures</td><td> &nbsp;</td>\n";
-
-    // for each compiler, generate <td>...</td> html
-    int compiler = 0;
-    for ( std::vector<string>::const_iterator itr=toolsets.begin();
-      itr != toolsets.end(); ++itr, ++compiler )
-    {
- report << "<td align=\"center\">" << error_count[compiler] << "</td>\n";
-    }
-
-    report << "</tr>\n</table>\n";
-  }
-
-} // unnamed namespace
-
-// main --------------------------------------------------------------------//
-
-#define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
-#include <boost/test/included/prg_exec_monitor.hpp>
-
-int cpp_main( int argc, char * argv[] ) // note name!
-{
-  fs::path comment_path;
-  while ( argc > 1 && *argv[1] == '-' )
-  {
-    if ( argc > 2 && std::strcmp( argv[1], "--compiler" ) == 0 )
-      { specific_compiler = argv[2]; --argc; ++argv; }
-    else if ( argc > 2 && std::strcmp( argv[1], "--locate-root" ) == 0 )
-      { locate_root = fs::path( argv[2], fs::native ); --argc; ++argv; }
-    else if ( argc > 2 && std::strcmp( argv[1], "--comment" ) == 0 )
-      { comment_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
-    else if ( argc > 2 && std::strcmp( argv[1], "--notes" ) == 0 )
-      { notes_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
-    else if ( argc > 2 && std::strcmp( argv[1], "--notes-map" ) == 0 )
-      { notes_map_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
- else if ( std::strcmp( argv[1], "--ignore-pass" ) == 0 ) ignore_pass = true;
-    else if ( std::strcmp( argv[1], "--no-warn" ) == 0 ) no_warn = true;
-    else if ( std::strcmp( argv[1], "--v1" ) == 0 ) boost_build_v2 = false;
-    else if ( std::strcmp( argv[1], "--v2" ) == 0 ) boost_build_v2 = true;
-    else if ( argc > 2 && std::strcmp( argv[1], "--jamfile" ) == 0)
-      { jamfile_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
- else if ( std::strcmp( argv[1], "--compile-time" ) == 0 ) compile_time = true;
-    else if ( std::strcmp( argv[1], "--run-time" ) == 0 ) run_time = true;
-    else { std::cerr << "Unknown option: " << argv[1] << "\n"; argc = 1; }
-    --argc;
-    ++argv;
-  }
-
-  if ( argc != 3 && argc != 4 )
-  {
-    std::cerr <<
- "Usage: compiler_status [options...] boost-root status-file [links-file]\n"
-      "  boost-root is the path to the boost tree root directory.\n"
-      "  status-file and links-file are paths to the output files.\n"
-      "Must be run from directory containing Jamfile\n"
-      "  options: --compiler name     Run for named compiler only\n"
- " --ignore-pass Do not report tests which pass all compilers\n" - " --no-warn Warnings not reported if test passes\n" - " --locate-root path Path to ALL_LOCATE_TARGET for bjam;\n"
-      "                               default boost-root.\n"
-      "           --comment path      Path to file containing HTML\n"
-      "                               to be copied into status-file.\n"
-      "           --notes path        Path to file containing HTML\n"
-      "                               to be copied into status-file.\n"
- " --notes-map path Path to file of toolset/test,n lines, where\n" - " n is number of note bookmark in --notes file.\n" - " --jamfile path Path to Jamfile. By default \"Jamfile\".\n"
-      "           --v1                Assume Boost.Build version 1.\n"
- " --v2 Assume Boost.Build version 2. (default)\n"
-      "           --ignore-pass       Ignore passing tests.\n"
-      "           --no-warn           Do not report warnings.\n"
-      "           --compile-time      Show compile time.\n"
-      "           --run-time          Show run time.\n"
- "Example: compiler_status --compiler gcc /boost-root cs.html cs-links.html\n" - "Note: Only the leaf of the links-file path and --notes file string are\n"
-      "used in status-file HTML links. Thus for browsing, status-file,\n"
-      "links-file, and --notes file must all be in the same directory.\n"
-      ;
-    return 1;
-  }
-
-  boost_root = fs::path( argv[1], fs::native );
-  if ( locate_root.empty() ) locate_root = boost_root;
-
-  if (jamfile_path.empty())
-    if (boost_build_v2)
-      jamfile_path = "Jamfile.v2";
-    else
-      jamfile_path = "Jamfile";
-  jamfile_path = fs::complete( jamfile_path, fs::initial_path() );
-  jamfile.open( jamfile_path );
-  if ( !jamfile )
-  {
- std::cerr << "Could not open Jamfile: " << jamfile_path.native_file_string() << std::endl;
-    return 1;
-  }
-
-  report.open( fs::path( argv[2], fs::native ) );
-  if ( !report )
-  {
- std::cerr << "Could not open report output file: " << argv[2] << std::endl;
-    return 1;
-  }
-
-  if ( argc == 4 )
-  {
-    fs::path links_path( argv[3], fs::native );
-    links_name = links_path.leaf();
-    links_file.open( links_path );
-    if ( !links_file )
-    {
- std::cerr << "Could not open links output file: " << argv[3] << std::endl;
-      return 1;
-    }
-  }
-  else no_links = true;
-
-  build_notes_bookmarks();
-
-  char run_date[128];
-  std::time_t tod;
-  std::time( &tod );
-  std::strftime( run_date, sizeof(run_date),
-    "%X UTC, %A %d %B %Y", std::gmtime( &tod ) );
-
-  std::string rev = revision( boost_root );
-
-  report << "<html>\n"
-          "<head>\n"
-          "<title>Boost Test Results</title>\n"
-          "</head>\n"
-          "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
-          "<table border=\"0\">\n"
-          "<tr>\n"
- "<td><img border=\"0\" src=\"http://www.boost.org/boost.png\"; width=\"277\" "
-          "height=\"86\"></td>\n"
-          "<td>\n"
-          "<h1>Boost Test Results - " + platform_desc() + "</h1>\n"
-          "<b>Run</b> "
-       << run_date;
-  if ( !rev.empty() ) report << ", <b>Revision</b> " << rev;
-  report << "\n";
-
-
-  if ( compile_time )
- report << "<p>Times reported are elapsed wall clock time in seconds.</p>\n";
-
-
-  if ( !comment_path.empty() )
-  {
-    fs::ifstream comment_file( comment_path );
-    if ( !comment_file )
-    {
- std::cerr << "Could not open \"--comment\" input file: " << comment_path.string() << std::endl;
-      return 1;
-    }
-    char c;
-    while ( comment_file.get( c ) ) { report.put( c ); }
-  }
-
-  report << "</td>\n</table>\n<br>\n";
-
-  if ( !no_links )
-  {
-    links_file
-      << "<html>\n"
-         "<head>\n"
-         "<title>Boost Test Details</title>\n"
-         "</head>\n"
-         "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
-         "<table border=\"0\">\n"
-         "<tr>\n"
- "<td><img border=\"0\" src=\"http://www.boost.org/boost.png\"; width=\"277\" "
-         "height=\"86\"></td>\n"
-         "<td>\n"
-         "<h1>Boost Test Details - " + platform_desc() + "</h1>\n"
-         "<b>Run Date:</b> "
-      << run_date;
-    if ( !rev.empty() ) links_file << ", <b>Revision</b> " << rev;
-    links_file << "\n</td>\n</table>\n<br>\n";
-  }
-
-  do_table();
-
-  if ( load_notes_html() ) report << notes_html << "\n";
-
-  report << "</body>\n"
-          "</html>\n"
-          ;
-
-  if ( !no_links )
-  {
-    links_file
-      << "</body>\n"
-         "</html>\n"
-         ;
-  }
-  return 0;
-}
+// Generate Compiler Status HTML from jam regression test output -----------//
+
+//  Copyright Beman Dawes 2002.  Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/tools/regression/ for documentation.
+
+/*******************************************************************************
+
+    This program was designed to work unchanged on all platforms and
+ configurations. All output which is platform or configuration dependent
+    is obtained from external sources such as the .xml file from
+    process_jam_log execution, the tools/build/xxx-tools.jam files, or the
+    output of the config_info tests.
+
+    Please avoid adding platform or configuration dependencies during
+    program maintenance.
+
+*******************************************************************************/
+
+#include <boost/config/warning_disable.hpp>
+
+#include "boost/config.hpp"
+#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem/convenience.hpp"
+#include "boost/filesystem/fstream.hpp"
+#include "detail/tiny_xml.hpp"
+namespace fs = boost::filesystem;
+namespace xml = boost::tiny_xml;
+
+#include <cstdlib>  // for abort, exit
+#include <cctype>   // for toupper
+#include <string>
+#include <vector>
+#include <set>
+#include <map>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <stdexcept>
+#include <cassert>
+
+using std::string;
+
+const string pass_msg( "Pass" );
+const string warn_msg( "<i>Warn</i>" );
+const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
+const string note_msg( "<sup>*</sup>" );
+const string missing_residue_msg( "<i>Missing</i>" );
+
+const std::size_t max_compile_msg_size = 10000;
+
+namespace
+{
+  fs::path boost_root;  // boost-root complete path
+ fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
+
+  bool compile_time;
+  bool run_time;
+  bool ignore_pass;
+  bool no_warn;
+  bool no_links;
+  bool boost_build_v2 = true;
+
+  fs::path jamfile_path;
+
+  fs::directory_iterator end_itr;
+
+ // It's immportant for reliability that we find the same compilers for each
+  // test, and that they match the column header.  So save the names at the
+  // time column headings are generated.
+  std::vector<string> toolsets;
+
+  fs::ifstream jamfile;
+  fs::ofstream report;
+  fs::ofstream links_file;
+  string links_name;
+
+  fs::path notes_path;
+  string notes_html;
+
+  fs::path notes_map_path;
+ typedef std::multimap< string, string > notes_map; // key is test_name-toolset,
+                                                // value is note bookmark
+  notes_map notes;
+
+  string specific_compiler; // if running on one toolset only
+
+  const string empty_string;
+
+  std::vector<int> error_count;
+
+  // prefix for library and test hyperlink prefix
+  string svn_root ( "http://svn.boost.org/trac/boost/browser/trunk/"; );
+  string url_prefix_dir_view( svn_root );
+  string url_prefix_checkout_view( svn_root );
+  string url_suffix_text_view( "" );
+
+// get revision number (as a string) if boost_root is svn working copy -----//
+
+  string revision( const fs::path & boost_root )
+  {
+    string rev;
+    fs::path entries( boost_root / ".svn" / "entries" );
+    fs::ifstream entries_file( entries );
+    if ( entries_file )
+    {
+      std::getline( entries_file, rev );
+      std::getline( entries_file, rev );
+      std::getline( entries_file, rev );
+      std::getline( entries_file, rev );  // revision number as a string
+    }
+    return rev;
+  }
+
+
+// build notes_bookmarks from notes HTML -----------------------------------//
+
+  void build_notes_bookmarks()
+  {
+    if ( notes_map_path.empty() ) return;
+    fs::ifstream notes_map_file( notes_map_path );
+    if ( !notes_map_file )
+    {
+ std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl;
+      std::exit( 1 );
+    }
+    string line;
+    while( std::getline( notes_map_file, line ) )
+    {
+      string::size_type pos = 0;
+      if ( (pos = line.find( ',', pos )) == string::npos ) continue;
+      string key(line.substr( 0, pos ) );
+      string bookmark( line.substr( pos+1 ) );
+
+// std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n";
+      notes.insert( notes_map::value_type( key, bookmark ) );
+    }
+  }
+
+// load_notes_html ---------------------------------------------------------//
+
+  bool load_notes_html()
+  {
+    if ( notes_path.empty() ) return false;
+    fs::ifstream notes_file( notes_path );
+    if ( !notes_file )
+    {
+ std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl;
+      std::exit( 1 );
+    }
+    string line;
+    bool in_body( false );
+    while( std::getline( notes_file, line ) )
+    {
+ if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false;
+      if ( in_body ) notes_html += line;
+      else if ( line.find( "<body>" ) ) in_body = true;
+    }
+    return true;
+  }
+
+// relative path between two paths -----------------------------------------//
+
+  void relative_path( const fs::path & from, const fs::path & to,
+    fs::path & target )
+  {
+    if ( from.string().size() <= to.string().size() ) return;
+    target /= "..";
+    relative_path( from.branch_path(), to, target );
+    return;
+  }
+
+// extract object library name from target directory string ----------------//
+
+  string extract_object_library_name( const string & s )
+  {
+    string t( s );
+    string::size_type pos = t.find( "/build/" );
+    if ( pos != string::npos ) pos += 7;
+    else if ( (pos = t.find( "/test/" )) != string::npos ) pos += 6;
+    else return "";
+    return t.substr( pos, t.find( "/", pos ) - pos );
+  }
+
+// find_file ---------------------------------------------------------------//
+//  given a directory to recursively search
+
+  bool find_file( const fs::path & dir_path, const string & name,
+    fs::path & path_found, const string & ignore_dir_named="" )
+  {
+    if ( !fs::exists( dir_path ) ) return false;
+    for ( fs::directory_iterator itr( dir_path ); itr != end_itr; ++itr )
+      if ( fs::is_directory( *itr )
+        && itr->filename() != ignore_dir_named )
+      {
+        if ( find_file( *itr, name, path_found ) ) return true;
+      }
+      else if ( itr->filename() == name )
+      {
+        path_found = *itr;
+        return true;
+      }
+    return false;
+  }
+
+// platform_desc -----------------------------------------------------------//
+
+  string platform_desc()
+  {
+    string result = BOOST_PLATFORM;
+    result[0] = std::toupper( result[0] );
+    return result;
+  }
+
+// version_desc ------------------------------------------------------------//
+//  from locate-root/status/bin/config_info.test/xxx/.../config_info.output
+
+  string version_desc( const string & compiler_name )
+  {
+    string result;
+    fs::path dot_output_path;
+    if ( find_file( locate_root / "bin/boost/status/config_info.test"
+      / compiler_name, "config_info.output", dot_output_path )
+      || find_file( locate_root / "status/bin/config_info.test"
+      / compiler_name, "config_info.output", dot_output_path ) )
+    {
+      fs::ifstream file( dot_output_path );
+      if ( file )
+      {
+        if( std::getline( file, result ) )
+        {
+          string::size_type pos = result.find( "version " );
+          if ( pos != string::npos )
+          {
+            result.erase( 0, pos+8 );
+          }
+          else result.clear();
+        }
+      }
+    }
+    return result;
+  }
+
+// compiler_desc -----------------------------------------------------------//
+//  from boost-root/tools/build/xxx-tools.jam
+
+  string compiler_desc( const string & compiler_name )
+  {
+    string result;
+    fs::path tools_path( boost_root / "tools/build/v1" / (compiler_name
+      + "-tools.jam") );
+    if ( !fs::exists( tools_path ) )
+ tools_path = boost_root / "tools/build" / (compiler_name + "-tools.jam");
+    fs::ifstream file( tools_path );
+    if ( file )
+    {
+      while( std::getline( file, result ) )
+      {
+        if ( result.substr( 0, 3 ) == "#//" )
+        {
+          result.erase( 0, 3 );
+          return result;
+        }
+      }
+      result.clear();
+    }
+    return result;
+  }
+
+// target_directory --------------------------------------------------------//
+//  this amounts to a request to find a unique leaf directory
+
+  fs::path target_directory( const fs::path & root )
+  {
+    if ( !fs::exists( root ) ) return fs::path("no-such-path");
+    fs::path child;
+    for ( fs::directory_iterator itr( root ); itr != end_itr; ++itr )
+    {
+      if ( fs::is_directory( *itr ) )
+      {
+        // SunCC creates an internal subdirectory everywhere it writes
+        // object files.  This confuses the target_directory() algorithm.
+        // This patch ignores the SunCC internal directory. Jens Maurer
+        if ( (*itr).filename() == "SunWS_cache" ) continue;
+ // SGI does something similar for template instantiations. Jens Maurer
+        if(  (*itr).filename() == "ii_files" ) continue;
+
+        if ( child.empty() ) child = *itr;
+        else
+        {
+ std::cout << "Warning: only first of two target possibilities will be reported for: \n "
+            << root.string() << ": " << child.filename()
+            << " and " << (*itr).filename() << "\n";
+        }
+      }
+    }
+    if ( child.empty() ) return root; // this dir has no children
+    return target_directory( child );
+  }
+
+// element_content ---------------------------------------------------------//
+
+  const string & element_content(
+    const xml::element & root, const string & name )
+  {
+    static string empty_string;
+    xml::element_list::const_iterator itr;
+    for ( itr = root.elements.begin();
+          itr != root.elements.end() && (*itr)->name != name;
+          ++itr ) {}
+    return itr != root.elements.end() ? (*itr)->content : empty_string;
+  }
+
+// find_element ------------------------------------------------------------//
+
+  const xml::element empty_element;
+
+  const xml::element & find_element(
+    const xml::element & root, const string & name )
+  {
+    xml::element_list::const_iterator itr;
+    for ( itr = root.elements.begin();
+          itr != root.elements.end() && (*itr)->name != name;
+          ++itr ) {}
+    return itr != root.elements.end() ? *((*itr).get()) : empty_element;
+  }
+
+// attribute_value ----------------------------------------------------------//
+
+const string & attribute_value( const xml::element & element,
+                                const string & attribute_name )
+{
+  static const string empty_string;
+  xml::attribute_list::const_iterator atr;
+  for ( atr = element.attributes.begin();
+        atr != element.attributes.end() && atr->name != attribute_name;
+        ++atr ) {}
+  return atr == element.attributes.end() ? empty_string : atr->value;
+}
+
+// find_bin_path -----------------------------------------------------------//
+
+// Takes a relative path from boost root to a Jamfile.
+// Returns the directory where the build targets from
+// that Jamfile are located. If not found, emits a warning
+// and returns empty path.
+const fs::path find_bin_path(const string& relative)
+{
+  fs::path bin_path;
+  if (boost_build_v2)
+  {
+    if ( relative == "status" )
+      bin_path = locate_root / "bin.v2" / "libs";
+    else
+    {
+      bin_path = locate_root / "bin.v2" / relative;
+      if (!fs::exists(bin_path))
+        bin_path = locate_root / "bin" / relative;
+    }
+    if (!fs::exists(bin_path))
+    {
+      std::cerr << "warning: could not find build results for '"
+                << relative << "'.\n";
+      std::cerr << "warning: tried directory "
+                << bin_path.native_directory_string() << "\n";
+      bin_path = "";
+    }
+  }
+  else
+  {
+    bin_path = locate_root / "bin/boost" / relative;
+    if (!fs::exists(bin_path))
+    {
+      bin_path = locate_root / "bin" / relative / "bin";
+      if (!fs::exists(bin_path))
+      {
+        bin_path = fs::path( locate_root / relative / "bin" );
+        if (!fs::exists(bin_path))
+        {
+          bin_path = fs::path( locate_root / "bin/boost/libs" /
+            relative.substr( relative.find( '/' )+1 ) );
+        }
+      }
+    }
+    if (!fs::exists(bin_path))
+    {
+      std::cerr << "warning: could not find build results for '"
+                << relative << "'.\n";
+      bin_path = "";
+    }
+  }
+  return bin_path;
+}
+
+
+// generate_report ---------------------------------------------------------//
+
+  // return 0 if nothing generated, 1 otherwise, except 2 if compiler msgs
+  int generate_report( const xml::element & db,
+                       const string & source_library_name,
+                       const string & test_type,
+ const string & test_name, // possibly object library name
+                       const string & toolset,
+                       bool pass,
+                       bool always_show_run_output = false )
+  {
+    // compile msgs sometimes modified, so make a local copy
+    string compile( ((pass && no_warn)
+      ? empty_string :  element_content( db, "compile" )) );
+
+ const string & link( pass ? empty_string : element_content( db, "link" ) );
+    const string & run( (pass && !always_show_run_output)
+      ? empty_string : element_content( db, "run" ) );
+    string lib( (pass ? empty_string : element_content( db, "lib" )) );
+
+    // some compilers output the filename even if there are no errors or
+ // warnings; detect this if one line of output and it contains no space.
+    string::size_type pos = compile.find( '\n', 1 );
+    if ( pos != string::npos && compile.size()-pos <= 2
+        && compile.find( ' ' ) == string::npos ) compile.clear();
+
+    if ( lib.empty()
+      && (compile.empty() || test_type == "compile_fail")
+      && link.empty() && run.empty() ) return 0;
+
+    int result = 1; // some kind of msg for sure
+
+    // limit compile message length
+    if ( compile.size() > max_compile_msg_size )
+    {
+      compile.erase( max_compile_msg_size );
+      compile += "...\n   (remainder deleted because of excessive size)\n";
+    }
+
+    links_file << "<h2><a name=\""
+      << source_library_name << "-" << test_name << "-" << toolset << "\">"
+ << source_library_name << " - " << test_name << " - " << toolset << "</a></h2>\n";
+
+    if ( !compile.empty() )
+    {
+      ++result;
+      links_file << "<h3>Compiler output:</h3><pre>"
+        << compile << "</pre>\n";
+    }
+    if ( !link.empty() )
+      links_file << "<h3>Linker output:</h3><pre>" << link << "</pre>\n";
+    if ( !run.empty() )
+      links_file << "<h3>Run output:</h3><pre>" << run << "</pre>\n";
+
+    // for an object library failure, generate a reference to the object
+    // library failure message, and (once only) generate the object
+    // library failure message itself
+    static std::set< string > failed_lib_target_dirs; // only generate once
+    if ( !lib.empty() )
+    {
+      if ( lib[0] == '\n' ) lib.erase( 0, 1 );
+      string object_library_name( extract_object_library_name( lib ) );
+
+      // changing the target directory naming scheme breaks
+      // extract_object_library_name()
+      assert( !object_library_name.empty() );
+      if ( object_library_name.empty() )
+ std::cerr << "Failed to extract object library name from " << lib << "\n";
+
+      links_file << "<h3>Library build failure: </h3>\n"
+        "See <a href=\"#"
+        << source_library_name << "-"
+        << object_library_name << "-" << toolset << "\">"
+        << source_library_name << " - "
+        << object_library_name << " - " << toolset << "</a>";
+
+ if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() )
+      {
+        failed_lib_target_dirs.insert( lib );
+        fs::path pth( locate_root / lib / "test_log.xml" );
+        fs::ifstream file( pth );
+        if ( file )
+        {
+          xml::element_ptr db = xml::parse( file, pth.string() );
+ generate_report( *db, source_library_name, test_type, object_library_name, toolset, false );
+        }
+        else
+        {
+          links_file << "<h2><a name=\""
+            << object_library_name << "-" << toolset << "\">"
+            << object_library_name << " - " << toolset << "</a></h2>\n"
+            "test_log.xml not found\n";
+        }
+      }
+    }
+    return result;
+  }
+
+ // add_notes --------------------------------------------------------------//
+
+ void add_notes( const string & key, bool fail, string & sep, string & target )
+  {
+    notes_map::const_iterator itr = notes.lower_bound( key );
+    if ( itr != notes.end() && itr->first == key )
+    {
+      for ( ; itr != notes.end() && itr->first == key; ++itr )
+      {
+        string note_desc( itr->second[0] == '-'
+          ? itr->second.substr( 1 ) : itr->second );
+        if ( fail || itr->second[0] == '-' )
+        {
+          target += sep;
+          sep = ",";
+          target += "<a href=\"";
+          target += "#";
+          target += note_desc;
+          target += "\">";
+          target += note_desc;
+          target += "</a>";
+        }
+      }
+    }
+  }
+
+ // get_notes -------------------------------------------------------------//
+
+  string get_notes( const string & toolset,
+ const string & library, const string & test, bool fail )
+  {
+    string sep;
+    string target( "<sup>" );
+    add_notes( toolset + "/" + library + "/" + test, fail, sep, target );
+    add_notes( "*/" + library + "/" + test, fail, sep, target );
+    add_notes( toolset + "/" + library + "/*", fail, sep, target );
+    add_notes( "*/" + library + "/*", fail, sep, target );
+    if ( target == "<sup>" ) target.clear();
+    else target += "</sup>";
+    return target;
+  }
+
+ // do_cell ---------------------------------------------------------------//
+
+  bool do_cell(
+    int compiler,
+    const string & lib_name,
+    const fs::path & test_dir,
+    const string & test_type,
+    const string & test_name,
+    const string & toolset,
+    string & target,
+    bool always_show_run_output )
+  // return true if any results except simple pass_msg
+  {
+    fs::path target_dir( target_directory( test_dir / toolset ) );
+    bool pass = false;
+
+    if ( !fs::exists( target_dir / "test_log.xml" ) )
+    {
+      std::cerr << "Missing jam_log.xml in target:\n "
+        << target_dir.string() << "\n";
+      target += "<td>" + missing_residue_msg + "</td>";
+      return true;
+    }
+
+    int anything_generated = 0;
+    bool note = false;
+
+    fs::path pth( target_dir / "test_log.xml" );
+    fs::ifstream file( pth );
+    if ( !file ) // could not open jam_log.xml
+    {
+      std::cerr << "Can't open jam_log.xml in target:\n "
+        << target_dir.string() << "\n";
+      target += "<td>" + missing_residue_msg + "</td>";
+      return false;
+    }
+
+    xml::element_ptr dbp = xml::parse( file, pth.string() );
+    const xml::element & db( *dbp );
+
+    std::string test_type_base( test_type );
+    if ( test_type_base == "run_pyd" ) test_type_base = "run";
+    else if ( test_type_base.size() > 5 )
+    {
+      const string::size_type trailer = test_type_base.size() - 5;
+      if ( test_type_base.substr( trailer ) == "_fail" )
+      {
+        test_type_base.erase( trailer );
+      }
+    }
+ const xml::element & test_type_element( find_element( db, test_type_base ) );
+
+    pass = !test_type_element.name.empty()
+      && attribute_value( test_type_element, "result" ) != "fail";
+
+    if ( !no_links )
+    {
+      note = attribute_value( test_type_element, "result" ) == "note";
+
+      // generate bookmarked report of results, and link to it
+      anything_generated
+ = generate_report( db, lib_name, test_type, test_name, toolset, pass,
+          always_show_run_output || note );
+    }
+
+    target += "<td>";
+
+    // generate the status table cell pass/warn/fail HTML
+    if ( anything_generated != 0 )
+    {
+      target += "<a href=\"";
+      target += links_name;
+      target += "#";
+      target += lib_name;
+      target += "-";
+      target += test_name;
+      target += "-";
+      target += toolset;
+      target += "\">";
+      target += pass
+        ? (anything_generated < 2 ? pass_msg : warn_msg)
+        : fail_msg;
+      target += "</a>";
+      if ( pass && note ) target += note_msg;
+    }
+    else  target += pass ? pass_msg : fail_msg;
+
+    // if notes, generate the superscript HTML
+    if ( !notes.empty() )
+      target += get_notes( toolset, lib_name, test_name, !pass );
+
+    // generate compile-time if requested
+    if ( compile_time )
+    {
+ const xml::element & compile_element( find_element( db, "compile" ) );
+
+      if ( !compile_element.name.empty() )
+      {
+        string times = attribute_value( compile_element, "timings" );
+        if ( !times.empty() )
+        {
+          target += "<br>";
+          target += times.substr( 0, times.find( " " ) );
+        }
+      }
+    }
+
+    // generate run-time if requested
+    if ( run_time )
+    {
+      const xml::element & run_element( find_element( db, "run" ) );
+
+      if ( !run_element.name.empty() )
+      {
+        string times = attribute_value( run_element, "timings" );
+        if ( !times.empty() )
+        {
+          target += "<br>";
+          target += times.substr( 0, times.find( " " ) );
+        }
+      }
+    }
+
+    if ( !pass ) ++error_count[compiler];
+
+    target += "</td>";
+    return (anything_generated != 0) || !pass;
+  }
+
+// do_row ------------------------------------------------------------------//
+
+  void do_row(
+    const fs::path & test_dir, // locate_root / "status/bin/any_test.test"
+    const string & test_name, // "any_test"
+    string & target )
+  {
+ // get library name, test-type, test-program path, etc., from the .xml file
+    string lib_name;
+    string test_path( test_name ); // test_name is default if missing .test
+    string test_type( "unknown" );
+    bool always_show_run_output( false );
+    fs::path xml_file_path;
+    if ( find_file( test_dir, "test_log.xml", xml_file_path ) )
+    {
+      fs::ifstream file( xml_file_path );
+      if ( file )
+      {
+        xml::element_ptr dbp = xml::parse( file, xml_file_path.string() );
+        const xml::element & db( *dbp );
+        test_path = attribute_value( db, "test-program" );
+        lib_name = attribute_value( db, "library" );
+        test_type = attribute_value( db, "test-type" );
+        always_show_run_output
+          = attribute_value( db, "show-run-output" ) == "true";
+      }
+    }
+
+    // generate the library name, test name, and test type table data
+    string::size_type row_start_pos = target.size();
+ target += "<tr><td><a href=\"" + url_prefix_dir_view + "/libs/" + lib_name
+      + "\">"  + lib_name  + "</a></td>";
+    target += "<td><a href=\"" + url_prefix_checkout_view + "/" + test_path
+      + url_suffix_text_view + "\">" + test_name + "</a>";
+
+    if ( compile_time ) target += "<br> Compile time:";
+    if ( run_time ) target += "<br> Run time:";
+
+    target += "</td>";
+    target += "<td>" + test_type + "</td>";
+
+    bool no_warn_save = no_warn;
+    //if ( test_type.find( "fail" ) != string::npos ) no_warn = true;
+
+    // for each compiler, generate <td>...</td> html
+    bool anything_to_report = false;
+    int compiler = 0;
+    for ( std::vector<string>::const_iterator itr=toolsets.begin();
+      itr != toolsets.end(); ++itr, ++compiler )
+    {
+ anything_to_report |= do_cell( compiler, lib_name, test_dir, test_type, test_name, *itr, target,
+        always_show_run_output );
+    }
+
+    target += "</tr>";
+ if ( ignore_pass && !anything_to_report ) target.erase( row_start_pos );
+    no_warn = no_warn_save;
+  }
+
+// do_rows_for_sub_tree ----------------------------------------------------//
+
+  void do_rows_for_sub_tree(
+    const fs::path & bin_dir, std::vector<string> & results )
+  {
+    for ( fs::directory_iterator itr( bin_dir ); itr != end_itr; ++itr )
+    {
+      if ( fs::is_directory( *itr )
+        && itr->string().find( ".test" ) == (itr->string().size()-5) )
+      {
+        results.push_back( std::string() );
+        do_row( *itr,
+                itr->filename().substr( 0, itr->filename().size()-5 ),
+                results[results.size()-1] );
+      }
+    }
+  }
+
+// find_compilers ------------------------------------------------------------//
+
+  void find_compilers(const fs::path & bin_dir)
+  {
+    fs::directory_iterator compiler_itr( bin_dir );
+    if ( specific_compiler.empty() )
+ std::clog << "Using " << bin_dir.string() << " to determine compilers\n";
+    for (; compiler_itr != end_itr; ++compiler_itr )
+    {
+      if ( fs::is_directory( *compiler_itr )  // check just to be sure
+ && compiler_itr->filename() != "test" ) // avoid strange directory (Jamfile bug?)
+      {
+        if ( specific_compiler.size() != 0
+          && specific_compiler != compiler_itr->filename() ) continue;
+        toolsets.push_back( compiler_itr->filename() );
+        string desc( compiler_desc( compiler_itr->filename() ) );
+        string vers( version_desc( compiler_itr->filename() ) );
+        report << "<td>"
+             << (desc.size() ? desc : compiler_itr->filename())
+             << (vers.size() ? (string( "<br>" ) + vers ) : string( "" ))
+             << "</td>\n";
+        error_count.push_back( 0 );
+      }
+    }
+  }
+
+// do_table_body -----------------------------------------------------------//
+
+  void do_table_body( const fs::path & bin_dir )
+  {
+    // rows are held in a vector so they can be sorted, if desired.
+    std::vector<string> results;
+
+    // do primary bin directory
+    do_rows_for_sub_tree( bin_dir, results );
+
+    // do subinclude bin directories
+    jamfile.clear();
+    jamfile.seekg(0);
+    string line;
+    bool run_tests = false;
+
+    while( std::getline( jamfile, line ) )
+    {
+      bool v2(false);
+      string::size_type sub_pos( line.find( "subinclude" ) );
+      if ( sub_pos == string::npos ) {
+        sub_pos = line.find( "build-project" );
+        v2 = true;
+      }
+      if ( sub_pos != string::npos
+        && line.find( '#' ) > sub_pos )
+      {
+        if (v2)
+          sub_pos = line.find_first_not_of( " \t./", sub_pos+13 );
+        else
+          sub_pos = line.find_first_not_of( " \t./", sub_pos+10 );
+
+        if ( sub_pos == string::npos ) continue;
+        string subinclude_bin_dir(
+ line.substr( sub_pos, line.find_first_of( " \t", sub_pos )-sub_pos ) );
+
+        fs::path bin_path = find_bin_path(subinclude_bin_dir);
+        if (!bin_path.empty())
+          do_rows_for_sub_tree( bin_path, results );
+      }
+      if ( ! run_tests )
+      {
+        string::size_type run_pos = line.find("run-tests");
+ if ( run_pos != string::npos && line.find_first_not_of(" \t") == run_pos )
+          run_tests = true;
+      }
+      else
+      {
+        if ( line.find(";") != string::npos )
+          run_tests = false;
+        else
+        {
+          string::size_type pos = line.find_first_not_of( " \t" );
+          if ( pos != string::npos && line[pos] != '#' )
+          {
+            string::size_type end_pos = line.find_first_of(" \t#", pos);
+ string::iterator end = end_pos != string::npos ? line.begin() + end_pos : line.end();
+            string run_tests_bin_dir(line.begin() + pos, end);
+            fs::path bin_path = find_bin_path("libs/" + run_tests_bin_dir);
+            if (!bin_path.empty())
+              do_rows_for_sub_tree( bin_path, results );
+          }
+        }
+      }
+    }
+
+
+    std::sort( results.begin(), results.end() );
+
+    for ( std::vector<string>::iterator v(results.begin());
+      v != results.end(); ++v )
+      { report << *v << "\n"; }
+  }
+
+// do_table ----------------------------------------------------------------//
+
+  void do_table()
+  {
+    // Find test result locations, trying:
+    // - Boost.Build V1 location with ALL_LOCATE_TARGET
+    // - Boost.Build V2 location with top-lelve "build-dir"
+    // - Boost.Build V1 location without ALL_LOCATE_TARGET
+    string relative( fs::initial_path().string() );
+
+#ifdef BOOST_WINDOWS_API
+ if (relative.size() > 1 && relative[1] == ':') relative[0] = std::tolower(relative[0]);
+#endif
+
+    if ( relative.find(boost_root.string()) != string::npos )
+      relative.erase( 0, boost_root.string().size()+1 );
+    else if ( relative.find(locate_root.string()) != string::npos )
+      relative.erase( 0, locate_root.string().size()+1 );
+    fs::path bin_path = find_bin_path(relative);
+
+    report << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n";
+
+    // generate the column headings
+
+    report << "<tr><td>Library</td><td>Test Name</td>\n"
+ "<td><a href=\"compiler_status.html#test-type\">Test Type</a></td>\n";
+
+    if ( relative == "status" )
+    {
+      fs::recursive_directory_iterator ritr( bin_path );
+      fs::recursive_directory_iterator end_ritr;
+      while ( ritr != end_ritr
+        && ((ritr->string().find( ".test" ) != (ritr->string().size()-5))
+        || !fs::is_directory( *ritr )))
+        ++ritr; // bypass chaff
+      if ( ritr != end_ritr )
+      {
+        find_compilers( *ritr );
+      }
+    }
+    else
+    {
+      fs::directory_iterator itr( bin_path );
+      while ( itr != end_itr
+        && ((itr->string().find( ".test" ) != (itr->string().size()-5))
+        || !fs::is_directory( *itr )))
+        ++itr; // bypass chaff
+      if ( itr != end_itr )
+      {
+        find_compilers( *itr );
+      }
+    }
+
+    report << "</tr>\n";
+
+    // now the rest of the table body
+
+    do_table_body( bin_path );
+
+    // error total row
+
+ report << "<tr> <td> &nbsp;</td><td>Number of Failures</td><td> &nbsp;</td>\n";
+
+    // for each compiler, generate <td>...</td> html
+    int compiler = 0;
+    for ( std::vector<string>::const_iterator itr=toolsets.begin();
+      itr != toolsets.end(); ++itr, ++compiler )
+    {
+ report << "<td align=\"center\">" << error_count[compiler] << "</td>\n";
+    }
+
+    report << "</tr>\n</table>\n";
+  }
+
+} // unnamed namespace
+
+// main --------------------------------------------------------------------//
+
+#define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
+#include <boost/test/included/prg_exec_monitor.hpp>
+
+int cpp_main( int argc, char * argv[] ) // note name!
+{
+  fs::path comment_path;
+  while ( argc > 1 && *argv[1] == '-' )
+  {
+    if ( argc > 2 && std::strcmp( argv[1], "--compiler" ) == 0 )
+      { specific_compiler = argv[2]; --argc; ++argv; }
+    else if ( argc > 2 && std::strcmp( argv[1], "--locate-root" ) == 0 )
+      { locate_root = fs::path( argv[2], fs::native ); --argc; ++argv; }
+    else if ( argc > 2 && std::strcmp( argv[1], "--comment" ) == 0 )
+      { comment_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
+    else if ( argc > 2 && std::strcmp( argv[1], "--notes" ) == 0 )
+      { notes_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
+    else if ( argc > 2 && std::strcmp( argv[1], "--notes-map" ) == 0 )
+      { notes_map_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
+ else if ( std::strcmp( argv[1], "--ignore-pass" ) == 0 ) ignore_pass = true;
+    else if ( std::strcmp( argv[1], "--no-warn" ) == 0 ) no_warn = true;
+    else if ( std::strcmp( argv[1], "--v1" ) == 0 ) boost_build_v2 = false;
+    else if ( std::strcmp( argv[1], "--v2" ) == 0 ) boost_build_v2 = true;
+    else if ( argc > 2 && std::strcmp( argv[1], "--jamfile" ) == 0)
+      { jamfile_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
+ else if ( std::strcmp( argv[1], "--compile-time" ) == 0 ) compile_time = true;
+    else if ( std::strcmp( argv[1], "--run-time" ) == 0 ) run_time = true;
+    else { std::cerr << "Unknown option: " << argv[1] << "\n"; argc = 1; }
+    --argc;
+    ++argv;
+  }
+
+  if ( argc != 3 && argc != 4 )
+  {
+    std::cerr <<
+ "Usage: compiler_status [options...] boost-root status-file [links-file]\n"
+      "  boost-root is the path to the boost tree root directory.\n"
+      "  status-file and links-file are paths to the output files.\n"
+      "Must be run from directory containing Jamfile\n"
+      "  options: --compiler name     Run for named compiler only\n"
+ " --ignore-pass Do not report tests which pass all compilers\n" + " --no-warn Warnings not reported if test passes\n" + " --locate-root path Path to ALL_LOCATE_TARGET for bjam;\n"
+      "                               default boost-root.\n"
+      "           --comment path      Path to file containing HTML\n"
+      "                               to be copied into status-file.\n"
+      "           --notes path        Path to file containing HTML\n"
+      "                               to be copied into status-file.\n"
+ " --notes-map path Path to file of toolset/test,n lines, where\n" + " n is number of note bookmark in --notes file.\n" + " --jamfile path Path to Jamfile. By default \"Jamfile\".\n"
+      "           --v1                Assume Boost.Build version 1.\n"
+ " --v2 Assume Boost.Build version 2. (default)\n"
+      "           --ignore-pass       Ignore passing tests.\n"
+      "           --no-warn           Do not report warnings.\n"
+      "           --compile-time      Show compile time.\n"
+      "           --run-time          Show run time.\n"
+ "Example: compiler_status --compiler gcc /boost-root cs.html cs-links.html\n" + "Note: Only the leaf of the links-file path and --notes file string are\n"
+      "used in status-file HTML links. Thus for browsing, status-file,\n"
+      "links-file, and --notes file must all be in the same directory.\n"
+      ;
+    return 1;
+  }
+
+  boost_root = fs::path( argv[1], fs::native );
+  if ( locate_root.empty() ) locate_root = boost_root;
+
+  if (jamfile_path.empty())
+    if (boost_build_v2)
+      jamfile_path = "Jamfile.v2";
+    else
+      jamfile_path = "Jamfile";
+  jamfile_path = fs::complete( jamfile_path, fs::initial_path() );
+  jamfile.open( jamfile_path );
+  if ( !jamfile )
+  {
+ std::cerr << "Could not open Jamfile: " << jamfile_path.native_file_string() << std::endl;
+    return 1;
+  }
+
+  report.open( fs::path( argv[2], fs::native ) );
+  if ( !report )
+  {
+ std::cerr << "Could not open report output file: " << argv[2] << std::endl;
+    return 1;
+  }
+
+  if ( argc == 4 )
+  {
+    fs::path links_path( argv[3], fs::native );
+    links_name = links_path.filename();
+    links_file.open( links_path );
+    if ( !links_file )
+    {
+ std::cerr << "Could not open links output file: " << argv[3] << std::endl;
+      return 1;
+    }
+  }
+  else no_links = true;
+
+  build_notes_bookmarks();
+
+  char run_date[128];
+  std::time_t tod;
+  std::time( &tod );
+  std::strftime( run_date, sizeof(run_date),
+    "%X UTC, %A %d %B %Y", std::gmtime( &tod ) );
+
+  std::string rev = revision( boost_root );
+
+  report << "<html>\n"
+          "<head>\n"
+          "<title>Boost Test Results</title>\n"
+          "</head>\n"
+          "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
+          "<table border=\"0\">\n"
+          "<tr>\n"
+ "<td><img border=\"0\" src=\"http://www.boost.org/boost.png\"; width=\"277\" "
+          "height=\"86\"></td>\n"
+          "<td>\n"
+          "<h1>Boost Test Results - " + platform_desc() + "</h1>\n"
+          "<b>Run</b> "
+       << run_date;
+  if ( !rev.empty() ) report << ", <b>Revision</b> " << rev;
+  report << "\n";
+
+
+  if ( compile_time )
+ report << "<p>Times reported are elapsed wall clock time in seconds.</p>\n";
+
+
+  if ( !comment_path.empty() )
+  {
+    fs::ifstream comment_file( comment_path );
+    if ( !comment_file )
+    {
+ std::cerr << "Could not open \"--comment\" input file: " << comment_path.string() << std::endl;
+      return 1;
+    }
+    char c;
+    while ( comment_file.get( c ) ) { report.put( c ); }
+  }
+
+  report << "</td>\n</table>\n<br>\n";
+
+  if ( !no_links )
+  {
+    links_file
+      << "<html>\n"
+         "<head>\n"
+         "<title>Boost Test Details</title>\n"
+         "</head>\n"
+         "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
+         "<table border=\"0\">\n"
+         "<tr>\n"
+ "<td><img border=\"0\" src=\"http://www.boost.org/boost.png\"; width=\"277\" "
+         "height=\"86\"></td>\n"
+         "<td>\n"
+         "<h1>Boost Test Details - " + platform_desc() + "</h1>\n"
+         "<b>Run Date:</b> "
+      << run_date;
+    if ( !rev.empty() ) links_file << ", <b>Revision</b> " << rev;
+    links_file << "\n</td>\n</table>\n<br>\n";
+  }
+
+  do_table();
+
+  if ( load_notes_html() ) report << notes_html << "\n";
+
+  report << "</body>\n"
+          "</html>\n"
+          ;
+
+  if ( !no_links )
+  {
+    links_file
+      << "</body>\n"
+         "</html>\n"
+         ;
+  }
+  return 0;
+}

Modified: trunk/tools/regression/src/detail/tiny_xml.cpp
==============================================================================
--- trunk/tools/regression/src/detail/tiny_xml.cpp      (original)
+++ trunk/tools/regression/src/detail/tiny_xml.cpp      Sun Apr  5 07:36:05 2009
@@ -1,167 +1,167 @@
-// tiny XML sub-set tools implementation -----------------------------------//
-
-//  (C) Copyright Beman Dawes 2002.  Distributed under the Boost
-//  Software License, Version 1.0. (See accompanying file
-//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#include "tiny_xml.hpp"
-#include <cassert>
-#include <cstring>
-
-namespace
-{
-
-  void eat_whitespace( char & c, std::istream & in )
-  {
-    while ( c == ' ' || c == '\r' || c == '\n' || c == '\t' )
-      in.get( c );
-  }
-
-  std::string get_name( char & c, std::istream & in )
-  {
-    std::string result;
-    eat_whitespace( c, in );
-    while ( std::strchr(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.", c )
-      != 0 )
-    {
-      result += c;
-      if(!in.get( c ))
-        throw std::string("xml: unexpected eof");
-    }
-    return result;
-  }
-
-  void eat_delim( char & c, std::istream & in,
-                  char delim, const std::string & msg )
-  {
-    eat_whitespace( c, in );
-    if ( c != delim )
-      throw std::string("xml syntax error, expected ") + delim
-       + " (" + msg + ")";
-    in.get( c );
-  }
-
-  std::string get_value( char & c, std::istream & in )
-  {
-    std::string result;
-    while ( c != '\"' )
-    {
-      result += c;
-      in.get( c );
-    }
-    in.get( c );
-    return result;
-  }
-
-}
-
-namespace boost
-{
-  namespace tiny_xml
-  {
-
- // parse -----------------------------------------------------------------//
-
-    element_ptr parse( std::istream & in, const std::string & msg )
-    {
-      char c = 0;  // current character
-      element_ptr e( new element );
-
-      if(!in.get( c ))
-        throw std::string("xml: unexpected eof");
-      if ( c == '<' )
-        if(!in.get( c ))
-          throw std::string("xml: unexpected eof");
-
-      e->name = get_name( c, in );
-      eat_whitespace( c, in );
-
-      // attributes
-      while ( c != '>' )
-      {
-        attribute a;
-        a.name = get_name( c, in );
-
-        eat_delim( c, in, '=', msg );
-        eat_delim( c, in, '\"', msg );
-
-        a.value = get_value( c, in );
-
-        e->attributes.push_back( a );
-        eat_whitespace( c, in );
-      }
-      if(!in.get( c )) // next after '>'
-        throw std::string("xml: unexpected eof");
-
-      eat_whitespace( c, in );
-
-      // sub-elements
-      while ( c == '<' )
-      {
-        if ( in.peek() == '/' ) break;
-        e->elements.push_back( parse( in, msg ) );
-        in.get( c ); // next after '>'
-        eat_whitespace( c, in );
-      }
-
-      // content
-      if ( c != '<' )
-      {
-        e->content += '\n';
-        while ( c != '<' )
-        {
-          e->content += c;
-          if(!in.get( c ))
-            throw std::string("xml: unexpected eof");
-        }
-      }
-
-      assert( c == '<' );
-      if(!in.get( c )) // next after '<'
-        throw std::string("xml: unexpected eof");
-
-      eat_delim( c, in, '/', msg );
-      std::string end_name( get_name( c, in ) );
-      if ( e->name != end_name )
-        throw std::string("xml syntax error: beginning name ")
-          + e->name + " did not match end name " + end_name
-          + " (" + msg + ")";
-
-      eat_delim( c, in, '>', msg );
-      return e;
-    }
-
- // write ---------------------------------------------------------------//
-
-    void write( const element & e, std::ostream & out )
-    {
-      out << "<" << e.name;
-      if ( !e.attributes.empty() )
-      {
-        for( attribute_list::const_iterator itr = e.attributes.begin();
-             itr != e.attributes.end(); ++itr )
-        {
-          out << " " << itr->name << "=\"" << itr->value << "\"";
-        }
-      }
-      out << ">";
-      if ( !e.elements.empty() )
-      {
-        out << "\n";
-        for( element_list::const_iterator itr = e.elements.begin();
-             itr != e.elements.end(); ++itr )
-        {
-          write( **itr, out );
-        }
-      }
-      if ( !e.content.empty() )
-      {
-        out << e.content;
-      }
-      out << "</" << e.name << ">\n";
-    }
-
-  } // namespace tiny_xml
-} // namespace boost
-
+// tiny XML sub-set tools implementation -----------------------------------//
+
+//  (C) Copyright Beman Dawes 2002.  Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "tiny_xml.hpp"
+#include <cassert>
+#include <cstring>
+
+namespace
+{
+
+  void eat_whitespace( char & c, std::istream & in )
+  {
+    while ( c == ' ' || c == '\r' || c == '\n' || c == '\t' )
+      in.get( c );
+  }
+
+  std::string get_name( char & c, std::istream & in )
+  {
+    std::string result;
+    eat_whitespace( c, in );
+    while ( std::strchr(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.", c )
+      != 0 )
+    {
+      result += c;
+      if(!in.get( c ))
+        throw std::string("xml: unexpected eof");
+    }
+    return result;
+  }
+
+  void eat_delim( char & c, std::istream & in,
+                  char delim, const std::string & msg )
+  {
+    eat_whitespace( c, in );
+    if ( c != delim )
+      throw std::string("xml syntax error, expected ") + delim
+       + " (" + msg + ")";
+    in.get( c );
+  }
+
+  std::string get_value( char & c, std::istream & in )
+  {
+    std::string result;
+    while ( c != '\"' )
+    {
+      result += c;
+      in.get( c );
+    }
+    in.get( c );
+    return result;
+  }
+
+}
+
+namespace boost
+{
+  namespace tiny_xml
+  {
+
+ // parse -----------------------------------------------------------------//
+
+    element_ptr parse( std::istream & in, const std::string & msg )
+    {
+      char c = 0;  // current character
+      element_ptr e( new element );
+
+      if(!in.get( c ))
+        throw std::string("xml: unexpected eof");
+      if ( c == '<' )
+        if(!in.get( c ))
+          throw std::string("xml: unexpected eof");
+
+      e->name = get_name( c, in );
+      eat_whitespace( c, in );
+
+      // attributes
+      while ( c != '>' )
+      {
+        attribute a;
+        a.name = get_name( c, in );
+
+        eat_delim( c, in, '=', msg );
+        eat_delim( c, in, '\"', msg );
+
+        a.value = get_value( c, in );
+
+        e->attributes.push_back( a );
+        eat_whitespace( c, in );
+      }
+      if(!in.get( c )) // next after '>'
+        throw std::string("xml: unexpected eof");
+
+      eat_whitespace( c, in );
+
+      // sub-elements
+      while ( c == '<' )
+      {
+        if ( in.peek() == '/' ) break;
+        e->elements.push_back( parse( in, msg ) );
+        in.get( c ); // next after '>'
+        eat_whitespace( c, in );
+      }
+
+      // content
+      if ( c != '<' )
+      {
+        e->content += '\n';
+        while ( c != '<' )
+        {
+          e->content += c;
+          if(!in.get( c ))
+            throw std::string("xml: unexpected eof");
+        }
+      }
+
+      assert( c == '<' );
+      if(!in.get( c )) // next after '<'
+        throw std::string("xml: unexpected eof");
+
+      eat_delim( c, in, '/', msg );
+      std::string end_name( get_name( c, in ) );
+      if ( e->name != end_name )
+        throw std::string("xml syntax error: beginning name ")
+          + e->name + " did not match end name " + end_name
+          + " (" + msg + ")";
+
+      eat_delim( c, in, '>', msg );
+      return e;
+    }
+
+ // write ---------------------------------------------------------------//
+
+    void write( const element & e, std::ostream & out )
+    {
+      out << "<" << e.name;
+      if ( !e.attributes.empty() )
+      {
+        for( attribute_list::const_iterator itr = e.attributes.begin();
+             itr != e.attributes.end(); ++itr )
+        {
+          out << " " << itr->name << "=\"" << itr->value << "\"";
+        }
+      }
+      out << ">";
+      if ( !e.elements.empty() )
+      {
+        out << "\n";
+        for( element_list::const_iterator itr = e.elements.begin();
+             itr != e.elements.end(); ++itr )
+        {
+          write( **itr, out );
+        }
+      }
+      if ( !e.content.empty() )
+      {
+        out << e.content;
+      }
+      out << "</" << e.name << ">\n";
+    }
+
+  } // namespace tiny_xml
+} // namespace boost
+

Modified: trunk/tools/regression/src/detail/tiny_xml.hpp
==============================================================================
--- trunk/tools/regression/src/detail/tiny_xml.hpp      (original)
+++ trunk/tools/regression/src/detail/tiny_xml.hpp      Sun Apr  5 07:36:05 2009
@@ -1,70 +1,70 @@
-// tiny XML sub-set tools --------------------------------------------------//
-
-//  (C) Copyright Beman Dawes 2002.  Distributed under the Boost
-//  Software License, Version 1.0. (See accompanying file
-//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-//  Provides self-contained tools for this XML sub-set:
-//
-//    element ::= { "<" name { name "=" "\"" value "\"" } ">"
-//                  {element} [contents] "</" name ">" }
-//
-//  The point of "self-contained" is to minimize tool-chain dependencies.
-
-#ifndef BOOST_TINY_XML_H
-#define BOOST_TINY_XML_H
-
-#include "boost/smart_ptr.hpp" // for shared_ptr
-#include "boost/utility.hpp"   // for noncopyable
-#include <list>
-#include <iostream>
-#include <string>
-
-namespace boost
-{
-  namespace tiny_xml
-  {
-    class element;
-    struct attribute
-    {
-      std::string name;
-      std::string value;
-
-      attribute(){}
-      attribute( const std::string & name, const std::string & value )
-        : name(name), value(value) {}
-    };
-    typedef boost::shared_ptr< element >  element_ptr;
-    typedef std::list< element_ptr  >     element_list;
-    typedef std::list< attribute >        attribute_list;
-
-    class element
- : private boost::noncopyable // because deep copy sematics would be required
-    {
-     public:
-      std::string     name;
-      attribute_list  attributes;
-      element_list    elements;
-      std::string     content;
-
-      element() {}
-      explicit element( const std::string & name ) : name(name) {}
-    };
-
-    element_ptr parse( std::istream & in, const std::string & msg );
-    // Precondition: stream positioned at either the initial "<"
-    // or the first character after the initial "<".
-    // Postcondition: stream positioned at the first character after final
-    //  ">" (or eof).
- // Returns: an element_ptr to an element representing the parsed stream.
-    // Throws: std::string on syntax error. msg appended to what() string.
-
-    void write( const element & e, std::ostream & out );
-
-  }
-}
-
-#endif  // BOOST_TINY_XML_H
-
-
-
+// tiny XML sub-set tools --------------------------------------------------//
+
+//  (C) Copyright Beman Dawes 2002.  Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  Provides self-contained tools for this XML sub-set:
+//
+//    element ::= { "<" name { name "=" "\"" value "\"" } ">"
+//                  {element} [contents] "</" name ">" }
+//
+//  The point of "self-contained" is to minimize tool-chain dependencies.
+
+#ifndef BOOST_TINY_XML_H
+#define BOOST_TINY_XML_H
+
+#include "boost/smart_ptr.hpp" // for shared_ptr
+#include "boost/utility.hpp"   // for noncopyable
+#include <list>
+#include <iostream>
+#include <string>
+
+namespace boost
+{
+  namespace tiny_xml
+  {
+    class element;
+    struct attribute
+    {
+      std::string name;
+      std::string value;
+
+      attribute(){}
+      attribute( const std::string & name, const std::string & value )
+        : name(name), value(value) {}
+    };
+    typedef boost::shared_ptr< element >  element_ptr;
+    typedef std::list< element_ptr  >     element_list;
+    typedef std::list< attribute >        attribute_list;
+
+    class element
+ : private boost::noncopyable // because deep copy sematics would be required
+    {
+     public:
+      std::string     name;
+      attribute_list  attributes;
+      element_list    elements;
+      std::string     content;
+
+      element() {}
+      explicit element( const std::string & name ) : name(name) {}
+    };
+
+    element_ptr parse( std::istream & in, const std::string & msg );
+    // Precondition: stream positioned at either the initial "<"
+    // or the first character after the initial "<".
+    // Postcondition: stream positioned at the first character after final
+    //  ">" (or eof).
+ // Returns: an element_ptr to an element representing the parsed stream.
+    // Throws: std::string on syntax error. msg appended to what() string.
+
+    void write( const element & e, std::ostream & out );
+
+  }
+}
+
+#endif  // BOOST_TINY_XML_H
+
+
+

Modified: trunk/tools/regression/src/detail/tiny_xml_test.cpp
==============================================================================
--- trunk/tools/regression/src/detail/tiny_xml_test.cpp (original)
+++ trunk/tools/regression/src/detail/tiny_xml_test.cpp Sun Apr 5 07:36:05 2009
@@ -1,17 +1,17 @@
-// tiny XML test program ---------------------------------------------------//
-
-//  Copyright Beman Dawes 2002.  Distributed under the Boost
-//  Software License, Version 1.0. (See accompanying file
-//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#include "tiny_xml.hpp"
-
-#include <iostream>
-
-int main()
-{
-  boost::tiny_xml::element_ptr tree( boost::tiny_xml::parse( std::cin ) );
-  boost::tiny_xml::write( *tree, std::cout );
-  return 0;
-}
-
+// tiny XML test program ---------------------------------------------------//
+
+//  Copyright Beman Dawes 2002.  Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "tiny_xml.hpp"
+
+#include <iostream>
+
+int main()
+{
+  boost::tiny_xml::element_ptr tree( boost::tiny_xml::parse( std::cin ) );
+  boost::tiny_xml::write( *tree, std::cout );
+  return 0;
+}
+

Modified: trunk/tools/regression/src/detail/tiny_xml_test.txt
==============================================================================
--- trunk/tools/regression/src/detail/tiny_xml_test.txt (original)
+++ trunk/tools/regression/src/detail/tiny_xml_test.txt Sun Apr 5 07:36:05 2009
@@ -1,12 +1,12 @@
-<root>
-<element-1 at-1="abcd" at-2 = "defg" >
-<element-1a>
-It's Howdy Doody time!
-</element-1a>
-<element-1b>It's not Howdy Doody time!</element-1b>
-</element-1>
-<element-2>
-It's
-Eastern Standard time!
-</element-2>
-</root>
+<root>
+<element-1 at-1="abcd" at-2 = "defg" >
+<element-1a>
+It's Howdy Doody time!
+</element-1a>
+<element-1b>It's not Howdy Doody time!</element-1b>
+</element-1>
+<element-2>
+It's
+Eastern Standard time!
+</element-2>
+</root>

Modified: trunk/tools/regression/src/library_status.cpp
==============================================================================
--- trunk/tools/regression/src/library_status.cpp       (original)
+++ trunk/tools/regression/src/library_status.cpp       Sun Apr  5 07:36:05 2009
@@ -1,983 +1,983 @@
-// Generate Compiler Status HTML from jam regression test output -----------//
-
-//  Copyright Beman Dawes 2002.  Distributed under the Boost
-//  Software License, Version 1.0. (See accompanying file
-//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-//  See http://www.boost.org/tools/regression/ for documentation.
-
-//Note: This version of the original program builds a large table
-//which includes all build variations such as build/release, static/dynamic, etc.
-
-
-/*******************************************************************************
-
-This program was designed to work unchanged on all platforms and
-configurations.  All output which is platform or configuration dependent
-is obtained from external sources such as the .xml file from
-process_jam_log execution, the tools/build/xxx-tools.jam files, or the
-output of the config_info tests.
-
-Please avoid adding platform or configuration dependencies during
-program maintenance.
-
-*******************************************************************************/
-
-#include "boost/filesystem/operations.hpp"
-#include "boost/filesystem/fstream.hpp"
-
-namespace fs = boost::filesystem;
-
-#include "detail/tiny_xml.hpp"
-namespace xml = boost::tiny_xml;
-
-#include "boost/iterator/transform_iterator.hpp"
-
-#include <cstdlib>  // for abort, exit
-#include <string>
-#include <vector>
-#include <set>
-#include <utility>  // for make_pair on STLPort
-#include <map>
-#include <algorithm>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <stdexcept>
-#include <cassert>
-#include <utility>
-
-using std::string;
-
-const string pass_msg( "Pass" );
-const string warn_msg( "<i>Warn</i>" );
-const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
-const string note_msg( "<sup>*</sup>" );
-const string missing_residue_msg( "<i>Missing</i>" );
-
-const std::size_t max_compile_msg_size = 10000;
-
-namespace
-{
-    fs::path boost_root;  // boost-root complete path
- fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
-    bool ignore_pass = false;
-    bool no_warn = false;
-    bool no_links = false;
-
-    fs::directory_iterator end_itr;
-
-    // transform pathname to something html can accept
-    struct char_xlate {
-        typedef char result_type;
-        result_type operator()(char c) const{
-            if(c == '/')
-                return '-';
-            return c;
-        }
-    };
- typedef boost::transform_iterator<char_xlate, std::string::const_iterator> html_from_path;
-
-    template<class I1, class I2>
-    std::ostream & operator<<(
-    std::ostream &os,
-    std::pair<I1, I2> p
-    ){
-        while(p.first != p.second)
-            os << *p.first++;
-        return os;
-    }
-
-    struct col_node {
-        int rows, cols;
-        bool has_leaf;
-        typedef std::map<std::string, col_node> subcolumns_t;
-        subcolumns_t m_subcolumns;
-        bool operator<(const col_node &cn) const;
-        col_node() :
-            has_leaf(false)
-        {}
-        std::pair<int, int> get_spans();
-    };
-
-    std::pair<int, int> col_node::get_spans(){
-        rows = 1;
-        cols = 0;
-        if(has_leaf){
-            cols = 1;
-        }
-        if(! m_subcolumns.empty()){
-            subcolumns_t::iterator itr;
- for(itr = m_subcolumns.begin(); itr != m_subcolumns.end(); ++itr){
-                std::pair<int, int> spans;
-                spans = itr->second.get_spans();
-                rows = std::max(rows, spans.first);
-                cols += spans.second;
-            }
-            ++rows;
-        }
-        return std::make_pair(rows, cols);
-    }
-
-    void build_node_tree(const fs::path & dir_root, col_node & node){
-        fs::path xml_file_path( dir_root / "test_log.xml" );
-        if (fs::exists( xml_file_path ) )
-        {
-            node.has_leaf = true;
-        }
-        fs::directory_iterator itr(dir_root);
-        while(itr != end_itr){
-            if(fs::is_directory(*itr)){
-                std::pair<col_node::subcolumns_t::iterator, bool> result
-                    = node.m_subcolumns.insert(
-                        std::make_pair(itr->leaf(), col_node())
-                    );
-                build_node_tree(*itr, result.first->second);
-            }
-            ++itr;
-        }
-    }
-
-    fs::ofstream report;
-    fs::ofstream links_file;
-    string links_name;
-
-    fs::path notes_path;
-    string notes_html;
-
-    fs::path notes_map_path;
- typedef std::multimap< string, string > notes_map; // key is test_name-toolset,
-    // value is note bookmark
-    notes_map notes;
-
-    string specific_compiler; // if running on one toolset only
-
-    const string empty_string;
-
- // build notes_bookmarks from notes HTML -----------------------------------//
-
-    void build_notes_bookmarks()
-    {
-        if ( notes_map_path.empty() ) return;
-        fs::ifstream notes_map_file( notes_map_path );
-        if ( !notes_map_file )
-        {
- std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl;
-            std::exit( 1 );
-        }
-        string line;
-        while( std::getline( notes_map_file, line ) )
-        {
-            string::size_type pos = 0;
-            if ( (pos = line.find( ',', pos )) == string::npos ) continue;
-            string key(line.substr( 0, pos ) );
-            string bookmark( line.substr( pos+1 ) );
-
- // std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n";
-            notes.insert( notes_map::value_type( key, bookmark ) );
-        }
-    }
-
- // load_notes_html ---------------------------------------------------------//
-
-    bool load_notes_html()
-    {
-        if ( notes_path.empty() ) return false;
-        fs::ifstream notes_file( notes_path );
-        if ( !notes_file )
-        {
- std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl;
-            std::exit( 1 );
-        }
-        string line;
-        bool in_body( false );
-        while( std::getline( notes_file, line ) )
-        {
- if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false;
-            if ( in_body ) notes_html += line;
-            else if ( line.find( "<body>" ) ) in_body = true;
-        }
-        return true;
-    }
-
- // extract object library name from target directory string ----------------//
-
-    string extract_object_library_name( const string & s )
-    {
-        string t( s );
-        string::size_type pos = t.find( "/build/" );
-        if ( pos != string::npos ) pos += 7;
-        else if ( (pos = t.find( "/test/" )) != string::npos ) pos += 6;
-        else return "";
-        return t.substr( pos, t.find( "/", pos ) - pos );
-    }
-
- // element_content ---------------------------------------------------------//
-
-    const string & element_content(
-        const xml::element & root, const string & name )
-    {
-        const static string empty_string;
-        xml::element_list::const_iterator itr;
-        for ( itr = root.elements.begin();
-            itr != root.elements.end() && (*itr)->name != name;
-            ++itr ) {}
- return itr != root.elements.end() ? (*itr)->content : empty_string;
-    }
-
- // find_element ------------------------------------------------------------//
-
-    const xml::element & find_element(
-        const xml::element & root, const string & name )
-    {
-        static const xml::element empty_element;
-        xml::element_list::const_iterator itr;
-        for ( itr = root.elements.begin();
-            itr != root.elements.end() && (*itr)->name != name;
-            ++itr ) {}
- return itr != root.elements.end() ? *((*itr).get()) : empty_element;
-    }
-
- // attribute_value ----------------------------------------------------------//
-
-    const string & attribute_value(
-        const xml::element & element,
-        const string & attribute_name
-    ){
-        xml::attribute_list::const_iterator atr;
-        for(
-            atr = element.attributes.begin();
-            atr != element.attributes.end();
-            ++atr
-        ){
-            if(atr->name == attribute_name)
-                return atr->value;
-        }
-        static const string empty_string;
-        return empty_string;
-    }
-
- // generate_report ---------------------------------------------------------//
-
- // return 0 if nothing generated, 1 otherwise, except 2 if compiler msgs
-    int generate_report(
-        const xml::element & db,
-        const std::string source_library_name,
-        const string & test_type,
-        const fs::path & target_dir,
-        bool pass,
-        bool always_show_run_output
-        )
-    {
-        // compile msgs sometimes modified, so make a local copy
-        string compile( ((pass && no_warn)
-            ? empty_string :  element_content( db, "compile" )) );
-
- const string & link( pass ? empty_string : element_content( db, "link" ) );
-        const string & run( (pass && !always_show_run_output)
-            ? empty_string : element_content( db, "run" ) );
-        string lib( (pass ? empty_string : element_content( db, "lib" )) );
-
- // some compilers output the filename even if there are no errors or - // warnings; detect this if one line of output and it contains no space.
-        string::size_type pos = compile.find( '\n', 1 );
-        if ( pos != string::npos && compile.size()-pos <= 2
-            && compile.find( ' ' ) == string::npos ) compile.clear();
-
-        if ( lib.empty()
-            && (
-                compile.empty() || test_type == "compile_fail"
-            )
-            && link.empty()
-            && run.empty()
-        )
-            return 0;
-
-        int result = 1; // some kind of msg for sure
-
-        // limit compile message length
-        if ( compile.size() > max_compile_msg_size )
-        {
-            compile.erase( max_compile_msg_size );
- compile += "...\n (remainder deleted because of excessive size)\n";
-        }
-
-        links_file << "<h2><a name=\"";
-        links_file << std::make_pair(
-            html_from_path(target_dir.string().begin()),
-            html_from_path(target_dir.string().end())
-            )
-            << "\">"
-            << std::make_pair(
-            html_from_path(target_dir.string().begin()),
-            html_from_path(target_dir.string().end())
-            )
-            ;
-        links_file << "</a></h2>\n";;
-
-        if ( !compile.empty() )
-        {
-            ++result;
-            links_file << "<h3>Compiler output:</h3><pre>"
-                << compile << "</pre>\n";
-        }
-        if ( !link.empty() )
- links_file << "<h3>Linker output:</h3><pre>" << link << "</pre>\n";
-        if ( !run.empty() )
-            links_file << "<h3>Run output:</h3><pre>" << run << "</pre>\n";
-
- // for an object library failure, generate a reference to the object
-        // library failure message, and (once only) generate the object
-        // library failure message itself
- static std::set< string > failed_lib_target_dirs; // only generate once
-        if ( !lib.empty() )
-        {
-            if ( lib[0] == '\n' ) lib.erase( 0, 1 );
- string object_library_name( extract_object_library_name( lib ) );
-
-            // changing the target directory naming scheme breaks
-            // extract_object_library_name()
-            assert( !object_library_name.empty() );
-            if ( object_library_name.empty() )
- std::cerr << "Failed to extract object library name from " << lib << "\n";
-
-            links_file << "<h3>Library build failure: </h3>\n"
-                "See <a href=\"#"
-                << source_library_name << "-"
-                << object_library_name << "-"
-                << std::make_pair(
-                html_from_path(target_dir.string().begin()),
-                html_from_path(target_dir.string().end())
-                )
-                << source_library_name << " - "
-                << object_library_name << " - "
-                << std::make_pair(
-                html_from_path(target_dir.string().begin()),
-                html_from_path(target_dir.string().end())
-                )
-                << "</a>";
- if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() )
-            {
-                failed_lib_target_dirs.insert( lib );
-                fs::path pth( locate_root / lib / "test_log.xml" );
-                fs::ifstream file( pth );
-                if ( file )
-                {
-                    xml::element_ptr db = xml::parse( file, pth.string() );
-                    generate_report(
-                        *db,
-                        source_library_name,
-                        test_type,
-                        target_dir,
-                        false,
-                        false
-                    );
-                }
-                else
-                {
-                    links_file << "<h2><a name=\""
-                        << object_library_name << "-"
-                        << std::make_pair(
-                        html_from_path(target_dir.string().begin()),
-                        html_from_path(target_dir.string().end())
-                        )
-                        << "\">"
-                        << object_library_name << " - "
-                        << std::make_pair(
-                        html_from_path(target_dir.string().begin()),
-                        html_from_path(target_dir.string().end())
-                        )
-                        << "</a></h2>\n"
-                        << "test_log.xml not found\n";
-                }
-            }
-        }
-        return result;
-    }
-
- // add_notes --------------------------------------------------------------//
-
- void add_notes( const string & key, bool fail, string & sep, string & target )
-    {
-        notes_map::const_iterator itr = notes.lower_bound( key );
-        if ( itr != notes.end() && itr->first == key )
-        {
-            for ( ; itr != notes.end() && itr->first == key; ++itr )
-            {
-                string note_desc( itr->second[0] == '-'
-                    ? itr->second.substr( 1 ) : itr->second );
-                if ( fail || itr->second[0] == '-' )
-                {
-                    target += sep;
-                    sep = ",";
-                    target += "<a href=\"";
-                    target += "#";
-                    target += note_desc;
-                    target += "\">";
-                    target += note_desc;
-                    target += "</a>";
-                }
-            }
-        }
-    }
-
- // do_cell ---------------------------------------------------------------//
-    bool do_cell(
-        const fs::path & target_dir,
-        const string & lib_name,
-        string & target,
-        bool profile
-    ){
-        // return true if any results except pass_msg
-        bool pass = false;
-
-        fs::path xml_file_path( target_dir / "test_log.xml" );
-        if ( !fs::exists( xml_file_path ) )
-        {
-            // suppress message because there are too many of them.
-            // "missing" is a legitmate result as its not a requirement
-            // that every test be run in every figuration.
-            //std::cerr << "Missing jam_log.xml in target:\n "
-            //    << target_dir.string() << "\n";
- target += "<td align=\"right\">" + missing_residue_msg + "</td>";
-            return true;
-        }
-
-        int anything_generated = 0;
-        bool note = false;
-
-        fs::ifstream file( xml_file_path );
-        if ( !file ) // could not open jam_log.xml
-        {
-            std::cerr << "Can't open jam_log.xml in target:\n "
-                << target_dir.string() << "\n";
-            target += "<td>" + missing_residue_msg + "</td>";
-            return false;
-        }
-
-        string test_type( "unknown" );
-        bool always_show_run_output( false );
-
-        xml::element_ptr dbp = xml::parse( file, xml_file_path.string() );
-        const xml::element & db( *dbp );
-        test_type = attribute_value( db, "test-type" );
-        always_show_run_output
-            = attribute_value( db, "show-run-output" ) == "true";
-
-        std::string test_type_base( test_type );
-        if ( test_type_base.size() > 5 )
-        {
-            const string::size_type trailer = test_type_base.size() - 5;
-            if ( test_type_base.substr( trailer ) == "_fail" )
-            {
-                test_type_base.erase( trailer );
-            }
-        }
-        if ( test_type_base.size() > 4 )
-        {
-            const string::size_type trailer = test_type_base.size() - 4;
-            if ( test_type_base.substr( trailer ) == "_pyd" )
-            {
-                test_type_base.erase( trailer );
-            }
-        }
- const xml::element & test_type_element( find_element( db, test_type_base ) );
-
-        pass = !test_type_element.name.empty()
-            && attribute_value( test_type_element, "result" ) != "fail";
-
-        if (!no_links){
-            if(!test_type_element.name.empty())
- note = attribute_value( test_type_element, "result" ) == "note";
-            anything_generated =
-                generate_report(
-                db,
-                lib_name,
-                test_type,
-                target_dir,
-                pass,
-                always_show_run_output || note
-            );
-        }
-
-        // generate the status table cell pass/warn/fail HTML
-        target += "<td align=\"right\">";
-        if ( anything_generated != 0 )
-        {
-            target += "<a href=\"";
-            target += links_name;
-            target += "#";
-            std::copy(
-                html_from_path(target_dir.string().begin()),
-                html_from_path(target_dir.string().end()),
-                std::back_inserter(target)
-                );
-            target += "\">";
-            target += pass
-                ? (anything_generated < 2 ? pass_msg : warn_msg)
-                : fail_msg;
-            target += "</a>";
-            if ( pass && note ) target += note_msg;
-        }
-        else  target += pass ? pass_msg : fail_msg;
-
-        // if profiling
-        if(profile && pass){
-            // add link to profile
-            target += " <a href=\"";
-            target += (target_dir / "profile.txt").string();
-            target += "\"><i>Profile</i></a>";
-        }
-
-        // if notes, generate the superscript HTML
-//        if ( !notes.empty() )
-//            target += get_notes( toolset, lib_name, test_name, !pass );
-
-        target += "</td>";
-        return (anything_generated != 0) || !pass;
-    }
-
-    bool visit_node_tree(
-        const col_node & node,
-        fs::path dir_root,
-        const string & lib_name,
-        string & target,
-        bool profile
-    ){
-        bool retval = false;
-        if(node.has_leaf){
-            retval = do_cell(
-                dir_root,
-                lib_name,
-                target,
-                profile
-            );
-        }
-
-        col_node::subcolumns_t::const_iterator col_itr;
-        for(
-            col_itr = node.m_subcolumns.begin();
-            col_itr != node.m_subcolumns.end();
-            ++col_itr
-        ){
-            fs::path subdir = dir_root / col_itr->first;
-            retval |= visit_node_tree(
-                col_itr->second,
-                subdir,
-                lib_name,
-                target,
-                col_itr->first == "profile"
-            );
-        }
-        return retval;
-    }
-
-    // emit results for each test
-    void do_row(
-        col_node test_node,
-        const fs::path & test_dir,
-        const string & lib_name,
-        const string & test_name,
-        string & target
-    ){
-        string::size_type row_start_pos = target.size();
-
-        target += "<tr>";
-
-        target += "<td>";
- //target += "<a href=\"" + url_prefix_dir_view + "/libs/" + lib_name + "\">";
-        target += test_name;
-        target += "</a>";
-        target += "</td>";
-
-//        target += "<td>" + test_type + "</td>";
-
-        bool no_warn_save = no_warn;
-
-//        if ( test_type.find( "fail" ) != string::npos ) no_warn = true;
-
-        // emit cells on this row
-        bool anything_to_report = visit_node_tree(
-            test_node,
-            test_dir,
-            lib_name,
-            target,
-            false
-        );
-
-        target += "</tr>";
-
-        if ( ignore_pass
-        && ! anything_to_report )
-            target.erase( row_start_pos );
-
-        no_warn = no_warn_save;
-    }
-
- // do_table_body -----------------------------------------------------------//
-
-    void do_table_body(
-        col_node root_node,
-        const string & lib_name,
-        const fs::path & test_lib_dir
-    ){
-        // rows are held in a vector so they can be sorted, if desired.
-        std::vector<string> results;
-
- for ( fs::directory_iterator itr( test_lib_dir ); itr != end_itr; ++itr )
-        {
-            if(! fs::is_directory(*itr))
-                continue;
-
-            string test_name = itr->leaf();
-            // strip off the ".test" is there is one
-            string::size_type s = test_name.find( ".test" );
-            if(string::npos != s)
-                test_name.resize(s);
-
-            results.push_back( std::string() );
-            do_row(
-                root_node, //*test_node_itr++,
-                *itr, // test dir
-                lib_name,
-                test_name,
-                results[results.size()-1]
-            );
-        }
-
-        std::sort( results.begin(), results.end() );
-
-        for (
-            std::vector<string>::iterator v(results.begin());
-            v != results.end();
-            ++v
-        ){
-            report << *v << "\n";
-        }
-    }
-
- // column header-----------------------------------------------------------//
-    int header_depth(const col_node & root){
-        col_node::subcolumns_t::const_iterator itr;
-        int max_depth = 1;
- for(itr = root.m_subcolumns.begin(); itr != root.m_subcolumns.end(); ++itr){
-            max_depth = std::max(max_depth, itr->second.rows);
-        }
-        return max_depth;
-    }
-
-    void header_cell(int rows, int cols, const std::string & name){
-        // add row cells
-        report << "<td align=\"center\" " ;
-        if(1 < cols)
-            report << "colspan=\"" << cols << "\" " ;
-        if(1 < rows)
-            // span rows to the end the header
-            report << "rowspan=\"" << rows << "\" " ;
-        report << ">" ;
-        report << name;
-        report << "</td>\n";
-    }
-
-    void emit_column_headers(
-        const col_node & node,
-        int display_row,
-        int current_row,
-        int row_count
-    ){
-        if(current_row < display_row){
-            if(! node.m_subcolumns.empty()){
-                col_node::subcolumns_t::const_iterator itr;
- for(itr = node.m_subcolumns.begin(); itr != node.m_subcolumns.end(); ++itr){ - emit_column_headers(itr->second, display_row, current_row + 1, row_count);
-                }
-            }
-            return;
-        }
-        if(node.has_leaf && ! node.m_subcolumns.empty()){
-            header_cell(row_count - current_row, 1, std::string(""));
-        }
-
-        col_node::subcolumns_t::const_iterator itr;
- for(itr = node.m_subcolumns.begin(); itr != node.m_subcolumns.end(); ++itr){
-            if(1 == itr->second.rows)
- header_cell(row_count - current_row, itr->second.cols, itr->first);
-            else
-                header_cell(1, itr->second.cols, itr->first);
-        }
-    }
-
-    fs::path find_lib_test_dir(){
-        // walk up from the path were we started until we find
-        // bin or bin.v2
-
-        fs::path::const_iterator leaf_itr = fs::initial_path().end();
-        fs::path test_lib_dir = fs::initial_path();
-        for(;;){
-            if(fs::is_directory( test_lib_dir / "bin.v2")){
-                test_lib_dir /= "bin.v2";
-                break;
-            }
-            if(fs::is_directory( test_lib_dir / "bin")){
-                // v1 includes the word boost
-                test_lib_dir /= "bin";
-                test_lib_dir /= "boost";
-                break;
-            }
-            if(test_lib_dir.empty())
-                throw std::string("binary path not found");
-            if(*leaf_itr != "libs")
-                --leaf_itr;
-            test_lib_dir.remove_leaf();
-        }
-
-        if(leaf_itr == fs::initial_path().end())
- throw std::string("must be run from within a library directory");
-
-        while(leaf_itr != fs::initial_path().end()){
-            test_lib_dir /= *leaf_itr++;    // append "libs"
-        }
-        return test_lib_dir;
-    }
-
-    // note : uncomment the #if/#endif and what this compile !!!
-    string find_lib_name(fs::path lib_test_dir){
-        unsigned int count;
-        fs::path::iterator e_itr = lib_test_dir.end();
-        for(count =  0;; ++count){
-            if(*--e_itr == "libs")
-                break;
-            if(lib_test_dir.empty())
- throw std::string("must be run from within a library directory");
-        }
-        string library_name;
-        for(;;){
-            library_name.append(*++e_itr);
-            if(1 == --count)
-                break;
-            library_name.append("/");
-        }
-        return library_name;
-    }
-
-    fs::path find_boost_root(){
-        fs::path boost_root = fs::initial_path();
-        for(;;){
-            if(fs::is_directory( boost_root / "boost")){
-                break;
-            }
-            if(boost_root.empty())
-                throw std::string("boost root not found");
-            boost_root.remove_leaf();
-        }
-
-        return boost_root;
-    }
-
- // do_table ----------------------------------------------------------------//
-    void do_table(const string & lib_name)
-    {
-        col_node root_node;
-
-        fs::path lib_test_dir = find_lib_test_dir();
-
- for ( fs::directory_iterator itr(lib_test_dir); itr != end_itr; ++itr )
-        {
-            if(! fs::is_directory(*itr))
-                continue;
-            build_node_tree(*itr, root_node);
-        }
-
-        // visit directory nodes and record nodetree
- report << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n";
-
-        // emit
-        root_node.get_spans();
-        int row_count = header_depth(root_node);
-        report << "<tr>\n";
-        report << "<td rowspan=\"" << row_count << "\">Test Name</td>\n";
-
-        // emit column headers
-        int row_index = 0;
-        for(;;){
-            emit_column_headers(root_node, row_index, 0, row_count);
-            report << "</tr>" ;
-            if(++row_index == row_count)
-                break;
-            report << "<tr>\n";
-        }
-
-        // now the rest of the table body
-        do_table_body(root_node, lib_name, lib_test_dir);
-
-        report << "</table>\n";
-   }
-}// unnamed namespace
-
-// main --------------------------------------------------------------------//
-
-#define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
-#include <boost/test/included/prg_exec_monitor.hpp>
-
-int cpp_main( int argc, char * argv[] ) // note name!
-{
-    fs::path comment_path;
-    while ( argc > 1 && *argv[1] == '-' )
-    {
-        if ( argc > 2 && std::strcmp( argv[1], "--compiler" ) == 0 )
-        { specific_compiler = argv[2]; --argc; ++argv; }
- else if ( argc > 2 && std::strcmp( argv[1], "--locate-root" ) == 0 )
-        { locate_root = fs::path( argv[2], fs::native ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--boost-root" ) == 0 )
-        { boost_root = fs::path( argv[2], fs::native ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--comment" ) == 0 )
-        { comment_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--notes" ) == 0 )
-        { notes_path = fs::path( argv[2], fs::native ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--notes-map" ) == 0 )
- { notes_map_path = fs::path( argv[2], fs::native ); --argc; ++argv; } - else if ( std::strcmp( argv[1], "--ignore-pass" ) == 0 ) ignore_pass = true; - else if ( std::strcmp( argv[1], "--no-warn" ) == 0 ) no_warn = true;
-        else if ( std::strcmp( argv[1], "--v2" ) == 0 )
-        {--argc; ++argv ;} // skip
-        else if ( argc > 2 && std::strcmp( argv[1], "--jamfile" ) == 0)
-        {--argc; ++argv;} // skip
- else { std::cerr << "Unknown option: " << argv[1] << "\n"; argc = 1; }
-        --argc;
-        ++argv;
-    }
-
-    if ( argc != 2 && argc != 3 )
-    {
-        std::cerr <<
-            "Usage: library_status [options...] status-file [links-file]\n"
-            "  boost-root is the path to the boost tree root directory.\n"
-            "  status-file and links-file are paths to the output files.\n"
-            "  options: --compiler name     Run for named compiler only\n"
- " --ignore-pass Do not report tests which pass all compilers\n" - " --no-warn Warnings not reported if test passes\n"
-                   "           --boost-root path default derived from current 
path.\n"
- " --locate-root path Path to ALL_LOCATE_TARGET for bjam;\n"
-                   "                               default boost-root.\n"
-            "           --comment path      Path to file containing HTML\n"
- " to be copied into status-file.\n"
-            "           --notes path        Path to file containing HTML\n"
- " to be copied into status-file.\n" - " --notes-map path Path to file of toolset/test,n lines, where\n" - " n is number of note bookmark in --notes file.\n" - "Example: compiler_status --compiler gcc /boost-root cs.html cs-links.html\n" - "Note: Only the leaf of the links-file path and --notes file string are\n" - "used in status-file HTML links. Thus for browsing, status-file,\n" - "links-file, and --notes file must all be in the same directory.\n"
-            ;
-        return 1;
-    }
-
-       if(boost_root.empty())
-               boost_root = find_boost_root();
-       if ( locate_root.empty() )
-               locate_root = boost_root;
-
-    report.open( fs::path( argv[1], fs::native ) );
-    if ( !report )
-    {
- std::cerr << "Could not open report output file: " << argv[2] << std::endl;
-        return 1;
-    }
-
-    if ( argc == 3 )
-    {
-        fs::path links_path( argv[2], fs::native );
-        links_name = links_path.leaf();
-        links_file.open( links_path );
-        if ( !links_file )
-        {
- std::cerr << "Could not open links output file: " << argv[3] << std::endl;
-            return 1;
-        }
-    }
-    else no_links = true;
-
-    build_notes_bookmarks();
-
-    const string library_name = find_lib_name(fs::initial_path());
-
-    char run_date[128];
-    std::time_t tod;
-    std::time( &tod );
-    std::strftime( run_date, sizeof(run_date),
-        "%X UTC, %A %d %B %Y", std::gmtime( &tod ) );
-
-    report
-        << "<html>\n"
-        << "<head>\n"
-        << "<title>Boost Library Status Automatic Test</title>\n"
-        << "</head>\n"
-        << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
-        << "<table border=\"0\">\n"
-        << "<tr>\n"
-        << "<td><img border=\"0\" "
-        << "src=\""
-        << boost_root / "boost.png"
-        << "\" width=\"277\" "
-        << "height=\"86\"></td>\n"
-        << "<td>\n"
-        << "<h1>Library Status: " + library_name + "</h1>\n"
-        << "<b>Run Date:</b> "
-        << run_date
-        << "\n"
-        ;
-
-    if ( !comment_path.empty() )
-    {
-        fs::ifstream comment_file( comment_path );
-        if ( !comment_file )
-        {
- std::cerr << "Could not open \"--comment\" input file: " << comment_path.string() << std::endl;
-            return 1;
-        }
-        char c;
-        while ( comment_file.get( c ) ) { report.put( c ); }
-    }
-
-    report << "</td>\n</table>\n<br>\n";
-
-    if ( !no_links )
-    {
-        links_file
-            << "<html>\n"
-            << "<head>\n"
-            << "<title>Boost Library Status Error Log</title>\n"
-            << "</head>\n"
-            << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
-            << "<table border=\"0\">\n"
-            << "<tr>\n"
-            << "<td><img border=\"0\" src=\""
-            << boost_root / "boost.png"
-            << "\" width=\"277\" "
-            << "height=\"86\"></td>\n"
-            << "<td>\n"
-            << "<h1>Library Status: " + library_name + "</h1>\n"
-            << "<b>Run Date:</b> "
-            << run_date
-            << "\n</td>\n</table>\n<br>\n"
-            ;
-    }
-
-    do_table(library_name);
-
-    if ( load_notes_html() ) report << notes_html << "\n";
-
-    report << "</body>\n"
-        "</html>\n"
-        ;
-
-    if ( !no_links )
-    {
-        links_file
-            << "</body>\n"
-            "</html>\n"
-            ;
-    }
-    return 0;
-}
+// Generate Compiler Status HTML from jam regression test output -----------//
+
+//  Copyright Beman Dawes 2002.  Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/tools/regression/ for documentation.
+
+//Note: This version of the original program builds a large table
+//which includes all build variations such as build/release, static/dynamic, etc.
+
+
+/*******************************************************************************
+
+This program was designed to work unchanged on all platforms and
+configurations.  All output which is platform or configuration dependent
+is obtained from external sources such as the .xml file from
+process_jam_log execution, the tools/build/xxx-tools.jam files, or the
+output of the config_info tests.
+
+Please avoid adding platform or configuration dependencies during
+program maintenance.
+
+*******************************************************************************/
+
+#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem/fstream.hpp"
+
+namespace fs = boost::filesystem;
+
+#include "detail/tiny_xml.hpp"
+namespace xml = boost::tiny_xml;
+
+#include "boost/iterator/transform_iterator.hpp"
+
+#include <cstdlib>  // for abort, exit
+#include <string>
+#include <vector>
+#include <set>
+#include <utility>  // for make_pair on STLPort
+#include <map>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <stdexcept>
+#include <cassert>
+#include <utility>
+
+using std::string;
+
+const string pass_msg( "Pass" );
+const string warn_msg( "<i>Warn</i>" );
+const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
+const string note_msg( "<sup>*</sup>" );
+const string missing_residue_msg( "<i>Missing</i>" );
+
+const std::size_t max_compile_msg_size = 10000;
+
+namespace
+{
+    fs::path boost_root;  // boost-root complete path
+ fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
+    bool ignore_pass = false;
+    bool no_warn = false;
+    bool no_links = false;
+
+    fs::directory_iterator end_itr;
+
+    // transform pathname to something html can accept
+    struct char_xlate {
+        typedef char result_type;
+        result_type operator()(char c) const{
+            if(c == '/')
+                return '-';
+            return c;
+        }
+    };
+ typedef boost::transform_iterator<char_xlate, std::string::const_iterator> html_from_path;
+
+    template<class I1, class I2>
+    std::ostream & operator<<(
+    std::ostream &os,
+    std::pair<I1, I2> p
+    ){
+        while(p.first != p.second)
+            os << *p.first++;
+        return os;
+    }
+
+    struct col_node {
+        int rows, cols;
+        bool has_leaf;
+        typedef std::map<std::string, col_node> subcolumns_t;
+        subcolumns_t m_subcolumns;
+        bool operator<(const col_node &cn) const;
+        col_node() :
+            has_leaf(false)
+        {}
+        std::pair<int, int> get_spans();
+    };
+
+    std::pair<int, int> col_node::get_spans(){
+        rows = 1;
+        cols = 0;
+        if(has_leaf){
+            cols = 1;
+        }
+        if(! m_subcolumns.empty()){
+            subcolumns_t::iterator itr;
+ for(itr = m_subcolumns.begin(); itr != m_subcolumns.end(); ++itr){
+                std::pair<int, int> spans;
+                spans = itr->second.get_spans();
+                rows = std::max(rows, spans.first);
+                cols += spans.second;
+            }
+            ++rows;
+        }
+        return std::make_pair(rows, cols);
+    }
+
+    void build_node_tree(const fs::path & dir_root, col_node & node){
+        fs::path xml_file_path( dir_root / "test_log.xml" );
+        if (fs::exists( xml_file_path ) )
+        {
+            node.has_leaf = true;
+        }
+        fs::directory_iterator itr(dir_root);
+        while(itr != end_itr){
+            if(fs::is_directory(*itr)){
+                std::pair<col_node::subcolumns_t::iterator, bool> result
+                    = node.m_subcolumns.insert(
+                        std::make_pair(itr->filename(), col_node())
+                    );
+                build_node_tree(*itr, result.first->second);
+            }
+            ++itr;
+        }
+    }
+
+    fs::ofstream report;
+    fs::ofstream links_file;
+    string links_name;
+
+    fs::path notes_path;
+    string notes_html;
+
+    fs::path notes_map_path;
+ typedef std::multimap< string, string > notes_map; // key is test_name-toolset,
+    // value is note bookmark
+    notes_map notes;
+
+    string specific_compiler; // if running on one toolset only
+
+    const string empty_string;
+
+ // build notes_bookmarks from notes HTML -----------------------------------//
+
+    void build_notes_bookmarks()
+    {
+        if ( notes_map_path.empty() ) return;
+        fs::ifstream notes_map_file( notes_map_path );
+        if ( !notes_map_file )
+        {
+ std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl;
+            std::exit( 1 );
+        }
+        string line;
+        while( std::getline( notes_map_file, line ) )
+        {
+            string::size_type pos = 0;
+            if ( (pos = line.find( ',', pos )) == string::npos ) continue;
+            string key(line.substr( 0, pos ) );
+            string bookmark( line.substr( pos+1 ) );
+
+ // std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n";
+            notes.insert( notes_map::value_type( key, bookmark ) );
+        }
+    }
+
+ // load_notes_html ---------------------------------------------------------//
+
+    bool load_notes_html()
+    {
+        if ( notes_path.empty() ) return false;
+        fs::ifstream notes_file( notes_path );
+        if ( !notes_file )
+        {
+ std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl;
+            std::exit( 1 );
+        }
+        string line;
+        bool in_body( false );
+        while( std::getline( notes_file, line ) )
+        {
+ if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false;
+            if ( in_body ) notes_html += line;
+            else if ( line.find( "<body>" ) ) in_body = true;
+        }
+        return true;
+    }
+
+ // extract object library name from target directory string ----------------//
+
+    string extract_object_library_name( const string & s )
+    {
+        string t( s );
+        string::size_type pos = t.find( "/build/" );
+        if ( pos != string::npos ) pos += 7;
+        else if ( (pos = t.find( "/test/" )) != string::npos ) pos += 6;
+        else return "";
+        return t.substr( pos, t.find( "/", pos ) - pos );
+    }
+
+ // element_content ---------------------------------------------------------//
+
+    const string & element_content(
+        const xml::element & root, const string & name )
+    {
+        const static string empty_string;
+        xml::element_list::const_iterator itr;
+        for ( itr = root.elements.begin();
+            itr != root.elements.end() && (*itr)->name != name;
+            ++itr ) {}
+ return itr != root.elements.end() ? (*itr)->content : empty_string;
+    }
+
+ // find_element ------------------------------------------------------------//
+
+    const xml::element & find_element(
+        const xml::element & root, const string & name )
+    {
+        static const xml::element empty_element;
+        xml::element_list::const_iterator itr;
+        for ( itr = root.elements.begin();
+            itr != root.elements.end() && (*itr)->name != name;
+            ++itr ) {}
+ return itr != root.elements.end() ? *((*itr).get()) : empty_element;
+    }
+
+ // attribute_value ----------------------------------------------------------//
+
+    const string & attribute_value(
+        const xml::element & element,
+        const string & attribute_name
+    ){
+        xml::attribute_list::const_iterator atr;
+        for(


==============================================================================
Diff truncated at 200k characters

Other related posts:

  • » [boost-doc-zh commit] r236 - boost/tools/regression - codesite-noreply