source: CMT/v1r26/source/cmt_tag.cxx

Last change on this file was 568, checked in by rybkin, 13 years ago

See C.L. 451

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