Main Page ? Class Hierarchy ? Compound List ? File List ? Compound Members ? File Members ?

cmtshowuses.cxx

Go to the documentation of this file.
00001 
00002 #include "Package.h"
00003 #include "tree_node.h"
00004 #include "dot.h"
00005 
00006 static bool debug ()
00007 {
00008   static bool state = ::getenv ("CMTGRAPHERDEBUG");
00009 
00010   return (state);
00011 }
00012 
00013 /*
00014 void qsort ( void* base, 
00015              size_t num, 
00016              size_t width, 
00017              int (*compare)(const void* elem1, const void* elem2));
00018 */
00019 
00020 
00027 class UsesGraphBuilder : public PAwk
00028 {
00029   public:
00030 
00032   UsesGraphBuilder (const cmt_string& package,
00033                     const cmt_string& version,
00034                     const cmt_string& path)
00035   {
00036     //
00037     // A tree starting from the specified package is built.
00038     //
00039     Package& p = Package::create (package, version, path);
00040     top_node.set (0, &p);
00041   }
00042 
00043   void start (bool collapse, const cmt_string& tags)
00044   {
00045     cmt_string command = "cmt.exe show uses -use=";
00046 
00047     const Package* p = top_node.get_package ();
00048 
00049     command += p->get_name ();
00050     command += ":";
00051     command += p->get_version ();
00052     if (p->get_path () != "")
00053       {
00054         command += ":";
00055         command += p->get_path ();
00056       }
00057 
00058     if (tags != "")
00059       {
00060         command += " -tag=";
00061         command += tags;
00062       }
00063 
00064     do_collapse = collapse;
00065     m_tags = tags;
00066     
00067     run (command);
00068   }
00069 
00070   void begin ()
00071   {
00072   }
00073 
00075   void filter (const cmt_string& line)
00076   {
00077     if (debug ())
00078       {
00079         cout << "filter> [" << line << "]" << endl;
00080       }
00081 
00082     bool in_use = true;
00083 
00089     if (line[0] != '#') return;
00090 
00091     CmtSystem::cmt_string_vector words;
00092 
00093     CmtSystem::split (line, " ", words);
00094 
00095     if (words[1] == "use")
00096       {
00097         // this is a normal use specification
00098         in_use = true;
00099       }
00100     else if (words[1] == "package")
00101       {
00102         // this happens when a package is not found
00103         in_use = false;
00104       }
00105     else 
00106       {
00107         //
00108         // This should never happen but we ignore it just in case.
00109         // We only consider lines starting with
00110         //     # use ...
00111         // or  # package ...
00112         //
00113         return;
00114       }
00115 
00116     cmt_string package;
00117     cmt_string version;
00118     cmt_string path;
00119 
00120     if (words.size () > 2) package = words[2];
00121     if (words.size () > 3) version = words[3];
00122     if (words.size () > 4) 
00123       {
00124         path = words[4];
00125 
00126         if ((path == "(no_version_directory)") ||
00127             (path == "(private)") ||
00128             (path == "(no_auto_imports)") ||
00129             (path.find ("(native_version=" == 0)))
00130           {
00131             path = "";
00132           }
00133       }
00134 
00135     if (package == "CMT") path = "";
00136 
00137     Package& p = Package::create (package, version, path);
00138 
00139     for (int i = 2; i < words.size (); ++i)
00140       {
00141         const cmt_string& w = words[i];
00142 
00143         if (w == "(no_version_directory)")
00144           {
00145             p.set_has_version_directory (false);
00146           }
00147         else if (w == "(private)")
00148           {
00149             p.set_is_public (false);
00150           }
00151         else if (w == "(no_auto_imports)")
00152           {
00153             p.set_auto_imports (false);
00154           }
00155         else if (w.find ("(native_version=") == 0)
00156           {
00157           }
00158       }
00159 
00160     p.set_done ();
00161 
00162     tree_node* current_node = &top_node;
00163 
00164     if (debug ())
00165       {
00166         cout << "filter> 1-current_node=" << current_node->get_name () << endl;
00167       }
00168 
00169     if (in_use)
00170       {
00171         //
00172         // count the number of spaces before "use"
00173         //   . the usual syntax from cmt show uses starts with "# "
00174         //   . then each sublevel is indented by 2 spaces
00175         // deduce from it the level in the tree
00176         //
00177 
00178         int level = line.find ("use");
00179         level -= 2;
00180         level /= 2;
00181 
00182         //
00183         // move down the tree. At each level, we consider the last entry (ie. back ())
00184         // since indentation is always relative to the current package.
00185         //
00186         for (int i = 0; i < level; i++)
00187           {
00188             tree_node* n = current_node->get_last_sub_node ();
00189             if (n != 0)
00190               {
00191                 current_node = n;
00192 
00193                 if (debug ())
00194                   {
00195                     cout << "filter> 2-current_node=" << current_node->get_name () << endl;
00196                   }
00197               }
00198             else
00199               {
00200                 break;
00201               }
00202           }
00203       }
00204 
00205     if (debug ())
00206       {
00207         cout << "filter> 3-current_node=" << current_node->get_name () << endl;
00208       }
00209 
00215     if (current_node->check_cycle (p))
00216       {
00217         cout << "cycle detected between packages " << 
00218             current_node->get_name () <<
00219             " and " << p.get_name () << endl;
00220           //return;
00221       }
00222 
00228     current_node->install_as_reference_node ();
00229 
00230     current_node->append (p);
00231 
00232     if (!in_use)
00233       {
00234         //
00235         // This package is specified in the use list but not reachable
00236         //
00237 
00238         p.set_unreachable ();
00239         return;
00240       }
00241 
00242     if (package == "CMT") cmt = &p;
00243   }
00244 
00245   tree_node& get_top_node ()
00246   {
00247     return (top_node);
00248   }
00249 
00253   void end ()
00254   {
00255     DotGenerator generator;
00256 
00257     generator.run (top_node, "forward", do_collapse, m_tags);
00258   }
00259 
00260 
00261   private:
00262   tree_node top_node;
00263   Package* cmt;
00264   bool do_collapse;
00265   cmt_string m_tags;
00266 };
00267 
00268 int main (int argc, char* argv[])
00269 {
00270   bool collapse = false;
00271   cmt_string tags;
00272   
00273   if (argc < 3) 
00274     {
00275       cerr << "cmtshowuses.exe [-collapse]   [] " << endl;
00276       return (1);
00277     }
00278   
00279   cmt_string option;
00280   cmt_string p;
00281   cmt_string v;
00282   cmt_string pp;
00283 
00284   for (;;)
00285     {
00286       option = argv[1];
00287       if (option[0] == '-')
00288         {
00289           if (option == "-collapse")
00290             {
00291               collapse = true;
00292               argv++;
00293               argc--;
00294             }
00295           else if (option.substr (0, 5) == "-tag=")
00296             {
00297               option.erase (0, 5);
00298               tags = option;
00299 
00300               argv++;
00301               argc--;
00302             }
00303         }
00304       else
00305         {
00306           p = argv[1];
00307           v = argv[2];
00308           if (argc >= 3) pp = argv[3];
00309 
00310           break;
00311         }
00312     }
00313   
00314   UsesGraphBuilder builder (p, v, pp);
00315   
00316   builder.start (collapse, tags);
00317   
00318   return (0);
00319 }
00320 

Generated at Fri Apr 12 16:18:11 2002 for cmtgrapher by 1.2.3 written by , ??1997-2000