source: CMT/v1r18p20060606/source/cmt_tag.cxx

Last change on this file was 11, checked in by arnault, 19 years ago

Changing eol-style property

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