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
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
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00129
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
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
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
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
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
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
00519 if (line[end-1] == '/') break;
00520 line.erase (begin, end - begin + 1);
00521 }
00522 }
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532 void ApplyPattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
00533 {
00534
00535
00536
00537
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
00652
00653
00654
00655
00656 void IgnorePattern::action (const CmtSystem::cmt_string_vector& words, Use* use)
00657 {
00658
00659
00660
00661
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 }