00001
00002 #include "idep_linkdep.h"
00003 #include "idep_namearray.h"
00004 #include "idep_nameindexmap.h"
00005 #include "idep_binrel.h"
00006 #include "idep_string.h"
00007 #include "idep_tokeniter.h"
00008 #include "idep_aliastable.h"
00009 #include "idep_aliasutil.h"
00010
00011 #include <cmath>
00012 #include <ctype.h>
00013 #include <cstring>
00014 #include <memory>
00015 #include <fstream>
00016 #ifdef USE_STRSTREAM
00017 #include <strstream>
00018 #else
00019 #include <sstream>
00020 #endif
00021 #include <iostream>
00022 #include <cassert>
00023
00024
00025 #if ( __GNUC__ < 3 )
00026 typedef int FmtFlags_t;
00027 #else
00028 typedef std::ios_base::fmtflags FmtFlags_t;
00029 #endif
00030
00031
00032
00033 static std::ostream& warn(std::ostream& ing, int index)
00034 {
00035 return ing << "Warning<" << index << ">: ";
00036 }
00037
00038 static std::ostream& err(std::ostream& orr)
00039 {
00040 return orr << "Error: ";
00041 }
00042
00043 static const char *stripDotSlash(const char *originalPath)
00044 {
00045 if (originalPath) {
00046 while ('.' == originalPath[0] && '/' == originalPath[1]) {
00047 originalPath += 2;
00048 }
00049 }
00050 return originalPath;
00051 }
00052
00053 static int isLocal(const char *dirFile)
00054 {
00055 return !strchr(dirFile, '/');
00056 }
00057
00058 static char *removeFileName(char *dirPath)
00059 {
00060 char *slash = strrchr(dirPath, '/');
00061 if (slash) {
00062 slash[1] = '\0';
00063 }
00064 else {
00065 dirPath[0] = '\0';
00066 }
00067 return dirPath;
00068 }
00069
00070 static char *removeSuffix(char *dirPath)
00071 {
00072 char *dot = strrchr(dirPath, '.');
00073 if (dot && !strchr(dot, '/')) {
00074 dot[0] = '\0';
00075 }
00076 return dirPath;
00077 }
00078
00079 static int digits(int n)
00080 {
00081 int fieldWidth = 10;
00082 assert (sizeof (long int) >= 4);
00083 long int x = 1000 * 1000 * 1000;
00084 while (fieldWidth > 1 && 0 == n / x) {
00085 --fieldWidth;
00086 x /= 10;
00087 }
00088 return fieldWidth;
00089 }
00090
00091 static double logBase2(double x)
00092 {
00093
00094
00095
00096 assert(x > 0.0);
00097 return log(x)/log(2);
00098 }
00099
00100 static double ccdBalencedBinaryTree(int n)
00101 {
00102
00103
00104
00105
00106
00107 assert(n >= 0);
00108 return (n + 1) * (logBase2(n + 1) - 1) + 1;
00109 }
00110
00111
00112
00113 struct idep_LinkDep_i {
00114 idep_NameIndexMap d_unaliases;
00115 idep_AliasTable d_aliases;
00116 idep_NameArray d_dependencyFiles;
00117
00118 idep_NameIndexMap *d_componentNames_p;
00119 idep_BinRel *d_dependencies_p;
00120 int *d_map_p;
00121 int *d_levels_p;
00122 int *d_levelNumbers_p;
00123 int *d_cycles_p;
00124 int *d_weights_p;
00125 int *d_cycleIndices_p;
00126 int d_numComponents;
00127 int d_numLevels;
00128 int d_numCycles;
00129 int d_numMembers;
00130 int d_ccd;
00131
00132 idep_LinkDep_i();
00133 ~idep_LinkDep_i();
00134
00135 int entry(const char *name, int suffixFlag);
00136 void loadDependencies(std::istream& in, int suffixFlag);
00137 void createCycleArray();
00138 int calculate(std::ostream& orr, int canonicalFlag, int suffixFlag);
00139 };
00140
00141 idep_LinkDep_i::idep_LinkDep_i()
00142 : d_componentNames_p(0)
00143 , d_dependencies_p(0)
00144 , d_map_p(0)
00145 , d_levels_p(0)
00146 , d_levelNumbers_p(0)
00147 , d_cycles_p(0)
00148 , d_weights_p(0)
00149 , d_cycleIndices_p(0)
00150 , d_numComponents(-1)
00151 , d_numLevels(-1)
00152 , d_numCycles(-1)
00153 , d_numMembers(-1)
00154 , d_ccd(-1)
00155 {
00156 }
00157
00158 idep_LinkDep_i::~idep_LinkDep_i()
00159 {
00160 delete d_componentNames_p;
00161 delete d_dependencies_p;
00162 delete [] d_map_p;
00163 delete [] d_levels_p;
00164 delete [] d_levelNumbers_p;
00165 delete [] d_cycles_p;
00166 delete [] d_weights_p;
00167 delete [] d_cycleIndices_p;
00168 }
00169
00170 int idep_LinkDep_i::entry(const char *name, int suffixFlag)
00171 {
00172 int size = strlen(name) + 1;
00173 char *buf = new char[size];
00174 memcpy(buf, name, size);
00175
00176 if (!isLocal(buf)) {
00177 removeFileName(buf);
00178 if (d_unaliases.lookup(buf) >= 0) {
00179 memcpy(buf, name, size);
00180 }
00181 }
00182
00183 if (suffixFlag) {
00184 removeSuffix(buf);
00185 }
00186
00187 const char *componentName = d_aliases.lookup(buf);
00188 if (!componentName) {
00189 const char SLASH_CHAR = '/';
00190 const char NULL_CHAR = '\0';
00191 int len = strlen(buf);
00192 int last = len - 1;
00193 if (SLASH_CHAR == buf[last]) {
00194 buf[last] = NULL_CHAR;
00195 componentName = d_aliases.lookup(buf);
00196 if (!componentName) {
00197 buf[last] = SLASH_CHAR;
00198 }
00199 }
00200 }
00201
00202 if (!componentName) {
00203 componentName = buf;
00204 }
00205
00206 int length = d_componentNames_p->length();
00207 int index = d_componentNames_p->entry(componentName);
00208 if (d_componentNames_p->length() > length) {
00209 d_dependencies_p->appendEntry();
00210 }
00211
00212 delete [] buf;
00213
00214 return index;
00215 }
00216
00217 void idep_LinkDep_i::loadDependencies(std::istream& in, int suffixFlag)
00218 {
00219 enum { INVALID_INDEX = -1 };
00220 const char NEWLINE_CHAR = '\n';
00221 int lineno = 1;
00222 int fromIndex = INVALID_INDEX;
00223 int lastTokenWasNewline = 1;
00224
00225 for (idep_TokenIter it(in); it; ++it) {
00226 if ('#' == *it()) {
00227 while (it && '\n' != *it()) {
00228 ++it;
00229 }
00230 if (!it) {
00231 continue;
00232 }
00233 }
00234
00235 if (NEWLINE_CHAR == *it()) {
00236 ++lineno;
00237 if (lastTokenWasNewline) {
00238 fromIndex = INVALID_INDEX;
00239 }
00240 lastTokenWasNewline = 1;
00241 }
00242 else {
00243 if (INVALID_INDEX == fromIndex) {
00244 fromIndex = entry(it(), suffixFlag);
00245 }
00246 else {
00247 int toIndex = entry(it(), suffixFlag);
00248 d_dependencies_p->set(fromIndex, toIndex);
00249 }
00250 lastTokenWasNewline = 0;
00251 }
00252 }
00253 }
00254
00255 void idep_LinkDep_i::createCycleArray()
00256 {
00257 assert (!d_cycles_p);
00258 assert (!d_weights_p);
00259 assert (!d_cycleIndices_p);
00260 assert (d_numComponents >= 0);
00261
00262
00263
00264 d_cycles_p = new int[d_numComponents];
00265 d_weights_p = new int[d_numComponents];
00266 d_cycleIndices_p = new int[d_numComponents];
00267
00268
00269
00270 enum { NO_CYCLE = -1 };
00271 int i;
00272 for (i = 0; i < d_numComponents; ++i) {
00273 d_cycles_p[i] = NO_CYCLE;
00274 d_weights_p[i] = 0;
00275 d_cycleIndices_p[i] = NO_CYCLE;
00276
00277
00278 }
00279
00280 d_numCycles = 0;
00281 d_numMembers = 0;
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 for (i = 0; i < d_numComponents; ++i) {
00295 if (d_cycles_p[i] >= 0) {
00296 continue;
00297 }
00298 int cycleFound = 0;
00299 d_cycles_p[i] = i;
00300 int j;
00301 for (j = i + 1; j < d_numComponents; ++j) {
00302 if (d_cycles_p[j] >= 0) {
00303 continue;
00304 }
00305 if (d_dependencies_p->get(i, j) && d_dependencies_p->get(j, i)) {
00306 cycleFound = 1;
00307 d_cycles_p[j] = i;
00308 }
00309 }
00310 if (cycleFound) {
00311 int weight = 0;
00312 for (j = i; j < d_numComponents; ++j) {
00313 if (d_cycles_p[j] == i) {
00314 ++weight;
00315 }
00316 }
00317 for (j = i; j < d_numComponents; ++j) {
00318 if (d_cycles_p[j] == i) {
00319 d_weights_p[j] = weight;
00320 }
00321 }
00322 d_numMembers += weight;
00323 ++d_numCycles;
00324 }
00325 else {
00326 d_cycles_p[i] = NO_CYCLE;
00327 }
00328 }
00329 }
00330
00331 int idep_LinkDep_i::calculate(std::ostream& orr, int canonicalFlag, int suffixFlag)
00332 {
00333 enum { IOERRR = -1 };
00334
00335
00336 delete d_componentNames_p;
00337 delete d_dependencies_p;
00338 delete [] d_map_p;
00339 delete [] d_levels_p;
00340 delete [] d_levelNumbers_p;
00341 delete [] d_cycles_p;
00342 delete [] d_weights_p;
00343 delete [] d_cycleIndices_p;
00344
00345
00346 d_componentNames_p = new idep_NameIndexMap;
00347 d_dependencies_p = new idep_BinRel;
00348 d_map_p = 0;
00349 d_levels_p = 0;
00350 d_levelNumbers_p = 0;
00351 d_cycles_p = 0;
00352 d_numLevels = -1;
00353 d_numComponents = -1;
00354 d_numCycles = -1;
00355 d_numMembers = -1;
00356 d_ccd = -1;
00357
00358
00359
00360 int i;
00361 for (i = 0; i < d_dependencyFiles.length(); ++i) {
00362 const int INSANITY = 1000;
00363 if (d_dependencies_p->length() > INSANITY) {
00364 orr << "SANITY CHECK: Number of components is currently "
00365 << d_dependencies_p->length() << " !!!!" << std::endl;
00366
00367 }
00368 enum { IOERROR = -1 };
00369 const char *file = d_dependencyFiles[i];
00370
00371 if ('\0' == *file) {
00372 loadDependencies(std::cin, suffixFlag);
00373
00374 std::cin.clear(std::ios::iostate(0));
00375 }
00376 else {
00377 std::ifstream in(file);
00378 if (!in) {
00379 err(orr) << "dependency file \"" << file
00380 << "\" not found." << std::endl;
00381 return IOERROR;
00382 }
00383 loadDependencies(in, suffixFlag);
00384 }
00385 }
00386
00387
00388
00389 d_numComponents = d_dependencies_p->length();
00390 assert (d_componentNames_p->length() == d_numComponents);
00391
00392
00393
00394
00395 d_levels_p = new int[d_numComponents];
00396 d_numLevels = 0;
00397
00398
00399
00400
00401 d_levelNumbers_p = new int[d_numComponents];
00402
00403
00404
00405
00406 d_map_p = new int[d_numComponents];
00407 int pIndex = 0;
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 char **lowerThan = new char *[d_numComponents + 1];
00440
00441 lowerThan[0] = new char[d_numComponents];
00442 memset(lowerThan[0], 0, d_numComponents);
00443 char *current = new char[d_numComponents];
00444
00445 d_dependencies_p->makeTransitive();
00446
00447 createCycleArray();
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 for (i = 0; i < d_numComponents; ++i) {
00458 if (d_cycles_p[i] == i) {
00459 int j;
00460 for (j = i + 1; j < d_numComponents; ++j) {
00461 if (d_cycles_p[j] == i) {
00462 assert(d_dependencies_p->get(i,j));
00463 d_dependencies_p->clr(i,j);
00464 lowerThan[0][j] = 1;
00465 }
00466 }
00467 }
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 while (pIndex < d_numComponents) {
00492 int componentCount = 0;
00493 memset(current, 0, d_numComponents);
00494 int i;
00495 for (i = 0; i < d_numComponents; ++i) {
00496 if (d_cycles_p[i] >= 0 && d_cycles_p[i] != i) {
00497 continue;
00498 }
00499
00500 if (lowerThan[d_numLevels][i]) {
00501 continue;
00502 }
00503
00504 int weight = 1;
00505
00506 if (d_cycles_p[i] == i) {
00507 weight = d_weights_p[i];
00508 if (d_weights_p[i] > d_numLevels + 1) {
00509 continue;
00510 }
00511 }
00512
00513 int searchLevel = d_numLevels + 1 - weight;
00514 int j;
00515 for (j = 0; j < d_numComponents; ++j) {
00516 if (i == j) {
00517 continue;
00518 }
00519 if (d_dependencies_p->get(i,j) && !lowerThan[searchLevel][j]) {
00520 break;
00521 }
00522 }
00523 if (j < d_numComponents) {
00524 continue;
00525 }
00526 current[i] = 1;
00527 d_map_p[pIndex++] = i;
00528 ++componentCount;
00529 if (d_cycles_p[i] == i) {
00530 for (j = i + 1; j < d_numComponents; ++j) {
00531 if (d_cycles_p[j] == i) {
00532 d_map_p[pIndex++] = j;
00533 ++componentCount;
00534 d_dependencies_p->set(i,j);
00535 }
00536 }
00537 }
00538 }
00539
00540
00541 for (i = 0; i < d_numComponents; ++i) {
00542 current[i] |= lowerThan[d_numLevels][i];
00543 }
00544 d_levels_p[d_numLevels++] = componentCount;
00545 lowerThan[d_numLevels] = current;
00546 current = new char[d_numComponents];
00547 }
00548
00549 assert (pIndex == d_numComponents);
00550
00551
00552
00553 int start = 0;
00554
00555 for (i = 0; i < d_numLevels; ++i) {
00556 int top = start + d_levels_p[i];
00557 int j;
00558 for (j = start; j < top; ++j) {
00559 d_levelNumbers_p[d_map_p[j]] = i;
00560 }
00561 start = top;
00562 }
00563
00564
00565
00566
00567
00568 start = 0;
00569 int k;
00570 for (k = 0; k < d_numLevels; ++k) {
00571 int top = start + d_levels_p[k];
00572 int i;
00573 for (i = start + 1; i < top; ++i) {
00574 int j;
00575 for (j = start; j < i; ++j) {
00576 if (strcmp((*d_componentNames_p)[d_map_p[i]],
00577 (*d_componentNames_p)[d_map_p[j]]) < 0) {
00578 int tmp = d_map_p[i];
00579 d_map_p[i] = d_map_p[j];
00580 d_map_p[j] = tmp;
00581 }
00582 }
00583 }
00584 start = top;
00585 }
00586
00587
00588
00589
00590
00591 int cycleCount = 0;
00592 for (i = 0; i < d_numComponents; ++i) {
00593 const int label = d_cycles_p[d_map_p[i]];
00594 if (label < 0) {
00595 continue;
00596 }
00597
00598 const int index = d_cycleIndices_p[d_map_p[i]];
00599 if (index >= 0 && index < cycleCount) {
00600 continue;
00601 }
00602
00603
00604
00605
00606 int j;
00607 for (j = i; j < d_numComponents; ++j) {
00608 if (label == d_cycles_p[d_map_p[j]]) {
00609 d_cycleIndices_p[d_map_p[j]] = cycleCount;
00610 }
00611 }
00612
00613 ++cycleCount;
00614 }
00615
00616 assert(cycleCount == d_numCycles);
00617
00618
00619
00620
00621
00622
00623
00624
00625 start = 0;
00626 for (k = 0; k < d_numLevels; ++k) {
00627 int top = start + d_levels_p[k];
00628 int i;
00629 for (i = start + 1; i < top; ++i) {
00630 int j;
00631 for (j = start; j < i; ++j) {
00632 int ci = d_cycleIndices_p[d_map_p[i]];
00633 int cj = d_cycleIndices_p[d_map_p[j]];
00634 if (ci < cj || ci == cj &&
00635 strcmp((*d_componentNames_p)[d_map_p[i]],
00636 (*d_componentNames_p)[d_map_p[j]]) < 0) {
00637 int tmp = d_map_p[i];
00638 d_map_p[i] = d_map_p[j];
00639 d_map_p[j] = tmp;
00640 }
00641 }
00642 }
00643 start = top;
00644 }
00645
00646
00647 for (i = 0; i <= d_numLevels; ++i) {
00648 delete [] lowerThan[i];
00649 }
00650 delete [] lowerThan;
00651 delete [] current;
00652
00653
00654 idep_BinRel tmp = *d_dependencies_p;
00655 for (i = 0; i < d_numComponents; ++i) {
00656 if (0 == d_levelNumbers_p[i]) {
00657 for (int j = 0; j < d_numComponents; ++j) {
00658 tmp.clr(j, i);
00659 }
00660 }
00661 else {
00662 tmp.set(i, i);
00663 }
00664 }
00665
00666 int sum = 0;
00667
00668 for (i = 0; i < d_numComponents; ++i) {
00669 for (int j = 0; j < d_numComponents; ++j) {
00670 if (tmp.get(i,j)) {
00671 ++sum;
00672 }
00673 }
00674 }
00675
00676 d_ccd = sum;
00677
00678 if (canonicalFlag) {
00679
00680
00681
00682
00683
00684
00685 idep_BinRel tmp(d_numComponents);
00686 int i;
00687 for (i = 0; i < d_numComponents; ++i) {
00688 int u = d_map_p[i];
00689 for (int j = 0; j < d_numComponents; ++j) {
00690 int v = d_map_p[j];
00691 int bit = d_dependencies_p->get(u, v);
00692 tmp.set(i, j, bit);
00693 }
00694 }
00695
00696 tmp.makeNonTransitive();
00697
00698 for (i = 0; i < d_numComponents; ++i) {
00699 int u = d_map_p[i];
00700 for (int j = 0; j < d_numComponents; ++j) {
00701 int v = d_map_p[j];
00702 int bit = tmp.get(i, j);
00703 d_dependencies_p->set(u, v, bit);
00704 }
00705 }
00706 }
00707
00708 return d_numMembers;
00709 }
00710
00711
00712
00713 idep_LinkDep::idep_LinkDep()
00714 : d_this(new idep_LinkDep_i)
00715 {
00716 }
00717
00718 idep_LinkDep::~idep_LinkDep()
00719 {
00720 delete d_this;
00721 }
00722
00723 void idep_LinkDep::addDependencyFile(const char *fileName)
00724 {
00725 d_this->d_dependencyFiles.append(fileName);
00726 }
00727
00728 const char *idep_LinkDep::addAlias(const char *alias, const char *component)
00729 {
00730 return d_this->d_aliases.add(alias, component) < 0 ?
00731 d_this->d_aliases.lookup(alias) : 0;
00732 }
00733
00734 int idep_LinkDep::readAliases(std::ostream& orr, const char *file)
00735 {
00736 return idep_AliasUtil::readAliases(&d_this->d_aliases, orr, file);
00737 }
00738
00739 void idep_LinkDep::addUnaliasDirectory(const char *dirName)
00740 {
00741 if (*dirName) {
00742 int len = strlen(dirName);
00743 if ('/' == dirName[len-1]) {
00744 const char *n = stripDotSlash(dirName);
00745 if (*n) {
00746 d_this->d_unaliases.add(n);
00747 }
00748 }
00749 else {
00750 char *buf = new char[len+2];
00751 memcpy (buf, dirName, len);
00752 buf[len] = '/';
00753 buf[len+1] = '\0';
00754 const char *n = stripDotSlash(buf);
00755 if (*n) {
00756 d_this->d_unaliases.add(n);
00757 }
00758 delete [] buf;
00759 }
00760 }
00761 }
00762
00763 int idep_LinkDep::readUnaliasDirectories(const char *file)
00764 {
00765 enum { BAD = -1, GOOD = 0 };
00766
00767 std::ifstream in(file);
00768 if (!in) {
00769 return BAD;
00770 }
00771
00772 for (idep_TokenIter it(in); it; ++it) {
00773 if ('\n' != *it()) {
00774 d_this->d_unaliases.add(it());
00775 }
00776 }
00777
00778 return GOOD;
00779 }
00780
00781 int idep_LinkDep::calculate(std::ostream& orr, int canonicalFlag, int suffixFlag)
00782 {
00783 return d_this->calculate(orr, canonicalFlag, suffixFlag);
00784 }
00785
00786 int idep_LinkDep::numComponents() const
00787 {
00788 return d_this->d_numComponents;
00789 }
00790
00791 int idep_LinkDep::numPackages() const
00792 {
00793 return numComponents() > 0 ? d_this->d_levels_p[0] : 0;
00794 }
00795
00796 int idep_LinkDep::numLocalComponents() const
00797 {
00798 return numComponents() - numPackages();
00799 }
00800
00801 int idep_LinkDep::numLevels() const
00802 {
00803 return d_this->d_numLevels - 1;
00804 }
00805
00806 int idep_LinkDep::numCycles() const
00807 {
00808 return d_this->d_numCycles;
00809 }
00810
00811 int idep_LinkDep::numMembers() const
00812 {
00813 return d_this->d_numMembers;
00814 }
00815
00816 int idep_LinkDep::ccd() const
00817 {
00818 return d_this->d_ccd;
00819 }
00820
00821 double idep_LinkDep::acd() const
00822 {
00823 return numLocalComponents() > 0 ? ccd()/(double)numLocalComponents() : 0.0;
00824 }
00825
00826 double idep_LinkDep::nccd() const
00827 {
00828 return numLocalComponents() > 0 ?
00829 ccd()/ccdBalencedBinaryTree(numLocalComponents()) : 0.0;
00830 }
00831
00832 void idep_LinkDep::printAliases(std::ostream& o) const
00833 {
00834 idep_AliasIter it(*this);
00835 if (it) {
00836 int fieldWidth = 0;
00837 {
00838 for (idep_AliasIter it(*this); it; ++it) {
00839 int len = strlen(it.fromName());
00840 if (fieldWidth < len) {
00841 fieldWidth = len;
00842 }
00843 }
00844 }
00845 o << "ALIASES:" << std::endl;
00846 for (; it; ++it) {
00847 o.width(fieldWidth);
00848 o << it.fromName() << " -> " << it.toName() << std::endl;
00849 }
00850 o << std::endl;
00851 }
00852 }
00853
00854 void idep_LinkDep::printUnaliases(std::ostream& o) const
00855 {
00856 idep_UnaliasIter it(*this);
00857 if (it) {
00858 o << "UNALIASES:" << std::endl;
00859 for (; it; ++it) {
00860 o << it() << std::endl;
00861 }
00862 o << std::endl;
00863 }
00864 }
00865
00866 void idep_LinkDep::printCycles(std::ostream& ing) const
00867 {
00868 const char *const SPACE = " ";
00869 for (idep_CycleIter cit(*this); cit; ++cit) {
00870 warn(ing, cit.cycle()) << "The following " << cit.weight()
00871 << " components are cyclically dependent:" << std::endl;
00872
00873 for (idep_MemberIter mit(cit); mit; ++mit) {
00874 ing << SPACE << mit() << std::endl;
00875 }
00876 ing << std::endl;
00877 }
00878 }
00879
00880 void idep_LinkDep::printLevels(std::ostream& o, int longFlag, int supressFlag) const
00881 {
00882 if (!supressFlag) {
00883 o << "LEVELS:" << std::endl;
00884 }
00885
00886 const char CY_LT = '<';
00887 const char CY_RT = '>';
00888
00889 int numLevelDigits = digits(numLevels() - 1);
00890 int componentNameFieldWidth = 0;
00891
00892 int numCycleDigits = digits(numCycles() - 1);
00893 int cycleFieldWidth = numCycleDigits + 2;
00894
00895 if (longFlag) {
00896 for (idep_LevelIter lit(*this); lit; ++lit) {
00897 for (idep_ComponentIter cit(lit); cit; ++cit) {
00898 int len = strlen(cit());
00899 if (componentNameFieldWidth < len) {
00900 componentNameFieldWidth = len;
00901 }
00902 }
00903 }
00904 }
00905
00906 for (idep_LevelIter lit(*this); lit; ++lit) {
00907 if (!supressFlag) {
00908 o.width(numLevelDigits);
00909 o << lit() << ". ";
00910 }
00911 int firstFlag = 1;
00912 for (idep_ComponentIter cit(lit); cit; ++cit) {
00913 if (firstFlag) {
00914 firstFlag = 0;
00915 }
00916 else {
00917 if (!supressFlag) {
00918 o.width(numLevelDigits + 2);
00919 o << "";
00920 }
00921 }
00922
00923 if (longFlag) {
00924 o.width(componentNameFieldWidth);
00925 }
00926 o << cit();
00927
00928 if (numCycles() > 0 && !supressFlag) {
00929 char field[100];
00930 #ifdef USE_STRSTREAM
00931 std::ostrstream f(field, sizeof field);
00932 #else
00933 std::ostringstream f(field);
00934 #endif
00935 f << CY_LT << cit.cycle() << CY_RT << std::ends;
00936 o.width(cycleFieldWidth);
00937 if (cit.cycle()) {
00938 FmtFlags_t oldState = o.flags();
00939 o.setf(std::ios::left, std::ios::adjustfield);
00940 o << field;
00941 o.flags(oldState);
00942 }
00943 else {
00944 o << "";
00945 }
00946 }
00947
00948 if (longFlag) {
00949 int firstFlag = 1;
00950 for (idep_DependencyIter dit(cit); dit; ++dit) {
00951 if (firstFlag) {
00952 firstFlag = 0;
00953 }
00954 else {
00955 if (!supressFlag) {
00956 o.width(numLevelDigits + 2);
00957 o << "";
00958 if (numCycles() > 0) {
00959 o.width(numCycleDigits + 2);
00960 o << "";
00961 }
00962 }
00963 o.width(componentNameFieldWidth);
00964 o << "";
00965 }
00966 o << ' ';
00967 if (!supressFlag) {
00968 o.width(numLevelDigits);
00969 o << dit.level() << ". ";
00970 }
00971 o << dit();
00972 if (dit.cycle() && !supressFlag) {
00973 o << CY_LT << dit.cycle() << CY_RT;
00974 }
00975 o << std::endl;
00976 }
00977 }
00978 o << std::endl;
00979 }
00980 o << std::endl;
00981 }
00982 }
00983
00984 inline const char *s(int n) { return (n == 1) ? "" : "s"; }
00985
00986
00987 void idep_LinkDep::printSummary(std::ostream& o) const
00988 {
00989 FmtFlags_t iostate = o.setf(std::ios::left, std::ios::adjustfield);
00990 const int FIELD_BUFFER_SIZE = 100;
00991 char field[FIELD_BUFFER_SIZE];
00992 o << "SUMMARY:" << std::endl;
00993
00994 const int N = 12;
00995 const int G = 1;
00996 const int W = 23;
00997
00998 if (numCycles() > 0) {
00999 {
01000 #ifdef USE_STRSTREAM
01001 std::ostrstream f(field, sizeof field);
01002 #else
01003 std::ostringstream f(field);
01004 #endif
01005 f.width(N);
01006 f << numCycles() << " Cycle" << s(numCycles()) << std::ends;
01007 o.width(W);
01008 o << field;
01009 }
01010 o.width(G);
01011 o << "";
01012 {
01013 #ifdef USE_STRSTREAM
01014 std::ostrstream f(field, sizeof field);
01015 #else
01016 std::ostringstream f(field);
01017 #endif
01018 f.width(N);
01019 f << numMembers() << " Members" << std::ends;
01020 o.width(W);
01021 o << field;
01022 }
01023 o << std::endl;
01024 }
01025 {
01026 #ifdef USE_STRSTREAM
01027 std::ostrstream f(field, sizeof field);
01028 #else
01029 std::ostringstream f(field);
01030 #endif
01031 f.width(N);
01032 f << numLocalComponents() << " Component"
01033 << s(numLocalComponents()) << std::ends;
01034 o.width(W);
01035 o << field;
01036 }
01037 o.width(G);
01038 o << "";
01039 {
01040 #ifdef USE_STRSTREAM
01041 std::ostrstream f(field, sizeof field);
01042 #else
01043 std::ostringstream f(field);
01044 #endif
01045 f.width(N);
01046 f << numLevels() << " Level" << s(numLevels()) << std::ends;
01047 o.width(W);
01048 o << field;
01049 }
01050 o.width(G);
01051 o << "";
01052 {
01053 #ifdef USE_STRSTREAM
01054 std::ostrstream f(field, sizeof field);
01055 #else
01056 std::ostringstream f(field);
01057 #endif
01058 f.width(N);
01059 f << numPackages() << " Package" << s(numPackages()) << std::ends;
01060 o.width(W);
01061 o << field;
01062 }
01063 o << std::endl;
01064 {
01065 #ifdef USE_STRSTREAM
01066 std::ostrstream f(field, sizeof field);
01067 #else
01068 std::ostringstream f(field);
01069 #endif
01070 f.width(N);
01071 f << ccd() << " CCD" << std::ends;
01072 o.width(W);
01073 o << field;
01074 }
01075 o.width(G);
01076 o << "";
01077 {
01078 #ifdef USE_STRSTREAM
01079 std::ostrstream f(field, sizeof field);
01080 #else
01081 std::ostringstream f(field);
01082 #endif
01083 f.width(N);
01084 f << acd() << " ACD" << std::ends;
01085 o.width(W);
01086 o << field;
01087 }
01088 o.width(G);
01089 o << "";
01090 {
01091 #ifdef USE_STRSTREAM
01092 std::ostrstream f(field, sizeof field);
01093 #else
01094 std::ostringstream f(field);
01095 #endif
01096 f.width(N);
01097 f << nccd() << " NCCD" << std::ends;
01098 o.width(W);
01099 o << field;
01100 }
01101 o << std::endl;
01102
01103 o.setf(iostate);
01104
01105 o << std::endl;
01106 }
01107
01108
01109
01110 std::ostream &operator<<(std::ostream& o, const idep_LinkDep& dep)
01111 {
01112 dep.printAliases(o);
01113 dep.printUnaliases(o);
01114 dep.printCycles(o);
01115 dep.printLevels(o, 1);
01116 dep.printSummary(o);
01117 return o;
01118 }
01119
01120
01121
01122 struct idep_AliasIter_i {
01123 idep_AliasTableIter d_iter;
01124
01125 idep_AliasIter_i(const idep_AliasTable& table);
01126 };
01127
01128 idep_AliasIter_i::idep_AliasIter_i(const idep_AliasTable& table)
01129 : d_iter(table)
01130 {
01131 }
01132
01133
01134
01135 idep_AliasIter::idep_AliasIter(const idep_LinkDep& dep)
01136 : d_this(new idep_AliasIter_i(dep.d_this->d_aliases))
01137 {
01138 }
01139
01140 idep_AliasIter::~idep_AliasIter()
01141 {
01142 delete d_this;
01143 }
01144
01145 void idep_AliasIter::operator++()
01146 {
01147 ++d_this->d_iter;
01148 }
01149
01150 idep_AliasIter::operator const void *() const
01151 {
01152 return d_this->d_iter;
01153 }
01154
01155 const char *idep_AliasIter::fromName() const
01156 {
01157 return d_this->d_iter.alias();
01158 }
01159
01160 const char *idep_AliasIter::toName() const
01161 {
01162 return d_this->d_iter.originalName();
01163 }
01164
01165
01166
01167 struct idep_UnaliasIter_i {
01168 const idep_NameIndexMap& d_array;
01169 int d_index;
01170
01171 idep_UnaliasIter_i(const idep_NameIndexMap& array);
01172 };
01173
01174 idep_UnaliasIter_i::idep_UnaliasIter_i(const idep_NameIndexMap& array)
01175 : d_array(array)
01176 , d_index(0)
01177 {
01178 }
01179
01180
01181
01182 idep_UnaliasIter::idep_UnaliasIter(const idep_LinkDep& dep)
01183 : d_this(new idep_UnaliasIter_i(dep.d_this->d_unaliases))
01184 {
01185 }
01186
01187 idep_UnaliasIter::~idep_UnaliasIter()
01188 {
01189 delete d_this;
01190 }
01191
01192
01193 void idep_UnaliasIter::operator++()
01194 {
01195 assert (*this);
01196 ++d_this->d_index;
01197 }
01198
01199 idep_UnaliasIter::operator const void *() const
01200 {
01201 return d_this->d_index < d_this->d_array.length() ? this : 0;
01202 }
01203
01204 const char *idep_UnaliasIter::operator()() const
01205 {
01206 return d_this->d_array[d_this->d_index];
01207 }
01208
01209
01210
01211 struct idep_CycleIter_i {
01212 const idep_LinkDep_i& d_dep;
01213 int d_cycleIndex;
01214 int d_componentIndex;
01215
01216 idep_CycleIter_i(const idep_LinkDep_i& dep);
01217 };
01218
01219 idep_CycleIter_i::idep_CycleIter_i(const idep_LinkDep_i& dep)
01220 : d_dep(dep)
01221 , d_cycleIndex(-1)
01222 , d_componentIndex(-1)
01223 {
01224 }
01225
01226
01227
01228 idep_CycleIter::idep_CycleIter(const idep_LinkDep& dep)
01229 : d_this(new idep_CycleIter_i(*dep.d_this))
01230 {
01231 ++*this;
01232 }
01233
01234 idep_CycleIter::~idep_CycleIter()
01235 {
01236 delete d_this;
01237 }
01238
01239 void idep_CycleIter::operator++()
01240 {
01241 assert(*this);
01242 ++d_this->d_cycleIndex;
01243 do {
01244 ++d_this->d_componentIndex;
01245 }
01246 while (*this && d_this->d_dep.d_cycleIndices_p[d_this->d_dep.d_map_p[
01247 d_this->d_componentIndex]] != d_this->d_cycleIndex);
01248 }
01249
01250 idep_CycleIter::operator const void *() const
01251 {
01252 return d_this->d_componentIndex < d_this->d_dep.d_numComponents ? this : 0;
01253 }
01254
01255 int idep_CycleIter::weight() const
01256 {
01257 return d_this->d_dep.d_weights_p[d_this->d_dep.d_map_p[
01258 d_this->d_componentIndex]];
01259 }
01260
01261 int idep_CycleIter::cycle() const
01262 {
01263 return d_this->d_cycleIndex + 1;
01264 }
01265
01266
01267
01268 struct idep_MemberIter_i {
01269 const idep_LinkDep_i& d_dep;
01270 const int d_cycleIndex;
01271 int d_index;
01272
01273 idep_MemberIter_i(const idep_CycleIter_i& iter);
01274 };
01275
01276 idep_MemberIter_i::idep_MemberIter_i(const idep_CycleIter_i& iter)
01277 : d_dep(iter.d_dep)
01278 , d_cycleIndex(iter.d_cycleIndex)
01279 , d_index(iter.d_componentIndex)
01280 {
01281 }
01282
01283
01284
01285 idep_MemberIter::idep_MemberIter(const idep_CycleIter& iter)
01286 : d_this(new idep_MemberIter_i(*iter.d_this))
01287 {
01288 }
01289
01290 idep_MemberIter::~idep_MemberIter()
01291 {
01292 delete d_this;
01293 }
01294
01295 void idep_MemberIter::operator++()
01296 {
01297 assert(*this);
01298 do {
01299 ++d_this->d_index;
01300 }
01301 while (*this && d_this->d_dep.d_cycleIndices_p[d_this->d_dep.d_map_p[
01302 d_this->d_index]] != d_this->d_cycleIndex);
01303 }
01304
01305 idep_MemberIter::operator const void *() const
01306 {
01307 return d_this->d_index < d_this->d_dep.d_numComponents ? this : 0;
01308 }
01309
01310 const char *idep_MemberIter::operator()() const
01311 {
01312 return (*d_this->d_dep.d_componentNames_p)[d_this->d_dep.d_map_p[
01313 d_this->d_index]];
01314 }
01315
01316
01317
01318 struct idep_LevelIter_i {
01319 const idep_LinkDep_i& d_dep;
01320 int d_level;
01321 int d_start;
01322
01323 idep_LevelIter_i(const idep_LinkDep_i& dep);
01324 };
01325
01326 idep_LevelIter_i::idep_LevelIter_i(const idep_LinkDep_i& dep)
01327 : d_dep(dep)
01328 , d_level(0)
01329 , d_start(0)
01330 {
01331 }
01332
01333
01334
01335 idep_LevelIter::idep_LevelIter(const idep_LinkDep& dep)
01336 : d_this(new idep_LevelIter_i(*dep.d_this))
01337 {
01338 }
01339
01340 idep_LevelIter::~idep_LevelIter()
01341 {
01342 delete d_this;
01343 }
01344
01345 void idep_LevelIter::operator++()
01346 {
01347 assert(*this);
01348 d_this->d_start += d_this->d_dep.d_levels_p[d_this->d_level++];
01349 }
01350
01351 idep_LevelIter::operator const void *() const
01352 {
01353 return d_this->d_level < d_this->d_dep.d_numLevels ? this : 0;
01354 }
01355
01356 int idep_LevelIter::operator()() const
01357 {
01358 return d_this->d_level;
01359 }
01360
01361
01362
01363
01364 struct idep_ComponentIter_i {
01365 const idep_LinkDep_i& d_dep;
01366 int d_index;
01367 int d_top;
01368
01369 idep_ComponentIter_i(const idep_LevelIter_i& iter);
01370 };
01371
01372 idep_ComponentIter_i::idep_ComponentIter_i(const idep_LevelIter_i& iter)
01373 : d_dep(iter.d_dep)
01374 , d_index(iter.d_start)
01375 , d_top(iter.d_start + iter.d_dep.d_levels_p[iter.d_level])
01376 {
01377 }
01378
01379
01380
01381 idep_ComponentIter::idep_ComponentIter(const idep_LevelIter& iter)
01382 : d_this(new idep_ComponentIter_i(*iter.d_this))
01383 {
01384 }
01385
01386 idep_ComponentIter::~idep_ComponentIter()
01387 {
01388 delete d_this;
01389 }
01390
01391 void idep_ComponentIter::operator++()
01392 {
01393 assert(*this);
01394 ++d_this->d_index;
01395 }
01396
01397 idep_ComponentIter::operator const void *() const
01398 {
01399 return d_this->d_index < d_this->d_top ? this : 0;
01400 }
01401
01402 const char *idep_ComponentIter::operator()() const
01403 {
01404 return (*d_this->d_dep.d_componentNames_p)[
01405 d_this->d_dep.d_map_p[d_this->d_index]];
01406 }
01407
01408 int idep_ComponentIter::cycle() const
01409 {
01410 return d_this->d_dep.d_cycleIndices_p[
01411 d_this->d_dep.d_map_p[d_this->d_index]] + 1;
01412 }
01413
01414
01415
01416 struct idep_DependencyIter_i {
01417 const idep_LinkDep_i& d_dep;
01418 int d_row;
01419 int d_col;
01420
01421 idep_DependencyIter_i(const idep_ComponentIter_i& iter);
01422 };
01423
01424 idep_DependencyIter_i::idep_DependencyIter_i(const idep_ComponentIter_i& iter)
01425 : d_dep(iter.d_dep)
01426 , d_row(iter.d_dep.d_map_p[iter.d_index])
01427 , d_col(-1)
01428 {
01429 }
01430
01431
01432
01433 idep_DependencyIter::idep_DependencyIter(const idep_ComponentIter& iter)
01434 : d_this(new idep_DependencyIter_i(*iter.d_this))
01435 {
01436 ++*this;
01437 }
01438
01439 idep_DependencyIter::~idep_DependencyIter()
01440 {
01441 delete d_this;
01442 }
01443
01444
01445 void idep_DependencyIter::operator++()
01446 {
01447 assert(*this);
01448 do {
01449 ++d_this->d_col;
01450 }
01451 while (*this &&
01452 !d_this->d_dep.d_dependencies_p->get(d_this->d_row,
01453 d_this->d_dep.d_map_p[d_this->d_col]));
01454 }
01455
01456 idep_DependencyIter::operator const void *() const
01457 {
01458 return d_this->d_col < d_this->d_dep.d_numComponents ? this : 0;
01459 }
01460
01461 const char *idep_DependencyIter::operator()() const
01462 {
01463 return (*d_this->d_dep.d_componentNames_p)[
01464 d_this->d_dep.d_map_p[d_this->d_col]];
01465 }
01466
01467 int idep_DependencyIter::level() const
01468 {
01469 return d_this->d_dep.d_levelNumbers_p[
01470 d_this->d_dep.d_map_p[d_this->d_col]];
01471 }
01472
01473 int idep_DependencyIter::cycle() const
01474 {
01475 return d_this->d_dep.d_cycleIndices_p[
01476 d_this->d_dep.d_map_p[d_this->d_col]] + 1;
01477 }
01478
01479
01480