source: CMT/HEAD/source/cmt_tag.cxx @ 662

Last change on this file since 662 was 662, checked in by rybkin, 10 years ago

See C.L. 521

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