source: CMT/v1r26p20160527/source/cmt_pattern.cxx

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

See C.L. 524

  • Property svn:eol-style set to native
File size: 24.8 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// Modified by Grigory Rybkin
5// See the complete license in cmt_license.txt "http://www.cecill.info".
6//-----------------------------------------------------------
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12
13#include "cmt.h"
14#include "cmt_pattern.h"
15#include "cmt_use.h"
16#include "cmt_database.h"
17#include "cmt_error.h"
18#include "cmt_syntax.h"
19#include "cmt_log.h"
20
21
22//----------------------------------------------------------
23
24PatternList* PatternList::find (const cmt_string& name)
25{
26  static PatternListMap& map = pattern_list_map ();
27
28  return (map.find (name));
29}
30
31
32Pattern* PatternList::find_pattern (const cmt_string& name)
33{
34  PatternList* list = find (name);
35  if (list == 0) return (0);
36
37  Pattern::PatternPtrVector& vector = list->get_patterns ();
38
39  if (vector.size () == 0) return (0);
40
41  Pattern* p = vector[vector.size () - 1];
42
43  return (p);
44}
45
46Pattern* PatternList::find (const cmt_string& name, Use* use)
47{
48  PatternList* list = find (name);
49  if (list == 0) return (0);
50
51  Pattern::PatternPtrVector& vector = list->get_patterns ();
52
53  for (int i = 0; i < vector.size (); i++)
54    {
55      Pattern* p = vector[i];
56
57      if (p->use == use) return (p);
58    }
59
60  return (0);
61}
62
63PatternList* PatternList::add (const cmt_string& name)
64{
65  PatternList* list = find (name);
66  if (list != 0) return (list);
67
68  static PatternListVector& vector = pattern_lists ();
69
70  PatternList& pl = vector.add ();
71  pl.m_name = name;
72
73  static PatternListMap& map = pattern_list_map ();
74  map.add (name, pl);
75
76  return (&pl);
77}
78
79void PatternList::clear_all ()
80{
81  static PatternListVector& vector = pattern_lists ();
82  static PatternListMap& map = pattern_list_map ();
83
84  for (int i = 0; i < vector.size (); i++)
85    {
86      PatternList& p = vector[i];
87      p.clear ();
88    }
89
90  vector.clear ();
91  map.clear ();
92}
93
94PatternList::PatternListMap& PatternList::pattern_list_map ()
95{
96  static Database& db = Database::instance ();
97  static PatternListMap& map = db.pattern_list_map ();
98
99  return (map);
100}
101
102PatternList::PatternListVector& PatternList::pattern_lists ()
103{
104  static Database& db = Database::instance ();
105  static PatternListVector& vector = db.pattern_lists ();
106
107  return (vector);
108}
109
110PatternList::PatternList ()
111{
112}
113
114PatternList::PatternList (const cmt_string& name) : m_name (name)
115{
116}
117
118PatternList::~PatternList ()
119{
120  clear ();
121}
122
123Pattern::PatternPtrVector& PatternList::get_patterns ()
124{
125  return (m_patterns);
126}
127
128void PatternList::add_pattern (Pattern* pattern)
129{
130  for (int i = 0; i < m_patterns.size (); i++)
131    {
132      Pattern* p = m_patterns[i];
133      if (p->use == pattern->use)
134        {
135          m_patterns[i] = pattern;
136          return;
137        }
138    }
139
140  m_patterns.push_back (pattern);
141}
142
143void PatternList::clear ()
144{
145  m_name = "";
146  m_patterns.clear ();
147}
148
149
150//----------------------------------------------------------
151//
152//  Operations on Patterns
153//
154//----------------------------------------------------------
155
156//----------------------------------------------------------
157void Pattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
158{
159  bool global = false;
160  int start_index;
161
162  if (words.size () < 2) return;
163
164  //
165  // expected syntax is:
166  //
167  //  pattern [-global] pattern-name any-cmt-statement
168  //
169  // where any-cmt-statement may contain "templates"
170  //
171  //      <package>
172  //      <PACKAGE>
173  //      <version>
174  //      <path>
175  //
176
177  cmt_string& option = words[1];
178
179  if (option == "-global")
180    {
181      global = true;
182      start_index = 2;
183    }
184  else
185    {
186      start_index = 1;
187    }
188
189  cmt_string& name = words[start_index];
190
191  start_index++;
192
193  add (name, words, start_index, global, use);
194
195  if (Cmt::get_debug () &&
196      CmtSystem::testenv ("CMTTESTPATTERN"))
197    {
198      cerr << "Pattern::action> add " << name << endl;
199    }
200}
201
202/**
203 *
204 *  Patterns are stored with two keys : <name> and <use>
205 *
206 *  thus search must done against these two keys.
207 *
208 */
209Pattern* Pattern::find (const cmt_string& name)
210{
211  Pattern* p = PatternList::find_pattern (name);
212
213  return (p);
214}
215
216//----------------------------------------------------------
217Pattern* Pattern::find (const cmt_string& name, Use* use)
218{
219  Pattern* p = PatternList::find (name, use);
220
221  return (p);
222}
223
224//----------------------------------------------------------
225void Pattern::add (const cmt_string& name,
226                   const CmtSystem::cmt_string_vector& words,
227                   int start_index,
228                   bool global,
229                   Use* use)
230{
231  static PatternVector& Patterns = patterns ();
232
233  Pattern* pattern;
234
235  pattern = find (name, use);
236
237  if (pattern == 0)
238    {
239      // No pattern for the pair <name, use> exist yet.
240      // create one.
241      Pattern& p = Patterns.add ();
242
243      p.clear ();
244
245      p.name = name;
246      p.use  = use;
247
248      PatternList* pl = PatternList::add (name);
249      pl->add_pattern (&p);
250
251      pattern = &p;
252    }
253  else
254    {
255      Pattern& p = *pattern;
256
257      p.clear ();
258
259      p.name = name;
260      p.use  = use;
261    }
262
263  pattern->line = "";
264
265  int first_word = start_index;
266
267  //
268  // Install the cmt-statement both as a vector of words and as a single line
269  //
270  for (int i = start_index; i < words.size (); i++)
271    {
272      bool need_quotes = (i > (first_word + 1));
273      //bool need_quotes = true;
274
275      cmt_string& s = words[i];
276
277      if (i > start_index) pattern->line += " ";
278
279      if (s == ";") first_word = i+1;
280
281      if ((s == "\n") | (s == ";"))
282        {
283          pattern->line += "\n  ";
284        }
285      else
286        {
287          cmt_string sep = "\"";
288
289          if (s.find (sep) != cmt_string::npos)
290            {
291              sep = "\'";
292            }
293
294          if (!need_quotes) sep = "";
295
296          pattern->line += sep;
297          pattern->line += s;
298          pattern->line += sep;
299        }
300    }
301
302  pattern->global = global;
303}
304
305/**
306 * Get the number of registered patterns
307 */
308int Pattern::pattern_number ()
309{
310  static PatternVector& Patterns = patterns ();
311
312  return (Patterns.size ());
313}
314
315/**
316 * Get the index'th pattern in the database
317 */
318Pattern& Pattern::pattern (int index)
319{
320  static PatternVector& Patterns = patterns ();
321
322  return (Patterns[index]);
323}
324
325//----------------------------------------------------------
326void Pattern::clear_all ()
327{
328  static PatternVector& Patterns = patterns ();
329
330  for (int i = 0; i < Patterns.size (); i++)
331    {
332      Pattern& p = Patterns[i];
333      p.clear ();
334    }
335
336  Patterns.clear ();
337}
338
339//----------------------------------------------------------
340Pattern::PatternVector& Pattern::patterns ()
341{
342  static Database& db = Database::instance ();
343  static PatternVector& Patterns = db.patterns ();
344
345  return (Patterns);
346}
347
348/**
349 * Applies all global patterns to all uses
350 */
351void PatternList::apply_all_globals ()
352{
353  static PatternListVector& PatternLists = pattern_lists ();
354
355  int i;
356
357  for (i = 0; i < PatternLists.size (); i++)
358    {
359      PatternList& pl = PatternLists[i];
360
361      int n = pl.m_patterns.size ();
362
363      if (n > 0)
364        {
365          Pattern* p = pl.m_patterns[n-1];
366
367          if ((p != 0) && (p->global)) p->apply ();
368        }
369    }
370}
371
372/**
373 * Applies all global patterns to a given Use
374 */
375void PatternList::apply_all_globals (Use* use)
376{
377  if (use->get_package_name () == "CMT") return;
378
379  static PatternListVector& PatternLists = pattern_lists ();
380
381  int i;
382
383  for (i = 0; i < PatternLists.size (); i++)
384    {
385      PatternList& pl = PatternLists[i];
386
387      int n = pl.m_patterns.size ();
388
389      if (n > 0)
390        {
391          Pattern* p = pl.m_patterns[n-1];
392
393          if ((p != 0) && (p->global)) 
394            {
395              if (p->global)
396                {
397                  if (IgnorePattern::find (p->name, use) == 0) p->apply (use);
398                }
399            }
400        }
401    }
402}
403
404/**
405 * Show all patterns
406 */
407void PatternList::show_all_patterns ()
408{
409  static PatternListVector& PatternLists = pattern_lists ();
410
411  int i;
412
413  for (i = 0; i < PatternLists.size (); i++)
414    {
415      PatternList& pl = PatternLists[i];
416
417      int n = pl.m_patterns.size ();
418
419      if (n > 0)
420        {
421          Pattern* p = pl.m_patterns[n-1];
422
423          if (p != 0) p->show ();
424        }
425    }
426}
427/**
428 * Show all pattern names
429 */
430void PatternList::show_all_pattern_names ()
431{
432  bool empty = true;
433
434  static PatternListVector& PatternLists = pattern_lists ();
435
436  int i;
437
438  for (i = 0; i < PatternLists.size (); i++)
439    {
440      PatternList& pl = PatternLists[i];
441
442      int n = pl.m_patterns.size ();
443
444      if (n > 0)
445        {
446          Pattern* p = pl.m_patterns[n-1];
447
448          if (p != 0)
449            {
450              cout << p->name << " ";
451              empty = false;
452            }
453        }
454    }
455  if (!empty) cout << endl;
456}
457
458/**
459 * Applies all global patterns to all uses
460 */
461void Pattern::apply_all_globals ()
462{
463  PatternList::apply_all_globals ();
464}
465
466/**
467 * Applies all global patterns to a given Use
468 */
469void Pattern::apply_all_globals (Use* use)
470{
471  PatternList::apply_all_globals ();
472}
473
474/**
475 * this is the cmt show patterns command
476 * It just shows the pattern declarations.
477 */
478void Pattern::show_all ()
479{
480  PatternList::show_all_patterns ();
481
482  show_all_applied_patterns ();
483}
484
485/**
486 * this is the cmt show applied_patterns command
487 * It just shows the pattern applications.
488 */
489void Pattern::show_all_applied_patterns ()
490{
491  Use* use = &(Use::current ());
492  for (int i = 0; i < use->apply_patterns.size (); i++)
493    {
494      const ApplyPattern& apply_pattern = use->apply_patterns[i];
495
496      cout << "# " << use->get_package_name ()
497           << " applies pattern " << apply_pattern.name << " => " << endl;
498
499      apply_pattern.show ();
500
501      cout << endl;
502    }
503}
504
505//----------------------------------------------------------
506void Pattern::show_all_names ()
507{
508  PatternList::show_all_pattern_names ();
509}
510
511/**
512 *  This is the cmt show pattern <name> command
513 * It shows both the pattern definition(s) and the places
514 * where it is explicitly applied.
515 */
516void Pattern::show (const cmt_string& name)
517{
518  static PatternVector& Patterns = patterns ();
519
520  int i;
521  int j;
522
523  bool found = false;
524
525  // First show the definitions.
526
527  Pattern* p = Pattern::find (name);
528
529  if (p == 0)
530    {
531      CmtError::set (CmtError::pattern_not_found, name);
532      return;
533    }
534
535  p->show ();
536
537  //
538  // Then show the packages which explicitly apply the pattern.
539  //
540  Use* use;
541  ApplyPattern* apply_pattern = 0;
542
543  Use::UsePtrVector& uses = Use::get_ordered_uses ();
544
545  for (i = 0; i < uses.size (); i++)
546    {
547      use = uses[i];
548      for (j = 0; j < use->apply_patterns.size (); j++)
549        {
550          apply_pattern = &(use->apply_patterns[j]);
551           
552          if (apply_pattern->name == name)
553            {
554              cout << "# applied by " << use->get_package_name () << " => " << endl;
555              apply_pattern->show ();
556              cout << endl;
557            }
558        }
559    }
560
561  use = &(Use::current ());
562  for (j = 0; j < use->apply_patterns.size (); j++)
563    {
564      apply_pattern = &(use->apply_patterns[j]);
565       
566      if (apply_pattern->name == name)
567        {
568          cout << "# " << use->get_package_name () << " " << use->version << " applies pattern " << name;
569          cout << " => " << endl;
570          apply_pattern->show ();
571          cout << endl;
572        }
573    }
574}
575
576//----------------------------------------------------------
577Pattern::Pattern ()
578{
579}
580
581//----------------------------------------------------------
582Pattern::~Pattern ()
583
584{
585}
586
587//----------------------------------------------------------
588void Pattern::clear ()
589{
590  global = false;
591  name = "";
592  use = 0;
593  line = "";
594}
595
596//----------------------------------------------------------
597void Pattern::show () const
598{
599  if (use != 0) cout << "# " << use->get_package_name () << " " << use->version;
600  else cout << "# ?? ";
601
602  cout  << " defines ";
603
604  if (global) cout << "global ";
605 
606  cout << "pattern " << name << " as" << endl;
607  cout << "  " << line << endl;
608}
609
610//----------------------------------------------------------
611class PatternCache
612{
613public:
614  static PatternCache& instance ()
615  {
616    static PatternCache me;
617
618    return (me);
619  }
620
621  static bool update (Use* c, Use* t)
622  {
623    static PatternCache& me = instance ();
624
625    return (me.do_update (c, t));
626  }
627
628  static Use::UsePtrVector& get_list ()
629  {
630    static PatternCache& me = instance ();
631
632    return (me.list);
633  }
634
635private:
636
637  PatternCache () : current(0), target(0)
638  {
639    current_name = "";
640    target_name = "";
641  }
642
643  bool do_update (Use* c, Use* t)
644  {
645    cmt_string c_name = c->get_package_name ();
646    cmt_string t_name = t->get_package_name ();
647
648    if ((current_name != c_name) || (target_name != t_name))
649      {
650        if (CmtSystem::getenv ("TESTCACHE") != "")
651          {
652            cerr << "update cache " << c->get_package_name () << "(" << c << ") " << t->get_package_name () << "(" << t << ")" << endl;
653          }
654       
655        current = c;
656        current_name = c_name;
657
658        target = t;
659        target_name = t_name;
660
661        list.clear ();
662         
663        if (current != target)
664          {
665            if (!current->get_paths (target, list)) return (false);
666          }
667        else
668          {
669            list.push_back (current);
670          }
671      }
672    else
673      {
674        if (CmtSystem::getenv ("TESTCACHE") != "")
675          {
676            cerr << "keep cache" << endl;
677          }
678      }
679    return (true);
680  }
681 
682  Use* current;
683  cmt_string current_name;
684  Use* target;
685  cmt_string target_name;
686  Use::UsePtrVector list;
687};
688
689/**
690 *   Applies a pattern to all uses (except CMT itself) between
691 *   current and the use that declared the pattern.
692 */
693void Pattern::apply () const
694{
695  Use::UsePtrVector& uses = Use::get_ordered_uses ();
696
697  Use* current = &(Use::current());
698
699  if (Cmt::get_debug ())
700    {
701      cout << "Pattern(" << name << "::apply> " << " defined in " << use->get_package_name () << endl;
702    }
703
704  if (!PatternCache::update (current, use)) return;
705
706  Use::UsePtrVector& list = PatternCache::get_list ();
707
708  for (int i = 0; i < list.size (); i++)
709    {
710      Use* u = list[i];
711
712      if (Cmt::get_debug ())
713        {
714          cout << "Pattern(" << name << "::apply> " << " to package " << u->get_package_name () << endl;
715        }
716
717      if ((u->get_package_name () != "CMT") && 
718          (IgnorePattern::find (name, u) == 0)) apply (u);
719    }
720}
721
722//----------------------------------------------------------
723void Pattern::apply (Use* context_use) const
724{
725  static Template::TemplateVector dummy_templates;
726
727  apply (context_use, dummy_templates);
728}
729
730/**
731 *  Applies a pattern to one particular use.
732 */
733void Pattern::apply (Use* context_use, 
734                     const Template::TemplateVector& templates) const
735{
736  cmt_string replacement;
737
738  expand (context_use, templates, replacement);
739
740  if (Cmt::get_debug () &&
741      CmtSystem::testenv ("CMTTESTPATTERN"))
742    {
743      cerr << "Pattern::apply> replacement=[" << replacement << "]" << endl;
744    }
745
746  if (replacement != "")
747    {
748      SyntaxParser::parse_requirements_text (replacement, "", context_use);
749    }
750}
751
752//----------------------------------------------------------
753void Pattern::expand (Use* context_use, 
754                      const Template::TemplateVector& templates, 
755                      cmt_string& replacement) const
756{
757  if (context_use == 0) context_use = &(Use::current ());
758
759  if (Cmt::get_debug () &&
760      CmtSystem::testenv ("CMTTESTPATTERN"))
761    {
762      cerr << "Pattern::expand1> line=[" << line << "]" << endl;
763    }
764
765  replacement = line;
766
767  if (replacement != "")
768    {
769      // Substitute templates from the cmt statement
770      replacement.replace_all ("<package>", context_use->get_package_name ().c_str ());
771      replacement.replace_all ("<PACKAGE>", context_use->prefix.c_str ());
772      replacement.replace_all ("<version>", context_use->version.c_str ());
773      replacement.replace_all ("<path>",    context_use->real_path.c_str ());
774      /*
775      cmt_string cmtpath = "";
776      cmt_string offset = "";
777
778      context_use->get_cmtpath_and_offset (cmtpath, offset);
779
780      Project* p = Project::find_by_cmtpath (cmtpath);
781      if (p != 0)
782      */
783      if (const Project* p = context_use->get_project ())
784        {
785          //          const cmt_string& n = p->get_name ();
786          replacement.replace_all ("<project>", p->get_name ().c_str ());
787        }
788
789      for (int j = 0; j < templates.size (); j++)
790        {
791          Template& t = templates[j];
792          cmt_string s;
793          s = "<";
794          s += t.name;
795          s += ">";
796          replacement.replace_all (s, t.value);
797        }
798
799      for (;;)
800        {
801          int begin = replacement.find ("<");
802          if (begin == cmt_string::npos) break;
803          int end = replacement.find (begin, ">");
804          if (end == cmt_string::npos) break;
805          // Do not erase XML constructs
806          if (replacement[end-1] == '/') break;
807          replacement.erase (begin, end - begin + 1);
808        }
809
810      if (Cmt::get_debug () &&
811          CmtSystem::testenv ("CMTTESTPATTERN"))
812        {
813          cerr << "Pattern::expand2> repl=[" << replacement << "]" << endl;
814        }
815
816    }
817}
818
819//----------------------------------------------------------
820//
821//  Operations on ApplyPatterns
822//
823//----------------------------------------------------------
824
825//----------------------------------------------------------
826void ApplyPattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
827{
828  //
829  // Expected syntax is
830  //
831  // apply_pattern <pattern-name> [ <template>=<value> ... ]
832  //   or just
833  // <pattern-name> [ <template>=<value> ... ]
834  //
835
836  int first_word = 0;
837
838  if (words[0] == "apply_pattern") first_word = 1;
839  else first_word = 0;
840
841  if (words.size () < (first_word + 1)) return;
842
843  if (use == 0) use = &(Use::current());
844
845  cmt_string name = words[first_word];
846  Symbol::expand (name);
847
848  if (name == "") return;
849
850  Pattern* p = Pattern::find (name);
851  if (p == 0) 
852    {
853      if (Cmt::get_current_access () == DeveloperMode &&
854          Cmt::get_recursive ())
855        CmtMessage::warning (CmtError::get_error_name (CmtError::pattern_not_found) +
856                             ": " + name +
857                             " (applied by " + use->get_package_name () + ")"
858                             );
859      return;
860      /*
861      if (use->get_current_scope () != ScopeUnspecified &&
862          use->get_current_scope () != ScopePublic)
863        return;
864      */
865      /*
866      cmt_string use_info (use->get_package_name () +
867                           " " + use->version +
868                           (use->path != "" ? " " + use->path : "") +
869                           " " + use->real_path
870                           );
871      */
872      /*
873        CmtError::set (CmtError::pattern_not_found, name +
874        " (applied by " + use->get_package_name () + ")"
875        );
876      */
877      /*
878      if (CmtMessage::active (Verbose))
879        {
880          CmtMessage::warning (CmtError::get_last_error ());
881        }
882      */
883    }
884
885  ApplyPattern* apply_pattern = add (name, use);
886
887  /*
888    We then look for all <name>=<value> pairs
889  */
890  enum
891    {
892      need_template,
893      need_equal,
894      need_value,
895      can_add,
896      in_error
897    } state = need_template;
898
899  cmt_string tname;
900  cmt_string tvalue;
901
902  for (int i = (first_word + 1); i < words.size (); i++)
903    {
904      cmt_string s = words[i];
905
906      if (Cmt::get_debug () &&
907          CmtSystem::testenv ("CMTTESTPATTERN"))
908        {
909          cerr << "ApplyPattern::action> " << name << " s=[" << s << "] state=" << state << endl;
910        }
911
912      int pos = cmt_string::npos;
913
914      switch (state)
915        {
916        case need_template:
917          pos = s.find ("=");
918
919          tname = s;
920          tvalue = "";
921
922          if (pos == cmt_string::npos)
923            {
924              state = need_equal;
925            }
926          else
927            {
928              s.substr (0, pos, tname);
929              s.substr (pos + 1, tvalue);
930
931              if (Cmt::get_debug () &&
932                  CmtSystem::testenv ("CMTTESTPATTERN"))
933                {
934                  cerr << "ApplyPattern::action-1> n=[" << tname << "] v=[" << tvalue << "]" << endl;
935                }
936             
937              if (tvalue == "")
938                {
939                  state = need_value;
940                }
941              else
942                {                 
943                  state = can_add;
944                }
945            }
946          break;
947        case need_equal:
948          pos = s.find ("=");
949
950          tvalue = "";
951
952          if (pos != 0)
953            {
954              state = in_error;
955              CmtMessage::warning ("bad syntax in apply_pattern " + name
956                                   + " (missing '=' separator)"
957                                   + ( (use != 0) ?
958                                       " (from " + use->get_package_name () + ")":
959                                       "" )
960                                   );
961              /*
962              if (!Cmt::get_quiet ())
963                {
964                  cerr << "#CMT> Warning: bad syntax in apply_pattern " << name
965                       << " (missing '=' separator)";
966
967                  if (use != 0) cerr << " (from " << use->get_package_name () << ")";
968
969                  cerr << endl;
970                }
971              */
972              break;
973            }
974          else
975            {
976              s.substr (pos + 1, tvalue);
977
978              if (tvalue == "")
979                {
980                  state = need_value;
981                }
982              else
983                {                 
984                  state = can_add;
985                }
986            }
987          break;
988        case need_value:
989
990          pos = s.find ("=");
991
992          if (pos == cmt_string::npos)
993            {
994              tvalue = s;
995              state = can_add;
996            }
997          else
998            {
999              tname = s;
1000              tvalue = "";
1001
1002              s.substr (0, pos, tname);
1003              s.substr (pos + 1, tvalue);
1004
1005              if (Cmt::get_debug () &&
1006                  CmtSystem::testenv ("CMTTESTPATTERN"))
1007                {
1008                  cerr << "ApplyPattern::action-2> n=[" << tname << "] v=[" << tvalue << "]" << endl;
1009                }
1010             
1011              if (tvalue == "")
1012                {
1013                  state = need_value;
1014                }
1015              else
1016                {                 
1017                  state = can_add;
1018                }
1019            }
1020
1021          break;
1022        default:
1023          break;
1024        }
1025
1026      if (state == can_add)
1027        {
1028          state = need_template;
1029
1030          if (Cmt::get_debug () &&
1031              CmtSystem::testenv ("CMTTESTPATTERN"))
1032            {
1033              cerr << "ApplyPattern::action-3> n=[" << tname << "] v=[" << tvalue << "]" << endl;
1034            }
1035
1036          cmt_string tsearch = "<";
1037          tsearch += tname;
1038          tsearch += ">";
1039
1040          if (p->line.find (tsearch) == cmt_string::npos)
1041            {
1042              CmtMessage::warning ("template <" + tname
1043                                   + "> not expected in pattern " + name
1044                                   + ( (use != 0) ?
1045                                       " (from " + use->get_package_name () + ")":
1046                                       "" )
1047                                   );
1048              /*
1049              if (!Cmt::get_quiet ())
1050                {
1051                  cerr << "#CMT> Warning: template <" << tname << "> not expected in pattern " << name;
1052                  if (use != 0) cerr << " (from " << use->get_package_name () << ")";
1053                  cerr << endl;
1054                }
1055              */
1056            }
1057
1058          Template& t = apply_pattern->replacements.add ();
1059
1060          t.name = tname;
1061          t.value = tvalue;
1062
1063          int size = t.value.size ();
1064
1065          if (size >= 2)
1066            {
1067              if (((t.value[0] == '"') && (t.value[size - 1] == '"')) ||
1068                  ((t.value[0] == '\'') && (t.value[size - 1] == '\'')))
1069                {
1070                  t.value.erase (size - 1);
1071                  t.value.erase (0, 1);
1072                }
1073            }
1074        }
1075    }
1076
1077  apply_pattern->apply ();
1078}
1079
1080//----------------------------------------------------------
1081ApplyPattern* ApplyPattern::add (const cmt_string& name, Use* use)
1082{
1083  ApplyPattern& a = use->apply_patterns.add ();
1084
1085  a.name = name;
1086  a.use  = use;
1087
1088  return (&a);
1089}
1090
1091//----------------------------------------------------------
1092ApplyPattern::ApplyPattern ()
1093{
1094}
1095
1096//----------------------------------------------------------
1097ApplyPattern::~ApplyPattern ()
1098{
1099}
1100
1101//----------------------------------------------------------
1102void ApplyPattern::show () const
1103{
1104  cmt_string replacement = "";
1105
1106  Pattern* p = Pattern::find (name);
1107  if (p == 0) return;
1108
1109  Use* u = use;
1110  if (u == 0) u = &(Use::current ());
1111
1112  p->expand (u, replacements, replacement);
1113
1114  if (replacement != "")
1115    {
1116      replacement.replace_all ("\"", "");
1117      cout << replacement;
1118    }
1119}
1120
1121//----------------------------------------------------------
1122void ApplyPattern::apply () const
1123{
1124  if (Cmt::get_debug () &&
1125      CmtSystem::testenv ("CMTTESTPATTERN"))
1126    {
1127      cerr << "ApplyPattern::apply> " << name << endl;
1128    }
1129
1130  Pattern* p = Pattern::find (name);
1131  if (p == 0) 
1132    {
1133      if (Cmt::get_debug () &&
1134          CmtSystem::testenv ("CMTTESTPATTERN"))
1135        {
1136          cerr << "ApplyPattern::apply> " << name << " not found" << endl;
1137        }
1138
1139      return;
1140    }
1141
1142  if (p->global) return;
1143 
1144  Use* u = use;
1145  if (u == 0) u = &(Use::current ());
1146
1147  p->apply (u, replacements);
1148}
1149
1150
1151
1152//----------------------------------------------------------
1153/*                                                          */
1154/*  Operations on IgnorePatterns                            */
1155/*                                                          */
1156//----------------------------------------------------------
1157
1158//----------------------------------------------------------
1159void IgnorePattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
1160{
1161  //
1162  // Expected syntax is
1163  //
1164  // ignore_pattern <pattern-name>
1165  //
1166
1167  if (words.size () < 2) return;
1168
1169  if (use == 0) use = &(Use::current());
1170
1171  cmt_string& name = words[1];
1172
1173  add (name, use);
1174}
1175
1176//----------------------------------------------------------
1177IgnorePattern* IgnorePattern::find (const cmt_string& name, Use* use)
1178{
1179  int ignore_pattern_index;
1180
1181  if (use == 0) use = &(Use::current());
1182
1183  if (use->ignore_patterns.size () == 0) return (0);
1184
1185  for (ignore_pattern_index = 0;
1186       ignore_pattern_index < use->ignore_patterns.size ();
1187       ignore_pattern_index++)
1188    {
1189      IgnorePattern& ignore_pattern = use->ignore_patterns[ignore_pattern_index];
1190
1191      if (ignore_pattern.name == name)
1192        {
1193          return (&ignore_pattern);
1194        }
1195    }
1196
1197  return (0);
1198}
1199
1200//----------------------------------------------------------
1201void IgnorePattern::add (const cmt_string& name, Use* use)
1202{
1203  IgnorePattern* ignore_pattern;
1204
1205  ignore_pattern = find (name, use);
1206
1207  if (ignore_pattern == 0)
1208    {
1209      IgnorePattern& a = use->ignore_patterns.add ();
1210
1211      a.name = name;
1212      a.use  = use;
1213    }
1214}
1215
1216//----------------------------------------------------------
1217IgnorePattern::IgnorePattern ()
1218{
1219}
1220
1221//----------------------------------------------------------
1222IgnorePattern::~IgnorePattern ()
1223{
1224}
1225
1226//----------------------------------------------------------
1227void IgnorePattern::show () const
1228{
1229}
Note: See TracBrowser for help on using the repository browser.