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