source: CMT/v1r16p20040901/src/cmt_tag.cxx @ 1

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

Import all tags

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  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 = 0;
562
563  if (default_tag == 0)
564    {
565      default_tag = add ("Default", PriorityDefault, "Default", 0);
566      default_tag->mark ();
567    }
568
569  return (default_tag);
570}
571
572/*----------------------------------------------------------*/
573Tag::Tag () :
574  m_name (""),
575  m_selected (false),
576  m_context (""),
577  m_def_use (0),
578  m_set_use (0),
579  m_priority (0)
580{
581  clear ();
582}
583
584/*----------------------------------------------------------*/
585Tag::Tag (const Tag& other)
586{
587  clear ();
588
589  m_name = other.m_name;
590  m_selected = other.m_selected;
591  m_and_operands = other.m_and_operands;
592  m_tag_refs = other.m_tag_refs;
593  m_tag_excludes = other.m_tag_excludes;
594  m_context = other.m_context;
595  m_def_use = other.m_def_use;
596  m_set_use = other.m_set_use;
597  m_priority = other.m_priority;
598}
599
600/*----------------------------------------------------------*/
601Tag& Tag::operator = (const Tag& other)
602{
603  clear ();
604
605  m_name = other.m_name;
606  m_selected = other.m_selected;
607  m_and_operands = other.m_and_operands;
608  m_tag_refs = other.m_tag_refs;
609  m_tag_excludes = other.m_tag_excludes;
610  m_context = other.m_context;
611  m_def_use = other.m_def_use;
612  m_set_use = other.m_set_use;
613  m_priority = other.m_priority;
614
615  return (*this);
616}
617
618/*----------------------------------------------------------*/
619Tag::~Tag ()
620{
621}
622
623/*----------------------------------------------------------*/
624void Tag::clear ()
625{
626  m_name = "";
627  m_tag_refs.clear ();
628  m_tag_excludes.clear ();
629  m_priority = PriorityUserTag;
630  m_def_use = 0;
631  m_set_use = 0;
632  m_context = "";
633
634  m_selected = false;
635  m_and_operands.clear ();
636}
637
638/*----------------------------------------------------------*/
639void Tag::add_tag_ref (Tag* ref)
640{
641  if (ref == 0) return;
642
643  if (m_tag_refs.size () > 0)
644    {
645      int number;
646
647      for (number = 0; number < m_tag_refs.size (); number++)
648        {
649          Tag* t = m_tag_refs[number];
650          if (t == ref) return;
651        }
652    }
653
654  m_tag_refs.push_back (ref);
655}
656
657/*----------------------------------------------------------*/
658void Tag::add_tag_exclude (Tag* ref)
659{
660  if (ref == 0) return;
661
662  if (m_tag_excludes.size () > 0)
663    {
664      int number;
665
666      for (number = 0; number < m_tag_excludes.size (); number++)
667        {
668          Tag* t = m_tag_excludes[number];
669          if (t == ref) return;
670        }
671    }
672
673  m_tag_excludes.push_back (ref);
674}
675
676/*----------------------------------------------------------*/
677void Tag::show_definition (bool quiet) const
678{
679  static const cmt_string priority_text[] = {
680    "Lowest",
681    "Default",
682    "Uname",
683    "Config",
684    "UserTag",
685    "PrimaryUserTag",
686    "Tag"
687  };
688
689  if (m_name == "Default") return;
690
691  cout << m_name;
692
693  if (!quiet)
694    {
695      //cout << "context=" << m_context << " use=" << m_def_use << endl;
696     
697      if ((m_context == "use") || (m_def_use != 0))
698        {
699          if (m_def_use != 0)
700            {
701              cout << " (from ";
702              if (m_context != "use") cout << m_context;
703              cout << "package " << m_def_use->get_package_name () << ")";
704            }
705        }
706      else
707        {
708          cout << " (from " << m_context << ")";
709        }
710      //cout << " (" << priority_text[m_priority] << ")";
711     
712      if (m_tag_refs.size () > 0)
713        {
714          int number;
715         
716          if (m_set_use != 0)
717            {
718              cout << " package " << m_set_use->get_package_name ();
719            }
720         
721          cout << " implies [";
722         
723          for (number = 0; number < m_tag_refs.size (); number++)
724            {
725              Tag* ref = m_tag_refs[number];
726              if (number > 0) cout << " ";
727              cout << ref->m_name;
728            }
729         
730          cout << "]";
731        }
732     
733      if (m_tag_excludes.size () > 0)
734        {
735          int number;
736         
737          if (m_set_use != 0)
738            {
739              cout << " package " << m_set_use->get_package_name ();
740            }
741         
742          cout << " excludes [";
743         
744          for (number = 0; number < m_tag_excludes.size (); number++)
745            {
746              Tag* ref = m_tag_excludes[number];
747              if (number > 0) cout << " ";
748              cout << ref->m_name;
749            }
750         
751          cout << "]";
752        }
753    }
754  cout << endl;
755}
756
757/*----------------------------------------------------------*/
758void Tag::show (bool quiet) const
759{
760  if (is_primary () && is_selected ()) show_definition (quiet);
761}
762
763/*----------------------------------------------------------*/
764bool Tag::is_selected () const
765{
766  if (is_primary ())
767    {
768      return (m_selected);
769    }
770  else
771    {
772      for (int i = 0; i < m_and_operands.size(); i++)
773        {
774          Tag* t = m_and_operands[i];
775
776          if (!t->is_selected ()) return (false);
777        }
778
779      return (true);
780    }
781}
782
783/*----------------------------------------------------------*/
784bool Tag::is_primary () const
785{
786  return (m_and_operands.size() == 0);
787}
788
789/*----------------------------------------------------------*/
790const cmt_string& Tag::get_name () const
791{
792  return (m_name);
793}
794
795/*----------------------------------------------------------*/
796int Tag::get_priority () const
797{
798  return (m_priority);
799}
800
801/**
802 *  Recomputes all references to other tags using the new set of
803 *  instances.  This concerns
804 *
805 *    TagPtrVector m_and_operands;
806 *    TagPtrVector m_tag_refs;
807 *    TagPtrVector m_tag_excludes;
808 *
809 *   The pointers stored in those reference vectors are pointing to Tag objects
810 *  in one collection
811 *    We want to convert these pointers to pointers to the same Tag objects but
812 *  stored in the other Tag collection provided in the argument.
813 *
814 */
815void Tag::install (TagMap& instances)
816{
817  int i;
818
819  for (i = 0; i <  m_and_operands.size (); i++)
820    {
821      Tag* t = m_and_operands[i];
822      if (t != 0)
823        {
824          t = find (t->m_name, instances);
825          m_and_operands[i] = t;
826        }
827    }
828
829  for (i = 0; i <  m_tag_refs.size (); i++)
830    {
831      Tag* t = m_tag_refs[i];
832      if (t != 0)
833        {
834          t = find (t->m_name, instances);
835          m_tag_refs[i] = t;
836        }
837    }
838
839  for (i = 0; i <  m_tag_excludes.size (); i++)
840    {
841      Tag* t = m_tag_excludes[i];
842      if (t != 0)
843        {
844          t = find (t->m_name, instances);
845          m_tag_excludes[i] = t;
846        }
847    }
848}
849
850
Note: See TracBrowser for help on using the repository browser.