Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

cmt_pattern.cxx

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <ctype.h>
00005 
00006 #include "cmt_pattern.h"
00007 #include "cmt_use.h"
00008 #include "cmt_database.h"
00009 #include "cmt_error.h"
00010 
00011 //----------------------------------------------------------
00012 //
00013 //  Operations on Patterns
00014 //
00015 //----------------------------------------------------------
00016 
00017 //----------------------------------------------------------
00018 void Pattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
00019 {
00020   bool global = false;
00021   int start_index;
00022 
00023   if (words.size () < 2) return;
00024 
00025     //
00026     // expected syntax is:
00027     //
00028     //  pattern [-global] pattern-name any-cmt-statement
00029     //
00030     // where any-cmt-statement may contain "templates"
00031     //
00032     //      <package>
00033     //      <PACKAGE>
00034     //      <version>
00035     //      <path>
00036     //
00037 
00038   cmt_string& option = words[1];
00039 
00040   if (option == "-global")
00041     {
00042       global = true;
00043       start_index = 2;
00044     }
00045   else
00046     {
00047       start_index = 1;
00048     }
00049 
00050   cmt_string& name = words[start_index];
00051 
00052   start_index++;
00053 
00054   add (name, words, start_index, global, use);
00055 
00056   if (CmtSystem::testenv ("CMTTESTPATTERN"))
00057     {
00058       cout << "Pattern::action> add " << name << endl;
00059     }
00060 }
00061 
00069 Pattern* Pattern::find (const cmt_string& name)
00070 {
00071   Use::UsePtrVector& uses = Use::uses ();
00072 
00073   Use* use = &(Use::current ());
00074 
00075   Pattern* p;
00076 
00077   p = find (name, use);
00078   if (p != 0) return (p);
00079 
00080   for (int i = 0; i < uses.size (); i++)
00081     {
00082       use = uses[i];
00083       p = find (name, use);
00084       if (p != 0) return (p);
00085     }
00086 
00087   return (0);
00088 }
00089 
00090 //----------------------------------------------------------
00091 Pattern* Pattern::find (const cmt_string& name, Use* use)
00092 {
00093   static PatternVector& Patterns = patterns ();
00094 
00095   int pattern_index;
00096   Pattern* pattern;
00097 
00098   if (Patterns.size () == 0) return (0);
00099 
00100   for (pattern_index = 0; pattern_index < Patterns.size (); pattern_index++)
00101     {
00102       pattern = &(Patterns[pattern_index]);
00103 
00104       if ((pattern->name == name) && (pattern->use) == use)
00105         {
00106           return (pattern);
00107         }
00108     }
00109 
00110   return (0);
00111 }
00112 
00113 //----------------------------------------------------------
00114 void Pattern::add (const cmt_string& name,
00115                    const CmtSystem::cmt_string_vector& words,
00116                    int start_index,
00117                    bool global,
00118                    Use* use)
00119 {
00120   static PatternVector& Patterns = patterns ();
00121 
00122   Pattern* pattern;
00123 
00124   pattern = find (name, use);
00125 
00126   if (pattern == 0)
00127     {
00128         // No pattern for the pair <name, use> exist yet.
00129         // create one.
00130       Pattern& p = Patterns.add ();
00131 
00132       p.clear ();
00133 
00134       p.name = name;
00135       p.use  = use;
00136 
00137       pattern = &p;
00138     }
00139   else
00140     {
00141       pattern->clear ();
00142     }
00143 
00144     //
00145     // Install the cmt-statement as a vector of words.
00146     //
00147   for (int i = start_index; i < words.size (); i++)
00148     {
00149       cmt_string& s = pattern->words.add ();
00150       s = words[i];
00151     }
00152 
00153   pattern->global = global;
00154 }
00155 
00159 int Pattern::pattern_number ()
00160 {
00161   static PatternVector& Patterns = patterns ();
00162 
00163   return (Patterns.size ());
00164 }
00165 
00169 Pattern& Pattern::pattern (int index)
00170 {
00171   static PatternVector& Patterns = patterns ();
00172 
00173   return (Patterns[index]);
00174 }
00175 
00176 //----------------------------------------------------------
00177 void Pattern::clear_all ()
00178 {
00179   static PatternVector& Patterns = patterns ();
00180 
00181   for (int i = 0; i < Patterns.size (); i++)
00182     {
00183       Pattern& p = Patterns[i];
00184       p.clear ();
00185     }
00186 
00187   Patterns.clear ();
00188 }
00189 
00190 //----------------------------------------------------------
00191 Pattern::PatternVector& Pattern::patterns ()
00192 {
00193   static Database& db = Database::instance ();
00194   static PatternVector& Patterns = db.patterns ();
00195 
00196   return (Patterns);
00197 }
00198 
00202 void Pattern::apply_all_globals ()
00203 {
00204   static PatternVector& Patterns = patterns ();
00205 
00206   int i;
00207 
00208   for (i = 0; i < Patterns.size (); i++)
00209     {
00210       Pattern& p = Patterns[i];
00211 
00212       if (p.global) p.apply ();
00213     }
00214 }
00215 
00219 void Pattern::apply_all_globals (Use* use)
00220 {
00221   if (use->package == "CMT") return;
00222 
00223   static PatternVector& Patterns = patterns ();
00224 
00225   int i;
00226 
00227   for (i = 0; i < Patterns.size (); i++)
00228     {
00229       Pattern& p = Patterns[i];
00230 
00231       if (p.global)
00232         {
00233           if (IgnorePattern::find (p.name, use) == 0) p.apply (use);
00234         }
00235     }
00236 }
00237 
00242 void Pattern::show_all ()
00243 {
00244   static PatternVector& Patterns = patterns ();
00245 
00246   int i;
00247 
00248   for (i = 0; i < Patterns.size (); i++)
00249     {
00250       Pattern& p = Patterns[i];
00251 
00252       cout << "# " << p.use->package << " " << p.use->version << " defines ";
00253       if (p.global) cout << "global ";
00254       cout << "pattern " << p.name << " as [";
00255 
00256       for (int wi = 0; wi < p.words.size (); wi++)
00257         {
00258           const cmt_string& s = p.words[wi];
00259           if (wi > 0) cout << " ";
00260           cout << s;
00261         }
00262 
00263       cout << "]" << endl;
00264     }
00265 
00266   Use* use = &(Use::current ());
00267   for (i = 0; i < use->apply_patterns.size (); i++)
00268     {
00269       const ApplyPattern& apply_pattern = use->apply_patterns[i];
00270 
00271       cout << "# " << use->package
00272            << " applies pattern " << apply_pattern.name << " => ";
00273       apply_pattern.show ();
00274     }
00275 }
00276 
00281 void Pattern::show_all_applied_patterns ()
00282 {
00283   Use* use = &(Use::current ());
00284   for (int i = 0; i < use->apply_patterns.size (); i++)
00285     {
00286       const ApplyPattern& apply_pattern = use->apply_patterns[i];
00287 
00288       cout << "# " << use->package
00289            << " applies pattern " << apply_pattern.name << " => ";
00290       apply_pattern.show ();
00291     }
00292 }
00293 
00294 //----------------------------------------------------------
00295 void Pattern::show_all_names ()
00296 {
00297   static PatternVector& Patterns = patterns ();
00298 
00299   if (Patterns.size () > 0)
00300     {
00301       for (int i = 0; i < Patterns.size (); i++)
00302         {
00303           Pattern& p = Patterns[i];
00304           
00305           cout << p.name << " ";
00306         }
00307 
00308       cout << endl;
00309     }
00310 }
00311 
00317 void Pattern::show (const cmt_string& name)
00318 {
00319   static PatternVector& Patterns = patterns ();
00320 
00321   int i;
00322   int j;
00323 
00324   bool found = false;
00325 
00326     // First show the definitions.
00327   for (i = 0; i < Patterns.size (); i++)
00328     {
00329       Pattern& p = Patterns[i];
00330 
00331       if (p.name == name)
00332         {
00333           found = true;
00334 
00335           cout << "# " << p.use->package << " " << p.use->version << " defines ";
00336           if (p.global) cout << "global ";
00337           cout << "pattern " << p.name << " as [";
00338 
00339           for (int wi = 0; wi < p.words.size (); wi++)
00340             {
00341               const cmt_string& s = p.words[wi];
00342               if (wi > 0) cout << " ";
00343               cout << s;
00344             }
00345 
00346           cout << "]" << endl;
00347         }
00348     }
00349 
00350   if (!found)
00351     {
00352       CmtError::set (CmtError::pattern_not_found, name);
00353       return;
00354     }
00355 
00356     //
00357     // Then show the packages which explicitly apply the pattern.
00358     //
00359   Use* use;
00360   ApplyPattern* apply_pattern = 0;
00361 
00362   Use::UsePtrVector& uses = Use::uses ();
00363 
00364   for (i = 0; i < uses.size (); i++)
00365     {
00366       use = uses[i];
00367       for (j = 0; j < use->apply_patterns.size (); j++)
00368         {
00369           apply_pattern = &(use->apply_patterns[j]);
00370             
00371           if (apply_pattern->name == name)
00372             {
00373               cout << "# " << use->package << " " << use->version << " applies pattern " << name;
00374               cout << " => ";
00375               apply_pattern->show ();
00376             }
00377         }
00378     }
00379 
00380   use = &(Use::current ());
00381   for (j = 0; j < use->apply_patterns.size (); j++)
00382     {
00383       apply_pattern = &(use->apply_patterns[j]);
00384         
00385       if (apply_pattern->name == name)
00386         {
00387           cout << "# " << use->package << " " << use->version << " applies pattern " << name;
00388           cout << " => ";
00389           apply_pattern->show ();
00390         }
00391     }
00392 }
00393 
00394 //----------------------------------------------------------
00395 Pattern::Pattern ()
00396 {
00397 }
00398 
00399 //----------------------------------------------------------
00400 Pattern::~Pattern ()
00401 
00402 {
00403 }
00404 
00405 //----------------------------------------------------------
00406 void Pattern::clear ()
00407 {
00408   global = false;
00409   name = "";
00410   use = 0;
00411   words.clear ();
00412 }
00413 
00417 void Pattern::apply () const
00418 {
00419   Use::UsePtrVector& uses = Use::uses ();
00420 
00421   Use* current = &(Use::current());
00422 
00423   Use::UsePtrVector list;
00424 
00425   if (current != use)
00426     {
00427       if (!current->get_paths (use, list)) return;
00428     }
00429   else
00430     {
00431       list.push_back (current);
00432     }
00433 
00434   for (int i = 0; i < list.size (); i++)
00435     {
00436       Use* u = list[i];
00437       if ((u->package != "CMT") && 
00438           (IgnorePattern::find (name, u) == 0)) apply (u);
00439     }
00440 }
00441 
00442 //----------------------------------------------------------
00443 void Pattern::apply (Use* context_use) const
00444 {
00445   static Template::TemplateVector dummy_templates;
00446 
00447   apply (context_use, dummy_templates);
00448 }
00449 
00453 void Pattern::apply (Use* context_use, 
00454                      const Template::TemplateVector& templates) const
00455 {
00456   cmt_string line;
00457 
00458   expand (context_use, templates, line);
00459 
00460   if (line != "")
00461     {
00462       Cmt::parse_requirements_text (line, "", context_use);
00463     }
00464 }
00465 
00466 //----------------------------------------------------------
00467 void Pattern::expand (Use* context_use, 
00468                       const Template::TemplateVector& templates, 
00469                       cmt_string& line) const
00470 {
00471   line = "";
00472 
00473     // First re-create the cmt statement as one line.
00474   for (int i = 0; i < words.size (); i++)
00475     {
00476       const cmt_string& w = words[i];
00477 
00478       if (i > 0) line += " ";
00479 
00480       if ((w == "\n") | (w == ";"))
00481         {
00482           line += "\n";
00483         }
00484       else
00485         {
00486           line += "\"";
00487           line += w;
00488           line += "\"";
00489         }
00490     }
00491 
00492   if (context_use == 0) context_use = &(Use::current ());
00493 
00494   if (line != "")
00495     {
00496         // Substitute templates from the cmt statement
00497       line.replace_all ("<package>", context_use->package.c_str ());
00498       line.replace_all ("<PACKAGE>", context_use->prefix.c_str ());
00499       line.replace_all ("<version>", context_use->version.c_str ());
00500       line.replace_all ("<path>",    context_use->real_path.c_str ());
00501 
00502       for (int j = 0; j < templates.size (); j++)
00503         {
00504           Template& t = templates[j];
00505           cmt_string s;
00506           s = "<";
00507           s += t.name;
00508           s += ">";
00509           line.replace_all (s, t.value);
00510         }
00511 
00512       for (;;)
00513         {
00514           int begin = line.find ("<");
00515           if (begin == cmt_string::npos) break;
00516           int end = line.find (begin, ">");
00517           if (end == cmt_string::npos) break;
00518           // Do not erase XML constructs
00519           if (line[end-1] == '/') break;
00520           line.erase (begin, end - begin + 1);
00521         }
00522     }
00523 }
00524 
00525 //----------------------------------------------------------
00526 //
00527 //  Operations on ApplyPatterns
00528 //
00529 //----------------------------------------------------------
00530 
00531 //----------------------------------------------------------
00532 void ApplyPattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
00533 {
00534     //
00535     // Expected syntax is
00536     //
00537     // apply_pattern <pattern-name> [ <template>=<value> ... ]
00538     //
00539 
00540   if (words.size () < 2) return;
00541 
00542   if (use == 0) use = &(Use::current());
00543 
00544   cmt_string& name = words[1];
00545 
00546   ApplyPattern* apply_pattern = add (name, use);
00547 
00548   for (int i = 2; i < words.size (); i++)
00549     {
00550       cmt_string s = words[i];
00551       int pos = s.find ("=");
00552       if (pos == cmt_string::npos) break;
00553       if (pos == 0) break;
00554 
00555       Template& t = apply_pattern->replacements.add ();
00556 
00557       s.substr (0, pos, t.name);
00558       s.substr (pos + 1, t.value);
00559 
00560       int size = t.value.size ();
00561 
00562       if (size >= 2)
00563         {
00564           if (((t.value[0] == '"') && (t.value[size - 1] == '"')) ||
00565               ((t.value[0] == '\'') && (t.value[size - 1] == '\'')))
00566             {
00567               t.value.erase (size - 1);
00568               t.value.erase (0, 1);
00569             }
00570         }
00571     }
00572 
00573   apply_pattern->apply ();
00574 }
00575 
00576 //----------------------------------------------------------
00577 ApplyPattern* ApplyPattern::add (const cmt_string& name, Use* use)
00578 {
00579   ApplyPattern& a = use->apply_patterns.add ();
00580 
00581   a.name = name;
00582   a.use  = use;
00583 
00584   return (&a);
00585 }
00586 
00587 //----------------------------------------------------------
00588 ApplyPattern::ApplyPattern ()
00589 {
00590 }
00591 
00592 //----------------------------------------------------------
00593 ApplyPattern::~ApplyPattern ()
00594 {
00595 }
00596 
00597 //----------------------------------------------------------
00598 void ApplyPattern::show () const
00599 {
00600   cmt_string line;
00601 
00602   line = "";
00603   Pattern* p = Pattern::find (name);
00604   if (p == 0) return;
00605 
00606   Use* u = use;
00607   if (u == 0) u = &(Use::current ());
00608 
00609   p->expand (u, replacements, line);
00610 
00611   if (line != "")
00612     {
00613       cout << "[" << line << "]" << endl;
00614     }
00615 }
00616 
00617 //----------------------------------------------------------
00618 void ApplyPattern::apply () const
00619 {
00620   cmt_string line;
00621 
00622   if (CmtSystem::testenv ("CMTTESTPATTERN"))
00623     {
00624       cout << "ApplyPattern::apply> " << name << endl;
00625     }
00626 
00627   line = "";
00628   Pattern* p = Pattern::find (name);
00629   if (p == 0) 
00630     {
00631       if (CmtSystem::testenv ("CMTTESTPATTERN"))
00632         {
00633           cout << "ApplyPattern::apply> " << name << " not found" << endl;
00634         }
00635 
00636       return;
00637     }
00638 
00639   if (p->global) return;
00640   
00641   Use* u = use;
00642   if (u == 0) u = &(Use::current ());
00643 
00644   p->apply (u, replacements);
00645 }
00646 
00647 
00648 
00649 //----------------------------------------------------------
00650 /*                                                          */
00651 /*  Operations on IgnorePatterns                            */
00652 /*                                                          */
00653 //----------------------------------------------------------
00654 
00655 //----------------------------------------------------------
00656 void IgnorePattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
00657 {
00658     //
00659     // Expected syntax is
00660     //
00661     // ignore_pattern <pattern-name>
00662     //
00663 
00664   if (words.size () < 2) return;
00665 
00666   if (use == 0) use = &(Use::current());
00667 
00668   cmt_string& name = words[1];
00669 
00670   add (name, use);
00671 }
00672 
00673 //----------------------------------------------------------
00674 IgnorePattern* IgnorePattern::find (const cmt_string& name, Use* use)
00675 {
00676   int ignore_pattern_index;
00677 
00678   if (use == 0) use = &(Use::current());
00679 
00680   if (use->ignore_patterns.size () == 0) return (0);
00681 
00682   for (ignore_pattern_index = 0;
00683        ignore_pattern_index < use->ignore_patterns.size ();
00684        ignore_pattern_index++)
00685     {
00686       IgnorePattern& ignore_pattern = use->ignore_patterns[ignore_pattern_index];
00687 
00688       if (ignore_pattern.name == name)
00689         {
00690           return (&ignore_pattern);
00691         }
00692     }
00693 
00694   return (0);
00695 }
00696 
00697 //----------------------------------------------------------
00698 void IgnorePattern::add (const cmt_string& name, Use* use)
00699 {
00700   IgnorePattern* ignore_pattern;
00701 
00702   ignore_pattern = find (name, use);
00703 
00704   if (ignore_pattern == 0)
00705     {
00706       IgnorePattern& a = use->ignore_patterns.add ();
00707 
00708       a.name = name;
00709       a.use  = use;
00710     }
00711 }
00712 
00713 //----------------------------------------------------------
00714 IgnorePattern::IgnorePattern ()
00715 {
00716 }
00717 
00718 //----------------------------------------------------------
00719 IgnorePattern::~IgnorePattern ()
00720 {
00721 }
00722 
00723 //----------------------------------------------------------
00724 void IgnorePattern::show () const
00725 {
00726 }

Generated at Thu May 16 16:27:07 2002 for CMT by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000