|
Packit |
1c1d7e |
/******************************************************************************
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Copyright (C) 1997-2015 by Dimitri van Heesch.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
1c1d7e |
* documentation under the terms of the GNU General Public License is hereby
|
|
Packit |
1c1d7e |
* granted. No representations are made about the suitability of this software
|
|
Packit |
1c1d7e |
* for any purpose. It is provided "as is" without express or implied warranty.
|
|
Packit |
1c1d7e |
* See the GNU General Public License for more details.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Documents produced by Doxygen are derivative works derived from the
|
|
Packit |
1c1d7e |
* input used in their production; they are not affected by this license.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/** @file
|
|
Packit |
1c1d7e |
* @brief Example of how to use doxygen as part of another GPL applications
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* This example shows how to configure and run doxygen programmatically from
|
|
Packit |
1c1d7e |
* within an application without generating the usual output.
|
|
Packit |
1c1d7e |
* The example should work on any Unix like OS (including Linux and Mac OS X).
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* This example shows how to use to code parser to get cross-references information
|
|
Packit |
1c1d7e |
* and it also shows how to look up symbols in a program parsed by doxygen and
|
|
Packit |
1c1d7e |
* show some information about them.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#include <stdlib.h>
|
|
Packit |
1c1d7e |
#include <qfile.h>
|
|
Packit |
1c1d7e |
#include <qdir.h>
|
|
Packit |
1c1d7e |
#include "doxygen.h"
|
|
Packit |
1c1d7e |
#include "outputgen.h"
|
|
Packit |
1c1d7e |
#include "parserintf.h"
|
|
Packit |
1c1d7e |
#include "classdef.h"
|
|
Packit |
1c1d7e |
#include "namespacedef.h"
|
|
Packit |
1c1d7e |
#include "filedef.h"
|
|
Packit |
1c1d7e |
#include "util.h"
|
|
Packit |
1c1d7e |
#include "classlist.h"
|
|
Packit |
1c1d7e |
#include "config.h"
|
|
Packit |
1c1d7e |
#include "filename.h"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
class XRefDummyCodeGenerator : public CodeOutputInterface
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
XRefDummyCodeGenerator(FileDef *fd) : m_fd(fd) {}
|
|
Packit |
1c1d7e |
~XRefDummyCodeGenerator() {}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// these are just null functions, they can be used to produce a syntax highlighted
|
|
Packit |
1c1d7e |
// and cross-linked version of the source code, but who needs that anyway ;-)
|
|
Packit |
1c1d7e |
void codify(const char *) {}
|
|
Packit |
1c1d7e |
void writeCodeLink(const char *,const char *,const char *,const char *,const char *) {}
|
|
Packit |
1c1d7e |
void writeLineNumber(const char *,const char *,const char *,int) {}
|
|
Packit |
1c1d7e |
virtual void writeTooltip(const char *,const DocLinkInfo &,
|
|
Packit |
1c1d7e |
const char *,const char *,const SourceLinkInfo &,
|
|
Packit |
1c1d7e |
const SourceLinkInfo &) {}
|
|
Packit |
1c1d7e |
void startCodeLine(bool) {}
|
|
Packit |
1c1d7e |
void endCodeLine() {}
|
|
Packit |
1c1d7e |
void startCodeAnchor(const char *) {}
|
|
Packit |
1c1d7e |
void endCodeAnchor() {}
|
|
Packit |
1c1d7e |
void startFontClass(const char *) {}
|
|
Packit |
1c1d7e |
void endFontClass() {}
|
|
Packit |
1c1d7e |
void writeCodeAnchor(const char *) {}
|
|
Packit |
1c1d7e |
void setCurrentDoc(Definition *,const char *,bool) {}
|
|
Packit |
1c1d7e |
void addWord(const char *,bool) {}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// here we are presented with the symbols found by the code parser
|
|
Packit |
1c1d7e |
void linkableSymbol(int l, const char *sym,Definition *symDef,Definition *context)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString ctx;
|
|
Packit |
1c1d7e |
if (context) // the context of the symbol is known
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (context->definitionType()==Definition::TypeMember) // it is inside a member
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
Definition *parentContext = context->getOuterScope();
|
|
Packit |
1c1d7e |
if (parentContext && parentContext->definitionType()==Definition::TypeClass)
|
|
Packit |
1c1d7e |
// it is inside a member of a class
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
ctx.sprintf("inside %s %s of %s %s",
|
|
Packit |
1c1d7e |
((MemberDef *)context)->memberTypeName().data(),
|
|
Packit |
1c1d7e |
context->name().data(),
|
|
Packit |
1c1d7e |
((ClassDef*)parentContext)->compoundTypeString().data(),
|
|
Packit |
1c1d7e |
parentContext->name().data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (parentContext==Doxygen::globalScope) // it is inside a global member
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
ctx.sprintf("inside %s %s",
|
|
Packit |
1c1d7e |
((MemberDef *)context)->memberTypeName().data(),
|
|
Packit |
1c1d7e |
context->name().data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (ctx.isEmpty()) // it is something else (class, or namespace member, ...)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
ctx.sprintf("in %s",context->name().data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
printf("Found symbol %s at line %d of %s %s\n",
|
|
Packit |
1c1d7e |
sym,l,m_fd->getDefFileName().data(),ctx.data());
|
|
Packit |
1c1d7e |
if (symDef && context) // in this case the definition of the symbol is
|
|
Packit |
1c1d7e |
// known to doxygen.
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
printf("-> defined at line %d of %s\n",
|
|
Packit |
1c1d7e |
symDef->getDefLine(),symDef->getDefFileName().data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
private:
|
|
Packit |
1c1d7e |
FileDef *m_fd;
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void findXRefSymbols(FileDef *fd)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// get the interface to a parser that matches the file extension
|
|
Packit |
1c1d7e |
ParserInterface *pIntf=Doxygen::parserManager->getParser(fd->getDefFileExtension());
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// get the programming language from the file name
|
|
Packit |
1c1d7e |
SrcLangExt lang = getLanguageFromFileName(fd->name());
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// reset the parsers state
|
|
Packit |
1c1d7e |
pIntf->resetCodeParserState();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// create a new backend object
|
|
Packit |
1c1d7e |
XRefDummyCodeGenerator *xrefGen = new XRefDummyCodeGenerator(fd);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// parse the source code
|
|
Packit |
1c1d7e |
pIntf->parseCode(*xrefGen,
|
|
Packit |
1c1d7e |
0,
|
|
Packit |
1c1d7e |
fileToString(fd->absFilePath()),
|
|
Packit |
1c1d7e |
lang,
|
|
Packit |
1c1d7e |
FALSE,
|
|
Packit |
1c1d7e |
0,
|
|
Packit |
1c1d7e |
fd);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// dismiss the object.
|
|
Packit |
1c1d7e |
delete xrefGen;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void listSymbol(Definition *d)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (d!=Doxygen::globalScope && // skip the global namespace symbol
|
|
Packit |
1c1d7e |
d->name().at(0)!='@' // skip anonymous stuff
|
|
Packit |
1c1d7e |
)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
printf("%s\n",
|
|
Packit |
1c1d7e |
d->name().data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void listSymbols()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QDictIterator<DefinitionIntf> sli(*Doxygen::symbolMap);
|
|
Packit |
1c1d7e |
DefinitionIntf *di;
|
|
Packit |
1c1d7e |
for (sli.toFirst();(di=sli.current());++sli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (di->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols
|
|
Packit |
1c1d7e |
// with same name
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DefinitionListIterator dli(*(DefinitionList*)di);
|
|
Packit |
1c1d7e |
Definition *d;
|
|
Packit |
1c1d7e |
// for each symbol
|
|
Packit |
1c1d7e |
for (dli.toFirst();(d=dli.current());++dli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
listSymbol(d);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else // single symbol
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
listSymbol((Definition*)di);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void lookupSymbol(Definition *d)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (d!=Doxygen::globalScope && // skip the global namespace symbol
|
|
Packit |
1c1d7e |
d->name().at(0)!='@' // skip anonymous stuff
|
|
Packit |
1c1d7e |
)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
printf("Symbol info\n");
|
|
Packit |
1c1d7e |
printf("-----------\n");
|
|
Packit |
1c1d7e |
printf("Name: %s\n",d->name().data());
|
|
Packit |
1c1d7e |
printf("File: %s\n",d->getDefFileName().data());
|
|
Packit |
1c1d7e |
printf("Line: %d\n",d->getDefLine());
|
|
Packit |
1c1d7e |
// depending on the definition type we can case to the appropriate
|
|
Packit |
1c1d7e |
// derived to get additional information
|
|
Packit |
1c1d7e |
switch (d->definitionType())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
case Definition::TypeClass:
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
ClassDef *cd = (ClassDef *)d;
|
|
Packit |
1c1d7e |
printf("Kind: %s\n",cd->compoundTypeString().data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case Definition::TypeFile:
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
FileDef *fd = (FileDef *)d;
|
|
Packit |
1c1d7e |
printf("Kind: File: #includes %d other files\n",
|
|
Packit |
1c1d7e |
fd->includeFileList() ? fd->includeFileList()->count() : 0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case Definition::TypeNamespace:
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
NamespaceDef *nd = (NamespaceDef *)d;
|
|
Packit |
1c1d7e |
printf("Kind: Namespace: contains %d classes and %d namespaces\n",
|
|
Packit |
1c1d7e |
nd->getClassSDict() ? nd->getClassSDict()->count() : 0,
|
|
Packit |
1c1d7e |
nd->getNamespaceSDict() ? nd->getNamespaceSDict()->count() : 0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case Definition::TypeMember:
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
MemberDef *md = (MemberDef *)d;
|
|
Packit |
1c1d7e |
printf("Kind: %s\n",md->memberTypeName().data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
default:
|
|
Packit |
1c1d7e |
// ignore groups/pages/packages/dirs for now
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void lookupSymbols(const QCString &sym)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!sym.isEmpty())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DefinitionIntf *di = Doxygen::symbolMap->find(sym);
|
|
Packit |
1c1d7e |
if (di)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (di->definitionType()==DefinitionIntf::TypeSymbolList)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DefinitionListIterator dli(*(DefinitionList*)di);
|
|
Packit |
1c1d7e |
Definition *d;
|
|
Packit |
1c1d7e |
// for each symbol with the given name
|
|
Packit |
1c1d7e |
for (dli.toFirst();(d=dli.current());++dli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
lookupSymbol(d);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
lookupSymbol((Definition*)di);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
printf("Unknown symbol\n");
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
int main(int argc,char **argv)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
char cmd[256];
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (argc<2)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
printf("Usage: %s [source_file | source_dir]\n",argv[0]);
|
|
Packit |
1c1d7e |
exit(1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// initialize data structures
|
|
Packit |
1c1d7e |
initDoxygen();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// setup the non-default configuration options
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// we need a place to put intermediate files
|
|
Packit |
1c1d7e |
Config_getString(OUTPUT_DIRECTORY)="/tmp/doxygen";
|
|
Packit |
1c1d7e |
// disable html output
|
|
Packit |
1c1d7e |
Config_getBool(GENERATE_HTML)=FALSE;
|
|
Packit |
1c1d7e |
// disable latex output
|
|
Packit |
1c1d7e |
Config_getBool(GENERATE_LATEX)=FALSE;
|
|
Packit |
1c1d7e |
// be quiet
|
|
Packit |
1c1d7e |
Config_getBool(QUIET)=TRUE;
|
|
Packit |
1c1d7e |
// turn off warnings
|
|
Packit |
1c1d7e |
Config_getBool(WARNINGS)=FALSE;
|
|
Packit |
1c1d7e |
Config_getBool(WARN_IF_UNDOCUMENTED)=FALSE;
|
|
Packit |
1c1d7e |
Config_getBool(WARN_IF_DOC_ERROR)=FALSE;
|
|
Packit |
1c1d7e |
// Extract as much as possible
|
|
Packit |
1c1d7e |
Config_getBool(EXTRACT_ALL)=TRUE;
|
|
Packit |
1c1d7e |
Config_getBool(EXTRACT_STATIC)=TRUE;
|
|
Packit |
1c1d7e |
Config_getBool(EXTRACT_PRIVATE)=TRUE;
|
|
Packit |
1c1d7e |
Config_getBool(EXTRACT_LOCAL_METHODS)=TRUE;
|
|
Packit |
1c1d7e |
// Extract source browse information, needed
|
|
Packit |
1c1d7e |
// to make doxygen gather the cross reference info
|
|
Packit |
1c1d7e |
Config_getBool(SOURCE_BROWSER)=TRUE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// set the input
|
|
Packit |
1c1d7e |
Config_getList(INPUT).append(argv[1]);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// check and finialize the configuration
|
|
Packit |
1c1d7e |
checkConfiguration();
|
|
Packit |
1c1d7e |
adjustConfiguration();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// parse the files
|
|
Packit |
1c1d7e |
parseInput();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// iterate over the input files
|
|
Packit |
1c1d7e |
FileNameListIterator fnli(*Doxygen::inputNameList);
|
|
Packit |
1c1d7e |
FileName *fn;
|
|
Packit |
1c1d7e |
// foreach file with a certain name
|
|
Packit |
1c1d7e |
for (fnli.toFirst();(fn=fnli.current());++fnli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
FileNameIterator fni(*fn);
|
|
Packit |
1c1d7e |
FileDef *fd;
|
|
Packit |
1c1d7e |
// for each file definition
|
|
Packit |
1c1d7e |
for (;(fd=fni.current());++fni)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// get the references (linked and unlinked) found in this file
|
|
Packit |
1c1d7e |
findXRefSymbols(fd);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// remove temporary files
|
|
Packit |
1c1d7e |
if (!Doxygen::objDBFileName.isEmpty()) QFile::remove(Doxygen::objDBFileName);
|
|
Packit |
1c1d7e |
if (!Doxygen::entryDBFileName.isEmpty()) QFile::remove(Doxygen::entryDBFileName);
|
|
Packit |
1c1d7e |
// clean up after us
|
|
Packit |
1c1d7e |
QDir().rmdir("/tmp/doxygen");
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
while (1)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
printf("> Type a symbol name or\n> .list for a list of symbols or\n> .quit to exit\n> ");
|
|
Packit |
1c1d7e |
fgets(cmd,256,stdin);
|
|
Packit |
1c1d7e |
QCString s(cmd);
|
|
Packit |
1c1d7e |
if (s.at(s.length()-1)=='\n') s=s.left(s.length()-1); // strip trailing \n
|
|
Packit |
1c1d7e |
if (s==".list")
|
|
Packit |
1c1d7e |
listSymbols();
|
|
Packit |
1c1d7e |
else if (s==".quit")
|
|
Packit |
1c1d7e |
exit(0);
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
lookupSymbols(s);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|