source: CMT/v1r22/source/cmt_tag.cxx

Last change on this file was 549, checked in by rybkin, 14 years ago

See C.L. 434

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