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