Main?Page | Class?Hierarchy | Class?List | File?List | Class?Members | File?Members

cmt_tag.cxx

Go to the documentation of this file.
00001 //-----------------------------------------------------------
00002 // Copyright Christian Arnault LAL-Orsay CNRS
00003 // 
00004 // See the complete license in cmt_license.txt "http://www.cecill.info". 
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 /*  Operations on Tags                                      */
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                     // Although this other contradictory tag is already selected,
00108                     // its priority is lower. Therefore it will lose !! It has to be 
00109                     // unselected ...
00110                     //
00111 
00112                   ref->unmark ();
00113                 }
00114               else
00115                 {
00116                     /*
00117                   if (!Cmt::quiet)
00118                     {
00119                       cerr << "Cannot mark excluded tag " << m_name << " p=" << m_priority
00120                            << " because " << ref->m_name << "(" << ref->m_priority << ")" << endl;
00121                       show (0);
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   //if (tag->m_tag_refs.size () == 0)
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 ())  // it was previously 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           if (!Cmt::quiet)
00246             {
00247               cerr << "Excluding tag " << n << "(" << ref->m_priority << ") from tag " 
00248                    << name << "(" << tag->m_priority << ")" << endl;
00249             }
00250             */
00251 
00252           tag->add_tag_exclude (ref);
00253           ref->add_tag_exclude (tag);
00254         }
00255 
00256         //
00257         // We have to check that some of the excluded tags may be already selected.
00258         // Then we have to figure out which one has to win:
00259         //
00260         //  the one with the highest priority
00261         //  or the first that had been declared.
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                 // Several contradictory tags are selected and have the same priority!!
00305                 //
00306             }
00307 
00308             //
00309             // We have at least one selected, and one winner. 
00310             // All others will be unselected.
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   TagPtrVector& vector = tags ();
00342 
00343   int tag_index;
00344   Tag* tag;
00345 
00346   if (vector.size () == 0) return (0);
00347 
00348   for (tag_index = 0; tag_index < vector.size (); tag_index++)
00349     {
00350       tag = vector[tag_index];
00351 
00352       if ((tag != 0) && (tag->m_name == name))
00353         {
00354           return (tag);
00355         }
00356     }
00357 
00358   return (0);
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   int tag_index;
00371 
00372   if (instances.size () == 0) return (0);
00373 
00374   for (tag_index = 0; tag_index < instances.size (); tag_index++)
00375     {
00376       Tag& tag = instances[tag_index];
00377 
00378       if (tag.m_name == name)
00379         {
00380           return (&tag);
00381         }
00382     }
00383 
00384   return (0);
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           if (!Cmt::quiet)
00413             {
00414               cerr << "increasing priority of " << name << " p=" << priority << endl;
00415             }
00416             */
00417         }
00418       else
00419         {
00420             /*
00421           if (!Cmt::quiet)
00422             {
00423               cerr << "keeping priority of " << name << " p=" << tag->m_priority << endl;
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       //cout << "context=" << m_context << " use=" << m_def_use << endl;
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       //cout << " (" << priority_text[m_priority] << ")";
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   Check if a tag is part of the operands of a tag
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   Check if a tag is part of the refs of a tag
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 

Generated on Mon May 2 10:25:06 2005 for CMT by 1.3.5