static QCString getListOfBibFiles(const QCString &sep,bool stripExtension) { QCString result; QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); const char *bibdata = citeDataList.first(); while (bibdata) { int i; QCString bibFile = bibdata; if (stripExtension && bibFile.right(4)==".bib") { bibFile = bibFile.left(bibFile.length()-4); } if (stripExtension && (i=bibFile.findRev('/'))!=-1) { bibFile = bibFile.mid(i+1); } if (!bibFile.isEmpty()) { result+=bibFile; bibdata = citeDataList.next(); if (bibdata) { result+=sep; } } else { bibdata = citeDataList.next(); } } return result; }
void CiteDict::writeLatexBibliography(FTextStream &t) { if (m_entries.count()==0) return; QCString style = Config_getString("LATEX_BIB_STYLE"); if (style.isEmpty()) style="plain"; t << "\\newpage \\bibliographystyle{" << style << "}" << endl; t << "\\bibliography{"; QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); const char *bibdata = citeDataList.first(); while (bibdata) { QCString bibFile = bibdata; if (!bibFile.isEmpty()) { t << bibFile; bibdata = citeDataList.next(); if (bibdata) { t << ","; } } else { bibdata = citeDataList.next(); } } t << "}" << endl; }
void CiteDict::clean() { // clean QDir thisDir; QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); const char *bibdata = citeDataList.first(); while (bibdata) { QCString bibFile = bibdata; if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; if (!bibFile.isEmpty()) thisDir.remove(m_baseFileName+"_"+bibFile); bibdata = citeDataList.next(); } thisDir.remove(m_baseFileName + ".aux"); thisDir.remove(m_baseFileName + ".bbl"); thisDir.remove(m_baseFileName + ".blg"); thisDir.remove(m_baseFileName + ".tmp"); thisDir.remove(m_baseFileName + ".bst"); QCString &outputDirectory = Config_getString("OUTPUT_DIRECTORY"); if (outputDirectory.isEmpty()) { outputDirectory=QDir::currentDirPath(); } QDir d(outputDirectory); d.rmdir("bib"); }
//---------------------------------------------------------------------------- // some quasi intelligent brief description abbreviator :^) QCString abbreviate(const char *s,const char *name) { QCString scopelessName=name; int i=scopelessName.findRev("::"); if (i!=-1) scopelessName=scopelessName.mid(i+2); QCString result=s; result=result.stripWhiteSpace(); // strip trailing . if (!result.isEmpty() && result.at(result.length()-1)=='.') result=result.left(result.length()-1); // strip any predefined prefix QStrList &briefDescAbbrev = Config_getList("ABBREVIATE_BRIEF"); const char *p = briefDescAbbrev.first(); while (p) { QCString s = p; s.replace(QRegExp("\\$name"), scopelessName); // replace $name with entity name s += " "; stripWord(result,s); p = briefDescAbbrev.next(); } // capitalize first word if (!result.isEmpty()) { int c=result[0]; if (c>='a' && c<='z') c+='A'-'a'; result[0]=c; } return result; }
bool CiteDict::writeAux() { //msg("..writing aux file\n"); QCString auxFileName(m_baseFileName + ".aux"); QFile auxFile(auxFileName); if (!auxFile.open(IO_WriteOnly)) // point it to something valid, because warn() relies on it { err("Error opening file %s for output\n", auxFileName.data()); return FALSE; } FTextStream t(&auxFile); QDictIterator<CiteInfo> cdi(m_entries); for (CiteInfo *ci = 0; (ci=cdi.current()); ++cdi) { t << "\\citation{" << ci->label << "}\n"; } t << "\\bibstyle{" << m_baseFileName << "}\n"; t << "\\bibdata{"; QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); const char *bibdata = citeDataList.first(); while (bibdata) { QCString bibFile = bibdata; if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; if (!bibFile.isEmpty()) { QFileInfo fi(bibFile); if (fi.exists()) { if (!copyFile(bibFile,m_baseFileName+"_"+bibFile)) { return FALSE; } t << m_baseFileName+"_"+bibFile; bibdata = citeDataList.next(); if (bibdata) { t << ","; } } else { err("The file %s specified at CITE_BIB_FILES could not be read!\n",bibdata); return FALSE; } } else { bibdata = citeDataList.next(); } } t << "}\n"; return TRUE; }
static bool matchExcludedSymbols(const char *name) { static QStrList &exclSyms = Config_getList("EXCLUDE_SYMBOLS"); if (exclSyms.count()==0) return FALSE; // nothing specified const char *pat = exclSyms.first(); QCString symName = name; while (pat) { QCString pattern = pat; bool forceStart=FALSE; bool forceEnd=FALSE; if (pattern.at(0)=='^') pattern=pattern.mid(1),forceStart=TRUE; if (pattern.at(pattern.length()-1)=='$') pattern=pattern.left(pattern.length()-1),forceEnd=TRUE; if (pattern.find('*')!=-1) // wildcard mode { QRegExp re(substitute(pattern,"*",".*"),TRUE); int i,pl; i = re.match(symName,0,&pl); //printf(" %d = re.match(%s) pattern=%s\n",i,symName.data(),pattern.data()); if (i!=-1) // wildcard match { int sl=symName.length(); // check if it is a whole word match if ((i==0 || pattern.at(0)=='*' || (!isId(symName.at(i-1)) && !forceStart)) && (i+pl==sl || pattern.at(i+pl)=='*' || (!isId(symName.at(i+pl)) && !forceEnd)) ) { //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); return TRUE; } } } else if (!pattern.isEmpty()) // match words { int i = symName.find(pattern); if (i!=-1) // we have a match! { int pl=pattern.length(); int sl=symName.length(); // check if it is a whole word match if ((i==0 || (!isId(symName.at(i-1)) && !forceStart)) && (i+pl==sl || (!isId(symName.at(i+pl)) && !forceEnd)) ) { //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); return TRUE; } } } pat = exclSyms.next(); } //printf("--> name=%s: no match\n",name); return FALSE; }
void CiteDict::resolve() { QStrList &citeBibFiles = Config_getList("CITE_BIB_FILES"); if (citeBibFiles.count()==0 || m_entries.count()==0) return; // nothing to cite QCString &outputDirectory = Config_getString("OUTPUT_DIRECTORY"); if (outputDirectory.isEmpty()) { outputDirectory=QDir::currentDirPath(); } QDir d(outputDirectory); d.mkdir("bib"); uint pid = portable_pid(); m_baseFileName.sprintf("doxygen_bibtex_%d",pid); m_baseFileName.prepend(outputDirectory+"/bib/"); if (writeAux() && writeBst() && execute()) { parse(); clean(); } if (Config_getBool("GENERATE_LATEX")) { // copy bib files to the latex output dir QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); QCString latexOutputDir = Config_getString("LATEX_OUTPUT")+"/"; const char *bibdata = citeDataList.first(); while (bibdata) { QCString bibFile = bibdata; if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; if (!bibFile.isEmpty()) { copyFile(bibFile,latexOutputDir+bibFile); } bibdata = citeDataList.next(); } } }
/*! strip part of \a path if it matches * one of the paths in the Config_getList(STRIP_FROM_PATH) list */ DirDef *DirDef::mergeDirectoryInTree(const QCString &path) { //printf("DirDef::mergeDirectoryInTree(%s)\n",path.data()); int p=0,i=0; DirDef *dir=0; while ((i=path.find('/',p))!=-1) { QCString part=path.left(i+1); if (!matchPath(part,Config_getList(STRIP_FROM_PATH)) && (part!="/" && part!="//")) { dir=createNewDir(part); } p=i+1; } return dir; }
static QCString getListOfBibFiles(const QCString &sep,bool namesOnly) { QCString result; QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); const char *bibdata = citeDataList.first(); while (bibdata) { int i; QCString bibFile = bibdata; if (namesOnly && bibFile.right(4)==".bib") // strip extension { bibFile = bibFile.left(bibFile.length()-4); } else { if (!namesOnly && bibFile.right(4)!=".bib") bibFile += ".bib"; } if ((i=bibFile.findRev('/'))!=-1) // strip path { bibFile = bibFile.mid(i+1); } if (!bibFile.isEmpty()) { if (namesOnly) // bare names { result+=bibFile; } else // add quotes for paths with spaces { result+="\""+bibFile+"\""; } bibdata = citeDataList.next(); if (bibdata) { result+=sep; } } else { bibdata = citeDataList.next(); } } return result; }
QCString VerilogDocGen::findFile(const char *fileName) { QStrList &includePath = Config_getList("INCLUDE_PATH"); char *s=includePath.first(); while (s) { QCString absName; absName += (QCString)s+"/"+fileName; QFileInfo fin(absName); if( fin.exists() && fin.isFile()) return absName; s=includePath.next(); } return ""; }
/*! constructs command line of htags(1) and executes it. * \retval TRUE success * \retval FALSE an error has occurred. */ bool Htags::execute(const QCString &htmldir) { static QStrList &inputSource = Config_getList("INPUT"); static bool quiet = Config_getBool("QUIET"); static bool warnings = Config_getBool("WARNINGS"); static QCString htagsOptions = ""; //Config_getString("HTAGS_OPTIONS"); static QCString projectName = Config_getString("PROJECT_NAME"); static QCString projectNumber = Config_getString("PROJECT_NUMBER"); QCString cwd = QDir::currentDirPath().utf8(); if (inputSource.isEmpty()) { g_inputDir.setPath(cwd); } else if (inputSource.count()==1) { g_inputDir.setPath(inputSource.first()); if (!g_inputDir.exists()) err("Cannot find directory %s. " "Check the value of the INPUT tag in the configuration file.\n", inputSource.first() ); } else { err("If you use USE_HTAGS then INPUT should specific a single directory. \n"); return FALSE; } /* * Construct command line for htags(1). */ QCString commandLine = " -g -s -a -n "; if (!quiet) commandLine += "-v "; if (warnings) commandLine += "-w "; if (!htagsOptions.isEmpty()) { commandLine += ' '; commandLine += htagsOptions; } if (!projectName.isEmpty()) { commandLine += "-t \""; commandLine += projectName; if (!projectNumber.isEmpty()) { commandLine += '-'; commandLine += projectNumber; } commandLine += "\" "; } commandLine += " \"" + htmldir + "\""; QCString oldDir = QDir::currentDirPath().utf8(); QDir::setCurrent(g_inputDir.absPath()); //printf("CommandLine=[%s]\n",commandLine.data()); portable_sysTimerStart(); bool result=portable_system("htags",commandLine,FALSE)==0; portable_sysTimerStop(); QDir::setCurrent(oldDir); return result; }
void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format) { static QCString plantumlJarPath = Config_getString("PLANTUML_JAR_PATH"); QCString pumlExe = "java"; QCString pumlArgs = ""; QStrList &pumlIncludePathList = Config_getList("PLANTUML_INCLUDE_PATH"); char *s=pumlIncludePathList.first(); if (s) { pumlArgs += "-Dplantuml.include.path=\""; pumlArgs += s; s = pumlIncludePathList.next(); } while (s) { pumlArgs += portable_pathListSeparator(); pumlArgs += s; s = pumlIncludePathList.next(); } if (pumlIncludePathList.first()) pumlArgs += "\" "; pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" "; pumlArgs+="-o \""; pumlArgs+=outDir; pumlArgs+="\" "; QCString extension; switch (format) { case PUML_BITMAP: pumlArgs+="-tpng"; extension=".png"; break; case PUML_EPS: pumlArgs+="-teps"; extension=".eps"; break; case PUML_SVG: pumlArgs+="-tsvg"; extension=".svg"; break; } pumlArgs+=" \""; pumlArgs+=baseName; pumlArgs+=".pu\" "; pumlArgs+="-charset " + Config_getString("INPUT_ENCODING") + " "; int exitCode; //printf("*** running: %s %s outDir:%s %s\n",pumlExe.data(),pumlArgs.data(),outDir,outFile); msg("Running PlantUML on generated file %s.pu\n",baseName); portable_sysTimerStart(); if ((exitCode=portable_system(pumlExe,pumlArgs,FALSE))!=0) { err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n", plantumlJarPath.data(),exitCode); } else if (Config_getBool("DOT_CLEANUP")) { QFile(QCString(baseName)+".pu").remove(); } portable_sysTimerStop(); if ( (format==PUML_EPS) && (Config_getBool("USE_PDFLATEX")) ) { QCString epstopdfArgs(maxCmdLine); epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",baseName,baseName); portable_sysTimerStart(); if (exitCode=portable_system("epstopdf",epstopdfArgs)!=0) { err("Problems running epstopdf. Check your TeX installation! Exit code: %d\n",exitCode); } portable_sysTimerStop(); } }
void CiteDict::generatePage() const { //printf("** CiteDict::generatePage() count=%d\n",m_ordering.count()); // do not generate an empty citations page if (isEmpty()) return; // nothing to cite // 1. generate file with markers and citations to OUTPUT_DIRECTORY QFile f; QCString outputDir = Config_getString("OUTPUT_DIRECTORY"); QCString citeListFile = outputDir+"/citelist.doc"; f.setName(citeListFile); if (!f.open(IO_WriteOnly)) { err("could not open file %s for writing\n",citeListFile.data()); } FTextStream t(&f); t << "<!-- BEGIN CITATIONS -->" << endl; t << "<!--" << endl; QDictIterator<CiteInfo> it(m_entries); CiteInfo *ci; for (it.toFirst();(ci=it.current());++it) { t << "\\citation{" << ci->label << "}" << endl; } t << "-->" << endl; t << "<!-- END CITATIONS -->" << endl; t << "<!-- BEGIN BIBLIOGRAPHY -->" << endl; t << "<!-- END BIBLIOGRAPHY -->" << endl; f.close(); // 2. generate bib2xhtml QCString bib2xhtmlFile = outputDir+"/bib2xhtml.pl"; f.setName(bib2xhtmlFile); QCString bib2xhtml = bib2xhtml_pl; if (!f.open(IO_WriteOnly)) { err("could not open file %s for writing\n",bib2xhtmlFile.data()); } f.writeBlock(bib2xhtml, bib2xhtml.length()); f.close(); // 3. generate doxygen.bst QCString doxygenBstFile = outputDir+"/doxygen.bst"; QCString bstData = doxygen_bst; f.setName(doxygenBstFile); if (!f.open(IO_WriteOnly)) { err("could not open file %s for writing\n",doxygenBstFile.data()); } f.writeBlock(bstData, bstData.length()); f.close(); // 4. for html we just copy the bib files to the output so that // bibtex can find them without path (bibtex doesn't support path's // with spaces!) QList<QCString> tempFiles; tempFiles.setAutoDelete(TRUE); QDir thisDir; if (Config_getBool("GENERATE_HTML")) { // copy bib files to the latex output dir QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); QCString bibOutputDir = outputDir+"/"; QFileInfo fo(bibOutputDir); const char *bibdata = citeDataList.first(); while (bibdata) { QCString bibFile = bibdata; if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; QFileInfo fi(bibFile); if (fi.exists() && fi.dirPath(TRUE)!=fo.absFilePath()) { if (!bibFile.isEmpty()) { QCString destFile=bibOutputDir+fi.fileName().data(); copyFile(bibFile,destFile); tempFiles.append(new QCString(destFile)); } } else if (!fi.exists()) { err("bib file %s not found!\n",bibFile.data()); } bibdata = citeDataList.next(); } } QCString oldDir = QDir::currentDirPath().utf8(); QDir::setCurrent(outputDir); // 5. run bib2xhtml perl script on the generated file which will insert the // bibliography in citelist.doc portable_system("perl","\""+bib2xhtmlFile+"\" "+getListOfBibFiles(" ",FALSE)+" \""+ citeListFile+"\""); QDir::setCurrent(oldDir); // 6. read back the file f.setName(citeListFile); if (!f.open(IO_ReadOnly)) { err("could not open file %s/citelist.doc for reading\n",outputDir.data()); } bool insideBib=FALSE; QCString doc; QFileInfo fi(citeListFile); QCString input(fi.size()+1); f.readBlock(input.data(),fi.size()); f.close(); input.at(fi.size())='\0'; int p=0,s; //printf("input=[%s]\n",input.data()); while ((s=input.find('\n',p))!=-1) { QCString line = input.mid(p,s-p); //printf("p=%d s=%d line=[%s]\n",p,s,line.data()); p=s+1; if (line.find("<!-- BEGIN BIBLIOGRAPHY")!=-1) insideBib=TRUE; else if (line.find("<!-- END BIBLIOGRAPH")!=-1) insideBib=FALSE; else if (insideBib) doc+=line+"\n"; int i; // determine text to use at the location of the @cite command if (insideBib && (i=line.find("<a name=\"CITEREF_"))!=-1) { int j=line.find("\">["); int k=line.find("]</a>"); if (j!=-1 && k!=-1) { QCString label = line.mid(i+17,j-i-17); QCString number = line.mid(j+2,k-j-1); CiteInfo *ci = m_entries.find(label); //printf("label='%s' number='%s' => %p\n",label.data(),number.data(),ci); if (ci) { ci->text = number; } } } } //printf("doc=[%s]\n",doc.data()); // 7. add it as a page addRelatedPage(CiteConsts::fileName, theTranslator->trCiteReferences(),doc,0,CiteConsts::fileName,1,0,0,0); // 8. for latex we just copy the bib files to the output and let // latex do this work. if (Config_getBool("GENERATE_LATEX")) { // copy bib files to the latex output dir QStrList &citeDataList = Config_getList("CITE_BIB_FILES"); QCString latexOutputDir = Config_getString("LATEX_OUTPUT")+"/"; const char *bibdata = citeDataList.first(); while (bibdata) { QCString bibFile = bibdata; if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; QFileInfo fi(bibFile); if (fi.exists()) { if (!bibFile.isEmpty()) { copyFile(bibFile,latexOutputDir+fi.fileName().data()); } } else { err("bib file %s not found!\n",bibFile.data()); } bibdata = citeDataList.next(); } } // 9. Remove temporary files thisDir.remove(citeListFile); thisDir.remove(doxygenBstFile); thisDir.remove(bib2xhtmlFile); while (!tempFiles.isEmpty()) { QCString *s=tempFiles.take(0); thisDir.remove(*s); } }
bool CiteDict::isEmpty() const { QStrList &citeBibFiles = Config_getList("CITE_BIB_FILES"); return (citeBibFiles.count()==0 || m_entries.isEmpty()); }
void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit) { static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); static QStrList &includePath = Config_getList(INCLUDE_PATH); static QStrList clangOptions = Config_getList(CLANG_OPTIONS); static QCString clangCompileDatabase = Config_getList(CLANG_COMPILATION_DATABASE_PATH); if (!clangAssistedParsing) return; //printf("ClangParser::start(%s)\n",fileName); p->fileName = fileName; p->index = clang_createIndex(0, 0); p->curLine = 1; p->curToken = 0; QDictIterator<void> di(Doxygen::inputPaths); int argc=0; std::string error; // load a clang compilation database (https://clang.llvm.org/docs/JSONCompilationDatabase.html) // this only needs to be loaded once, and could be refactored to a higher level function static std::unique_ptr<clang::tooling::CompilationDatabase> db = clang::tooling::CompilationDatabase::loadFromDirectory(clangCompileDatabase.data(), error); int clang_option_len = 0; std::vector<clang::tooling::CompileCommand> command; if (strcmp(clangCompileDatabase, "0") != 0) { if (db == nullptr) { // user specified a path, but DB file was not found err("%s using clang compilation database path of: \"%s\"\n", error.c_str(), clangCompileDatabase.data()); } else { // check if the file we are parsing is in the DB command = db->getCompileCommands(fileName); if (!command.empty() ) { // it's possible to have multiple entries for the same file, so use the last entry clang_option_len = command[command.size()-1].CommandLine.size(); } } } char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()+clang_option_len)); if (!command.empty() ) { std::vector<std::string> options = command[command.size()-1].CommandLine; // copy each compiler option used from the database. Skip the first which is compiler exe. for (auto option = options.begin()+1; option != options.end(); option++) { argv[argc++] = strdup(option->c_str()); } // this extra addition to argv is accounted for as we are skipping the first entry in argv[argc++]=strdup("-w"); // finally, turn off warnings. } else { // add include paths for input files for (di.toFirst();di.current();++di,++argc) { QCString inc = QCString("-I")+di.currentKey(); argv[argc]=strdup(inc.data()); //printf("argv[%d]=%s\n",argc,argv[argc]); } // add external include paths for (uint i=0;i<includePath.count();i++) { QCString inc = QCString("-I")+includePath.at(i); argv[argc++]=strdup(inc.data()); } // user specified options for (uint i=0;i<clangOptions.count();i++) { argv[argc++]=strdup(clangOptions.at(i)); } // extra options argv[argc++]=strdup("-ferror-limit=0"); argv[argc++]=strdup("-x"); // Since we can be presented with a .h file that can contain C/C++ or // Objective C code and we need to configure the parser before knowing this, // we use the source file to detected the language. Detection will fail if you // pass a bunch of .h files containing ObjC code, and no sources :-( SrcLangExt lang = getLanguageFromFileName(fileName); if (lang==SrcLangExt_ObjC || p->detectedLang!=ClangParser::Private::Detected_Cpp) { QCString fn = fileName; if (p->detectedLang==ClangParser::Private::Detected_Cpp && (fn.right(4).lower()==".cpp" || fn.right(4).lower()==".cxx" || fn.right(3).lower()==".cc" || fn.right(2).lower()==".c")) { // fall back to C/C++ once we see an extension that indicates this p->detectedLang = ClangParser::Private::Detected_Cpp; } else if (fn.right(3).lower()==".mm") // switch to Objective C++ { p->detectedLang = ClangParser::Private::Detected_ObjCpp; } else if (fn.right(2).lower()==".m") // switch to Objective C { p->detectedLang = ClangParser::Private::Detected_ObjC; } } switch(p->detectedLang) { case ClangParser::Private::Detected_Cpp: argv[argc++]=strdup("c++"); break; case ClangParser::Private::Detected_ObjC: argv[argc++]=strdup("objective-c"); break; case ClangParser::Private::Detected_ObjCpp: argv[argc++]=strdup("objective-c++"); break; } // provide the input and and its dependencies as unsaved files so we can // pass the filtered versions argv[argc++]=strdup(fileName); } static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); //printf("source %s ----------\n%s\n-------------\n\n", // fileName,p->source.data()); uint numUnsavedFiles = filesInTranslationUnit.count()+1; p->numFiles = numUnsavedFiles; p->sources = new QCString[numUnsavedFiles]; p->ufs = new CXUnsavedFile[numUnsavedFiles]; p->sources[0] = detab(fileToString(fileName,filterSourceFiles,TRUE)); p->ufs[0].Filename = strdup(fileName); p->ufs[0].Contents = p->sources[0].data(); p->ufs[0].Length = p->sources[0].length(); QStrListIterator it(filesInTranslationUnit); uint i=1; for (it.toFirst();it.current() && i<numUnsavedFiles;++it,i++) { p->fileMapping.insert(it.current(),new uint(i)); p->sources[i] = detab(fileToString(it.current(),filterSourceFiles,TRUE)); p->ufs[i].Filename = strdup(it.current()); p->ufs[i].Contents = p->sources[i].data(); p->ufs[i].Length = p->sources[i].length(); } // let libclang do the actual parsing p->tu = clang_parseTranslationUnit(p->index, 0, argv, argc, p->ufs, numUnsavedFiles, CXTranslationUnit_DetailedPreprocessingRecord); // free arguments for (int i=0;i<argc;++i) { free(argv[i]); } free(argv); if (p->tu) { // filter out any includes not found by the clang parser determineInputFilesInSameTu(filesInTranslationUnit); // show any warnings that the compiler produced for (uint i=0, n=clang_getNumDiagnostics(p->tu); i!=n; ++i) { CXDiagnostic diag = clang_getDiagnostic(p->tu, i); CXString string = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions()); err("%s [clang]\n",clang_getCString(string)); clang_disposeString(string); clang_disposeDiagnostic(diag); } // create a source range for the given file QFileInfo fi(fileName); CXFile f = clang_getFile(p->tu, fileName); CXSourceLocation fileBegin = clang_getLocationForOffset(p->tu, f, 0); CXSourceLocation fileEnd = clang_getLocationForOffset(p->tu, f, p->ufs[0].Length); CXSourceRange fileRange = clang_getRange(fileBegin, fileEnd); // produce a token stream for the file clang_tokenize(p->tu,fileRange,&p->tokens,&p->numTokens); // produce cursors for each token in the stream p->cursors=new CXCursor[p->numTokens]; clang_annotateTokens(p->tu,p->tokens,p->numTokens,p->cursors); } else { p->tokens = 0; p->numTokens = 0; p->cursors = 0; err("clang: Failed to parse translation unit %s\n",fileName); } }
/** * evaluate a variable */ bool CondParser::evalVariable(const char *varName) { if (Config_getList("ENABLED_SECTIONS").find(varName)==-1) return FALSE; return TRUE; }
void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit) { static bool clangAssistedParsing = Config_getBool("CLANG_ASSISTED_PARSING"); static QStrList &includePath = Config_getList("INCLUDE_PATH"); static QStrList clangOptions = Config_getList("CLANG_OPTIONS"); if (!clangAssistedParsing) return; //printf("ClangParser::start(%s)\n",fileName); p->fileName = fileName; p->index = clang_createIndex(0, 0); p->curLine = 1; p->curToken = 0; char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count())); QDictIterator<void> di(Doxygen::inputPaths); int argc=0; // add include paths for input files for (di.toFirst();di.current();++di,++argc) { QCString inc = QCString("-I")+di.currentKey(); argv[argc]=strdup(inc.data()); //printf("argv[%d]=%s\n",argc,argv[argc]); } // add external include paths for (uint i=0;i<includePath.count();i++) { QCString inc = QCString("-I")+includePath.at(i); argv[argc++]=strdup(inc.data()); } // user specified options for (uint i=0;i<clangOptions.count();i++) { argv[argc++]=strdup(clangOptions.at(i)); } // extra options argv[argc++]=strdup("-ferror-limit=0"); argv[argc++]=strdup("-x"); // Since we can be presented with a .h file that can contain C/C++ or // Objective C code and we need to configure the parser before knowing this, // we use the source file to detected the language. Detection will fail if you // pass a bunch of .h files containing ObjC code, and no sources :-( SrcLangExt lang = getLanguageFromFileName(fileName); if (lang==SrcLangExt_ObjC || p->detectedLang!=ClangParser::Private::Detected_Cpp) { QCString fn = fileName; if (p->detectedLang==ClangParser::Private::Detected_Cpp && (fn.right(4).lower()==".cpp" || fn.right(4).lower()==".cxx" || fn.right(3).lower()==".cc" || fn.right(2).lower()==".c")) { // fall back to C/C++ once we see an extension that indicates this p->detectedLang = ClangParser::Private::Detected_Cpp; } else if (fn.right(3).lower()==".mm") // switch to Objective C++ { p->detectedLang = ClangParser::Private::Detected_ObjCpp; } else if (fn.right(2).lower()==".m") // switch to Objective C { p->detectedLang = ClangParser::Private::Detected_ObjC; } } switch(p->detectedLang) { case ClangParser::Private::Detected_Cpp: argv[argc++]=strdup("c++"); break; case ClangParser::Private::Detected_ObjC: argv[argc++]=strdup("objective-c"); break; case ClangParser::Private::Detected_ObjCpp: argv[argc++]=strdup("objective-c++"); break; } // provide the input and and its dependencies as unsaved files so we can // pass the filtered versions argv[argc++]=strdup(fileName); static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); //printf("source %s ----------\n%s\n-------------\n\n", // fileName,p->source.data()); uint numUnsavedFiles = filesInTranslationUnit.count()+1; p->numFiles = numUnsavedFiles; p->sources = new QCString[numUnsavedFiles]; p->ufs = new CXUnsavedFile[numUnsavedFiles]; p->sources[0] = detab(fileToString(fileName,filterSourceFiles,TRUE)); p->ufs[0].Filename = strdup(fileName); p->ufs[0].Contents = p->sources[0].data(); p->ufs[0].Length = p->sources[0].length(); QStrListIterator it(filesInTranslationUnit); uint i=1; for (it.toFirst();it.current() && i<numUnsavedFiles;++it,i++) { p->fileMapping.insert(it.current(),new uint(i)); p->sources[i] = detab(fileToString(it.current(),filterSourceFiles,TRUE)); p->ufs[i].Filename = strdup(it.current()); p->ufs[i].Contents = p->sources[i].data(); p->ufs[i].Length = p->sources[i].length(); } // let libclang do the actual parsing p->tu = clang_parseTranslationUnit(p->index, 0, argv, argc, p->ufs, numUnsavedFiles, CXTranslationUnit_DetailedPreprocessingRecord); // free arguments for (int i=0;i<argc;++i) { free(argv[i]); } free(argv); if (p->tu) { // filter out any includes not found by the clang parser determineInputFilesInSameTu(filesInTranslationUnit); // show any warnings that the compiler produced for (uint i=0, n=clang_getNumDiagnostics(p->tu); i!=n; ++i) { CXDiagnostic diag = clang_getDiagnostic(p->tu, i); CXString string = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions()); err("%s [clang]\n",clang_getCString(string)); clang_disposeString(string); clang_disposeDiagnostic(diag); } // create a source range for the given file QFileInfo fi(fileName); CXFile f = clang_getFile(p->tu, fileName); CXSourceLocation fileBegin = clang_getLocationForOffset(p->tu, f, 0); CXSourceLocation fileEnd = clang_getLocationForOffset(p->tu, f, p->ufs[0].Length); CXSourceRange fileRange = clang_getRange(fileBegin, fileEnd); // produce a token stream for the file clang_tokenize(p->tu,fileRange,&p->tokens,&p->numTokens); // produce cursors for each token in the stream p->cursors=new CXCursor[p->numTokens]; clang_annotateTokens(p->tu,p->tokens,p->numTokens,p->cursors); } else { p->tokens = 0; p->numTokens = 0; p->cursors = 0; err("clang: Failed to parse translation unit %s\n",fileName); } }
void writeInstallScript() { QCString fileName=Config_getString("HTML_OUTPUT")+"/installdox"; QFile f(fileName); if (f.open(IO_WriteOnly)) { FTextStream t(&f); t << "#!" << Config_getString("PERL_PATH") << endl << endl << "%subst = ( "; char *s=Config_getList("TAGFILES").first(); while (s) { QCString tagLine=s; QCString fileName; int eqPos = tagLine.find('='); if (eqPos!=-1) // strip destination part { fileName = tagLine.left(eqPos).stripWhiteSpace(); } else { fileName = tagLine; } QFileInfo fi(fileName); t << "\"" << fi.fileName() << "\", \"\""; s=Config_getList("TAGFILES").next(); if (s) t << ", "; } t << ");\n"; t << "$quiet = 0;\n"; t << "\n"; t << "if (open(F,\"search.cfg\"))\n"; t << "{\n"; t << " $_=<F> ; s/[ \\t\\n]*$//g ; $subst{\"_doc\"} = $_;\n"; t << " $_=<F> ; s/[ \\t\\n]*$//g ; $subst{\"_cgi\"} = $_;\n"; t << "}\n"; t << "\n"; t << "while ( @ARGV ) {\n"; t << " $_ = shift @ARGV;\n"; t << " if ( s/^-// ) {\n"; t << " if ( /^l(.*)/ ) {\n"; t << " $v = ($1 eq \"\") ? shift @ARGV : $1;\n"; t << " ($v =~ /\\/$/) || ($v .= \"/\");\n"; t << " $_ = $v;\n"; t << " if ( /(.+)\\@(.+)/ ) {\n"; t << " if ( exists $subst{$1} ) {\n"; t << " $subst{$1} = $2;\n"; t << " } else {\n"; t << " print STDERR \"Unknown tag file $1 given with option -l\\n\";\n"; t << " &usage();\n"; t << " }\n"; t << " } else {\n"; t << " print STDERR \"Argument $_ is invalid for option -l\\n\";\n"; t << " &usage();\n"; t << " }\n"; t << " }\n"; t << " elsif ( /^q/ ) {\n"; t << " $quiet = 1;\n"; t << " }\n"; t << " elsif ( /^\\?|^h/ ) {\n"; t << " &usage();\n"; t << " }\n"; t << " else {\n"; t << " print STDERR \"Illegal option -$_\\n\";\n"; t << " &usage();\n"; t << " }\n"; t << " }\n"; t << " else {\n"; t << " push (@files, $_ );\n"; t << " }\n"; t << "}\n"; t << "\n"; t << "foreach $sub (keys %subst)\n"; t << "{\n"; t << " if ( $subst{$sub} eq \"\" ) \n"; t << " {\n"; t << " print STDERR \"No substitute given for tag file `$sub'\\n\";\n"; t << " &usage();\n"; t << " }\n"; t << " elsif ( ! $quiet && $sub ne \"_doc\" && $sub ne \"_cgi\" )\n"; t << " {\n"; t << " print \"Substituting $subst{$sub} for each occurrence of tag file $sub\\n\"; \n"; t << " }\n"; t << "}\n"; t << "\n"; t << "if ( ! @files ) {\n"; t << " if (opendir(D,\".\")) {\n"; t << " foreach $file ( readdir(D) ) {\n"; t << " $match = \"" << Config_getString("HTML_FILE_EXTENSION") << "\";\n"; t << " next if ( $file =~ /^\\.\\.?$/ );\n"; t << " ($file =~ /$match/) && (push @files, $file);\n"; t << " ($file =~ \"tree.js\") && (push @files, $file);\n"; t << " }\n"; t << " closedir(D);\n"; t << " }\n"; t << "}\n"; t << "\n"; t << "if ( ! @files ) {\n"; t << " print STDERR \"Warning: No input files given and none found!\\n\";\n"; t << "}\n"; t << "\n"; t << "foreach $f (@files)\n"; t << "{\n"; t << " if ( ! $quiet ) {\n"; t << " print \"Editing: $f...\\n\";\n"; t << " }\n"; t << " $oldf = $f;\n"; t << " $f .= \".bak\";\n"; t << " unless (rename $oldf,$f) {\n"; t << " print STDERR \"Error: cannot rename file $oldf\\n\";\n"; t << " exit 1;\n"; t << " }\n"; t << " if (open(F,\"<$f\")) {\n"; t << " unless (open(G,\">$oldf\")) {\n"; t << " print STDERR \"Error: opening file $oldf for writing\\n\";\n"; t << " exit 1;\n"; t << " }\n"; t << " if ($oldf ne \"tree.js\") {\n"; t << " while (<F>) {\n"; t << " s/doxygen\\=\\\"([^ \\\"\\:\\t\\>\\<]*)\\:([^ \\\"\\t\\>\\<]*)\\\" (href|src)=\\\"\\2/doxygen\\=\\\"$1:$subst{$1}\\\" \\3=\\\"$subst{$1}/g;\n"; t << " print G \"$_\";\n"; t << " }\n"; t << " }\n"; t << " else {\n"; t << " while (<F>) {\n"; t << " s/\\\"([^ \\\"\\:\\t\\>\\<]*)\\:([^ \\\"\\t\\>\\<]*)\\\", \\\"\\2/\\\"$1:$subst{$1}\\\" ,\\\"$subst{$1}/g;\n"; t << " print G \"$_\";\n"; t << " }\n"; t << " }\n"; t << " } \n"; t << " else {\n"; t << " print STDERR \"Warning file $f does not exist\\n\";\n"; t << " }\n"; t << " unlink $f;\n"; t << "}\n"; t << "\n"; t << "sub usage {\n"; t << " print STDERR \"Usage: installdox [options] [html-file [html-file ...]]\\n\";\n"; t << " print STDERR \"Options:\\n\";\n"; t << " print STDERR \" -l tagfile\\@linkName tag file + URL or directory \\n\";\n"; t << " print STDERR \" -q Quiet mode\\n\\n\";\n"; t << " exit 1;\n"; t << "}\n"; } else { err("Error: Cannot open file %s for writing\n",fileName.data()); } f.close(); struct stat stat_struct; stat(fileName,&stat_struct); #if !defined(_WIN32) chmod(fileName,stat_struct.st_mode|S_IXUSR|S_IXGRP|S_IXOTH); #endif }
int main(int argc,char **argv) { char cmd[256]; if (argc<2) { printf("Usage: %s [source_file | source_dir]\n",argv[0]); exit(1); } // initialize data structures initDoxygen(); // setup the non-default configuration options // we need a place to put intermediate files Config_getString("OUTPUT_DIRECTORY")="/tmp/doxygen"; // disable html output Config_getBool("GENERATE_HTML")=FALSE; // disable latex output Config_getBool("GENERATE_LATEX")=FALSE; // be quiet Config_getBool("QUIET")=TRUE; // turn off warnings Config_getBool("WARNINGS")=FALSE; Config_getBool("WARN_IF_UNDOCUMENTED")=FALSE; Config_getBool("WARN_IF_DOC_ERROR")=FALSE; // Extract as much as possible Config_getBool("EXTRACT_ALL")=TRUE; Config_getBool("EXTRACT_STATIC")=TRUE; Config_getBool("EXTRACT_PRIVATE")=TRUE; Config_getBool("EXTRACT_LOCAL_METHODS")=TRUE; // Extract source browse information, needed // to make doxygen gather the cross reference info Config_getBool("SOURCE_BROWSER")=TRUE; // set the input Config_getList("INPUT").append(argv[1]); // check and finialize the configuration checkConfiguration(); adjustConfiguration(); // parse the files parseInput(); // iterate over the input files FileNameListIterator fnli(*Doxygen::inputNameList); FileName *fn; // foreach file with a certain name for (fnli.toFirst();(fn=fnli.current());++fnli) { FileNameIterator fni(*fn); FileDef *fd; // for each file definition for (;(fd=fni.current());++fni) { // get the references (linked and unlinked) found in this file findXRefSymbols(fd); } } // remove temporary files if (!Doxygen::objDBFileName.isEmpty()) unlink(Doxygen::objDBFileName); if (!Doxygen::entryDBFileName.isEmpty()) unlink(Doxygen::entryDBFileName); // clean up after us rmdir("/tmp/doxygen"); while (1) { printf("> Type a symbol name or\n> .list for a list of symbols or\n> .quit to exit\n> "); fgets(cmd,256,stdin); QCString s(cmd); if (s.at(s.length()-1)=='\n') s=s.left(s.length()-1); // strip trailing \n if (s==".list") listSymbols(); else if (s==".quit") exit(0); else lookupSymbols(s); } }