source: CMT/v1r25/source/cmt_pattern.cxx

Last change on this file was 607, checked in by rybkin, 12 years ago

See C.L. 482

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