source: CMT/v1r14p20031120/src/cmt_pattern.cxx @ 1

Last change on this file since 1 was 1, checked in by arnault, 19 years ago

Import all tags

File size: 18.5 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5
6#include "cmt_pattern.h"
7#include "cmt_use.h"
8#include "cmt_database.h"
9#include "cmt_error.h"
10#include "cmt_syntax.h"
11
12
13//----------------------------------------------------------
14
15PatternList* PatternList::find (const cmt_string& name)
16{
17  static PatternListMap& map = pattern_list_map ();
18
19  return (map.find (name));
20}
21
22
23Pattern* PatternList::find_pattern (const cmt_string& name)
24{
25  PatternList* list = find (name);
26  if (list == 0) return (0);
27
28  Pattern::PatternPtrVector& vector = list->get_patterns ();
29
30  if (vector.size () == 0) return (0);
31
32  Pattern* p = vector[vector.size () - 1];
33
34  return (p);
35}
36
37Pattern* PatternList::find (const cmt_string& name, Use* use)
38{
39  PatternList* list = find (name);
40  if (list == 0) return (0);
41
42  Pattern::PatternPtrVector& vector = list->get_patterns ();
43
44  for (int i = 0; i < vector.size (); i++)
45    {
46      Pattern* p = vector[i];
47
48      if (p->use == use) return (p);
49    }
50
51  return (0);
52}
53
54PatternList* PatternList::add (const cmt_string& name)
55{
56  PatternList* list = find (name);
57  if (list != 0) return (list);
58
59  static PatternListVector& vector = pattern_lists ();
60
61  PatternList& pl = vector.add ();
62  pl.m_name = name;
63
64  static PatternListMap& map = pattern_list_map ();
65  map.add (name, pl);
66
67  return (&pl);
68}
69
70void PatternList::clear_all ()
71{
72  static PatternListVector& vector = pattern_lists ();
73  static PatternListMap& map = pattern_list_map ();
74
75  for (int i = 0; i < vector.size (); i++)
76    {
77      PatternList& p = vector[i];
78      p.clear ();
79    }
80
81  vector.clear ();
82  map.clear ();
83}
84
85PatternList::PatternListMap& PatternList::pattern_list_map ()
86{
87  static Database& db = Database::instance ();
88  static PatternListMap& map = db.pattern_list_map ();
89
90  return (map);
91}
92
93PatternList::PatternListVector& PatternList::pattern_lists ()
94{
95  static Database& db = Database::instance ();
96  static PatternListVector& vector = db.pattern_lists ();
97
98  return (vector);
99}
100
101PatternList::PatternList ()
102{
103}
104
105PatternList::PatternList (const cmt_string& name) : m_name (name)
106{
107}
108
109PatternList::~PatternList ()
110{
111  clear ();
112}
113
114Pattern::PatternPtrVector& PatternList::get_patterns ()
115{
116  return (m_patterns);
117}
118
119void PatternList::add_pattern (Pattern* pattern)
120{
121  for (int i = 0; i < m_patterns.size (); i++)
122    {
123      Pattern* p = m_patterns[i];
124      if (p->use == pattern->use)
125        {
126          m_patterns[i] = pattern;
127          return;
128        }
129    }
130
131  m_patterns.push_back (pattern);
132}
133
134void PatternList::clear ()
135{
136  m_name = "";
137  m_patterns.clear ();
138}
139
140
141//----------------------------------------------------------
142//
143//  Operations on Patterns
144//
145//----------------------------------------------------------
146
147//----------------------------------------------------------
148void Pattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
149{
150  bool global = false;
151  int start_index;
152
153  if (words.size () < 2) return;
154
155    //
156    // expected syntax is:
157    //
158    //  pattern [-global] pattern-name any-cmt-statement
159    //
160    // where any-cmt-statement may contain "templates"
161    //
162    //      <package>
163    //      <PACKAGE>
164    //      <version>
165    //      <path>
166    //
167
168  cmt_string& option = words[1];
169
170  if (option == "-global")
171    {
172      global = true;
173      start_index = 2;
174    }
175  else
176    {
177      start_index = 1;
178    }
179
180  cmt_string& name = words[start_index];
181
182  start_index++;
183
184  add (name, words, start_index, global, use);
185
186  if (CmtSystem::testenv ("CMTTESTPATTERN"))
187    {
188      cout << "Pattern::action> add " << name << endl;
189    }
190}
191
192/**
193 *
194 *  Patterns are stored with two keys : <name> and <use>
195 *
196 *  thus search must done against these two keys.
197 *
198 */
199Pattern* Pattern::find (const cmt_string& name)
200{
201  Pattern* p = PatternList::find_pattern (name);
202
203  return (p);
204}
205
206//----------------------------------------------------------
207Pattern* Pattern::find (const cmt_string& name, Use* use)
208{
209  Pattern* p = PatternList::find (name, use);
210
211  return (p);
212}
213
214//----------------------------------------------------------
215void Pattern::add (const cmt_string& name,
216                   const CmtSystem::cmt_string_vector& words,
217                   int start_index,
218                   bool global,
219                   Use* use)
220{
221  static PatternVector& Patterns = patterns ();
222
223  Pattern* pattern;
224
225  pattern = find (name, use);
226
227  if (pattern == 0)
228    {
229        // No pattern for the pair <name, use> exist yet.
230        // create one.
231      Pattern& p = Patterns.add ();
232
233      p.clear ();
234
235      p.name = name;
236      p.use  = use;
237
238      PatternList* pl = PatternList::add (name);
239      pl->add_pattern (&p);
240
241      pattern = &p;
242    }
243  else
244    {
245      Pattern& p = *pattern;
246
247      p.clear ();
248
249      p.name = name;
250      p.use  = use;
251    }
252
253    //
254    // Install the cmt-statement as a vector of words.
255    //
256  for (int i = start_index; i < words.size (); i++)
257    {
258      cmt_string& s = pattern->words.add ();
259      s = words[i];
260    }
261
262  pattern->global = global;
263}
264
265/**
266 * Get the number of registered patterns
267 */
268int Pattern::pattern_number ()
269{
270  static PatternVector& Patterns = patterns ();
271
272  return (Patterns.size ());
273}
274
275/**
276 * Get the index'th pattern in the database
277 */
278Pattern& Pattern::pattern (int index)
279{
280  static PatternVector& Patterns = patterns ();
281
282  return (Patterns[index]);
283}
284
285//----------------------------------------------------------
286void Pattern::clear_all ()
287{
288  static PatternVector& Patterns = patterns ();
289
290  for (int i = 0; i < Patterns.size (); i++)
291    {
292      Pattern& p = Patterns[i];
293      p.clear ();
294    }
295
296  Patterns.clear ();
297}
298
299//----------------------------------------------------------
300Pattern::PatternVector& Pattern::patterns ()
301{
302  static Database& db = Database::instance ();
303  static PatternVector& Patterns = db.patterns ();
304
305  return (Patterns);
306}
307
308/**
309 * Applies all global patterns to all uses
310 */
311void Pattern::apply_all_globals ()
312{
313  static PatternVector& Patterns = patterns ();
314
315  int i;
316
317  for (i = 0; i < Patterns.size (); i++)
318    {
319      Pattern& p = Patterns[i];
320
321      if (p.global) p.apply ();
322    }
323}
324
325/**
326 * Applies all global patterns to a given Use
327 */
328void Pattern::apply_all_globals (Use* use)
329{
330  if (use->get_package_name () == "CMT") return;
331
332  static PatternVector& Patterns = patterns ();
333
334  int i;
335
336  for (i = 0; i < Patterns.size (); i++)
337    {
338      Pattern& p = Patterns[i];
339
340      if (p.global)
341        {
342          if (IgnorePattern::find (p.name, use) == 0) p.apply (use);
343        }
344    }
345}
346
347/**
348 * this is the cmt show patterns command
349 * It just shows the pattern declarations.
350 */
351void Pattern::show_all ()
352{
353  static PatternVector& Patterns = patterns ();
354
355  int i;
356
357  for (i = 0; i < Patterns.size (); i++)
358    {
359      Pattern& p = Patterns[i];
360
361      if (p.use != 0) cout << "# " << p.use->get_package_name () << " " << p.use->version;
362      else cout << "# ?? ";
363
364      cout  << " defines ";
365
366      if (p.global) cout << "global ";
367
368      cout << "pattern " << p.name << " as [";
369
370      for (int wi = 0; wi < p.words.size (); wi++)
371        {
372          const cmt_string& s = p.words[wi];
373          if (wi > 0) cout << " ";
374          cout << s;
375        }
376
377      cout << "]" << endl;
378    }
379
380  Use* use = &(Use::current ());
381  for (i = 0; i < use->apply_patterns.size (); i++)
382    {
383      const ApplyPattern& apply_pattern = use->apply_patterns[i];
384
385      cout << "# " << use->get_package_name ()
386           << " applies pattern " << apply_pattern.name << " => ";
387      apply_pattern.show ();
388      cout << endl;
389    }
390}
391
392/**
393 * this is the cmt show applied_patterns command
394 * It just shows the pattern applications.
395 */
396void Pattern::show_all_applied_patterns ()
397{
398  Use* use = &(Use::current ());
399  for (int i = 0; i < use->apply_patterns.size (); i++)
400    {
401      const ApplyPattern& apply_pattern = use->apply_patterns[i];
402
403      cout << "# " << use->get_package_name ()
404           << " applies pattern " << apply_pattern.name << " => ";
405      apply_pattern.show ();
406      cout << endl;
407    }
408}
409
410//----------------------------------------------------------
411void Pattern::show_all_names ()
412{
413  static PatternVector& Patterns = patterns ();
414
415  if (Patterns.size () > 0)
416    {
417      for (int i = 0; i < Patterns.size (); i++)
418        {
419          Pattern& p = Patterns[i];
420         
421          cout << p.name << " ";
422        }
423
424      cout << endl;
425    }
426}
427
428/**
429 *  This is the cmt show pattern <name> command
430 * It shows both the pattern definition(s) and the places
431 * where it is explicitly applied.
432 */
433void Pattern::show (const cmt_string& name)
434{
435  static PatternVector& Patterns = patterns ();
436
437  int i;
438  int j;
439
440  bool found = false;
441
442    // First show the definitions.
443
444  Pattern* p = Pattern::find (name);
445
446  if (p == 0)
447    {
448      CmtError::set (CmtError::pattern_not_found, name);
449      return;
450    }
451
452  cout << "# " << p->use->get_package_name () << " " << p->use->version << " defines ";
453  if (p->global) cout << "global ";
454  cout << "pattern " << p->name << " as [";
455 
456  for (int wi = 0; wi < p->words.size (); wi++)
457    {
458      const cmt_string& s = p->words[wi];
459      if (wi > 0) cout << " ";
460      cout << s;
461    }
462
463  cout << "]" << endl;
464
465    //
466    // Then show the packages which explicitly apply the pattern.
467    //
468  Use* use;
469  ApplyPattern* apply_pattern = 0;
470
471  Use::UsePtrVector& uses = Use::get_ordered_uses ();
472
473  for (i = 0; i < uses.size (); i++)
474    {
475      use = uses[i];
476      for (j = 0; j < use->apply_patterns.size (); j++)
477        {
478          apply_pattern = &(use->apply_patterns[j]);
479           
480          if (apply_pattern->name == name)
481            {
482              cout << "# applied by " << use->get_package_name () << " => " << endl;
483              apply_pattern->show ();
484              cout << endl;
485            }
486        }
487    }
488
489  use = &(Use::current ());
490  for (j = 0; j < use->apply_patterns.size (); j++)
491    {
492      apply_pattern = &(use->apply_patterns[j]);
493       
494      if (apply_pattern->name == name)
495        {
496          cout << "# " << use->get_package_name () << " " << use->version << " applies pattern " << name;
497          cout << " => ";
498          apply_pattern->show ();
499          cout << endl;
500        }
501    }
502}
503
504//----------------------------------------------------------
505Pattern::Pattern ()
506{
507}
508
509//----------------------------------------------------------
510Pattern::~Pattern ()
511
512{
513}
514
515//----------------------------------------------------------
516void Pattern::clear ()
517{
518  global = false;
519  name = "";
520  use = 0;
521  words.clear ();
522}
523
524/**
525 *   Applies a pattern to all uses (except CMT itself) between
526 *   current and the use that declared the pattern.
527 */
528void Pattern::apply () const
529{
530  Use::UsePtrVector& uses = Use::get_ordered_uses ();
531
532  Use* current = &(Use::current());
533
534  Use::UsePtrVector list;
535
536  if (Cmt::get_debug ())
537    {
538      cout << "Pattern(" << name << "::apply> " << " defined in " << use->get_package_name () << endl;
539    }
540
541  if (current != use)
542    {
543      if (!current->get_paths (use, list)) return;
544    }
545  else
546    {
547      list.push_back (current);
548    }
549
550  for (int i = 0; i < list.size (); i++)
551    {
552      Use* u = list[i];
553
554      if (Cmt::get_debug ())
555        {
556          cout << "Pattern(" << name << "::apply> " << " to package " << u->get_package_name () << endl;
557        }
558
559      if ((u->get_package_name () != "CMT") && 
560          (IgnorePattern::find (name, u) == 0)) apply (u);
561    }
562}
563
564//----------------------------------------------------------
565void Pattern::apply (Use* context_use) const
566{
567  static Template::TemplateVector dummy_templates;
568
569  apply (context_use, dummy_templates);
570}
571
572/**
573 *  Applies a pattern to one particular use.
574 */
575void Pattern::apply (Use* context_use, 
576                     const Template::TemplateVector& templates) const
577{
578  cmt_string line;
579
580  expand (context_use, templates, line);
581
582  if (line != "")
583    {
584      SyntaxParser::parse_requirements_text (line, "", context_use);
585    }
586}
587
588//----------------------------------------------------------
589void Pattern::expand (Use* context_use, 
590                      const Template::TemplateVector& templates, 
591                      cmt_string& line) const
592{
593  line = "";
594
595    // First re-create the cmt statement as one line.
596  for (int i = 0; i < words.size (); i++)
597    {
598      const cmt_string& w = words[i];
599
600      if (i > 0) line += " ";
601
602      if ((w == "\n") | (w == ";"))
603        {
604          line += "\n";
605        }
606      else
607        {
608          line += "\"";
609          line += w;
610          line += "\"";
611        }
612    }
613
614  if (context_use == 0) context_use = &(Use::current ());
615
616  if (line != "")
617    {
618        // Substitute templates from the cmt statement
619      line.replace_all ("<package>", context_use->get_package_name ().c_str ());
620      line.replace_all ("<PACKAGE>", context_use->prefix.c_str ());
621      line.replace_all ("<version>", context_use->version.c_str ());
622      line.replace_all ("<path>",    context_use->real_path.c_str ());
623
624      for (int j = 0; j < templates.size (); j++)
625        {
626          Template& t = templates[j];
627          cmt_string s;
628          s = "<";
629          s += t.name;
630          s += ">";
631          line.replace_all (s, t.value);
632        }
633
634      for (;;)
635        {
636          int begin = line.find ("<");
637          if (begin == cmt_string::npos) break;
638          int end = line.find (begin, ">");
639          if (end == cmt_string::npos) break;
640          // Do not erase XML constructs
641          if (line[end-1] == '/') break;
642          line.erase (begin, end - begin + 1);
643        }
644    }
645}
646
647//----------------------------------------------------------
648//
649//  Operations on ApplyPatterns
650//
651//----------------------------------------------------------
652
653//----------------------------------------------------------
654void ApplyPattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
655{
656    //
657    // Expected syntax is
658    //
659    // apply_pattern <pattern-name> [ <template>=<value> ... ]
660    //
661
662  if (words.size () < 2) return;
663
664  if (use == 0) use = &(Use::current());
665
666  cmt_string name = words[1];
667  Symbol::expand (name);
668
669  if (name == "") return;
670
671  ApplyPattern* apply_pattern = add (name, use);
672
673  for (int i = 2; i < words.size (); i++)
674    {
675      cmt_string s = words[i];
676      int pos = s.find ("=");
677      if (pos == cmt_string::npos) break;
678      if (pos == 0) break;
679
680      Template& t = apply_pattern->replacements.add ();
681
682      s.substr (0, pos, t.name);
683      s.substr (pos + 1, t.value);
684
685      int size = t.value.size ();
686
687      if (size >= 2)
688        {
689          if (((t.value[0] == '"') && (t.value[size - 1] == '"')) ||
690              ((t.value[0] == '\'') && (t.value[size - 1] == '\'')))
691            {
692              t.value.erase (size - 1);
693              t.value.erase (0, 1);
694            }
695        }
696    }
697
698  apply_pattern->apply ();
699}
700
701//----------------------------------------------------------
702ApplyPattern* ApplyPattern::add (const cmt_string& name, Use* use)
703{
704  ApplyPattern& a = use->apply_patterns.add ();
705
706  a.name = name;
707  a.use  = use;
708
709  return (&a);
710}
711
712//----------------------------------------------------------
713ApplyPattern::ApplyPattern ()
714{
715}
716
717//----------------------------------------------------------
718ApplyPattern::~ApplyPattern ()
719{
720}
721
722//----------------------------------------------------------
723void ApplyPattern::show () const
724{
725  cmt_string line;
726
727  line = "";
728  Pattern* p = Pattern::find (name);
729  if (p == 0) return;
730
731  Use* u = use;
732  if (u == 0) u = &(Use::current ());
733
734  p->expand (u, replacements, line);
735
736  if (line != "")
737    {
738      line.replace_all ("\"", "");
739      cout << line;
740    }
741}
742
743//----------------------------------------------------------
744void ApplyPattern::apply () const
745{
746  cmt_string line;
747
748  if (CmtSystem::testenv ("CMTTESTPATTERN"))
749    {
750      cout << "ApplyPattern::apply> " << name << endl;
751    }
752
753  line = "";
754  Pattern* p = Pattern::find (name);
755  if (p == 0) 
756    {
757      if (CmtSystem::testenv ("CMTTESTPATTERN"))
758        {
759          cout << "ApplyPattern::apply> " << name << " not found" << endl;
760        }
761
762      return;
763    }
764
765  if (p->global) return;
766 
767  Use* u = use;
768  if (u == 0) u = &(Use::current ());
769
770  p->apply (u, replacements);
771}
772
773
774
775//----------------------------------------------------------
776/*                                                          */
777/*  Operations on IgnorePatterns                            */
778/*                                                          */
779//----------------------------------------------------------
780
781//----------------------------------------------------------
782void IgnorePattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
783{
784    //
785    // Expected syntax is
786    //
787    // ignore_pattern <pattern-name>
788    //
789
790  if (words.size () < 2) return;
791
792  if (use == 0) use = &(Use::current());
793
794  cmt_string& name = words[1];
795
796  add (name, use);
797}
798
799//----------------------------------------------------------
800IgnorePattern* IgnorePattern::find (const cmt_string& name, Use* use)
801{
802  int ignore_pattern_index;
803
804  if (use == 0) use = &(Use::current());
805
806  if (use->ignore_patterns.size () == 0) return (0);
807
808  for (ignore_pattern_index = 0;
809       ignore_pattern_index < use->ignore_patterns.size ();
810       ignore_pattern_index++)
811    {
812      IgnorePattern& ignore_pattern = use->ignore_patterns[ignore_pattern_index];
813
814      if (ignore_pattern.name == name)
815        {
816          return (&ignore_pattern);
817        }
818    }
819
820  return (0);
821}
822
823//----------------------------------------------------------
824void IgnorePattern::add (const cmt_string& name, Use* use)
825{
826  IgnorePattern* ignore_pattern;
827
828  ignore_pattern = find (name, use);
829
830  if (ignore_pattern == 0)
831    {
832      IgnorePattern& a = use->ignore_patterns.add ();
833
834      a.name = name;
835      a.use  = use;
836    }
837}
838
839//----------------------------------------------------------
840IgnorePattern::IgnorePattern ()
841{
842}
843
844//----------------------------------------------------------
845IgnorePattern::~IgnorePattern ()
846{
847}
848
849//----------------------------------------------------------
850void IgnorePattern::show () const
851{
852}
Note: See TracBrowser for help on using the repository browser.