1 /***************************************************************************** |
1 /***************************************************************************** |
2 * |
2 * |
3 * |
3 * |
4 * |
4 * |
5 * Copyright (C) 1997-2008 by Dimitri van Heesch. |
5 * Copyright (C) 1997-2010 by Dimitri van Heesch. |
6 * |
6 * |
7 * Permission to use, copy, modify, and distribute this software and its |
7 * Permission to use, copy, modify, and distribute this software and its |
8 * documentation under the terms of the GNU General Public License is hereby |
8 * documentation under the terms of the GNU General Public License is hereby |
9 * granted. No representations are made about the suitability of this software |
9 * granted. No representations are made about the suitability of this software |
10 * for any purpose. It is provided "as is" without express or implied warranty. |
10 * for any purpose. It is provided "as is" without express or implied warranty. |
2074 |
2074 |
2075 // no match |
2075 // no match |
2076 return ""; |
2076 return ""; |
2077 } |
2077 } |
2078 |
2078 |
|
2079 #if 0 |
2079 QCString recodeString(const QCString &str,const char *fromEncoding,const char *toEncoding) |
2080 QCString recodeString(const QCString &str,const char *fromEncoding,const char *toEncoding) |
2080 { |
2081 { |
2081 QCString inputEncoding = fromEncoding; |
2082 QCString inputEncoding = fromEncoding; |
2082 QCString outputEncoding = toEncoding; |
2083 QCString outputEncoding = toEncoding; |
2083 if (inputEncoding.isEmpty() || outputEncoding.isEmpty() || |
2084 if (inputEncoding.isEmpty() || outputEncoding.isEmpty() || |
2251 return ""; |
2253 return ""; |
2252 } |
2254 } |
2253 |
2255 |
2254 QCString dateToString(bool includeTime) |
2256 QCString dateToString(bool includeTime) |
2255 { |
2257 { |
|
2258 QDateTime current = QDateTime::currentDateTime(); |
|
2259 return theTranslator->trDateTime(current.date().year(), |
|
2260 current.date().month(), |
|
2261 current.date().day(), |
|
2262 current.date().dayOfWeek(), |
|
2263 current.time().hour(), |
|
2264 current.time().minute(), |
|
2265 current.time().second(), |
|
2266 includeTime); |
|
2267 #if 0 |
2256 if (includeTime) |
2268 if (includeTime) |
2257 { |
2269 { |
2258 return convertToQCString(QDateTime::currentDateTime().toString()); |
2270 return convertToQCString(QDateTime::currentDateTime().toString()); |
2259 } |
2271 } |
2260 else |
2272 else |
3568 bool checkStatics, |
3581 bool checkStatics, |
3569 FileDef *currentFile, |
3582 FileDef *currentFile, |
3570 bool checkCV, |
3583 bool checkCV, |
3571 QList<MemberDef> &members) |
3584 QList<MemberDef> &members) |
3572 { |
3585 { |
3573 //printf("\n findMembersWithSpecificName() - start\n"); |
3586 //printf(" Function with global scope name `%s' args=`%s'\n", |
3574 //printf(" findMembersWithSpecificName() Function with global scope name `%s' args=`%s'\n",mn->memberName(),args); |
3587 // mn->memberName(),args); |
3575 MemberListIterator mli(*mn); |
3588 MemberListIterator mli(*mn); |
3576 MemberDef *md; |
3589 MemberDef *md; |
3577 for (mli.toFirst();(md=mli.current());++mli) |
3590 for (mli.toFirst();(md=mli.current());++mli) |
3578 { |
3591 { |
3579 FileDef *fd=md->getFileDef(); |
3592 FileDef *fd=md->getFileDef(); |
3580 GroupDef *gd=md->getGroupDef(); |
3593 GroupDef *gd=md->getGroupDef(); |
3581 //printf(" findMembersWithSpecificName() md->name()=`%s' md->args=`%s' fd=%p gd=%p file=%s\n", |
3594 //printf(" md->name()=`%s' md->args=`%s' fd=%p gd=%p current=%p\n", |
3582 // md->name().data(),args,fd,gd,fd?fd->absFilePath().data():""); |
3595 // md->name().data(),args,fd,gd,currentFile); |
3583 //if (gd) printf(" findMembersWithSpecificName() group isLinkable()=%d\n", gd->isLinkable()); |
|
3584 //if (fd) printf(" findMembersWithSpecificName() file isLinkable()=%d\n", fd->isLinkable()); |
|
3585 //if (md) printf(" findMembersWithSpecificName() memb isLinkable()=%d\n", md->isLinkable()); |
|
3586 if ( |
3596 if ( |
3587 ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) && |
3597 ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) && |
3588 md->getNamespaceDef()==0 && md->isLinkable() && |
3598 md->getNamespaceDef()==0 && md->isLinkable() && |
3589 (!checkStatics || !md->isStatic() || currentFile==0 || fd==currentFile) // statics must appear in the same file |
3599 (!checkStatics || (!md->isStatic() && !md->isDefine()) || |
|
3600 currentFile==0 || fd==currentFile) // statics must appear in the same file |
3590 ) |
3601 ) |
3591 { |
3602 { |
3592 //printf(" findMembersWithSpecificName() fd=%p gd=%p args=`%s'\n",fd,gd,args); |
3603 //printf(" findMembersWithSpecificName() fd=%p gd=%p args=`%s'\n",fd,gd,args); |
3593 bool match=TRUE; |
3604 bool match=TRUE; |
3594 ArgumentList *argList=0; |
3605 ArgumentList *argList=0; |
3684 |
3695 |
3685 MemberName *mn = Doxygen::memberNameSDict->find(mName); |
3696 MemberName *mn = Doxygen::memberNameSDict->find(mName); |
3686 //printf("getDefs(): mName=%s mn=%p\n",mName.data(),mn); |
3697 //printf("getDefs(): mName=%s mn=%p\n",mName.data(),mn); |
3687 if (!forceEmptyScope && mn && !(scopeName.isEmpty() && mScope.isEmpty())) |
3698 if (!forceEmptyScope && mn && !(scopeName.isEmpty() && mScope.isEmpty())) |
3688 { |
3699 { |
3689 //printf("getDefs(): >member name found\n"); |
3700 //printf(" >member name '%s' found\n",mName.data()); |
3690 int scopeOffset=scopeName.length(); |
3701 int scopeOffset=scopeName.length(); |
3691 do |
3702 do |
3692 { |
3703 { |
3693 QCString className = scopeName.left(scopeOffset); |
3704 QCString className = scopeName.left(scopeOffset); |
3694 if (!className.isEmpty() && !mScope.isEmpty()) |
3705 if (!className.isEmpty() && !mScope.isEmpty()) |
3695 { |
3706 { |
3696 className+="::"+mScope; |
3707 className+="::"+mScope; |
3697 } |
3708 } |
3698 else if (!mScope.isEmpty()) |
3709 else if (!mScope.isEmpty()) |
3699 { |
3710 { |
3700 className=mScope.copy(); |
3711 className=mScope; |
3701 } |
3712 } |
3702 //printf("getDefs(): Trying class scope %s\n",className.data()); |
3713 //printf("getDefs(): Trying class scope %s\n",className.data()); |
3703 |
3714 |
3704 ClassDef *fcd=0; |
3715 ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className); |
|
3716 //printf("Trying class scope %s: %p\n",className.data(),fcd); |
3705 // todo: fill in correct fileScope! |
3717 // todo: fill in correct fileScope! |
3706 if ((fcd=getResolvedClass(Doxygen::globalScope,0,className)) && // is it a documented class |
3718 if (fcd && // is it a documented class |
3707 fcd->isLinkable() |
3719 fcd->isLinkable() |
3708 ) |
3720 ) |
3709 { |
3721 { |
3710 //printf("getDefs(): getDefs(): Found fcd=%p\n",fcd); |
3722 //printf("getDefs(): getDefs(): Found fcd=%p\n",fcd); |
3711 MemberListIterator mmli(*mn); |
3723 MemberListIterator mmli(*mn); |
3959 if (members.count()==0) // nothing found |
3971 if (members.count()==0) // nothing found |
3960 { |
3972 { |
3961 // search again without strict static checking |
3973 // search again without strict static checking |
3962 findMembersWithSpecificName(mn,args,FALSE,currentFile,checkCV,members); |
3974 findMembersWithSpecificName(mn,args,FALSE,currentFile,checkCV,members); |
3963 } |
3975 } |
3964 |
|
3965 #if 0 |
|
3966 //printf(" Function with global scope name `%s' args=`%s'\n",memberName.data(),args); |
|
3967 MemberListIterator mli(*mn); |
|
3968 for (mli.toFirst();(md=mli.current());++mli) |
|
3969 { |
|
3970 fd=md->getFileDef(); |
|
3971 gd=md->getGroupDef(); |
|
3972 //printf(" md->name()=`%s' md->args=`%s' fd=%p gd=%p\n", |
|
3973 // md->name().data(),args,fd,gd); |
|
3974 if ( |
|
3975 ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) && |
|
3976 md->getNamespaceDef()==0 && md->isLinkable() && |
|
3977 (!md->isStatic() || fd==currentFile) // statics must appear in the same file |
|
3978 ) |
|
3979 { |
|
3980 //printf(" fd=%p gd=%p args=`%s'\n",fd,gd,args); |
|
3981 bool match=TRUE; |
|
3982 ArgumentList *argList=0; |
|
3983 if (args && !md->isDefine() && strcmp(args,"()")!=0) |
|
3984 { |
|
3985 argList=new ArgumentList; |
|
3986 LockingPtr<ArgumentList> mdAl = md->argumentList(); |
|
3987 stringToArgumentList(args,argList); |
|
3988 match=matchArguments2( |
|
3989 md->getOuterScope(),fd,mdAl.pointer(), |
|
3990 Doxygen::globalScope,fd,argList, |
|
3991 checkCV); |
|
3992 delete argList; argList=0; |
|
3993 } |
|
3994 if (match) |
|
3995 { |
|
3996 //printf("Found match!\n"); |
|
3997 members.append(md); |
|
3998 } |
|
3999 } |
|
4000 } |
|
4001 #endif |
|
4002 if (members.count()!=1 && args && !strcmp(args,"()")) |
3976 if (members.count()!=1 && args && !strcmp(args,"()")) |
4003 { |
3977 { |
4004 // no exact match found, but if args="()" an arbitrary |
3978 // no exact match found, but if args="()" an arbitrary |
4005 // member will do |
3979 // member will do |
4006 md=mn->last(); |
3980 md=mn->last(); |
4772 return FALSE; |
4746 return FALSE; |
4773 } |
4747 } |
4774 |
4748 |
4775 //---------------------------------------------------------------------- |
4749 //---------------------------------------------------------------------- |
4776 |
4750 |
4777 QCString escapeCharsInString(const char *name,bool allowDots) |
4751 QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscore) |
4778 { |
4752 { |
4779 static bool caseSenseNames = Config_getBool("CASE_SENSE_NAMES"); |
4753 static bool caseSenseNames = Config_getBool("CASE_SENSE_NAMES"); |
4780 QCString result; |
4754 QCString result; |
4781 char c; |
4755 char c; |
4782 const char *p=name; |
4756 const char *p=name; |
4783 while ((c=*p++)!=0) |
4757 while ((c=*p++)!=0) |
4784 { |
4758 { |
4785 switch(c) |
4759 switch(c) |
4786 { |
4760 { |
4787 case '_': result+="__"; break; |
4761 case '_': if (allowUnderscore) result+="_"; else result+="__"; break; |
4788 case '-': result+="-"; break; |
4762 case '-': result+="-"; break; |
4789 case ':': result+="_1"; break; |
4763 case ':': result+="_1"; break; |
4790 case '/': result+="_2"; break; |
4764 case '/': result+="_2"; break; |
4791 case '<': result+="_3"; break; |
4765 case '<': result+="_3"; break; |
4792 case '>': result+="_4"; break; |
4766 case '>': result+="_4"; break; |
4836 |
4810 |
4837 /*! This function determines the file name on disk of an item |
4811 /*! This function determines the file name on disk of an item |
4838 * given its name, which could be a class name with template |
4812 * given its name, which could be a class name with template |
4839 * arguments, so special characters need to be escaped. |
4813 * arguments, so special characters need to be escaped. |
4840 */ |
4814 */ |
4841 QCString convertNameToFile(const char *name,bool allowDots) |
4815 QCString convertNameToFile(const char *name,bool allowDots,bool allowUnderscore) |
4842 { |
4816 { |
4843 static bool shortNames = Config_getBool("SHORT_NAMES"); |
4817 static bool shortNames = Config_getBool("SHORT_NAMES"); |
4844 static bool createSubdirs = Config_getBool("CREATE_SUBDIRS"); |
4818 static bool createSubdirs = Config_getBool("CREATE_SUBDIRS"); |
4845 QCString result; |
4819 QCString result; |
4846 if (shortNames) // use short names only |
4820 if (shortNames) // use short names only |
4862 } |
4836 } |
4863 result.sprintf("a%05d",num); |
4837 result.sprintf("a%05d",num); |
4864 } |
4838 } |
4865 else // long names |
4839 else // long names |
4866 { |
4840 { |
4867 result=escapeCharsInString(name,allowDots); |
4841 result=escapeCharsInString(name,allowDots,allowUnderscore); |
4868 int resultLen = result.length(); |
4842 int resultLen = result.length(); |
4869 if (resultLen>=128) // prevent names that cannot be created! |
4843 if (resultLen>=128) // prevent names that cannot be created! |
4870 { |
4844 { |
4871 // third algorithm based on MD5 hash |
4845 // third algorithm based on MD5 hash |
4872 uchar md5_sig[16]; |
4846 uchar md5_sig[16]; |
5850 |
5824 |
5851 void addRefItem(const QList<ListItemInfo> *sli, |
5825 void addRefItem(const QList<ListItemInfo> *sli, |
5852 const char *key, |
5826 const char *key, |
5853 const char *prefix, const char *name,const char *title,const char *args) |
5827 const char *prefix, const char *name,const char *title,const char *args) |
5854 { |
5828 { |
5855 //printf("addRefItem(sli=%p,prefix=%s,name=%s,title=%s,args=%s)\n",sli,prefix,name,title,args); |
5829 //printf("addRefItem(sli=%p,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",sli,key,prefix,name,title,args); |
5856 if (sli) |
5830 if (sli) |
5857 { |
5831 { |
5858 QListIterator<ListItemInfo> slii(*sli); |
5832 QListIterator<ListItemInfo> slii(*sli); |
5859 ListItemInfo *lii; |
5833 ListItemInfo *lii; |
5860 for (slii.toFirst();(lii=slii.current());++slii) |
5834 for (slii.toFirst();(lii=slii.current());++slii) |
5879 item->title = title; |
5853 item->title = title; |
5880 item->args = args; |
5854 item->args = args; |
5881 |
5855 |
5882 refList->insertIntoList(key,item); |
5856 refList->insertIntoList(key,item); |
5883 |
5857 |
5884 #if 0 |
|
5885 |
|
5886 //printf("anchor=%s written=%d\n",item->listAnchor.data(),item->written); |
|
5887 //if (item->written) return; |
|
5888 |
|
5889 QCString doc; |
|
5890 doc = "\\anchor "; |
|
5891 doc += item->listAnchor; |
|
5892 doc += " <dl><dt>"; |
|
5893 doc += prefix; |
|
5894 doc += " \\_internalref "; |
|
5895 doc += name; |
|
5896 doc += " \""; |
|
5897 doc += title; |
|
5898 doc += "\""; |
|
5899 if (args) doc += args; |
|
5900 doc += "</dt>\n<dd>"; |
|
5901 doc += item->text; |
|
5902 doc += "</dd></dl>\n"; |
|
5903 addRelatedPage(refList->listName(),refList->pageTitle(),doc,0,refList->listName(),1,0,0,0); |
|
5904 //item->written=TRUE; |
|
5905 #endif |
|
5906 } |
5858 } |
5907 } |
5859 } |
5908 } |
5860 } |
5909 } |
5861 } |
5910 |
5862 |
6368 int p=0,i,l; |
6320 int p=0,i,l; |
6369 while ((i=wordExp.match(s,p,&l))!=-1) |
6321 while ((i=wordExp.match(s,p,&l))!=-1) |
6370 { |
6322 { |
6371 if (s.mid(i,l)==word) |
6323 if (s.mid(i,l)==word) |
6372 { |
6324 { |
6373 if (i>0 && isspace(s.at(i-1))) |
6325 if (i>0 && isspace((uchar)s.at(i-1))) |
6374 i--,l++; |
6326 i--,l++; |
6375 else if (i+l<(int)s.length() && isspace(s.at(i+l))) |
6327 else if (i+l<(int)s.length() && isspace(s.at(i+l))) |
6376 l++; |
6328 l++; |
6377 s = s.left(i)+s.mid(i+l); // remove word + spacing |
6329 s = s.left(i)+s.mid(i+l); // remove word + spacing |
6378 return TRUE; |
6330 return TRUE; |
6866 fprintf(stderr,"============ STACKTRACE END ==============\n"); |
6818 fprintf(stderr,"============ STACKTRACE END ==============\n"); |
6867 //fprintf(stderr,"%s\n", frameStrings[x]); |
6819 //fprintf(stderr,"%s\n", frameStrings[x]); |
6868 #endif |
6820 #endif |
6869 } |
6821 } |
6870 |
6822 |
6871 static int transcodeCharacterBuffer(BufStr &srcBuf,int size, |
6823 static int transcodeCharacterBuffer(const char *fileName,BufStr &srcBuf,int size, |
6872 const char *inputEncoding,const char *outputEncoding) |
6824 const char *inputEncoding,const char *outputEncoding) |
6873 { |
6825 { |
6874 if (inputEncoding==0 || outputEncoding==0) return size; |
6826 if (inputEncoding==0 || outputEncoding==0) return size; |
6875 if (qstricmp(inputEncoding,outputEncoding)==0) return size; |
6827 if (qstricmp(inputEncoding,outputEncoding)==0) return size; |
6876 void *cd = portable_iconv_open(outputEncoding,inputEncoding); |
6828 void *cd = portable_iconv_open(outputEncoding,inputEncoding); |
6895 strncpy(srcBuf.data(),tmpBuf.data(),newSize); |
6847 strncpy(srcBuf.data(),tmpBuf.data(),newSize); |
6896 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,srcBuf.data()); |
6848 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,srcBuf.data()); |
6897 } |
6849 } |
6898 else |
6850 else |
6899 { |
6851 { |
6900 err("Error: failed to translate characters from %s to %s: check INPUT_ENCODING\n", |
6852 err("%s: Error: failed to translate characters from %s to %s: check INPUT_ENCODING\n", |
6901 inputEncoding,outputEncoding); |
6853 fileName,inputEncoding,outputEncoding); |
6902 exit(1); |
6854 exit(1); |
6903 } |
6855 } |
6904 portable_iconv_close(cd); |
6856 portable_iconv_close(cd); |
6905 return newSize; |
6857 return newSize; |
6906 } |
6858 } |
6959 ((inBuf.at(0)==-1 && inBuf.at(1)==-2) || // Litte endian BOM |
6911 ((inBuf.at(0)==-1 && inBuf.at(1)==-2) || // Litte endian BOM |
6960 (inBuf.at(0)==-2 && inBuf.at(1)==-1) // big endian BOM |
6912 (inBuf.at(0)==-2 && inBuf.at(1)==-1) // big endian BOM |
6961 ) |
6913 ) |
6962 ) // UCS-2 encoded file |
6914 ) // UCS-2 encoded file |
6963 { |
6915 { |
6964 transcodeCharacterBuffer(inBuf,inBuf.curPos(), |
6916 transcodeCharacterBuffer(fileName,inBuf,inBuf.curPos(), |
6965 "UCS-2","UTF-8"); |
6917 "UCS-2","UTF-8"); |
6966 } |
6918 } |
6967 else if (inBuf.size()>=3 && |
6919 else if (inBuf.size()>=3 && |
6968 (uchar)inBuf.at(0)==0xEF && |
6920 (uchar)inBuf.at(0)==0xEF && |
6969 (uchar)inBuf.at(1)==0xBB && |
6921 (uchar)inBuf.at(1)==0xBB && |
6974 inBuf.dropFromStart(3); // remove UTF-8 BOM: no translation needed |
6926 inBuf.dropFromStart(3); // remove UTF-8 BOM: no translation needed |
6975 } |
6927 } |
6976 else // transcode according to the INPUT_ENCODING setting |
6928 else // transcode according to the INPUT_ENCODING setting |
6977 { |
6929 { |
6978 // do character transcoding if needed. |
6930 // do character transcoding if needed. |
6979 transcodeCharacterBuffer(inBuf,inBuf.curPos(), |
6931 transcodeCharacterBuffer(fileName,inBuf,inBuf.curPos(), |
6980 Config_getString("INPUT_ENCODING"),"UTF-8"); |
6932 Config_getString("INPUT_ENCODING"),"UTF-8"); |
6981 } |
6933 } |
6982 |
6934 |
6983 inBuf.addChar('\n'); /* to prevent problems under Windows ? */ |
6935 inBuf.addChar('\n'); /* to prevent problems under Windows ? */ |
6984 |
6936 |
7009 } |
6961 } |
7010 tf+=title.right(title.length()-p); |
6962 tf+=title.right(title.length()-p); |
7011 return tf; |
6963 return tf; |
7012 } |
6964 } |
7013 |
6965 |
|
6966 //---------------------------------------------------------------------------- |
|
6967 // returns TRUE if the name of the file represented by `fi' matches |
|
6968 // one of the file patterns in the `patList' list. |
|
6969 |
|
6970 bool patternMatch(const QFileInfo &fi,const QStrList *patList) |
|
6971 { |
|
6972 bool found=FALSE; |
|
6973 if (patList) |
|
6974 { |
|
6975 QStrListIterator it(*patList); |
|
6976 QCString pattern; |
|
6977 for (it.toFirst();(pattern=it.current());++it) |
|
6978 { |
|
6979 if (!pattern.isEmpty() && !found) |
|
6980 { |
|
6981 int i=pattern.find('='); |
|
6982 if (i!=-1) pattern=pattern.left(i); // strip of the extension specific filter name |
|
6983 |
|
6984 #if defined(_WIN32) || defined(__MACOSX__) // Windows or MacOSX |
|
6985 QRegExp re(pattern,FALSE,TRUE); // case insensitive match |
|
6986 #else // unix |
|
6987 QRegExp re(pattern,TRUE,TRUE); // case sensitive match |
|
6988 #endif |
|
6989 found = found || re.match(fi.fileName())!=-1 || |
|
6990 re.match(fi.filePath())!=-1 || |
|
6991 re.match(fi.absFilePath())!=-1; |
|
6992 //printf("Matching `%s' against pattern `%s' found=%d\n", |
|
6993 // fi->fileName().data(),pattern.data(),found); |
|
6994 } |
|
6995 } |
|
6996 } |
|
6997 return found; |
|
6998 } |
|
6999 |
|
7000 void writeSummaryLink(OutputList &ol,const char *label,const char *title, |
|
7001 bool &first) |
|
7002 { |
|
7003 if (first) |
|
7004 { |
|
7005 ol.writeString(" <div class=\"summary\">\n"); |
|
7006 first=FALSE; |
|
7007 } |
|
7008 else |
|
7009 { |
|
7010 ol.writeString(" |\n"); |
|
7011 } |
|
7012 ol.writeString("<a href=\"#"); |
|
7013 ol.writeString(label); |
|
7014 ol.writeString("\">"); |
|
7015 ol.writeString(title); |
|
7016 ol.writeString("</a>"); |
|
7017 } |
|
7018 |
|
7019 |
|
7020 |