Blame addon/doxyapp/doxyapp.cpp

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