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