00001
00002
00003
00004
00005
00006
00007 #include
00008 #include
00009 #include
00010 #include
00011
00012 #include "cmt_tag.h"
00013 #include "cmt_database.h"
00014 #include "cmt_log.h"
00015
00016
00017
00018
00019
00020
00021
00022
00023 void Tag::unmark ()
00024 {
00025 if (!is_primary ()) return;
00026 if (!m_selected) return;
00027
00028 Log;
00029
00030 if ((m_priority == PriorityDefault) ||
00031 (m_priority == PrioritySite) ||
00032 (m_priority == PriorityUname)) return;
00033
00034 log << "Unmarking tag[" << this << "] " << m_name << " p=" << m_priority << log_endl;
00035
00036 m_selected = false;
00037 m_def_use = 0;
00038 }
00039
00040
00041 void Tag::unmark_all ()
00042 {
00043 static TagPtrVector& vector = tags ();
00044
00045 int tag_number;
00046
00047 for (tag_number = 0; tag_number < vector.size (); tag_number++)
00048 {
00049 Tag* tag = vector[tag_number];
00050
00051 tag->unmark ();
00052 }
00053 }
00054
00059 void Tag::restore_tree ()
00060 {
00061 static TagPtrVector& vector = tags ();
00062
00063 int tag_number;
00064
00065 for (tag_number = 0; tag_number < vector.size (); tag_number++)
00066 {
00067 Tag* tag = vector[tag_number];
00068
00069 if (tag->is_primary () && tag->is_selected ())
00070 {
00071 if (tag->m_tag_refs.size () > 0)
00072 {
00073 int number;
00074
00075 for (number = 0; number < tag->m_tag_refs.size (); number++)
00076 {
00077 Tag* ref = tag->m_tag_refs[number];
00078
00079 ref->mark ();
00080 }
00081 }
00082 }
00083 }
00084 }
00085
00086
00087 void Tag::mark ()
00088 {
00089 if (!is_primary ()) return;
00090 if (m_selected) return;
00091
00092 Log;
00093
00094 if (m_tag_excludes.size () > 0)
00095 {
00096 int number;
00097
00098 for (number = 0; number < m_tag_excludes.size (); number++)
00099 {
00100 Tag* ref = m_tag_excludes[number];
00101
00102 if (ref->is_selected ())
00103 {
00104 if (m_priority > ref->m_priority)
00105 {
00106
00107
00108
00109
00110
00111
00112 ref->unmark ();
00113 }
00114 else
00115 {
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 return;
00126 }
00127 }
00128 }
00129 }
00130
00131 m_selected = true;
00132
00133 log << "Marking tag[" << this << "] " << m_name << " p=" << m_priority << log_endl;
00134
00135 if (m_tag_refs.size () > 0)
00136 {
00137 int number;
00138
00139 for (number = 0; number < m_tag_refs.size (); number++)
00140 {
00141 Tag* ref = m_tag_refs[number];
00142
00143 ref->mark ();
00144 }
00145 }
00146 }
00147
00148
00149 void Tag::action (const CmtSystem::cmt_string_vector& words, Use* use)
00150 {
00151 cmt_string name;
00152 Tag* tag;
00153 Tag* ref;
00154
00155 if (words.size () < 1) return;
00156 name = words[1];
00157 if (name == "") return;
00158
00159 tag = add (name, PriorityUserTag, "use", use);
00160
00161 int priority = PriorityUserTag;
00162 if (tag->m_priority > priority)
00163 {
00164 priority = tag->m_priority;
00165 }
00166
00167
00168
00169
00170 tag->m_set_use = use;
00171
00172
00173
00174 for (int i = 2; i < words.size (); i++)
00175 {
00176 name = words[i];
00177 if (name == "") break;
00178 ref = add (name, priority, "use", use);
00179 tag->add_tag_ref (ref);
00180 if (tag->is_selected ())
00181 {
00182 ref->mark ();
00183 }
00184 }
00185 }
00186
00187
00188 void Tag::action_apply (const CmtSystem::cmt_string_vector& words, Use* use)
00189 {
00190 cmt_string name;
00191 Tag* tag;
00192
00193 if (words.size () < 1) return;
00194 name = words[1];
00195 if (name == "") return;
00196
00197 Symbol::expand (name);
00198
00199 if (name == "")
00200 {
00201 if (!Cmt::get_quiet ())
00202 {
00203 cerr << "#CMT> Warning: apply_tag with empty name [" << words[1] << "]" << endl;
00204 }
00205 }
00206 else
00207 {
00208 tag = find (name);
00209 if (tag == 0)
00210 {
00211 tag = add (name, PriorityUserTag, "use", use);
00212 }
00213
00214 tag->mark ();
00215 }
00216 }
00217
00218
00219 void Tag::action_exclude (const CmtSystem::cmt_string_vector& words, Use* use)
00220 {
00221 cmt_string name;
00222 Tag* tag;
00223 Tag* ref;
00224
00225 if (words.size () < 1) return;
00226 name = words[1];
00227 if (name == "") return;
00228
00229 tag = add (name, PriorityUserTag, "use", use);
00230
00231 if (tag->m_tag_excludes.size () == 0)
00232 {
00233 tag->m_set_use = use;
00234
00235 int i;
00236
00237 for (i = 2; i < words.size (); i++)
00238 {
00239 cmt_string n;
00240 n = words[i];
00241 if (n == "") break;
00242 ref = add (n, PriorityUserTag, "use", use);
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 tag->add_tag_exclude (ref);
00253 ref->add_tag_exclude (tag);
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 int count = 0;
00265 int winner_count = 0;
00266
00267 Tag* winner = 0;
00268
00269 if (tag->is_selected ())
00270 {
00271 count++;
00272 winner = tag;
00273 winner_count = 1;
00274 }
00275
00276 for (i = 0; i < tag->m_tag_excludes.size (); i++)
00277 {
00278 Tag* ref = tag->m_tag_excludes[i];
00279
00280 if (ref == 0) continue;
00281
00282 if (ref->is_selected ())
00283 {
00284 count++;
00285
00286 if ((winner == 0) ||
00287 (ref->m_priority > winner->m_priority))
00288 {
00289 winner = ref;
00290 winner_count = 1;
00291 }
00292 else if (ref->m_priority == winner->m_priority)
00293 {
00294 winner_count++;
00295 }
00296 }
00297 }
00298
00299 if (count > 1)
00300 {
00301 if (winner_count > 1)
00302 {
00303
00304
00305
00306 }
00307
00308
00309
00310
00311
00312
00313 if (tag != winner)
00314 {
00315 tag->unmark ();
00316 }
00317
00318 for (i = 0; i < tag->m_tag_excludes.size (); i++)
00319 {
00320 Tag* ref = tag->m_tag_excludes[i];
00321
00322 if (ref == 0) continue;
00323 if (ref == winner) continue;
00324
00325 ref->unmark ();
00326 }
00327 }
00328 }
00329 }
00330
00331
00332 Tag* Tag::find (const cmt_string& name)
00333 {
00334 TagMap& map = tag_map ();
00335
00336 Tag* result = map.find (name);
00337
00338 return (result);
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 }
00361
00362
00363 Tag* Tag::find (const cmt_string& name, TagMap& instances)
00364 {
00365 Tag* result = instances.find (name);
00366
00367 return (result);
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 }
00387
00388
00389 Tag* Tag::add (const cmt_string& name,
00390 int priority,
00391 const cmt_string& context,
00392 Use* use)
00393 {
00394 Log;
00395
00396 TagMap& map = tag_map ();
00397 TagPtrVector& vector = tags ();
00398 TagVector& instances = all_tags ();
00399
00400 Tag* tag;
00401
00402 if (name == "") return (0);
00403
00404 tag = find (name);
00405 if (tag != 0)
00406 {
00407 if (priority > tag->m_priority)
00408 {
00409 tag->m_priority = priority;
00410
00411
00412
00413
00414
00415
00416
00417 }
00418 else
00419 {
00420
00421
00422
00423
00424
00425
00426 }
00427
00428 log << "re-adding tag[" << tag << "] " << name << " p=" << priority << log_endl;
00429
00430 return (tag);
00431 }
00432
00433 Tag& tag_object = instances.add ();
00434 tag = &tag_object;
00435 vector.push_back (tag);
00436 map.add (name, tag_object);
00437
00438 log << "adding tag[" << tag << "] " << name << " p=" << priority << log_endl;
00439
00440 tag->clear ();
00441
00442 tag->m_name = name;
00443 tag->m_priority = priority;
00444 tag->m_def_use = use;
00445 tag->m_context = context;
00446
00447 int pos = 0;
00448 int length = name.size ();
00449 while (pos < length)
00450 {
00451 int and_pos = name.find (pos, "&");
00452 if ((and_pos == cmt_string::npos) && (pos == 0)) break;
00453
00454 cmt_string op_name;
00455
00456 if (and_pos == cmt_string::npos)
00457 {
00458 name.substr (pos, op_name);
00459 }
00460 else
00461 {
00462 name.substr (pos, and_pos - pos, op_name);
00463 }
00464
00465 if (op_name != "")
00466 {
00467 Tag* t = find (op_name);
00468 if (t == 0)
00469 {
00470 t = add (op_name, priority, context, use);
00471 }
00472
00473 if (t != 0)
00474 {
00475 tag->m_and_operands.push_back (t);
00476 if (t->get_priority () > priority)
00477 {
00478 tag->m_priority = t->get_priority ();
00479 }
00480 }
00481 else
00482 {
00483 cerr << "#Tag::add> unknown tag " << op_name << " in tag expression" << endl;
00484 }
00485 }
00486
00487 if (and_pos == cmt_string::npos) break;
00488
00489 pos = and_pos + 1;
00490 }
00491
00492 return (tag);
00493 }
00494
00495
00496 int Tag::tag_number ()
00497 {
00498 static TagPtrVector& vector = tags ();
00499
00500 return (vector.size ());
00501 }
00502
00503
00504 Tag* Tag::tag (int index)
00505 {
00506 static TagPtrVector& vector = tags ();
00507
00508 return (vector[index]);
00509 }
00510
00511
00512 void Tag::clear_all ()
00513 {
00514 TagMap& map = tag_map ();
00515 TagPtrVector& vector = tags ();
00516 TagVector& instances = all_tags ();
00517
00518 int tag_index;
00519
00520 for (tag_index = 0; tag_index < instances.size (); tag_index++)
00521 {
00522 Tag& tag = instances[tag_index];
00523 tag.clear ();
00524 }
00525
00526 map.clear ();
00527 vector.clear ();
00528 instances.clear ();
00529 }
00530
00531
00532 Tag::TagMap& Tag::tag_map ()
00533 {
00534 static Database& db = Database::instance ();
00535 TagMap& map = db.tag_map ();
00536
00537 return (map);
00538 }
00539
00540
00541 Tag::TagVector& Tag::all_tags ()
00542 {
00543 static Database& db = Database::instance ();
00544 TagVector& vector = db.all_tags ();
00545
00546 return (vector);
00547 }
00548
00549
00550 Tag::TagPtrVector& Tag::tags ()
00551 {
00552 static Database& db = Database::instance ();
00553 TagPtrVector& vector = db.tags ();
00554
00555 return (vector);
00556 }
00557
00558
00559 Tag* Tag::get_default ()
00560 {
00561 static Tag default_tag;
00562 static bool initialized = false;
00563 if (!initialized)
00564 {
00565 initialized = true;
00566
00567 default_tag.m_name = "Default";
00568 default_tag.m_selected = true;
00569 default_tag.m_context = "Default";
00570 default_tag.m_priority = PriorityDefault;
00571 }
00572
00573 return (&(default_tag));
00574 }
00575
00576
00577 bool Tag::check_tag_used (const Tag* tag)
00578 {
00579 if (tag == 0) return (false);
00580
00581 if (tag->m_tag_refs.size () > 0) return (true);
00582 if (tag->m_tag_excludes.size () > 0) return (true);
00583
00584 return (false);
00585 }
00586
00587
00588 Tag::Tag () :
00589 m_name (""),
00590 m_selected (false),
00591 m_context (""),
00592 m_def_use (0),
00593 m_set_use (0),
00594 m_priority (0)
00595 {
00596 clear ();
00597 }
00598
00599
00600 Tag::Tag (const Tag& other)
00601 {
00602 clear ();
00603
00604 m_name = other.m_name;
00605 m_selected = other.m_selected;
00606 m_and_operands = other.m_and_operands;
00607 m_tag_refs = other.m_tag_refs;
00608 m_tag_excludes = other.m_tag_excludes;
00609 m_context = other.m_context;
00610 m_def_use = other.m_def_use;
00611 m_set_use = other.m_set_use;
00612 m_priority = other.m_priority;
00613 }
00614
00615
00616 Tag& Tag::operator = (const Tag& other)
00617 {
00618 clear ();
00619
00620 m_name = other.m_name;
00621 m_selected = other.m_selected;
00622 m_and_operands = other.m_and_operands;
00623 m_tag_refs = other.m_tag_refs;
00624 m_tag_excludes = other.m_tag_excludes;
00625 m_context = other.m_context;
00626 m_def_use = other.m_def_use;
00627 m_set_use = other.m_set_use;
00628 m_priority = other.m_priority;
00629
00630 return (*this);
00631 }
00632
00633
00634 Tag::~Tag ()
00635 {
00636 }
00637
00638
00639 void Tag::clear ()
00640 {
00641 m_name = "";
00642 m_tag_refs.clear ();
00643 m_tag_excludes.clear ();
00644 m_priority = PriorityUserTag;
00645 m_def_use = 0;
00646 m_set_use = 0;
00647 m_context = "";
00648
00649 m_selected = false;
00650 m_and_operands.clear ();
00651 }
00652
00653
00654 void Tag::add_tag_ref (Tag* ref)
00655 {
00656 if (ref == 0) return;
00657
00658 if (m_tag_refs.size () > 0)
00659 {
00660 int number;
00661
00662 for (number = 0; number < m_tag_refs.size (); number++)
00663 {
00664 Tag* t = m_tag_refs[number];
00665 if (t == ref) return;
00666 }
00667 }
00668
00669 m_tag_refs.push_back (ref);
00670 }
00671
00672
00673 void Tag::add_tag_exclude (Tag* ref)
00674 {
00675 if (ref == 0) return;
00676
00677 if (m_tag_excludes.size () > 0)
00678 {
00679 int number;
00680
00681 for (number = 0; number < m_tag_excludes.size (); number++)
00682 {
00683 Tag* t = m_tag_excludes[number];
00684 if (t == ref) return;
00685 }
00686 }
00687
00688 m_tag_excludes.push_back (ref);
00689 }
00690
00691
00692 void Tag::show_definition (bool quiet) const
00693 {
00694 static const cmt_string priority_text[] = {
00695 "Lowest",
00696 "Default",
00697 "Uname",
00698 "Config",
00699 "UserTag",
00700 "PrimaryUserTag",
00701 "Tag"
00702 };
00703
00704 if (m_name == "Default") return;
00705
00706 cout << m_name;
00707
00708 if (!quiet)
00709 {
00710
00711
00712 if ((m_context == "use") || (m_def_use != 0))
00713 {
00714 if (m_def_use != 0)
00715 {
00716 cout << " (from ";
00717 if (m_context != "use") cout << m_context;
00718 cout << "package " << m_def_use->get_package_name () << ")";
00719 }
00720 }
00721 else
00722 {
00723 cout << " (from " << m_context << ")";
00724 }
00725
00726
00727 if (m_tag_refs.size () > 0)
00728 {
00729 int number;
00730
00731 if (m_set_use != 0)
00732 {
00733 cout << " package " << m_set_use->get_package_name ();
00734 }
00735
00736 cout << " implies [";
00737
00738 for (number = 0; number < m_tag_refs.size (); number++)
00739 {
00740 Tag* ref = m_tag_refs[number];
00741 if (number > 0) cout << " ";
00742 cout << ref->m_name;
00743 }
00744
00745 cout << "]";
00746 }
00747
00748 if (m_tag_excludes.size () > 0)
00749 {
00750 int number;
00751
00752 if (m_set_use != 0)
00753 {
00754 cout << " package " << m_set_use->get_package_name ();
00755 }
00756
00757 cout << " excludes [";
00758
00759 for (number = 0; number < m_tag_excludes.size (); number++)
00760 {
00761 Tag* ref = m_tag_excludes[number];
00762 if (number > 0) cout << " ";
00763 cout << ref->m_name;
00764 }
00765
00766 cout << "]";
00767 }
00768 }
00769 cout << endl;
00770 }
00771
00772
00773 void Tag::show (bool quiet) const
00774 {
00775 if (is_primary () && is_selected ()) show_definition (quiet);
00776 }
00777
00778
00779 bool Tag::is_selected () const
00780 {
00781 if (is_primary ())
00782 {
00783 return (m_selected);
00784 }
00785 else
00786 {
00787 for (int i = 0; i < m_and_operands.size(); i++)
00788 {
00789 Tag* t = m_and_operands[i];
00790
00791 if (!t->is_selected ()) return (false);
00792 }
00793
00794 return (true);
00795 }
00796 }
00797
00798
00799 bool Tag::is_primary () const
00800 {
00801 return (m_and_operands.size() == 0);
00802 }
00803
00804
00805 const cmt_string& Tag::get_name () const
00806 {
00807 return (m_name);
00808 }
00809
00810
00811 int Tag::get_priority () const
00812 {
00813 return (m_priority);
00814 }
00815
00830 void Tag::install (TagMap& instances)
00831 {
00832 int i;
00833
00834 for (i = 0; i < m_and_operands.size (); i++)
00835 {
00836 Tag* t = m_and_operands[i];
00837 if (t != 0)
00838 {
00839 t = find (t->m_name, instances);
00840 m_and_operands[i] = t;
00841 }
00842 }
00843
00844 for (i = 0; i < m_tag_refs.size (); i++)
00845 {
00846 Tag* t = m_tag_refs[i];
00847 if (t != 0)
00848 {
00849 t = find (t->m_name, instances);
00850 m_tag_refs[i] = t;
00851 }
00852 }
00853
00854 for (i = 0; i < m_tag_excludes.size (); i++)
00855 {
00856 Tag* t = m_tag_excludes[i];
00857 if (t != 0)
00858 {
00859 t = find (t->m_name, instances);
00860 m_tag_excludes[i] = t;
00861 }
00862 }
00863 }
00864
00865
00866
00867
00868 bool Tag::use_operand (const Tag* other) const
00869 {
00870 if (other == this) return (true);
00871 if (m_and_operands.size () == 0) return (false);
00872
00873 for (int i = 0; i < m_and_operands.size (); i++)
00874 {
00875 Tag* t = m_and_operands[i];
00876
00877 if (t != 0)
00878 {
00879 if (t->use_operand (other)) return (true);
00880 }
00881 }
00882
00883 return (false);
00884 }
00885
00886
00887
00888
00889 bool Tag::use_ref (const Tag* other) const
00890 {
00891 if (other == this) return (false);
00892 if (m_tag_refs.size () == 0) return (false);
00893
00894 for (int i = 0; i < m_tag_refs.size (); i++)
00895 {
00896 Tag* t = m_tag_refs[i];
00897
00898 if (t == other) return (true);
00899 }
00900
00901 return (false);
00902 }
00903
00904