/****************************************************************************** * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */ #include #include "textstream.h" #include "xmlgen.h" #include "doxygen.h" #include "message.h" #include "config.h" #include "classlist.h" #include "util.h" #include "defargs.h" #include "outputgen.h" #include "dot.h" #include "dotclassgraph.h" #include "dotincldepgraph.h" #include "pagedef.h" #include "filename.h" #include "version.h" #include "xmldocvisitor.h" #include "docparser.h" #include "language.h" #include "parserintf.h" #include "arguments.h" #include "memberlist.h" #include "groupdef.h" #include "memberdef.h" #include "namespacedef.h" #include "membername.h" #include "membergroup.h" #include "dirdef.h" #include "section.h" #include "htmlentity.h" #include "resourcemgr.h" #include "dir.h" #include "utf8.h" // no debug info #define XML_DB(x) do {} while(0) // debug to stdout //#define XML_DB(x) printf x // debug inside output //#define XML_DB(x) QCString __t;__t.sprintf x;m_t << __t //------------------ static std::map g_xmlSectionMap = { { MemberListType_pubTypes,"public-type" }, { MemberListType_pubMethods,"public-func" }, { MemberListType_pubAttribs,"public-attrib" }, { MemberListType_pubSlots,"public-slot" }, { MemberListType_signals,"signal" }, { MemberListType_dcopMethods,"dcop-func" }, { MemberListType_properties,"property" }, { MemberListType_events,"event" }, { MemberListType_interfaces,"interfaces" }, { MemberListType_services,"services" }, { MemberListType_pubStaticMethods,"public-static-func" }, { MemberListType_pubStaticAttribs,"public-static-attrib" }, { MemberListType_proTypes,"protected-type" }, { MemberListType_proMethods,"protected-func" }, { MemberListType_proAttribs,"protected-attrib" }, { MemberListType_proSlots,"protected-slot" }, { MemberListType_proStaticMethods,"protected-static-func" }, { MemberListType_proStaticAttribs,"protected-static-attrib" }, { MemberListType_pacTypes,"package-type" }, { MemberListType_pacMethods,"package-func" }, { MemberListType_pacAttribs,"package-attrib" }, { MemberListType_pacStaticMethods,"package-static-func" }, { MemberListType_pacStaticAttribs,"package-static-attrib" }, { MemberListType_priTypes,"private-type" }, { MemberListType_priMethods,"private-func" }, { MemberListType_priAttribs,"private-attrib" }, { MemberListType_priSlots,"private-slot" }, { MemberListType_priStaticMethods,"private-static-func" }, { MemberListType_priStaticAttribs,"private-static-attrib" }, { MemberListType_friends,"friend" }, { MemberListType_related,"related" }, { MemberListType_decDefineMembers,"define" }, { MemberListType_decProtoMembers,"prototype" }, { MemberListType_decTypedefMembers,"typedef" }, { MemberListType_decSequenceMembers,"sequence" }, { MemberListType_decDictionaryMembers,"dictionary" }, { MemberListType_decEnumMembers,"enum" }, { MemberListType_decFuncMembers,"func" }, { MemberListType_decVarMembers,"var" }, }; static const char *xmlSectionMapper(MemberListType ml) { auto it = g_xmlSectionMap.find(ml); return it!=g_xmlSectionMap.end() ? it->second.c_str() : ""; } inline void writeXMLString(TextStream &t,const QCString &s) { t << convertToXML(s); } inline void writeXMLCodeString(TextStream &t,const QCString &str, int &col) { if (str.isEmpty()) return; const char *s = str.data(); char c; while ((c=*s++)) { switch(c) { case '\t': { int tabSize = Config_getInt(TAB_SIZE); int spacesToNextTabStop = tabSize - (col%tabSize); col+=spacesToNextTabStop; while (spacesToNextTabStop--) t << ""; break; } case ' ': t << ""; col++; break; case '<': t << "<"; col++; break; case '>': t << ">"; col++; break; case '&': t << "&"; col++; break; case '\'': t << "'"; col++; break; case '"': t << """; col++; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: // encode invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char) t << ""; break; default: s=writeUTF8Char(t,s-1); col++; break; } } } static void writeXMLHeader(TextStream &t) { t << "\n";; t << "trISOLang() << "\""; t << ">\n"; } static void writeCombineScript() { QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/combine.xslt"; std::ofstream t(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!t.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } t << "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n"; } void writeXMLLink(TextStream &t,const QCString &extRef,const QCString &compoundId, const QCString &anchorId,const QCString &text,const QCString &tooltip) { t << ""; writeXMLString(t,text); t << ""; } /** Implements TextGeneratorIntf for an XML stream. */ class TextGeneratorXMLImpl : public TextGeneratorIntf { public: TextGeneratorXMLImpl(TextStream &t): m_t(t) {} void writeString(const QCString &s,bool /*keepSpaces*/) const { writeXMLString(m_t,s); } void writeBreak(int) const {} void writeLink(const QCString &extRef,const QCString &file, const QCString &anchor,const QCString &text ) const { writeXMLLink(m_t,extRef,file,anchor,text,QCString()); } private: TextStream &m_t; }; //------------------------------------------------------------------------------------------- XMLCodeGenerator::XMLCodeGenerator(TextStream &t) : m_t(t), m_lineNumber(-1), m_isMemberRef(FALSE), m_col(0), m_insideCodeLine(FALSE), m_normalHLNeedStartTag(TRUE), m_insideSpecialHL(FALSE) { } /** Generator for producing XML formatted source code. */ void XMLCodeGenerator::codify(const QCString &text) { XML_DB(("(codify \"%s\")\n",text)); if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) { m_t << ""; m_normalHLNeedStartTag=FALSE; } writeXMLCodeString(m_t,text,m_col); } void XMLCodeGenerator::writeCodeLink(CodeSymbolType, const QCString &ref,const QCString &file, const QCString &anchor,const QCString &name, const QCString &tooltip) { XML_DB(("(writeCodeLink)\n")); if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) { m_t << ""; m_normalHLNeedStartTag=FALSE; } writeXMLLink(m_t,ref,file,anchor,name,tooltip); m_col+=name.length(); } void XMLCodeGenerator::writeTooltip(const QCString &, const DocLinkInfo &, const QCString &, const QCString &, const SourceLinkInfo &, const SourceLinkInfo & ) { XML_DB(("(writeToolTip)\n")); } void XMLCodeGenerator::startCodeLine(bool) { XML_DB(("(startCodeLine)\n")); m_t << ""; m_insideCodeLine=TRUE; m_col=0; } void XMLCodeGenerator::endCodeLine() { XML_DB(("(endCodeLine)\n")); if (!m_insideSpecialHL && !m_normalHLNeedStartTag) { m_t << ""; m_normalHLNeedStartTag=TRUE; } m_t << "\n"; // non DocBook m_lineNumber = -1; m_refId.resize(0); m_external.resize(0); m_insideCodeLine=FALSE; } void XMLCodeGenerator::startFontClass(const QCString &colorClass) { XML_DB(("(startFontClass)\n")); if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag) { m_t << ""; m_normalHLNeedStartTag=TRUE; } m_t << ""; // non DocBook m_insideSpecialHL=TRUE; } void XMLCodeGenerator::endFontClass() { XML_DB(("(endFontClass)\n")); m_t << ""; // non DocBook m_insideSpecialHL=FALSE; } void XMLCodeGenerator::writeCodeAnchor(const QCString &) { XML_DB(("(writeCodeAnchor)\n")); } void XMLCodeGenerator::writeLineNumber(const QCString &extRef,const QCString &compId, const QCString &anchorId,int l,bool) { XML_DB(("(writeLineNumber)\n")); // we remember the information provided here to use it // at the start tag. m_lineNumber = l; if (!compId.isEmpty()) { m_refId=compId; if (!anchorId.isEmpty()) m_refId+=QCString("_1")+anchorId; m_isMemberRef = anchorId!=0; if (!extRef.isEmpty()) m_external=extRef; } } void XMLCodeGenerator::finish() { if (m_insideCodeLine) endCodeLine(); } void XMLCodeGenerator::startCodeFragment(const QCString &) { m_t << " \n"; } void XMLCodeGenerator::endCodeFragment(const QCString &) { m_t << " \n"; } //------------------------------------------------------------------------------------------- static void writeTemplateArgumentList(TextStream &t, const ArgumentList &al, const Definition *scope, const FileDef *fileScope, int indent) { QCString indentStr; indentStr.fill(' ',indent); if (al.hasParameters()) { t << indentStr << "\n"; for (const Argument &a : al) { t << indentStr << " \n"; if (!a.type.isEmpty()) { t << indentStr << " "; linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a.type); t << "\n"; } if (!a.name.isEmpty()) { t << indentStr << " " << convertToXML(a.name) << "\n"; t << indentStr << " " << convertToXML(a.name) << "\n"; } if (!a.defval.isEmpty()) { t << indentStr << " "; linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a.defval); t << "\n"; } if (!a.typeConstraint.isEmpty()) { t << indentStr << " "; linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a.typeConstraint); t << "\n"; } t << indentStr << " \n"; } t << indentStr << "\n"; } } static void writeMemberTemplateLists(const MemberDef *md,TextStream &t) { writeTemplateArgumentList(t,md->templateArguments(),md->getClassDef(),md->getFileDef(),8); } static void writeTemplateList(const ClassDef *cd,TextStream &t) { writeTemplateArgumentList(t,cd->templateArguments(),cd,cd->getFileDef(),4); } static void writeTemplateList(const ConceptDef *cd,TextStream &t) { writeTemplateArgumentList(t,cd->getTemplateParameterList(),cd,cd->getFileDef(),4); } static void writeXMLDocBlock(TextStream &t, const QCString &fileName, int lineNr, const Definition *scope, const MemberDef * md, const QCString &text) { QCString stext = text.stripWhiteSpace(); if (stext.isEmpty()) return; // convert the documentation string into an abstract syntax tree auto parser { createDocParser() }; auto ast { validatingParseDoc(*parser.get(), fileName,lineNr,scope,md,text,FALSE,FALSE, QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)) }; auto astImpl = dynamic_cast(ast.get()); if (astImpl) { // create a code generator auto xmlCodeGen = std::make_unique(t); // create a parse tree visitor for XML XmlDocVisitor visitor(t,*xmlCodeGen,scope?scope->getDefFileExtension():QCString("")); // visit all nodes std::visit(visitor,astImpl->root); // clean up } } void writeXMLCodeBlock(TextStream &t,FileDef *fd) { auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension()); intf->resetCodeParserState(); XMLCodeGenerator *xmlGen = new XMLCodeGenerator(t); xmlGen->startCodeFragment("DoxyCode"); intf->parseCode(*xmlGen, // codeOutIntf QCString(), // scopeName fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)), langExt, // lang FALSE, // isExampleBlock QCString(), // exampleName fd, // fileDef -1, // startLine -1, // endLine FALSE, // inlineFragment 0, // memberDef TRUE // showLineNumbers ); xmlGen->endCodeFragment("DoxyCode"); xmlGen->finish(); delete xmlGen; } static void writeMemberReference(TextStream &t,const Definition *def,const MemberDef *rmd,const QCString &tagName) { QCString scope = rmd->getScopeString(); QCString name = rmd->name(); if (!scope.isEmpty() && scope!=def->name()) { name.prepend(scope+getLanguageSpecificSeparator(rmd->getLanguage())); } t << " <" << tagName << " refid=\""; t << rmd->getOutputFileBase() << "_1" << rmd->anchor() << "\""; if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { t << " compoundref=\"" << rmd->getBodyDef()->getOutputFileBase() << "\""; t << " startline=\"" << rmd->getStartBodyLine() << "\""; if (rmd->getEndBodyLine()!=-1) { t << " endline=\"" << rmd->getEndBodyLine() << "\""; } } t << ">" << convertToXML(name) << "\n"; } static void stripQualifiers(QCString &typeStr) { bool done=FALSE; typeStr.stripPrefix("friend "); while (!done) { if (typeStr.stripPrefix("static ")); else if (typeStr.stripPrefix("virtual ")); else if (typeStr=="virtual") typeStr=""; else done=TRUE; } } static QCString classOutputFileBase(const ClassDef *cd) { //bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES); //if (inlineGroupedClasses && cd->partOfGroups()!=0) return cd->getOutputFileBase(); //else // return cd->getOutputFileBase(); } static QCString memberOutputFileBase(const MemberDef *md) { //bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES); //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0) // return md->getClassDef()->getXmlOutputFileBase(); //else // return md->getOutputFileBase(); return md->getOutputFileBase(); } static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &t,const Definition *def) { // + declaration/definition arg lists // + reimplements // + reimplementedBy // + exceptions // + const/volatile specifiers // - examples // + source definition // + source references // + source referenced by // - body code // + template arguments // (templateArguments(), definitionTemplateParameterLists()) // - call graph // enum values are written as part of the enum if (md->memberType()==MemberType_EnumValue) return; if (md->isHidden()) return; // group members are only visible in their group //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return; QCString memType; bool isFunc=FALSE; switch (md->memberType()) { case MemberType_Define: memType="define"; break; case MemberType_Function: memType="function"; isFunc=TRUE; break; case MemberType_Variable: memType="variable"; break; case MemberType_Typedef: memType="typedef"; break; case MemberType_Enumeration: memType="enum"; break; case MemberType_EnumValue: ASSERT(0); break; case MemberType_Signal: memType="signal"; isFunc=TRUE; break; case MemberType_Slot: memType="slot"; isFunc=TRUE; break; case MemberType_Friend: memType="friend"; isFunc=TRUE; break; case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break; case MemberType_Property: memType="property"; break; case MemberType_Event: memType="event"; break; case MemberType_Interface: memType="interface"; break; case MemberType_Service: memType="service"; break; case MemberType_Sequence: memType="sequence"; break; case MemberType_Dictionary: memType="dictionary"; break; } ti << " anchor() << "\" kind=\"" << memType << "\">" << convertToXML(md->name()) << "\n"; t << " getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); } else { t << memberOutputFileBase(md); } t << "_1" // encoded ':' character (see util.cpp:convertNameToFile) << md->anchor(); t << "\" prot=\""; switch(md->protection()) { case Public: t << "public"; break; case Protected: t << "protected"; break; case Private: t << "private"; break; case Package: t << "package"; break; } t << "\""; t << " static=\""; if (md->isStatic()) t << "yes"; else t << "no"; t << "\""; if (md->isConstExpr()) { t << " constexpr=\"yes\""; } if (isFunc) { const ArgumentList &al = md->argumentList(); t << " const=\""; if (al.constSpecifier()) t << "yes"; else t << "no"; t << "\""; t << " explicit=\""; if (md->isExplicit()) t << "yes"; else t << "no"; t << "\""; t << " inline=\""; if (md->isInline()) t << "yes"; else t << "no"; t << "\""; if (al.refQualifier()!=RefQualifierNone) { t << " refqual=\""; if (al.refQualifier()==RefQualifierLValue) t << "lvalue"; else t << "rvalue"; t << "\""; } if (md->isFinal()) { t << " final=\"yes\""; } if (md->isSealed()) { t << " sealed=\"yes\""; } if (md->isNew()) { t << " new=\"yes\""; } if (md->isOptional()) { t << " optional=\"yes\""; } if (md->isRequired()) { t << " required=\"yes\""; } if (md->isNoExcept()) { t << " noexcept=\"yes\""; } if (al.volatileSpecifier()) { t << " volatile=\"yes\""; } t << " virt=\""; switch (md->virtualness()) { case Normal: t << "non-virtual"; break; case Virtual: t << "virtual"; break; case Pure: t << "pure-virtual"; break; default: ASSERT(0); } t << "\""; } if (md->memberType() == MemberType_Enumeration) { t << " strong=\""; if (md->isStrong()) t << "yes"; else t << "no"; t << "\""; } if (md->memberType() == MemberType_Variable) { //ArgumentList *al = md->argumentList(); //t << " volatile=\""; //if (al && al->volatileSpecifier) t << "yes"; else t << "no"; t << " mutable=\""; if (md->isMutable()) t << "yes"; else t << "no"; t << "\""; if (md->isInitonly()) { t << " initonly=\"yes\""; } if (md->isAttribute()) { t << " attribute=\"yes\""; } if (md->isUNOProperty()) { t << " property=\"yes\""; } if (md->isReadonly()) { t << " readonly=\"yes\""; } if (md->isBound()) { t << " bound=\"yes\""; } if (md->isRemovable()) { t << " removable=\"yes\""; } if (md->isConstrained()) { t << " constrained=\"yes\""; } if (md->isTransient()) { t << " transient=\"yes\""; } if (md->isMaybeVoid()) { t << " maybevoid=\"yes\""; } if (md->isMaybeDefault()) { t << " maybedefault=\"yes\""; } if (md->isMaybeAmbiguous()) { t << " maybeambiguous=\"yes\""; } } else if (md->memberType() == MemberType_Property) { t << " readable=\""; if (md->isReadable()) t << "yes"; else t << "no"; t << "\""; t << " writable=\""; if (md->isWritable()) t << "yes"; else t << "no"; t << "\""; t << " gettable=\""; if (md->isGettable()) t << "yes"; else t << "no"; t << "\""; t << " privategettable=\""; if (md->isPrivateGettable()) t << "yes"; else t << "no"; t << "\""; t << " protectedgettable=\""; if (md->isProtectedGettable()) t << "yes"; else t << "no"; t << "\""; t << " settable=\""; if (md->isSettable()) t << "yes"; else t << "no"; t << "\""; t << " privatesettable=\""; if (md->isPrivateSettable()) t << "yes"; else t << "no"; t << "\""; t << " protectedsettable=\""; if (md->isProtectedSettable()) t << "yes"; else t << "no"; t << "\""; if (md->isAssign() || md->isCopy() || md->isRetain() || md->isStrong() || md->isWeak()) { t << " accessor=\""; if (md->isAssign()) t << "assign"; else if (md->isCopy()) t << "copy"; else if (md->isRetain()) t << "retain"; else if (md->isStrong()) t << "strong"; else if (md->isWeak()) t << "weak"; t << "\""; } } else if (md->memberType() == MemberType_Event) { t << " add=\""; if (md->isAddable()) t << "yes"; else t << "no"; t << "\""; t << " remove=\""; if (md->isRemovable()) t << "yes"; else t << "no"; t << "\""; t << " raise=\""; if (md->isRaisable()) t << "yes"; else t << "no"; t << "\""; } t << ">\n"; if (md->memberType()!=MemberType_Define && md->memberType()!=MemberType_Enumeration ) { writeMemberTemplateLists(md,t); QCString typeStr = md->typeString(); stripQualifiers(typeStr); t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,typeStr); t << "\n"; t << " " << convertToXML(md->definition()) << "\n"; t << " " << convertToXML(md->argsString()) << "\n"; } if (md->memberType() == MemberType_Enumeration) { t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->enumBaseType()); t << "\n"; } QCString name = md->name(); QCString qualifiedName = md->qualifiedName();; t << " " << convertToXML(name) << "\n"; if (name!=qualifiedName) { t << " " << convertToXML(qualifiedName) << "\n"; } if (md->memberType() == MemberType_Property) { if (md->isReadable()) t << " " << convertToXML(md->getReadAccessor()) << "\n"; if (md->isWritable()) t << " " << convertToXML(md->getWriteAccessor()) << "\n"; } if (md->memberType()==MemberType_Variable && !md->bitfieldString().isEmpty()) { QCString bitfield = md->bitfieldString(); if (bitfield.at(0)==':') bitfield=bitfield.mid(1); t << " " << convertToXML(bitfield) << "\n"; } const MemberDef *rmd = md->reimplements(); if (rmd) { t << " anchor() << "\">" << convertToXML(rmd->name()) << "\n"; } for (const auto &rbmd : md->reimplementedBy()) { t << " anchor() << "\">" << convertToXML(rbmd->name()) << "\n"; } if (md->isFriendClass()) // for friend classes we show a link to the class as a "parameter" { t << " \n"; t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->name()); t << "\n"; t << " \n"; } else if (isFunc) //function { const ArgumentList &declAl = md->declArgumentList(); const ArgumentList &defAl = md->argumentList(); bool isFortran = md->getLanguage()==SrcLangExt_Fortran; if (declAl.hasParameters()) { auto defIt = defAl.begin(); for (const Argument &a : declAl) { //const Argument *defArg = defAli.current(); const Argument *defArg = 0; if (defIt!=defAl.end()) { defArg = &(*defIt); ++defIt; } t << " \n"; if (!a.attrib.isEmpty()) { t << " "; writeXMLString(t,a.attrib); t << "\n"; } if (isFortran && defArg && !defArg->type.isEmpty()) { t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,defArg->type); t << "\n"; } else if (!a.type.isEmpty()) { t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,a.type); t << "\n"; } if (!a.name.isEmpty()) { t << " "; writeXMLString(t,a.name); t << "\n"; } if (defArg && !defArg->name.isEmpty() && defArg->name!=a.name) { t << " "; writeXMLString(t,defArg->name); t << "\n"; } if (!a.array.isEmpty()) { t << " "; writeXMLString(t,a.array); t << "\n"; } if (!a.defval.isEmpty()) { t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,a.defval); t << "\n"; } if (defArg && defArg->hasDocumentation()) { t << " "; writeXMLDocBlock(t,md->getDefFileName(),md->getDefLine(), md->getOuterScope(),md,defArg->docs); t << "\n"; } t << " \n"; } } } else if (md->memberType()==MemberType_Define && !md->argsString().isEmpty()) // define { if (md->argumentList().empty()) // special case for "foo()" to // distinguish it from "foo". { t << " \n"; } else { for (const Argument &a : md->argumentList()) { t << " " << a.type << "\n"; } } } if (!md->requiresClause().isEmpty()) { t << " "; linkifyText(TextGeneratorXMLImpl(t),md,md->getFileDef(),md,md->requiresClause()); t << " \n"; } if (md->hasOneLineInitializer() || md->hasMultiLineInitializer()) { t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->initializer()); t << "\n"; } if (!md->excpString().isEmpty()) { t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->excpString()); t << "\n"; } if (md->memberType()==MemberType_Enumeration) // enum { for (const auto &emd : md->enumFieldList()) { ti << " anchor() << "\" kind=\"enumvalue\">" << convertToXML(emd->name()) << "\n"; t << " anchor() << "\" prot=\""; switch (emd->protection()) { case Public: t << "public"; break; case Protected: t << "protected"; break; case Private: t << "private"; break; case Package: t << "package"; break; } t << "\">\n"; t << " "; writeXMLString(t,emd->name()); t << "\n"; if (!emd->initializer().isEmpty()) { t << " "; writeXMLString(t,emd->initializer()); t << "\n"; } t << " \n"; writeXMLDocBlock(t,emd->briefFile(),emd->briefLine(),emd->getOuterScope(),emd,emd->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,emd->docFile(),emd->docLine(),emd->getOuterScope(),emd,emd->documentation()); t << " \n"; t << " \n"; } } t << " \n"; writeXMLDocBlock(t,md->briefFile(),md->briefLine(),md->getOuterScope(),md,md->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation()); t << " \n"; t << " \n"; writeXMLDocBlock(t,md->docFile(),md->inbodyLine(),md->getOuterScope(),md,md->inbodyDocumentation()); t << " \n"; if (md->getDefLine()!=-1) { t << " getDefFileName())) << "\" line=\"" << md->getDefLine() << "\" column=\"" << md->getDefColumn() << "\"" ; if (md->getStartBodyLine()!=-1) { const FileDef *bodyDef = md->getBodyDef(); if (bodyDef) { t << " bodyfile=\"" << convertToXML(stripFromPath(bodyDef->absFilePath())) << "\""; } t << " bodystart=\"" << md->getStartBodyLine() << "\" bodyend=\"" << md->getEndBodyLine() << "\""; } if (md->getDeclLine()!=-1) { t << " declfile=\"" << convertToXML(stripFromPath(md->getDeclFileName())) << "\" declline=\"" << md->getDeclLine() << "\" declcolumn=\"" << md->getDeclColumn() << "\""; } t << "/>\n"; } //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); auto refList = md->getReferencesMembers(); for (const auto &refmd : refList) { writeMemberReference(t,def,refmd,"references"); } auto refByList = md->getReferencedByMembers(); for (const auto &refmd : refByList) { writeMemberReference(t,def,refmd,"referencedby"); } t << " \n"; } // namespace members are also inserted in the file scope, but // to prevent this duplication in the XML output, we optionally filter those here. static bool memberVisible(const Definition *d,const MemberDef *md) { return Config_getBool(XML_NS_MEMB_FILE_SCOPE) || d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0; } static void generateXMLSection(const Definition *d,TextStream &ti,TextStream &t, const MemberList *ml,const QCString &kind,const QCString &header=QCString(), const QCString &documentation=QCString()) { if (ml==0) return; int count=0; for (const auto &md : *ml) { if (memberVisible(d,md) && (md->memberType()!=MemberType_EnumValue) && !md->isHidden()) { count++; } } if (count==0) return; // empty list t << " \n"; if (!header.isEmpty()) { t << "
" << convertToXML(header) << "
\n"; } if (!documentation.isEmpty()) { t << " "; writeXMLDocBlock(t,d->docFile(),d->docLine(),d,0,documentation); t << "\n"; } for (const auto &md : *ml) { if (memberVisible(d,md)) { generateXMLForMember(md,ti,t,d); } } t << "
\n"; } static void writeListOfAllMembers(const ClassDef *cd,TextStream &t) { t << " \n"; for (auto &mni : cd->memberNameInfoLinkedMap()) { for (auto &mi : *mni) { const MemberDef *md=mi->memberDef(); if (!md->isAnonymous()) { Protection prot = mi->prot(); Specifier virt=md->virtualness(); t << " anchor() << "\" prot=\""; switch (prot) { case Public: t << "public"; break; case Protected: t << "protected"; break; case Private: t << "private"; break; case Package: t << "package"; break; } t << "\" virt=\""; switch(virt) { case Normal: t << "non-virtual"; break; case Virtual: t << "virtual"; break; case Pure: t << "pure-virtual"; break; } t << "\""; if (!mi->ambiguityResolutionScope().isEmpty()) { t << " ambiguityscope=\"" << convertToXML(mi->ambiguityResolutionScope()) << "\""; } t << ">" << convertToXML(cd->name()) << "" << convertToXML(md->name()) << "\n"; } } } t << " \n"; } static void writeInnerClasses(const ClassLinkedRefMap &cl,TextStream &t) { for (const auto &cd : cl) { if (!cd->isHidden() && !cd->isAnonymous()) { t << " protection()) { case Public: t << "public"; break; case Protected: t << "protected"; break; case Private: t << "private"; break; case Package: t << "package"; break; } t << "\">" << convertToXML(cd->name()) << "\n"; } } } static void writeInnerNamespaces(const NamespaceLinkedRefMap &nl,TextStream &t) { for (const auto &nd : nl) { if (!nd->isHidden() && !nd->isAnonymous()) { t << " getOutputFileBase() << "\"" << (nd->isInline() ? " inline=\"yes\"" : "") << ">" << convertToXML(nd->name()) << "\n"; } } } static void writeInnerFiles(const FileList &fl,TextStream &t) { for (const auto &fd : fl) { t << " getOutputFileBase() << "\">" << convertToXML(fd->name()) << "\n"; } } static void writeInnerPages(const PageLinkedRefMap &pl,TextStream &t) { for (const auto &pd : pl) { t << " getOutputFileBase(); if (pd->getGroupDef()) { t << "_" << pd->name(); } t << "\">" << convertToXML(pd->title()) << "\n"; } } static void writeInnerGroups(const GroupList &gl,TextStream &t) { for (const auto &sgd : gl) { t << " getOutputFileBase() << "\">" << convertToXML(sgd->groupTitle()) << "\n"; } } static void writeInnerDirs(const DirList *dl,TextStream &t) { if (dl) { for(const auto subdir : *dl) { t << " getOutputFileBase() << "\">" << convertToXML(subdir->displayName()) << "\n"; } } } static void writeIncludeInfo(const IncludeInfo *ii,TextStream &t) { if (ii) { QCString nm = ii->includeName; if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName(); if (!nm.isEmpty()) { t << " fileDef && !ii->fileDef->isReference()) // TODO: support external references { t << " refid=\"" << ii->fileDef->getOutputFileBase() << "\""; } t << " local=\"" << (ii->local ? "yes" : "no") << "\">"; t << nm; t << "\n"; } } } static void generateXMLForClass(const ClassDef *cd,TextStream &ti) { // + brief description // + detailed description // + template argument list(s) // - include file // + member groups // + inheritance diagram // + list of direct super classes // + list of direct sub classes // + list of inner classes // + collaboration diagram // + list of all members // + user defined member sections // + standard member sections // + detailed member documentation // - examples using the class if (cd->isReference()) return; // skip external references. if (cd->isHidden()) return; // skip hidden classes. if (cd->isAnonymous()) return; // skip anonymous compounds. if (cd->templateMaster()!=0) return; // skip generated template instances. if (cd->isArtificial()) return; // skip artificially created classes msg("Generating XML output for class %s\n",qPrint(cd->name())); ti << " compoundTypeString() << "\">" << convertToXML(cd->name()) << "\n"; QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+ classOutputFileBase(cd)+".xml"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } TextStream t(&f); writeXMLHeader(t); t << " compoundTypeString() << "\" language=\"" << langToString(cd->getLanguage()) << "\" prot=\""; switch (cd->protection()) { case Public: t << "public"; break; case Protected: t << "protected"; break; case Private: t << "private"; break; case Package: t << "package"; break; } if (cd->isFinal()) t << "\" final=\"yes"; if (cd->isSealed()) t << "\" sealed=\"yes"; if (cd->isAbstract()) t << "\" abstract=\"yes"; t << "\">\n"; t << " "; writeXMLString(t,cd->name()); t << "\n"; for (const auto &bcd : cd->baseClasses()) { t << " isLinkable()) { t << "refid=\"" << classOutputFileBase(bcd.classDef) << "\" "; } t << "prot=\""; switch (bcd.prot) { case Public: t << "public"; break; case Protected: t << "protected"; break; case Private: t << "private"; break; case Package: ASSERT(0); break; } t << "\" virt=\""; switch(bcd.virt) { case Normal: t << "non-virtual"; break; case Virtual: t << "virtual"; break; case Pure: t <<"pure-virtual"; break; } t << "\">"; if (!bcd.templSpecifiers.isEmpty()) { t << convertToXML( insertTemplateSpecifierInScope( bcd.classDef->name(),bcd.templSpecifiers) ); } else { t << convertToXML(bcd.classDef->displayName()); } t << "\n"; } for (const auto &bcd : cd->subClasses()) { t << " " << convertToXML(bcd.classDef->displayName()) << "\n"; } writeIncludeInfo(cd->includeInfo(),t); writeInnerClasses(cd->getClasses(),t); writeTemplateList(cd,t); for (const auto &mg : cd->getMemberGroups()) { generateXMLSection(cd,ti,t,&mg->members(),"user-defined",mg->header(), mg->documentation()); } for (const auto &ml : cd->getMemberLists()) { if ((ml->listType()&MemberListType_detailedLists)==0) { generateXMLSection(cd,ti,t,ml.get(),xmlSectionMapper(ml->listType())); } } if (!cd->requiresClause().isEmpty()) { t << " "; linkifyText(TextGeneratorXMLImpl(t),cd,cd->getFileDef(),0,cd->requiresClause()); t << " \n"; } t << " \n"; writeXMLDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation()); t << " \n"; DotClassGraph inheritanceGraph(cd,Inheritance); if (!inheritanceGraph.isTrivial()) { t << " \n"; inheritanceGraph.writeXML(t); t << " \n"; } DotClassGraph collaborationGraph(cd,Collaboration); if (!collaborationGraph.isTrivial()) { t << " \n"; collaborationGraph.writeXML(t); t << " \n"; } t << " getDefFileName())) << "\" line=\"" << cd->getDefLine() << "\"" << " column=\"" << cd->getDefColumn() << "\"" ; if (cd->getStartBodyLine()!=-1) { const FileDef *bodyDef = cd->getBodyDef(); if (bodyDef) { t << " bodyfile=\"" << convertToXML(stripFromPath(bodyDef->absFilePath())) << "\""; } t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" << cd->getEndBodyLine() << "\""; } t << "/>\n"; writeListOfAllMembers(cd,t); t << " \n"; t << "
\n"; ti << " \n"; } static void generateXMLForConcept(const ConceptDef *cd,TextStream &ti) { if (cd->isReference() || cd->isHidden()) return; // skip external references. ti << " getOutputFileBase() << "\" kind=\"concept\"" << ">" << convertToXML(cd->name()) << "\n"; QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+cd->getOutputFileBase()+".xml"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } TextStream t(&f); writeXMLHeader(t); t << " getOutputFileBase() << "\" kind=\"concept\">\n"; t << " "; writeXMLString(t,cd->name()); t << "\n"; writeIncludeInfo(cd->includeInfo(),t); writeTemplateList(cd,t); t << " "; linkifyText(TextGeneratorXMLImpl(t),cd,cd->getFileDef(),0,cd->initializer()); t << " \n"; t << " \n"; writeXMLDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation()); t << " \n"; t << " getDefFileName())) << "\" line=\"" << cd->getDefLine() << "\"" << " column=\"" << cd->getDefColumn() << "\"/>\n" ; t << " \n"; t << "\n"; ti << " \n"; } static void generateXMLForNamespace(const NamespaceDef *nd,TextStream &ti) { // + contained class definitions // + contained namespace definitions // + member groups // + normal members // + brief desc // + detailed desc // + location // - files containing (parts of) the namespace definition if (nd->isReference() || nd->isHidden()) return; // skip external references ti << " getOutputFileBase() << "\" kind=\"namespace\"" << ">" << convertToXML(nd->name()) << "\n"; QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+nd->getOutputFileBase()+".xml"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } TextStream t(&f); writeXMLHeader(t); t << " getOutputFileBase() << "\" kind=\"namespace\" " << (nd->isInline()?"inline=\"yes\" ":"") << "language=\"" << langToString(nd->getLanguage()) << "\">\n"; t << " "; writeXMLString(t,nd->name()); t << "\n"; writeInnerClasses(nd->getClasses(),t); writeInnerNamespaces(nd->getNamespaces(),t); for (const auto &mg : nd->getMemberGroups()) { generateXMLSection(nd,ti,t,&mg->members(),"user-defined",mg->header(), mg->documentation()); } for (const auto &ml : nd->getMemberLists()) { if ((ml->listType()&MemberListType_declarationLists)!=0) { generateXMLSection(nd,ti,t,ml.get(),xmlSectionMapper(ml->listType())); } } t << " \n"; writeXMLDocBlock(t,nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation()); t << " \n"; t << " getDefFileName())) << "\" line=\"" << nd->getDefLine() << "\"" << " column=\"" << nd->getDefColumn() << "\"/>\n" ; t << " \n"; t << "\n"; ti << " \n"; } static void generateXMLForFile(FileDef *fd,TextStream &ti) { // + includes files // + includedby files // + include graph // + included by graph // + contained class definitions // + contained namespace definitions // + member groups // + normal members // + brief desc // + detailed desc // + source code // + location // - number of lines if (fd->isReference()) return; // skip external references ti << " getOutputFileBase() << "\" kind=\"file\">" << convertToXML(fd->name()) << "\n"; QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+fd->getOutputFileBase()+".xml"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } TextStream t(&f); writeXMLHeader(t); t << " getOutputFileBase() << "\" kind=\"file\" language=\"" << langToString(fd->getLanguage()) << "\">\n"; t << " "; writeXMLString(t,fd->name()); t << "\n"; for (const auto &inc : fd->includeFileList()) { t << " isReference()) // TODO: support external references { t << " refid=\"" << inc.fileDef->getOutputFileBase() << "\""; } t << " local=\"" << (inc.local ? "yes" : "no") << "\">"; t << inc.includeName; t << "\n"; } for (const auto &inc : fd->includedByFileList()) { t << " isReference()) // TODO: support external references { t << " refid=\"" << inc.fileDef->getOutputFileBase() << "\""; } t << " local=\"" << (inc.local ? "yes" : "no") << "\">"; t << inc.includeName; t << "\n"; } DotInclDepGraph incDepGraph(fd,FALSE); if (!incDepGraph.isTrivial()) { t << " \n"; incDepGraph.writeXML(t); t << " \n"; } DotInclDepGraph invIncDepGraph(fd,TRUE); if (!invIncDepGraph.isTrivial()) { t << " \n"; invIncDepGraph.writeXML(t); t << " \n"; } writeInnerClasses(fd->getClasses(),t); writeInnerNamespaces(fd->getNamespaces(),t); for (const auto &mg : fd->getMemberGroups()) { generateXMLSection(fd,ti,t,&mg->members(),"user-defined",mg->header(), mg->documentation()); } for (const auto &ml : fd->getMemberLists()) { if ((ml->listType()&MemberListType_declarationLists)!=0) { generateXMLSection(fd,ti,t,ml.get(),xmlSectionMapper(ml->listType())); } } t << " \n"; writeXMLDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,fd->docFile(),fd->docLine(),fd,0,fd->documentation()); t << " \n"; if (Config_getBool(XML_PROGRAMLISTING)) { writeXMLCodeBlock(t,fd); } t << " getDefFileName())) << "\"/>\n"; t << " \n"; t << "\n"; ti << " \n"; } static void generateXMLForGroup(const GroupDef *gd,TextStream &ti) { // + members // + member groups // + files // + classes // + namespaces // - packages // + pages // + child groups // - examples // + brief description // + detailed description if (gd->isReference()) return; // skip external references ti << " getOutputFileBase() << "\" kind=\"group\">" << convertToXML(gd->name()) << "\n"; QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+gd->getOutputFileBase()+".xml"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } TextStream t(&f); writeXMLHeader(t); t << " getOutputFileBase() << "\" kind=\"group\">\n"; t << " " << convertToXML(gd->name()) << "\n"; t << " " << convertToXML(gd->groupTitle()) << "\n"; writeInnerFiles(gd->getFiles(),t); writeInnerClasses(gd->getClasses(),t); writeInnerNamespaces(gd->getNamespaces(),t); writeInnerPages(gd->getPages(),t); writeInnerGroups(gd->getSubGroups(),t); for (const auto &mg : gd->getMemberGroups()) { generateXMLSection(gd,ti,t,&mg->members(),"user-defined",mg->header(), mg->documentation()); } for (const auto &ml : gd->getMemberLists()) { if ((ml->listType()&MemberListType_declarationLists)!=0) { generateXMLSection(gd,ti,t,ml.get(),xmlSectionMapper(ml->listType())); } } t << " \n"; writeXMLDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation()); t << " \n"; t << " \n"; t << "\n"; ti << " \n"; } static void generateXMLForDir(DirDef *dd,TextStream &ti) { if (dd->isReference()) return; // skip external references ti << " getOutputFileBase() << "\" kind=\"dir\">" << convertToXML(dd->displayName()) << "\n"; QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+dd->getOutputFileBase()+".xml"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } TextStream t(&f); writeXMLHeader(t); t << " getOutputFileBase() << "\" kind=\"dir\">\n"; t << " " << convertToXML(dd->displayName()) << "\n"; writeInnerDirs(&dd->subDirs(),t); writeInnerFiles(dd->getFiles(),t); t << " \n"; writeXMLDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription()); t << " \n"; t << " \n"; writeXMLDocBlock(t,dd->docFile(),dd->docLine(),dd,0,dd->documentation()); t << " \n"; t << " name())) << "\"/>\n"; t << " \n"; t << "\n"; ti << " \n"; } static void generateXMLForPage(PageDef *pd,TextStream &ti,bool isExample) { // + name // + title // + documentation // + location const char *kindName = isExample ? "example" : "page"; if (pd->isReference()) return; QCString pageName = pd->getOutputFileBase(); if (pd->getGroupDef()) { pageName+=QCString("_")+pd->name(); } if (pageName=="index") pageName="indexpage"; // to prevent overwriting the generated index page. ti << " " << convertToXML(pd->name()) << "\n"; QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+pageName+".xml"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } TextStream t(&f); writeXMLHeader(t); t << " \n"; t << " " << convertToXML(pd->name()) << "\n"; if (pd==Doxygen::mainPage.get()) // main page is special { QCString title; if (mainPageHasTitle()) { title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title())); } else { title = Config_getString(PROJECT_NAME); } t << " " << convertToXML(convertCharEntitiesToUTF8(title)) << "\n"; } else { const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) { t << " " << convertToXML(filterTitle(convertCharEntitiesToUTF8(si->title()))) << "\n"; } } writeInnerPages(pd->getSubPages(),t); const SectionRefs §ionRefs = pd->getSectionRefs(); if (pd->localToc().isXmlEnabled() && !sectionRefs.empty()) { t << " \n"; int level=1,l; bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; int maxLevel = pd->localToc().xmlLevel(); for (const SectionInfo *si : sectionRefs) { if (isSection(si->type())) { //printf(" level=%d title=%s\n",level,qPrint(si->title)); int nextLevel = static_cast(si->type()); if (nextLevel>level) { for (l=level;l\n"; } } else if (nextLevelnextLevel;l--) { if (l <= maxLevel && inLi[l]) t << " \n"; inLi[l]=FALSE; if (l <= maxLevel) t << " \n"; } } if (nextLevel <= maxLevel) { if (inLi[nextLevel]) t << " \n"; QCString titleDoc = convertToXML(si->title()); t << " \n"; t << " " << (si->title().isEmpty()?si->label():titleDoc) << "\n"; t << " " << convertToXML(pageName) << "_1" << convertToXML(si->label()) << "\n"; inLi[nextLevel]=TRUE; level = nextLevel; } } } while (level>1 && level <= maxLevel) { if (inLi[level]) t << " \n"; inLi[level]=FALSE; t << " \n"; level--; } if (level <= maxLevel && inLi[level]) t << " \n"; inLi[level]=FALSE; t << " \n"; } t << " \n"; writeXMLDocBlock(t,pd->briefFile(),pd->briefLine(),pd,0,pd->briefDescription()); t << " \n"; t << " \n"; if (isExample) { writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0, pd->documentation()+"\n\\include "+pd->name()); } else { writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0, pd->documentation()); } t << " \n"; t << " getDefFileName())) << "\"/>\n"; t << " \n"; t << "\n"; ti << " \n"; } void generateXML() { // + classes // + concepts // + namespaces // + files // + groups // + related pages // - examples QCString outputDirectory = Config_getString(XML_OUTPUT); Dir xmlDir(outputDirectory.str()); createSubDirs(xmlDir); ResourceMgr::instance().copyResource("xml.xsd",outputDirectory); ResourceMgr::instance().copyResource("index.xsd",outputDirectory); ResourceMgr::instance().copyResource("doxyfile.xsd",outputDirectory); QCString fileName=outputDirectory+"/compound.xsd"; std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } { TextStream t(&f); // write compound.xsd, but replace special marker with the entities QCString compound_xsd = ResourceMgr::instance().getAsString("compound.xsd"); const char *startLine = compound_xsd.data(); while (*startLine) { // find end of the line const char *endLine = startLine+1; while (*endLine && *(endLine-1)!='\n') endLine++; // skip to end of the line including \n int len=static_cast(endLine-startLine); if (len>0) { QCString s(startLine,len); if (s.find("")!=-1) { HtmlEntityMapper::instance()->writeXMLSchema(t); } else { t.write(startLine,len); } } startLine=endLine; } } f.close(); fileName=outputDirectory+"/Doxyfile.xml"; f.open(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing\n",fileName.data()); return; } else { TextStream t(&f); Config::writeXMLDoxyfile(t); } f.close(); fileName=outputDirectory+"/index.xml"; f.open(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!f.is_open()) { err("Cannot open file %s for writing!\n",qPrint(fileName)); return; } else { TextStream t(&f); // write index header t << "\n";; t << "trISOLang() << "\""; t << ">\n"; for (const auto &cd : *Doxygen::classLinkedMap) { generateXMLForClass(cd.get(),t); } for (const auto &cd : *Doxygen::conceptLinkedMap) { msg("Generating XML output for concept %s\n",qPrint(cd->name())); generateXMLForConcept(cd.get(),t); } for (const auto &nd : *Doxygen::namespaceLinkedMap) { msg("Generating XML output for namespace %s\n",qPrint(nd->name())); generateXMLForNamespace(nd.get(),t); } for (const auto &fn : *Doxygen::inputNameLinkedMap) { for (const auto &fd : *fn) { msg("Generating XML output for file %s\n",qPrint(fd->name())); generateXMLForFile(fd.get(),t); } } for (const auto &gd : *Doxygen::groupLinkedMap) { msg("Generating XML output for group %s\n",qPrint(gd->name())); generateXMLForGroup(gd.get(),t); } for (const auto &pd : *Doxygen::pageLinkedMap) { msg("Generating XML output for page %s\n",qPrint(pd->name())); generateXMLForPage(pd.get(),t,FALSE); } for (const auto &dd : *Doxygen::dirLinkedMap) { msg("Generate XML output for dir %s\n",qPrint(dd->name())); generateXMLForDir(dd.get(),t); } for (const auto &pd : *Doxygen::exampleLinkedMap) { msg("Generating XML output for example %s\n",qPrint(pd->name())); generateXMLForPage(pd.get(),t,TRUE); } if (Doxygen::mainPage) { msg("Generating XML output for the main page\n"); generateXMLForPage(Doxygen::mainPage.get(),t,FALSE); } //t << " \n"; t << "\n"; } writeCombineScript(); clearSubDirs(xmlDir); }