00001 // idep_linkdep.h 00002 #ifndef INCLUDED_IDEP_LINKDEP 00003 #define INCLUDED_IDEP_LINKDEP 00004 00005 // This wrapper component defines 8 fully insulated classes: 00006 // idep_LinkDep: environment for analyzing link dependencies 00007 // idep_AliasIter: iterate over specified alias pairs 00008 // idep_UnaliasIter: iterate over specified unaliased directories 00009 // idep_CycleIter: iterate over cycles in the system 00010 // idep_MemberIter: iterate over members within a given cycle 00011 // idep_LevelIter: iterate over levels in the system 00012 // idep_ComponentIter: iterate over components on a given level 00013 // idep_DependencyIter: iterate over dependencies for a given component 00014 00015 #include <iosfwd> 00016 class idep_AliasIter; 00017 class idep_UnaliasIter; 00018 class idep_CycleIter; 00019 class idep_MemberIter; 00020 class idep_LevelIter; 00021 class idep_ComponentIter; 00022 class idep_DependencyIter; 00023 00024 class idep_LinkDep_i; 00025 class idep_LinkDep { 00026 idep_LinkDep_i *d_this; 00027 00028 friend class idep_AliasIter; 00029 friend class idep_UnaliasIter; 00030 friend class idep_CycleIter; 00031 friend class idep_MemberIter; 00032 friend class idep_LevelIter; 00033 friend class idep_ComponentIter; 00034 friend class idep_DependencyIter; 00035 00036 private: 00037 idep_LinkDep(const idep_LinkDep&); // not implemented 00038 idep_LinkDep& operator=(const idep_LinkDep&); // not implemented 00039 00040 public: 00041 // CREATORS 00042 idep_LinkDep(); 00043 ~idep_LinkDep(); 00044 00045 // MANIPULATORS 00046 void addDependencyFile(const char *fileName); 00047 // Add a file containing dependencies to be parsed. Parsing errors 00048 // will be reported during the calculation phase. Note that the 00049 // empty string ("") is interpreted to mean <stdin>. 00050 00051 const char *addAlias(const char *aliasName, const char *componentName); 00052 // Add an alias/component name pair to the set of aliases. This 00053 // function returns 0 on success or a character string containing 00054 // a previously corresponding component name for this alias that is 00055 // not identical to the once specified here. 00056 00057 int readAliases(std::ostream& err, const char *file); 00058 // Read a list of component aliases from the specified file. Each 00059 // contiguous sequence of non-whitespace characters represents a name. 00060 // Names are also arranged into sequences. The first name in a name 00061 // sequence represents the actual component name. Names that follow 00062 // on the same line (horizontal sequence) or subsequent lines 00063 // (vertical sequence) are interpreted as aliases for that component 00064 // name. A horizontal sequence is terminated by a newline ('\n') 00065 // unless preceded by a backslash ('\\'). A vertical sequence is 00066 // terminated by a blank line. This function quietly returns 0 on 00067 // success. If the specified file is not readable, this function 00068 // quietly returns -1. If an alias that is inconsistent with a 00069 // previously specified alias is encountered, the conflicting aliases 00070 // are identified to the err stream. After parsing is complete, the 00071 // number of offending aliases is returned as the value of this 00072 // function. 00073 00074 void addUnaliasDirectory(const char *dirName); 00075 // Add a directory _not_ to be treated as a single unit by default. 00076 // This function has no effect if the directory has already been 00077 // specified. 00078 00079 int readUnaliasDirectories(const char *file); 00080 // Add a list of unalias directories read from the specified file. 00081 // This function assumes that each contiguous sequence of 00082 // non-whitespace characters represents a directory to be added. 00083 // This function returns 0 unless the specified file is unreadable 00084 // or contains non-ascii characters. 00085 00086 int calculate(std::ostream& err,int canonicalFlag=1,int suffixFlag=0); 00087 // Calculate link-time component dependencies. This function returns 00088 // 0 on success, non-zero on error. If an io-error occurs, the result 00089 // will be negative, and this object will be left in an invalid state. 00090 // Otherwise the number of components involved in cyclic dependencies 00091 // will be returned. Specific errors will be reported to the indicated 00092 // output stream stream (err). A non-zero canocialFlag argument 00093 // request a canonical representation of the dependencies -- i.e., 00094 // containing no redundant, transitive edges. Overriding this default 00095 // behavior causes the complete (transitive) graph to remain. Also by 00096 // default, all file suffixes are removed. Passing a non-zero value 00097 // for the optional suffixFlag argument causes individual component 00098 // files to be treated as separate physical entities. 00099 00100 // ACCESSORS 00101 int numComponents() const; 00102 // Return the total number of components in the system. Note: This 00103 // number is the sum of the number of local components and the 00104 // number of external packages, and is NOT used to calculate ACD 00105 // and NCCD. 00106 00107 int numLocalComponents() const; 00108 // Return the number of (local) components -- i.e., with level > 0. 00109 // Note: it is this value that is used to calculate ACD and NCCD. 00110 00111 int numPackages() const; 00112 // Return the number of entities with a level of 0. Note a local 00113 // component that has no external dependencies at all (i.e., not even 00114 // a standard compiler library include directive) will be incorrectly 00115 // treated as a package. Adding a fictitious dependency on the 00116 // language ("C++") or the local directory (".") corrects this problem. 00117 00118 int numLevels() const; 00119 // Return the number of (local) component levels in this subsystem. 00120 // This value represent the "depth" of the (local) component 00121 // dependency graph. 00122 00123 int numCycles() const; 00124 // Return the number of local cycles in this subsystem 00125 00126 int numMembers() const; 00127 // Return the number of cyclically dependent components in this 00128 // subsystem. 00129 00130 int ccd() const; 00131 // Return the Cumulative Component Dependency (CCD) for this subsystem 00132 // assuming level 0 entities have 0 weight. 00133 00134 double acd() const; 00135 // Return the Average Component Dependency (ACD) for this subsystem 00136 // ignoring level 0 entities. 00137 00138 double nccd() const; 00139 // Return the Normalized Cumulative Component Dependency (NCCD) for 00140 // this subsystem ignoring level 0 entities. 00141 00142 void printAliases(std::ostream& out) const; 00143 // Format all aliases in this environment to the specified output 00144 // stream. 00145 00146 void printUnaliases(std::ostream& out) const; 00147 // Format all unaliases in this environment to the specified output 00148 // stream. 00149 00150 void printCycles(std::ostream& out) const; 00151 // Format all cyclically-dependent components to the specified 00152 // output stream. 00153 00154 void printLevels(std::ostream& out, int longFlag = 0, 00155 int supressFlag = 0) const; 00156 // Format all components in levelized order to the specified output 00157 // stream. If the optional longFlag argument is specified with a 00158 // value other than 0, the dependencies of each component will be 00159 // explicitly delineated. Otherwise, only the components and their 00160 // corresponding levels will be included. By default, component 00161 // levels and identifying cycle suffixes will be included in the 00162 // output. If the value of the optional supressFlag argument is 00163 // not 0, only the component names will be supplied with levels 00164 // delimited only by the extra blank line. 00165 00166 void printSummary(std::ostream& out) const; 00167 // Format statistics characterizing dependencies within this package 00168 // to the specified output stream. These statistics include 00169 // the following: 00170 // 00171 // Components The number of (local) components with a level above 00172 // 0 (i.e., the number of components with at least one 00173 // dependency). 00174 // 00175 // Levels The height of the component dependency graph. 00176 // 00177 // Packages The number of level 0 entities (i.e., the number of 00178 // entities with no dependencies). 00179 // 00180 // CCD The sum over all (local) components C(i) of the 00181 // number of (local) components required to link and 00182 // test C(i). 00183 // 00184 // ACD The ratio of the CCD to the number of (local) 00185 // components. 00186 // 00187 // NCCD The ratio of CCD to the CCD of a (theoretical) 00188 // balanced binary dependency tree with an equal 00189 // number of local components. (Note: For most 00190 // high-quality package architectures, this number 00191 // will not be much greater than 1.00). 00192 // 00193 // In the presence of cyclic component dependencies, the members of 00194 // each distinct maximal cycle are identified with a unique cycle 00195 // index enclosed in angle brackets ('<' and '>'). An additional 00196 // summary line preceding the others is formatted to the specified 00197 // output stream: 00198 // 00199 // Cycles The number of distinct maximal cycles in the 00200 // component dependency graph. 00201 // 00202 // Members The total number of components participating in 00203 // cycles. 00204 }; 00205 00206 std::ostream& operator<<(std::ostream& out, const idep_LinkDep& dep); 00207 // Format all available information in the specified environment (dep) 00208 // to the specified output stream (out) including the following: 00209 // unaliases: directories not to group 00210 // aliases: component file name mappings 00211 // cycles: maximial interdependent subgraphs 00212 // levels: components in levelized order along with dependencies 00213 // summary: statistics characterizing local component dependencies 00214 00215 class idep_AliasIter_i; 00216 class idep_AliasIter { 00217 idep_AliasIter_i *d_this; 00218 00219 private: 00220 idep_AliasIter(const idep_AliasIter&); // not implemented 00221 idep_AliasIter& operator=(const idep_AliasIter&); // not implemented 00222 00223 public: 00224 // CREATORS 00225 idep_AliasIter(const idep_LinkDep& linkDep); 00226 ~idep_AliasIter(); 00227 00228 // MANIPULATORS 00229 void operator++(); 00230 00231 // ACCESSORS 00232 operator const void *() const; 00233 const char *fromName() const; 00234 // Return current alias Name. 00235 00236 const char *toName() const; 00237 // Return corresponding actual Name. 00238 }; 00239 00240 class idep_UnaliasIter_i; 00241 class idep_UnaliasIter { 00242 idep_UnaliasIter_i *d_this; 00243 00244 private: 00245 idep_UnaliasIter(const idep_UnaliasIter&); // not implemented 00246 idep_UnaliasIter& operator=(const idep_UnaliasIter&); // not implemented 00247 00248 public: 00249 // CREATORS 00250 idep_UnaliasIter(const idep_LinkDep& linkDep); 00251 ~idep_UnaliasIter(); 00252 00253 // MANIPULATORS 00254 void operator++(); 00255 00256 // ACCESSORS 00257 operator const void *() const; 00258 const char *operator()() const; 00259 // Return current unalias (directory) name. 00260 }; 00261 00262 class idep_CycleIter_i; 00263 class idep_CycleIter { 00264 idep_CycleIter_i *d_this; 00265 00266 friend class idep_MemberIter; 00267 00268 private: 00269 idep_CycleIter(const idep_CycleIter&); // not implemented 00270 idep_CycleIter& operator=(const idep_CycleIter&); // not implemented 00271 00272 public: 00273 // CREATORS 00274 idep_CycleIter(const idep_LinkDep& linkDep); 00275 ~idep_CycleIter(); 00276 00277 // MANIPULATORS 00278 void operator++(); 00279 00280 // ACCESSORS 00281 operator const void *() const; 00282 int weight() const; 00283 // Return the number of members in the current (maximal) cycle. 00284 00285 int cycle() const; 00286 // Return the positive index of the current cycle. 00287 }; 00288 00289 class idep_MemberIter_i; 00290 class idep_MemberIter { 00291 idep_MemberIter_i *d_this; 00292 00293 private: 00294 idep_MemberIter(const idep_MemberIter&); // not implemented 00295 idep_MemberIter& operator=(const idep_MemberIter&); // not implemented 00296 00297 public: 00298 // CREATORS 00299 idep_MemberIter(const idep_CycleIter& cycleIter); 00300 ~idep_MemberIter(); 00301 00302 // MANIPULATORS 00303 void operator++(); 00304 00305 // ACCESSORS 00306 operator const void *() const; 00307 const char *operator()() const; 00308 // Return the name of the current member of the current cycle. 00309 }; 00310 00311 class idep_LevelIter_i; 00312 class idep_LevelIter { 00313 idep_LevelIter_i *d_this; 00314 00315 friend class idep_ComponentIter; 00316 00317 private: 00318 idep_LevelIter(const idep_LevelIter&); // not implemented 00319 idep_LevelIter& operator=(const idep_LevelIter&); // not implemented 00320 00321 public: 00322 // CREATORS 00323 idep_LevelIter(const idep_LinkDep& linkDep); 00324 ~idep_LevelIter(); 00325 00326 // MANIPULATORS 00327 void operator++(); 00328 00329 // ACCESSORS 00330 operator const void *() const; 00331 int operator()() const; 00332 // Return the index of the current level. 00333 }; 00334 00335 class idep_ComponentIter_i; 00336 class idep_ComponentIter { 00337 idep_ComponentIter_i *d_this; 00338 00339 friend class idep_DependencyIter; 00340 00341 private: 00342 idep_ComponentIter(const idep_ComponentIter&); // not impl. 00343 idep_ComponentIter& operator=(const idep_ComponentIter&); // not impl. 00344 00345 public: 00346 // CREATORS 00347 idep_ComponentIter(const idep_LevelIter& levelIter); 00348 ~idep_ComponentIter(); 00349 00350 // MANIPULATORS 00351 void operator++(); 00352 00353 // ACCESSORS 00354 operator const void *() const; 00355 const char *operator()() const; 00356 // Return the name of the current component on the current level. 00357 00358 int cycle() const; 00359 // return the positive index of the current cycle or 0 if acyclic. 00360 }; 00361 00362 class idep_DependencyIter_i; 00363 class idep_DependencyIter { 00364 idep_DependencyIter_i *d_this; 00365 00366 private: 00367 idep_DependencyIter(const idep_DependencyIter&); // not impl. 00368 idep_DependencyIter& operator=(const idep_DependencyIter&); // not impl. 00369 00370 public: 00371 // CREATORS 00372 idep_DependencyIter(const idep_ComponentIter& componentIter); 00373 ~idep_DependencyIter(); 00374 00375 // MANIPULATORS 00376 void operator++(); 00377 00378 // ACCESSORS 00379 operator const void *() const; 00380 const char *operator()() const; 00381 // Return the name of the current component on which the initial 00382 // component depends. 00383 00384 int level() const; 00385 // Return the level of the current component. 00386 00387 int cycle() const; 00388 // return the positive index of the current cycle or 0 if acyclic. 00389 }; 00390 00391 #endif 00392 00393 00394
1.3.9.1