00001
00002
00003
00004
00005
00006
00007 #ifdef WIN32
00008 #include <direct.h>
00009 #define popen _popen
00010 #define pclose _pclose
00011 #endif
00012
00013 #include "cmt_awk.h"
00014 #include "cmt_system.h"
00015
00016 class Parser
00017 {
00018 public:
00019 Parser (Awk* awk, const cmt_string pattern, const cmt_regexp* expression) :
00020 m_pattern (pattern), m_expression (expression), m_awk(awk)
00021 {
00022 }
00023
00030 Awk::condition parse (const cmt_string& text)
00031 {
00032 Awk::condition result = Awk::ok;
00033
00034 cmt_string line;
00035 int pos;
00036 int max_pos;
00037
00038 pos = 0;
00039 max_pos = text.size ();
00040
00041 m_accumulator.erase (0);
00042
00043 for (pos = 0; pos < max_pos;)
00044 {
00045 int eol = text.find (pos, '\n');
00046
00047 if (eol == cmt_string::npos)
00048 {
00049
00050 text.substr (pos, line);
00051 pos = max_pos;
00052 }
00053 else
00054 {
00055 int length = 1;
00056
00057 int cr = text.find (pos, "\r\n");
00058
00059 if (cr == (eol-1))
00060 {
00061 eol = cr;
00062 length = 2;
00063 }
00064
00065 if (eol == pos)
00066 {
00067
00068 line = "";
00069 pos += length;
00070 }
00071 else
00072 {
00073
00074
00075 text.substr (pos, eol - pos, line);
00076 pos = eol + length;
00077 }
00078 }
00079
00080 if (m_awk != 0) m_awk->inc_line_number ();
00081
00082
00083
00084 result = parse_line (line);
00085 if (result != Awk::ok) break;
00086 }
00087
00088 return (result);
00089 }
00090
00098 Awk::condition parse_line (const cmt_string& line)
00099 {
00100 Awk::condition result = Awk::ok;
00101 int length;
00102 cmt_string temp_line = line;
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 bool finished = true;
00113
00114 length = temp_line.size ();
00115
00116 if (length == 0)
00117 {
00118
00119 finished = true;
00120 }
00121 else
00122 {
00123 int back_slash = temp_line.find_last_of ('\\');
00124
00125 if (back_slash != cmt_string::npos)
00126 {
00127
00128
00129
00130
00131
00132 bool at_end = true;
00133
00134 for (int i = (back_slash + 1); i < length; i++)
00135 {
00136 char c = temp_line[i];
00137 if ((c != ' ') && (c != '\t'))
00138 {
00139 at_end = false;
00140 break;
00141 }
00142 }
00143
00144 if (at_end)
00145 {
00146 temp_line.erase (back_slash);
00147 finished = false;
00148 }
00149 else
00150 {
00151
00152 finished = true;
00153 }
00154 }
00155
00156 m_accumulator += temp_line;
00157 }
00158
00159
00160
00161
00162 if (!finished)
00163 {
00164
00165
00166 return (Awk::ok);
00167 }
00168
00169
00170
00171 if (m_accumulator != "")
00172 {
00173 bool ok = false;
00174
00175 if (m_expression != 0)
00176 {
00177 if (m_expression->match (m_accumulator))
00178 {
00179 ok = true;
00180 }
00181 }
00182 else
00183 {
00184 if ((m_pattern == "") ||
00185 (m_accumulator.find (m_pattern) != cmt_string::npos))
00186 {
00187 ok = true;
00188 }
00189 }
00190
00191 if (ok && (m_awk != 0))
00192 {
00193
00194
00195 m_awk->filter (m_accumulator);
00196 result = m_awk->get_last_condition ();
00197 }
00198
00199 m_accumulator.erase (0);
00200 }
00201
00202 return (result);
00203 }
00204
00205 private:
00206
00207 cmt_string m_accumulator;
00208 cmt_string m_pattern;
00209 const cmt_regexp* m_expression;
00210 Awk* m_awk;
00211 };
00212
00213
00214 Awk::Awk ()
00215 {
00216 m_condition = ok;
00217 }
00218
00219
00220 Awk::~Awk ()
00221 {
00222 }
00223
00224
00225 Awk::condition Awk::run (const cmt_string& text,
00226 const cmt_string& pattern)
00227 {
00228 m_line_number = 0;
00229 m_condition = ok;
00230
00231 begin ();
00232 if (m_condition != ok) return (m_condition);
00233
00234 if (CmtSystem::testenv ("CMTTESTAWK"))
00235 {
00236 Parser p (this, pattern, 0);
00237
00238 m_condition = p.parse (text);
00239 if (m_condition != ok) return (m_condition);
00240 }
00241 else
00242 {
00243 cmt_string line;
00244 int pos = 0;
00245 int max_pos;
00246
00247 max_pos = text.size ();
00248
00249 for (pos = 0; pos < max_pos;)
00250 {
00251 int cr = text.find (pos, "\r\n");
00252 int nl = text.find (pos, '\n');
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 int first = nl;
00268
00269 if (cr != cmt_string::npos)
00270 {
00271
00272
00273 if (nl == cmt_string::npos)
00274 {
00275
00276 first = cr;
00277 }
00278 else
00279 {
00280
00281 first = (nl < cr) ? nl : cr;
00282 }
00283 }
00284
00285 if (first == cmt_string::npos)
00286 {
00287
00288 text.substr (pos, line);
00289 pos = max_pos;
00290 }
00291 else if (first > pos)
00292 {
00293
00294
00295 text.substr (pos, first - pos, line);
00296 pos = first + 1;
00297 }
00298 else
00299 {
00300
00301 line = "";
00302 pos++;
00303 }
00304
00305 m_line_number++;
00306
00307 if (line != "")
00308 {
00309 if ((pattern == "") ||
00310 (line.find (pattern) != cmt_string::npos))
00311 {
00312 filter (line);
00313 if (m_condition != ok) return (m_condition);
00314 }
00315 }
00316 }
00317 }
00318
00319 end ();
00320
00321 return (m_condition);
00322 }
00323
00324
00325 Awk::condition Awk::run (const cmt_string& text,
00326 const cmt_regexp& expression)
00327 {
00328 m_line_number = 0;
00329 m_condition = ok;
00330
00331 begin ();
00332 if (m_condition != ok) return (m_condition);
00333
00334 Parser p (this, "", &expression);
00335
00336 m_condition = p.parse (text);
00337 if (m_condition != ok) return (m_condition);
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 end ();
00407
00408 return (m_condition);
00409 }
00410
00411
00412 void Awk::stop ()
00413 {
00414 m_condition = stopped;
00415 }
00416
00417
00418 void Awk::abort ()
00419 {
00420 m_condition = failed;
00421 }
00422
00423
00424 void Awk::allow_continuation ()
00425 {
00426 m_continuation_allowed = true;
00427 }
00428
00429
00430 Awk::condition Awk::get_last_condition () const
00431 {
00432 return (m_condition);
00433 }
00434
00435
00436 void Awk::begin ()
00437 {
00438 }
00439
00440
00441 void Awk::filter (const cmt_string& )
00442 {
00443
00444 }
00445
00446
00447 void Awk::end ()
00448 {
00449 }
00450
00451
00452 void Awk::inc_line_number ()
00453 {
00454 m_line_number++;
00455 }
00456
00457
00458 Awk::condition FAwk::run (const cmt_string& file_name,
00459 const cmt_string& pattern)
00460 {
00461 if (!CmtSystem::test_file (file_name)) return (failed);
00462
00463 CmtSystem::basename (file_name, m_file_name);
00464 CmtSystem::dirname (file_name, m_dir_name);
00465
00466 cmt_string text;
00467
00468 text.read (file_name);
00469
00470 return (Awk::run (text, pattern));
00471 }
00472
00473
00474 Awk::condition FAwk::run (const cmt_string& file_name,
00475 const cmt_regexp& expression)
00476 {
00477 if (!CmtSystem::test_file (file_name)) return (failed);
00478
00479 CmtSystem::basename (file_name, m_file_name);
00480 CmtSystem::dirname (file_name, m_dir_name);
00481
00482 cmt_string text;
00483
00484 text.read (file_name);
00485
00486 return (Awk::run (text, expression));
00487 }
00488
00489
00490 Awk::condition PAwk::run (const cmt_string& command,
00491 const cmt_string& pattern)
00492 {
00493 cmt_string line;
00494
00495 m_line_number = 0;
00496 m_condition = ok;
00497
00498 begin ();
00499 if (m_condition != ok) return (m_condition);
00500
00501 FILE* f = popen (command.c_str (), "r");
00502
00503 if (f == 0) return (failed);
00504
00505 char buffer[8192];
00506 char* ptr;
00507
00508 while ((ptr = fgets (buffer, sizeof (buffer), f)) != NULL)
00509 {
00510 line = ptr;
00511
00512 if (line.find ("\n") == cmt_string::npos)
00513 {
00514 cerr << "#CMT> Warning: Line too long and truncated in PAwk::run for command " << command << endl;
00515 }
00516
00517 line.replace ("\n", "");
00518
00519 m_line_number++;
00520
00521 if (line != "")
00522 {
00523 if ((pattern == "") ||
00524 (line.find (pattern) != cmt_string::npos))
00525 {
00526 filter (line);
00527 if (m_condition != ok) return (m_condition);
00528 }
00529 }
00530 }
00531
00532 pclose (f);
00533
00534 end ();
00535
00536 return (m_condition);
00537 }
00538
00539
00540 Awk::condition PAwk::run (const cmt_string& command,
00541 const cmt_regexp& expression)
00542 {
00543 cmt_string line;
00544
00545 m_line_number = 0;
00546 m_condition = ok;
00547
00548 begin ();
00549 if (m_condition != ok) return (m_condition);
00550
00551 FILE* f = popen (command.c_str (), "r");
00552
00553 if (f == 0) return (failed);
00554
00555 char buffer[256];
00556 char* ptr;
00557
00558 while ((ptr = fgets (buffer, sizeof (buffer), f)) != NULL)
00559 {
00560 line = ptr;
00561
00562 line.replace ("\n", "");
00563
00564 m_line_number++;
00565
00566 if (line != "")
00567 {
00568 if (expression.match (line))
00569 {
00570 filter (line);
00571 if (m_condition != ok) return (m_condition);
00572 }
00573 }
00574 }
00575
00576 pclose (f);
00577
00578 end ();
00579
00580 return (m_condition);
00581 }
00582
00583
00584 PathScanner::PathScanner ()
00585 {
00586 _running = false;
00587 _level = 0;
00588 }
00589
00590
00591 bool PathScanner::scan_path (const cmt_string& path, actor& a)
00592 {
00593 if (_running) return (false);
00594
00595 _level = 0;
00596 _running = true;
00597
00598 cmt_string compressed_path = path;
00599 CmtSystem::compress_path (compressed_path);
00600 scan_path (compressed_path, 0, a);
00601
00602 _running = false;
00603 _level = 0;
00604
00605 return (true);
00606 }
00607
00608
00609 void PathScanner::scan_path (const cmt_string& path, int level, actor& a)
00610 {
00611 if (level > 10)
00612 {
00613
00614 return;
00615 }
00616
00617
00618
00619
00620
00621 if (!CmtSystem::test_directory (path)) return;
00622
00623 CmtSystem::cmt_string_vector list;
00624 CmtSystem::cmt_string_vector entrylist;
00625
00626 CmtSystem::scan_dir (path, list);
00627
00628 if (list.size () == 0) return;
00629
00630 _level++;
00631
00632
00633 bool has_package = false;
00634
00635 cmt_string name;
00636 cmt_string version;
00637 cmt_string where;
00638
00639 int i;
00640
00641 for (i = 0; i < list.size (); i++)
00642 {
00643 const cmt_string& here = list[i];
00644
00645 if (!CmtSystem::test_directory (here)) continue;
00646
00647 name = "";
00648 version = "";
00649
00650 cmt_string entry;
00651 CmtSystem::basename (here, entry);
00652 CmtSystem::dirname (path, where);
00653
00654
00655
00656 if ((level == 0) && (entry == "InstallArea")) continue;
00657
00658 cmt_string req;
00659
00660 req = here;
00661 req += CmtSystem::file_separator ();
00662 req += "mgr";
00663 req += CmtSystem::file_separator ();
00664 req += "requirements";
00665
00666 if (CmtSystem::test_file (req))
00667 {
00668
00669
00670
00671
00672 version = entry;
00673 CmtSystem::basename (path, name);
00674
00675
00676
00677 a.run (name, version, where);
00678 has_package = true;
00679
00680 continue;
00681 }
00682
00683 req = here;
00684 req += CmtSystem::file_separator ();
00685 req += "cmt";
00686 req += CmtSystem::file_separator ();
00687 req += "requirements";
00688
00689 if (CmtSystem::test_file (req))
00690 {
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 cmt_string vreq;
00703 vreq = here;
00704 vreq += CmtSystem::file_separator ();
00705 vreq += "cmt";
00706 vreq += CmtSystem::file_separator ();
00707 vreq += "version.cmt";
00708
00709 if (CmtSystem::test_file (vreq))
00710 {
00711 version.read (vreq);
00712 int pos;
00713 pos = version.find ('\n');
00714 if (pos != cmt_string::npos) version.erase (pos);
00715 pos = version.find ('\r');
00716 if (pos != cmt_string::npos) version.erase (pos);
00717
00718
00719
00720 a.run (entry, version, path);
00721 has_package = true;
00722
00723 continue;
00724 }
00725
00726 cmt_string p;
00727
00728 p.read (req);
00729 int pos;
00730 pos = p.find ("package");
00731 if (pos != cmt_string::npos)
00732 {
00733 p.erase (0, pos+8);
00734 pos = p.find ('\n');
00735 if (pos != cmt_string::npos) p.erase (pos);
00736 pos = p.find ('\r');
00737 if (pos != cmt_string::npos) p.erase (pos);
00738 p.replace_all (" ", "");
00739 p.replace_all ("\t", "");
00740 if (p != "") name = p;
00741 }
00742
00743 if (name != "")
00744 {
00745
00746
00747 if (entry == name)
00748 {
00749
00750
00751
00752
00753 a.run (name, "v1", path);
00754 has_package = true;
00755
00756 continue;
00757 }
00758
00759 version = entry;
00760 CmtSystem::basename (path, entry);
00761
00762 if (entry == name)
00763 {
00764
00765
00766
00767
00768 a.run (name, version, where);
00769 has_package = true;
00770
00771 continue;
00772 }
00773
00774
00775
00776
00777 }
00778 else
00779 {
00780 version = entry;
00781 CmtSystem::basename (path, entry);
00782 }
00783
00784
00785
00786
00787
00788 if (CmtSystem::is_version_directory (version))
00789 {
00790
00791
00792 a.run (entry, version, where);
00793 has_package = true;
00794
00795 continue;
00796 }
00797
00798 name = version;
00799
00800 where += CmtSystem::file_separator ();
00801 where += entry;
00802
00803
00804
00805 a.run (name, "v1", where);
00806 has_package = true;
00807
00808 continue;
00809 }
00810
00811
00812
00813 scan_path (here, level + 1, a);
00814 }
00815
00816 if (has_package)
00817 {
00818
00819
00820
00821
00822 for (i = 0; i < entrylist.size (); i++)
00823 {
00824 const cmt_string& e = entrylist[i];
00825
00826 cmt_string p = path;
00827 p += CmtSystem::file_separator ();
00828 p += e;
00829
00830
00831
00832
00833
00834
00835 cout << "#PathScanner::scan_path> Restarting scan_path on p=" << p << endl;
00836
00837
00838 scan_path (p, 1, a);
00839 }
00840 }
00841
00842 _level--;
00843 }
00844
00845
00846
00847 bool PathScanner::scan_package (const cmt_string& path,
00848 const cmt_string& package)
00849 {
00850
00851
00852
00853
00854 if (!CmtSystem::test_directory (path)) return (false);
00855
00856 cmt_string pattern = path;
00857 pattern += CmtSystem::file_separator ();
00858 pattern += package;
00859
00860 if (!CmtSystem::test_directory (pattern)) return (false);
00861
00862 CmtSystem::cmt_string_vector list;
00863
00864 CmtSystem::scan_dir (pattern, list);
00865
00866 if (list.size () == 0)
00867 {
00868 return (false);
00869 }
00870
00871 bool result = false;
00872
00873 int i;
00874 for (i = 0; i < list.size (); i++)
00875 {
00876 const cmt_string& name = list[i];
00877
00878 cmt_string version;
00879 CmtSystem::basename (name, version);
00880
00881 if (version == "cmt")
00882 {
00883 cmt_string req;
00884
00885 req = name;
00886 req += CmtSystem::file_separator ();
00887 req += "requirements";
00888
00889 if (CmtSystem::test_file (req))
00890 {
00891
00892
00893 cmt_string req;
00894
00895 req = name;
00896 req += CmtSystem::file_separator ();
00897 req += "version.cmt";
00898
00899 cmt_string version;
00900 if (CmtSystem::test_file (req))
00901 {
00902 version.read (req);
00903 int pos;
00904 pos = version.find ('\n');
00905 if (pos != cmt_string::npos) version.erase (pos);
00906 pos = version.find ('\r');
00907 if (pos != cmt_string::npos) version.erase (pos);
00908 }
00909 else
00910 {
00911 version = "v*";
00912 }
00913
00914 cout << package << " " << version << " " << path << endl;
00915
00916 result = true;
00917 }
00918 }
00919 else if (CmtSystem::is_version_directory (version))
00920 {
00921 cmt_string req;
00922
00923 req = name;
00924 req += CmtSystem::file_separator ();
00925 req += "cmt";
00926 req += CmtSystem::file_separator ();
00927 req += "requirements";
00928
00929 if (CmtSystem::test_file (req))
00930 {
00931
00932
00933 cout << package << " " << version << " " << path << endl;
00934
00935 result = true;
00936 }
00937 else
00938 {
00939
00940
00941 req = name;
00942 req += CmtSystem::file_separator ();
00943 req += "mgr";
00944 req += CmtSystem::file_separator ();
00945 req += "requirements";
00946
00947 if (CmtSystem::test_file (req))
00948 {
00949
00950
00951 cout << package << " " << version << " " << path << endl;
00952
00953 result = true;
00954 }
00955 else
00956 {
00957
00958 }
00959 }
00960 }
00961 else
00962 {
00963
00964 }
00965 }
00966
00967 return (result);
00968 }
00969