source: CMT/v1r20p20070524/source/cmt_tag.cxx

Last change on this file was 400, checked in by arnault, 17 years ago

Text formatting
Sending warnings & errors to stderr
Using internally PWD for every cd/pwd
CL 327

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