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
00015
00016
00017
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
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
00098 in_use = true;
00099 }
00100 else if (words[1] == "package")
00101 {
00102
00103 in_use = false;
00104 }
00105 else
00106 {
00107
00108
00109
00110
00111
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
00173
00174
00175
00176
00177
00178 int level = line.find ("use");
00179 level -= 2;
00180 level /= 2;
00181
00182
00183
00184
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
00221 }
00222
00228 current_node->install_as_reference_node ();
00229
00230 current_node->append (p);
00231
00232 if (!in_use)
00233 {
00234
00235
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