📄 util.cpp
字号:
/***************************************************************************** * * $Id: util.cpp,v 1.74 2001/03/19 19:27:42 root Exp $ * * Copyright (C) 1997-2001 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 <stdlib.h>#include <ctype.h>#ifdef _WIN32#include <windows.h>#endif#include "qtbc.h"#include <qregexp.h>#include <qfileinfo.h>#include <qdir.h>#include "util.h"#include "message.h"#include "classdef.h"#include "filedef.h"#include "doxygen.h"#include "doc.h"#include "outputlist.h"#include "defargs.h"#include "language.h"#include "config.h"#include "htmlhelp.h"#include "example.h"#include "version.h"#include "groupdef.h"#include "reflist.h"#include "page.h"#ifndef _WIN32#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>#include <errno.h>extern char **environ;#endif#if defined(_MSC_VER) || defined(__BORLANDC__)#define popen _popen#define pclose _pclose#endif//------------------------------------------------------------------------// TextGeneratorOLImpl implementation//------------------------------------------------------------------------TextGeneratorOLImpl::TextGeneratorOLImpl(OutputDocInterface &od) : m_od(od) {}void TextGeneratorOLImpl::writeString(const char *s) const{ m_od.docify(s); }void TextGeneratorOLImpl::writeBreak() const{ m_od.pushGeneratorState(); m_od.disableAllBut(OutputGenerator::Html); m_od.lineBreak(); m_od.popGeneratorState();}void TextGeneratorOLImpl::writeLink(const char *extRef,const char *file, const char *anchor,const char *text ) const{ m_od.writeObjectLink(extRef,file,anchor,text);}//------------------------------------------------------------------------//------------------------------------------------------------------------ /*! Implements an interruptable system call on Unix/Windows */int iSystem(const char *command,const char *args,bool isBatchFile){#ifndef _WIN32 isBatchFile=isBatchFile; /*! taken from the system() manpage on my Linux box */ int pid,status; if (command==0) return 1; pid = fork(); if (pid==-1) return -1; if (pid==0) { char buf[4096]; strcpy(buf,command); strcat(buf," "); strcat(buf,args); const char * argv[4]; argv[0] = "sh"; argv[1] = "-c"; argv[2] = buf; argv[3] = 0; execve("/bin/sh",(char * const *)argv,environ); exit(127); } for (;;) { if (waitpid(pid,&status,0)==-1) { if (errno!=EINTR) return -1; } else { return status; } }#else if (isBatchFile) { QCString fullCmd = command; fullCmd += " "; fullCmd += args; return system(fullCmd); } else { SHELLEXECUTEINFO sInfo = { sizeof(SHELLEXECUTEINFO), /* structure size */ SEE_MASK_NOCLOSEPROCESS, /* leave the process running */ NULL, /* window handle */ NULL, /* action to perform: open */ command, /* file to execute */ args, /* argument list */ NULL, /* use current working dir */ SW_HIDE, /* minimize on start-up */ 0, /* application instance handle */ NULL, /* ignored: id list */ NULL, /* ignored: class name */ NULL, /* ignored: key class */ 0, /* ignored: hot key */ NULL, /* ignored: icon */ NULL /* resulting application handle */ }; if (!ShellExecuteEx(&sInfo)) { return -1; } else if (sInfo.hProcess) /* executable was launched, wait for it to finish */ { WaitForSingleObject(sInfo.hProcess,INFINITE); CloseHandle(sInfo.hProcess); } } return 0; //return system(command);#endif}// an inheritance tree of depth of 100000 should be enough for everyone :-)const int maxInheritanceDepth = 100000; bool isId(char c){ return c=='_' || isalnum(c);}/*! Removes all anoymous scopes from string s Possible examples:\verbatim "bla::@10::blep" => "bla::blep" "bla::@10::@11::blep" => "bla::blep" "@10::blep" => "blep" " @10::blep" => "blep" "@9::@10::blep" => "blep" "bla::@1" => "bla" "bla::@1::@2" => "bla" "bla @1" => "bla"\endverbatim */QCString removeAnonymousScopes(const QCString &s){ QCString result; if (s.isEmpty()) return result; static QRegExp re("[ :]*@[0-9]+[: ]*"); int i,l,sl=s.length(); int p=0; while ((i=re.match(s,p,&l))!=-1) { result+=s.mid(p,i-p); int c=i; bool b1=FALSE,b2=FALSE; while (c<i+l && s.at(c)!='@') if (s.at(c++)==':') b1=TRUE; c=i+l-1; while (c>=i && s.at(c)!='@') if (s.at(c--)==':') b2=TRUE; if (b1 && b2) { result+="::"; } p=i+l; } result+=s.right(sl-p); //printf("removeAnonymousScopes(`%s')=`%s'\n",s.data(),result.data()); return result;}// replace anonymous scopes with __anonymous__ QCString replaceAnonymousScopes(const QCString &s){ QCString result; if (s.isEmpty()) return result; static QRegExp re("@[0-9]+"); int i,l,sl=s.length(); int p=0; while ((i=re.match(s,p,&l))!=-1) { result+=s.mid(p,i-p); result+="__anonymous__"; p=i+l; } result+=s.right(sl-p); //printf("replaceAnonymousScopes(`%s')=`%s'\n",s.data(),result.data()); return result;}// strip annonymous left hand side part of the scopeQCString stripAnonymousNamespaceScope(const QCString &s){#if 0 int oi=0,i=0,p=0; p=s.find('@'); if (p==-1) return s; while (s.at(p)=='@' && (i=s.find("::@",p))!=-1 && Doxygen::namespaceDict[s.left(i)]!=0) { oi=i; p=i+2; } if (oi==0) { //printf("stripAnonymousNamespaceScope(`%s')=`%s'\n",s.data(),s.data()); return s; } else { //printf("stripAnonymousNamespaceScope(`%s')=`%s'\n",s.data(),s.right(s.length()-oi-2).data()); return s.right(s.length()-oi-2); }#endif int i,p=0,l; QCString newScope; while ((i=getScopeFragment(s,p,&l))!=-1) { //printf("Scope fragment %s\n",s.mid(i,l).data()); if (Doxygen::namespaceSDict[s.left(i+l)]!=0) { if (s.at(i)!='@') { if (!newScope.isEmpty()) newScope+="::"; newScope+=s.mid(i,l); } } else { if (!newScope.isEmpty()) newScope+="::"; newScope+=s.right(s.length()-i); goto done; } p=i+l; }done: //printf("stripAnonymousNamespaceScope(`%s')=`%s'\n",s.data(),newScope.data()); return newScope;}void writePageRef(OutputDocInterface &od,const char *cn,const char *mn){ od.pushGeneratorState(); od.disable(OutputGenerator::Html); od.disable(OutputGenerator::Man); if (Config_getBool("PDF_HYPERLINKS")) od.disable(OutputGenerator::Latex); if (Config_getBool("RTF_HYPERLINKS")) od.disable(OutputGenerator::RTF); od.startPageRef(); od.docify(theTranslator->trPageAbbreviation()); od.endPageRef(cn,mn); od.popGeneratorState();}/*! Generate a place holder for a position in a list. Used for * translators to be able to specify different elements orders * depending on whether text flows from left to right or visa versa. */QCString generateMarker(int id){ QCString result; result.sprintf("@%d\n",id); return result;}/*! strip part of \a path if it matches * one of the paths in the Config_getList("STRIP_FROM_PATH") list */QCString stripFromPath(const QCString &path){ const char *s=Config_getList("STRIP_FROM_PATH").first(); while (s) { QCString prefix = s; if (path.left(prefix.length())==prefix) { return path.right(path.length()-prefix.length()); } s = Config_getList("STRIP_FROM_PATH").next(); } return path;}/*! try to determine if \a name is a source or a header file name by looking * at the extension. A number of variations is allowed in both upper and * lower case) If anyone knows or uses another extension please let me know :-) */int guessSection(const char *name){ QCString n=((QCString)name).lower(); if (n.right(2)==".c" || // source n.right(3)==".cc" || n.right(4)==".cxx" || n.right(4)==".cpp" || n.right(4)==".c++" || n.right(5)==".java" || n.right(3)==".ii" || // inline n.right(4)==".ixx" || n.right(4)==".ipp" || n.right(4)==".i++" || n.right(4)==".inl" ) return Entry::SOURCE_SEC; if (n.right(2)==".h" || // header n.right(3)==".hh" || n.right(4)==".hxx" || n.right(4)==".hpp" || n.right(4)==".h++" || n.right(4)==".idl" ) return Entry::HEADER_SEC; return 0;}QCString resolveTypeDef(Definition *d,const QCString &name){ //printf("resolveTypeDef(%s,%s)\n",d ? d->name().data() : "<none>",name.data()); QCString result; if (name.isEmpty()) return result; Definition *mContext=d; MemberDef *md=0; while (mContext && md==0) { MemberNameSDict *mnd=0; if (mContext->definitionType()==Definition::TypeClass) { mnd=&Doxygen::memberNameSDict; } else { mnd=&Doxygen::functionNameSDict; } MemberName *mn=mnd->find(name); if (mn) { MemberNameIterator mni(*mn); MemberDef *tmd=0; for (;(tmd=mni.current());++mni) { //printf("Found member %s scope=%p mContext=%p\n",tmd->name().data(), // tmd->getOuterScope(),mContext); if (tmd->isTypedef() && tmd->getOuterScope()==mContext) { md=tmd; } } } mContext=mContext->getOuterScope(); } if (md) { //printf("Found typedef name `%s' in scope `%s' value=`%s'\n", // name.data(),d->name().data(),md->typeString() // ); result=md->typeString(); } else { //printf("Typedef `%s' not found in scope `%s'!\n", // name.data(),d ? d->name().data() : "<global>"); } return result; }/*! Get a class definition given its name. * Returns 0 if the class is not found. */ClassDef *getClass(const char *name){ if (name==0 || name[0]=='\0') return 0; return Doxygen::classSDict.find(name);}NamespaceDef *getResolvedNamespace(const char *name){ if (name==0 || name[0]=='\0') return 0; QCString *subst = Doxygen::namespaceAliasDict[name]; if (subst) { int count=0; // recursion detection guard QCString *newSubst; while ((newSubst=Doxygen::namespaceAliasDict[*subst]) && count<10) { subst=newSubst; count++; } if (count==10) { warn_cont("Warning: possible recursive namespace alias detected for %s!\n",name); } return Doxygen::namespaceSDict[subst->data()]; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -