source: CMT/HEAD/source/cmt_pattern.cxx @ 542

Last change on this file since 542 was 542, checked in by rybkin, 14 years ago

See C.L. 429

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