00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include
00015 #include
00016 #include
00017
00018 #include "cmt_triggers.h"
00019 #include "cmt_std.h"
00020 #include "cmt_string.h"
00021 #include "cmt_system.h"
00022 #include "cmt_awk.h"
00023 #include "cmt_use.h"
00024 #include "cmt_symbol.h"
00025 #include "cmt_constituent.h"
00026 #include "cmt_syntax.h"
00027
00028
00029 class Libmap
00030 {
00031 public:
00032 typedef cmt_vector LibmapVector;
00033
00034 static Libmap& find (const cmt_string& name, const cmt_string& package);
00035 static Libmap& add (const cmt_string& name, const cmt_string& package);
00036 static LibmapVector& libmaps ();
00037 static Libmap& find_with_trigger (const cmt_string& name);
00038 static Libmap& null ();
00039
00040 public:
00041 Libmap ();
00042
00043 void add_trigger (const cmt_string& trigger_name);
00044 void add_use (const cmt_string& use_name);
00045 int operator != (const Libmap& other) const;
00046 int operator == (const Libmap& other) const;
00047 void set_used ();
00048
00049 cmt_string name;
00050 cmt_string package;
00051 CmtSystem::cmt_string_vector triggers;
00052 bool used;
00053 CmtSystem::cmt_string_vector uses;
00054 };
00055
00056
00057
00058 Libmap& Libmap::find (const cmt_string& name, const cmt_string& package)
00059 {
00060 LibmapVector& table = libmaps ();
00061
00062 for (int i = 0; i < table.size (); i++)
00063 {
00064 Libmap& libmap = table[i];
00065
00066 #ifdef USE_PACKAGE_SCOPE
00067 if ((name == libmap.name) &&
00068 (package == libmap.package)) return (libmap);
00069 #else
00070 if (name == libmap.name) return (libmap);
00071 #endif
00072 }
00073
00074 return (null ());
00075 }
00076
00077 Libmap& Libmap::add (const cmt_string& name, const cmt_string& package)
00078 {
00079 {
00080 Libmap& libmap = find (name, package);
00081
00082 if (libmap != null ()) return (libmap);
00083 }
00084
00085 LibmapVector& table = libmaps ();
00086
00087 Libmap& libmap = table.add ();
00088
00089 libmap.name = name;
00090 libmap.package = package;
00091
00092 return (libmap);
00093 }
00094
00095 Libmap::LibmapVector& Libmap::libmaps ()
00096 {
00097 static cmt_vector table;
00098
00099 return (table);
00100 }
00101
00102 Libmap::Libmap () : used (false)
00103 {
00104 }
00105
00106 void Libmap::add_trigger (const cmt_string& trigger_name)
00107 {
00108 cmt_string& trigger = triggers.add ();
00109
00110 trigger = trigger_name;
00111 }
00112
00113 void Libmap::add_use (const cmt_string& use_name)
00114 {
00115 cmt_string& use = uses.add ();
00116
00117 use = use_name;
00118 }
00119
00120 Libmap& Libmap::find_with_trigger (const cmt_string& name)
00121 {
00122 LibmapVector& table = libmaps ();
00123
00124 for (int i = 0; i < table.size (); i++)
00125 {
00126 Libmap& libmap = table[i];
00127
00128 for (int j = 0; j < libmap.triggers.size (); j++)
00129 {
00130 const cmt_string& trigger = libmap.triggers[j];
00131
00132 if (name == trigger) return (libmap);
00133 }
00134 }
00135
00136 return (null ());
00137 }
00138
00139 Libmap& Libmap::null ()
00140 {
00141 static Libmap null_libmap;
00142
00143 return (null_libmap);
00144 }
00145
00146 int Libmap::operator != (const Libmap& other) const
00147 {
00148 return (this != &other);
00149 }
00150
00151 int Libmap::operator == (const Libmap& other) const
00152 {
00153 return (this == &other);
00154 }
00155
00156 void Libmap::set_used ()
00157 {
00158 if (used) return;
00159
00160 used = true;
00161
00162 cmt_string package_name;
00163 cmt_string use_name;
00164
00165 for (int i = 0; i < uses.size (); i++)
00166 {
00167 const cmt_string& use = uses[i];
00168
00169 int pos = use.find ("::");
00170
00171 if (pos == cmt_string::npos)
00172 {
00173 package_name = "";
00174 use_name = use;
00175 }
00176 else
00177 {
00178 use.substr (0, pos, package_name);
00179 use.substr (pos + 2, use_name);
00180
00181 Libmap& libmap = find (use_name, package_name);
00182 if (libmap != null ())
00183 {
00184 libmap.set_used ();
00185 }
00186 }
00187 }
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 class TriggerAnalyzer : public FAwk
00223 {
00224 public:
00225 TriggerAnalyzer (const cmt_string& package_name);
00226 void begin ();
00227 void filter (const cmt_string& line);
00228 void end ();
00229
00230 private:
00231 cmt_string package;
00232 };
00233
00234
00235
00236 TriggerAnalyzer::TriggerAnalyzer (const cmt_string& package_name) :
00237 package (package_name)
00238 {
00239 }
00240
00241 void TriggerAnalyzer::begin ()
00242 {
00243 }
00244
00245 void TriggerAnalyzer::filter (const cmt_string& line)
00246 {
00247 int pos = line.find ("=");
00248 if (pos == 0)
00249 {
00250 if (!Cmt::get_quiet ())
00251 {
00252 cerr << "Syntax error in trigger file : empty name" << endl;
00253 }
00254 exit (0);
00255 }
00256 if (pos == cmt_string::npos)
00257 {
00258 if (!Cmt::get_quiet ())
00259 {
00260 cerr << "Syntax error in trigger file : no = sign" << endl;
00261 }
00262 exit (0);
00263 }
00264
00265 cmt_string name;
00266 cmt_string text;
00267 CmtSystem::cmt_string_vector words;
00268
00269 line.substr (0, pos, name);
00270 line.substr (pos + 1, text);
00271 CmtSystem::split (text, " ", words);
00272
00273 if (name.find ("_triggers") != cmt_string::npos)
00274 {
00275 name.replace ("_triggers", "");
00276
00277 Libmap& libmap = Libmap::add (name, package);
00278
00279 for (int i = 0; i < words.size (); i++)
00280 {
00281 const cmt_string& w = words[i];
00282 libmap.add_trigger (w);
00283 }
00284 }
00285 else if (name.find ("_implied_libraries") != cmt_string::npos)
00286 {
00287 name.replace ("_implied_libraries", "");
00288
00289 Libmap& libmap = Libmap::add (name, package);
00290
00291 for (int i = 0; i < words.size (); i++)
00292 {
00293 const cmt_string& w = words[i];
00294 libmap.add_use (w);
00295 }
00296 }
00297 else
00298 {
00299 if (!Cmt::get_quiet ())
00300 {
00301 cerr << "Syntax error in trigger file : bad keyword (" <<
00302 name << ")" << endl;
00303 }
00304 exit (0);
00305 }
00306 }
00307
00308 void TriggerAnalyzer::end ()
00309 {
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 class DependencyAnalyzer : public FAwk
00348 {
00349 public:
00350 DependencyAnalyzer (const cmt_string& package_name,
00351 Constituent& constituent_ref);
00352 void begin ();
00353 void filter (const cmt_string& line);
00354 virtual void end ();
00355
00356 protected:
00357
00358 void add_trigger (const cmt_string& name);
00359 void add_use (Libmap& libmap);
00360
00361 CmtSystem::cmt_string_vector include_dirs;
00362 cmt_vector uses;
00363 CmtSystem::cmt_string_vector triggers;
00364 Constituent& constituent;
00365 cmt_string package;
00366 cmt_string package_upper;
00367 };
00368
00369 class LibraryAnalyzer : public DependencyAnalyzer
00370 {
00371 public:
00372 LibraryAnalyzer (const cmt_string& package_name,
00373 Constituent& constituent_ref);
00374 void end ();
00375 };
00376
00377 class ApplicationAnalyzer : public DependencyAnalyzer
00378 {
00379 public:
00380 ApplicationAnalyzer (const cmt_string& package_name,
00381 Constituent& constituent_ref);
00382 void end ();
00383 };
00384
00385
00386
00387 DependencyAnalyzer::DependencyAnalyzer (const cmt_string& package_name,
00388 Constituent& constituent_ref) :
00389 package (package_name),
00390 constituent (constituent_ref)
00391 {
00392 cmt_string dirs;
00393
00394 int pos;
00395 char c;
00396
00397 package_upper = package;
00398
00399 for (pos = 0; pos < package_upper.size (); pos++)
00400 {
00401 c = package_upper[pos];
00402 package_upper[pos] = toupper (c);
00403 }
00404
00405 CmtSystem::execute ("cmt show include_dirs", dirs);
00406 dirs.replace_all ("\n", "");
00407 CmtSystem::split (dirs, " ", include_dirs);
00408 }
00409
00410 void DependencyAnalyzer::begin ()
00411 {
00412 }
00413
00414 void DependencyAnalyzer::filter (const cmt_string& line)
00415 {
00416
00417 int pos = line.find ("=");
00418 if ((pos == 0) || (pos == cmt_string::npos))
00419 {
00420 if (!Cmt::get_quiet ())
00421 {
00422 cerr << " ERROR: Syntax in dependency file: " << line << endl;
00423 cerr << " Missing = or target name." << endl;
00424 }
00425 exit (1);
00426 }
00427
00428 cmt_string module;
00429
00430 line.substr (0, pos, module);
00431 module.trim ();
00432 module.replace ("_dependencies", "");
00433
00434 if (module == "cmt_path_make") return;
00435
00436 int underscore = module.find_last_of ("_");
00437
00438 if (underscore != cmt_string::npos)
00439 {
00440 module[underscore] = '.';
00441 }
00442
00443 static cmt_string dependencies;
00444
00445 line.substr (pos + 1, dependencies);
00446
00447 if (dependencies == "")
00448 {
00449 cerr << "#CMT> Warning: It seems there is nothing after \'=\' "
00450 "in dependency file " << m_file_name << endl;
00451 return;
00452 }
00453
00454 CmtSystem::cmt_string_vector deps;
00455
00456 CmtSystem::split (dependencies, " ", deps);
00457
00458 for (int i = 0; i < deps.size (); i++)
00459 {
00460 const cmt_string& dep = deps[i];
00461
00462
00463
00464
00465
00466
00467
00468
00469 if (dep.find (module) != cmt_string::npos)
00470 {
00471
00472 }
00473 else
00474 {
00475 bool found = false;
00476
00477 for (int j = 0; j < include_dirs.size (); j++)
00478 {
00479 const cmt_string& dir = include_dirs[j];
00480
00481 if (dep.find (dir) == 0)
00482 {
00483
00484
00485 cmt_string name = dep;
00486
00487 if (dir == "$(src)")
00488 {
00489 cmt_string new_dir;
00490
00491 new_dir = "$(";
00492 new_dir += package_upper;
00493 new_dir += "ROOT)/src/";
00494
00495 name.replace (dir, new_dir);
00496 }
00497
00498 if (CmtSystem::file_separator () == '\\')
00499 {
00500 name.replace_all (CmtSystem::file_separator (), "/");
00501 }
00502
00503 Libmap& libmap = Libmap::find_with_trigger (name);
00504
00505 if (libmap != Libmap::null ())
00506 {
00507 add_use (libmap);
00508 }
00509 else
00510 {
00511 add_trigger (name);
00512 }
00513
00514 found = true;
00515 break;
00516 }
00517 }
00518
00519 if (!found)
00520 {
00521 cmt_string name = dep;
00522
00523 if (CmtSystem::file_separator () == '\\')
00524 {
00525 name.replace_all (CmtSystem::file_separator (), "/");
00526 }
00527
00528
00529
00530 Libmap& libmap = Libmap::find_with_trigger (name);
00531
00532 if (libmap != Libmap::null ())
00533 {
00534 add_use (libmap);
00535 }
00536 }
00537 }
00538 }
00539 }
00540
00541 void DependencyAnalyzer::end ()
00542 {
00543 }
00544
00545 void DependencyAnalyzer::add_trigger (const cmt_string& name)
00546 {
00547 for (int i = 0; i < triggers.size (); i++)
00548 {
00549 const cmt_string& trigger = triggers[i];
00550
00551 if (trigger == name) return;
00552 }
00553
00554 cmt_string& new_trigger = triggers.add ();
00555
00556 new_trigger = name;
00557 }
00558
00559 void DependencyAnalyzer::add_use (Libmap& libmap)
00560 {
00561 for (int i = 0; i < uses.size (); i++)
00562 {
00563 const Libmap& ref = *(uses[i]);
00564
00565 if (ref == libmap) return;
00566 }
00567
00568 uses.push_back (&libmap);
00569 }
00570
00571 LibraryAnalyzer::LibraryAnalyzer (const cmt_string& package_name,
00572 Constituent& constituent_ref) :
00573 DependencyAnalyzer (package_name, constituent_ref)
00574 {
00575 }
00576
00577 void LibraryAnalyzer::end ()
00578 {
00579 cmt_string macro_name;
00580 cmt_string output;
00581
00582 int i;
00583
00584 if (uses.size () > 0)
00585 {
00586 for (i = 0; i < uses.size (); i++)
00587 {
00588 Libmap& libmap = *(uses[i]);
00589
00590 libmap.set_used ();
00591 }
00592
00593 Libmap::LibmapVector& table = Libmap::libmaps ();
00594
00595 macro_name = constituent.name;
00596 macro_name += "_implied_libraries";
00597
00598 output = "macro_prepend ";
00599 output += macro_name;
00600 output += " \"";
00601 for (i = 0; i < table.size (); i++)
00602 {
00603 Libmap& libmap = table[i];
00604
00605 if (libmap.used)
00606 {
00607 #ifdef USE_PACKAGE_SCOPE
00608 output += libmap.package;
00609 output += "::";
00610 #endif
00611 output += libmap.name;
00612 output += " ";
00613 }
00614 }
00615 output += "\"";
00616
00617 SyntaxParser::parse_requirements_text (output, "", 0);
00618
00619 Symbol* macro = Symbol::find (macro_name);
00620 output = macro_name;
00621 output += "=";
00622 output += macro->build_macro_value ();
00623
00624 cout << output << endl;
00625 }
00626
00627 if (triggers.size () > 0)
00628 {
00629 macro_name = constituent.name;
00630 macro_name += "_triggers";
00631
00632 output = "macro_prepend ";
00633 output += macro_name;
00634 output += " \"";
00635 for (i = 0; i < triggers.size (); i++)
00636 {
00637 const cmt_string& trigger = triggers[i];
00638
00639 output += trigger;
00640 output += " ";
00641 }
00642 output += "\"";
00643
00644 SyntaxParser::parse_requirements_text (output, "", 0);
00645
00646 Symbol* macro = Symbol::find (macro_name);
00647 output = macro_name;
00648 output += "=";
00649 output += macro->build_macro_value ();
00650
00651 cout << output << endl;
00652 }
00653 }
00654
00655 ApplicationAnalyzer::ApplicationAnalyzer (const cmt_string& package_name,
00656 Constituent& constituent_ref) :
00657 DependencyAnalyzer (package_name, constituent_ref)
00658 {
00659 }
00660
00661 void ApplicationAnalyzer::end ()
00662 {
00663 cmt_string macro_name;
00664 cmt_string output;
00665
00666 int i;
00667
00668 if (uses.size () > 0)
00669 {
00670 for (i = 0; i < uses.size (); i++)
00671 {
00672 Libmap& libmap = *(uses[i]);
00673
00674 libmap.set_used ();
00675 }
00676
00677 Libmap::LibmapVector& table = Libmap::libmaps ();
00678
00679 macro_name = constituent.name;
00680 macro_name += "linkopts";
00681
00682 output = "macro_prepend ";
00683 output += macro_name;
00684 output += " \"";
00685 for (i = 0; i < table.size (); i++)
00686 {
00687 Libmap& libmap = table[i];
00688
00689 if (libmap.used)
00690 {
00691 output += "$(implied_library_prefix)";
00692 output += libmap.name;
00693 output += "$(implied_library_suffix) ";
00694 }
00695 }
00696 output += "\"";
00697
00698 SyntaxParser::parse_requirements_text (output, "", 0);
00699
00700 Symbol* macro = Symbol::find (macro_name);
00701 output = macro_name;
00702 output += "=";
00703 output += macro->build_macro_value ();
00704
00705 cout << output << endl;
00706 }
00707 }
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721 class UseAnalyzer
00722 {
00723 public:
00724 void run (const cmt_string& constituent);
00725 void run (const cmt_string& location,
00726 const cmt_string& package,
00727 const cmt_string& filter_out = "");
00728 };
00729
00730
00731
00732 void UseAnalyzer::run (const cmt_string& constituent)
00733 {
00734 Use* use = &(Use::current ());
00735
00736 run ("./", use->get_package_name (), constituent);
00737
00738 Use::UsePtrVector& uses = Use::get_ordered_uses ();
00739 for (int i = 0; i < uses.size (); i++)
00740 {
00741 use = uses[i];
00742
00743 cmt_string s;
00744
00745 s = use->real_path;
00746 s += CmtSystem::file_separator ();
00747 s += use->get_package_name ();
00748 s += CmtSystem::file_separator ();
00749 s += use->version;
00750 s += CmtSystem::file_separator ();
00751
00752 if (use->style == mgr_style) s += "mgr";
00753 else s += "cmt";
00754
00755 s += CmtSystem::file_separator ();
00756
00757 run (s, use->get_package_name ());
00758 }
00759 }
00760
00761 void UseAnalyzer::run (const cmt_string& location,
00762 const cmt_string& package,
00763 const cmt_string& filter_out)
00764 {
00765 static cmt_regexp expression ("[.]triggers$");
00766
00767 TriggerAnalyzer analyzer (package);
00768
00769 CmtSystem::cmt_string_vector files;
00770
00771 CmtSystem::scan_dir (location, expression, files);
00772
00773 cmt_string name;
00774
00775 for (int i = 0; i < files.size (); i++)
00776 {
00777 const cmt_string& file = files[i];
00778
00779 if (filter_out != "")
00780 {
00781 CmtSystem::basename (file, ".triggers", name);
00782 if (name == filter_out) continue;
00783 }
00784
00785 analyzer.run (file);
00786 }
00787 }
00788
00789
00790
00791
00792 void TriggerGenerator::run (const cmt_string& constituent_name)
00793 {
00794 Constituent* constituent = Constituent::find (constituent_name);
00795
00796 Use* use = &(Use::current ());
00797 cmt_string package = use->get_package_name ();
00798
00799
00800
00801
00802 UseAnalyzer use_analyzer;
00803 use_analyzer.run (constituent_name);
00804
00805 cmt_string file_name;
00806
00807 file_name = "./";
00808 file_name += constituent_name;
00809 file_name += "_dependencies.";
00810 #ifdef WIN32
00811 file_name += "nmake";
00812 #else
00813 file_name += "make";
00814 #endif
00815
00816 DependencyAnalyzer* analyzer = 0;
00817
00818 if (constituent->type == Library)
00819 {
00820 analyzer = new LibraryAnalyzer (package, *constituent);
00821 }
00822 else if (constituent->type == Application)
00823 {
00824 analyzer = new ApplicationAnalyzer (package, *constituent);
00825 }
00826 else
00827 {
00828 return;
00829 }
00830
00831 if (analyzer->run (file_name) == Awk::failed)
00832 {
00833 cerr << " File " << file_name << " not found" << endl;
00834 }
00835
00836 delete analyzer;
00837 }
00838