00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010
00011 #include "cmt_use.h"
00012 #include "cmt_system.h"
00013 #include "cmt_symbol.h"
00014 #include "cmt_error.h"
00015 #include "cmt_database.h"
00016 #include "cmt_syntax.h"
00017
00018 static void show_packages ();
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 static bool add_request (const cmt_string& path,
00036 const cmt_string& package_name,
00037 const cmt_string& version)
00038 {
00039 static cmt_map <cmt_string, bool> requests;
00040
00041 cmt_string request = package_name;
00042 request += " ";
00043 request += version;
00044 request += " ";
00045 request += path;
00046 static bool b = true;
00047
00048 bool new_request = false;
00049
00050 if (!requests.has ((const cmt_string&) request))
00051 {
00052 new_request = true;
00053 requests.add ((const cmt_string&) request, b);
00054 }
00055
00056 return (new_request);
00057 }
00058
00059 class UseContext
00060 {
00061 public:
00062
00063 static UseContext& current ()
00064 {
00065 static UseContext me;
00066
00067 return (me);
00068 }
00069
00070 UseContext ()
00071 {
00072 m_auto_imports = On;
00073 }
00074
00075 UseContext (const UseContext& other)
00076 {
00077 m_auto_imports = other.m_auto_imports;
00078 }
00079
00080 UseContext& operator = (const UseContext& other)
00081 {
00082 m_auto_imports = other.m_auto_imports;
00083
00084 return (*this);
00085 }
00086
00087 static void set_current (State auto_imports)
00088 {
00089 UseContext& c = current ();
00090
00091 c.m_auto_imports = auto_imports;
00092 }
00093
00094 static State get_current_auto_imports ()
00095 {
00096 UseContext& c = current ();
00097
00098 return (c.m_auto_imports);
00099 }
00100
00101 private:
00102 State m_auto_imports;
00103 };
00104
00105
00106 class BestFitSelector
00107 {
00108 public:
00109 Use* operate (Use* ref_use, Use* new_use);
00110 };
00111
00112
00113
00114 typedef enum
00115 {
00116 IdenticalIds,
00117
00118 IncompatibleMajorIds,
00119 NewMajorIdGreaterThanOld,
00120 OldMajorIdGreaterThanNew,
00121 ExplicitOldMajorIdWinsAgainstWildarded,
00122 ExplicitNewMajorIdWinsAgainstWildarded,
00123
00124 ExplicitOldMinorIdWinsAgainstWildarded,
00125 ExplicitNewMinorIdWinsAgainstWildarded,
00126 NewMinorIdGreaterThanOld,
00127
00128 ExplicitOldPatchIdWinsAgainstWildarded,
00129 ExplicitNewPatchIdWinsAgainstWildarded,
00130 NewPatchIdGreaterThanOld
00131 } CompareStatus;
00132
00133 static CompareStatus compare_versions (const cmt_string& ref_version, const cmt_string& new_version)
00134 {
00135 CompareStatus result = IdenticalIds;
00136
00137 int old_v = -1;
00138 int old_r = -1;
00139 int old_p = -1;
00140
00141 int new_v = -1;
00142 int new_r = -1;
00143 int new_p = -1;
00144
00145 CmtSystem::is_version_directory (ref_version, old_v, old_r, old_p);
00146
00147 CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
00148
00149 if ((new_v != -1) && (old_v != -1) && (new_v != old_v))
00150 {
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 if (new_v > old_v)
00161 {
00162 result = NewMajorIdGreaterThanOld;
00163 }
00164 else
00165 {
00166 result = OldMajorIdGreaterThanNew;
00167 }
00168
00169 }
00170 else if ((new_v == -1) || (old_v == -1))
00171 {
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 if ((old_v == -1) && (new_v != -1))
00183 {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 result = ExplicitNewMajorIdWinsAgainstWildarded;
00194 }
00195 else
00196 {
00197
00198
00199
00200
00201
00202
00203
00204 result = ExplicitOldMajorIdWinsAgainstWildarded;
00205 }
00206 }
00207 else if ((new_r == -1) || (old_r == -1) || (new_r < old_r))
00208 {
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 if ((old_r == -1) && (new_r != -1))
00220 {
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 result = ExplicitNewMinorIdWinsAgainstWildarded;
00233 }
00234 else
00235 {
00236
00237
00238
00239
00240
00241
00242
00243 result = ExplicitOldMinorIdWinsAgainstWildarded;
00244 }
00245 }
00246 else if (new_r > old_r)
00247 {
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 result = NewMinorIdGreaterThanOld;
00258 }
00259 else if ((new_p == -1) || (old_p == -1) || (new_p < old_p))
00260 {
00261
00262
00263
00264
00265
00266
00267 if ((old_p == -1) && (new_p != -1))
00268 {
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 result = ExplicitNewPatchIdWinsAgainstWildarded;
00279 }
00280 else
00281 {
00282
00283
00284
00285
00286
00287
00288
00289 result = ExplicitOldPatchIdWinsAgainstWildarded;
00290 }
00291 }
00292 else if (new_p > old_p)
00293 {
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 result = NewPatchIdGreaterThanOld;
00304 }
00305
00306 return (result);
00307 }
00308
00309
00310
00311
00312
00313
00314
00318 void Use::select_clients (const cmt_string& package,
00319 const cmt_string& version)
00320 {
00321 static UsePtrVector& uses = get_ordered_uses ();
00322
00323 int number;
00324 Use* use = 0;
00325
00326 unselect_all ();
00327 undiscard_all ();
00328
00329 for (number = uses.size () - 1; number >= 0; number--)
00330 {
00331 use = uses[number];
00332 if (use == 0) continue;
00333 if (use->is_selected ()) continue;
00334 use->select ();
00335 if (!use->is_client (package, version)) use->discard ();
00336 }
00337 }
00338
00339
00340 void Use::show_all (bool skip_discarded)
00341 {
00342 show_all ("use ", skip_discarded);
00343 }
00344
00345
00346 void Use::show_cycles ()
00347 {
00348 static int level = 0;
00349 static UsePtrVector stack;
00350 int size = 0;
00351
00352 if (level == 0)
00353 {
00354 unselect_all ();
00355 unselect ();
00356 stack.clear ();
00357 }
00358
00359
00360
00361
00362
00363 for (int k = 0; k < level; k++)
00364 {
00365 Use* u = stack[k];
00366 if (u == this)
00367 {
00368 for (;k < level; k++)
00369 {
00370 u = stack[k];
00371 cout << u->get_package_name () << " ";
00372 }
00373
00374 cout << endl;
00375
00376 return;
00377 }
00378 }
00379
00380
00381 if (stack.size () <= level)
00382 {
00383 stack.push_back (this);
00384 }
00385 else
00386 {
00387 stack[level] = this;
00388 }
00389
00390 if (selected) return;
00391 selected = true;
00392
00393 size = sub_uses.size ();
00394 for (int n = 0; n < size; n++)
00395 {
00396 Use* use = sub_uses[n];
00397
00398 if (use == 0) continue;
00399
00400
00401
00402
00403 if (use->discarded)
00404 {
00405 Use* u;
00406
00407 u = use->get_selected_version ();
00408 if (u == 0) continue;
00409
00410 use = u;
00411 }
00412
00413 level++;
00414 use->show_cycles ();
00415 level--;
00416 }
00417 }
00418
00419
00420 void Use::push_scope_section (ScopeType type)
00421 {
00422 scope_sections.push_back (type);
00423 }
00424
00425
00426 void Use::pop_scope_section ()
00427 {
00428 scope_sections.pop_back ();
00429 }
00430
00431
00432 void Use::close_scope_sections ()
00433 {
00434 scope_sections.clear ();
00435 }
00436
00437
00438 ScopeType Use::get_current_scope () const
00439 {
00440 if (scope_sections.size () == 0) return (initial_scope);
00441 const ScopeSection& s = scope_sections.back ();
00442 return (s.get_scope ());
00443 }
00444
00445
00446 void Use::show_all (const cmt_string& prefix, bool skip_discarded)
00447 {
00448 static UsePtrVector& uses = get_ordered_uses ();
00449
00450 Use* use;
00451 int number;
00452
00453 if (Cmt::get_debug ())
00454 {
00455 cout << "use::show_all-1> ";
00456
00457 int i;
00458
00459 for (i = 0; i < uses.size (); i++)
00460 {
00461 Use* u = uses[i];
00462 cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
00463 }
00464
00465 cout << endl;
00466 }
00467
00468 unselect_all ();
00469
00470 use = &(current ());
00471 use->unselect ();
00472 if (!Cmt::get_quiet ()) use->show_sub_uses ("", skip_discarded);
00473
00474 if (uses.size () > 0)
00475 {
00476 if (!Cmt::get_quiet ())
00477 {
00478 cout << "#\n";
00479 cout << "# Selection :\n";
00480 }
00481
00482
00483
00484
00485
00486 use = Use::find ("CMT");
00487 Use::move (use);
00488
00489 for (number = uses.size () - 1; number >= 0; number--)
00490 {
00491 use = uses[number];
00492
00493 if (use->discarded) continue;
00494
00495 if (!use->located ())
00496 {
00497 if (!Cmt::get_quiet ())
00498 {
00499 cout << "# package " << use->get_package_name () <<
00500 " " << use->version << " " << use->path <<
00501 " not found" <<
00502 endl;
00503 }
00504 CmtError::set (CmtError::package_not_found, use->get_package_name ());
00505 }
00506 else
00507 {
00508 static const cmt_string empty;
00509 cmt_string p = use->real_path;
00510 if (use->path != "")
00511 {
00512 int pos = p.find_last_of (use->path);
00513 if (pos != cmt_string::npos)
00514 {
00515 p.erase (pos);
00516 }
00517 }
00518
00519 cout << prefix << use->get_package_name ()
00520 << " " << use->version;
00521
00522 if (CmtSystem::absolute_path (use->path))
00523 {
00524 if (!Cmt::get_quiet ())
00525 {
00526 cout << " (" << use->path << ")";
00527 }
00528 }
00529 else
00530 {
00531 cout << " " << use->path;
00532 }
00533
00534 if (!Cmt::get_quiet ())
00535 {
00536 if (p != "") cout << " (" << p << ")";
00537 if (use->auto_imports == Off) cout << " (no_auto_imports)";
00538 }
00539
00540 cout << endl;
00541 }
00542 }
00543
00544 if (Cmt::get_cmt_home () != "")
00545 {
00546 cout << prefix << CmtSystem::get_home_package () << " v0";
00547 if (!Cmt::get_quiet ())
00548 {
00549 cout << " (" << Cmt::get_cmt_home () << ")";
00550 }
00551 cout << endl;
00552 }
00553
00554 if (Cmt::get_cmt_user_context () != "")
00555 {
00556 cout << prefix << CmtSystem::get_user_context_package () << " v0";
00557 if (!Cmt::get_quiet ())
00558 {
00559 cout << " (" << Cmt::get_cmt_user_context () << ")";
00560 }
00561 cout << endl;
00562 }
00563 }
00564 }
00565
00572 class use_action_iterator
00573 {
00574 public:
00575
00576 use_action_iterator ()
00577 {
00578 state = need_package;
00579 auto_imports = Unspecified;
00580 }
00581
00582 void set (const cmt_string& w)
00583 {
00584 if (w == "-auto_imports")
00585 {
00586 auto_imports = On;
00587 }
00588 else if (w == "-no_auto_imports")
00589 {
00590 auto_imports = Off;
00591 }
00592 else if (w == "|")
00593 {
00594 state = need_version_alias;
00595 }
00596 else
00597 {
00598 switch (state)
00599 {
00600 case need_package:
00601 package = w;
00602 state = need_version;
00603 break;
00604 case need_version:
00605 version = w;
00606 state = need_path;
00607 break;
00608 case need_path:
00609 path = w;
00610 while (path[path.size() - 1] == '/') path.erase (path.size() - 1);
00611 while (path[path.size() - 1] == '\\') path.erase (path.size() - 1);
00612 state = finished;
00613 break;
00614 case need_version_alias:
00615 version_alias = w;
00616 state = need_path_alias;
00617 break;
00618 case need_path_alias:
00619 path_alias = w;
00620 while (path_alias[path_alias.size() - 1] == '/') path_alias.erase (path_alias.size() - 1);
00621 while (path_alias[path_alias.size() - 1] == '\\') path_alias.erase (path_alias.size() - 1);
00622 state = finished;
00623 break;
00624 }
00625 }
00626 }
00627
00628 bool ok ()
00629 {
00630 if (package == "") return (false);
00631 if (CmtSystem::is_home_package (package, version)) return (false);
00632 if (CmtSystem::is_user_context_package (package, version)) return (false);
00633 if (CmtSystem::is_project_package (package, version)) return (false);
00634
00635 return (true);
00636 }
00637
00643 Use* get_use (Use* parent)
00644 {
00645 static Use::UsePtrVector& uses = Use::get_ordered_uses ();
00646
00647 if (version == "") version = "*";
00648
00649 if (Cmt::get_debug ())
00650 {
00651 int i;
00652
00653 cout << "use::action1> current=" << parent->get_package_name () <<
00654 " package=" << package << " ";
00655
00656 for (i = 0; i < uses.size (); i++)
00657 {
00658 Use* u = uses[i];
00659 cout << u->get_package_name () << " ";
00660 }
00661 cout << endl;
00662 }
00663
00664 const Use& cu = Use::current ();
00665
00675 ActionType action = Cmt::get_action ();
00676
00677 if (Cmt::get_debug ())
00678 {
00679 cout << "before adding " << package <<"> auto_imports=" << auto_imports
00680 << " (current AI was " << UseContext::get_current_auto_imports () << ")"
00681 << " (Use::scope=" << parent->get_current_scope () << ")"
00682 << " (parent=" << parent->get_package_name () << ")"
00683 << endl;
00684 }
00685
00686 bool hidden_by_scope = false;
00687
00688 if (parent->get_current_scope () == ScopePrivate)
00689 {
00690 hidden_by_scope = true;
00691
00692
00693 if ((parent == 0) ||
00694 (parent->get_package () == cu.get_package ())) hidden_by_scope = false;
00695
00696
00697
00698 if (Cmt::get_scope_filtering_mode () == reach_private_uses) hidden_by_scope = false;
00699 }
00700
00701 if (hidden_by_scope)
00702 {
00703 return (0);
00704 }
00705
00706
00707
00708 UseContext save = UseContext::current ();
00709
00714 switch (auto_imports)
00715 {
00716 case Unspecified:
00717
00718
00719
00720 UseContext::set_current (UseContext::get_current_auto_imports ());
00721 break;
00722 case Off:
00723
00724
00725
00726 UseContext::set_current (Off);
00727 break;
00728 case On:
00729
00730
00731
00732
00733 if (UseContext::get_current_auto_imports () != Off)
00734 {
00735 UseContext::set_current (On);
00736 }
00737 break;
00738 }
00739
00740 if (Cmt::get_debug ())
00741 {
00742 cout << "about to add " << package << endl;
00743 show_packages ();
00744 }
00745
00747 Use* new_use = Use::add (path, package, version,
00748 version_alias, path_alias, parent,
00749 auto_imports);
00750
00751 if (new_use != 0)
00752 {
00753 if (Cmt::get_debug ())
00754 {
00755 cout << "after adding1 " << package
00756 << "> auto_imports=" << new_use->auto_imports << endl;
00757
00758 show_packages ();
00759 }
00760
00761 switch (new_use->auto_imports)
00762 {
00763 case Unspecified:
00764 new_use->auto_imports = UseContext::get_current_auto_imports ();
00765 if (new_use->auto_imports == Unspecified)
00766 {
00767 new_use->auto_imports = On;
00768 }
00769 break;
00770 case On:
00771 break;
00772 case Off:
00773 if (UseContext::get_current_auto_imports () == On)
00774 {
00786 new_use->set_auto_imports (On);
00787 }
00788 break;
00789 }
00790
00791
00792 if (Cmt::get_debug ())
00793 {
00794 cout << "after adding2 " << package
00795 << "> auto_imports=" << new_use->auto_imports << " ";
00796 cout << endl;
00797 }
00798
00799 UseContext& c = UseContext::current ();
00800 c = save;
00801
00802 Use::reorder (new_use, parent);
00803
00804 if (Cmt::get_debug ())
00805 {
00806 cout << "use::action2> current=" << parent->get_package_name ()
00807 << " package=" << package << " ";
00808
00809 int i;
00810
00811 for (i = 0; i < uses.size (); i++)
00812 {
00813 Use* u = uses[i];
00814 cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
00815 }
00816
00817 cout << endl;
00818 }
00819 }
00820
00821 return (new_use);
00822 }
00823
00824 private:
00825
00826 enum
00827 {
00828 need_package,
00829 need_version,
00830 need_path,
00831 need_version_alias,
00832 need_path_alias,
00833 finished
00834 } state;
00835
00836 State auto_imports;
00837
00838 cmt_string package;
00839 cmt_string version;
00840 cmt_string path;
00841 cmt_string version_alias;
00842 cmt_string path_alias;
00843 };
00844
00845
00846 Use* Use::action (const CmtSystem::cmt_string_vector& words, Use* parent)
00847 {
00848 Use* new_use;
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860 if (words.size () < 2) return (0);
00861
00862 use_action_iterator it;
00863
00864 for (int i = 1; i < words.size (); i++)
00865 {
00866 const cmt_string& w = words[i];
00867 cmt_string ew = w;
00868
00869 Symbol::expand (ew);
00870 if (ew != w)
00871 {
00872 CmtSystem::cmt_string_vector ws;
00873
00874 CmtSystem::split (ew, " ", ws);
00875
00876 for (int j = 0; j < ws.size (); ++j)
00877 {
00878 const cmt_string& ww = ws[j];
00879 it.set (ww);
00880 }
00881 }
00882 else
00883 {
00884 it.set (ew);
00885 }
00886 }
00887
00888 if (!it.ok ()) return (0);
00889
00890 static int level = 0;
00891
00892 level++;
00893 new_use = it.get_use (parent);
00894 level--;
00895
00896 return (new_use);
00897 }
00898
00899
00900 void Use::author_action (const CmtSystem::cmt_string_vector& words)
00901 {
00902 if (author != "") author += "\n";
00903 for (int i = 1; i < words.size (); i++)
00904 {
00905 const cmt_string& w = words[i];
00906
00907 if (i > 1) author += " ";
00908 author += w;
00909 }
00910 }
00911
00912
00913 void Use::manager_action (const CmtSystem::cmt_string_vector& words)
00914 {
00915 if (manager != "") manager += "\n";
00916 for (int i = 1; i < words.size (); i++)
00917 {
00918 const cmt_string& w = words[i];
00919
00920 if (i > 1) manager += " ";
00921 manager += w;
00922 }
00923 }
00924
00925
00926 Use* Use::find (const cmt_string& package,
00927 const cmt_string& version,
00928 const cmt_string& path)
00929 {
00930 Package* p = Package::find (package);
00931 if (p == 0) return (0);
00932
00933 UsePtrVector& uses = p->get_uses ();
00934
00935 int use_index;
00936 int size = uses.size ();
00937
00938 for (use_index = 0; use_index < size; use_index++)
00939 {
00940 Use& use = (*uses[use_index]);
00941
00942
00943
00944 if (version == "") return (&use);
00945
00946
00947
00948
00949
00950
00951
00952 if (use.specified_version == version) return (&use);
00953 }
00954
00955 return (0);
00956 }
00957
00958
00959 int Use::find_index (const cmt_string& package_name,
00960 const cmt_string& version,
00961 const cmt_string& path)
00962 {
00963 Package* package = Package::find (package_name);
00964 if (package == 0) return (-1);
00965
00966 UsePtrVector& uses = package->get_uses ();
00967
00968 int use_index;
00969 int size = uses.size ();
00970 for (use_index = 0; use_index < size; use_index++)
00971 {
00972 Use* use = uses[use_index];
00973
00974 if (Cmt::get_debug ())
00975 {
00976 cout << "Use::find_index> " << package_name
00977 << " " << use
00978 << " " << use->m_index
00979 << endl;
00980 }
00981
00982
00983
00984 if (version == "") return (use->m_index);
00985
00986
00987
00988
00989
00990
00991
00992 if (use->specified_version == version) return (use->m_index);
00993 }
00994
00995 return (-1);
00996 }
00997
01006 void Use::set_auto_imports_state (int use_index,
01007 cmt_vector<bool>& auto_imports_states)
01008 {
01009
01010 if ((use_index < 0) || (use_index >= auto_imports_states.size ())) return;
01011
01012 Use::UsePtrVector& uses = Use::get_ordered_uses ();
01013
01014 if (Cmt::get_debug ())
01015 {
01016 int i;
01017
01018 cout << "Use::set_auto_imports_state> use_index=" << use_index << " ";
01019
01020 for (i = 0; i < auto_imports_states.size (); i++)
01021 {
01022 cout << (auto_imports_states[i] ? "|" : "o");
01023 }
01024
01025 for (i = 0; i < auto_imports_states.size (); i++)
01026 {
01027 cout << " " << (uses[i])->get_package_name ();
01028 }
01029
01030 cout << endl;
01031 }
01032
01033
01034 if (auto_imports_states[use_index]) return;
01035
01036 Use* use = uses[use_index];
01037
01038
01039
01040 if (use->auto_imports != Off) return;
01041
01052 auto_imports_states[use_index] = true;
01053
01054 int size = 0;
01055
01056 size = use->sub_uses.size ();
01057 for (int i = 0; i < size; i++)
01058 {
01059 Use* u = use->sub_uses[i];
01060
01061
01062
01063 int j = u->m_index;
01064
01065 if (j >= 0)
01066 {
01067 if (u->sub_use_auto_imports[i] == Off)
01068 {
01069 set_auto_imports_state (j, auto_imports_states);
01070 }
01071 else
01072 {
01073 auto_imports_states[j] = true;
01074 }
01075 }
01076 }
01077 }
01078
01079
01080
01081
01082
01083
01084 void Use::move (Use* use)
01085 {
01086 if (use == 0) return;
01087
01088 static UsePtrVector& uses = get_ordered_uses ();
01089
01090 int size = uses.size ();
01091
01092 if (size == 0) return;
01093
01094
01095
01096
01097
01098 int use_index = use->m_index;
01099
01100 if (use_index < 0) return;
01101
01102
01103
01104
01105 for (use_index++; use_index < size; use_index++)
01106 {
01107 Use* u = uses[use_index];
01108 u->m_index--;
01109
01110 uses[use_index - 1] = uses[use_index];
01111 }
01112
01113
01114
01115
01116
01117 use->m_index = size - 1;
01118 uses[size - 1] = use;
01119 }
01120
01126 void Use::reorder (Use* provider, Use* client)
01127 {
01128 static UsePtrVector& uses = get_ordered_uses ();
01129
01130 int use_index;
01131
01132 int size = uses.size ();
01133
01134 if (size == 0) return;
01135 if (provider == client) return;
01136
01137
01138
01139
01140
01141
01142 int provider_index = -1;
01143 int client_index = -1;
01144
01145 provider_index = provider->m_index;
01146 client_index = client->m_index;
01147
01148 if (Cmt::get_debug ())
01149 {
01150 cout << "Use::reorder> provider=" << provider_index << " client=" << client_index << endl;
01151 }
01152
01153
01154
01155
01156 if (provider_index == -1) return;
01157 if (client_index == -1) return;
01158
01159 if (client_index < provider_index)
01160 {
01161
01162
01163
01164 return;
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180 for (use_index = client_index - 1; use_index >= provider_index; use_index--)
01181 {
01182 Use* use = uses[use_index];
01183 use->m_index++;
01184
01185 uses[use_index + 1] = uses[use_index];
01186 }
01187
01188 uses[provider_index] = client;
01189 client->m_index = provider_index;
01190 }
01191
01192
01193 void Use::clear_all ()
01194 {
01195 static UsePtrVector& uses = get_ordered_uses ();
01196 static UseVector& instances = get_instances ();
01197
01198 int use_index;
01199
01200 for (use_index = 0; use_index < instances.size (); use_index++)
01201 {
01202 Use& use = instances[use_index];
01203 use.clear ();
01204 }
01205
01206 uses.clear ();
01207 instances.clear ();
01208 }
01209
01210
01211 void Use::unselect_all ()
01212 {
01213 static UsePtrVector& uses = get_ordered_uses ();
01214
01215 int use_index;
01216
01217 int size = uses.size ();
01218
01219 if (size == 0) return;
01220
01221 for (use_index = 0; use_index < size; use_index++)
01222 {
01223 Use* use = uses[use_index];
01224
01225 if (use != 0)
01226 {
01227 use->unselect ();
01228 }
01229 }
01230 }
01231
01232
01233 void Use::undiscard_all ()
01234 {
01235 static UsePtrVector& uses = get_ordered_uses ();
01236
01237 int use_index;
01238
01239 if (uses.size () == 0) return;
01240
01241 for (use_index = 0; use_index < uses.size (); use_index++)
01242 {
01243 Use* use = uses[use_index];
01244
01245 if (use != 0)
01246 {
01247 use->undiscard ();
01248 }
01249 }
01250 }
01251
01252
01253 void Use::fill_macro_all (cmt_string& buffer, const cmt_string& suffix)
01254 {
01255 UsePtrVector& uses = get_ordered_uses ();
01256
01257 buffer = "macro_append use_";
01258 buffer += suffix;
01259 buffer += " \" ";
01260 (Use::current()).fill_macro (buffer, suffix);
01261
01262 for (int number = 0; number < uses.size (); number++)
01263 {
01264 Use* use = uses[number];
01265
01266 Package* p = use->get_package ();
01267 if (p->is_cmt ()) continue;
01268
01269 if (use->discarded) continue;
01270 if (use->auto_imports == Off) continue;
01271
01272 use->fill_macro (buffer, suffix);
01273 }
01274
01275 buffer += "\"";
01276 }
01277
01278
01279 Use::Use ()
01280 {
01281 done = false;
01282 discarded = false;
01283 auto_imports = Unspecified;
01284 m_package = 0;
01285 m_index = -1;
01286
01287 clear ();
01288 }
01289
01290
01291 Use::Use (const cmt_string& new_package,
01292 const cmt_string& new_version,
01293 const cmt_string& new_path)
01294 {
01295 auto_imports = Unspecified;
01296 m_located = false;
01297 m_package = 0;
01298 m_index = -1;
01299
01300 set (new_package, new_version, new_path);
01301 }
01302
01303
01304 Use::~Use ()
01305 {
01306 clear ();
01307 }
01308
01309
01310 void Use::clear ()
01311 {
01312 specified_path = "";
01313 path = "";
01314
01315 if (m_package != 0)
01316 {
01317 m_package->remove_use (this);
01318 m_package = 0;
01319 }
01320
01321 version = "";
01322 author = "";
01323 manager = "";
01324 real_path = "";
01325
01326 prefix = "";
01327 style = mgr_style;
01328 initial_scope = ScopePublic;
01329 done = false;
01330 discarded = false;
01331 selected = false;
01332 auto_imports = Unspecified;
01333
01334 includes.clear ();
01335 include_path = "";
01336 scripts.clear ();
01337 apply_patterns.clear ();
01338 ignore_patterns.clear ();
01339
01340 sub_uses.clear ();
01341 sub_use_scopes.clear ();
01342 sub_use_auto_imports.clear ();
01343
01344 requests.clear ();
01345
01346 alternate_versions.clear ();
01347 alternate_paths.clear ();
01348
01349 version_alias = "";
01350 path_alias = "";
01351
01352 m_located = false;
01353 m_has_native_version = false;
01354 m_index = -1;
01355 }
01356
01357
01358 void Use::set (const cmt_string& new_package,
01359 const cmt_string& new_version,
01360 const cmt_string& new_path,
01361 const cmt_string& new_version_alias,
01362 const cmt_string& new_path_alias)
01363 {
01364 clear ();
01365
01366 Package* p = Package::add (new_package);
01367
01368 m_package = p;
01369 p->add_use (this);
01370
01371 specified_path = new_path;
01372
01373
01374 specified_version = new_version;
01375 version = new_version;
01376 path = specified_path;
01377 Symbol::expand (path);
01378 real_path = "";
01379 style = mgr_style;
01380 initial_scope = ScopePublic;
01381 done = false;
01382 discarded = false;
01383 Cmt::build_prefix (new_package, prefix);
01384
01385 version_alias = new_version_alias;
01386 path_alias = new_path_alias;
01387 }
01388
01389
01390 void Use::change_path (const cmt_string& new_path)
01391 {
01392
01393
01394
01395
01396
01397 real_path = "";
01398
01399 if (new_path != "")
01400 {
01401 if ((path.size () > 0) &&
01402 (!CmtSystem::absolute_path (path)))
01403 {
01404 real_path = new_path;
01405 real_path += CmtSystem::file_separator ();
01406 real_path += path;
01407 }
01408 else
01409 {
01410 real_path = new_path;
01411 }
01412
01413
01414 CmtSystem::compress_path (real_path);
01415 }
01416
01417 m_located = true;
01418 }
01419
01420
01421 int Use::reach_package (const cmt_string& from_path)
01422 {
01423 if (Cmt::get_debug ())
01424 {
01425 cout << "Use::reach_package> (" << get_package_name () << " "
01426 << version << ")from " << from_path << endl;
01427 }
01428
01429
01430
01431
01432
01433
01434 if ((from_path != "") && !CmtSystem::cd (from_path)) return (0);
01435
01436 if (Cmt::get_debug ())
01437 {
01438 cout << "Use::reach_package-2>" << endl;
01439 }
01440
01441
01442 if (from_path != real_path)
01443 {
01444
01445 if ((path.size () > 0) && (!CmtSystem::absolute_path (path)))
01446 {
01447 if (!CmtSystem::cd (path))
01448 {
01449 return (0);
01450 }
01451 }
01452 }
01453
01454 if (Cmt::get_debug ())
01455 {
01456 cout << "Use::reach_package-3>" << endl;
01457 }
01458
01459
01460 if (get_package_name () == CmtSystem::get_home_package ())
01461 {
01462 discarded = 1;
01463 if (!CmtSystem::test_file ("requirements"))
01464 {
01465 return (0);
01466 }
01467 else
01468 {
01469 return (1);
01470 }
01471 }
01472
01473 if (Cmt::get_debug ())
01474 {
01475 cout << "Use::reach_package-4>" << endl;
01476 }
01477
01478
01479 if (get_package_name () == CmtSystem::get_user_context_package ())
01480 {
01481 discarded = 1;
01482 if (!CmtSystem::test_file ("requirements"))
01483 {
01484 return (0);
01485 }
01486 else
01487 {
01488 return (1);
01489 }
01490 }
01491
01492
01493 if (get_package_name () == CmtSystem::get_project_package ())
01494 {
01495 discarded = 1;
01496 if (!CmtSystem::test_file ("project"))
01497 {
01498 return (0);
01499 }
01500 else
01501 {
01502 return (1);
01503 }
01504 }
01505
01506 if (Cmt::get_debug ())
01507 {
01508 cout << "Use::reach_package-5>" << endl;
01509 }
01510
01511
01512 if (!CmtSystem::cd (get_package_name ()))
01513 {
01514 return (0);
01515 }
01516
01517 if (Cmt::get_debug ())
01518 {
01519 cout << "Use::reach_package-6>" << endl;
01520 }
01521
01522 if (CmtSystem::test_file ("cmt/requirements"))
01523 {
01524 CmtSystem::cd ("cmt");
01525
01526 style = no_version_style;
01527
01528 if (CmtSystem::test_file ("version.cmt"))
01529 {
01530 cmt_string v;
01531
01532 v.read ("version.cmt");
01533 int pos;
01534 pos = v.find ('\n');
01535 if (pos != cmt_string::npos) v.erase (pos);
01536 pos = v.find ('\r');
01537 if (pos != cmt_string::npos) v.erase (pos);
01538
01539 CompareStatus s = compare_versions (version, v);
01540
01541 if (Cmt::get_debug ())
01542 {
01543 cout << "Use::reach_package-6.1> version=" << version << " v=" << v << " s=" << s << endl;
01544 }
01545
01546 switch (s)
01547 {
01548 case IdenticalIds:
01549 case ExplicitOldMajorIdWinsAgainstWildarded:
01550 case ExplicitOldMinorIdWinsAgainstWildarded:
01551 case ExplicitOldPatchIdWinsAgainstWildarded:
01552 break;
01553 case ExplicitNewMajorIdWinsAgainstWildarded:
01554 case ExplicitNewMinorIdWinsAgainstWildarded:
01555 case NewMinorIdGreaterThanOld:
01556 case ExplicitNewPatchIdWinsAgainstWildarded:
01557 case NewPatchIdGreaterThanOld:
01558 break;
01559 case OldMajorIdGreaterThanNew:
01560 case NewMajorIdGreaterThanOld:
01561 break;
01562 case IncompatibleMajorIds:
01563 return (0);
01564 }
01565 version = v;
01566 }
01567 else if (version == "")
01568 {
01569 version = "v0";
01570 }
01571
01572 return (1);
01573 }
01574 else if (!CmtSystem::cd (version))
01575 {
01576
01577
01578
01579
01580 if ((version == "") ||
01581 (version.find ("*") != cmt_string::npos))
01582 {
01583 static CmtSystem::cmt_string_vector versions;
01584 static cmt_string name;
01585
01586 name = ".";
01587 name += CmtSystem::file_separator ();
01588 if (version == "") name += "*";
01589 else name += version;
01590
01591 CmtSystem::scan_dir (name, versions);
01592
01593 int i;
01594 bool found = false;
01595
01596 for (i = 0; i < versions.size (); i++)
01597 {
01598 const cmt_string& vers = versions[i];
01599
01600 if (Cmt::get_debug ())
01601 {
01602 cout << " ... version " << vers << " exists" << endl;
01603 }
01604
01605 CmtSystem::basename (vers, name);
01606
01607 int v;
01608 int r;
01609 int p;
01610
01611 if (CmtSystem::is_version_directory (name, v, r, p))
01612 {
01613
01614
01615
01616
01617
01618
01619 cmt_string req;
01620
01621 req = name;
01622 req += CmtSystem::file_separator ();
01623 req += "mgr";
01624 req += CmtSystem::file_separator ();
01625 req += "requirements";
01626
01627 if (!CmtSystem::test_file (req))
01628 {
01629 req = name;
01630 req += CmtSystem::file_separator ();
01631 req += "cmt";
01632 req += CmtSystem::file_separator ();
01633 req += "requirements";
01634
01635 if (!CmtSystem::test_file (req)) continue;
01636 }
01637
01638 cmt_string& new_v = alternate_versions.add ();
01639 new_v = name;
01640 cmt_string& new_p = alternate_paths.add ();
01641 new_p = from_path;
01642
01643 found = true;
01644 }
01645 }
01646
01647 if (!found)
01648 {
01649 if (CmtSystem::test_file ("cmt/requirements"))
01650 {
01651 CmtSystem::cd ("cmt");
01652 style = no_version_style;
01653 return (1);
01654 }
01655 }
01656 }
01657
01658 if (Cmt::get_debug ())
01659 {
01660 cout << " ... end of version scan" << endl;
01661 }
01662
01663
01664
01665
01666
01667
01668 return (0);
01669 }
01670
01671 if (Cmt::get_debug ())
01672 {
01673 cout << "Use::reach_package-7>" << endl;
01674 }
01675
01676
01677
01678
01679 if (!CmtSystem::test_file ("cmt/requirements"))
01680 {
01681 if (!CmtSystem::test_file ("mgr/requirements"))
01682 {
01683 return (0);
01684 }
01685 else
01686 {
01687 CmtSystem::cd ("mgr");
01688 style = mgr_style;
01689 }
01690 }
01691 else
01692 {
01693 CmtSystem::cd ("cmt");
01694 style = cmt_style;
01695 }
01696
01697 if (Cmt::get_debug ())
01698 {
01699 cout << "Use::reach_package-8>" << endl;
01700 }
01701
01702 return (1);
01703 }
01704
01705 class UseProjectAction : public IProjectAction
01706 {
01707 public:
01708 UseProjectAction (Use* use) : m_use (use), m_found (false)
01709 {
01710 }
01711
01712 bool found () const
01713 {
01714 return (m_found);
01715 }
01716
01717 bool run (const Project& project)
01718 {
01719 const cmt_string& path = project.get_cmtpath ();
01720
01721 m_use->alternate_versions.clear ();
01722 m_use->alternate_paths.clear ();
01723
01724 if (m_use->reach_package (path))
01725 {
01726 if (Cmt::get_debug ())
01727 {
01728 cout << "move_to4> " << path << endl;
01729 }
01730
01731 m_use->change_path (path);
01732
01733 m_found = true;
01734
01735 return (false);
01736 }
01737 else if (m_use->alternate_versions.size () > 0)
01738 {
01739 if (m_use->select_alternate ())
01740 {
01741 if (Cmt::get_debug ())
01742 {
01743 cout << "move_to5> " << m_use->real_path << endl;
01744 }
01745
01746 m_found = true;
01747
01748 return (false);
01749 }
01750 }
01751
01752 return (true);
01753 }
01754
01755 private:
01756 Use* m_use;
01757 bool m_found;
01758 };
01759
01760
01761 bool Use::move_to ()
01762 {
01763 if (m_located)
01764 {
01765
01766
01767
01768
01769
01770 if (Cmt::get_debug ())
01771 {
01772 cout << "move_to1> " << real_path << endl;
01773 }
01774
01775 reach_package (real_path);
01776
01777 return (true);
01778 }
01779
01780 cmt_string expanded_path = path;
01781
01782
01783
01784
01785 if (expanded_path == "")
01786 {
01787 if (reach_package (""))
01788 {
01789 if (Cmt::get_debug ())
01790 {
01791 cout << "move_to2> " << expanded_path << endl;
01792 }
01793
01794 change_path (expanded_path);
01795
01796 return (true);
01797 }
01798 else if (alternate_versions.size () > 0)
01799 {
01800 if (select_alternate ())
01801 {
01802 if (Cmt::get_debug ())
01803 {
01804 cout << "move_to5> " << real_path << endl;
01805 }
01806
01807 return (true);
01808 }
01809 }
01810 }
01811
01812
01813
01814
01815
01816 if (CmtSystem::absolute_path (expanded_path))
01817 {
01818 if (reach_package (expanded_path))
01819 {
01820 if (Cmt::get_debug ())
01821 {
01822 cout << "move_to3> " << expanded_path << endl;
01823 }
01824
01825 change_path (expanded_path);
01826
01827 return (true);
01828 }
01829 else if (alternate_versions.size () > 0)
01830 {
01831 if (select_alternate ())
01832 {
01833 if (Cmt::get_debug ())
01834 {
01835 cout << "move_to5> " << real_path << endl;
01836 }
01837
01838 return (true);
01839 }
01840 }
01841 }
01842
01843
01844
01845
01846
01847 UseProjectAction pa (this);
01848
01849 Project::broadcast (pa);
01850
01851 if (pa.found ()) return (true);
01852
01853 return (false);
01854 }
01855
01856
01857 bool Use::select_alternate ()
01858 {
01859 int i;
01860
01861 int v0 = 0;
01862 int r0 = 0;
01863 int p0 = 0;
01864
01865 int v = 0;
01866 int r = 0;
01867 int p = 0;
01868
01869 int selected_index = -1;
01870
01871 for (i = 0; i < alternate_versions.size (); i++)
01872 {
01873 cmt_string& name = alternate_versions[i];
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885 if (i == 0)
01886 {
01887 CmtSystem::is_version_directory (name, v0, r0, p0);
01888 selected_index = 0;
01889 }
01890 else
01891 {
01892 CmtSystem::is_version_directory (name, v, r, p);
01893
01894 if (v > v0)
01895 {
01896 selected_index = i;
01897 v0 = v;
01898 r0 = r;
01899 p0 = p;
01900 }
01901 else if (v == v0)
01902 {
01903 if (r > r0)
01904 {
01905 selected_index = i;
01906 r0 = r;
01907 p0 = p;
01908 }
01909 else if (r == r0)
01910 {
01911 if (p > p0)
01912 {
01913 selected_index = i;
01914 p0 = p;
01915 }
01916 }
01917 }
01918 }
01919 }
01920
01921 if (selected_index >= 0)
01922 {
01923 if (CmtSystem::cd (alternate_paths[selected_index]))
01924 {
01925 version = alternate_versions[selected_index];
01926 if (reach_package (alternate_paths[selected_index]))
01927 {
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937 if (Cmt::get_debug ())
01938 {
01939 cout << "select_alternate> " << alternate_paths[selected_index] << endl;
01940 }
01941
01942 change_path (alternate_paths[selected_index]);
01943 return (true);
01944 }
01945 }
01946 }
01947
01948 return (false);
01949 }
01950
01951
01952 bool Use::need_new (const cmt_string& path,
01953 const cmt_string& package,
01954 const cmt_string& version,
01955 Use** old_use,
01956 Use* context_use)
01957 {
01958 bool new_request = add_request (path, package, version);
01959
01960 Use& current_use = Use::current ();
01961
01962 if (package == current_use.get_package_name ())
01963 {
01964 if (Cmt::get_debug ())
01965 {
01966 cout << " ... recursive use to current package" << endl;
01967 }
01968
01969 if (old_use != 0) *old_use = ¤t_use;
01970 return (false);
01971 }
01972
01973 Package* p = Package::add (package);
01974
01975 UsePtrVector& uses = p->get_uses ();
01976
01977 bool do_need_new = true;
01978 Use* found = 0;
01979 Use* registered = 0;
01980
01981 int req_v = -1;
01982 int req_r = -1;
01983 int req_p = -1;
01984
01985 CmtSystem::is_version_directory (version, req_v, req_r, req_p);
01986
01987 if (Cmt::get_debug ())
01988 {
01989 cout << "need_new> p=" << package << " v=" << version << " v=" << req_v << " r=" << req_r << " p=" << req_p << endl;
01990 }
01991
01992 bool has_wild_card = (req_v == -1) || (req_r == -1) || (req_p == -1);
01993
01994 int new_v = -1;
01995 int new_r = -1;
01996 int new_p = -1;
01997
01998 int use_index;
01999
02000 if (old_use != 0) *old_use = 0;
02001
02002
02003 for (use_index = 0; use_index < uses.size (); use_index++)
02004 {
02005 Use& use = (*uses[use_index]);
02006
02007 if (use.m_index < 0) continue;
02008
02009 registered = &use;
02010
02011 break;
02012 }
02013
02014
02015
02016 cmt_string decision;
02017
02018 if (registered != 0)
02019 {
02020 Use& use = (*registered);
02021
02022 found = &use;
02023
02024 CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
02025
02026 bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
02027
02028 if (has_wild_card && !use_has_wild_card)
02029 {
02030 if (Cmt::get_debug ())
02031 {
02032 cout << " ... wildcarded request loses against existing explicit" << endl;
02033 }
02034
02035 do_need_new = false;
02036 }
02037 else
02038 {
02039
02040
02041 if ((version == use.specified_version) &&
02042 (path == use.specified_path))
02043 {
02044 if (Cmt::get_debug ())
02045 {
02046 cout << " ... exactly same version and path!" << endl;
02047 }
02048
02049 do_need_new = false;
02050 }
02051 else if (version != use.specified_version)
02052 {
02053 if (Cmt::get_debug ())
02054 {
02055 cout << "requested explicit wins against existing wildcarded"
02056 << endl;
02057 }
02058
02059
02060 }
02061 else
02062 {
02063 if (Cmt::get_debug ())
02064 {
02065 cout << "only paths differ, consider the new one."
02066 << endl;
02067 }
02068
02069
02070 }
02071 }
02072
02073
02074
02075 if (new_request && !Cmt::get_quiet ())
02076 {
02077 if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
02078 {
02079 cout << "# Required version " << version
02080 << " of package " << package;
02081
02082 if (context_use != 0)
02083 {
02084 cout << " [from " << context_use->get_package_name () << "]";
02085 }
02086
02087 cout << " incompatible with selected version " << use.version;
02088
02089 if (use.version != use.specified_version)
02090 {
02091 cout << " (" << use.specified_version << ")" ;
02092 }
02093
02094 cout << endl;
02095 }
02096 }
02097
02098 if (Cmt::get_debug ())
02099 {
02100 cout << "# " << package << " " << version;
02101
02102 if (context_use != 0)
02103 {
02104 cout << " [from " << context_use->get_package_name () << "]";
02105 }
02106
02107 if (do_need_new)
02108 {
02109 cout << " > ";
02110 }
02111 else
02112 {
02113 cout << " < ";
02114 }
02115
02116 cout << use.version;
02117 if (use.version != use.specified_version)
02118 {
02119 cout << " (" << use.specified_version << ")" ;
02120 }
02121
02122 cout << " (r) ";
02123
02124 cout << endl;
02125 }
02126 }
02127
02128 if (do_need_new)
02129 {
02130
02131
02132
02133 for (use_index = 0; use_index < uses.size (); use_index++)
02134 {
02135 Use& use = (*uses[use_index]);
02136
02137 if (use.m_index >= 0) continue;
02138
02139
02140
02141 found = &use;
02142
02143 CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
02144
02145 bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
02146
02147 if (has_wild_card && !use_has_wild_card)
02148 {
02149 if (Cmt::get_debug ())
02150 {
02151 cout << " ... requested wildcarded loses against existing explicit" << endl;
02152 }
02153
02154 do_need_new = false;
02155 }
02156 else
02157 {
02158
02159
02160 if ((version == use.specified_version) &&
02161 (path == use.specified_path))
02162 {
02163 if (Cmt::get_debug ())
02164 {
02165 cout << " ... exactly same version and path!" << endl;
02166 }
02167
02168 do_need_new = false;
02169 }
02170 else if (version != use.specified_version)
02171 {
02172 if (Cmt::get_debug ())
02173 {
02174 cout << "requested explicit wins against existing wildcarded"
02175 << endl;
02176 }
02177
02178
02179 }
02180 else
02181 {
02182 if (Cmt::get_debug ())
02183 {
02184 cout << "only paths differ, consider the new one."
02185 << endl;
02186 }
02187
02188
02189 }
02190 }
02191
02192
02193 if (new_request && !Cmt::get_quiet ())
02194 {
02195 if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
02196 {
02197 cout << "# Required version " << version
02198 << " of package " << package;
02199
02200 if (context_use != 0)
02201 {
02202 cout << " [from " << context_use->get_package_name () << "]";
02203 }
02204
02205 cout << " incompatible with selected version " << use.version;
02206
02207 if (use.version != use.specified_version)
02208 {
02209 cout << " (" << use.specified_version << ")" ;
02210 }
02211
02212 cout << endl;
02213 }
02214 }
02215
02216 if (Cmt::get_debug ())
02217 {
02218 cout << "# " << package << " " << version;
02219
02220 if (context_use != 0)
02221 {
02222 cout << " [from " << context_use->get_package_name () << "]";
02223 }
02224
02225 if (do_need_new)
02226 {
02227 cout << " > ";
02228 }
02229 else
02230 {
02231 cout << " < ";
02232 }
02233
02234 if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
02235 {
02236 cout << "(incompatible) ";
02237 }
02238
02239 cout << use.version;
02240 if (use.version != use.specified_version)
02241 {
02242 cout << " (" << use.specified_version << ")" ;
02243 }
02244 cout << endl;
02245 }
02246 }
02247 }
02248
02249 if (old_use != 0)
02250 {
02251 if (registered != 0) *old_use = registered;
02252 else *old_use = found;
02253 }
02254
02255 return (do_need_new);
02256 }
02257
02258
02259
02260
02261
02262
02263
02264 Use* Use::create (const cmt_string& path,
02265 const cmt_string& package,
02266 const cmt_string& version,
02267 const cmt_string& version_alias,
02268 const cmt_string& path_alias)
02269 {
02270 Package* p = 0;
02271
02272 p = Package::add (package);
02273
02274 UsePtrVector& vector = p->get_uses ();
02275
02276
02277 for (int use_index = 0; use_index < vector.size (); use_index++)
02278 {
02279 Use* use = vector[use_index];
02280
02281 if ((use->specified_version == version) &&
02282 (use->specified_path == path)) return (use);
02283 }
02284
02285
02286
02287 static UseVector& instances = get_instances ();
02288
02289 Use& use_object = instances.add ();
02290
02291 use_object.set (package, version, path, version_alias, path_alias);
02292
02293 return (&use_object);
02294 }
02295
02296
02297
02298
02299
02300
02301
02302
02303 Use* Use::add (const cmt_string& path,
02304 const cmt_string& package_name,
02305 const cmt_string& version,
02306 const cmt_string& version_alias,
02307 const cmt_string& path_alias,
02308 Use* context_use,
02309 State specified_auto_imports)
02310 {
02311 bool do_need_new = false;
02312
02313 Use* old_use = 0;
02314 Use* use = 0;
02315
02316 do_need_new = need_new (path, package_name, version, &old_use, context_use);
02317
02318 if (Cmt::get_debug ())
02319 {
02320 if (old_use != 0)
02321 {
02322 cout << "add> old_use " << old_use->get_package_name () <<
02323 " " << old_use->version <<
02324 " " << old_use->path <<
02325 endl;
02326 }
02327 }
02328
02329 if (do_need_new)
02330 {
02331 use = create (path, package_name, version, version_alias, path_alias);
02332 }
02333 else
02334 {
02335
02336 use = old_use;
02337 old_use = 0;
02338 }
02339
02340 if (package_name == CmtSystem::get_home_package ())
02341 {
02342 return (use);
02343 }
02344
02345 if (package_name == CmtSystem::get_user_context_package ())
02346 {
02347 return (use);
02348 }
02349
02350 if (package_name == CmtSystem::get_project_package ())
02351 {
02352 return (use);
02353 }
02354
02355 cmt_string here = CmtSystem::pwd ();
02356
02357
02358
02359
02360
02361 if (context_use != 0)
02362 {
02363 context_use->sub_uses.push_back (use);
02364
02365 context_use->sub_use_scopes.push_back (context_use->get_current_scope ());
02366
02367 context_use->sub_use_auto_imports.push_back (specified_auto_imports);
02368
02369 cmt_string& request = context_use->requests.add ();
02370
02371 request = package_name;
02372 request += " ";
02373 request += version;
02374 request += " ";
02375 request += path;
02376
02377
02378 if (Cmt::get_debug ())
02379 {
02380 cout << "Use::add context(" << context_use->get_package_name () << ") "
02381 << "[u:" << package_name
02382 << " s:" << context_use->get_current_scope ()
02383 << " ai:" << specified_auto_imports
02384 << "]" << endl;
02385 }
02386 }
02387
02388 if (use == &(Use::current ()))
02389 {
02390 return (use);
02391 }
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407 bool found = use->move_to ();
02408
02409 if (Cmt::get_debug ())
02410 {
02411 cout << "add> use [" << use << "] " << use->get_package_name ()
02412 << " " << use->version
02413 << " " << use->path
02414 << " found=" << found
02415 << " done=" << use->done
02416 << endl;
02417
02418 show_packages ();
02419 }
02420
02421 if (!found)
02422 {
02423 if (!Cmt::get_quiet ())
02424 {
02425 cerr << "#CMT> Warning: package " << use->get_package_name () <<
02426 " " << use->version << " " << use->path <<
02427 " not found";
02428
02429 if (context_use != 0)
02430 {
02431 cerr << " (requested by " << context_use->get_package_name () << ")";
02432 }
02433
02434 cerr << endl;
02435 }
02436
02437
02438 use = 0;
02439 }
02440
02441 if ((old_use != 0) && (use != old_use))
02442 {
02443 if (Cmt::get_debug ())
02444 {
02445 cout << "There was another version of this Use. \n"
02446 << "But a new one was created due to some criteria. \n"
02447 << "Now we are going to apply the version strategy to make the final selection"
02448 << endl;
02449 }
02450
02451
02452
02453
02454
02455
02456
02457 if (Cmt::get_debug ())
02458 {
02459 cout << "select? [" << use << "] vs old_use[" << old_use << "] "
02460 << old_use->get_package_name ()
02461 << " " << old_use->version
02462 << " " << old_use->path
02463 << endl;
02464 }
02465
02466 if (!found)
02467 {
02468
02469
02470
02471
02472
02473 if (use != 0) use->discard ();
02474 use = old_use;
02475 found = use->move_to ();
02476 }
02477 else
02478 {
02479
02480
02481
02482
02483 static BestFitSelector selector;
02484 Use* selected_use = selector.operate (old_use, use);
02485
02486 if (Cmt::get_debug ())
02487 {
02488 cout << "after operate old=" << old_use << "(" << old_use->m_index << ")"
02489 << " use=" << use << "(" << use->m_index << ")"
02490 << " => selected=" << selected_use
02491 << endl;
02492 }
02493
02494
02495
02496
02497
02498 if (use != selected_use)
02499 {
02500 use = use->set_selected_version (selected_use);
02501 }
02502
02503
02504
02505
02506
02507 found = use->move_to ();
02508 }
02509 }
02510
02511
02512
02513
02514
02515
02516
02517 if (found)
02518 {
02519 static UsePtrVector& uses = get_ordered_uses ();
02520
02521 bool registered = false;
02522 const Use& cu = Use::current ();
02523
02524 Package* package = Package::find (package_name);
02525
02526
02527
02528
02529 if ((use != &cu) && (package == cu.get_package ()))
02530 {
02531
02532 registered = true;
02533 use->done = true;
02534 use->m_index = -1;
02535 }
02536 else
02537 {
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556 UsePtrVector& puses = package->get_uses ();
02557
02558 if (use->m_index >= 0) registered = true;
02559
02560
02561
02562
02563 for (int i = 0; i < puses.size(); i++)
02564 {
02565 Use* u = puses[i];
02566
02567 if (Cmt::get_debug ())
02568 {
02569 cout << "add> check registering between " << use
02570 << ":" << use->get_package_name ()
02571 << "(" << use->m_index << ")"
02572 << " and " << u
02573 << ":" << u->get_package_name ()
02574 << "(" << u->m_index << ")"
02575 << endl;
02576 }
02577
02578 if ((u != use) && (u->m_index >= 0))
02579 {
02580
02581
02582 if (Cmt::get_debug ())
02583 {
02584 cout << "add> Another use of that package is already registered "
02585 << " use(" << use->m_index << ")";
02586 if (use->m_index >= 0)
02587 {
02588 cout << "[" << (uses[use->m_index])->get_package_name () << "]";
02589 }
02590 cout << " u(" << u->m_index << ")";
02591 if (u->m_index >= 0)
02592 {
02593 cout << "[" << (uses[u->m_index])->get_package_name () << "]";
02594 }
02595 cout << endl;
02596 }
02597
02598 if (use->m_index < 0)
02599 {
02600
02601
02602
02603
02604 u->set_selected_version (use);
02605
02606 registered = true;
02607 }
02608 else
02609 {
02610
02611 if (Cmt::get_debug ())
02612 {
02613 cout << "Duplicate entry in ordered uses" << endl;
02614 }
02615 }
02616 }
02617 }
02618
02619 if (Cmt::get_debug ())
02620 {
02621 cout << "add> registering completed" << endl;
02622 show_packages ();
02623 }
02624 }
02625
02626 if (!registered)
02627 {
02628 if (Cmt::get_debug ())
02629 {
02630 cout << "add> We install use at the end the ordered list of uses" << endl;
02631 }
02632
02633 uses.push_back (use);
02634 use->m_index = uses.size () - 1;
02635 }
02636
02637 if (Cmt::get_debug ())
02638 {
02639 for (int use_index = 0; use_index < uses.size (); use_index++)
02640 {
02641 Use* u = (Use*) uses[use_index];
02642 cout << " use[" << use_index << "] p=(" << u << ")" << u->get_package_name ()
02643 << " v=" << u->version
02644 << " discarded=" << u->discarded
02645 << " selected=" << u->selected
02646 << " done=" << u->done
02647 << " index=" << u->m_index
02648 << endl;
02649 }
02650
02651 }
02652
02653 if (!use->done && Cmt::get_recursive ())
02654 {
02655 use->done = true;
02656
02657 if (Cmt::get_debug ())
02658 {
02659 cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
02660 }
02661
02662 SyntaxParser::parse_requirements ("requirements", use);
02663 }
02664 else
02665 {
02666 if (Cmt::get_debug ())
02667 {
02668 cout << "Requirements file at " << CmtSystem::pwd () << " already parsed" << endl;
02669 }
02670 }
02671 }
02672
02673 CmtSystem::cd (here);
02674
02675 return (use);
02676 }
02677
02678
02679 void Use::discard ()
02680 {
02681 discarded = true;
02682 }
02683
02684
02685 void Use::undiscard ()
02686 {
02687 discarded = false;
02688 }
02689
02690
02691 void Use::select ()
02692 {
02693 selected = true;
02694 }
02695
02696
02697 void Use::unselect ()
02698 {
02699 selected = false;
02700 }
02701
02702
02703 bool Use::is_selected ()
02704 {
02705 return (selected);
02706 }
02707
02714 bool Use::is_client (const cmt_string& used_package,
02715 const cmt_string& used_version)
02716 {
02717
02718
02719 Package* package = Package::find (used_package);
02720
02721 if ((get_package () == package) &&
02722 (version == used_version)) return (true);
02723
02724 if (discarded) return (false);
02725
02726 int i;
02727
02728 for (i = 0; i < sub_uses.size (); i++)
02729 {
02730 Use* use = sub_uses[i];
02731 if (use == 0) continue;
02732
02733 if ((use->get_package () == package) &&
02734 (use->version == used_version)) return (true);
02735
02736
02737
02738
02739
02740
02741
02742 }
02743
02744 return (false);
02745 }
02746
02747
02748 void Use::apply_global_patterns ()
02749 {
02750 int i;
02751
02752 Pattern::PatternVector& vector = Pattern::patterns ();
02753
02754 for (i = 0; i < vector.size (); i++)
02755 {
02756 Pattern& p = vector[i];
02757
02758 if (p.global)
02759 {
02760 p.apply (this);
02761 }
02762 }
02763 }
02764
02765
02766 void Use::set_include_path (const cmt_string& new_path)
02767 {
02768 include_path = new_path;
02769 }
02770
02778 void Use::get_full_path (cmt_string& s) const
02779 {
02780 if (real_path == "") s = CmtSystem::pwd ();
02781 else s = real_path;
02782
02783 s += CmtSystem::file_separator ();
02784 s += get_package_name ();
02785
02786 if (style != no_version_style)
02787 {
02788 s += CmtSystem::file_separator ();
02789 s += version;
02790 }
02791 }
02792
02797 cmt_string Use::get_full_path () const
02798 {
02799 cmt_string result;
02800
02801 get_full_path (result);
02802
02803 return (result);
02804 }
02805
02812 void Use::reduce_path (cmt_string& s) const
02813 {
02814 cmt_string pattern;
02815 get_full_path (pattern);
02816 pattern += CmtSystem::file_separator ();
02817
02818 cmt_string replacement = "${";
02819 replacement += prefix;
02820 replacement += "ROOT}";
02821 replacement += CmtSystem::file_separator ();
02822
02823 s.replace (pattern, replacement);
02824 }
02825
02826
02827 void Use::get_cmtpath_and_offset (cmt_string& cmtpath, cmt_string& offset) const
02828 {
02829 if (get_package_name () == CmtSystem::get_project_package ())
02830 {
02831 offset = "";
02832 CmtSystem::dirname (path, cmtpath);
02833 return;
02834 }
02835 else if (get_package_name () == CmtSystem::get_home_package ())
02836 {
02837 offset = "";
02838 cmtpath = path;
02839 return;
02840 }
02841 else if (get_package_name () == CmtSystem::get_user_context_package ())
02842 {
02843 offset = "";
02844 cmtpath = path;
02845 return;
02846 }
02847
02848 cmtpath = "";
02849 offset = "";
02850
02851 cmtpath = Project::find_in_cmt_paths (real_path);
02852
02853 if (cmtpath != "")
02854 {
02855 CmtSystem::compress_path (cmtpath);
02856
02857 static const cmt_string empty_string;
02858 static const cmt_string fs = CmtSystem::file_separator ();
02859
02860 offset = real_path;
02861 offset.replace (cmtpath, empty_string);
02862
02869 if (offset[0] == CmtSystem::file_separator ())
02870 {
02871
02872
02873 offset.replace (fs, empty_string);
02874 }
02875 }
02876 }
02877
02878
02879 void Use::fill_includes_macro (cmt_string& buffer) const
02880 {
02881 if (include_path == "")
02882 {
02883 buffer += "$(ppcmd)\"$(";
02884 buffer += get_package_name ();
02885 buffer += "_root)";
02886 buffer += CmtSystem::file_separator ();
02887 buffer += "src\" ";
02888 }
02889 else if (include_path != "none")
02890 {
02891 buffer += "$(ppcmd)\"";
02892 buffer += include_path;
02893 buffer += "\" ";
02894 }
02895
02896 for (int i = 0; i < includes.size (); i++)
02897 {
02898 Include& incl = includes[i];
02899
02900 buffer += "$(ppcmd)\"";
02901 buffer += incl.name;
02902 buffer += "\" ";
02903 }
02904 }
02905
02906
02907 void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
02908 {
02909 buffer += " $(";
02910 buffer += get_package_name ();
02911 buffer += "_";
02912 buffer += suffix;
02913 buffer += ") ";
02914 }
02915
02916
02917 void Use::fill_standard_macros (cmt_string& buffer) const
02918 {
02919 static cmt_string fs = CmtSystem::file_separator ();
02920
02921 buffer = "";
02922
02923 cmt_string package_name = get_package_name ();
02924
02925 buffer += "macro ";
02926 buffer += package_name;
02927 buffer += "_tag";
02928 buffer += " \"$(tag)\"";
02929 buffer += "\n";
02930
02931 if (located ())
02932 {
02933 buffer += "macro ";
02934 buffer += prefix;
02935 buffer += "ROOT";
02936 buffer += " \"";
02937 buffer += get_full_path ();
02938 buffer += "\"";
02939 buffer += "\n";
02940
02941 buffer += "macro ";
02942 buffer += package_name;
02943 buffer += "_root";
02944 buffer += " \"";
02945 buffer += real_path;
02946 buffer += fs;
02947 buffer += package_name;
02948 if (style != no_version_style)
02949 {
02950 buffer += fs;
02951 buffer += version;
02952 }
02953 buffer += "\"";
02954 buffer += "\n";
02955 }
02956
02957 buffer += "macro ";
02958 buffer += prefix;
02959 buffer += "VERSION";
02960 buffer += " \"";
02961 buffer += version;
02962 buffer += "\"";
02963 buffer += "\n";
02964
02965 cmt_string cmtpath = "";
02966 cmt_string offset = "";
02967
02968 get_cmtpath_and_offset (cmtpath, offset);
02969
02970 buffer += "macro ";
02971 buffer += package_name;
02972 buffer += "_cmtpath";
02973 buffer += " \"";
02974 buffer += cmtpath;
02975 buffer += "\"";
02976 buffer += "\n";
02977
02978 buffer += "macro ";
02979 buffer += package_name;
02980 buffer += "_offset";
02981 buffer += " \"";
02982 buffer += offset;
02983 buffer += "\"";
02984 buffer += "\n";
02985
02986 Project* p = Project::find_by_cmtpath (cmtpath);
02987
02988 buffer += "macro ";
02989 buffer += package_name;
02990 buffer += "_project";
02991 buffer += " \"";
02992 if (p != 0)
02993 {
02994 buffer += p->get_name ();
02995 }
02996 buffer += "\"";
02997
02998 buffer += "macro ";
02999 buffer += package_name;
03000 buffer += "_project_release";
03001 buffer += " \"";
03002 if (p != 0)
03003 {
03004 buffer += p->get_release ();
03005 }
03006 buffer += "\"";
03007 }
03008
03009
03010
03011 static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
03012 {
03013 bool result = false;
03014
03015 cmt_string here = CmtSystem::pwd ();
03016
03017 cmt_string h1;
03018 if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
03019
03020 CmtSystem::cd (here);
03021
03022 cmt_string h2;
03023 if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
03024
03025 result = (h1 == h2);
03026
03027 CmtSystem::cd (here);
03028
03029 return (result);
03030 }
03031
03032
03033 static bool install_library (const cmt_string& source_library_name,
03034 const cmt_string& dest_library_name,
03035 const cmt_string& cmtinstallarea,
03036 const cmt_string& tag,
03037 const cmt_string& symlinkcmd)
03038 {
03039 cmt_string libname = source_library_name;
03040 cmt_string name = dest_library_name;
03041 cmt_string s;
03042 Use& current_use = Use::current ();
03043
03044 Symbol::expand (name);
03045 Symbol::expand (libname);
03046
03047 if (cmtinstallarea != "")
03048 {
03049 s = cmtinstallarea;
03050 s += CmtSystem::file_separator ();
03051 s += tag;
03052 s += CmtSystem::file_separator ();
03053 s += "lib";
03054 s += CmtSystem::file_separator ();
03055 s += name;
03056
03057
03058
03059 cmt_string ref_file = s;
03060 ref_file += ".cmtref";
03061
03062 cmt_string text = libname;
03063 text += "\n";
03064
03065 Symbol::expand (ref_file);
03066 Symbol::expand (text);
03067
03068 if (!Cmt::get_quiet ()) cout << " Creating the reference file " << ref_file << endl;
03069 text.write (ref_file);
03070 }
03071 else
03072 {
03073 s = "../$(";
03074 s += current_use.get_package_name ();
03075 s += "_tag)/";
03076 s += name;
03077 }
03078
03079 Symbol::expand (s);
03080
03081 cmt_string source;
03082 cmt_string dest;
03083
03084 CmtSystem::dirname (libname, source);
03085 CmtSystem::dirname (s, dest);
03086
03087 if (same_dirs (source, dest))
03088 {
03089 return (false);
03090 }
03091
03092
03093 cout << " Symlinking " << libname << " to " << s << endl;
03094
03095 if (symlinkcmd == "")
03096 {
03097 if (!CmtSystem::create_symlink (libname, s))
03098 {
03099 cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
03100 return (false);
03101 }
03102 }
03103 else
03104 {
03105 cmt_string cmd = symlinkcmd;
03106 cmd += " ";
03107 cmd += libname;
03108 cmd += " ";
03109 cmd += s;
03110
03111 int status = CmtSystem::execute (cmd);
03112
03113 if (status != 0)
03114 {
03115 cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
03116 return (false);
03117 }
03118 }
03119
03120 return (true);
03121 }
03122
03123
03127 void Use::build_library_links (const cmt_string& cmtinstallarea,
03128 const cmt_string& tag,
03129 const cmt_string& shlibsuffix,
03130 const cmt_string& symlinkcmd) const
03131 {
03132 if (!located ())
03133 {
03134 if (!Cmt::get_quiet ())
03135 {
03136 cout << "# package " << get_package_name () <<
03137 " " << version << " " << path <<
03138 " not found" <<
03139 endl;
03140 }
03141 return;
03142 }
03143
03144 cmt_string s;
03145
03146 s = get_package_name ();
03147 s += "_libraries";
03148
03149 Symbol* libraries_macro = Symbol::find (s);
03150
03151 if (libraries_macro == 0) return;
03152
03153 cmt_string libraries = libraries_macro->build_macro_value ();
03154 Symbol::expand (libraries);
03155 static CmtSystem::cmt_string_vector values;
03156
03157 CmtSystem::split (libraries, " \t", values);
03158
03159 for (int j = 0; j < values.size (); j++)
03160 {
03161 const cmt_string& library = values[j];
03162
03163 static cmt_string libname;
03164 static cmt_string name;
03165
03166
03167
03168 libname = library;
03169 Symbol::expand (libname);
03170
03171 bool is_absolute = false;
03172
03173 is_absolute = CmtSystem::absolute_path (libname);
03174
03175 if (is_absolute)
03176 {
03182 cmt_string suffix;
03183 CmtSystem::basename (library, name);
03184 }
03185 else
03186 {
03194 libname = "${";
03195 libname += prefix;
03196 libname += "ROOT}/${";
03197 libname += get_package_name ();
03198 libname += "_tag}/";
03199 libname += "$(library_prefix)";
03200 libname += library;
03201 libname += "$(library_suffix)";
03202 libname += ".";
03203 libname += shlibsuffix;
03204
03205 name = "$(library_prefix)";
03206 name += library;
03207 name += "$(library_suffix)";
03208 name += ".";
03209 name += shlibsuffix;
03210 }
03211
03212 if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
03213 {
03214 continue;
03215 }
03216
03217 #ifdef __APPLE__
03218 if (!is_absolute)
03219 {
03220 libname = "${";
03221 libname += prefix;
03222 libname += "ROOT}/${";
03223 libname += get_package_name ();
03224 libname += "_tag}/";
03225 libname += library;
03226 libname += ".bundle";
03227
03228 name = library;
03229 name += ".bundle";
03230
03231 if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
03232 {
03233 continue;
03234 }
03235 }
03236 #endif
03237 }
03238 }
03239
03244 Use* Use::get_selected_version ()
03245 {
03246
03247
03248 if (!discarded) return (this);
03249
03250 Package* p = m_package;
03251
03252 Use::UsePtrVector& uses = p->get_uses ();
03253
03254 bool dbg = Cmt::get_debug ();
03255
03256 int size = uses.size ();
03257
03258 for (int i = 0; i < size; i++)
03259 {
03260 Use* u = uses[i];
03261 if (u == 0) continue;
03262 if (u->discarded) continue;
03263 if (dbg)
03264 {
03265 cout << "Use::get_selected_version> for package " << get_package_name ()
03266 << " got a version " << u << endl;
03267 }
03268 return (u);
03269 }
03270
03271 return (0);
03272 }
03273
03281 Use* Use::set_selected_version (Use* selected_use)
03282 {
03283 if (this == selected_use) return (this);
03284
03285 static UsePtrVector& uses = get_ordered_uses ();
03286
03287 if (m_index >= 0)
03288 {
03289
03290
03291
03292 selected_use->m_index = m_index;
03293 selected_use->auto_imports = auto_imports;
03294
03295 selected_use->undiscard ();
03296
03297 m_index = -1;
03298
03299 uses[selected_use->m_index] = selected_use;
03300 }
03301
03302 discard ();
03303
03304 return (selected_use);
03305 }
03306
03307 void Use::set_auto_imports (State new_state)
03308 {
03309 if (Cmt::get_debug ())
03310 {
03311 cout << "Use::set_auto_imports>(" << get_package_name () << ") "
03312 << auto_imports << " -> " << new_state << endl;
03313 }
03314
03315 if (auto_imports == new_state) return;
03316
03317 State old_state = auto_imports;
03318
03319 auto_imports = new_state;
03320
03321
03322
03323 if ((old_state == Off) && (new_state == On))
03324 {
03325 cmt_string s;
03326 static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
03327
03328 if (Cmt::get_debug ())
03329 {
03330 s = "Use::set_auto_imports>(";
03331 s += get_package_name ();
03332 s += ") ";
03333
03334 cout << s << endl;
03335 }
03336
03337 for (int i = 0; i < sub_uses.size (); i++)
03338 {
03339 Use* u = sub_uses[i];
03340 State state = sub_use_auto_imports[i];
03341
03342 if (Cmt::get_debug ())
03343 {
03344 s += " ";
03345 s += u->get_package_name ();
03346 s += "(";
03347 s += state_text[state];
03348 s += ")";
03349 }
03350
03351 if (state == Unspecified)
03352 {
03353 u->set_auto_imports (On);
03354 }
03355 }
03356
03357 if (Cmt::get_debug ())
03358 {
03359 cout << s << endl;
03360 }
03361 }
03362 }
03363
03364 void Use::set_native_version (bool state)
03365 {
03366 m_has_native_version = state;
03367 }
03368
03369 bool Use::has_native_version () const
03370 {
03371 return (m_has_native_version);
03372 }
03373
03374 Package* Use::get_package () const
03375 {
03376 return (m_package);
03377 }
03378
03379 const cmt_string& Use::get_package_name () const
03380 {
03381 static const cmt_string null = "";
03382
03383 Package* p = m_package;
03384 if (p == 0) return (null);
03385
03386 return (p->get_name ());
03387 }
03388
03389 void Use::set_package_name (const cmt_string& name)
03390 {
03391 Package* p = Package::add (name);
03392
03393 m_package = p;
03394 p->add_use (this);
03395 }
03396
03397 int Use::get_index () const
03398 {
03399 return (m_index);
03400 }
03401
03402
03403 bool Use::get_all_clients (const cmt_string& to_name)
03404 {
03405 Use::UsePtrVector& uses = Use::get_ordered_uses ();
03406
03407 Use* use = Use::find (to_name);
03408
03409 if (use == 0)
03410 {
03411 cerr << "#CMT> No access to " << to_name << endl;
03412 return (false);
03413 }
03414
03415 cmt_map <cmt_string, Use*> all_clients;
03416 cmt_map <cmt_string, Use*> all_clients_ok;
03417
03418 const cmt_string& name = get_package_name ();
03419
03420 Use* me = this;
03421
03422 all_clients.add (name, me);
03423 all_clients_ok.add (name, me);
03424
03425 bool status = get_all_clients (use, to_name, all_clients, all_clients_ok);
03426
03427 return (status);
03428 }
03429
03430
03431 bool Use::get_all_clients (Use* to,
03432 const cmt_string& result,
03433 cmt_map <cmt_string, Use*>& all_clients,
03434 cmt_map <cmt_string, Use*>& all_clients_ok)
03435 {
03436 if (this == to)
03437 {
03438 cout << result << endl;
03439 return (true);
03440 }
03441
03442 const cmt_string& to_name = to->get_package_name ();
03443 const cmt_string& to_version = to->version;
03444
03445
03446
03447 if (all_clients.has (to_name))
03448 {
03449 if (all_clients_ok.has (to_name))
03450 {
03451 cout << " ..." << result << endl;
03452 return (true);
03453 }
03454 else
03455 {
03456 return (false);
03457 }
03458 }
03459
03460 all_clients.add (to_name, to);
03461
03462 bool status = false;
03463
03464 Use::UsePtrVector& uses = Use::get_ordered_uses ();
03465 Use* use = 0;
03466
03467 for (int n = 0; n < uses.size (); ++n)
03468 {
03469 use = uses[n];
03470
03471 if (use->discarded) continue;
03472
03473 if (!use->located ()) continue;
03474
03475 if (use == to) continue;
03476
03477 if (use->is_client (to_name, to_version))
03478 {
03479 const cmt_string& n = use->get_package_name ();
03480
03481 cmt_string r;
03482
03483 if ((use->initial_scope != ScopeUnspecified) &&
03484 (use->initial_scope != ScopePublic))
03485 {
03486 r += "(private)";
03487 }
03488
03489 if (use->auto_imports == Off) r += "(no_auto_imports)";
03490
03491 r += n;
03492 r += ".";
03493 r += result;
03494
03495
03496
03497 if (get_all_clients (use, r, all_clients, all_clients_ok))
03498 {
03499 all_clients_ok.add (n, use);
03500 status = true;
03501 }
03502 }
03503 }
03504
03505 use = this;
03506
03507 if (use->is_client (to_name, to_version))
03508 {
03509 const cmt_string& n = use->get_package_name ();
03510
03511 cmt_string r;
03512
03513 if ((use->initial_scope != ScopeUnspecified) &&
03514 (use->initial_scope != ScopePublic))
03515 {
03516 r += "(private)";
03517 }
03518
03519 if (use->auto_imports == Off) r += "(no_auto_imports)";
03520
03521 r += n;
03522 r += ".";
03523 r += result;
03524
03525
03526
03527 if (get_all_clients (use, r, all_clients, all_clients_ok))
03528 {
03529 all_clients_ok.add (n, use);
03530 status = true;
03531 }
03532 }
03533
03534 return (status);
03535 }
03536
03544 bool Use::get_paths (Use* to, UsePtrVector& list)
03545 {
03546 bool is_in_path = false;
03547 bool cycle = false;
03548 bool already_in_path = false;
03549 bool dbg = Cmt::get_debug ();
03550
03551 static int level = 0;
03552
03553 int size = 0;
03554
03555 if (level == 0)
03556 {
03557 unselect_all ();
03558 selected = false;
03559 }
03560
03561 if (selected)
03562 {
03568 size = list.size ();
03569
03570 for (int m = 0; m < size; m++)
03571 {
03572 Use* u = list[m];
03573 if (u == this)
03574 {
03575 if (dbg)
03576 {
03577 for (int lll = 0; lll < level; lll++) cout << " ";
03578 cout << " Use::get_paths." << level << "> try1.2 sub="
03579 << get_package_name () << " already_in_path " << endl;
03580 }
03581
03582 return (true);
03583 }
03584 }
03585
03586 return (false);
03587 }
03588
03589 selected = true;
03590
03591 if (dbg)
03592 {
03593 for (int lll = 0; lll < level; lll++) cout << " ";
03594 cout << "Use::get_paths." << level << ">" << get_package_name ()
03595 << " to=" << to->get_package_name ()
03596 << " list=[";
03597
03598 for (int m = 0; m < list.size (); m++)
03599 {
03600 Use* u = list[m];
03601 cout << u->get_package_name () << " ";
03602 }
03603
03604 cout << "]" << endl;
03605 }
03606
03611
03612
03613 if (this->get_package_name () == to->get_package_name ())
03614 {
03615
03616 is_in_path = true;
03617 }
03618 else
03619 {
03623 size = sub_uses.size ();
03624
03625 if (dbg)
03626 {
03627 for (int lll = 0; lll < level; lll++) cout << " ";
03628 cout << " Use::get_paths." << level << "> size=" << size << endl;
03629 }
03630
03631 for (int n = 0; n < size; n++)
03632 {
03633 Use* use = sub_uses[n];
03634
03635 if (use == 0) continue;
03636
03637 if (dbg)
03638 {
03639 for (int lll = 0; lll < level; lll++) cout << " ";
03640 cout << " Use::get_paths." << level << "> try1 sub="
03641 << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
03642 }
03643
03644 if (use->discarded)
03645 {
03646 Use* u;
03647
03648 u = use->get_selected_version ();
03649 if (u == 0)
03650 {
03656 continue;
03657 }
03658
03659 use = u;
03660 }
03661
03662 if (dbg)
03663 {
03664 for (int lll = 0; lll < level; lll++) cout << " ";
03665 cout << " Use::get_paths." << level << "> try2 sub="
03666 << use->get_package_name () << " " << use->discarded << endl;
03667 }
03668
03669 level++;
03670 bool r = use->get_paths (to, list);
03671 level--;
03672
03673 if (r)
03674 {
03675 is_in_path = true;
03676 }
03677 }
03678 }
03679
03680 if (is_in_path)
03681 {
03682 if (dbg)
03683 {
03684 for (int lll = 0; lll < level; lll++) cout << " ";
03685 cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
03686 }
03687 list.push_back (this);
03688 }
03689
03690 return (is_in_path);
03691 }
03692
03693
03694 bool Use::located () const
03695 {
03696 return (m_located);
03697 }
03698
03699
03700 void Use::show_sub_uses (const cmt_string& request, bool skip_discarded)
03701 {
03702 Use* current = &(Use::current ());
03703 int n;
03704 Use* use;
03705 static int level = 0;
03706
03707 if (skip_discarded && discarded) return;
03708
03709 if (level > 0)
03710 {
03711 cout << "# ";
03712 for (n = 0; n < (level-1); n++) cout << " ";
03713
03714 if (request == "")
03715 {
03716 cout << "use " << get_package_name () << " " << specified_version;
03717
03718 if (this == current)
03719 {
03720 cout << " (current)";
03721 }
03722 else
03723 {
03724 if (specified_path != "") cout << " " << specified_path;
03725 }
03726 }
03727 else
03728 {
03729 cout << "use " << request;
03730 }
03731
03732 if (version_alias != "")
03733 {
03734 cout << " | " << version_alias << " " << path_alias;
03735 }
03736
03737 if (initial_scope == ScopeUnspecified) cout << " (unspecified)";
03738 else if (initial_scope != ScopePublic) cout << " (private)";
03739
03740 if (auto_imports == Off) cout << " (no_auto_imports)";
03741
03742 if (style == no_version_style) cout << " (no_version_directory)";
03743
03744 if (m_has_native_version)
03745 {
03746 cmt_string n = get_package_name ();
03747 n += "_native_version";
03748
03749 Symbol* s = Symbol::find (n);
03750 if (s != 0)
03751 {
03752 cmt_string value = s->resolve_macro_value ();
03753 cout << " (native_version=" << value << ")";
03754 }
03755 }
03756
03757 cout << endl;
03758 }
03759
03760 if (selected) return;
03761 selected = true;
03762
03763 level++;
03764 for (n = 0; n < sub_uses.size (); n++)
03765 {
03766 use = sub_uses[n];
03767 if (use == 0) continue;
03768
03769 const cmt_string& request = requests[n];
03770
03771 ScopeType saved_scope = use->initial_scope;
03772 State saved_state = use->auto_imports;
03773
03774 use->initial_scope = sub_use_scopes[n];
03775 use->auto_imports = sub_use_auto_imports[n];
03776
03777 use->show_sub_uses (request, skip_discarded);
03778
03779 use->initial_scope = saved_scope;
03780 use->auto_imports = saved_state;
03781 }
03782 level--;
03783 }
03784
03785
03786 Use& Use::current ()
03787 {
03788 static UseVector& instances = get_instances ();
03789 static Use* current_use = 0;
03790
03791 if ((current_use == 0) || (instances.size () == 0))
03792 {
03793 Use& use_object = instances.add ();
03794 current_use = &use_object;
03795 }
03796
03797 return (*current_use);
03798 }
03799
03800
03801 const Use& Use::const_current ()
03802 {
03803 const Use& use = Use::current ();
03804
03805 return (use);
03806 }
03807
03808
03809 Use::UseVector& Use::get_instances ()
03810 {
03811 static Database& db = Database::instance ();
03812 static UseVector& instances = db.all_uses ();
03813
03814 return (instances);
03815 }
03816
03817
03818 Use::UsePtrVector& Use::get_ordered_uses ()
03819 {
03820 static Database& db = Database::instance ();
03821 static UsePtrVector& uses = db.uses ();
03822
03823 return (uses);
03824 }
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834 Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
03835 {
03836 Use* selected = ref_use;
03837
03838 int ref_v = -1;
03839 int ref_r = -1;
03840 int ref_p = -1;
03841 cmt_string ref_pp;
03842
03843 int new_v = -1;
03844 int new_r = -1;
03845 int new_p = -1;
03846 cmt_string new_pp;
03847
03848 int alias_v = -1;
03849 int alias_r = -1;
03850 int alias_p = -1;
03851 cmt_string alias_pp;
03852
03853 enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
03854
03855
03856 cmt_string ref_version = ref_use->specified_version;
03857 cmt_string new_version = new_use->specified_version;
03858
03859 CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
03860 ref_pp = ref_use->path;
03861
03862 CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
03863 new_pp = new_use->path;
03864
03865 if (new_use->version_alias != "")
03866 {
03867 has_alias = new_has_alias;
03868 CmtSystem::is_version_directory (new_use->version_alias,
03869 alias_v, alias_r, alias_p);
03870 alias_pp = new_use->path_alias;
03871 }
03872 else if (ref_use->version_alias != "")
03873 {
03874 has_alias = ref_has_alias;
03875 CmtSystem::is_version_directory (ref_use->version_alias,
03876 alias_v, alias_r, alias_p);
03877 alias_pp = ref_use->path_alias;
03878 }
03879
03880 ref_use->undiscard ();
03881 new_use->undiscard ();
03882
03883 if (new_v != ref_v)
03884 {
03885 if (has_alias != no_alias)
03886 {
03887 if (has_alias == new_has_alias)
03888 {
03889 new_v = alias_v;
03890 new_r = alias_r;
03891 new_p = alias_p;
03892 new_pp = alias_pp;
03893 }
03894 else if (has_alias == ref_has_alias)
03895 {
03896 ref_v = alias_v;
03897 ref_r = alias_r;
03898 ref_p = alias_p;
03899 ref_pp = alias_pp;
03900 }
03901 }
03902 }
03903
03904 bool ref_v_wildcarded = ((ref_v) == -1);
03905 bool ref_r_wildcarded = ((ref_r) == -1);
03906 bool ref_p_wildcarded = ((ref_p) == -1);
03907
03908 bool ref_v_explicit = !ref_v_wildcarded;
03909 bool ref_r_explicit = !ref_r_wildcarded;
03910 bool ref_p_explicit = !ref_p_wildcarded;
03911
03912 bool new_v_wildcarded = ((new_v) == -1);
03913 bool new_r_wildcarded = ((new_r) == -1);
03914 bool new_p_wildcarded = ((new_p) == -1);
03915
03916 bool new_v_explicit = !new_v_wildcarded;
03917 bool new_r_explicit = !new_r_wildcarded;
03918 bool new_p_explicit = !new_p_wildcarded;
03919
03920 bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
03921
03922 cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
03923 cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
03924 cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
03925
03926 cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
03927 cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
03928 cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
03929
03930
03931 CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
03932 CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
03933
03934 cmt_string new_selected_version = new_use->version;
03935
03936 if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
03937 {
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952 if (new_v > ref_v)
03953 {
03954 if (verbose && !Cmt::get_quiet ())
03955 {
03956 cerr << "# Select " << new_vc << " version " << new_version
03957 << " of package " << ref_use->get_package_name ()
03958 << " instead of existing " << ref_vc << " " << ref_version
03959 << endl;
03960 }
03961
03962 if (ref_use != new_use) ref_use->discard ();
03963 selected = new_use;
03964 selected->done = false;
03965 }
03966 }
03967 else if (new_v_wildcarded || ref_v_wildcarded)
03968 {
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980 if (ref_v_wildcarded && new_v_explicit)
03981 {
03982 if ((ref_use->real_path != new_use->real_path) ||
03983 (ref_use->version != new_use->version))
03984 {
03985 if (ref_use != new_use) ref_use->discard ();
03986 selected = new_use;
03987 selected->done = false;
03988
03989 if (verbose && !Cmt::get_quiet ())
03990 {
03991 cerr << "# Select explicit version " << new_version
03992 << "(" << new_use->version << ")"
03993 << " of package " << ref_use->get_package_name ()
03994 << " instead of existing wildcarded " << ref_version
03995 << "(" << ref_use->version << ")"
03996 << endl;
03997 }
03998 }
03999 else
04000 {
04001 if (ref_use != new_use) new_use->discard ();
04002
04003 }
04004 }
04005 else
04006 {
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019 if (ref_use != new_use) new_use->discard ();
04020 }
04021 }
04022 else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
04023 {
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033 if (ref_r_wildcarded && new_r_explicit)
04034 {
04035
04036
04037 if ((ref_use->real_path != new_use->real_path) ||
04038 (ref_use->version != new_use->version))
04039 {
04040 if (ref_use != new_use) ref_use->discard ();
04041 selected = new_use;
04042 selected->done = false;
04043
04044 if (verbose && !Cmt::get_quiet ())
04045 {
04046 cerr << "# Select explicit release " << new_version
04047 << " of package " << ref_use->get_package_name ()
04048 << " instead of existing wildcarded " << ref_version
04049 << endl;
04050 }
04051 }
04052 else
04053 {
04054
04055
04056 if (ref_use != new_use) new_use->discard ();
04057
04058 }
04059 }
04060 else
04061 {
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072 if (ref_use != new_use) new_use->discard ();
04073 }
04074 }
04075 else if (new_r > ref_r)
04076 {
04077 if (verbose && !Cmt::get_quiet ())
04078 {
04079 cerr << "# Select " << new_rc << " release " << new_version
04080 << " of package " << ref_use->get_package_name ()
04081 << " instead of existing " << ref_rc << " " << ref_version
04082 << endl;
04083 }
04084
04085 if (ref_use != new_use) ref_use->discard ();
04086 selected = new_use;
04087 selected->done = false;
04088 }
04089 else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
04090 {
04091
04092
04093
04094
04095
04096 if (ref_p_wildcarded && new_p_explicit)
04097 {
04098 if ((ref_use->real_path != new_use->real_path) ||
04099 (ref_use->version != new_use->version))
04100 {
04101 if (ref_use != new_use) ref_use->discard ();
04102 selected = new_use;
04103 selected->done = false;
04104
04105 if (verbose && !Cmt::get_quiet ())
04106 {
04107 cerr << "# Select explicit patch " << new_version
04108 << " of package " << ref_use->get_package_name ()
04109 << " instead of existing wildcarded " << ref_version
04110 << endl;
04111 }
04112 }
04113 else
04114 {
04115 if (ref_use != new_use) new_use->discard ();
04116 ref_use->version = new_selected_version;
04117 }
04118 }
04119 else
04120 {
04121
04122
04123
04124
04125
04126
04127
04128
04129
04130
04131
04132
04133 if (ref_use != new_use) new_use->discard ();
04134 }
04135 }
04136 else if (new_p > ref_p)
04137 {
04138 if (verbose && !Cmt::get_quiet ())
04139 {
04140 cerr << "# Select " << new_pc << " patch " << new_version
04141 << " of package " << ref_use->get_package_name ()
04142 << " instead of existing " << ref_pc << " " << ref_version
04143 << endl;
04144 }
04145
04146 if (ref_use != new_use) ref_use->discard ();
04147 selected = new_use;
04148 selected->done = false;
04149 }
04150 else if (new_pp != ref_pp)
04151 {
04152 if (ref_use != new_use) ref_use->discard ();
04153 selected = new_use;
04154 selected->done = false;
04155 }
04156
04157 return (selected);
04158 }
04159
04160
04161
04162
04163
04164
04165 Package* Package::find (const cmt_string& name)
04166 {
04167 static PackageMap& PackageMap = package_map ();
04168
04169 Package* result = 0;
04170
04171 result = PackageMap.find (name);
04172
04173 return (result);
04174 }
04175
04176 Package* Package::add (const cmt_string& name)
04177 {
04178 static PackageVector& Packages = packages ();
04179 static PackageMap& PackageMap = package_map ();
04180
04181 {
04182 Package* package;
04183
04184 package = find (name);
04185 if (package != 0) return (package);
04186 }
04187
04188 Package& package = Packages.add ();
04189 PackageMap.add (name, package);
04190
04191 package.m_name = name;
04192
04193 if (name == "CMT")
04194 {
04195 package.m_is_cmt = true;
04196 }
04197 else if (name == "methods")
04198 {
04199 package.m_is_cmt = true;
04200 }
04201
04202 if (Cmt::get_debug ())
04203 {
04204 cout << "Package::add (" << name << ")" << endl;
04205 }
04206
04207 return (&package);
04208 }
04209
04210 Package::PackageVector& Package::packages ()
04211 {
04212 static Database& db = Database::instance ();
04213 static PackageVector& Packages = db.packages ();
04214
04215 return (Packages);
04216 }
04217
04218 Package::PackageMap& Package::package_map ()
04219 {
04220 static Database& db = Database::instance ();
04221 static PackageMap& PackageMap = db.package_map ();
04222
04223 return (PackageMap);
04224 }
04225
04226 void Package::clear_all ()
04227 {
04228 static PackageVector& Packages = packages ();
04229 static PackageMap& PackageMap = package_map ();
04230
04231 PackageMap.clear ();
04232 Packages.clear ();
04233 }
04234
04235 Package::Package () : m_is_cmt (false)
04236 {
04237 if (Cmt::get_debug ())
04238 {
04239 cout << "Package::Package" << endl;
04240 }
04241 }
04242
04243 Package::~Package ()
04244 {
04245 m_name = "";
04246 }
04247
04248 const cmt_string& Package::get_name () const
04249 {
04250 return (m_name);
04251 }
04252
04253 void Package::add_use (Use* use)
04254 {
04255 for (int i = 0; i < m_uses.size (); i++)
04256 {
04257 Use* u = m_uses[i];
04258 if (u == use) return;
04259 }
04260
04261 m_uses.push_back (use);
04262 }
04263
04264 void Package::remove_use (Use* use)
04265 {
04266 if (Cmt::get_debug ())
04267 {
04268 cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
04269 cout << " name=" << m_name
04270 << " uses=" << m_uses.size () << endl;
04271 }
04272
04273 Use::UsePtrVector temp;
04274
04275 temp = m_uses;
04276
04277 m_uses.clear ();
04278
04279 for (int i = 0; i < temp.size (); i++)
04280 {
04281 Use* u = temp[i];
04282 if (u != use)
04283 {
04284 m_uses.push_back (u);
04285 }
04286 }
04287 }
04288
04289 Use::UsePtrVector& Package::get_uses ()
04290 {
04291 return (m_uses);
04292 }
04293
04294 bool Package::is_cmt ()
04295 {
04296 return (m_is_cmt);
04297 }
04298
04299 static void show_packages ()
04300 {
04301 Package::PackageVector& vector = Package::packages ();
04302
04303 int i;
04304 int j;
04305
04306 cout << "### Packages: ";
04307 for (i = 0; i < vector.size (); i++)
04308 {
04309 Package& p = vector[i];
04310 cout << p.get_name () << "[";
04311 Use::UsePtrVector& uses = p.get_uses ();
04312 for (j = 0; j < uses.size (); j++)
04313 {
04314 Use* u = uses[j];
04315 cout << u << ",";
04316 }
04317
04318 cout << "] ";
04319 }
04320 cout << endl;
04321
04322 {
04323 static Use::UsePtrVector& uses = Use::get_ordered_uses ();
04324
04325 cout << "### Uses: ";
04326 for (i = 0; i < uses.size (); i++)
04327 {
04328 Use* u = uses[i];
04329 cout << "[" << u << "]" << u->get_package_name () << " ";
04330 }
04331 }
04332
04333 cout << endl;
04334 }
04335