source: CMT/HEAD/source/cmt_tag.cxx @ 653

Last change on this file since 653 was 653, checked in by rybkin, 11 years ago

See C.L. 512

  • Property svn:eol-style set to native
File size: 20.8 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11
12#include "cmt_tag.h"
13#include "cmt_database.h"
14#include "cmt_log.h"
15
16/*----------------------------------------------------------*/
17/*                                                          */
18/*  Operations on Tags                                      */
19/*                                                          */
20/*----------------------------------------------------------*/
21
22/*----------------------------------------------------------*/
23void Tag::unmark ()
24{
25  if (!is_primary ()) return;
26  if (!m_selected) return;
27
28  Log;
29
30  if ((m_priority == PriorityDefault) ||
31      (m_priority == PrioritySite) ||
32      (m_priority == PriorityUname)) return;
33
34  log << "Unmarking tag[" << this << "] " << m_name << " p=" << m_priority << log_endl;
35
36  m_selected = false;
37  m_def_use = 0;
38  //m_act_context = "";
39}
40
41/*----------------------------------------------------------*/
42void Tag::unmark_all ()
43{
44  static TagPtrVector& vector = tags ();
45
46  int tag_number;
47
48  Log;
49  log << "Unmarking all tags (" << vector.size () << ")" << log_endl;
50
51  for (tag_number = 0; tag_number < vector.size (); tag_number++)
52    {
53      Tag* tag = vector[tag_number];
54
55      tag->unmark ();
56    }
57}
58
59/**
60 *   Restore the tag tree after cleaning up one tag and
61 *   its local tree.
62 */
63void Tag::restore_tree ()
64{
65  static TagPtrVector& vector = tags ();
66
67  int tag_number;
68
69  Log;
70  log << "Restore tags tree (" << vector.size () << ")" << log_endl;
71
72  for (tag_number = 0; tag_number < vector.size (); tag_number++)
73    {
74      Tag* tag = vector[tag_number];
75     
76      if (tag->is_primary () && tag->is_selected ())
77        {
78          if (tag->m_tag_refs.size () > 0)
79            {
80              int number;
81             
82              for (number = 0; number < tag->m_tag_refs.size (); number++)
83                {
84                  Tag* ref = tag->m_tag_refs[number];
85                 
86                  ref->mark ("");
87                }
88            }
89        }
90    }
91}
92
93/*----------------------------------------------------------*/
94void Tag::mark (const cmt_string& context)
95//void Tag::mark ()
96{
97  if (!is_primary ()) return;
98  if (m_selected) return;
99
100  Log;
101
102  const CmtSystem::cmt_string_vector& tags_remove = Cmt::get_tags_remove ();
103  for (int i = tags_remove.size () - 1; i >= 0; i--)
104    if (tags_remove[i] == m_name) return;
105
106  if (m_tag_excludes.size () > 0)
107    {
108      int number;
109
110      for (number = 0; number < m_tag_excludes.size (); number++)
111        {
112          Tag* ref = m_tag_excludes[number];
113
114          if (ref->is_selected ()) 
115            {
116              if (m_priority > ref->m_priority)
117                {
118                  //
119                  // Although this other contradictory tag is already selected,
120                  // its priority is lower. Therefore it will lose !! It has to be
121                  // unselected ...
122                  //
123
124                  ref->unmark ();
125                }
126              else
127                {
128                  /*
129                    if (!Cmt::quiet)
130                    {
131                    cerr << "Cannot mark excluded tag " << m_name << " p=" << m_priority
132                    << " because " << ref->m_name << "(" << ref->m_priority << ")" << endl;
133                    show (0);
134                    }
135                  */
136
137                  return;
138                }
139            }
140        }
141    }
142
143  m_selected = true;
144  if (context.size () != 0)
145    m_act_context = context;
146
147  log << "Marking tag[" << this << "] " << m_name << " p=" << m_priority
148      << " context=" << context << log_endl;
149
150  if (m_tag_refs.size () > 0)
151    {
152      int number;
153
154      for (number = 0; number < m_tag_refs.size (); number++)
155        {
156          Tag* ref = m_tag_refs[number];
157
158          ref->mark (context);
159        }
160    }
161}
162
163/*----------------------------------------------------------*/
164void Tag::action (const CmtSystem::cmt_string_vector& words, Use* use)
165{
166  cmt_string name;
167  Tag* tag;
168  Tag* ref;
169
170  if (words.size () < 1) return;
171  name = words[1];
172  if (name == "") return;
173
174  tag = add (name, PriorityUserTag, "use", use);
175
176  int priority = PriorityUserTag;
177  if (tag->m_priority > priority)
178    {
179      priority = tag->m_priority;
180    }
181
182  //if (tag->m_tag_refs.size () == 0)
183  //{
184
185  tag->add_ref_use (use);
186  //  tag->m_set_use = use;
187
188  //}
189
190  for (int i = 2; i < words.size (); i++)
191    {
192      name = words[i];
193      if (name == "") break;
194      ref = add (name, priority, "use", use);
195      tag->add_tag_ref (ref);
196      if (tag->is_selected ())  // it was previously selected
197        {
198          ref->mark (use ? use->get_package_name () : "");
199        }
200    }
201}
202
203/*----------------------------------------------------------*/
204void Tag::action_apply (const CmtSystem::cmt_string_vector& words, Use* use)
205{
206  cmt_string name;
207  Tag* tag;
208 
209  if (words.size () < 1) return;
210  name = words[1];
211  if (name == "") return;
212 
213  if (use->get_current_scope () == ScopePrivate) return;
214
215  Symbol::expand (name);
216 
217 
218  if (name == "")
219    {
220      CmtMessage::warning ("apply_tag with empty name [" + words[1] + "]");
221      /*
222      if (!Cmt::get_quiet ())
223        {
224          cerr << "#CMT> Warning: apply_tag with empty name [" << words[1] << "]" << endl;
225        }
226      */
227    }
228  else
229    {
230      tag = find (name);
231      if (tag == 0)
232        {
233          tag = add (name, PriorityUserTag, "use", use);
234        }
235
236      tag->mark (use ? use->get_package_name () : "");
237    }
238}
239
240/*----------------------------------------------------------*/
241void Tag::action_exclude (const CmtSystem::cmt_string_vector& words, Use* use)
242{
243  cmt_string name;
244  Tag* tag;
245  Tag* ref;
246
247  if (words.size () < 1) return;
248  name = words[1];
249  if (name == "") return;
250  if (use->get_current_scope () == ScopePrivate) return;
251
252  tag = add (name, PriorityUserTag, "use", use);
253
254  if (tag->m_tag_excludes.size () == 0)
255    {
256      tag->m_set_use = use;
257
258      int i;
259
260      for (i = 2; i < words.size (); i++)
261        {
262          cmt_string n;
263          n = words[i];
264          if (n == "") break;
265          ref = add (n, PriorityUserTag, "use", use);
266
267          /*
268            if (!Cmt::quiet)
269            {
270            cerr << "Excluding tag " << n << "(" << ref->m_priority << ") from tag "
271            << name << "(" << tag->m_priority << ")" << endl;
272            }
273          */
274
275          tag->add_tag_exclude (ref);
276          ref->add_tag_exclude (tag);
277        }
278
279      //
280      // We have to check that some of the excluded tags may be already selected.
281      // Then we have to figure out which one has to win:
282      //
283      //  the one with the highest priority
284      //  or the first that had been declared.
285      //
286     
287      int count = 0;
288      int winner_count = 0;
289     
290      Tag* winner = 0;
291
292      if (tag->is_selected ()) 
293        {
294          count++;
295          winner = tag;
296          winner_count = 1;
297        }
298
299      for (i = 0; i < tag->m_tag_excludes.size (); i++)
300        {
301          Tag* ref = tag->m_tag_excludes[i];
302         
303          if (ref == 0) continue;
304             
305          if (ref->is_selected ()) 
306            {
307              count++;
308
309              if ((winner == 0) ||
310                  (ref->m_priority > winner->m_priority))
311                {
312                  winner = ref;
313                  winner_count = 1;
314                }
315              else if (ref->m_priority == winner->m_priority)
316                {
317                  winner_count++;
318                }
319            }
320        }
321     
322      if (count > 1)
323        {
324          if (winner_count > 1)
325            {
326              //
327              // Several contradictory tags are selected and have the same priority!!
328              //
329            }
330
331          //
332          // We have at least one selected, and one winner.
333          // All others will be unselected.
334          //
335         
336          if (tag != winner)
337            {
338              tag->unmark ();
339            }
340
341          for (i = 0; i < tag->m_tag_excludes.size (); i++)
342            {
343              Tag* ref = tag->m_tag_excludes[i];
344             
345              if (ref == 0) continue;
346              if (ref == winner) continue;
347             
348              ref->unmark ();
349            }
350        }
351    }
352}
353
354/*----------------------------------------------------------*/
355Tag* Tag::find (const cmt_string& name)
356{
357  TagMap& map = tag_map ();
358
359  Tag* result = map.find (name);
360
361  return (result);
362
363  /*
364    TagPtrVector& vector = tags ();
365
366    int tag_index;
367    Tag* tag;
368
369    if (vector.size () == 0) return (0);
370
371    for (tag_index = 0; tag_index < vector.size (); tag_index++)
372    {
373    tag = vector[tag_index];
374
375    if ((tag != 0) && (tag->m_name == name))
376    {
377    return (tag);
378    }
379    }
380
381    return (0);
382  */
383}
384
385/*----------------------------------------------------------*/
386Tag* Tag::find (const cmt_string& name, TagMap& instances)
387{
388  Tag* result = instances.find (name);
389
390  return (result);
391
392  /*
393    int tag_index;
394
395    if (instances.size () == 0) return (0);
396
397    for (tag_index = 0; tag_index < instances.size (); tag_index++)
398    {
399    Tag& tag = instances[tag_index];
400
401    if (tag.m_name == name)
402    {
403    return (&tag);
404    }
405    }
406
407    return (0);
408  */
409}
410
411/*----------------------------------------------------------*/
412Tag* Tag::add (const cmt_string& name, 
413               int priority, 
414               const cmt_string& context, 
415               Use* use)
416{
417  Log;
418
419  TagMap& map = tag_map ();
420  TagPtrVector& vector = tags ();
421  TagVector& instances = all_tags ();
422
423  Tag* tag;
424
425  if (name == "") return (0);
426
427  tag = find (name);
428  if (tag != 0)
429    {
430      if (priority > tag->m_priority) 
431        {
432          tag->m_priority = priority;
433
434          /*
435            if (!Cmt::quiet)
436            {
437            cerr << "increasing priority of " << name << " p=" << priority << endl;
438            }
439          */
440        }
441      else
442        {
443          /*
444            if (!Cmt::quiet)
445            {
446            cerr << "keeping priority of " << name << " p=" << tag->m_priority << endl;
447            }
448          */
449        }
450
451      log << "re-adding tag[" << tag << "] " << name << " p=" << priority
452          << " context=" << context << (use != 0 ? " " + use->get_info () : "") << log_endl;
453     
454      return (tag);
455    }
456
457  Tag& tag_object = instances.add ();
458  tag = &tag_object;
459  vector.push_back (tag);
460  map.add (name, tag_object);
461
462  log << "adding tag[" << tag << "] " << name << " p=" << priority
463      << " context=" << context << (use != 0 ? " " + use->get_info () : "") << log_endl;
464 
465  tag->clear ();
466
467  tag->m_name = name;
468  tag->m_priority = priority;
469  tag->m_def_use = use;
470  tag->m_context = context;
471
472  int pos = 0;
473  int length = name.size ();
474  while (pos < length)
475    {
476      int and_pos = name.find (pos, "&");
477      if ((and_pos == cmt_string::npos) && (pos == 0)) break;
478
479      cmt_string op_name;
480
481      if (and_pos == cmt_string::npos)
482        {
483          name.substr (pos, op_name);
484        }
485      else
486        {
487          name.substr (pos, and_pos - pos, op_name);
488        }
489
490      if (op_name != "")
491        {
492          Tag* t = find (op_name);
493          if (t == 0)
494            {
495              t = add (op_name, priority, context, use);
496            }
497
498          if (t != 0)
499            {
500              tag->m_and_operands.push_back (t);
501              if (t->get_priority () > priority)
502                {
503                  tag->m_priority = t->get_priority ();
504                }
505            }
506          else
507            {
508              CmtMessage::warning ("Tag::add> unknown tag " + op_name + " in tag expression");
509              //              cerr << "#Tag::add> unknown tag " << op_name << " in tag expression" << endl;
510            }
511        }
512
513      if (and_pos == cmt_string::npos) break;
514
515      pos = and_pos + 1;
516    }
517
518  return (tag);
519}
520
521/*----------------------------------------------------------*/
522int Tag::tag_number ()
523{
524  static TagPtrVector& vector = tags ();
525
526  return (vector.size ());
527}
528
529/*----------------------------------------------------------*/
530Tag* Tag::tag (int index)
531{
532  static TagPtrVector& vector = tags ();
533
534  return (vector[index]);
535}
536
537/*----------------------------------------------------------*/
538void Tag::clear_all ()
539{
540  TagMap& map = tag_map ();
541  TagPtrVector& vector = tags ();
542  TagVector& instances = all_tags ();
543
544  int tag_index;
545
546  for (tag_index = 0; tag_index < instances.size (); tag_index++)
547    {
548      Tag& tag = instances[tag_index];
549      tag.clear ();
550    }
551
552  map.clear ();
553  vector.clear ();
554  instances.clear ();
555}
556
557/*----------------------------------------------------------*/
558Tag::TagMap& Tag::tag_map ()
559{
560  static Database& db = Database::instance ();
561  TagMap& map = db.tag_map ();
562
563  return (map);
564}
565
566/*----------------------------------------------------------*/
567Tag::TagVector& Tag::all_tags ()
568{
569  static Database& db = Database::instance ();
570  TagVector& vector = db.all_tags ();
571
572  return (vector);
573}
574
575/*----------------------------------------------------------*/
576Tag::TagPtrVector& Tag::tags ()
577{
578  static Database& db = Database::instance ();
579  TagPtrVector& vector = db.tags ();
580
581  return (vector);
582}
583
584/*----------------------------------------------------------*/
585Tag* Tag::get_default ()
586{
587  static Tag default_tag;
588  static bool initialized = false;
589  if (!initialized)
590    {
591      initialized = true;
592
593      default_tag.m_name = "Default";
594      default_tag.m_selected = true;
595      default_tag.m_context = "Default";
596      default_tag.m_priority = PriorityDefault;
597    }
598
599  return (&(default_tag));
600}
601
602/*----------------------------------------------------------*/
603bool Tag::check_tag_used (const Tag* tag)
604{
605  if (tag == 0) return (false);
606
607  if (tag->m_tag_refs.size () > 0) return (true);
608  if (tag->m_tag_excludes.size () > 0) return (true);
609
610  return (false);
611}
612
613/*----------------------------------------------------------*/
614Tag::Tag () :
615  m_name (""),
616  m_selected (false),
617  m_context (""),
618  m_def_use (0),
619  m_set_use (0),
620  m_act_context (""),
621  m_priority (0)
622{
623  clear ();
624}
625
626/*----------------------------------------------------------*/
627Tag::Tag (const Tag& other)
628{
629  clear ();
630
631  m_name = other.m_name;
632  m_selected = other.m_selected;
633  m_and_operands = other.m_and_operands;
634  m_tag_refs = other.m_tag_refs;
635  m_tag_excludes = other.m_tag_excludes;
636  m_context = other.m_context;
637  m_def_use = other.m_def_use;
638  m_set_use = other.m_set_use;
639  m_act_context = other.m_act_context;
640  m_ref_uses = other.m_ref_uses;
641  m_priority = other.m_priority;
642}
643
644/*----------------------------------------------------------*/
645Tag& Tag::operator = (const Tag& other)
646{
647  clear ();
648
649  m_name = other.m_name;
650  m_selected = other.m_selected;
651  m_and_operands = other.m_and_operands;
652  m_tag_refs = other.m_tag_refs;
653  m_tag_excludes = other.m_tag_excludes;
654  m_context = other.m_context;
655  m_def_use = other.m_def_use;
656  m_set_use = other.m_set_use;
657  m_act_context = other.m_act_context;
658  m_ref_uses = other.m_ref_uses;
659  m_priority = other.m_priority;
660
661  return (*this);
662}
663
664/*----------------------------------------------------------*/
665Tag::~Tag ()
666{
667}
668
669/*----------------------------------------------------------*/
670void Tag::clear ()
671{
672  m_name = "";
673  m_tag_refs.clear ();
674  m_tag_excludes.clear ();
675  m_priority = PriorityUserTag;
676  m_def_use = 0;
677  m_set_use = 0;
678  m_act_context = "";
679  m_ref_uses.clear ();
680  m_context = "";
681
682  m_selected = false;
683  m_and_operands.clear ();
684}
685
686/*----------------------------------------------------------*/
687void Tag::add_tag_ref (Tag* ref)
688{
689  if (ref == 0) return;
690
691  if (m_tag_refs.size () > 0)
692    {
693      int number;
694
695      for (number = 0; number < m_tag_refs.size (); number++)
696        {
697          Tag* t = m_tag_refs[number];
698          if (t == ref) return;
699        }
700    }
701
702  m_tag_refs.push_back (ref);
703}
704
705/*----------------------------------------------------------*/
706void Tag::add_tag_exclude (Tag* ref)
707{
708  if (ref == 0) return;
709
710  if (m_tag_excludes.size () > 0)
711    {
712      int number;
713
714      for (number = 0; number < m_tag_excludes.size (); number++)
715        {
716          Tag* t = m_tag_excludes[number];
717          if (t == ref) return;
718        }
719    }
720
721  m_tag_excludes.push_back (ref);
722}
723
724/*----------------------------------------------------------*/
725void Tag::add_ref_use (Use* use)
726{
727  if (use == 0) return;
728
729  for (int number = 0; number < m_ref_uses.size (); number++)
730    {
731      Use* u = m_ref_uses[number];
732      if (u == use) return;
733    }
734
735  m_ref_uses.push_back (use);
736}
737
738/*----------------------------------------------------------*/
739void Tag::show_definition (bool quiet, ostream& out,
740                           const cmt_string& prefix) const
741{
742  static const cmt_string priority_text[] = {
743    "Lowest",
744    "Default",
745    "Uname",
746    "Config",
747    "UserTag",
748    "PrimaryUserTag",
749    "Tag"
750  };
751
752  if (m_name == "Default") return;
753
754  out << prefix << m_name;
755
756  if (!quiet)
757    {
758      //cout << "context=" << m_context << " use=" << m_def_use << endl;
759     
760      if ((m_context == "use") || (m_def_use != 0))
761        {
762          if (m_def_use != 0)
763            {
764              out << " (from ";
765              if (m_context != "use") out << m_context + " in ";
766              out << "package " << m_def_use->get_package_name () << ")";
767            }
768        }
769      else
770        {
771          out << " (from " << m_context << ")";
772        }
773      //out << " (" << priority_text[m_priority] << ")";
774     
775      if (m_tag_refs.size () > 0)
776        {
777          int number;
778         
779          if (m_ref_uses.size () != 0)
780            {
781              out << " package [";
782              for (number = 0; number < m_ref_uses.size (); number++)
783                {
784                  Use* use = m_ref_uses[number];
785                  if (number > 0) out << " ";
786                  out << use->get_package_name ();
787                }
788              out << "]";
789            }
790          /*
791          if (m_set_use != 0)
792            {
793              out << " package " << m_set_use->get_package_name ();
794            }
795          */
796         
797          out << " implies [";
798         
799          for (number = 0; number < m_tag_refs.size (); number++)
800            {
801              Tag* ref = m_tag_refs[number];
802              if (number > 0) out << " ";
803              out << ref->m_name;
804            }
805         
806          out << "]";
807        }
808     
809      if (m_tag_excludes.size () > 0)
810        {
811          int number;
812         
813          if (m_set_use != 0)
814            {
815              out << " package " << m_set_use->get_package_name ();
816            }
817         
818          out << " excludes [";
819         
820          for (number = 0; number < m_tag_excludes.size (); number++)
821            {
822              Tag* ref = m_tag_excludes[number];
823              if (number > 0) out << " ";
824              out << ref->m_name;
825            }
826         
827          out << "]";
828        }
829      if (m_act_context.size () != 0 &&
830          (m_def_use != 0 &&
831           m_act_context != m_context &&
832           m_act_context != m_def_use->get_package_name () ||
833           m_def_use == 0 &&
834           m_act_context != m_context))
835        out << " activated " << m_act_context;
836    }
837  out << endl;
838}
839
840/*----------------------------------------------------------*/
841void Tag::show (bool quiet, ostream& out, const cmt_string& prefix) const
842{
843  if (is_primary () && is_selected ()) show_definition (quiet, out, prefix);
844}
845
846/*----------------------------------------------------------*/
847bool Tag::is_selected () const
848{
849  if (is_primary ())
850    {
851      return (m_selected);
852    }
853  else
854    {
855      for (int i = 0; i < m_and_operands.size(); i++)
856        {
857          Tag* t = m_and_operands[i];
858
859          if (!t->is_selected ()) return (false);
860        }
861
862      return (true);
863    }
864}
865
866/*----------------------------------------------------------*/
867bool Tag::is_primary () const
868{
869  return (m_and_operands.size() == 0);
870}
871
872/*----------------------------------------------------------*/
873const cmt_string& Tag::get_name () const
874{
875  return (m_name);
876}
877
878/*----------------------------------------------------------*/
879int Tag::get_priority () const
880{
881  return (m_priority);
882}
883
884/**
885 *  Recomputes all references to other tags using the new set of
886 *  instances.  This concerns
887 *
888 *    TagPtrVector m_and_operands;
889 *    TagPtrVector m_tag_refs;
890 *    TagPtrVector m_tag_excludes;
891 *
892 *   The pointers stored in those reference vectors are pointing to Tag objects
893 *  in one collection
894 *    We want to convert these pointers to pointers to the same Tag objects but
895 *  stored in the other Tag collection provided in the argument.
896 *
897 */
898void Tag::install (TagMap& instances)
899{
900  int i;
901
902  for (i = 0; i <  m_and_operands.size (); i++)
903    {
904      Tag* t = m_and_operands[i];
905      if (t != 0)
906        {
907          t = find (t->m_name, instances);
908          m_and_operands[i] = t;
909        }
910    }
911
912  for (i = 0; i <  m_tag_refs.size (); i++)
913    {
914      Tag* t = m_tag_refs[i];
915      if (t != 0)
916        {
917          t = find (t->m_name, instances);
918          m_tag_refs[i] = t;
919        }
920    }
921
922  for (i = 0; i <  m_tag_excludes.size (); i++)
923    {
924      Tag* t = m_tag_excludes[i];
925      if (t != 0)
926        {
927          t = find (t->m_name, instances);
928          m_tag_excludes[i] = t;
929        }
930    }
931}
932
933/*
934  Check if a tag is part of the operands of a tag
935*/
936bool Tag::use_operand (const Tag* other) const
937{
938  if (other == this) return (true);
939  if (m_and_operands.size () == 0) return (false);
940
941  for (int i = 0; i < m_and_operands.size (); i++)
942    {
943      Tag* t = m_and_operands[i];
944
945      if (t != 0)
946        {
947          if (t->use_operand (other)) return (true);
948        }
949    }
950
951  return (false);
952}
953
954/*
955  Check if a tag is part of the refs of a tag
956*/
957bool Tag::use_ref (const Tag* other) const
958{
959  if (other == this) return (false);
960  if (m_tag_refs.size () == 0) return (false);
961
962  for (int i = 0; i < m_tag_refs.size (); i++)
963    {
964      Tag* t = m_tag_refs[i];
965
966      if (t == other) return (true);
967    }
968
969  return (false);
970}
971
972
Note: See TracBrowser for help on using the repository browser.