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

Last change on this file since 652 was 652, checked in by rybkin, 11 years ago

See C.L. 511

  • 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// 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      if (const Project* p = context_use->get_project ())
783        {
784          //          const cmt_string& n = p->get_name ();
785          replacement.replace_all ("<project>", p->get_name ().c_str ());
786        }
787
788      for (int j = 0; j < templates.size (); j++)
789        {
790          Template& t = templates[j];
791          cmt_string s;
792          s = "<";
793          s += t.name;
794          s += ">";
795          replacement.replace_all (s, t.value);
796        }
797
798      for (;;)
799        {
800          int begin = replacement.find ("<");
801          if (begin == cmt_string::npos) break;
802          int end = replacement.find (begin, ">");
803          if (end == cmt_string::npos) break;
804          // Do not erase XML constructs
805          if (replacement[end-1] == '/') break;
806          replacement.erase (begin, end - begin + 1);
807        }
808
809      if (Cmt::get_debug () &&
810          CmtSystem::testenv ("CMTTESTPATTERN"))
811        {
812          cerr << "Pattern::expand2> repl=[" << replacement << "]" << endl;
813        }
814
815    }
816}
817
818//----------------------------------------------------------
819//
820//  Operations on ApplyPatterns
821//
822//----------------------------------------------------------
823
824//----------------------------------------------------------
825void ApplyPattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
826{
827  //
828  // Expected syntax is
829  //
830  // apply_pattern <pattern-name> [ <template>=<value> ... ]
831  //   or just
832  // <pattern-name> [ <template>=<value> ... ]
833  //
834
835  int first_word = 0;
836
837  if (words[0] == "apply_pattern") first_word = 1;
838  else first_word = 0;
839
840  if (words.size () < (first_word + 1)) return;
841
842  if (use == 0) use = &(Use::current());
843
844  cmt_string name = words[first_word];
845  Symbol::expand (name);
846
847  if (name == "") return;
848
849  Pattern* p = Pattern::find (name);
850  if (p == 0) 
851    {
852      if (Cmt::get_current_access () == DeveloperMode &&
853          Cmt::get_recursive ())
854        CmtMessage::warning (CmtError::get_error_name (CmtError::pattern_not_found) +
855                             ": " + name +
856                             " (applied by " + use->get_package_name () + ")"
857                             );
858      return;
859      /*
860      if (use->get_current_scope () != ScopeUnspecified &&
861          use->get_current_scope () != ScopePublic)
862        return;
863      */
864      /*
865      cmt_string use_info (use->get_package_name () +
866                           " " + use->version +
867                           (use->path != "" ? " " + use->path : "") +
868                           " " + use->real_path
869                           );
870      */
871      /*
872        CmtError::set (CmtError::pattern_not_found, name +
873        " (applied by " + use->get_package_name () + ")"
874        );
875      */
876      /*
877      if (CmtMessage::active (Verbose))
878        {
879          CmtMessage::warning (CmtError::get_last_error ());
880        }
881      */
882    }
883
884  ApplyPattern* apply_pattern = add (name, use);
885
886  /*
887    We then look for all <name>=<value> pairs
888  */
889  enum
890    {
891      need_template,
892      need_equal,
893      need_value,
894      can_add,
895      in_error
896    } state = need_template;
897
898  cmt_string tname;
899  cmt_string tvalue;
900
901  for (int i = (first_word + 1); i < words.size (); i++)
902    {
903      cmt_string s = words[i];
904
905      if (Cmt::get_debug () &&
906          CmtSystem::testenv ("CMTTESTPATTERN"))
907        {
908          cerr << "ApplyPattern::action> " << name << " s=[" << s << "] state=" << state << endl;
909        }
910
911      int pos = cmt_string::npos;
912
913      switch (state)
914        {
915        case need_template:
916          pos = s.find ("=");
917
918          tname = s;
919          tvalue = "";
920
921          if (pos == cmt_string::npos)
922            {
923              state = need_equal;
924            }
925          else
926            {
927              s.substr (0, pos, tname);
928              s.substr (pos + 1, tvalue);
929
930              if (Cmt::get_debug () &&
931                  CmtSystem::testenv ("CMTTESTPATTERN"))
932                {
933                  cerr << "ApplyPattern::action-1> n=[" << tname << "] v=[" << tvalue << "]" << endl;
934                }
935             
936              if (tvalue == "")
937                {
938                  state = need_value;
939                }
940              else
941                {                 
942                  state = can_add;
943                }
944            }
945          break;
946        case need_equal:
947          pos = s.find ("=");
948
949          tvalue = "";
950
951          if (pos != 0)
952            {
953              state = in_error;
954              CmtMessage::warning ("bad syntax in apply_pattern " + name
955                                   + " (missing '=' separator)"
956                                   + ( (use != 0) ?
957                                       " (from " + use->get_package_name () + ")":
958                                       "" )
959                                   );
960              /*
961              if (!Cmt::get_quiet ())
962                {
963                  cerr << "#CMT> Warning: bad syntax in apply_pattern " << name
964                       << " (missing '=' separator)";
965
966                  if (use != 0) cerr << " (from " << use->get_package_name () << ")";
967
968                  cerr << endl;
969                }
970              */
971              break;
972            }
973          else
974            {
975              s.substr (pos + 1, tvalue);
976
977              if (tvalue == "")
978                {
979                  state = need_value;
980                }
981              else
982                {                 
983                  state = can_add;
984                }
985            }
986          break;
987        case need_value:
988
989          pos = s.find ("=");
990
991          if (pos == cmt_string::npos)
992            {
993              tvalue = s;
994              state = can_add;
995            }
996          else
997            {
998              tname = s;
999              tvalue = "";
1000
1001              s.substr (0, pos, tname);
1002              s.substr (pos + 1, tvalue);
1003
1004              if (Cmt::get_debug () &&
1005                  CmtSystem::testenv ("CMTTESTPATTERN"))
1006                {
1007                  cerr << "ApplyPattern::action-2> n=[" << tname << "] v=[" << tvalue << "]" << endl;
1008                }
1009             
1010              if (tvalue == "")
1011                {
1012                  state = need_value;
1013                }
1014              else
1015                {                 
1016                  state = can_add;
1017                }
1018            }
1019
1020          break;
1021        }
1022
1023      if (state == can_add)
1024        {
1025          state = need_template;
1026
1027          if (Cmt::get_debug () &&
1028              CmtSystem::testenv ("CMTTESTPATTERN"))
1029            {
1030              cerr << "ApplyPattern::action-3> n=[" << tname << "] v=[" << tvalue << "]" << endl;
1031            }
1032
1033          cmt_string tsearch = "<";
1034          tsearch += tname;
1035          tsearch += ">";
1036
1037          if (p->line.find (tsearch) == cmt_string::npos)
1038            {
1039              CmtMessage::warning ("template <" + tname
1040                                   + "> not expected in pattern " + name
1041                                   + ( (use != 0) ?
1042                                       " (from " + use->get_package_name () + ")":
1043                                       "" )
1044                                   );
1045              /*
1046              if (!Cmt::get_quiet ())
1047                {
1048                  cerr << "#CMT> Warning: template <" << tname << "> not expected in pattern " << name;
1049                  if (use != 0) cerr << " (from " << use->get_package_name () << ")";
1050                  cerr << endl;
1051                }
1052              */
1053            }
1054
1055          Template& t = apply_pattern->replacements.add ();
1056
1057          t.name = tname;
1058          t.value = tvalue;
1059
1060          int size = t.value.size ();
1061
1062          if (size >= 2)
1063            {
1064              if (((t.value[0] == '"') && (t.value[size - 1] == '"')) ||
1065                  ((t.value[0] == '\'') && (t.value[size - 1] == '\'')))
1066                {
1067                  t.value.erase (size - 1);
1068                  t.value.erase (0, 1);
1069                }
1070            }
1071        }
1072    }
1073
1074  apply_pattern->apply ();
1075}
1076
1077//----------------------------------------------------------
1078ApplyPattern* ApplyPattern::add (const cmt_string& name, Use* use)
1079{
1080  ApplyPattern& a = use->apply_patterns.add ();
1081
1082  a.name = name;
1083  a.use  = use;
1084
1085  return (&a);
1086}
1087
1088//----------------------------------------------------------
1089ApplyPattern::ApplyPattern ()
1090{
1091}
1092
1093//----------------------------------------------------------
1094ApplyPattern::~ApplyPattern ()
1095{
1096}
1097
1098//----------------------------------------------------------
1099void ApplyPattern::show () const
1100{
1101  cmt_string replacement = "";
1102
1103  Pattern* p = Pattern::find (name);
1104  if (p == 0) return;
1105
1106  Use* u = use;
1107  if (u == 0) u = &(Use::current ());
1108
1109  p->expand (u, replacements, replacement);
1110
1111  if (replacement != "")
1112    {
1113      replacement.replace_all ("\"", "");
1114      cout << replacement;
1115    }
1116}
1117
1118//----------------------------------------------------------
1119void ApplyPattern::apply () const
1120{
1121  if (Cmt::get_debug () &&
1122      CmtSystem::testenv ("CMTTESTPATTERN"))
1123    {
1124      cerr << "ApplyPattern::apply> " << name << endl;
1125    }
1126
1127  Pattern* p = Pattern::find (name);
1128  if (p == 0) 
1129    {
1130      if (Cmt::get_debug () &&
1131          CmtSystem::testenv ("CMTTESTPATTERN"))
1132        {
1133          cerr << "ApplyPattern::apply> " << name << " not found" << endl;
1134        }
1135
1136      return;
1137    }
1138
1139  if (p->global) return;
1140 
1141  Use* u = use;
1142  if (u == 0) u = &(Use::current ());
1143
1144  p->apply (u, replacements);
1145}
1146
1147
1148
1149//----------------------------------------------------------
1150/*                                                          */
1151/*  Operations on IgnorePatterns                            */
1152/*                                                          */
1153//----------------------------------------------------------
1154
1155//----------------------------------------------------------
1156void IgnorePattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
1157{
1158  //
1159  // Expected syntax is
1160  //
1161  // ignore_pattern <pattern-name>
1162  //
1163
1164  if (words.size () < 2) return;
1165
1166  if (use == 0) use = &(Use::current());
1167
1168  cmt_string& name = words[1];
1169
1170  add (name, use);
1171}
1172
1173//----------------------------------------------------------
1174IgnorePattern* IgnorePattern::find (const cmt_string& name, Use* use)
1175{
1176  int ignore_pattern_index;
1177
1178  if (use == 0) use = &(Use::current());
1179
1180  if (use->ignore_patterns.size () == 0) return (0);
1181
1182  for (ignore_pattern_index = 0;
1183       ignore_pattern_index < use->ignore_patterns.size ();
1184       ignore_pattern_index++)
1185    {
1186      IgnorePattern& ignore_pattern = use->ignore_patterns[ignore_pattern_index];
1187
1188      if (ignore_pattern.name == name)
1189        {
1190          return (&ignore_pattern);
1191        }
1192    }
1193
1194  return (0);
1195}
1196
1197//----------------------------------------------------------
1198void IgnorePattern::add (const cmt_string& name, Use* use)
1199{
1200  IgnorePattern* ignore_pattern;
1201
1202  ignore_pattern = find (name, use);
1203
1204  if (ignore_pattern == 0)
1205    {
1206      IgnorePattern& a = use->ignore_patterns.add ();
1207
1208      a.name = name;
1209      a.use  = use;
1210    }
1211}
1212
1213//----------------------------------------------------------
1214IgnorePattern::IgnorePattern ()
1215{
1216}
1217
1218//----------------------------------------------------------
1219IgnorePattern::~IgnorePattern ()
1220{
1221}
1222
1223//----------------------------------------------------------
1224void IgnorePattern::show () const
1225{
1226}
Note: See TracBrowser for help on using the repository browser.