00001
00002
00003
00004
00005
00006
00007 #include
00008 #include
00009
00010 #ifndef WIN32
00011 #include
00012 #endif
00013
00014 #include "cmt_generator.h"
00015 #include "cmt_use.h"
00016 #include "cmt_symbol.h"
00017
00018 #include "cmt_generators.h"
00019
00020
00021 void SourceFile::set (const cmt_string name, Language& language, const cmt_string output)
00022 {
00023 m_name = name;
00024 m_language = &language;
00025 m_output = output;
00026
00027 CmtSystem::reduce_file_separators (m_name);
00028 }
00029
00030 cmt_string SourceFile::name () const
00031 {
00032 return (m_name);
00033 }
00034
00035 Language& SourceFile::language () const
00036 {
00037 return (*m_language);
00038 }
00039
00040 cmt_string SourceFile::output () const
00041 {
00042 return (m_output);
00043 }
00044
00045
00046
00047 CmtGenerator::CmtGenerator ()
00048 {
00049 m_CONSTITUENT.set ("CONSTITUENT");
00050 m_LINKMACRO.set ("LINKMACRO");
00051 m_DOCPATH.set ("DOCPATH");
00052 m_PACKAGEPATH.set ("PACKAGEPATH");
00053 m_PACKAGEPREFIX.set ("PACKAGEPREFIX");
00054 m_PACKAGE.set ("PACKAGE");
00055 m_VERSION.set ("VERSION");
00056 m_MGRSTYLE.set ("MGRSTYLE");
00057 m_TITLE.set ("TITLE");
00058 m_GROUP.set ("GROUP");
00059 m_CONSTITUENT.set ("CONSTITUENT");
00060 m_CONSTITUENTSUFFIX.set ("CONSTITUENTSUFFIX");
00061 m_LIBRARYSUFFIX.set ("LIBRARYSUFFIX");
00062 m_USER.set ("USER");
00063 m_DATE.set ("DATE");
00064 m_PROTOTARGET.set ("PROTOTARGET");
00065 m_OBJS.set ("OBJS");
00066 m_CLASSES.set ("CLASSES");
00067 m_PROTOSTAMPS.set ("PROTOSTAMPS");
00068 m_NAME.set ("NAME");
00069 m_FILEPATH.set ("FILEPATH");
00070 m_FILESUFFIX.set ("FILESUFFIX");
00071 m_SUFFIX.set ("SUFFIX");
00072 m_FILENAME.set ("FILENAME");
00073 m_LINKMACRO.set ("LINKMACRO");
00074 m_LINE.set ("LINE");
00075 m_ADDINCLUDE.set ("ADDINCLUDE");
00076 m_FULLNAME.set ("FULLNAME");
00077 m_DIRNAME.set ("DIRNAME");
00078 m_OUTPUTNAME.set ("OUTPUTNAME");
00079 m_ALLOS9SOURCES.set ("ALLOS9SOURCES");
00080 m_NODEBUGUSELINKOPTS.set ("NODEBUGUSELINKOPTS");
00081 m_DEBUGUSELINKOPTS.set ("DEBUGUSELINKOPTS");
00082 m_USEINCLUDES.set ("USEINCLUDES");
00083 m_HASTARGETTAG.set ("HASTARGETTAG");
00084 }
00085
00086
00087 void CmtGenerator::reset ()
00088 {
00089 m_CONSTITUENT = "";
00090 m_LINKMACRO = "";
00091 m_DOCPATH = "";
00092 m_PACKAGEPATH = "";
00093 m_PACKAGEPREFIX = "";
00094 m_PACKAGE = "";
00095 m_VERSION = "";
00096 m_MGRSTYLE = "";
00097 m_TITLE = "";
00098 m_GROUP = "";
00099 m_CONSTITUENTSUFFIX = "";
00100 m_LIBRARYSUFFIX = "";
00101 m_USER = "";
00102 m_DATE = "";
00103 m_PROTOTARGET = "";
00104 m_OBJS = "";
00105 m_CLASSES = "";
00106 m_PROTOSTAMPS = "";
00107 m_NAME = "";
00108 m_FILEPATH = "";
00109 m_FILESUFFIX = "";
00110 m_SUFFIX = "";
00111 m_FILENAME = "";
00112 m_LINE = "";
00113 m_ADDINCLUDE = "";
00114 m_FULLNAME = "";
00115 m_OUTPUTNAME = "";
00116 m_ALLOS9SOURCES = "";
00117 m_NODEBUGUSELINKOPTS = "";
00118 m_DEBUGUSELINKOPTS = "";
00119 m_USEINCLUDES = "";
00120 m_HASTARGETTAG = "";
00121 m_PACKINCLUDES = "";
00122 m_PACKOS9 = false;
00123 m_GENERATOR = "";
00124
00125 is_library = false;
00126 is_application = false;
00127 srcdir = "";
00128 docdir = "";
00129 cmtdir = "";
00130 incdir = "";
00131 src = "$(src)";
00132 doc = "$(doc)";
00133 inc = "$(inc)";
00134 mgr = "$(mgr)";
00135 cmt = "$(cmt)";
00136 protos = "";
00137 protonames = "";
00138 os9sources = "";
00139
00140 m_source_files.clear ();
00141
00142 Language::setup_all_fragments ();
00143
00144 CmtSystem::cd (Cmt::get_current_dir ());
00145
00146 cmt_string branch = CmtSystem::current_branch ();
00147
00148 if ((branch == "mgr") || (branch == "cmt"))
00149 {
00150 if (CmtSystem::test_directory ("../src"))
00151 {
00152 srcdir = "..";
00153 srcdir += CmtSystem::file_separator ();
00154 srcdir += "src";
00155 srcdir += CmtSystem::file_separator ();
00156 }
00157 else
00158 {
00159 srcdir = "";
00160 }
00161
00162 if (CmtSystem::test_directory ("../doc"))
00163 {
00164 docdir = "..";
00165 docdir += CmtSystem::file_separator ();
00166 docdir += "doc";
00167 docdir += CmtSystem::file_separator ();
00168 }
00169 else
00170 {
00171 docdir = "";
00172 }
00173
00174 if (CmtSystem::test_directory ("../cmt"))
00175 {
00176 cmtdir = "..";
00177 cmtdir += CmtSystem::file_separator ();
00178 cmtdir += "cmt";
00179 cmtdir += CmtSystem::file_separator ();
00180 }
00181 else if (CmtSystem::test_directory ("../mgr"))
00182 {
00183 cmtdir = "..";
00184 cmtdir += CmtSystem::file_separator ();
00185 cmtdir += "mgr";
00186 cmtdir += CmtSystem::file_separator ();
00187 }
00188 else
00189 {
00190 cmtdir = CmtSystem::pwd ();
00191 cmtdir += CmtSystem::file_separator ();
00192 }
00193
00194 if (CmtSystem::test_directory ("../src"))
00195 {
00196 incdir = "..";
00197 incdir += CmtSystem::file_separator ();
00198 incdir += "src";
00199 incdir += CmtSystem::file_separator ();
00200 }
00201 else
00202 {
00203 incdir = "";
00204 }
00205 }
00206 else
00207 {
00208 srcdir = ".";
00209 srcdir += CmtSystem::file_separator ();
00210 docdir = ".";
00211 docdir += CmtSystem::file_separator ();
00212 cmtdir = CmtSystem::pwd ();
00213 cmtdir += CmtSystem::file_separator ();
00214 incdir = ".";
00215 incdir += CmtSystem::file_separator ();
00216 }
00217 }
00218
00219
00220 bool CmtGenerator::prepare_output (const cmt_string& package,
00221 const Constituent& constituent)
00222 {
00223 m_PACKAGE = package;
00224 m_CONSTITUENT = constituent.name;
00225 m_CONSTITUENTSUFFIX = constituent.suffix;
00226
00227 m_PACKOS9 = constituent.need_OS9;
00228
00229 m_output_file_name = cmtdir + m_CONSTITUENT + ".";
00230
00231 if (Cmt::build_nmake ())
00232 {
00233 m_output_file_name += "nmake";
00234 }
00235 else
00236 {
00237 m_output_file_name += "make";
00238 }
00239
00240 m_output_file_name += "new";
00241
00242
00243 m_output_file = fopen (m_output_file_name.c_str (), "wb");
00244 if (m_output_file != NULL)
00245 {
00246 return (true);
00247 }
00248 else
00249 {
00250 return (false);
00251 }
00252 }
00253
00254
00255 void CmtGenerator::check (const cmt_string& name)
00256 {
00257 static cmt_string old;
00258 static cmt_string backup;
00259
00260 old = name;
00261
00262 int pos = old.find_last_of ("new");
00263 old.erase (pos);
00264
00265 if (!CmtSystem::compare_files (old, name))
00266 {
00267 backup = old;
00268 backup += "sav";
00269
00270 unlink (backup.c_str ());
00271 rename (old.c_str (), backup.c_str ());
00272 rename (name.c_str (), old.c_str ());
00273 }
00274 else
00275 {
00276 unlink (name);
00277 }
00278 }
00279
00280
00281 void CmtGenerator::commit (const cmt_string& name)
00282 {
00283 static cmt_string old;
00284 static cmt_string backup;
00285
00286 old = name;
00287
00288 int pos = old.find_last_of ("new");
00289 old.erase (pos);
00290
00291 if (CmtSystem::test_file (old))
00292 {
00293 backup = old;
00294 backup += "sav";
00295
00296 unlink (backup.c_str ());
00297 rename (old.c_str (), backup.c_str ());
00298 }
00299
00300 rename (name.c_str (), old.c_str ());
00301 }
00302
00303
00304 void CmtGenerator::terminate ()
00305 {
00306 fclose (m_output_file);
00307
00308
00309
00310 commit (m_output_file_name);
00311 }
00312
00313
00314 void CmtGenerator::fill_outputs ()
00315 {
00316 bool first = true;
00317
00318 m_OBJS = "";
00319
00320 for (int i = 0; i < m_source_files.size (); i++)
00321 {
00322 const SourceFile& file = m_source_files[i];
00323 const cmt_string output = file.output ();
00324
00325 if (output != "")
00326 {
00327 if (first)
00328 {
00329 first = false;
00330 }
00331 else
00332 {
00333 m_OBJS += " ";
00334 }
00335
00336 m_OBJS += output;
00337 }
00338
00339 if (Cmt::get_debug ())
00340 {
00341 cout << "CmtGenerator::fill_outputs> output=" << output << " OBJS=" << m_OBJS << endl;
00342 }
00343
00344 }
00345
00346 if (Cmt::get_debug ())
00347 {
00348 cout << "CmtGenerator::fill_outputs> OBJS=" << m_OBJS << endl;
00349 }
00350
00351 }
00352
00353
00354 void CmtGenerator::prepare_use_context ()
00355 {
00356 cmt_string path;
00357 cmt_string substitution;
00358
00359 Use* use = &Use::current ();
00360
00361 m_deps_builder.clear ();
00362
00363 if (use->include_path != "none")
00364 {
00365 if (use->include_path == "")
00366 {
00367 m_deps_builder.add (incdir, "$(src)");
00368 }
00369 else
00370 {
00371 substitution = use->include_path;
00372
00373 path = substitution;
00374 Symbol::expand (path);
00375
00376 CmtSystem::reduce_file_separators (path);
00377
00378 m_deps_builder.add (path, substitution);
00379 }
00380 }
00381
00382 m_deps_builder.add_includes (*use);
00383
00384 Use::UsePtrVector& uses = Use::get_ordered_uses ();
00385
00386 if (uses.size () > 0)
00387 {
00388 int number;
00389
00390 for (number = 0; number < uses.size (); number++)
00391 {
00392 use = uses[number];
00393 if (use->discarded) continue;
00394
00395 if (use->real_path != "")
00396 {
00397 if (use->include_path != "none")
00398 {
00399 if (use->include_path == "")
00400 {
00401 use->get_full_path (path);
00402 path += CmtSystem::file_separator ();
00403 path += "src";
00404
00405 substitution = "$(";
00406 substitution += use->prefix;
00407 substitution += "ROOT)";
00408 substitution += CmtSystem::file_separator ();
00409 substitution += "src";
00410 substitution += CmtSystem::file_separator ();
00411 }
00412 else
00413 {
00414 substitution = use->include_path;
00415
00416 path = substitution;
00417 Symbol::expand (path);
00418
00419 CmtSystem::reduce_file_separators (path);
00420 }
00421
00422 m_deps_builder.add (path, substitution);
00423 }
00424
00425 m_deps_builder.add_includes (*use);
00426 }
00427 }
00428 }
00429 }
00430
00431
00432 void CmtGenerator::filter_path (cmt_string& text)
00433 {
00434 CmtSystem::compress_path (text);
00435
00436 text.replace_all ("./../src/../", "../");
00437 text.replace_all ("./../src/", "$(src)");
00438
00439 text.replace_all (".\\..\\src\\..\\", "..\\");
00440 text.replace_all (".\\..\\src\\", "$(src)");
00441
00442 text.replace_all ("../src/../", "../");
00443 text.replace_all ("../src/", "$(src)");
00444
00445 text.replace_all ("..\\src\\..\\", "..\\");
00446 text.replace_all ("..\\src\\", "$(src)");
00447
00448 text.replace_all ("../doc/../", "../");
00449 text.replace_all ("../doc/", "$(doc)");
00450
00451 text.replace_all ("..\\doc\\..\\", "..\\");
00452 text.replace_all ("..\\doc\\", "$(doc)");
00453
00454 text.replace_all ("$(src)$(src)", "$(src)");
00455 }
00456
00466 int CmtGenerator::get_all_files (const cmt_string& full_name,
00467 const cmt_vector& exclude_exprs,
00468 const cmt_vector& select_exprs,
00469 CmtSystem::cmt_string_vector& files)
00470 {
00471 static cmt_string suffix;
00472 static cmt_string name;
00473
00474 bool has_excludes = false;
00475 bool has_selects = false;
00476
00477 suffix = "";
00478 name = "";
00479
00480 files.clear ();
00481
00482 has_excludes = (exclude_exprs.size () > 0);
00483 has_selects = (select_exprs.size () > 0);
00484
00485 CmtSystem::get_dot_suffix (full_name, suffix);
00486
00487 bool wilcarded_suffix = false;
00488
00489 if (suffix == ".*") wilcarded_suffix = true;
00490
00491 int count = 0;
00492
00493 if (full_name.find ('*') != cmt_string::npos)
00494 {
00495 CmtSystem::scan_dir (full_name, files);
00496
00497 if (Cmt::get_debug ())
00498 {
00499 cout << "CMT::get_all_files> full_name=" << full_name <<
00500 " pwd=" << CmtSystem::pwd () << endl;
00501 cout << "CMT::get_all_files> files.size=" << files.size () << endl;
00502 }
00503
00518 for (int j = 0; j < files.size (); j++)
00519 {
00520 cmt_string& n = files[j];
00521
00522 bool rejected = false;
00523
00524 if (n == "")
00525 {
00526 rejected = true;
00527 }
00528
00529 if (!rejected && has_selects)
00530 {
00531 rejected = true;
00532
00533 for (int k = 0; k < select_exprs.size (); k++)
00534 {
00535 const cmt_regexp& exp = select_exprs[k];
00536 if (exp.match (n))
00537 {
00538 rejected = false;
00539 break;
00540 }
00541 }
00542 }
00543
00544 if (!rejected && has_excludes)
00545 {
00546 for (int k = 0; k < exclude_exprs.size (); k++)
00547 {
00548 const cmt_regexp& exp = exclude_exprs[k];
00549 if (exp.match (n))
00550 {
00551 rejected = true;
00552 break;
00553 }
00554 }
00555 }
00556
00557 if (!rejected)
00558 {
00559 static cmt_string s;
00560
00561 CmtSystem::get_dot_suffix (n, s);
00562 if (!wilcarded_suffix && (s != suffix))
00563 {
00564 rejected = true;
00565 }
00566 else
00567 {
00568 count++;
00569 }
00570 }
00571
00572 if (Cmt::get_debug ())
00573 {
00574 if (rejected)
00575 {
00576 cout << "CMT::get_all_files> reject " << n << endl;
00577 }
00578 else
00579 {
00580 cout << "CMT::get_all_files> keep " << n << endl;
00581 }
00582 }
00583
00584 if (rejected)
00585 {
00586 n = "";
00587 }
00588 }
00589 }
00590 else
00591 {
00592 if (full_name != "")
00593 {
00594 bool rejected = false;
00595
00596 if (has_excludes)
00597 {
00598 for (int k = 0; k < exclude_exprs.size (); k++)
00599 {
00600 const cmt_regexp& exp = exclude_exprs[k];
00601 if (exp.match (full_name))
00602 {
00603 rejected = true;
00604 break;
00605 }
00606 }
00607 }
00608
00609 if (!rejected)
00610 {
00611 cmt_string& n = files.add ();
00612
00613 n = full_name;
00614
00615 count++;
00616 }
00617 }
00618 }
00619
00620 return (count);
00621 }
00622
00623
00624 void CmtGenerator::set_full_name (cmt_string& full_name, cmt_string& file)
00625 {
00626 full_name = "";
00627
00628 Symbol::expand (file);
00629
00630 if (file == "") return;
00631
00632 if (!CmtSystem::absolute_path (file))
00633 {
00634 full_name = srcdir;
00635 if (full_name != "") full_name += CmtSystem::file_separator ();
00636 }
00637
00638 full_name += file;
00639
00640 CmtSystem::reduce_file_separators (full_name);
00641 }
00642
00643
00644 static ApplicationGenerator ApplicationContext;
00645 static LibraryGenerator LibraryContext;
00646 static DocumentGenerator DocumentContext;
00647 static ReadmeGenerator ReadmeContext;
00648 static PrototypeGenerator PrototypeContext;
00649 static DefaultMakefileGenerator DefaultMakefileContext;
00650 static MSDEVGenerator MSDEVContext;
00651 static VSNETGenerator VSNETContext;
00652 static MakeSetupGenerator MakeSetupContext;
00653 static ConstituentsMakefileGenerator ConstituentsMakefileContext;
00654 static DependencyGenerator DependencyContext;
00655
00656
00657 int Generator::build_msdev_workspace (const Constituent::ConstituentVector& constituents)
00658 {
00659 return (MSDEVContext.build_workspace (constituents));
00660 }
00661
00662
00663 int Generator::build_msdev (const Constituent& constituent)
00664 {
00665 return (MSDEVContext.build_project (constituent));
00666 }
00667
00668
00669 int Generator::build_vsnet_workspace (const Constituent::ConstituentVector& constituents)
00670 {
00671 return (VSNETContext.build_workspace (constituents));
00672 }
00673
00674
00675 int Generator::build_vsnet (const Constituent& constituent)
00676 {
00677 return (VSNETContext.build_project (constituent));
00678 }
00679
00680
00681 void Generator::build_make_setup (const cmt_string& package)
00682 {
00683 MakeSetupContext.build (package);
00684 }
00685
00686
00687 void Generator::build_constituents_makefile (const cmt_string& package,
00688 const CmtSystem::cmt_string_vector& arguments)
00689 {
00690 ConstituentsMakefileContext.build (package, arguments);
00691 }
00692
00693
00694 int Generator::build_constituent_makefile (const Constituent& constituent)
00695 {
00696 const cmt_string& package = Cmt::get_current_package ();
00697
00698 switch (constituent.type)
00699 {
00700 case Application:
00701 ApplicationContext.build (package, constituent);
00702 break;
00703 case Library:
00704 LibraryContext.build (package, constituent);
00705 break;
00706 case Document:
00707 DocumentContext.build (package, constituent);
00708 break;
00709 }
00710
00711 return (0);
00712 }
00713
00714
00715 void Generator::build_constituent_makefile (const cmt_string& name)
00716 {
00717 const Constituent* constituent = Constituent::find (name);
00718 if (constituent != 0) build_constituent_makefile (*constituent);
00719 }
00720
00721
00722 void Generator::build_default_makefile ()
00723 {
00724 DefaultMakefileContext.build ();
00725 }
00726
00727
00728 void Generator::build_dependencies (const CmtSystem::cmt_string_vector& arguments)
00729 {
00730 DependencyContext.build (arguments);
00731 }
00732
00733
00734 void Generator::build_prototype (const cmt_string& file_name)
00735 {
00736 PrototypeContext.build (file_name);
00737 }
00738
00739
00740 void Generator::build_readme (const CmtSystem::cmt_string_vector& arguments)
00741 {
00742 ReadmeContext.build (arguments);
00743 }
00744
00745 class WinDefAwk : public PAwk
00746 {
00747 public :
00748 WinDefAwk (const cmt_string& library_name)
00749 {
00750 m_name = library_name;
00751 }
00752
00753 void begin ()
00754 {
00755 cout << "LIBRARY " << m_name << endl;
00756 cout << "EXPORTS" << endl;
00757 }
00758
00759 void filter (const cmt_string& line)
00760 {
00761 if (line.find ("External") == cmt_string::npos) return;
00762 if (line.find ("??_") != cmt_string::npos)
00763 {
00764 if (line.find ("operator/=") == cmt_string::npos) return;
00765
00766 }
00767
00768 CmtSystem::cmt_string_vector words;
00769 CmtSystem::split (line, " \t", words);
00770 if (words.size () >= 8)
00771 {
00772 int pos = 7;
00773
00774 cmt_string& fifth_word = words[4];
00775 if (fifth_word == "()") pos = 7;
00776 else if (fifth_word == "External") pos = 6;
00777 else return;
00778
00779 cmt_string& symbol = words[pos];
00780 if (symbol[0] == '_') symbol.erase (0, 1);
00781 symbol.replace_all ("\r", "");
00782 symbol.replace_all ("\n", "");
00783
00784 if ((pos == 6) && (line.find("static class") != cmt_string::npos))
00785 {
00786
00787 cout << " " << symbol << " " << endl;
00788 }
00789 else if (pos == 6)
00790 {
00791
00792 cout << " " << symbol << "\tDATA" << endl;
00793 }
00794 else
00795 {
00796
00797 cout << " " << symbol << " " << endl;
00798 }
00799 }
00800 }
00801
00802 void end ()
00803 {
00804 }
00805
00806 private:
00807 cmt_string m_name;
00808 };
00809
00810
00811 void Generator::build_windefs (const cmt_string& library_name)
00812 {
00813 cmt_string bin;
00814 cmt_string name;
00815 cmt_string suffix;
00816
00817 CmtSystem::dirname (library_name, bin);
00818 CmtSystem::get_dot_suffix (library_name, suffix);
00819 CmtSystem::basename (library_name, suffix, name);
00820
00821 if (!CmtSystem::cd (bin)) return;
00822
00823 cmt_string text;
00824 cmt_string command;
00825
00826 command = "dumpbin /symbols ";
00827 command += library_name;
00828
00829 WinDefAwk filter (name);
00830
00831 filter.run (command, "SECT");
00832 }
00833
00834
00835 void Packager::begin ()
00836 {
00837 m_package_name = "";
00838 }
00839
00840 void Packager::filter (const cmt_string& line)
00841 {
00842 CmtSystem::cmt_string_vector words;
00843
00844 CmtSystem::split (line, " ", words);
00845 if (words.size () > 1)
00846 {
00847 cmt_string& w = words[0];
00848
00849 if (w == "package")
00850 {
00851 m_package_name = words[1];
00852
00853 int pos = m_package_name.find (";");
00854 if (pos != cmt_string::npos) m_package_name.erase (pos);
00855 m_package_name.replace_all (".", CmtSystem::file_separator ());
00856 }
00857 }
00858 }
00859
00860 cmt_string& Packager::package_name ()
00861 {
00862 return (m_package_name);
00863 }
00864