00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <Basics.H>
00020 #include <FS.H>
00021 #include <FP.H>
00022
00023
00024 #include <BitVector.H>
00025 #include <FV.H>
00026 #include <CompactFV.H>
00027 #include <TextIO.H>
00028 #include <Debug.H>
00029
00030
00031 #include "SPKFileRep.H"
00032 #include "IntIntTblLR.H"
00033 #include "CacheEntry.H"
00034 #include "VPKFileChkPt.H"
00035 #include "SPKFile.H"
00036
00037 using std::streampos;
00038 using std::ostream;
00039 using std::ifstream;
00040 using std::cerr;
00041 using std::endl;
00042
00043
00044
00045 bool SPKFile::Update(const VPKFileChkPt *chkpt, const BitVector *toDelete,
00046 BitVector* &exCommonNames, BitVector* &exUncommonNames,
00047 BitVector* &packMask, IntIntTblLR* &reMap,
00048 bool &isEmpty) throw ()
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 {
00077
00078 if (chkpt == (VPKFileChkPt *)NULL) {
00079 chkpt = this->CheckPoint();
00080 assert(!(chkpt->hasNewEntries));
00081 } else if (this->sourceFunc == (Text *)NULL) {
00082
00083 this->sourceFunc = chkpt->sourceFunc;
00084 }
00085
00086
00087 assert(chkpt->hasNewEntries || (toDelete != (BitVector *)NULL));
00088 exCommonNames = exUncommonNames = packMask = (BitVector *)NULL;
00089 reMap = (IntIntTblLR *)NULL;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 BitVector newAllNames, newCommonNames;
00101 int totalEntries = 0;
00102 bool thisDelOne = false;
00103 if (toDelete == (BitVector *)NULL) {
00104
00105
00106 newAllNames.SetInterval(0, this->allNames.len - 1);
00107 newAllNames -= this->commonNames;
00108 totalEntries = this->oldEntries.Size();
00109 } else {
00110
00111 ScanCommonTable(this->oldEntries, toDelete,
00112 newAllNames, newCommonNames,
00113 totalEntries, thisDelOne);
00114 }
00115
00116 bool newDelOne = false;
00117 int numCommonEntries = totalEntries;
00118 int numStableEntries = totalEntries;
00119
00120
00121 if (chkpt->newCommon.Size() > 0) {
00122 ScanCommonTable(chkpt->newCommon, toDelete,
00123 newAllNames, newCommonNames,
00124 totalEntries, newDelOne);
00125 numCommonEntries = totalEntries;
00126 }
00127
00128
00129 if (numCommonEntries > 0) {
00130 newAllNames |= this->commonNames;
00131 newCommonNames |= this->commonNames;
00132 }
00133
00134
00135 if (chkpt->newUncommon != (CE::List *)NULL) {
00136 ScanList(chkpt->newUncommon, toDelete,
00137 newAllNames, newCommonNames,
00138 totalEntries, newDelOne);
00139 }
00140
00141
00142 bool newChkptEntries = (totalEntries > numStableEntries);
00143 bool delAny = (thisDelOne || newDelOne);
00144
00145
00146
00147
00148 isEmpty = (totalEntries == 0);
00149 bool isNewPKFile = (this->pkEpoch == 0);
00150
00151
00152
00153
00154
00155
00156
00157 bool pkfileModified = (newChkptEntries || delAny);
00158 if (!pkfileModified) return pkfileModified;
00159
00160
00161 if (isNewPKFile) {
00162
00163
00164
00165
00166 if (!(newCommonNames.IsEmpty())) {
00167 exUncommonNames = NEW_CONSTR(BitVector, (&newCommonNames));
00168 }
00169 } else if (isEmpty) {
00170
00171
00172
00173 exCommonNames = NEW_CONSTR(BitVector, (&(this->commonNames)));
00174 } else {
00175
00176 BitVector bothCommon(&(this->commonNames));
00177 bothCommon &= newCommonNames;
00178
00179
00180 if (bothCommon < this->commonNames) {
00181 exCommonNames = NEW_CONSTR(BitVector, (&(this->commonNames)));
00182 *exCommonNames -= newCommonNames;
00183 }
00184 if (bothCommon < newCommonNames) {
00185 exUncommonNames = NEW_CONSTR(BitVector, (&newCommonNames));
00186 *exUncommonNames -= this->commonNames;
00187 }
00188 }
00189
00190
00191 bool commonNamesChanged =
00192 ((exCommonNames != NULL) || (exUncommonNames != NULL));
00193 if (commonNamesChanged) {
00194 this->commonNames = newCommonNames;
00195 }
00196
00197
00198
00199
00200 if (isEmpty) {
00201
00202
00203 this->allNames.Reset();
00204 this->oldEntries.Init();
00205
00206
00207
00208 packMask = NEW(BitVector);
00209 reMap = NEW_CONSTR(IntIntTblLR, ( 0));
00210 } else {
00211
00212
00213
00214
00215
00216
00217
00218 if (delAny) {
00219 int nextAvail = newAllNames.NextAvail( false);
00220 assert(nextAvail <= chkpt->allNamesLen);
00221 if (nextAvail < chkpt->allNamesLen) {
00222
00223 packMask = NEW_CONSTR(BitVector, (&newAllNames));
00224 reMap = NEW_CONSTR(IntIntTblLR,
00225 ( chkpt->allNamesLen));
00226 BVIter it(*packMask);
00227 for (int i = 0, k; it.Next( k); i++) {
00228
00229 bool inTbl = reMap->Put(k, i);
00230 assert(!inTbl);
00231 }
00232 }
00233 }
00234 assert((packMask == NULL) == (reMap == NULL));
00235 assert((packMask == NULL) || delAny);
00236
00237
00238
00239 for (int i = this->allNames.len; i < chkpt->allNamesLen; i++) {
00240 this->allNames.Append(chkpt->allNames->name[i]);
00241 }
00242
00243 this->allNames.Pack(packMask);
00244
00245
00246 if (isNewPKFile) {
00247
00248
00249 assert(this->oldEntries.Size() == 0);
00250 } else if (thisDelOne || commonNamesChanged) {
00251
00252
00253
00254
00255 assert(this->oldEntries.Size() > 0);
00256 UpdateCommonTable(this->oldEntries, toDelete, exCommonNames,
00257 exUncommonNames, packMask, reMap, true);
00258 }
00259
00260
00261 if (chkpt->hasNewEntries) {
00262 AddEntries(*chkpt, toDelete, exCommonNames, exUncommonNames,
00263 packMask, reMap, true);
00264 }
00265
00266
00267 this->commonNames.Pack(packMask);
00268 }
00269
00270
00271
00272
00273 this->pkEpoch = chkpt->pkEpoch + 1;
00274 this->namesEpoch = chkpt->namesEpoch;
00275 if (reMap != NULL) {
00276
00277 this->namesEpoch++;
00278 }
00279 assert(pkfileModified);
00280 return pkfileModified;
00281 }
00282
00283 VPKFileChkPt *SPKFile::CheckPoint() throw ()
00284 {
00285 VPKFileChkPt *res = NEW(VPKFileChkPt);
00286
00287 res->sourceFunc = this->sourceFunc;
00288 res->pkEpoch = this->pkEpoch;
00289 res->namesEpoch = this->namesEpoch;
00290 res->allNamesLen = this->allNames.len;
00291 res->allNames = &(this->allNames);
00292 return res;
00293 }
00294
00295 void SPKFile::ScanCommonTable(const CFPEntryMap &cfpTbl,
00296 const BitVector *toDelete, BitVector &uncommonJoin,
00297 BitVector &uncommonMeet, int &totalEntries,
00298 bool &delOne) const throw ()
00299 {
00300 if (cfpTbl.Size() > 0) {
00301 CFPEntryIter iter(&cfpTbl);
00302 FP::Tag cfp; CE::List *curr;
00303 while (iter.Next( cfp, curr)) {
00304 ScanList(curr, toDelete, uncommonJoin,
00305 uncommonMeet, totalEntries,
00306 delOne);
00307 }
00308 }
00309 }
00310
00311 void SPKFile::ScanList(const CE::List *head, const BitVector *toDelete,
00312 BitVector &uncommonJoin, BitVector &uncommonMeet,
00313 int &totalEntries, bool &delOne) const throw ()
00314 {
00315 for (const CE::List *curr = head; curr != NULL; curr = curr->Tail()) {
00316 CE::T *ce = curr->Head();
00317 if (toDelete != NULL && toDelete->Read(ce->CI())) {
00318
00319 delOne = true;
00320 } else {
00321
00322 uncommonJoin |= ce->UncommonNames();
00323 if (totalEntries > 0) {
00324
00325 uncommonMeet &= ce->UncommonNames();
00326 } else {
00327
00328 uncommonMeet = ce->UncommonNames();
00329 }
00330 totalEntries++;
00331 }
00332 }
00333 }
00334
00335 CE::List* SPKFile::ExtractEntries( CFPEntryMap &cfpTbl) throw ()
00336 {
00337
00338 CE::List *res = (CE::List *)NULL, *curr;
00339 FP::Tag cfp;
00340 CFPEntryIter iter(&cfpTbl);
00341 while (iter.Next( cfp, curr)) {
00342 while (curr != (CE::List *)NULL) {
00343 res = NEW_CONSTR(CE::List, (curr->Head(), res));
00344 curr = curr->Tail();
00345 }
00346 }
00347
00348 cfpTbl.Init();
00349 return res;
00350 }
00351
00352 void SPKFile::UpdateCommonTable( CFPEntryMap &cfpTbl,
00353 const BitVector *toDelete, const BitVector *exCommonNames,
00354 const BitVector *exUncommonNames, const BitVector *packMask,
00355 const IntIntTblLR *reMap, bool unlazyTag) throw ()
00356
00357
00358 {
00359
00360 assert(cfpTbl.Size() > 0);
00361 assert((packMask == NULL) == (reMap == NULL));
00362
00363
00364 CE::List *existing = ExtractEntries(cfpTbl);
00365
00366
00367
00368 UpdateList(cfpTbl, existing, toDelete, exCommonNames, exUncommonNames,
00369 packMask, reMap, unlazyTag);
00370 }
00371
00372 void SPKFile::AddEntries(const VPKFileChkPt &chkpt, const BitVector *toDelete,
00373 const BitVector *exCommonNames, const BitVector *exUncommonNames,
00374 const BitVector *packMask, const IntIntTblLR *reMap, bool unlazyTag)
00375 throw ()
00376
00377 {
00378 assert((packMask == NULL) == (reMap == NULL));
00379
00380
00381 if (chkpt.newCommon.Size() > 0) {
00382 assert(this->pkEpoch > 0);
00383 CFPEntryIter iter(&(chkpt.newCommon));
00384 FP::Tag cfp; CE::List *ents;
00385 while (iter.Next( cfp, ents)) {
00386 UpdateList(this->oldEntries, ents, toDelete, exCommonNames,
00387 exUncommonNames, packMask, reMap, unlazyTag);
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 UpdateList(this->oldEntries, chkpt.newUncommon, toDelete,
00400 (BitVector *)NULL, &commonNames,
00401 packMask, reMap, unlazyTag);
00402 }
00403
00404 void SPKFile::UpdateList( CFPEntryMap &cfpTbl,
00405 const CE::List *ents, const BitVector *toDelete,
00406 const BitVector *exCommonNames, const BitVector *exUncommonNames,
00407 const BitVector *packMask, const IntIntTblLR *reMap, bool unlazyTag)
00408 throw ()
00409
00410 {
00411 for (; ents != (CE::List *)NULL; ents = ents->Tail()) {
00412 CE::T *ce = ents->Head();
00413 if ((toDelete == (BitVector *)NULL) || !(toDelete->Read(ce->CI()))) {
00414
00415
00416
00417 FP::Tag *commonFP = ce->CombineFP(commonNames);
00418
00419
00420 ce->Update(exCommonNames, exUncommonNames, packMask, reMap);
00421
00422
00423 if (unlazyTag) ce->UnlazyUncommonFP();
00424
00425
00426 AddEntryToTable(cfpTbl, *commonFP, ce);
00427 }
00428 }
00429 }
00430
00431 void SPKFile::AddEntryToTable( CFPEntryMap &cfpTbl,
00432 const FP::Tag &cfp, CE::T *ce) const throw ()
00433 {
00434 CE::List *curr;
00435 if (!cfpTbl.Get(cfp, curr)) {
00436 curr = (CE::List *)NULL;
00437 }
00438 curr = NEW_CONSTR(CE::List, (ce, curr));
00439 (void)cfpTbl.Put(cfp, curr);
00440 }
00441
00442
00443
00444
00445 CE::T* SPKFile::Lookup(ifstream &ifs, streampos origin,
00446 int version, const FP::Tag &commonTag, const FP::List &fps)
00447 throw (FS::EndOfFile, FS::Failure)
00448
00449 {
00450
00451 assert(FS::Posn(ifs) == origin);
00452
00453
00454 SPKFileRep::Header hdr(ifs, origin, version, false);
00455
00456
00457 streampos offset = LookupCFP(ifs, origin, version, commonTag, hdr);
00458 if (offset < 0) return (CE::T *)NULL;
00459 FS::Seek(ifs, origin + offset);
00460
00461
00462 CE::T *res;
00463 if (version <= SPKFileRep::SourceFuncVersion) {
00464 res = LookupEntryV1(ifs, fps);
00465 } else {
00466
00467 assert(false);
00468 }
00469 return res;
00470 }
00471
00472
00473 streampos SPKFile::LookupCFP(ifstream &ifs, streampos origin,
00474 int version, const FP::Tag &cfp, const SPKFileRep::Header &hdr)
00475 throw (FS::EndOfFile, FS::Failure)
00476
00477 {
00478 streampos res;
00479 switch (hdr.type) {
00480 case SPKFileRep::HT_List:
00481 if (version <= SPKFileRep::SourceFuncVersion) {
00482 res = LookupCFPInListV1(ifs, origin, cfp, hdr.num);
00483 } else {
00484
00485 assert(false);
00486 }
00487 break;
00488 case SPKFileRep::HT_SortedList:
00489 if (version <= SPKFileRep::SourceFuncVersion) {
00490 res = LookupCFPInSortedListV1(ifs, origin, cfp, hdr.num);
00491 } else {
00492
00493 assert(false);
00494 }
00495 break;
00496 case SPKFileRep::HT_HashTable:
00497 case SPKFileRep::HT_PerfectHashTable:
00498
00499 assert(false);
00500 default:
00501 assert(false);
00502 }
00503 return res;
00504 }
00505
00506
00507 streampos SPKFile::LookupCFPInListV1(ifstream &ifs, streampos origin,
00508 const FP::Tag &cfp, int num) throw (FS::EndOfFile, FS::Failure)
00509
00510 {
00511 for (int i = 0; i < num; i++) {
00512 SPKFileRep::HeaderEntry he(ifs, origin);
00513 if (he.cfp == cfp) {
00514
00515 return he.offset;
00516 }
00517 }
00518 return (-1);
00519 }
00520
00521
00522 streampos SPKFile::LookupCFPInSortedListV1(ifstream &ifs, streampos origin,
00523 const FP::Tag &cfp, int num) throw (FS::EndOfFile, FS::Failure)
00524
00525 {
00526
00527 int lo = 0, hi = num;
00528 streampos base = FS::Posn(ifs);
00529 while (lo < hi) {
00530
00531
00532
00533
00534
00535 int mid = (lo + hi) / 2;
00536 assert(lo <= mid && mid < hi);
00537 FS::Seek(ifs, (base +
00538 (streampos) (mid * SPKFileRep::HeaderEntry::Size())));
00539 SPKFileRep::HeaderEntry midEntry(ifs, origin);
00540
00541
00542 int cmp = Compare(cfp, midEntry.cfp);
00543 if (cmp < 0) {
00544
00545 hi = mid;
00546 } else if (cmp > 0) {
00547
00548 lo = mid + 1;
00549 } else {
00550 return (streampos)(midEntry.offset);
00551 }
00552 }
00553 return (-1);
00554 }
00555
00556
00557 CE::T* SPKFile::LookupEntryV1(ifstream &ifs, const FP::List &fps)
00558 throw (FS::EndOfFile, FS::Failure)
00559
00560 {
00561
00562 SPKFileRep::UShort numEntries;
00563 FS::Read(ifs, (char *)(&numEntries), sizeof(numEntries));
00564
00565
00566 for (int i = 0; i < numEntries; i++) {
00567
00568 CE::T *ce = NEW_CONSTR(CE::T, (ifs));
00569 assert(ce->UncommonFPIsUnlazied());
00570
00571
00572 if (ce->FPMatch(fps)) {
00573 return ce;
00574 }
00575 }
00576 return (CE::T *)NULL;
00577 }
00578
00579
00580
00581 void SPKFile::Read(ifstream &ifs, streampos origin, int version,
00582 SPKFileRep::Header* &hdr, bool readEntries, bool readImmutable)
00583 throw (FS::EndOfFile, FS::Failure)
00584
00585 {
00586
00587 assert(FS::Posn(ifs) == origin);
00588
00589
00590 if (readEntries) {
00591
00592 hdr = NEW_CONSTR(SPKFileRep::Header,
00593 (ifs, origin,
00594 version, true));
00595 } else {
00596 hdr = (SPKFileRep::Header *)NULL;
00597 SPKFileRep::Header::Skip(ifs, origin, version);
00598 }
00599
00600
00601 if (version >= SPKFileRep::SourceFuncVersion) {
00602 Text *temp = NEW(Text);
00603 TextIO::Read(ifs, *temp);
00604 this->sourceFunc = temp;
00605 if (this->sourceFunc->Length() == 0) this->sourceFunc = (Text *)NULL;
00606 } else {
00607 this->sourceFunc = (Text *)NULL;
00608 }
00609 FS::Read(ifs, (char *)(&(this->pkEpoch)), sizeof(this->pkEpoch));
00610 FS::Read(ifs, (char *)(&(this->namesEpoch)), sizeof(this->namesEpoch));
00611 CompactFV::List compactFV(ifs);
00612 this->allNames.Grow( compactFV.num + 5);
00613 compactFV.ToFVList( this->allNames);
00614 this->commonNames.Read(ifs);
00615
00616
00617 if (readEntries) {
00618
00619 for (int i = 0; i < hdr->num; i++) {
00620
00621 assert(FS::Posn(ifs) == origin + (streampos) hdr->entry[i].offset);
00622
00623
00624 CE::List *entryList = this->ReadEntries(ifs, readImmutable);
00625
00626
00627 bool inTbl = this->oldEntries.Put(hdr->entry[i].cfp, entryList);
00628 assert(!inTbl);
00629 }
00630 }
00631 }
00632
00633 CE::List *SPKFile::ReadEntries(ifstream &ifs, bool readImmutable)
00634 throw (FS::EndOfFile, FS::Failure)
00635
00636 {
00637
00638 SPKFileRep::UShort numEntries;
00639 FS::Read(ifs, (char *)(&numEntries), sizeof(numEntries));
00640
00641
00642
00643
00644
00645 CE::T *entry;
00646 CE::List *head = (CE::List *)NULL, *prev, *curr;
00647
00648
00649 for (int i = 0; i < numEntries; i++) {
00650 entry = NEW_CONSTR(CE::T, (ifs, readImmutable));
00651 curr = NEW_CONSTR(CE::List, (entry, (CE::List *)NULL));
00652 if (head == (CE::List *)NULL)
00653 head = curr;
00654 else
00655 prev->SetTail(curr);
00656 prev = curr;
00657 }
00658
00659
00660 for (curr = head; curr != (CE::List *)NULL; curr = curr->Tail()) {
00661 curr->Head()->ReadExtras(ifs);
00662 }
00663 return head;
00664 }
00665
00666 void SPKFile::Write(ifstream &ifs, ostream &ofs, streampos origin,
00667 SPKFileRep::Header* &hdr) const
00668 throw (FS::Failure)
00669
00670 {
00671
00672 FP::Tag key;
00673 CE::List *entryList;
00674
00675
00676 hdr = NEW(SPKFileRep::Header);
00677 hdr->num = this->oldEntries.Size();
00678 hdr->entry = NEW_ARRAY(SPKFileRep::HeaderEntry, hdr->num);
00679 CFPEntryIter it(&(this->oldEntries));
00680 int i;
00681 for (i = 0; it.Next( key, entryList); i++) {
00682 assert(i < hdr->num);
00683 hdr->entry[i].cfp = key;
00684 }
00685
00686
00687 hdr->Write(ofs, origin);
00688
00689
00690 const Text *t = (this->sourceFunc != (Text *)NULL)
00691 ? this->sourceFunc : NEW(Text);
00692 TextIO::Write(ofs, *t);
00693 FS::Write(ofs, (char *)(&(this->pkEpoch)), sizeof(this->pkEpoch));
00694 FS::Write(ofs, (char *)(&(this->namesEpoch)), sizeof(this->namesEpoch));
00695 try
00696 {
00697 CompactFV::List compactFV(this->allNames);
00698 compactFV.Write(ofs);
00699 }
00700
00701
00702
00703
00704
00705 catch(PrefixTbl::Overflow)
00706 {
00707 Debug::Lock();
00708
00709 cerr << Debug::Timestamp()
00710 << "INTERNAL ERROR: "
00711 << "PrefixTbl overflow in writing free variables to "
00712 << "stable PKFile:" << endl
00713 << " pk = " << pk << endl
00714 << " sourceFunc = " << ((this->sourceFunc != (Text *)NULL)
00715 ? this->sourceFunc->cchars()
00716 : "<UNKNOWN>") << endl
00717 << "(This means you've exceeded internal limits of the" << endl
00718 << "cache server, and you may have to erase your cache.)" << endl;
00719
00720 Debug::Unlock();
00721
00722
00723
00724 abort();
00725 }
00726 this->commonNames.Write(ofs);
00727
00728
00729 for (i = 0; i < hdr->num; i++) {
00730 SPKFileRep::HeaderEntry *entryPtr = &(hdr->entry[i]);
00731 entryPtr->offset = FS::Posn(ofs) - origin;
00732 bool inTbl = this->oldEntries.Get(entryPtr->cfp, entryList);
00733 assert(inTbl);
00734 WriteEntries(ifs, ofs, entryList);
00735 }
00736 }
00737
00738 void SPKFile::WriteEntries(ifstream &ifs, ostream &ofs, CE::List *entryList)
00739 const throw (FS::Failure)
00740
00741 {
00742
00743 SPKFileRep::UShort numEntries = CE::List::Length(entryList);
00744 FS::Write(ofs, (char *)(&numEntries), sizeof(numEntries));
00745
00746
00747 CE::List *curr;
00748 for (curr = entryList; curr != NULL; curr = curr->Tail()) {
00749 {
00750 unsigned int missing;
00751 if(curr->Head()->CheckUsedNames(&(this->commonNames), missing))
00752 {
00753 Debug::Lock();
00754
00755 cerr << Debug::Timestamp()
00756 << "INTERNAL ERROR: "
00757 << "Detected incorrect commonNames|uncommonNames:" << endl
00758 << " pk = " << pk << endl
00759 << " ci = " << curr->Head()->CI() << endl
00760 << " missing name = " << missing << endl << endl
00761 << " (Please report this as a bug.)" << endl;
00762
00763 Debug::Unlock();
00764
00765
00766
00767 abort();
00768 }
00769 }
00770
00771 curr->Head()->Write(ofs, &ifs);
00772 }
00773
00774
00775 for (curr = entryList; curr != NULL; curr = curr->Tail()) {
00776 curr->Head()->WriteExtras(ofs);
00777 }
00778 }
00779
00780 static void SPKFile_WriteBanner(ostream &os, char c, int width) throw ()
00781 {
00782 os << "// "; width -= 3;
00783 for (int i = 0; i < width; i++) os << c;
00784 os << endl;
00785 }
00786
00787 void SPKFile::Debug(ostream &os, const SPKFileRep::Header &hdr,
00788 streampos origin, bool verbose) const throw ()
00789 {
00790 const int BannerWidth = 75;
00791
00792
00793 os << endl;
00794 SPKFile_WriteBanner(os, '+', BannerWidth);
00795 os << "// <PKFile> (offset " << origin << ")" << endl;
00796 SPKFile_WriteBanner(os, '+', BannerWidth);
00797 if (!verbose) {
00798 os << endl << "pk = " << pk << endl;
00799 } else {
00800 os << "pk = " << pk << endl;
00801 }
00802
00803
00804 hdr.Debug(os, verbose);
00805 int i;
00806 for (i = 0; i < hdr.num; i++) {
00807 hdr.entry[i].Debug(os, verbose);
00808 }
00809
00810 if (verbose) {
00811
00812 os << endl << "// <PKFHeaderTail>" << endl;
00813 os << "sourceFunc = " <<
00814 ((this->sourceFunc != (Text *)NULL)
00815 ? this->sourceFunc->cchars()
00816 : "<UNKNOWN>")
00817 << endl;
00818 os << "pkEpoch = " << this->pkEpoch << endl;
00819 os << "nmsEpoch = " << this->namesEpoch << endl;
00820 os << "allNames =" << endl;
00821 this->allNames.Print(os, 2, &(this->commonNames));
00822 os << "commonNms = {" << endl;
00823 this->commonNames.PrintAll(os, 4);
00824 os << " } (" << this->commonNames.Cardinality() << " total)" << endl;
00825 }
00826
00827
00828 for (i = 0; i < hdr.num; i++) {
00829
00830 os << endl;
00831 if (verbose) {
00832 SPKFile_WriteBanner(os, '-', BannerWidth);
00833 }
00834 os << "// <PKEntries> (offset " << hdr.entry[i].offset << ")" << endl;
00835 CE::List *list;
00836 bool inTbl = this->oldEntries.Get(hdr.entry[i].cfp, list);
00837 assert(inTbl);
00838 os << "numEntries = " << CE::List::Length(list) << endl;
00839
00840 if (verbose) {
00841
00842 CE::List *curr;
00843 int i;
00844 for (curr=list, i=1; curr != NULL; curr=curr->Tail(), i++) {
00845 os << endl << "// <PKEntry> (#" << i << ")" << endl;
00846 curr->Head()->Debug(os);
00847 }
00848
00849
00850 for (curr=list, i=1; curr != NULL; curr=curr->Tail(), i++) {
00851 os << endl << "// <PKEntryExtra> (#" << i << ")" << endl;
00852 curr->Head()->DebugExtras(os);
00853 }
00854 }
00855 }
00856 }