From b23f4c3efee981f10bf100970b6db5602e955ba1 Mon Sep 17 00:00:00 2001
From: zosrothko
Date: Wed, 1 Nov 2017 09:03:10 +0100
Subject: [PATCH] Backport from feature-gradle
Signed-off-by: zosrothko
---
Foundation/include/Poco/Environment.h | 127 ++
Foundation/src/Environment.cpp | 166 ++
PocoDoc/cfg/mkdoc-poco.xml | 135 ++
PocoDoc/cfg/mkdocumentation.xml | 117 ++
PocoDoc/src/DocWriter.cpp | 2377 +++++++++++++++++++++++++
PocoDoc/src/DocWriter.h | 227 +++
PocoDoc/src/PocoDoc.cpp | 494 +++++
7 files changed, 3643 insertions(+)
create mode 100644 Foundation/include/Poco/Environment.h
create mode 100644 Foundation/src/Environment.cpp
create mode 100644 PocoDoc/cfg/mkdoc-poco.xml
create mode 100644 PocoDoc/cfg/mkdocumentation.xml
create mode 100644 PocoDoc/src/DocWriter.cpp
create mode 100644 PocoDoc/src/DocWriter.h
create mode 100644 PocoDoc/src/PocoDoc.cpp
diff --git a/Foundation/include/Poco/Environment.h b/Foundation/include/Poco/Environment.h
new file mode 100644
index 000000000..8faf7b5f7
--- /dev/null
+++ b/Foundation/include/Poco/Environment.h
@@ -0,0 +1,127 @@
+//
+// Environment.h
+//
+// Library: Foundation
+// Package: Core
+// Module: Environment
+//
+// Definition of the Environment class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Foundation_Environment_INCLUDED
+#define Foundation_Environment_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Environment
+ /// This class provides access to environment variables
+ /// and some general system information.
+{
+public:
+ typedef UInt8 NodeId[6]; /// Ethernet address.
+
+ static std::string get(const std::string& name);
+ /// Returns the value of the environment variable
+ /// with the given name. Throws a NotFoundException
+ /// if the variable does not exist.
+
+ static std::string get(const std::string& name, const std::string& defaultValue);
+ /// Returns the value of the environment variable
+ /// with the given name. If the environment variable
+ /// is undefined, returns defaultValue instead.
+
+ static bool has(const std::string& name);
+ /// Returns true iff an environment variable
+ /// with the given name is defined.
+
+ static void set(const std::string& name, const std::string& value);
+ /// Sets the environment variable with the given name
+ /// to the given value.
+
+ static std::string osName();
+ /// Returns the operating system name.
+
+ static std::string osDisplayName();
+ /// Returns the operating system name in a
+ /// "user-friendly" way.
+ ///
+ /// Currently this is only implemented for
+ /// Windows. There it will return names like
+ /// "Windows XP" or "Windows 7/Server 2008 SP2".
+ /// On other platforms, returns the same as
+ /// osName().
+
+ static std::string osVersion();
+ /// Returns the operating system version.
+
+ static std::string osArchitecture();
+ /// Returns the operating system architecture.
+
+ static std::string nodeName();
+ /// Returns the node (or host) name.
+
+ static void nodeId(NodeId& id);
+ /// Returns the Ethernet address of the first Ethernet
+ /// adapter found on the system.
+ ///
+ /// Throws a SystemException if no Ethernet adapter is available.
+
+ static std::string nodeId();
+ /// Returns the Ethernet address (format "xx:xx:xx:xx:xx:xx")
+ /// of the first Ethernet adapter found on the system.
+ ///
+ /// Throws a SystemException if no Ethernet adapter is available.
+
+ static unsigned processorCount();
+ /// Returns the number of processors installed in the system.
+ ///
+ /// If the number of processors cannot be determined, returns 1.
+
+ static Poco::UInt32 libraryVersion();
+ /// Returns the POCO C++ Libraries version as a hexadecimal
+ /// number in format 0xAABBCCDD, where
+ /// - AA is the major version number,
+ /// - BB is the minor version number,
+ /// - CC is the revision number, and
+ /// - DD is the patch level number.
+ ///
+ /// Some patch level ranges have special meanings:
+ /// - Dx mark development releases,
+ /// - Ax mark alpha releases, and
+ /// - Bx mark beta releases.
+
+ static Poco::Int32 os();
+ /// Return the operating system as defined
+ /// in the include Foundation/Platform.h (POCO_OS)
+
+ static Poco::Int32 cpu();
+ /// Return the underlying cpu that runs this operating system
+ /// as defined in Foundation/Platform (POCO_ARCH)
+
+ static bool osFamilyUnix();
+ /// Return true if the operating system belongs to the Linux family
+
+ static bool osFamilyWindows();
+ /// Return true if the operating system belongs to the Windows family
+
+ static bool osFamilyVms();
+ /// Return true if the operating system belongs to the VMS family
+
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Environment_INCLUDED
diff --git a/Foundation/src/Environment.cpp b/Foundation/src/Environment.cpp
new file mode 100644
index 000000000..5509aa791
--- /dev/null
+++ b/Foundation/src/Environment.cpp
@@ -0,0 +1,166 @@
+//
+// Environment.cpp
+//
+// Library: Foundation
+// Package: Core
+// Module: Environment
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Environment.h"
+#include "Poco/Version.h"
+#include
+#include // sprintf()
+
+
+#if defined(POCO_OS_FAMILY_VMS)
+#include "Environment_VMS.cpp"
+#elif defined(POCO_VXWORKS)
+#include "Environment_VX.cpp"
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Environment_UNIX.cpp"
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#if defined(_WIN32_WCE)
+#include "Environment_WINCE.cpp"
+#else
+#include "Environment_WIN32.cpp"
+#endif
+#endif
+
+
+namespace Poco {
+
+
+std::string Environment::get(const std::string& name)
+{
+ return EnvironmentImpl::getImpl(name);
+}
+
+
+std::string Environment::get(const std::string& name, const std::string& defaultValue)
+{
+ if (has(name))
+ return get(name);
+ else
+ return defaultValue;
+}
+
+
+bool Environment::has(const std::string& name)
+{
+ return EnvironmentImpl::hasImpl(name);
+}
+
+
+void Environment::set(const std::string& name, const std::string& value)
+{
+ EnvironmentImpl::setImpl(name, value);
+}
+
+
+std::string Environment::osName()
+{
+ return EnvironmentImpl::osNameImpl();
+}
+
+
+std::string Environment::osDisplayName()
+{
+ return EnvironmentImpl::osDisplayNameImpl();
+}
+
+
+std::string Environment::osVersion()
+{
+ return EnvironmentImpl::osVersionImpl();
+}
+
+
+std::string Environment::osArchitecture()
+{
+ return EnvironmentImpl::osArchitectureImpl();
+}
+
+
+std::string Environment::nodeName()
+{
+ return EnvironmentImpl::nodeNameImpl();
+}
+
+
+std::string Environment::nodeId()
+{
+ NodeId id;
+ nodeId(id);
+ char result[18];
+ std::sprintf(result, "%02x:%02x:%02x:%02x:%02x:%02x",
+ id[0],
+ id[1],
+ id[2],
+ id[3],
+ id[4],
+ id[5]);
+ return std::string(result);
+}
+
+
+void Environment::nodeId(NodeId& id)
+{
+ return EnvironmentImpl::nodeIdImpl(id);
+}
+
+
+unsigned Environment::processorCount()
+{
+ return EnvironmentImpl::processorCountImpl();
+}
+
+
+Poco::UInt32 Environment::libraryVersion()
+{
+ return POCO_VERSION;
+}
+
+Poco::Int32 Environment::os()
+{
+ return POCO_OS;
+}
+
+Poco::Int32 Environment::cpu()
+{
+ return POCO_ARCH;
+}
+
+bool Environment::osFamilyUnix()
+{
+#if defined(POCO_OS_FAMILY_UNIX)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool Environment::osFamilyWindows()
+{
+#if defined(POCO_OS_FAMILY_WINDOWS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool Environment::osFamilyVms()
+{
+#if defined(POCO_OS_FAMILY_VMS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+} // namespace Poco
diff --git a/PocoDoc/cfg/mkdoc-poco.xml b/PocoDoc/cfg/mkdoc-poco.xml
new file mode 100644
index 000000000..19e62ccb9
--- /dev/null
+++ b/PocoDoc/cfg/mkdoc-poco.xml
@@ -0,0 +1,135 @@
+
+
+
+
+ ${PocoBuild}/*/include/Poco/*.h
+ ${PocoBuild}/*/include/Poco/*/*.h
+ ${PocoBuild}/*/include/Poco/*/*/*.h
+ ${PocoBuild}/*/include/Poco/*/*.h
+ ${PocoBuild}/*/*/include/Poco/*/*/*.h
+
+
+ *_*.h,
+ expat*.h,
+ zconf.h,
+ zlib.h,
+ Alignment.h,
+ QName.h,
+ CppUnitException.h,
+ Constants.h,
+ inffast.h,
+ ${PocoBuild}/PDF/include/*.h,
+ ${PocoBuild}/CppParser/include/*.h
+
+
+
+ ${PocoBuild}/doc/*.page,
+ ${PocoBuild}/*/doc/*.page
+ ${PocoBuild}/*/*/doc/*.page
+
+
+ ${PocoBase}/PocoDoc/resources/css,
+ ${PocoBase}/PocoDoc/resources/js,
+ ${PocoBase}/PocoDoc/resources/images,
+ ${PocoBase}/PocoDoc/resources/index.thtml,
+ ${PocoBuild}/*/doc/images
+
+
+
+ cl.exe
+
+ ${Includes},
+ /I${PocoBase}/openssl/include
+ /I${VC}/include,
+ /I${WDK}/shared
+ /I${WDK}/um
+ /I${WDK}/ucrt
+ /nologo,
+ /D_DEBUG,
+ /E,
+ /C,
+ /DPOCO_NO_GCC_API_ATTRIBUTE
+ /DPOCO_NO_WINDOWS_H
+
+ ${VC}/bin
+ true
+
+
+ ${CXX} ${CXXFLAGS}
+
+ ${Includes},
+ -I/usr/local/mysql/include,
+ -I/usr/include/mysql,
+ -I/usr/include/postgresql,
+ -D_DEBUG,
+ -E,
+ -C,
+ -DPOCO_NO_GCC_API_ATTRIBUTE
+ -DPOCO_NO_WINDOWS_H
+
+
+ true
+
+
+ EN
+ utf-8
+ POCO C++ Libraries
+ Applied Informatics Software Engineering GmbH and Contributors
+ http://pocoproject.org/
+
+
+
+ All Base Classes
+ All Symbols
+ Anonymous
+ Constructors
+ Class
+ Deprecated
+ Description
+ Destructor
+ Direct Base Classes
+ Enumerations
+ Functions
+
+ if and only if
+ Inheritance
+ Inherited Functions
+ is deprecated and should no longer be used
+ Known Derived Classes
+ Library
+ Member Functions
+ Member Summary
+ more...
+ Namespaces
+ Namespace
+ Nested Classes
+ Package
+ Packages
+ Package Index
+ See also
+ Struct
+ Symbol Index
+ This
+ Types
+ Variables
+ Contents
+ User Guides and Tutorials
+ Introduction
+
+
+
+
+
+
+ c1
+ warning
+
+
+
+
+ ConsoleChannel
+ %s: [%p] %t
+
+
+
+
diff --git a/PocoDoc/cfg/mkdocumentation.xml b/PocoDoc/cfg/mkdocumentation.xml
new file mode 100644
index 000000000..affe2828c
--- /dev/null
+++ b/PocoDoc/cfg/mkdocumentation.xml
@@ -0,0 +1,117 @@
+
+
+
+
+ ${PocoBuild}/*/include/Poco/*.h
+ ${PocoBuild}/*/include/Poco/*/*.h
+ ${PocoBuild}/*/include/Poco/*/*/*.h
+ ${PocoBuild}/*/include/Poco/*/*.h
+ ${PocoBuild}/*/*/include/Poco/*/*/*.h
+
+
+ *_*.h,
+ expat*.h,
+ zconf.h,
+ zlib.h,
+ XMLStreamParser.h,
+ CppUnitException.h,
+ RepeatedTest.h,
+
+
+
+ ${PocoBuild}/doc/*.page,
+ ${PocoBuild}/*/doc/*.page
+ ${PocoBuild}/*/*/doc/*.page
+
+
+ ${PocoBase}/PocoDoc/resources/css,
+ ${PocoBase}/PocoDoc/resources/js,
+ ${PocoBase}/PocoDoc/resources/images,
+ ${PocoBase}/PocoDoc/resources/index.thtml,
+ ${PocoBuild}/*/doc/images
+
+
+ C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\cl.exe
+
+ ${Includes},
+ -I/usr/local/mysql/include,
+ -I/usr/include/mysql,
+ -I/usr/include/postgresql,
+ /I${PocoBase}/openssl/include
+ /IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include,
+ /IC:\Program Files (x86)\Windows Kits\8.1\Include\shared,
+ /IC:\Program Files (x86)\Windows Kits\8.1\Include\um,
+ /IC:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\ucrt,
+ /nologo,
+ -D_DEBUG,
+ -E,
+ -C,
+ -DPOCO_NO_GCC_API_ATTRIBUTE
+ -DPOCO_NO_WINDOWS_H
+
+
+ true
+
+ EN
+ utf-8
+ Applied Informatics C++ Libraries and Tools
+ Applied Informatics Software Engineering GmbH and Contributors
+ http://www.appinf.com/
+ images/headerlogo.png
+
+
+
+ All Base Classes
+ All Symbols
+ Anonymous
+ Constructors
+ Class
+ Deprecated
+ Description
+ Destructor
+ Direct Base Classes
+ Enumerations
+ Functions
+
+ if and only if
+ Inheritance
+ Inherited Functions
+ is deprecated and should no longer be used
+ Known Derived Classes
+ Library
+ Member Functions
+ Member Summary
+ more...
+ Namespaces
+ Namespace
+ Nested Classes
+ Package
+ Packages
+ Package Index
+ See also
+ Struct
+ Symbol Index
+ This
+ Types
+ Variables
+ Contents
+ User Guides and Tutorials
+ Introduction
+
+
+
+
+
+
+ c1
+ information
+
+
+
+
+ ConsoleChannel
+ %s: [%p] %t
+
+
+
+
diff --git a/PocoDoc/src/DocWriter.cpp b/PocoDoc/src/DocWriter.cpp
new file mode 100644
index 000000000..a6361aef1
--- /dev/null
+++ b/PocoDoc/src/DocWriter.cpp
@@ -0,0 +1,2377 @@
+//
+// DocWriter.cpp
+//
+// Copyright (c) 2005-2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "DocWriter.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/Path.h"
+#include "Poco/String.h"
+#include "Poco/DateTime.h"
+#include "Poco/DateTimeFormat.h"
+#include "Poco/DateTimeFormatter.h"
+#include "Poco/RegularExpression.h"
+#include "Poco/Exception.h"
+#include "Poco/Format.h"
+#include "Poco/Util/Application.h"
+#include "Poco/CppParser/Struct.h"
+#include "Poco/CppParser/Enum.h"
+#include "Poco/CppParser/EnumValue.h"
+#include "Poco/CppParser/Function.h"
+#include "Poco/CppParser/Parameter.h"
+#include "Poco/CppParser/TypeDef.h"
+#include "Poco/CppParser/Variable.h"
+#include
\n\n- ";
+ writeOrderedListItem(ostr, text);
+ state = TEXT_OLIST;
+ break;
+ case TEXT_LIST:
+ case TEXT_OLIST:
+ ostr << "
\n- ";
+ writeOrderedListItem(ostr, text);
+ state = TEXT_OLIST;
+ break;
+ case TEXT_LITERAL:
+ writeLiteral(ostr, text);
+ break;
+ default:
+ break;
+ }
+ break;
+ case TEXT_LITERAL:
+ switch (state)
+ {
+ case TEXT_PARAGRAPH:
+ ostr << "\n
";
+ writeLiteral(ostr, text);
+ state = TEXT_LITERAL;
+ break;
+ case TEXT_LIST:
+ writeText(ostr, text);
+ state = TEXT_LIST;
+ break;
+ case TEXT_OLIST:
+ writeText(ostr, text);
+ state = TEXT_OLIST;
+ break;
+ case TEXT_LITERAL:
+ writeLiteral(ostr, text);
+ break;
+ default:
+ break;
+ }
+ break;
+ case TEXT_WHITESPACE:
+ switch (state)
+ {
+ case TEXT_PARAGRAPH:
+ ostr << "\n";
+ break;
+ case TEXT_LIST:
+ ostr << "
\n\n";
+ state = TEXT_PARAGRAPH;
+ break;
+ case TEXT_OLIST:
+ ostr << "\n
\n";
+ state = TEXT_PARAGRAPH;
+ break;
+ case TEXT_LITERAL:
+ writeLiteral(ostr, text);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+}
+
+
+void DocWriter::writeSummary(std::ostream& ostr, const std::string& text, const std::string& uri)
+{
+ ostr << "
";
+ std::string::const_iterator beg = text.begin();
+ std::string::const_iterator it = beg;
+ std::string::const_iterator end = text.end();
+ while (it != end && *it != '.') ++it;
+ if (it != end) ++it;
+ writeText(ostr, beg, it);
+ if (!uri.empty())
+ {
+ ostr << nbsp ;
+ writeImageLink(ostr, uri, "arrow.png", tr("more"));
+ }
+ ostr << "
\n";
+}
+
+
+DocWriter::TextState DocWriter::analyzeLine(const std::string& line)
+{
+ int nSpaces = 0;
+ std::string::const_iterator it = line.begin();
+ std::string::const_iterator end = line.end();
+ while (it != end && std::isspace(*it)) { ++it; ++nSpaces; }
+ if (it == end)
+ return TEXT_WHITESPACE;
+ else if (nSpaces < 3)
+ return TEXT_PARAGRAPH;
+ else if (*it == '-' || *it == '*')
+ return TEXT_LIST;
+ else if (std::isdigit(*it))
+ {
+ ++it;
+ if (it != end && *it == '.')
+ return TEXT_OLIST;
+ }
+ return TEXT_LITERAL;
+}
+
+
+std::string DocWriter::htmlizeName(const std::string& name)
+{
+ std::string result;
+ for (std::string::const_iterator it = name.begin(); it != name.end(); ++it)
+ {
+ if (*it == ' ')
+ result += nbsp ;
+ else
+ result += htmlize(*it);
+ }
+ return result;
+}
+
+
+void DocWriter::writeText(std::ostream& ostr, const std::string& text)
+{
+ std::string::const_iterator it(text.begin());
+ std::string::const_iterator end(text.end());
+
+ while (it != end && std::isspace(*it)) ++it;
+ if (it != end)
+ {
+ if (*it == '!')
+ {
+ std::string heading("h4");
+ ++it;
+ if (it != end && *it == '!')
+ {
+ heading = "h3";
+ ++it;
+ }
+ if (it != end && *it == '!')
+ {
+ heading = "h2";
+ ++it;
+ }
+ while (it != end && std::isspace(*it)) ++it;
+ ostr << "<" << heading << ">" << format("", _titleId++) << htmlize(std::string(it, end)) << "" << heading << ">" << std::endl;
+ return;
+ }
+ }
+ writeText(ostr, it, end);
+ ostr << ' ';
+}
+
+
+void DocWriter::writeText(std::ostream& ostr, std::string::const_iterator begin, const std::string::const_iterator& end)
+{
+ std::string token;
+ nextToken(begin, end, token);
+ while (!token.empty())
+ {
+ if (!writeSymbol(ostr, token, begin, end) && !writeSpecial(ostr, token, begin, end))
+ {
+ if (token == "[[")
+ {
+ std::string uri;
+ std::string text;
+ std::string::const_iterator it(begin);
+ while (it != end && std::isspace(*it)) ++it;
+ while (it != end && !std::isspace(*it)) uri += *it++;
+ while (it != end && std::isspace(*it)) ++it;
+ while (it != end && *it != ']') text += *it++;
+ while (it != end && *it == ']') ++it;
+ if (uri.compare(0, 6, "image:") == 0)
+ {
+ uri.erase(0, 6);
+ writeImage(ostr, uri, text);
+ }
+ else
+ {
+ std::string target;
+ if (uri.compare(0, 7, "http://") == 0 || uri.compare(0, 8, "https://") == 0)
+ target = "_blank";
+ writeTargetLink(ostr, uri, text, target);
+ }
+ begin = it;
+ nextToken(begin, end, token);
+ continue;
+ }
+ if (token == "RFC")
+ {
+ std::string::const_iterator it(begin);
+ std::string spc;
+ nextToken(begin, end, spc);
+ if (spc == " ")
+ {
+ std::string n;
+ nextToken(begin, end, n);
+ if (!n.empty() && std::isdigit(n[0]))
+ {
+ std::string uri(RFC_URI);
+ uri += n;
+ uri += ".txt";
+ writeTargetLink(ostr, uri, token + " " + n, "_blank");
+ nextToken(begin, end, token);
+ continue;
+ }
+ }
+ begin = it;
+ }
+ if (token == "http")
+ {
+ std::string::const_iterator it(begin);
+ std::string css;
+ nextToken(begin, end, css);
+ if (css == "://")
+ {
+ std::string uri(token);
+ uri += css;
+ while (begin != end && !std::isspace(*begin) && *begin != '>' && *begin != ')') uri += *begin++;
+ if (uri[uri.length() - 1] == '.')
+ {
+ uri.resize(uri.length() - 1);
+ writeTargetLink(ostr, uri, uri, "_blank");
+ ostr << '.';
+ }
+ else writeTargetLink(ostr, uri, uri, "_blank");
+ nextToken(begin, end, token);
+ continue;
+ }
+ else
+ ostr << htmlize(token);
+ begin = it;
+ }
+ else
+ {
+ ostr << htmlize(token);
+ }
+ nextToken(begin, end, token);
+ }
+ }
+}
+
+
+void DocWriter::writeDecl(std::ostream& ostr, const std::string& decl)
+{
+ writeDecl(ostr, decl.begin(), decl.end());
+}
+
+
+void DocWriter::writeDecl(std::ostream& ostr, std::string::const_iterator begin, const std::string::const_iterator& end)
+{
+ std::string token;
+ nextToken(begin, end, token);
+ while (!token.empty())
+ {
+ if (!writeSymbol(ostr, token, begin, end))
+ {
+ ostr << htmlize(token);
+ nextToken(begin, end, token);
+ }
+ }
+}
+
+
+bool DocWriter::writeSymbol(std::ostream& ostr, std::string& token, std::string::const_iterator& begin, const std::string::const_iterator& end)
+{
+ if (std::isalnum(token[0]) && _pNameSpace)
+ {
+ std::string id(token);
+ std::string next;
+ std::string::const_iterator it(begin);
+ nextToken(begin, end, next);
+ begin = it;
+ if (std::isupper(id[0]) || (!next.empty() && next[0] == '('))
+ {
+ std::string::const_iterator it2(begin);
+ while (next == "::")
+ {
+ nextToken(begin, end, next); // ::
+ id += next;
+ nextToken(begin, end, next); // id
+ id += next;
+ it2 = begin;
+ nextToken(begin, end, next);
+ begin = it2;
+ }
+ Symbol* pSym = _pNameSpace->lookup(id);
+ if (pSym)
+ {
+ writeLink(ostr, pSym, id);
+ nextToken(begin, end, token);
+ return true;
+ }
+ begin = it;
+ }
+ }
+ return false;
+}
+
+
+bool DocWriter::writeSpecial(std::ostream& ostr, std::string& token, std::string::const_iterator& begin, const std::string::const_iterator& end)
+{
+ if (token == "<%")
+ {
+ _htmlMode = true;
+ ostr << "
";
+ }
+ else if (token == "<{")
+ {
+ _htmlMode = true;
+ }
+ else if (token == "%>")
+ {
+ _htmlMode = false;
+ ostr << "";
+ }
+ else if (token == "}>")
+ {
+ _htmlMode = false;
+ }
+ else if (token == "")
+ {
+ std::string prop;
+ nextToken(begin, end, token);
+ while (!token.empty() && token != "?>")
+ {
+ prop.append(token);
+ nextToken(begin, end, token);
+ }
+ Poco::trimInPlace(prop);
+ Application& app = Application::instance();
+ ostr << htmlize(app.config().getString(prop, std::string("NOT FOUND: ") + prop));
+ }
+ else if (_htmlMode)
+ {
+ ostr << token;
+ }
+ else if (token == "<*")
+ {
+ ostr << "";
+ }
+ else if (token == "*>")
+ {
+ ostr << "";
+ }
+ else if (token == "";
+ }
+ else if (token == "!>")
+ {
+ ostr << "";
+ }
+ else if (token == "<[")
+ {
+ ostr << "";
+ _literalMode = true;
+ }
+ else if (token == "]>")
+ {
+ ostr << "";
+ _literalMode = false;
+ }
+ else if (token == "--" && !_literalMode)
+ {
+ ostr << mdash;
+ }
+ else if (token == "iff" && !_literalMode)
+ {
+ ostr << tr("iff");
+ }
+ else if (token != "----")
+ {
+ return false;
+ }
+ nextToken(begin, end, token);
+ return true;
+}
+
+
+void DocWriter::nextToken(std::string::const_iterator& it, const std::string::const_iterator& end, std::string& token)
+{
+ token.clear();
+ if (it != end && (std::isalnum(*it) || *it == '_'))
+ {
+ while (it != end && (std::isalnum(*it) || *it == '_')) token += *it++;
+ }
+ else if (it != end && std::isspace(*it))
+ {
+ while (it != end && std::isspace(*it)) token += *it++;
+ }
+ else if (it != end && *it == '<')
+ {
+ token += *it++;
+ if (it != end && std::ispunct(*it)) token += *it++;
+ }
+ else if (it != end && *it == '[')
+ {
+ token += *it++;
+ if (it != end && *it == '[') token += *it++;
+ }
+ else if (it != end && (*it == ']' || *it == '*' || *it == '!' || *it == '%' || *it == '}' || *it == '?'))
+ {
+ token += *it++;
+ if (it != end && *it == '>') token += *it++;
+ }
+ else if (it != end && *it == '-')
+ {
+ while (it != end && *it == '-') token += *it++;
+ }
+ else if (it != end && *it == ':')
+ {
+ while (it != end && (*it == ':' || *it == '/')) token += *it++;
+ }
+ else if (it != end)
+ {
+ token += *it++;
+ }
+}
+
+
+void DocWriter::writeListItem(std::ostream& ostr, const std::string& text)
+{
+ std::string::const_iterator it = text.begin();
+ std::string::const_iterator end = text.end();
+ while (it != end && std::isspace(*it)) ++it;
+ if ((it != end && *it == '-') || *it == '*')
+ {
+ ++it;
+ while (it != end && std::isspace(*it)) ++it;
+ }
+ writeText(ostr, it, end);
+ ostr << ' ';
+}
+
+
+void DocWriter::writeOrderedListItem(std::ostream& ostr, const std::string& text)
+{
+ std::string::const_iterator it = text.begin();
+ std::string::const_iterator end = text.end();
+ while (it != end && std::isspace(*it)) ++it;
+ if (it != end && std::isdigit(*it))
+ {
+ while (it != end && std::isdigit(*it)) ++it;
+ if (it != end && *it == '.') ++it;
+ while (it != end && std::isspace(*it)) ++it;
+ }
+ writeText(ostr, it, end);
+ ostr << ' ';
+}
+
+
+void DocWriter::writeLiteral(std::ostream& ostr, const std::string& text)
+{
+ if (_pendingLine)
+ {
+ ostr << "\n";
+ _pendingLine = false;
+ }
+
+ std::string::const_iterator it(text.begin());
+ std::string::const_iterator end(text.end());
+ if (_indent == 0)
+ {
+ while (it != end && std::isspace(*it))
+ {
+ ++it;
+ ++_indent;
+ }
+ }
+ else
+ {
+ int i = 0;
+ while (it != end && i < _indent)
+ {
+ ++it;
+ ++i;
+ }
+ }
+ std::string line(it, end);
+ Poco::trimRightInPlace(line);
+ if (line.empty())
+ _pendingLine = true;
+ else
+ ostr << htmlize(std::string(it, end)) << "\n";
+}
+
+
+void DocWriter::writeFileInfo(std::ostream& ostr, const Symbol* pSymbol)
+{
+ std::string library(pSymbol->getLibrary());
+ std::string package(pSymbol->getPackage());
+ if (library.empty() || library == "ChangeThis")
+ logger().notice(std::string("No library name specified in ") + pSymbol->getFile());
+ if (package.empty() || package == "ChangeThis")
+ logger().notice(std::string("No package name specified in ") + pSymbol->getFile());
+
+ ostr << "
\n";
+ ostr << "" << tr("Library") << ": " << library << "
\n"
+ << "" << tr("Package") << ": " << package << "
\n"
+ << "" << tr("Header") << ": " << headerFor(pSymbol);
+ ostr << "
\n";
+}
+
+
+void DocWriter::writeInheritance(std::ostream& ostr, const Struct* pStruct)
+{
+ std::set bases;
+ pStruct->bases(bases);
+ if (!bases.empty() || pStruct->derivedBegin() != pStruct->derivedEnd())
+ {
+ writeSubTitle(ostr, tr("Inheritance"));
+ if (pStruct->baseBegin() != pStruct->baseEnd())
+ {
+ ostr << "" << tr("Direct_Base_Classes") << ": ";
+ bool first = true;
+ for (Struct::BaseIterator it = pStruct->baseBegin(); it != pStruct->baseEnd(); ++it)
+ {
+ std::string base;
+ if (it->pClass)
+ {
+ if (it->pClass->nameSpace() == pStruct->nameSpace())
+ base = it->pClass->name();
+ else
+ base = it->pClass->fullName();
+ }
+ else base = it->name;
+ writeNameListItem(ostr, base, it->pClass, pStruct->nameSpace(), first);
+ }
+ ostr << "
\n";
+ }
+ if (!bases.empty())
+ {
+ ostr << "" << tr("All_Base_Classes") << ": ";
+ bool first = true;
+ for (std::set::const_iterator it = bases.begin(); it != bases.end(); ++it)
+ {
+ std::string base;
+ Symbol* pBase = pStruct->nameSpace()->lookup(*it);
+ if (pBase)
+ {
+ if (pBase->nameSpace() == pStruct->nameSpace())
+ base = pBase->name();
+ else
+ base = pBase->fullName();
+ }
+ else base = *it;
+ writeNameListItem(ostr, base, pBase, pStruct->nameSpace(), first);
+ }
+ ostr << "
\n";
+ }
+ Struct::StructSet derived;
+ pStruct->derived(derived);
+ if (!derived.empty())
+ {
+ ostr << "" << tr("Known_Derived_Classes") << ": ";
+ bool first = true;
+ for (Struct::StructSet::const_iterator it = derived.begin(); it != derived.end(); ++it)
+ {
+ std::string derived;
+ if ((*it)->nameSpace() == pStruct->nameSpace())
+ derived = (*it)->name();
+ else
+ derived = (*it)->fullName();
+ writeNameListItem(ostr, derived, *it, pStruct->nameSpace(), first);
+ }
+ ostr << "
\n";
+ }
+ }
+}
+
+
+void DocWriter::writeMethodSummary(std::ostream& ostr, const Struct* pStruct)
+{
+ bool titleWritten = false;
+ MethodMap methods;
+ Struct::Functions functions;
+ pStruct->methods(Symbol::ACC_PUBLIC, functions);
+ for (Struct::Functions::const_iterator it = functions.begin(); it != functions.end(); ++it)
+ {
+ if (methods.find((*it)->name()) == methods.end())
+ methods[(*it)->name()] = *it;
+ }
+ pStruct->methods(Symbol::ACC_PROTECTED, functions);
+ for (Struct::Functions::const_iterator it = functions.begin(); it != functions.end(); ++it)
+ {
+ if (methods.find((*it)->name()) == methods.end())
+ methods[(*it)->name()] = *it;
+ }
+ if (!methods.empty())
+ {
+ writeSubTitle(ostr, tr("Member_Summary"));
+ titleWritten = true;
+ ostr << "" << tr("Member_Functions") << ": ";
+ bool first = true;
+ for (MethodMap::const_iterator it = methods.begin(); it != methods.end(); ++it)
+ {
+ writeNameListItem(ostr, it->first, it->second, pStruct, first);
+ }
+ ostr << "
\n";
+ }
+ methods.clear();
+ Struct::FunctionSet inhFunctions;
+ pStruct->inheritedMethods(inhFunctions);
+ for (Struct::FunctionSet::const_iterator it = inhFunctions.begin(); it != inhFunctions.end(); ++it)
+ {
+ if (methods.find((*it)->name()) == methods.end())
+ methods[(*it)->name()] = *it;
+ }
+ if (!methods.empty())
+ {
+ if (!titleWritten)
+ writeSubTitle(ostr, tr("Member_Summary"));
+ ostr << "" << tr("Inherited_Functions") << ": ";
+ bool first = true;
+ for (MethodMap::const_iterator it = methods.begin(); it != methods.end(); ++it)
+ {
+ writeNameListItem(ostr, it->first, it->second, pStruct, first);
+ }
+ ostr << "
\n";
+ }
+}
+
+
+void DocWriter::writeNestedClasses(std::ostream& ostr, const Struct* pStruct)
+{
+ NameSpace::SymbolTable classes;
+ pStruct->classes(classes);
+ bool hasNested = false;
+ for (NameSpace::Iterator it = classes.begin(); it != classes.end(); ++it)
+ {
+ if (it->second->getAccess() != Symbol::ACC_PRIVATE)
+ hasNested = true;
+ }
+ if (hasNested)
+ {
+ writeSubTitle(ostr, tr("Nested_Classes"));
+ for (NameSpace::Iterator it = classes.begin(); it != classes.end(); ++it)
+ {
+ if (it->second->getAccess() != Symbol::ACC_PRIVATE)
+ writeClassSummary(ostr, static_cast(it->second));
+ }
+ }
+}
+
+
+void DocWriter::writeNameSpacesSummary(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable nameSpaces;
+ pNameSpace->nameSpaces(nameSpaces);
+ if (!nameSpaces.empty())
+ {
+ ostr << "" << tr("Namespaces") << ": " << std::endl;
+ bool first = true;
+ for (NameSpace::Iterator it = nameSpaces.begin(); it != nameSpaces.end(); ++it)
+ {
+ writeNameListItem(ostr, it->second->name(), it->second, pNameSpace, first);
+ }
+ ostr << "
" << std::endl;
+ }
+}
+
+
+void DocWriter::writeNameSpaces(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable nameSpaces;
+ pNameSpace->nameSpaces(nameSpaces);
+ if (!nameSpaces.empty())
+ {
+ writeSubTitle(ostr, tr("Namespaces"));
+ for (NameSpace::Iterator it = nameSpaces.begin(); it != nameSpaces.end(); ++it)
+ {
+ ostr << "";
+ std::string what("namespace ");
+ what += it->second->name();
+ writeLink(ostr, uriFor(it->second), what, "class");
+ ostr << "
\n";
+ }
+ }
+}
+
+
+void DocWriter::writeClassesSummary(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable classes;
+ pNameSpace->classes(classes);
+ if (!classes.empty())
+ {
+ ostr << "" << tr("Classes") << ": " << std::endl;
+ bool first = true;
+ for (NameSpace::Iterator it = classes.begin(); it != classes.end(); ++it)
+ {
+ writeNameListItem(ostr, it->second->name(), it->second, pNameSpace, first);
+ }
+ ostr << "
" << std::endl;
+ }
+}
+
+
+void DocWriter::writeClasses(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable classes;
+ pNameSpace->classes(classes);
+ if (!classes.empty())
+ {
+ writeSubTitle(ostr, tr("Classes"));
+ for (NameSpace::Iterator it = classes.begin(); it != classes.end(); ++it)
+ {
+ writeClassSummary(ostr, static_cast(it->second));
+ }
+ }
+}
+
+
+void DocWriter::writeClassSummary(std::ostream& ostr, const Struct* pStruct)
+{
+ ostr << "";
+ std::string what;
+ if (pStruct->isClass())
+ what += "class ";
+ else
+ what += "struct ";
+ what += pStruct->name();
+ writeLink(ostr, uriFor(pStruct), what, "class");
+ if (pStruct->getAccess() != Symbol::ACC_PUBLIC)
+ writeIcon(ostr, "protected");
+ ostr << "
\n";
+ writeSummary(ostr, pStruct->getDocumentation(), uriFor(pStruct));
+}
+
+
+void DocWriter::writeTypesSummary(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable types;
+ pNameSpace->typeDefs(types);
+ if (!types.empty())
+ {
+ ostr << "" << tr("Types") << ": " << std::endl;
+ bool first = true;
+ for (NameSpace::Iterator it = types.begin(); it != types.end(); ++it)
+ {
+ writeNameListItem(ostr, it->second->name(), it->second, pNameSpace, first);
+ }
+ ostr << "
" << std::endl;
+ }
+}
+
+
+void DocWriter::writeTypes(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable types;
+ pNameSpace->typeDefs(types);
+ bool hasTypes = false;
+ for (NameSpace::Iterator it = types.begin(); !hasTypes && it != types.end(); ++it)
+ {
+ if (it->second->getAccess() != Symbol::ACC_PRIVATE)
+ hasTypes = true;
+ }
+ if (hasTypes)
+ {
+ writeSubTitle(ostr, tr("Types"));
+ for (NameSpace::Iterator it = types.begin(); it != types.end(); ++it)
+ {
+ if (it->second->getAccess() != Symbol::ACC_PRIVATE)
+ writeType(ostr, static_cast(it->second));
+ }
+ }
+}
+
+
+void DocWriter::writeType(std::ostream& ostr, const TypeDef* pType)
+{
+ ostr << "";
+ writeAnchor(ostr, pType->name(), pType);
+ if (pType->getAccess() != Symbol::ACC_PUBLIC)
+ writeIcon(ostr, "protected");
+ ostr << "
\n";
+ ostr << "";
+ writeDecl(ostr, pType->declaration());
+ ostr << ";
\n";
+ writeDescription(ostr, pType->getDocumentation());
+}
+
+
+void DocWriter::writeEnums(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable enums;
+ pNameSpace->enums(enums);
+ bool hasEnums = false;
+ for (NameSpace::Iterator it = enums.begin(); !hasEnums && it != enums.end(); ++it)
+ {
+ if (it->second->getAccess() != Symbol::ACC_PRIVATE)
+ hasEnums = true;
+ }
+ if (hasEnums)
+ {
+ writeSubTitle(ostr, tr("Enumerations"));
+ for (NameSpace::Iterator it = enums.begin(); it != enums.end(); ++it)
+ {
+ if (it->second->getAccess() != Symbol::ACC_PRIVATE)
+ writeEnum(ostr, static_cast(it->second));
+ }
+ }
+}
+
+
+void DocWriter::writeEnum(std::ostream& ostr, const Enum* pEnum)
+{
+ ostr << "";
+ const std::string& name = pEnum->name();
+ if (name[0] == '#')
+ ostr << "" << tr("Anonymous") << "";
+ else
+ writeAnchor(ostr, name, pEnum);
+ if (pEnum->getAccess() != Symbol::ACC_PUBLIC)
+ writeIcon(ostr, "protected");
+ ostr << "
\n";
+ writeDescription(ostr, pEnum->getDocumentation());
+ for (Enum::Iterator it = pEnum->begin(); it != pEnum->end(); ++it)
+ {
+ const std::string& name = (*it)->name();
+ const std::string& value = (*it)->value();
+ ostr << "";
+ writeAnchor(ostr, name, *it);
+ if (!value.empty())
+ ostr << " = " << htmlize(value);
+ ostr << "
\n";
+ writeDescription(ostr, (*it)->getDocumentation());
+ }
+}
+
+
+void DocWriter::writeConstructors(std::ostream& ostr, const Struct* pStruct)
+{
+ Struct::Functions ctors;
+ pStruct->constructors(ctors);
+ if (!ctors.empty())
+ {
+ writeSubTitle(ostr, tr("Constructors"));
+ for (Struct::Functions::const_iterator it = ctors.begin(); it != ctors.end(); ++it)
+ {
+ if ((*it)->getAccess() == Symbol::ACC_PUBLIC)
+ writeFunction(ostr, *it);
+ }
+ for (Struct::Functions::const_iterator it = ctors.begin(); it != ctors.end(); ++it)
+ {
+ if ((*it)->getAccess() == Symbol::ACC_PROTECTED)
+ writeFunction(ostr, *it);
+ }
+ }
+}
+
+
+void DocWriter::writeDestructor(std::ostream& ostr, const Struct* pStruct)
+{
+ if (pStruct->destructor())
+ {
+ writeSubTitle(ostr, tr("Destructor"));
+ writeFunction(ostr, pStruct->destructor());
+ }
+}
+
+
+void DocWriter::writeMethods(std::ostream& ostr, const Struct* pStruct)
+{
+ Struct::Functions methods;
+ pStruct->methods(Symbol::ACC_PUBLIC, methods);
+ pStruct->methods(Symbol::ACC_PROTECTED, methods);
+ if (!methods.empty())
+ {
+ writeSubTitle(ostr, tr("Member_Functions"));
+ for (Struct::Functions::const_iterator it = methods.begin(); it != methods.end(); ++it)
+ {
+ writeFunction(ostr, *it);
+ }
+ }
+}
+
+
+void DocWriter::writeFunctionsSummary(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable funcs;
+ pNameSpace->functions(funcs);
+ if (!funcs.empty())
+ {
+ ostr << "" << tr("Functions") << ": " << std::endl;
+ std::string lastName;
+ bool first = true;
+ for (NameSpace::Iterator it = funcs.begin(); it != funcs.end(); ++it)
+ {
+ if (it->second->name() != lastName)
+ {
+ writeNameListItem(ostr, it->second->name(), it->second, pNameSpace, first);
+ lastName = it->second->name();
+ }
+ }
+ ostr << "
" << std::endl;
+ }
+}
+
+
+void DocWriter::writeFunctions(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable funcs;
+ pNameSpace->functions(funcs);
+ if (!funcs.empty())
+ {
+ writeSubTitle(ostr, tr("Functions"));
+ for (NameSpace::Iterator it = funcs.begin(); it != funcs.end(); ++it)
+ {
+ writeFunction(ostr, static_cast(it->second));
+ }
+ }
+}
+
+
+void DocWriter::writeFunction(std::ostream& ostr, const Function* pFunc)
+{
+ ostr << "";
+ writeAnchor(ostr, pFunc->name(), pFunc);
+ if (pFunc->getAccess() != Symbol::ACC_PUBLIC)
+ writeIcon(ostr, "protected");
+ if (pFunc->isVirtual())
+ writeIcon(ostr, "virtual");
+ else if (pFunc->flags() & Function::FN_STATIC)
+ writeIcon(ostr, "static");
+ if (pFunc->flags() & Function::FN_INLINE)
+ writeIcon(ostr, "inline");
+ ostr << "
\n";
+ ostr << "";
+ const std::string& decl = pFunc->declaration();
+ writeDecl(ostr, decl);
+ if (!std::isalnum(decl[decl.length() - 1]))
+ ostr << " ";
+ ostr << "(";
+ bool hasArgs = false;
+ for (Function::Iterator it = pFunc->begin(); it != pFunc->end(); ++it)
+ {
+ hasArgs = true;
+ if (it != pFunc->begin())
+ ostr << ",";
+ ostr << "
";
+ writeDecl(ostr, (*it)->declaration());
+ if ((*it)->hasDefaultValue())
+ {
+ ostr << " = " << (*it)->defaultDecl();
+ }
+ }
+ if (hasArgs)
+ ostr << "
";
+ ostr << ")";
+ if (pFunc->flags() & Function::FN_CONST)
+ ostr << " const";
+ if (pFunc->flags() & Function::FN_OVERRIDE)
+ ostr << " override";
+ else if (pFunc->flags() & Function::FN_FINAL)
+ ostr << " final";
+ if (pFunc->flags() & Function::FN_DELETE)
+ ostr << " = delete";
+ else if (pFunc->flags() & Function::FN_DEFAULT)
+ ostr << " = default";
+ else if (pFunc->flags() & Function::FN_PURE_VIRTUAL)
+ ostr << " = 0";
+ ostr << ";
\n";
+
+ if (pFunc->attrs().has("deprecated"))
+ {
+ writeDeprecated(ostr, "function");
+ }
+
+ Function* pOverridden = pFunc->getOverridden();
+ const std::string& doc(pFunc->getDocumentation());
+ if (doc.empty() && pFunc->isPublic() && !pOverridden && !pFunc->isConstructor() && !pFunc->isDestructor())
+ logger().notice(std::string("Undocumented public function: ") + pFunc->fullName());
+
+ writeDescription(ostr, doc);
+ if (pOverridden)
+ {
+ ostr << "" << tr("See_also") << ": ";
+ writeLink(ostr, pOverridden, pOverridden->fullName() + "()");
+ ostr << "
\n";
+ }
+}
+
+
+void DocWriter::writeVariables(std::ostream& ostr, const NameSpace* pNameSpace)
+{
+ NameSpace::SymbolTable vars;
+ pNameSpace->variables(vars);
+ bool hasVars = false;
+ for (NameSpace::Iterator it = vars.begin(); !hasVars && it != vars.end(); ++it)
+ {
+ if (it->second->getAccess() != Symbol::ACC_PRIVATE)
+ hasVars = true;
+ }
+ if (hasVars)
+ {
+
+ writeSubTitle(ostr, tr("Variables"));
+ for (NameSpace::Iterator it = vars.begin(); it != vars.end(); ++it)
+ {
+ if (it->second->getAccess() == Symbol::ACC_PUBLIC)
+ writeVariable(ostr, static_cast(it->second));
+ }
+ for (NameSpace::Iterator it = vars.begin(); it != vars.end(); ++it)
+ {
+ if (it->second->getAccess() == Symbol::ACC_PROTECTED)
+ writeVariable(ostr, static_cast(it->second));
+ }
+ }
+}
+
+
+void DocWriter::writeVariable(std::ostream& ostr, const Variable* pVar)
+{
+ ostr << "";
+ writeAnchor(ostr, pVar->name(), pVar);
+ if (pVar->getAccess() != Symbol::ACC_PUBLIC)
+ writeIcon(ostr, "protected");
+ if (pVar->flags() & Function::FN_STATIC)
+ writeIcon(ostr, "static");
+ ostr << "
\n";
+ ostr << "";
+ writeDecl(ostr, pVar->declaration());
+ ostr << ";
\n";
+ writeDescription(ostr, pVar->getDocumentation());
+}
+
+
+void DocWriter::writeNameListItem(std::ostream& ostr, const std::string& str, const Symbol* pSymbol, const NameSpace* pNameSpace, bool& first)
+{
+ if (first)
+ first = false;
+ else
+ ostr << ", ";
+
+ if (pSymbol)
+ writeLink(ostr, pSymbol, str);
+ else
+ ostr << htmlizeName(str);
+}
+
+
+void DocWriter::writeLink(std::ostream& ostr, const std::string& uri, const std::string& text)
+{
+ ostr << "" << htmlize(text) << "";
+}
+
+
+void DocWriter::writeLink(std::ostream& ostr, const Symbol* pSymbol, const std::string& name)
+{
+ ostr << "" << htmlizeName(name) << "";
+}
+
+
+void DocWriter::writeLink(std::ostream& ostr, const std::string& uri, const std::string& text, const std::string& linkClass)
+{
+ ostr << "" << htmlize(text) << "";
+}
+
+
+void DocWriter::writeTargetLink(std::ostream& ostr, const std::string& uri, const std::string& text, const std::string& target)
+{
+ if (_noFrames && target != "_blank")
+ ostr << "" << text << "";
+ else if (!target.empty())
+ ostr << "" << text << "";
+ else
+ ostr << "" << htmlize(text) << "";
+}
+
+
+void DocWriter::writeImageLink(std::ostream& ostr, const std::string& uri, const std::string& image, const std::string& alt)
+{
+ ostr << "";
+ ostr << "
";
+ ostr << "";
+}
+
+
+void DocWriter::writeImage(std::ostream& ostr, const std::string& uri, const std::string& caption)
+{
+ ostr << "" << std::endl;
+ ostr << "

" << std::endl;
+ if (!caption.empty())
+ {
+ ostr << "
" << htmlize(caption) << "
";
+ }
+ ostr << "
" << std::endl;
+}
+
+
+void DocWriter::writeIcon(std::ostream& ostr, const std::string& icon)
+{
+ ostr << "
";
+}
+
+
+void DocWriter::writeAnchor(std::ostream& ostr, const std::string& text, const Symbol* pSymbol)
+{
+ ostr << "" << htmlize(text) << "";
+}
+
+
+void DocWriter::writeDeprecated(std::ostream& ostr, const std::string& what)
+{
+ ostr << "" << std::endl;
+ ostr << "
" << tr("Deprecated") << ". " << tr("This") << " " << what << " " << tr("is_deprecated") << ".
" << std::endl;
+ ostr << "
" << std::endl;
+}
+
+
+std::string DocWriter::headerFor(const Symbol* pSymbol)
+{
+ Path path(pSymbol->getFile());
+ std::string header;
+ int i = 0;
+ while (i < path.depth() - 1 && path[i] != "include") ++i;
+ for (++i; i < path.depth(); ++i)
+ {
+ header += path[i];
+ header += "/";
+ }
+ header += path.getFileName();
+ return header;
+}
+
+
+std::string DocWriter::titleFor(const Symbol* pSymbol)
+{
+ std::string title;
+ switch (pSymbol->kind())
+ {
+ case Symbol::SYM_NAMESPACE:
+ title += "namespace";
+ break;
+ case Symbol::SYM_STRUCT:
+ title += (static_cast(pSymbol)->isClass() ? "class" : "struct");
+ break;
+ case Symbol::SYM_ENUM:
+ title += "enum ";
+ break;
+ default:
+ break;
+ }
+ if (!title.empty()) title += " ";
+ const Function* pFunc = dynamic_cast(pSymbol);
+ if (pFunc && pFunc->isConstructor())
+ {
+ title += "class " + pSymbol->nameSpace()->fullName();
+ }
+ else
+ {
+ title += pSymbol->fullName();
+ if (pFunc) title += "()";
+ }
+ return title;
+}
+
+
+std::string DocWriter::htmlize(const std::string& str)
+{
+ std::string result;
+ for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
+ result += htmlize(*it);
+ return result;
+}
+
+
+std::string DocWriter::htmlize(char c)
+{
+ std::string result;
+ switch (c)
+ {
+ case '"':
+ result += """;
+ break;
+ case '<':
+ result += "<";
+ break;
+ case '>':
+ result += ">";
+ break;
+ case '&':
+ result += "&";
+ break;
+ default:
+ result += c;
+ }
+ return result;
+}
+
+
+void DocWriter::libraries(std::set& libs)
+{
+ for (NameSpace::SymbolTable::const_iterator it = _symbols.begin(); it != _symbols.end(); ++it)
+ {
+ const std::string& lib = it->second->getLibrary();
+ if (!lib.empty())
+ libs.insert(lib);
+ }
+}
+
+
+void DocWriter::packages(const std::string& lib, std::set& packages)
+{
+ for (NameSpace::SymbolTable::const_iterator it = _symbols.begin(); it != _symbols.end(); ++it)
+ {
+ const std::string& plib = it->second->getLibrary();
+ const std::string& pkg = it->second->getPackage();
+ if (!pkg.empty() && lib == plib)
+ packages.insert(pkg);
+ }
+}
+
+
+void DocWriter::writePages()
+{
+ _pNameSpace = rootNameSpace();
+ for (PageMap::iterator it = _pages.begin(); it != _pages.end(); ++it)
+ {
+ writePage(it->second);
+ }
+}
+
+
+void DocWriter::writePage(Page& page)
+{
+ std::ifstream istr(page.path.c_str());
+ if (!istr.good()) throw Poco::OpenFileException(page.path);
+ std::string title;
+ std::string category;
+ std::string text;
+ int ch = istr.get();
+ while (ch != -1 && ch != '\n') { title += (char) ch; ch = istr.get(); }
+ ch = istr.get();
+ while (ch != -1 && ch != '\n') { category += (char) ch; ch = istr.get(); }
+
+ while (std::isspace(ch)) ch = istr.get();
+ while (ch != -1)
+ {
+ text += (char) ch;
+ if (ch == '\n') text += ' ';
+ ch = istr.get();
+ }
+
+ page.title = title;
+ page.category = category;
+
+ TOC toc;
+ scanTOC(text, toc);
+
+ std::string path(pathFor(page.fileName));
+ std::ofstream ostr(path.c_str());
+ if (!ostr.good()) throw Poco::CreateFileException(path);
+ writeHeader(ostr, title, "js/iframeResizer.min.js");
+ writeTitle(ostr, tr(category), title);
+ beginBody(ostr);
+ writeNavigationFrame(ostr, "category", category);
+ beginContent(ostr);
+ if (!toc.empty())
+ {
+ writeTOC(ostr, toc);
+ }
+ writeDescription(ostr, text);
+ writeCopyright(ostr);
+ endContent(ostr);
+ endBody(ostr);
+ ostr << "" << std::endl;
+ writeFooter(ostr);
+}
+
+
+void DocWriter::scanTOC(const std::string& text, TOC& toc)
+{
+ int titleId = 0;
+ std::istringstream istr(text);
+ while (!istr.eof())
+ {
+ std::string line;
+ std::getline(istr, line);
+ std::string::const_iterator it(line.begin());
+ std::string::const_iterator end(line.end());
+ while (it != end && std::isspace(*it)) ++it;
+ if (it != end && *it == '!')
+ {
+ ++it;
+ int level = MAX_TITLE_LEVEL;
+ while (it != end && *it == '!')
+ {
+ level--;
+ ++it;
+ }
+ while (it != end && std::isspace(*it)) ++it;
+ TOCEntry entry;
+ entry.id = titleId++;
+ entry.level = level;
+ entry.title.assign(it, end);
+ toc.push_back(entry);
+ }
+ }
+}
+
+
+void DocWriter::writeTOC(std::ostream& ostr, const TOC& toc)
+{
+ ostr << "" << std::endl;
+ ostr << "
- " << tr("TOC") << std::endl;
+ int lastLevel = 0;
+ for (TOC::const_iterator it = toc.begin(); it != toc.end(); ++it)
+ {
+ int level = it->level;
+ if (level > lastLevel)
+ {
+ ostr << "
" << std::endl;
+ }
+ else if (level < lastLevel)
+ {
+ for (int i = level; i < lastLevel; i++)
+ {
+ ostr << "
" << std::endl;
+ }
+ }
+ else
+ {
+ ostr << "" << std::endl;
+ }
+ ostr << "
" << htmlize(it->title) << "" << std::endl;
+ lastLevel = level;
+ }
+ while (lastLevel-- > 1)
+ {
+ ostr << "" << std::endl;
+ }
+ ostr << "
" << std::endl;
+}
+
+
+void DocWriter::writeCategoryIndex(const std::string& category, const std::string& fileName)
+{
+ std::ofstream ostr(pathFor(fileName).c_str());
+ if (!ostr.good()) throw Poco::CreateFileException(fileName);
+ writeHeader(ostr, tr(category));
+ beginBody(ostr);
+ ostr << "" << htmlize(tr(category)) << "
";
+ writeCategoryIndex(ostr, category, "_top");
+ endBody(ostr);
+ writeFooter(ostr);
+}
+
+
+void DocWriter::writeCategoryIndex(std::ostream& ostr, const std::string& category, const std::string& target)
+{
+ ostr << "\n";
+ for (PageMap::const_iterator it = _pages.begin(); it != _pages.end(); ++it)
+ {
+ if (it->second.category == category)
+ {
+ ostr << "- ";
+ writeTargetLink(ostr, it->second.fileName, it->second.title, target);
+ ostr << "
\n";
+ }
+ }
+ ostr << "
\n";
+}
+
+
+NameSpace* DocWriter::rootNameSpace() const
+{
+ for (NameSpace::SymbolTable::const_iterator it = _symbols.begin(); it != _symbols.end(); ++it)
+ {
+ if (it->second->kind() == Symbol::SYM_NAMESPACE)
+ {
+ NameSpace* pNS = static_cast(it->second);
+ while (pNS->nameSpace()) pNS = pNS->nameSpace();
+ return pNS;
+ }
+ }
+ return 0;
+}
+
+
+const std::string& DocWriter::tr(const std::string& id)
+{
+ StringMap::const_iterator it = _strings.find(id);
+
+ if (it == _strings.end())
+ {
+ loadString(id, id, _language);
+ it = _strings.find(id);
+ }
+ if (it != _strings.end())
+ return it->second;
+ else
+ return id;
+}
+
+
+void DocWriter::loadString(const std::string& id, const std::string& def, const std::string& language)
+{
+ Application& app = Application::instance();
+ std::pair p(id, app.config().getString("Translations." + language + "." + id, def));
+ _strings.insert(p);
+}
+
+
+void DocWriter::loadStrings(const std::string& language)
+{
+ _strings.clear();
+ loadString("AAAIntroduction", "Introduction", language);
+ loadString("All_Base_Classes", "All Base Classes", language);
+ loadString("All_Symbols", "All Symbols", language);
+ loadString("Anonymous", "Anonymous", language);
+ loadString("Constructors", "Constructors", language);
+ loadString("Class", "Class", language);
+ loadString("Deprecated", "Deprecated", language);
+ loadString("Description", "Description", language);
+ loadString("Destructor", "Destructor", language);
+ loadString("Direct_Base_Classes", "Direct Base Classes", language);
+ loadString("Enumerations", "Enumerations", language);
+ loadString("Functions", "Functions", language);
+ loadString("Header", "Header", language);
+ loadString("iff", "if and only if", language);
+ loadString("Inheritance", "Inheritance", language);
+ loadString("Inherited_Functions", "Inherited Functions", language);
+ loadString("is_deprecated", "is deprecated and should no longer be used", language);
+ loadString("Known_Derived_Classes", "Known Derived Classes", language);
+ loadString("Library", "Library", language);
+ loadString("License", "License", language);
+ loadString("Member_Functions", "Member Functions", language);
+ loadString("Member_Summary", "Member Summary", language);
+ loadString("more", "more...", language);
+ loadString("Namespaces", "Namespaces", language);
+ loadString("Namespace", "Namespace", language);
+ loadString("Nested_Classes", "Nested Classes", language);
+ loadString("Package", "Package", language);
+ loadString("Packages", "Packages", language);
+ loadString("Package_Index", "Package Index", language);
+ loadString("Reference", "Reference", language);
+ loadString("See_also", "See also", language);
+ loadString("Struct", "Struct", language);
+ loadString("Symbol_Index", "Symbol Index", language);
+ loadString("This", "This", language);
+ loadString("Types", "Types", language);
+ loadString("Variables", "Variables", language);
+}
diff --git a/PocoDoc/src/DocWriter.h b/PocoDoc/src/DocWriter.h
new file mode 100644
index 000000000..e70763c6c
--- /dev/null
+++ b/PocoDoc/src/DocWriter.h
@@ -0,0 +1,227 @@
+//
+// DocWriter.h
+//
+// Definition of the DocWriter class.
+//
+// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef PocoDoc_DocWriter_INCLUDED
+#define PocoDoc_DocWriter_INCLUDED
+
+
+#include "Poco/CppParser/NameSpace.h"
+#include "Poco/Logger.h"
+#include
+#include
+#include
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class Symbol;
+class Struct;
+class Function;
+class TypeDef;
+class Enum;
+class Variable;
+
+
+} } // namespace Poco::CppParser
+
+
+class DocWriter
+ /// Given a symbol table obtained from a CppParser, this
+ /// class writes reference documentation in HTML format
+ /// to a directory.
+{
+public:
+ DocWriter(const Poco::CppParser::NameSpace::SymbolTable& symbols, const std::string& path, bool prettifyCode = true, bool noFrames = false);
+ /// Creates the DocWriter.
+
+ ~DocWriter();
+ /// Destroys the DocWriter.
+
+ void write();
+ /// Writes all documentation files.
+
+ void writeEclipseTOC();
+ /// Write Eclipse Table-Of-Contents XML files.
+
+ void addPage(const std::string& path);
+ /// Adds a page.
+
+protected:
+ enum TextState
+ {
+ TEXT_PARAGRAPH,
+ TEXT_LIST,
+ TEXT_OLIST,
+ TEXT_LITERAL,
+ TEXT_WHITESPACE
+ };
+
+ struct Page
+ {
+ std::string path;
+ std::string fileName;
+ std::string title;
+ std::string category;
+ };
+
+ enum
+ {
+ MAX_TITLE_LEVEL = 3,
+ PAGE_INDEX_COLUMNS = 2,
+ NAMESPACE_INDEX_COLUMNS = 4
+ };
+
+ struct TOCEntry
+ {
+ std::string title;
+ int level;
+ int id;
+ };
+
+ typedef std::vector TOC;
+ typedef std::map MethodMap;
+ typedef std::map StringMap;
+ typedef std::map PageMap;
+
+ void writePages();
+ void writePage(Page& page);
+ void scanTOC(const std::string& text, TOC& toc);
+ void writeTOC(std::ostream& ostr, const TOC& toc);
+ void writeCategoryIndex(const std::string& category, const std::string& fileName);
+ void writeCategoryIndex(std::ostream& ostr, const std::string& category, const std::string& target);
+ void writePageIndex(std::ostream& ostr);
+ void writeNameSpaceIndex(std::ostream& ostr);
+
+ void writeClass(const Poco::CppParser::Struct* pStruct);
+ void writeNameSpace(const Poco::CppParser::NameSpace* pNameSpace);
+
+ void writeNavigation();
+ void writePackage(const std::string& file, const std::string& library, const std::string& package);
+
+ std::string pathFor(const std::string& file);
+ static std::string fileNameFor(const Poco::CppParser::Symbol* pNameSpace);
+ static std::string baseNameFor(const Poco::CppParser::Symbol* pNameSpace);
+ static std::string uriFor(const Poco::CppParser::Symbol* pSymbol);
+ static std::string makeFileName(const std::string& str);
+ static std::string headerFor(const Poco::CppParser::Symbol* pSymbol);
+ static std::string titleFor(const Poco::CppParser::Symbol* pSymbol);
+
+ void writeHeader(std::ostream& ostr, const std::string& title, const std::string& extraScript = "");
+ void writeNavigationFrame(std::ostream& ostr, const std::string& group, const std::string& item);
+ static void writeFooter(std::ostream& ostr);
+ void writeCopyright(std::ostream& ostr);
+ static void writeTitle(std::ostream& ostr, const std::string& category, const std::string& title);
+ static void writeTitle(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace, const std::string& title);
+ static void writeSubTitle(std::ostream& ostr, const std::string& title);
+ static void beginBody(std::ostream& ostr);
+ static void endBody(std::ostream& ostr);
+ static void beginContent(std::ostream& ostr);
+ static void endContent(std::ostream& ostr);
+ void writeDescription(std::ostream& ostr, const std::string& text);
+ void writeDescriptionLine(std::ostream& ostr, const std::string& text, TextState& state);
+ void writeSummary(std::ostream& ostr, const std::string& text, const std::string& uri);
+ static std::string htmlize(const std::string& str);
+ static std::string htmlize(char c);
+ static TextState analyzeLine(const std::string& line);
+ static std::string htmlizeName(const std::string& name);
+ void writeText(std::ostream& ostr, const std::string& text);
+ void writeText(std::ostream& ostr, std::string::const_iterator begin, const std::string::const_iterator& end);
+ void writeDecl(std::ostream& ostr, const std::string& decl);
+ void writeDecl(std::ostream& ostr, std::string::const_iterator begin, const std::string::const_iterator& end);
+ bool writeSymbol(std::ostream& ostr, std::string& token, std::string::const_iterator& begin, const std::string::const_iterator& end);
+ bool writeSpecial(std::ostream& ostr, std::string& token, std::string::const_iterator& begin, const std::string::const_iterator& end);
+ void nextToken(std::string::const_iterator& it, const std::string::const_iterator& end, std::string& token);
+ void writeListItem(std::ostream& ostr, const std::string& text);
+ void writeOrderedListItem(std::ostream& ostr, const std::string& text);
+ void writeLiteral(std::ostream& ostr, const std::string& text);
+ void writeFileInfo(std::ostream& ostr, const Poco::CppParser::Symbol* pSymbol);
+ void writeInheritance(std::ostream& ostr, const Poco::CppParser::Struct* pStruct);
+ void writeMethodSummary(std::ostream& ostr, const Poco::CppParser::Struct* pStruct);
+ void writeNestedClasses(std::ostream& ostr, const Poco::CppParser::Struct* pStruct);
+ void writeNameSpacesSummary(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeNameSpaces(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeClassesSummary(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeClasses(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeClassSummary(std::ostream& ostr, const Poco::CppParser::Struct* pStruct);
+ void writeTypesSummary(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeTypes(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeType(std::ostream& ostr, const Poco::CppParser::TypeDef* pType);
+ void writeEnums(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeEnum(std::ostream& ostr, const Poco::CppParser::Enum* pEnum);
+ void writeConstructors(std::ostream& ostr, const Poco::CppParser::Struct* pStruct);
+ void writeDestructor(std::ostream& ostr, const Poco::CppParser::Struct* pStruct);
+ void writeMethods(std::ostream& ostr, const Poco::CppParser::Struct* pNameSpace);
+ void writeFunctionsSummary(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeFunctions(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeFunction(std::ostream& ostr, const Poco::CppParser::Function* pFunc);
+ void writeVariables(std::ostream& ostr, const Poco::CppParser::NameSpace* pNameSpace);
+ void writeVariable(std::ostream& ostr, const Poco::CppParser::Variable* pVar);
+ static void writeNameListItem(std::ostream& ostr, const std::string& name, const Poco::CppParser::Symbol* pSymbol, const Poco::CppParser::NameSpace* pNameSpace, bool& first);
+ static void writeLink(std::ostream& ostr, const std::string& uri, const std::string& text);
+ static void writeLink(std::ostream& ostr, const Poco::CppParser::Symbol* pSymbol, const std::string& text);
+ static void writeLink(std::ostream& ostr, const std::string& uri, const std::string& text, const std::string& linkClass);
+ void writeTargetLink(std::ostream& ostr, const std::string& uri, const std::string& text, const std::string& target);
+ static void writeImageLink(std::ostream& ostr, const std::string& uri, const std::string& image, const std::string& alt);
+ static void writeImage(std::ostream& ostr, const std::string& uri, const std::string& caption);
+ static void writeIcon(std::ostream& ostr, const std::string& icon);
+ static void writeAnchor(std::ostream& ostr, const std::string& text, const Poco::CppParser::Symbol* pSymbol);
+ static void writeDeprecated(std::ostream& ostr, const std::string& what);
+ void libraries(std::set& libs);
+ void packages(const std::string& lib, std::set& packages);
+
+ Poco::CppParser::NameSpace* rootNameSpace() const;
+
+ static const std::string& tr(const std::string& id);
+ static void loadStrings(const std::string& language);
+ static void loadString(const std::string& id, const std::string& def, const std::string& language);
+
+ static Poco::Logger& logger();
+
+ static const std::string RFC_URI;
+ static const std::string nbsp;
+ static const std::string copy;
+ static const std::string mdash;
+
+private:
+ bool _prettifyCode;
+ bool _noFrames;
+ bool _htmlMode;
+ bool _literalMode;
+ const Poco::CppParser::NameSpace::SymbolTable& _symbols;
+ std::string _path;
+ const Poco::CppParser::NameSpace* _pNameSpace;
+ PageMap _pages;
+ bool _pendingLine;
+ int _indent;
+ int _titleId;
+
+ static std::string _language;
+ static StringMap _strings;
+
+ static Poco::Logger* _pLogger;
+};
+
+
+//
+// inlines
+//
+inline Poco::Logger& DocWriter::logger()
+{
+ poco_check_ptr (_pLogger);
+
+ return *_pLogger;
+}
+
+
+#endif // PocoDoc_DocWriter_INCLUDED
diff --git a/PocoDoc/src/PocoDoc.cpp b/PocoDoc/src/PocoDoc.cpp
new file mode 100644
index 000000000..00766a8ea
--- /dev/null
+++ b/PocoDoc/src/PocoDoc.cpp
@@ -0,0 +1,494 @@
+//
+// PocoDoc.cpp
+//
+// Copyright (c) 2005-2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/StringTokenizer.h"
+#include "Poco/Glob.h"
+#include "Poco/Path.h"
+#include "Poco/File.h"
+#include "Poco/DirectoryIterator.h"
+#include "Poco/Process.h"
+#include "Poco/Pipe.h"
+#include "Poco/PipeStream.h"
+#include "Poco/Environment.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/Exception.h"
+#include "Poco/Stopwatch.h"
+#include "Poco/DateTime.h"
+#include "Poco/DateTimeFormatter.h"
+#include "Poco/Timespan.h"
+#include "Poco/DateTimeFormatter.h"
+#include "Poco/Util/Application.h"
+#include "Poco/Util/Option.h"
+#include "Poco/Util/OptionSet.h"
+#include "Poco/Util/HelpFormatter.h"
+#include "Poco/Util/AbstractConfiguration.h"
+#include "Poco/CppParser/Parser.h"
+#include "Poco/CppParser/NameSpace.h"
+#include "Poco/CppParser/Struct.h"
+#include "Poco/CppParser/Utility.h"
+#include "DocWriter.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+using Poco::StringTokenizer;
+using Poco::Glob;
+using Poco::Path;
+using Poco::File;
+using Poco::DirectoryIterator;
+using Poco::Process;
+using Poco::ProcessHandle;
+using Poco::Environment;
+using Poco::NumberFormatter;
+using Poco::Exception;
+using Poco::Util::Application;
+using Poco::Util::Option;
+using Poco::Util::OptionSet;
+using Poco::Util::OptionCallback;
+using Poco::Util::HelpFormatter;
+using Poco::Util::AbstractConfiguration;
+
+static std::string osName = Environment::osName();
+
+class Preprocessor
+{
+public:
+ Preprocessor(const ProcessHandle& proc, std::istream* pStream):
+ _proc(proc),
+ _pStream(pStream)
+ {
+ }
+
+ Preprocessor(const ProcessHandle& proc, std::istream* pStream, const std::string& file):
+ _proc(proc),
+ _pStream(pStream),
+ _file(file)
+ {
+ }
+
+ std::istream& stream()
+ {
+ return *_pStream;
+ }
+
+ ~Preprocessor()
+ {
+ int c = _pStream->get();
+ while (c != -1) c = _pStream->get();
+ delete _pStream;
+ _proc.wait();
+ if (!_file.empty())
+ {
+ try
+ {
+ File f(_file);
+ f.remove();
+ }
+ catch (Exception&)
+ {
+ }
+ }
+ }
+
+private:
+ ProcessHandle _proc;
+ std::istream* _pStream;
+ std::string _file;
+};
+
+
+class PocoDocApp: public Application
+{
+public:
+ PocoDocApp():
+ _helpRequested(false),
+ _writeEclipseTOC(false)
+ {
+ std::setlocale(LC_ALL, "");
+ }
+
+ ~PocoDocApp()
+ {
+ }
+
+protected:
+ void initialize(Application& self)
+ {
+ loadConfiguration(); // load default configuration files, if present
+ Application::initialize(self);
+ }
+
+ void uninitialize()
+ {
+ Application::uninitialize();
+ }
+
+ void reinitialize(Application& self)
+ {
+ Application::reinitialize(self);
+ }
+
+ void defineOptions(OptionSet& options)
+ {
+ Application::defineOptions(options);
+
+ options.addOption(
+ Option("help", "h", "display help information on command line arguments")
+ .required(false)
+ .repeatable(false)
+ .callback(OptionCallback(this, &PocoDocApp::handleHelp)));
+
+ options.addOption(
+ Option("config-file", "f", "load configuration data from a file")
+ .required(false)
+ .repeatable(true)
+ .argument("file")
+ .callback(OptionCallback(this, &PocoDocApp::handleConfig)));
+
+ options.addOption(
+ Option("eclipse", "e", "write Eclipse TOC file")
+ .required(false)
+ .repeatable(false)
+ .callback(OptionCallback(this, &PocoDocApp::handleEclipse)));
+ }
+
+ void handleHelp(const std::string& name, const std::string& value)
+ {
+ _helpRequested = true;
+ displayHelp();
+ stopOptionsProcessing();
+ }
+
+ void handleEclipse(const std::string& name, const std::string& value)
+ {
+ _writeEclipseTOC = true;
+ }
+
+ void handleConfig(const std::string& name, const std::string& value)
+ {
+ loadConfiguration(value, -200);
+ }
+
+ void displayHelp()
+ {
+ HelpFormatter helpFormatter(options());
+ helpFormatter.setCommand(commandName());
+ helpFormatter.setUsage("OPTIONS");
+ helpFormatter.setHeader("Applied Informatics' super duper documentation builder.");
+ helpFormatter.format(std::cout);
+ }
+
+ void buildFileList(std::set& files)
+ {
+ std::set temp;
+ std::string includes = config().getString("PocoDoc.files.include");
+ std::string excludes = config().getString("PocoDoc.files.exclude", "");
+ StringTokenizer incTokenizer(includes, ",\n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ for (StringTokenizer::Iterator it = incTokenizer.begin(); it != incTokenizer.end(); ++it)
+ {
+ Glob::glob(*it, temp);
+ }
+ StringTokenizer excTokenizer(excludes, ",\n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ for (std::set::const_iterator it = temp.begin(); it != temp.end(); ++it)
+ {
+ Path p(*it);
+ bool include = true;
+ for (StringTokenizer::Iterator itg = excTokenizer.begin(); itg != excTokenizer.end(); ++itg)
+ {
+ Glob glob(*itg);
+ if (glob.match(p.getFileName()))
+ include = false;
+ }
+ if (include)
+ files.insert(*it);
+ }
+ }
+
+ Preprocessor* preprocess(const std::string& file)
+ {
+ Path pp(file);
+ pp.setExtension("i");
+ std::string comp = "PocoDoc.compiler";
+ if (Environment::osFamilyWindows())
+ comp += ".windows";
+ else
+ comp += ".unix";
+ std::string exec = config().getString(comp + ".exec");
+ std::string opts = config().getString(comp + ".options");
+ std::string path = config().getString(comp + ".path", "");
+ bool usePipe = config().getBool(comp + ".usePipe", false);
+ std::string popts;
+ for (std::string::const_iterator it = opts.begin(); it != opts.end(); ++it)
+ {
+ if (*it == '%')
+ popts += pp.getBaseName();
+ else
+ popts += *it;
+ }
+ StringTokenizer tokenizer(popts, ",\n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ std::vector args(tokenizer.begin(), tokenizer.end());
+ args.push_back(file);
+
+ if (!path.empty())
+ {
+ std::string newPath(Environment::get("PATH"));
+ newPath += Path::pathSeparator();
+ newPath += path;
+ Environment::set("PATH", path);
+ }
+
+ if (usePipe)
+ {
+ Poco::Pipe inPipe;
+ ProcessHandle proc = Process::launch(exec, args, 0, &inPipe, 0);
+ return new Preprocessor(proc, new Poco::PipeInputStream(inPipe));
+ }
+ else
+ {
+ ProcessHandle proc = Process::launch(exec, args);
+ proc.wait();
+ return new Preprocessor(proc, new std::ifstream(pp.getFileName().c_str()), pp.getFileName());
+ }
+ }
+
+ void parse(const std::string& file)
+ {
+ logger().information("Preprocessing " + file);
+ std::unique_ptr pPreProc(preprocess(file));
+
+ logger().information("Parsing " + file);
+ if (pPreProc->stream().good())
+ {
+ Poco::CppParser::Parser parser(_gst, file, pPreProc->stream());
+ parser.parse();
+ }
+ else throw Poco::OpenFileException("cannot read from preprocessor");
+ }
+
+ int parseAll()
+ {
+ int errors = 0;
+ std::set files;
+ buildFileList(files);
+ for (std::set::const_iterator it = files.begin(); it != files.end(); ++it)
+ {
+ try
+ {
+ parse(*it);
+ }
+ catch (Exception& exc)
+ {
+ logger().log(exc);
+ ++errors;
+ }
+ }
+ return errors;
+ }
+
+ void fixup()
+ {
+ logger().information("Fixing-up class hierarchies");
+ for (Poco::CppParser::NameSpace::SymbolTable::iterator it = _gst.begin(); it != _gst.end(); ++it)
+ {
+ Poco::CppParser::Struct* pStruct = dynamic_cast(it->second);
+ if (pStruct)
+ {
+ pStruct->fixupBases();
+ }
+ }
+ }
+
+ void writeDoc()
+ {
+ logger().information("Generating documentation");
+ Path path(config().getString("PocoDoc.output", "doc"));
+ path.makeDirectory();
+ File file(path);
+ file.createDirectories();
+
+ DocWriter writer(_gst, path.toString(), config().getBool("PocoDoc.prettifyCode", false), _writeEclipseTOC);
+
+ if (config().hasProperty("PocoDoc.pages"))
+ {
+ std::string pages = config().getString("PocoDoc.pages");
+ StringTokenizer tokenizer(pages, ",\n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ std::set pageSet;
+ for (StringTokenizer::Iterator it = tokenizer.begin(); it != tokenizer.end(); ++it)
+ {
+ Glob::glob(*it, pageSet);
+ }
+ for (std::set::const_iterator it = pageSet.begin(); it != pageSet.end(); ++it)
+ {
+ writer.addPage(*it);
+ }
+ }
+ writer.write();
+
+ if (_writeEclipseTOC)
+ {
+ writer.writeEclipseTOC();
+ }
+ }
+
+ void copyResources()
+ {
+ logger().information("Copying resources");
+ Path path(config().getString("PocoDoc.output", "doc"));
+
+ if (config().hasProperty("PocoDoc.resources"))
+ {
+ std::string pages = config().getString("PocoDoc.resources");
+ StringTokenizer tokenizer(pages, ",\n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ std::set pageSet;
+ for (StringTokenizer::Iterator it = tokenizer.begin(); it != tokenizer.end(); ++it)
+ {
+ Glob::glob(*it, pageSet);
+ }
+ for (std::set::const_iterator it = pageSet.begin(); it != pageSet.end(); ++it)
+ {
+ try
+ {
+ copyResource(Path(*it), path);
+ }
+ catch (Poco::Exception& exc)
+ {
+ logger().log(exc);
+ }
+ }
+ }
+ }
+
+ void copyResource(const Path& source, const Path& dest)
+ {
+ logger().information(std::string("Copying resource ") + source.toString() + " to " + dest.toString());
+ File sf(source);
+ if (sf.isDirectory())
+ copyDirectory(source, dest);
+ else
+ copyFile(source, dest);
+ }
+
+ void copyFile(const Path& source, const Path& dest)
+ {
+ Path dd(dest);
+ dd.makeDirectory();
+ File df(dd);
+ df.createDirectories();
+ dd.setFileName(source.getFileName());
+ if (source.getExtension() == "thtml")
+ {
+ dd.setExtension("html");
+ std::ifstream istr(source.toString().c_str());
+ std::ofstream ostr(dd.toString().c_str());
+ while (istr.good())
+ {
+ std::string line;
+ std::getline(istr, line);
+ ostr << config().expand(line) << std::endl;
+ }
+ }
+ else
+ {
+ File sf(source);
+ sf.copyTo(dd.toString());
+ }
+ }
+
+ void copyDirectory(const Path& source, const Path& dest)
+ {
+ Path src(source);
+ src.makeFile();
+ DirectoryIterator it(src);
+ DirectoryIterator end;
+ for (; it != end; ++it)
+ {
+ Path dd(dest);
+ dd.makeDirectory();
+ dd.pushDirectory(src.getFileName());
+ copyResource(it.path(), dd);
+ }
+ }
+
+ int main(const std::vector& args)
+ {
+ if (!_helpRequested)
+ {
+ Poco::DateTime now;
+ config().setString("PocoDoc.date", Poco::DateTimeFormatter::format(now, "%Y-%m-%d"));
+ config().setString("PocoDoc.year", Poco::DateTimeFormatter::format(now, "%Y"));
+ config().setString("PocoDoc.googleAnalyticsCode", generateGoogleAnalyticsCode());
+ Poco::Stopwatch sw;
+ int errors = 0;
+ try
+ {
+ sw.start();
+ errors = parseAll();
+ fixup();
+ writeDoc();
+ copyResources();
+ sw.stop();
+ }
+ catch (Exception& exc)
+ {
+ std::cerr << exc.displayText() << std::endl;
+ }
+ logger().information(NumberFormatter::format(errors) + " errors.");
+ logger().information(std::string("Time: ") + Poco::DateTimeFormatter::format(Poco::Timespan(sw.elapsed())));
+ }
+ return Application::EXIT_OK;
+ }
+
+ std::string generateGoogleAnalyticsCode()
+ {
+ std::stringstream ostr;
+ std::string googleAnalyticsId(config().getString("PocoDoc.googleAnalyticsId", ""));
+ if (!googleAnalyticsId.empty())
+ {
+ ostr << "\n";
+ ostr << "\n";
+ ostr << "\n";
+ ostr << "\n";
+ }
+ return ostr.str();
+ }
+
+private:
+ bool _helpRequested;
+ bool _writeEclipseTOC;
+ Poco::CppParser::NameSpace::SymbolTable _gst;
+};
+
+
+int main(int argc, char** argv)
+{
+ PocoDocApp app;
+ try
+ {
+ app.init(argc, argv);
+ }
+ catch (Poco::Exception& exc)
+ {
+ app.logger().log(exc);
+ return Application::EXIT_CONFIG;
+ }
+ return app.run();
+}