00001 /****************************************************************************** 00002 * 00003 * $Id: entry.cpp,v 1.29 2001/03/19 19:27:40 root Exp $ 00004 * 00005 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00006 * 00007 * Permission to use, copy, modify, and distribute this software and its 00008 * documentation under the terms of the GNU General Public License is hereby 00009 * granted. No representations are made about the suitability of this software 00010 * for any purpose. It is provided "as is" without express or implied warranty. 00011 * See the GNU General Public License for more details. 00012 * 00013 * Documents produced by Doxygen are derivative works derived from the 00014 * input used in their production; they are not affected by this license. 00015 * 00016 */ 00017 00018 #include <stdlib.h> 00019 #include <qfile.h> 00020 #include "entry.h" 00021 #include "marshal.h" 00022 #include "util.h" 00023 #include "section.h" 00024 #include "doxygen.h" 00025 00026 //------------------------------------------------------------------ 00027 00028 #define HEADER ('D'<<24)+('O'<<16)+('X'<<8)+'!' 00029 00030 //------------------------------------------------------------------ 00031 00035 bool ArgumentList::hasDocumentation() const 00036 { 00037 bool hasDocs=FALSE; 00038 ArgumentListIterator ali(*this); 00039 Argument *a; 00040 for (ali.toFirst();!hasDocs && (a=ali.current());++ali) 00041 { 00042 hasDocs = hasDocs || a->hasDocumentation(); 00043 } 00044 return hasDocs; 00045 } 00046 00047 //------------------------------------------------------------------ 00048 00049 int Entry::num=0; 00050 00051 Entry::Entry() 00052 { 00053 //printf("Entry::Entry(%p)\n",this); 00054 num++; 00055 m_parent=0; 00056 section = EMPTY_SEC; 00057 m_sublist = new QList<Entry>; 00058 m_sublist->setAutoDelete(TRUE); 00059 extends = new QList<BaseInfo>; 00060 extends->setAutoDelete(TRUE); 00061 groups = new QList<Grouping>; 00062 groups->setAutoDelete(TRUE); 00063 anchors = new QList<SectionInfo>; // Doxygen::sectionDict takes ownership of the items! 00064 argList = new ArgumentList; 00065 argList->setAutoDelete(TRUE); 00066 //printf("Entry::Entry() tArgList=0\n"); 00067 tArgLists = 0; 00068 typeConstr = 0; 00069 mGrpId = -1; 00070 tagInfo = 0; 00071 sli = 0; 00072 relatesDup = FALSE; 00073 hidden = FALSE; 00074 groupDocType = GROUPDOC_NORMAL; 00075 reset(); 00076 } 00077 00078 Entry::Entry(const Entry &e) 00079 { 00080 //printf("Entry::Entry(%p):copy\n",this); 00081 num++; 00082 section = e.section; 00083 protection = e.protection; 00084 mtype = e.mtype; 00085 stat = e.stat; 00086 explicitExternal = e.explicitExternal; 00087 virt = e.virt; 00088 m_parent = e.m_parent; 00089 type = e.type.copy(); 00090 name = e.name.copy(); 00091 args = e.args; 00092 bitfields = e.bitfields.copy(); 00093 exception = e.exception.copy(); 00094 program = e.program; 00095 includeFile = e.includeFile.copy(); 00096 includeName = e.includeFile.copy(); 00097 doc = e.doc.copy(); 00098 docLine = e.docLine; 00099 docFile = e.docFile.copy(); 00100 relates = e.relates.copy(); 00101 relatesDup = e.relatesDup; 00102 read = e.read.copy(); 00103 write = e.write.copy(); 00104 brief = e.brief.copy(); 00105 briefLine = e.briefLine; 00106 briefFile = e.briefFile.copy(); 00107 inbodyDocs = e.inbodyDocs.copy(); 00108 inbodyLine = e.inbodyLine; 00109 inbodyFile = e.inbodyFile.copy(); 00110 inside = e.inside.copy(); 00111 fileName = e.fileName.copy(); 00112 startLine = e.startLine; 00113 mGrpId = e.mGrpId; 00114 bodyLine = e.bodyLine; 00115 endBodyLine = e.endBodyLine; 00116 spec = e.spec; 00117 initializer = e.initializer; 00118 initLines = e.initLines; 00119 callGraph = e.callGraph; 00120 callerGraph = e.callerGraph; 00121 objc = e.objc; 00122 tagInfo = e.tagInfo; 00123 hidden = e.hidden; 00124 artificial = e.artificial; 00125 m_sublist = new QList<Entry>; 00126 m_sublist->setAutoDelete(TRUE); 00127 extends = new QList<BaseInfo>; 00128 extends->setAutoDelete(TRUE); 00129 groups = new QList<Grouping>; 00130 groups->setAutoDelete(TRUE); 00131 anchors = new QList<SectionInfo>; 00132 argList = new ArgumentList; 00133 argList->setAutoDelete(TRUE); 00134 typeConstr = new ArgumentList; 00135 typeConstr->setAutoDelete(TRUE); 00136 tArgLists = 0; 00137 groupDocType = e.groupDocType; 00138 00139 // deep copy of the child entry list 00140 QListIterator<Entry> eli(*e.m_sublist); 00141 Entry *cur; 00142 for (;(cur=eli.current());++eli) 00143 { 00144 m_sublist->append(new Entry(*cur)); 00145 } 00146 00147 // deep copy base class list 00148 QListIterator<BaseInfo> bli(*e.extends); 00149 BaseInfo *bi; 00150 for (;(bi=bli.current());++bli) 00151 { 00152 extends->append(new BaseInfo(*bi)); 00153 } 00154 00155 // deep copy group list 00156 QListIterator<Grouping> gli(*e.groups); 00157 Grouping *g; 00158 for (;(g=gli.current());++gli) 00159 { 00160 groups->append(new Grouping(*g)); 00161 } 00162 00163 QListIterator<SectionInfo> sli2(*e.anchors); 00164 SectionInfo *s; 00165 for (;(s=sli2.current());++sli2) 00166 { 00167 anchors->append(new SectionInfo(*s)); 00168 } 00169 00170 // deep copy argument list 00171 QListIterator<Argument> ali(*e.argList); 00172 Argument *a; 00173 for (;(a=ali.current());++ali) 00174 { 00175 argList->append(new Argument(*a)); 00176 } 00177 argList->constSpecifier = e.argList->constSpecifier; 00178 argList->volatileSpecifier = e.argList->volatileSpecifier; 00179 argList->pureSpecifier = e.argList->pureSpecifier; 00180 00181 // deep copy type contraint list 00182 if (e.typeConstr) 00183 { 00184 QListIterator<Argument> tcli(*e.typeConstr); 00185 for (;(a=tcli.current());++tcli) 00186 { 00187 typeConstr->append(new Argument(*a)); 00188 } 00189 } 00190 00191 // deep copy template argument lists 00192 if (e.tArgLists) 00193 { 00194 tArgLists = copyArgumentLists(e.tArgLists); 00195 } 00196 00197 if (e.sli) 00198 { 00199 sli = new QList<ListItemInfo>; 00200 sli->setAutoDelete(TRUE); 00201 QListIterator<ListItemInfo> slii(*e.sli); 00202 ListItemInfo *ili; 00203 for (slii.toFirst();(ili=slii.current());++slii) 00204 { 00205 sli->append(new ListItemInfo(*ili)); 00206 } 00207 } 00208 else 00209 { 00210 sli=0; 00211 } 00212 } 00213 00214 Entry::~Entry() 00215 { 00216 //printf("Entry::~Entry(%p) num=%d\n",this,num); 00217 //printf("Deleting entry %d name %s type %x children %d\n", 00218 // num,name.data(),section,sublist->count()); 00219 00220 delete m_sublist; // each element is now own by a EntryNav so we do no longer own 00221 // our children. 00222 delete extends; 00223 delete groups; 00224 delete anchors; 00225 delete argList; 00226 delete tArgLists; 00227 delete tagInfo; 00228 delete sli; 00229 num--; 00230 } 00231 00232 void Entry::addSubEntry(Entry *current) 00233 { 00234 //printf("Entry %d with name %s type 0x%x added to %s type 0x%x\n", 00235 // current->num,current->name.data(),current->section, 00236 // name.data(),section); 00237 //printf("Entry::addSubEntry(%s:%p) to %s\n",current->name.data(), 00238 // current,name.data()); 00239 current->m_parent=this; 00240 m_sublist->append(current); 00241 } 00242 00243 void Entry::reset() 00244 { 00245 //printf("Entry::reset()\n"); 00246 name.resize(0); 00247 type.resize(0); 00248 args.resize(0); 00249 bitfields.resize(0); 00250 exception.resize(0); 00251 program.resize(0); 00252 includeFile.resize(0); 00253 includeName.resize(0); 00254 doc.resize(0); 00255 docFile.resize(0); 00256 docLine=-1; 00257 relates.resize(0); 00258 relatesDup=FALSE; 00259 brief.resize(0); 00260 briefFile.resize(0); 00261 briefLine=-1; 00262 inbodyDocs.resize(0); 00263 inbodyFile.resize(0); 00264 inbodyLine=-1; 00265 inside.resize(0); 00266 fileName.resize(0); 00267 initializer.resize(0); 00268 initLines = -1; 00269 startLine = 1; 00270 bodyLine = -1; 00271 endBodyLine = -1; 00272 mGrpId = -1; 00273 callGraph = FALSE; 00274 callerGraph = FALSE; 00275 section = EMPTY_SEC; 00276 mtype = Method; 00277 virt = Normal; 00278 stat = FALSE; 00279 proto = FALSE; 00280 explicitExternal = FALSE; 00281 spec = 0; 00282 objc = FALSE; 00283 hidden = FALSE; 00284 artificial = FALSE; 00285 subGrouping = TRUE; 00286 protection = Public; 00287 groupDocType = GROUPDOC_NORMAL; 00288 m_sublist->clear(); 00289 extends->clear(); 00290 groups->clear(); 00291 anchors->clear(); 00292 argList->clear(); 00293 if (tagInfo) { delete tagInfo; tagInfo=0; } 00294 if (tArgLists) { delete tArgLists; tArgLists=0; } 00295 if (sli) { delete sli; sli=0; } 00296 if (typeConstr) { delete typeConstr; typeConstr=0; } 00297 //if (mtArgList) { delete mtArgList; mtArgList=0; } 00298 } 00299 00300 00301 int Entry::getSize() 00302 { 00303 return sizeof(Entry); 00304 } 00305 00306 void Entry::createSubtreeIndex(EntryNav *nav,FileStorage *storage,FileDef *fd) 00307 { 00308 EntryNav *childNav = new EntryNav(nav,this); 00309 nav->addChild(childNav); 00310 childNav->setFileDef(fd); 00311 childNav->saveEntry(this,storage); 00312 if (m_sublist) 00313 { 00314 //printf("saveEntry: %d children\n",node->sublist->count()); 00315 QListIterator<Entry> eli(*m_sublist); 00316 Entry *childNode; 00317 for (eli.toFirst();(childNode=eli.current());++eli) 00318 { 00319 childNode->createSubtreeIndex(childNav,storage,fd); 00320 } 00321 //m_sublist->setAutoDelete(FALSE); 00322 m_sublist->clear(); 00323 } 00324 } 00325 00326 void Entry::createNavigationIndex(EntryNav *rootNav,FileStorage *storage,FileDef *fd) 00327 { 00328 //printf("createNavigationIndex(%p) sublist=%p\n",this,m_sublist); 00329 if (m_sublist) 00330 { 00331 //printf("saveEntries: %d children\n",root->sublist->count()); 00332 // store all child entries of root, but keep the navigation info (=index) 00333 QListIterator<Entry> eli(*m_sublist); 00334 Entry *e; 00335 for (eli.toFirst();(e=eli.current());++eli) 00336 { 00337 createSubtreeIndex(rootNav,storage,fd); 00338 } 00339 // remove all entries from root 00340 //m_sublist->setAutoDelete(FALSE); 00341 m_sublist->clear(); 00342 } 00343 } 00344 00345 void Entry::addSpecialListItem(const char *listName,int itemId) 00346 { 00347 if (sli==0) 00348 { 00349 sli = new QList<ListItemInfo>; 00350 sli->setAutoDelete(TRUE); 00351 } 00352 ListItemInfo *ili=new ListItemInfo; 00353 ili->type = listName; 00354 ili->itemId = itemId; 00355 sli->append(ili); 00356 } 00357 00358 //------------------------------------------------------------------ 00359 00360 00361 EntryNav::EntryNav(EntryNav *parent, Entry *e) 00362 : m_parent(parent), m_subList(0), m_section(e->section), m_type(e->type), 00363 m_name(e->name), m_fileDef(0), m_info(0), m_offset(-1), 00364 m_noLoad(FALSE) 00365 { 00366 if (e->tagInfo) 00367 { 00368 m_tagInfo = new TagInfo; 00369 m_tagInfo->tagName = e->tagInfo->tagName; 00370 m_tagInfo->fileName = e->tagInfo->fileName; 00371 m_tagInfo->anchor = e->tagInfo->anchor; 00372 if (e->tagInfo) 00373 { 00374 //printf("tagInfo %p: tagName=%s fileName=%s anchor=%s\n", 00375 // e->tagInfo, 00376 // e->tagInfo->tagName.data(), 00377 // e->tagInfo->fileName.data(), 00378 // e->tagInfo->anchor.data()); 00379 } 00380 } 00381 else 00382 { 00383 m_tagInfo = 0; 00384 } 00385 } 00386 00387 EntryNav::~EntryNav() 00388 { 00389 delete m_subList; 00390 delete m_info; 00391 delete m_tagInfo; 00392 } 00393 00394 void EntryNav::addChild(EntryNav *e) 00395 { 00396 if (m_subList==0) 00397 { 00398 m_subList = new QList<EntryNav>; 00399 m_subList->setAutoDelete(TRUE); 00400 } 00401 m_subList->append(e); 00402 } 00403 00404 bool EntryNav::loadEntry(FileStorage *storage) 00405 { 00406 if (m_noLoad) 00407 { 00408 return TRUE; 00409 } 00410 if (m_offset==-1) 00411 { 00412 //printf("offset not set!\n"); 00413 return FALSE; 00414 } 00415 //delete m_info; 00416 //printf("EntryNav::loadEntry: new entry %p: %s\n",m_info,m_name.data()); 00417 //m_info->tagInfo = m_tagInfo; 00418 //if (m_parent) 00419 //{ 00420 // m_info->parent = m_parent->m_info; 00421 //} 00422 //m_info->parent = 0; 00423 //printf("load entry: seek to %llx\n",m_offset); 00424 if (!storage->seek(m_offset)) 00425 { 00426 //printf("seek failed!\n"); 00427 return FALSE; 00428 } 00429 if (m_info) delete m_info; 00430 m_info = unmarshalEntry(storage); 00431 m_info->name = m_name; 00432 m_info->type = m_type; 00433 m_info->section = m_section; 00434 return TRUE; 00435 } 00436 00437 bool EntryNav::saveEntry(Entry *e,FileStorage *storage) 00438 { 00439 m_offset = storage->pos(); 00440 //printf("EntryNav::saveEntry offset=%llx\n",m_offset); 00441 marshalEntry(storage,e); 00442 return TRUE; 00443 } 00444 00445 void EntryNav::releaseEntry() 00446 { 00447 if (!m_noLoad) 00448 { 00449 //printf("EntryNav::releaseEntry %p\n",m_info); 00450 delete m_info; 00451 m_info=0; 00452 } 00453 } 00454 00455 void EntryNav::setEntry(Entry *e) 00456 { 00457 delete m_info; 00458 m_info = e; 00459 //printf("EntryNav::setEntry %p\n",e); 00460 m_noLoad=TRUE; 00461 } 00462