Blame addon/doxyparse/doxyparse.cpp

Packit 1c1d7e
/******************************************************************************
Packit 1c1d7e
 *
Packit 1c1d7e
 * Copyright (C) 2009-2015 by Joenio Costa.
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 Code parse based on doxyapp by Dimitri van Heesch
Packit 1c1d7e
 *
Packit 1c1d7e
 */
Packit 1c1d7e
Packit 1c1d7e
#include <stdlib.h>
Packit 1c1d7e
#include <unistd.h>
Packit 1c1d7e
#include "doxygen.h"
Packit 1c1d7e
#include "outputgen.h"
Packit 1c1d7e
#include "parserintf.h"
Packit 1c1d7e
#include "classlist.h"
Packit 1c1d7e
#include "config.h"
Packit 1c1d7e
#include "filedef.h"
Packit 1c1d7e
#include "util.h"
Packit 1c1d7e
#include "filename.h"
Packit 1c1d7e
#include "arguments.h"
Packit 1c1d7e
#include "memberlist.h"
Packit 1c1d7e
#include "types.h"
Packit 1c1d7e
#include <string>
Packit 1c1d7e
#include <cstdlib>
Packit 1c1d7e
#include <sstream>
Packit 1c1d7e
#include <map>
Packit 1c1d7e
Packit 1c1d7e
class Doxyparse : public CodeOutputInterface
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    Doxyparse(FileDef *fd) : m_fd(fd) {}
Packit 1c1d7e
   ~Doxyparse() {}
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 startCodeLine() {}
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 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 setCurrentDoc(Definition *,const char *,bool) {}
Packit 1c1d7e
    void addWord(const char *,bool) {}
Packit 1c1d7e
Packit 1c1d7e
    void linkableSymbol(int l, const char *sym, Definition *symDef, Definition *context)
Packit 1c1d7e
    {
Packit 1c1d7e
      if (!symDef) {
Packit 1c1d7e
        // in this case we have a local or external symbol
Packit 1c1d7e
Packit 1c1d7e
        // TODO record use of external symbols
Packit 1c1d7e
        // TODO must have a way to differentiate external symbols from local variables
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
  private:
Packit 1c1d7e
    FileDef *m_fd;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
static bool is_c_code = true;
Packit 1c1d7e
static std::map<std::string, bool> modules;
Packit 1c1d7e
static std::string current_module;
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
  Doxyparse *parse = new Doxyparse(fd);
Packit 1c1d7e
Packit 1c1d7e
  // parse the source code
Packit 1c1d7e
  pIntf->parseCode(*parse, 0, fileToString(fd->absFilePath()), lang, FALSE, 0, fd);
Packit 1c1d7e
Packit 1c1d7e
  // dismiss the object.
Packit 1c1d7e
  delete parse;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static bool ignoreStaticExternalCall(MemberDef *context, MemberDef *md) {
Packit 1c1d7e
  if (md->isStatic()) {
Packit 1c1d7e
    if(md->getFileDef()) {
Packit 1c1d7e
      if(md->getFileDef()->getOutputFileBase() == context->getFileDef()->getOutputFileBase())
Packit 1c1d7e
        // TODO ignore prefix of file
Packit 1c1d7e
        return false;
Packit 1c1d7e
      else
Packit 1c1d7e
        return true;
Packit 1c1d7e
    }
Packit 1c1d7e
    else {
Packit 1c1d7e
      return false;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  else {
Packit 1c1d7e
    return false;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void printFile(std::string file) {
Packit 1c1d7e
  printf("%s:\n", file.c_str());
Packit 1c1d7e
}
Packit 1c1d7e
static void printModule(std::string module) {
Packit 1c1d7e
  current_module = module;
Packit 1c1d7e
  printf("  %s:\n", module.c_str());
Packit 1c1d7e
}
Packit 1c1d7e
static void printClassInformation(std::string information) {
Packit 1c1d7e
  printf("    information: %s\n", information.c_str());
Packit 1c1d7e
}
Packit 1c1d7e
static void printInheritance(std::string base_class) {
Packit 1c1d7e
  printf("    inherits: %s\n", base_class.c_str());
Packit 1c1d7e
}
Packit 1c1d7e
static void printDefines() {
Packit 1c1d7e
  if (! modules[current_module]) {
Packit 1c1d7e
    printf("    defines:\n");
Packit 1c1d7e
  }
Packit 1c1d7e
  modules[current_module] = true;
Packit 1c1d7e
}
Packit 1c1d7e
static void printDefinition(std::string type, std::string signature, int line) {
Packit 1c1d7e
  printf("      - %s:\n", signature.c_str());
Packit 1c1d7e
  printf("          type: %s\n", type.c_str());
Packit 1c1d7e
  printf("          line: %d\n", line);
Packit 1c1d7e
}
Packit 1c1d7e
static void printProtection(std::string protection) {
Packit 1c1d7e
  printf("          protection: %s\n", protection.c_str());
Packit 1c1d7e
}
Packit 1c1d7e
static void printNumberOfLines(int lines) {
Packit 1c1d7e
  printf("          lines_of_code: %d\n", lines);
Packit 1c1d7e
}
Packit 1c1d7e
static void printNumberOfArguments(int arguments) {
Packit 1c1d7e
  printf("          parameters: %d\n", arguments);
Packit 1c1d7e
}
Packit 1c1d7e
static void printUses() {
Packit 1c1d7e
  printf("          uses:\n");
Packit 1c1d7e
}
Packit 1c1d7e
static void printReferenceTo(std::string type, std::string signature, std::string defined_in) {
Packit 1c1d7e
  printf("            - %s:\n", signature.c_str());
Packit 1c1d7e
  printf("                type: %s\n", type.c_str());
Packit 1c1d7e
  printf("                defined_in: %s\n", defined_in.c_str());
Packit 1c1d7e
}
Packit 1c1d7e
static void printNumberOfConditionalPaths(MemberDef* md) {
Packit 1c1d7e
  printf("          conditional_paths: %d\n", md->numberOfFlowKeyWords());
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static int isPartOfCStruct(MemberDef * md) {
Packit 1c1d7e
  return is_c_code && md->getClassDef() != NULL;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
std::string functionSignature(MemberDef* md) {
Packit 1c1d7e
  std::string signature = md->name().data();
Packit 1c1d7e
  if(md->isFunction()){
Packit 1c1d7e
    ArgumentList *argList = md->argumentList();
Packit 1c1d7e
    ArgumentListIterator iterator(*argList);
Packit 1c1d7e
    signature += "(";
Packit 1c1d7e
    Argument * argument = iterator.toFirst();
Packit 1c1d7e
    if(argument != NULL) {
Packit 1c1d7e
      signature += argument->type.data();
Packit 1c1d7e
      for(++iterator; (argument = iterator.current()) ;++iterator){
Packit 1c1d7e
        signature += std::string(",") + argument->type.data();
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    signature += ")";
Packit 1c1d7e
  }
Packit 1c1d7e
  return signature;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void referenceTo(MemberDef* md) {
Packit 1c1d7e
  std::string type = md->memberTypeName().data();
Packit 1c1d7e
  std::string defined_in = "";
Packit 1c1d7e
  std::string signature = "";
Packit 1c1d7e
  if (isPartOfCStruct(md)) {
Packit 1c1d7e
    signature = md->getClassDef()->name().data() + std::string("::") + functionSignature(md);
Packit 1c1d7e
    defined_in = md->getClassDef()->getFileDef()->getOutputFileBase().data();
Packit 1c1d7e
  }
Packit 1c1d7e
  else {
Packit 1c1d7e
    signature = functionSignature(md);
Packit 1c1d7e
    if (md->getClassDef()) {
Packit 1c1d7e
      defined_in = md->getClassDef()->name().data();
Packit 1c1d7e
    }
Packit 1c1d7e
    else if (md->getFileDef()) {
Packit 1c1d7e
      defined_in = md->getFileDef()->getOutputFileBase().data();
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  printReferenceTo(type, signature, defined_in);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void cModule(ClassDef* cd) {
Packit 1c1d7e
  MemberList* ml = cd->getMemberList(MemberListType_variableMembers);
Packit 1c1d7e
  if (ml) {
Packit 1c1d7e
    MemberListIterator mli(*ml);
Packit 1c1d7e
    MemberDef* md;
Packit 1c1d7e
    for (mli.toFirst(); (md=mli.current()); ++mli) {
Packit 1c1d7e
      printDefinition("variable", cd->name().data() + std::string("::") + md->name().data(), md->getDefLine());
Packit 1c1d7e
      if (md->protection() == Public) {
Packit 1c1d7e
        printProtection("public");
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void functionInformation(MemberDef* md) {
Packit 1c1d7e
  int size = md->getEndBodyLine() - md->getStartBodyLine() + 1;
Packit 1c1d7e
  printNumberOfLines(size);
Packit 1c1d7e
  ArgumentList *argList = md->argumentList();
Packit 1c1d7e
  printNumberOfArguments(argList->count());
Packit 1c1d7e
  printNumberOfConditionalPaths(md);
Packit 1c1d7e
  MemberSDict *defDict = md->getReferencesMembers();
Packit 1c1d7e
  if (defDict) {
Packit 1c1d7e
    MemberSDict::Iterator msdi(*defDict);
Packit 1c1d7e
    MemberDef *rmd;
Packit 1c1d7e
    printUses();
Packit 1c1d7e
    for (msdi.toFirst(); (rmd=msdi.current()); ++msdi) {
Packit 1c1d7e
      if (rmd->definitionType() == Definition::TypeMember && !ignoreStaticExternalCall(md, rmd)) {
Packit 1c1d7e
        referenceTo(rmd);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void lookupSymbol(Definition *d) {
Packit 1c1d7e
  if (d->definitionType() == Definition::TypeMember) {
Packit 1c1d7e
    MemberDef *md = (MemberDef *)d;
Packit 1c1d7e
    std::string type = md->memberTypeName().data();
Packit 1c1d7e
    std::string signature = functionSignature(md);
Packit 1c1d7e
    printDefinition(type, signature, md->getDefLine());
Packit 1c1d7e
    if (md->protection() == Public) {
Packit 1c1d7e
      printProtection("protection public");
Packit 1c1d7e
    }
Packit 1c1d7e
    if (md->isFunction()) {
Packit 1c1d7e
      functionInformation(md);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void listMembers(MemberList *ml) {
Packit 1c1d7e
  if (ml) {
Packit 1c1d7e
    MemberListIterator mli(*ml);
Packit 1c1d7e
    MemberDef *md;
Packit 1c1d7e
    printDefines();
Packit 1c1d7e
    for (mli.toFirst(); (md=mli.current()); ++mli) {
Packit 1c1d7e
      lookupSymbol((Definition*) md);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void listAllMembers(ClassDef* cd) {
Packit 1c1d7e
  // methods
Packit 1c1d7e
  listMembers(cd->getMemberList(MemberListType_functionMembers));
Packit 1c1d7e
  // constructors
Packit 1c1d7e
  listMembers(cd->getMemberList(MemberListType_constructors));
Packit 1c1d7e
  // attributes
Packit 1c1d7e
  listMembers(cd->getMemberList(MemberListType_variableMembers));
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void classInformation(ClassDef* cd) {
Packit 1c1d7e
  if (is_c_code) {
Packit 1c1d7e
    cModule(cd);
Packit 1c1d7e
  } else {
Packit 1c1d7e
    printModule(cd->name().data());
Packit 1c1d7e
    BaseClassList* baseClasses = cd->baseClasses();
Packit 1c1d7e
    if (baseClasses) {
Packit 1c1d7e
      BaseClassListIterator bci(*baseClasses);
Packit 1c1d7e
      BaseClassDef* bcd;
Packit 1c1d7e
      for (bci.toFirst(); (bcd = bci.current()); ++bci) {
Packit 1c1d7e
        printInheritance(bcd->classDef->name().data());
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    if(cd->isAbstract()) {
Packit 1c1d7e
      printClassInformation("abstract class");
Packit 1c1d7e
    }
Packit 1c1d7e
    listAllMembers(cd);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static bool checkLanguage(std::string& filename, std::string extension) {
Packit 1c1d7e
  if (filename.find(extension, filename.size() - extension.size()) != std::string::npos) {
Packit 1c1d7e
    return true;
Packit 1c1d7e
  } else {
Packit 1c1d7e
    return false;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/* Detects the programming language of the project. Actually, we only care
Packit 1c1d7e
 * about whether it is a C project or not. */
Packit 1c1d7e
static void detectProgrammingLanguage(FileNameListIterator& fnli) {
Packit 1c1d7e
  FileName* fn;
Packit 1c1d7e
  for (fnli.toFirst(); (fn=fnli.current()); ++fnli) {
Packit 1c1d7e
    std::string filename = fn->fileName();
Packit 1c1d7e
    if (
Packit 1c1d7e
        checkLanguage(filename, ".cc") ||
Packit 1c1d7e
        checkLanguage(filename, ".cxx") ||
Packit 1c1d7e
        checkLanguage(filename, ".cpp") ||
Packit 1c1d7e
        checkLanguage(filename, ".java")
Packit 1c1d7e
       ) {
Packit 1c1d7e
      is_c_code = false;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void listSymbols() {
Packit 1c1d7e
  // iterate over the input files
Packit 1c1d7e
  FileNameListIterator fnli(*Doxygen::inputNameList);
Packit 1c1d7e
  FileName *fn;
Packit 1c1d7e
Packit 1c1d7e
  detectProgrammingLanguage(fnli);
Packit 1c1d7e
Packit 1c1d7e
  // for each file
Packit 1c1d7e
  for (fnli.toFirst(); (fn=fnli.current()); ++fnli) {
Packit 1c1d7e
    FileNameIterator fni(*fn);
Packit 1c1d7e
    FileDef *fd;
Packit 1c1d7e
    for (; (fd=fni.current()); ++fni) {
Packit 1c1d7e
      printFile(fd->absFilePath().data());
Packit 1c1d7e
      MemberList *ml = fd->getMemberList(MemberListType_allMembersList);
Packit 1c1d7e
      if (ml && ml->count() > 0) {
Packit 1c1d7e
        printModule(fd->getOutputFileBase().data());
Packit 1c1d7e
        listMembers(ml);
Packit 1c1d7e
      }
Packit 1c1d7e
Packit 1c1d7e
      ClassSDict *classes = fd->getClassSDict();
Packit 1c1d7e
      if (classes) {
Packit 1c1d7e
        ClassSDict::Iterator cli(*classes);
Packit 1c1d7e
        ClassDef *cd;
Packit 1c1d7e
        for (cli.toFirst(); (cd = cli.current()); ++cli) {
Packit 1c1d7e
          classInformation(cd);
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  // TODO print external symbols referenced
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
int main(int argc,char **argv) {
Packit 1c1d7e
  if (argc < 2) {
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
  // check and finalize the configuration
Packit 1c1d7e
  checkConfiguration();
Packit 1c1d7e
  adjustConfiguration();
Packit 1c1d7e
Packit 1c1d7e
  // setup the non-default configuration options
Packit 1c1d7e
Packit 1c1d7e
  // we need a place to put intermediate files
Packit 1c1d7e
  std::ostringstream tmpdir;
Packit 1c1d7e
  tmpdir << "/tmp/doxyparse-" << getpid();
Packit 1c1d7e
  Config_getString(OUTPUT_DIRECTORY)= tmpdir.str().c_str();
Packit 1c1d7e
  // enable HTML (fake) output to omit warning about missing output format
Packit 1c1d7e
  Config_getBool(GENERATE_HTML)=TRUE;
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
  // find functions call between modules
Packit 1c1d7e
  Config_getBool(CALL_GRAPH)=TRUE;
Packit 1c1d7e
  // loop recursive over input files
Packit 1c1d7e
  Config_getBool(RECURSIVE)=TRUE;
Packit 1c1d7e
  // set the input
Packit 1c1d7e
  Config_getList(INPUT).clear();
Packit 1c1d7e
  for (int i = 1; i < argc; i++) {
Packit 1c1d7e
    if (strcmp(argv[i], "-") == 0) {
Packit 1c1d7e
      char filename[1024];
Packit 1c1d7e
      while (1) {
Packit 1c1d7e
        scanf("%s[^\n]", filename);
Packit 1c1d7e
        if (feof(stdin)) {
Packit 1c1d7e
          break;
Packit 1c1d7e
        }
Packit 1c1d7e
        Config_getList(INPUT).append(filename);
Packit 1c1d7e
      }
Packit 1c1d7e
    } else {
Packit 1c1d7e
      Config_getList(INPUT).append(argv[i]);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  if (Config_getList(INPUT).isEmpty()) {
Packit 1c1d7e
    exit(0);
Packit 1c1d7e
  }
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
  // for each file with a certain name
Packit 1c1d7e
  for (fnli.toFirst();(fn=fnli.current());++fnli) {
Packit 1c1d7e
    FileNameIterator fni(*fn);
Packit 1c1d7e
    FileDef *fd;
Packit 1c1d7e
    // for each file definition
Packit 1c1d7e
    for (;(fd=fni.current());++fni) {
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()) unlink(Doxygen::objDBFileName);
Packit 1c1d7e
  if (!Doxygen::entryDBFileName.isEmpty()) unlink(Doxygen::entryDBFileName);
Packit 1c1d7e
  // clean up after us
Packit 1c1d7e
  rmdir(Config_getString(OUTPUT_DIRECTORY));
Packit 1c1d7e
Packit 1c1d7e
  listSymbols();
Packit 1c1d7e
Packit 1c1d7e
  std::string cleanup_command = "rm -rf ";
Packit 1c1d7e
  cleanup_command += tmpdir.str();
Packit 1c1d7e
  system(cleanup_command.c_str());
Packit 1c1d7e
Packit 1c1d7e
  exit(0);
Packit 1c1d7e
}