source: CMT/v1r20p20090520/source/cmt_tag.cxx

Last change on this file was 459, checked in by rybkin, 16 years ago

See C.L. 360

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