one2all.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:33k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: one2all.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:42:05  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: one2all.cpp,v 1000.2 2004/06/01 19:42:05 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Anton Lavrentiev, Vladimir Ivanov
  35.  *
  36.  * File Description:
  37.  *    MSVC 6.0 project file converter. Expand a signle configuration project
  38.  *    file to multi-configuration project file.
  39.  *
  40.  */
  41. /*  !!! Warning !!!
  42.     Seems that PCRE has a bug (or may be this is a feature?).
  43.     It doesn't correct handle regular expressions with brackets "[]"
  44.     if a PCRE_MULTILINE / PCRE_DOTALL flag is specified
  45.     (may be and some other).
  46.     It is necessary to investigate and try a new PCRE version.
  47. */
  48. #include <ncbi_pch.hpp>
  49. #include <corelib/ncbiapp.hpp>
  50. #include <corelib/ncbienv.hpp>
  51. #include <corelib/ncbiargs.hpp>
  52. #include <corelib/ncbifile.hpp>
  53. #include <util/regexp.hpp>
  54. USING_NCBI_SCOPE;
  55. /// End-of-line symbol.
  56. const char* kEOL = "n";
  57. /// String to replace matched data in templates.
  58. const char* kTemplate = "@@@";
  59. /// Single/Multiline PCRE compilation flags.
  60. const CRegexp::TCompile kSL = PCRE_DOTALL + PCRE_UNGREEDY;
  61. const CRegexp::TCompile kML = PCRE_MULTILINE + PCRE_UNGREEDY;
  62. const CRegexp::TCompile kDF = 0;
  63. /////////////////////////////////////////////////////////////////////////////
  64. //  
  65. //  Configurations
  66. //
  67. /// Configurations.
  68. static const char* kConfigName[] = { "Release", "Debug"  };
  69. /// Suffixes. Empty suffix ("") should be last.
  70. static const char* kSuffixName[] = { "DLL", "MT",  ""    };  
  71. static const char* kSuffixLib[]  = { "/MD", "/MT", "/ML" };
  72. /////////////////////////////////////////////////////////////////////////////
  73. //
  74. //  Main application class
  75. //
  76. class CMainApplication : public CNcbiApplication
  77. {
  78. public:
  79.     /// Configuration enumerators.
  80.     /// Lesser value have more priority.
  81.     enum EConfig {
  82.         eRelease = 0,
  83.         eDebug,
  84.         eConfigMax
  85.     };
  86.     enum ESuffix {
  87.         eDLL = 0,
  88.         eMT,
  89.         eST,
  90.         eSuffixMax
  91.     };
  92.     /// Define a replacement command. 
  93.     struct SReplacement {
  94.         const char*  from;  ///< Change from value.
  95.         const char*  to;    ///< Change to value.
  96.         size_t       count; ///< Maximum count of changes (0 - infinite).
  97.     };
  98. public:
  99.     /// Constructor.
  100.     CMainApplication(void);
  101.     /// Overrided methods.
  102.     virtual void Init(void);
  103.     virtual int  Run (void);
  104. private:
  105.     /// Parse program arguments.
  106.     void ParseArguments(void);
  107.     /// Process all project files in the specified directory.
  108.     void ProcessDir(const string& dir_name);
  109.     /// Process one project file only.
  110.     void ProcessFile(const string& file_name);
  111.     /// Replace configuration settings accordingly required configuration.
  112.     /// Return name of the configuration with or without used GUI.
  113.     string Configure(
  114.         const string& cfg_template,
  115.         string&       cfg_str,
  116.         EConfig       config,
  117.         ESuffix       suffix
  118.     );
  119. private:
  120.     /// Parameters.
  121.     bool    m_Cfg[eConfigMax][eSuffixMax]; //< Configurations
  122.     string  m_Path;                        //< Directory or file name
  123.     bool    m_IsRecursive;                 //< Process m_Path recursively
  124.     bool    m_IsDistribution;              //< Distribution mode
  125.     bool    m_CreateBackup;                //< Create backup files
  126. };
  127. /// Iterators by possible configurations.
  128. #define ITERATE_CONFIG(i) 
  129.     for (int i = 0; i < CMainApplication::eConfigMax; i++)
  130. #define ITERATE_SUFFIX(i) 
  131.     for (int i = 0; i < CMainApplication::eSuffixMax; i++)
  132. /// Compose configuration name.
  133. #define CONFIG_NAME(config, suffix) 
  134.     ((string)kConfigName[config] + kSuffixName[suffix]);
  135. CMainApplication::CMainApplication(void)
  136.     : m_Path(kEmptyStr), m_IsRecursive(false), m_IsDistribution(false)
  137. {
  138.     memset(m_Cfg, 0, sizeof(m_Cfg));
  139. }
  140. void CMainApplication::Init(void)
  141. {
  142.     // Set error posting and tracing on maximum.
  143.     SetDiagTrace(eDT_Enable);
  144.     SetDiagPostFlag(eDPF_Default);
  145.     SetDiagPostLevel(eDiag_Info);
  146.     // Describe the expected command-line arguments.
  147.     auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
  148.     arg_desc->AddPositional
  149.         ("path",
  150.          "Directory or project file name to convert",
  151.          CArgDescriptions::eString);
  152.     arg_desc->AddOptionalPositional
  153.         ("config_type",
  154.          "Type of configuration to produce (default is "all")",
  155.          CArgDescriptions::eString);
  156.     arg_desc->SetConstraint
  157.         ("config_type", &(*new CArgAllow_Strings, "all", "release", "debug"));
  158.     arg_desc->AddOptionalPositional
  159.         ("config_spec",
  160.          "Set of build configurations (default is all)",
  161.          CArgDescriptions::eInteger);
  162.     arg_desc->SetConstraint
  163.         ("config_spec", new CArgAllow_Integers(2, 4));
  164.     arg_desc->AddFlag
  165.         ("r", "Process all project files in the <path> recursively " 
  166.          "(only if <path> is a directory)");
  167.     arg_desc->AddFlag
  168.         ("d", "Distributive mode;  remove include/library paths, " 
  169.          "which refers to DIZZY");
  170.     arg_desc->AddFlag
  171.         ("b", "Create backup file");
  172. /*
  173.     arg_desc->AddFlag
  174.         ("dll", "generate DLL configuration");
  175.     arg_desc->AddFlag
  176.         ("st", "generate single-threaded configuration");
  177.     arg_desc->AddFlag
  178.         ("mt", "generate multi-threaded configuration");
  179. */
  180.     // Specify USAGE context.
  181.     arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),
  182.        "Automatic multi config for Microsoft Visual C++ Project File V 6.0");
  183.     // Setup arg.descriptions for this application.
  184.     SetupArgDescriptions(arg_desc.release());
  185. }
  186. void CMainApplication::ParseArguments(void)
  187. {
  188.     CArgs args = GetArgs();
  189.     // Path
  190.     m_Path = args["path"].AsString();
  191.     // Flags
  192.     m_IsRecursive    = args["r"];
  193.     m_IsDistribution = args["d"];
  194.     m_CreateBackup   = args["b"];
  195.     // Configurations
  196.     string cfg = args["config_type"] ? args["config_type"].AsString() : "all";
  197.     bool cfg_enable[eConfigMax];
  198.     memset(cfg_enable, 0, sizeof(cfg_enable));
  199.     if (cfg == "all") {
  200.         cfg_enable[eRelease] = true;
  201.         cfg_enable[eDebug]   = true;
  202.     }
  203.     else if (cfg == "debug") {
  204.         cfg_enable[eDebug] = true;
  205.     }
  206.     else if (cfg == "release") {
  207.         cfg_enable[eRelease] = true;
  208.     }
  209.     // Special parameter
  210.     int spec = args["config_spec"] ? args["config_spec"].AsInteger() : 0;
  211.     ITERATE_CONFIG(i) {
  212.         if ( cfg_enable[i] ) {
  213.             switch ( spec ) {
  214.             case 2:
  215.                 // DLL
  216.                 m_Cfg[i][eDLL] = true;
  217.                 break;
  218.             case 3:
  219.                 // MT
  220.                 m_Cfg[i][eMT]  = true;
  221.                 break;
  222.             case 4:
  223.                 // DLL, ST
  224.                 m_Cfg[i][eDLL] = true;
  225.                 m_Cfg[i][eST]  = true;
  226.                 break;
  227.             default:
  228.                 // DLL, MT, ST
  229.                 m_Cfg[i][eDLL] = true;
  230.                 m_Cfg[i][eMT]  = true;
  231.                 m_Cfg[i][eST]  = true;
  232.             }
  233.         }
  234.     }
  235. }
  236. void CMainApplication::ProcessDir(const string& dir_name)
  237. {
  238.     CDir dir(dir_name);
  239.     CDir::TEntries contents = dir.GetEntries("*");
  240.     ITERATE(CDir::TEntries, i, contents) {
  241.         string name  = (*i)->GetName();
  242.         if ( name == "."  ||  name == ".."  ||  
  243.              name == string(1,CDir::GetPathSeparator()) ) {
  244.             continue;
  245.         }
  246.         string path = (*i)->GetPath();
  247.         if ( (*i)->IsFile()  &&  NStr::EndsWith(name, ".dsp") ) {
  248.             ProcessFile(path);
  249.         } 
  250.         else if ( (*i)->IsDir() ) {
  251.             if ( m_IsRecursive ) {
  252.                 ProcessDir(path);
  253.             }
  254.         }
  255.     }
  256. }
  257. void CMainApplication::ProcessFile(const string& file_name)
  258. {
  259.     try 
  260.     {
  261.         string content;  // File content
  262.         string str;      // Temporary string
  263.         // Read all file into memory.
  264.         CNcbiIfstream is(file_name.c_str(), IOS_BASE::in | IOS_BASE::binary);
  265.         if ( !is.is_open() ) {
  266.             throw (string)"cannot be opened";
  267.         }
  268.         while ( is ) {
  269.             char buf[16384];
  270.             is.read(buf, sizeof(buf));
  271.             size_t count = is.gcount();
  272.             if ( count ) {
  273.                 buf[count] = '';
  274.                 content.append(buf);
  275.             }
  276.         }
  277.         is.close();
  278.         // DOS-2-UNIX conversion.
  279.         // (shouldn't be here, but just in case for sanity).
  280.         content = NStr::Replace(content, "rn", kEOL);
  281.         content = NStr::Replace(content, "r",   kEOL);
  282.         CRegexpUtil re(content);
  283.         // Check signature.
  284.         if ( !re.Exists(
  285.             "^# Microsoft Developer Studio Project File - Name=.*n" 
  286.             "# Microsoft Developer Studio Generated Build File, " 
  287.             "Format Version 6.00n" 
  288.             "# \*\* DO NOT EDIT \*\*nn" 
  289.             "# TARGTYPE .*n",  kSL) ) {
  290.             throw (string)"doesn't look like MSVC++ 6.0 Project File";
  291.         }
  292.         // Check multiple configurations.
  293.         if ( re.Exists("n!IF .*n!ELSEIF .*n!ENDIF.*# Begin Target", kSL) ) {
  294.             throw (string)"contains more than one configuration";
  295.         }
  296.         // Check for per-config dependencies, warn if any and disable it.
  297.         if ( re.Exists("^# PROP +AllowPerConfigDependencies +1", kML) ) {
  298.             if ( re.Exists("n# Begin Target.*n!IF ", kSL) ) {
  299.                 ERR_POST(Warning <<
  300.                          "File contains per-configuration dependencies,n" 
  301.                          "which may or may not be handled correctly by "   
  302.                          "this program.");
  303.             }
  304.         }
  305.         re.Replace("^(# PROP +AllowPerConfigDependencies +)1", "{$1}0", kML);
  306.         // Extract beginning of the file.
  307.         // Get template to summarize configurations in the header.
  308.         str = re.Extract("^.*n!MESSAGE *nn", kSL);
  309.         CRegexpUtil re_header(str);
  310.         str = re.Extract("^!MESSAGE +".*".*$", kML);
  311.         CRegexpUtil re_header_cfg_template(str);
  312.         re_header_cfg_template.Replace("(!MESSAGE +".* - \w+ ).*(".*)$",
  313.                                        string("$1") + kTemplate + "$2", kSL);
  314.         string cfg_name = re_header_cfg_template.Extract("".* - .*"", kML);
  315.         // Extract middle part.
  316.         string middle = 
  317.             re.Extract("n(# Begin Project.*)n*(!IF|# PROP BASE) +",
  318.                        kSL, kDF, 1)
  319.             + kEOL + kEOL;
  320.         // Extract configuration-dependent part. Make template from it.
  321.         str = re.Extract("n(!IF .*n!E.*)n.*# Begin Target", kSL, kDF, 1);
  322.         CRegexpUtil re_cfg_template(str);
  323.         if ( str.empty() ) {
  324.             // Extract a configuration-dependent part.
  325.             str = re.Extract("n(# PROP BASE .*n)# Begin Target", kSL, kDF,1);
  326.             // Get all together.
  327.             str = "!IF  "$(CFG)" == " + cfg_name + "nn" + str +"n!ENDIF ";
  328.             re_cfg_template.Reset(str);
  329.         } else {
  330.             re_cfg_template.Replace("^!ELSEIF .*$", "!ENDIF", kML);
  331.             re_cfg_template.Replace("^(!IF .*".* - \w+ ).*(".*)$",
  332.                                     string("$1") + kTemplate + "$2", kML);
  333.         }
  334.         ITERATE_CONFIG(i) {
  335.             ITERATE_SUFFIX(j) {
  336.                 string cfg = CONFIG_NAME(i,j);
  337.                 re_cfg_template.SetRange("^# PROP ");
  338.                 re_cfg_template.ReplaceRange(cfg, kTemplate, kDF, kDF,
  339.                                              CRegexpUtil::eOutside);
  340.                 re_cfg_template.SetRange("^# PROP .*"[^ ]*" + cfg +
  341.                                          "[^ ]*"");
  342.                 re_cfg_template.ReplaceRange(cfg, kTemplate, kDF, kDF,
  343.                                              CRegexpUtil::eInside);
  344.             }
  345.         }
  346.         // Extract tail of the file.
  347.         string tail;
  348.         size_t pos = content.find("n# Begin Target");
  349.         if (pos != NPOS) {
  350.             tail = content.substr(pos);
  351.             size_t src_start = 0;
  352.             size_t src_end   = 0;
  353.             // Process all custom builds.
  354.             for (;;) {
  355.                 // Find each source file description.
  356.                 src_start = tail.find("n# Begin Source File", src_end);
  357.                 if (src_start == NPOS) {
  358.                     break;
  359.                 }
  360.                 src_end = tail.find("n# End Source File", src_start);
  361.                 str = tail.substr(src_start, src_end - src_start);
  362.                 // Check for custom build.
  363.                 CRegexpUtil re_cb(str);
  364.                 re_cb.Replace("n!ELSEIF .*n!ENDIF", "n!ENDIF", kSL);
  365.                 string str_cb_template = 
  366.                     re_cb.Extract("!IF .*n# Begin Custom Build.*n!ENDIF",
  367.                                   kSL);
  368.                 if ( str_cb_template.empty() ) {
  369.                     str_cb_template = re_cb.Extract("nSOURCE=.*n(.*# Begin Custom Build.*)$", kSL, kDF, 1);
  370.                     if ( !str_cb_template.empty() ) {
  371.                         str_cb_template = "!IF  "$(CFG)" == " +
  372.                             cfg_name + "nn" + str_cb_template + "nn!ENDIF";
  373.                         re_cb.Replace("(nSOURCE=.*n).*$", "$1n@CB", kSL);
  374.                     }
  375.                 } else {
  376.                     re_cb.Replace("(.*n)!IF .*n!ENDIF(.*)$", "$1@CB$2", kSL);
  377.                 }
  378.                 // Is custom build block found?
  379.                 if ( !str_cb_template.empty() ) {
  380.                     // Replace config name wherever appropriate.
  381.                     ITERATE_CONFIG(i) {
  382.                         ITERATE_SUFFIX(j) {
  383.                             string cfg = CONFIG_NAME(i,j);
  384.                             str_cb_template = NStr::Replace(str_cb_template,
  385.                                                             cfg, kTemplate);
  386.                         }
  387.                     }
  388.                     // Accumulate parts to replace. 
  389.                     string cb;
  390.                     ITERATE_CONFIG(i) {
  391.                         ITERATE_SUFFIX(j) {
  392.                             // Is configuration [i,j] enabled?
  393.                             if ( m_Cfg[i][j] ) {
  394.                                 string cfg = CONFIG_NAME(i,j);
  395.                                 cb += NStr::Replace(str_cb_template,
  396.                                                     kTemplate, cfg);
  397.                             }
  398.                         }
  399.                     }
  400.                     // Replace ENDIF..IF with ELSEIF.
  401.                     cb = NStr::Replace(cb, "!ENDIF!IF", "!ELSEIF") + kEOL;
  402.                     // Put custom build back.
  403.                     re_cb.Replace("@CB", cb, kSL);
  404.                     tail.replace(src_start, src_end - src_start, re_cb);
  405.                     pos += re_cb.GetResult().length();
  406.                 }
  407.             }
  408.         }
  409.         CRegexpUtil re_tail(tail);
  410.         // Get template to summarize configurations in the tail.
  411.         str = re_tail.Extract("^# +Name +".*"", kML);
  412.         CRegexpUtil re_tail_cfg_template(str);
  413.         re_tail_cfg_template.Replace("(.*".* - \w+ ).*(".*)$",
  414.                                      string("$1") + kTemplate + "$2", kSL);
  415.         // Make required replacements and configs.
  416.         int    default_found = false;
  417.         string cfg_header;
  418.         string cfg_tail;
  419.         string eol = "";
  420.         string cfgs;
  421.         ITERATE_CONFIG(i) {
  422.             ITERATE_SUFFIX(j) {
  423.                 // Is configuration $i$j enabled?
  424.                 if ( m_Cfg[i][j] ) {
  425.                     string cfg = CONFIG_NAME(i,j);
  426.                     // Accumulate configurations to replace. 
  427.                     cfg_header += eol + NStr::Replace(re_header_cfg_template,
  428.                                                       kTemplate, cfg);
  429.                     cfg_tail   += eol + NStr::Replace(re_tail_cfg_template,
  430.                                                       kTemplate, cfg);
  431.                     // Is a first configuration (namely default) ?
  432.                     // It must be a configuration with maximum priority.
  433.                     if ( !default_found ) {
  434.                         // Replace all conf. names in the header with
  435.                         // the name of default configuration.
  436.                         re_header.Replace("(CFG=["]*.* - \w+ ).*("|n)",
  437.                                           "$1" + cfg + "$2", kSL);
  438.                         default_found = true;
  439.                         eol = kEOL;
  440.                     }
  441.                     // Configure $i$j.
  442.                     cfgs += Configure(re_cfg_template, str,
  443.                                       EConfig(i), ESuffix(j)) + " ";
  444.                     middle += str;
  445.                 }
  446.             }
  447.         }
  448.         // Replace ENDIF..IF with ELSEIF.
  449.         CRegexpUtil re_middle(middle);
  450.         re_middle.Replace("!ENDIF\s*!IF", "!ELSEIF", kSL);
  451.         // Summarize configurations in the header and
  452.         // tail parts of the project.
  453.         re_header.Replace("^!MESSAGE +".*".*$", cfg_header, kML);
  454.         re_tail.Replace  ("^# Name +".*".*$",   cfg_tail,   kML);
  455.         // Glue all parts together and make UNIX-2-DOS conversion.
  456.         str = (string)re_header + (string)re_middle + kEOL + (string)re_tail;
  457.         str = NStr::Replace(str, kEOL, "rn");
  458.         // Write content into new file and than rename it.
  459.         string file_name_new = file_name + ".new";
  460.         CNcbiOfstream os(file_name_new.c_str(),
  461.                          IOS_BASE::out | IOS_BASE::binary);
  462.         if ( !os.is_open() ) {
  463.             throw (string)"cannot create output file " + file_name_new;
  464.         }
  465.         os << str;
  466.         os.flush();
  467.         if ( !os ) {
  468.             throw (string)"cannot write to file " + file_name_new;
  469.         }
  470.         os.close();
  471.         // Print names of created configurations
  472.         LOG_POST(file_name << ":  " << cfgs);
  473.         // Replace original project file (backup kept in .bak).
  474.         CTime ftime;
  475.         CFile(file_name).GetTime(&ftime);
  476.         if ( m_CreateBackup ) {
  477.             string file_backup =  file_name + ".bak";
  478.             CFile(file_backup).Remove();
  479.             CFile(file_name).Rename(file_backup);
  480.         } else {
  481.             CFile(file_name).Remove();
  482.         }
  483.         if ( !CFile(file_name_new).Rename(file_name) ) {
  484.             throw (string)"cannot rename file";
  485.         }
  486.         CFile(file_name).SetTime(&ftime, &ftime);
  487.     }
  488.     catch (string& e) {
  489.         ERR_POST(file_name << ": " << e << ".");
  490.     }
  491.     catch (CException& e) {
  492.         NCBI_REPORT_EXCEPTION(file_name + ": ", e);
  493.     }
  494.     catch (...) {
  495.         ERR_POST(file_name << ": unknown error");
  496.     }
  497. }
  498. string CMainApplication::Configure(const string& cfg_template,
  499.                                    string& cfg_str,
  500.                                    EConfig config, ESuffix suffix)
  501. {
  502.     // Configuration name.
  503.     string cfg = CONFIG_NAME(config, suffix);
  504.     // Replace templated chunks with configuration name.
  505.     cfg_str = NStr::Replace(cfg_template, kTemplate, cfg);
  506.     // Replace debugging macro.
  507.     if (config == eDebug) {
  508.         cfg_str = NStr::Replace(cfg_str, "NDEBUG", "_DEBUG");
  509.     } else {
  510.         cfg_str = NStr::Replace(cfg_str, "_DEBUG", "NDEBUG");
  511.     }
  512.     // Check used GUI.
  513.     
  514.     CRegexpUtil re(cfg_str);
  515.     string gui;
  516.     string wxdll;
  517.     bool   wxdll_making = false;
  518.     if (re.Exists("^# ADD .*CPP .*__WX(DEBUG|MSW)__", kML)  ||
  519.         re.Exists("^# ADD .*CPP .*WX.{2,3}INGDLL", kML)) {
  520.         // The project use wxWindows (or is a part of wxWindows).
  521.         gui = "wxwin";
  522.         // Flag proper macros for DLL mode.
  523.         if ( suffix == eDLL ) {
  524.             if ( re.Exists("^# ADD .*CPP .*/D *["]{0,1}WXMAKINGDLL=*[0-9]*["]{0,1}", kML) ) {
  525.                 wxdll = "/D "WXMAKINGDLL=1"";
  526.                 wxdll_making = true;
  527.             } else {
  528.                 wxdll = "/D "WXUSINGDLL=1"";
  529.             }
  530.         }
  531.         // Remove some wxWindows macros, which are surely
  532.         // configuration-dependent.
  533.         re.SetRange("^# ADD .*CPP ");
  534.         re.ReplaceRange("  */D  *["]{0,1}__WXDEBUG__=*[0-9]*["]{0,1}",
  535.                         kEmptyStr);
  536.         re.ReplaceRange("  */D  *["]{0,1}WX.{2,3}INGDLL=*[0-9]*["]{0,1}",
  537.                         kEmptyStr);
  538.     } else if (re.Exists("^# ADD .*LINK32 .*fltk[a-z]*[.]lib", kML)) {
  539.         // The project is a FLTK-dependent project.
  540.         gui = "fltk";
  541.     }
  542.     // Either replace with hooks, or just remove the compiler switches,
  543.     // which may be configuration-dependent or inconsistent.
  544.     const SReplacement ksOpt[] = {
  545.         { "/Gm"           , ""   , 0 },
  546.         { "/GZ"           , ""   , 0 },
  547.         { "/G[0-9]"       , ""   , 0 },
  548.         { "/FR"           , ""   , 0 },
  549.         { "/Fr"           , ""   , 0 },
  550.         { "/c"            , " @c", 0 },
  551.         { "/ZI"           , " @Z", 0 },
  552.         { "/Zi"           , " @Z", 0 },
  553.         { "/Z7"           , " @Z", 0 },
  554.         { "/O[0-9A-Za-z]*", " @O", 0 },
  555.         { "/D +"{0,1}DEBUG=*[0-9]*"{0,1}", " @D", 0 }
  556.     };
  557.     re.SetRange("^# ADD .*CPP ");
  558.     for (size_t i = 0; i < sizeof(ksOpt)/sizeof(ksOpt[0]); i++) {
  559.         re.ReplaceRange(string(" +") + ksOpt[i].from, ksOpt[i].to,
  560.                         kDF, kDF, CRegexpUtil::eInside, (int)ksOpt[i].count);
  561.     }
  562.     // Configuration-dependent changes: replace hooks and more compiler
  563.     // options where appropriate.
  564.     const SReplacement ksOptDebug[] = {
  565.         { "@c"       , " /GZ /c"         , 0 },
  566.         { "@O"       , " /Od"            , 1 },
  567.         { "@Z"       , " /Z7"            , 1 },
  568.         { "@D"       , " /D "DEBUG=1"" , 1 },
  569.         { "(/W[^ ]*)", " $1 /Gm"         , 1 },
  570.         { "@O"       , ""                , 0 },
  571.         { "@Z"       , ""                , 0 },
  572.         { "@D"       , ""                , 0 }
  573.     };
  574.     const SReplacement ksOptRelease[] = {
  575.         { "@c"       , " /c"             , 0 },
  576.         { "@O"       , " /O2"            , 1 },
  577.         { "@O"       , ""                , 0 },
  578.         { "@Z"       , ""                , 0 },
  579.         { "@D"       , ""                , 0 }
  580.     };
  581.   
  582.     const SReplacement* subst;
  583.     size_t              subst_size;
  584.     if (config == eDebug) {
  585.         re.SetRange("^# PROP ");
  586.         re.ReplaceRange("  *Use_Debug_Libraries  *0"," Use_Debug_Libraries 1");
  587.         re.SetRange("^# ADD .*LINK32 ");
  588.         re.ReplaceRange("  */pdb:[^ ]*", kEmptyStr);
  589.         re.ReplaceRange("/mach", "/pdb:none /debug /mach");
  590.         subst = &ksOptDebug[0];
  591.         subst_size = sizeof(ksOptDebug)/sizeof(subst[0]);
  592.     } else {
  593.         re.SetRange("^# PROP ");
  594.         re.ReplaceRange("  *Use_Debug_Libraries  *1"," Use_Debug_Libraries 0");
  595.         re.SetRange("^# ADD .*LINK32 ");
  596.         re.ReplaceRange("  */pdbtype[^ ]*", kEmptyStr);
  597.         subst = &ksOptRelease[0];
  598.         subst_size = sizeof(ksOptRelease)/sizeof(subst[0]);
  599.     }
  600.     re.SetRange("^# ADD .*CPP ");
  601.     for (int i = 0; i < subst_size; i++) {
  602.         re.ReplaceRange(string(" +") + subst[i].from, subst[i].to, 
  603.                         kDF, kDF, CRegexpUtil::eInside, subst[i].count);
  604.     }
  605.     re.Replace("^(# ADD .*LINK32.*) */debug(.*)", "$1$2", kML);
  606.     // Now replace the code generation switch.
  607.     re.SetRange("^# ADD .*CPP ");
  608.     ITERATE_SUFFIX(i) {
  609.         re.ReplaceRange(string(" +") + kSuffixLib[i] + "[d]{0,1}", " @C");
  610.     }
  611.     string lib_switch = kSuffixLib[suffix];
  612.     if (config == eDebug) {
  613.         lib_switch += "d";
  614.     }
  615.     string ksLib[][2] = {
  616.         { "@C"      , lib_switch              },
  617.         { "/nologo" , "/nologo " + lib_switch },
  618.         { " CPP"    , " CPP" + lib_switch     }
  619.     };
  620.     re.SetRange("^# ADD +CPP ");
  621.     for (size_t i = 0; i < sizeof(ksLib)/sizeof(ksLib[0]); i++) {
  622.         if ( re.ReplaceRange(ksLib[i][0], ksLib[i][1], 
  623.                              kDF, kDF, CRegexpUtil::eInside, 1) ) {
  624.             break;
  625.         }
  626.     }
  627.     re.SetRange("^# ADD +BASE +CPP ");
  628.     for (size_t i = 0; i < sizeof(ksLib)/sizeof(ksLib[0]); i++) {
  629.         if ( re.ReplaceRange(ksLib[i][0], ksLib[i][1],
  630.                              kDF, kDF, CRegexpUtil::eInside, 1) ) {
  631.             break;
  632.         }
  633.     }
  634.     re.Replace("^(# ADD .*CPP +.*) *@C(.*)", "$1$2", kML);
  635.     re.Replace("^(# ADD .*LINK32 +.*) */incremental:(yes|no)(.*)", "$1$3",kML);
  636.     // Make sure that incremental linking is on
  637.     // except for wxWindows DLLs in the release mode (very slow).
  638.     string incr_link;
  639.     if ( !re.Exists("^# ADD .*LINK32 .*/dll", kML) ) {
  640.         incr_link = (config == eDebug) ? "yes" : "no";
  641.     } else if ( !gui.empty()  &&  config == eRelease  &&  wxdll_making ) {
  642.         incr_link = "no";
  643.     }
  644.     if ( !incr_link.empty() ) {
  645.         re.Replace("^(# ADD .*LINK32 .*/nologo)(.*)",
  646.                    string("$1 /incremental:") + incr_link + "$2", kML);
  647.     }
  648.     // When requested, remove include/library paths, which refer to DIZZY.
  649.     if ( m_IsDistribution ) {
  650.         re.SetRange("^# ADD .*(CPP|RSC) ");
  651.         re.ReplaceRange(" +/[Ii] +["]{0,1}\\\\[Dd][Ii][Zz][Zz][Yy]\\[^ ]*",
  652.                         kEmptyStr);
  653.         re.SetRange("^# ADD .*LINK32 ");
  654.         re.ReplaceRange(" +/libpath:["]{0,1}\\\\[Dd][Ii][Zz][Zz][Yy]\\[^ ]*",
  655.                         kEmptyStr);
  656.     }
  657.     // wxWindows-specific changes from now on.
  658.     if ( gui == "wxwin" ) {
  659.         // # Define __WXDEBUG__ for debug configs.
  660.         string wxdebug; 
  661.         if ( config == eDebug ) {
  662.             wxdebug = "/D "__WXDEBUG__=1"";
  663.         }
  664.         // wxWindows defines is to be added to compiler options.
  665.         if ( !wxdebug.empty()  ||  !wxdll.empty() ) {
  666.             string wx = NStr::TruncateSpaces(wxdebug + " " + wxdll);
  667.             string ksWx[][2] = {
  668.                 { "/Y" , wx + " /Y" },
  669.                 { "/D" , wx + " /D" },
  670.                 { "/c" , wx + " /Y" },
  671.                 { " *$", "$0 "+ wx  }
  672.             };
  673.             // Insert it once in each line
  674.             re.SetRange("^# ADD +CPP ");
  675.             for (size_t i = 0; i < sizeof(ksWx)/sizeof(ksWx[0]); i++) {
  676.                 if ( re.ReplaceRange(ksWx[i][0], ksWx[i][1],
  677.                                      kDF, kDF, CRegexpUtil::eInside, 1) ) {
  678.                     break;
  679.                 }
  680.             }
  681.             re.SetRange("^# ADD +BASE +CPP ");
  682.             for (size_t i = 0; i < sizeof(ksWx)/sizeof(ksWx[0]); i++) {
  683.                 if ( re.ReplaceRange(ksWx[i][0], ksWx[i][1],
  684.                                      kDF, kDF, CRegexpUtil::eInside, 1) ) {
  685.                     break;
  686.                 }
  687.             }
  688.         }
  689.         // Enforce /subsystem:windows.
  690.         re.SetRange("^# ADD .*LINK32 ");
  691.         re.ReplaceRange("/subsystem:[A-Za-z]*", "@s");
  692.         string ksWxss[][2] = {
  693.             { "@s"     , ""         },
  694.             { "/nologo", "/nologo " },
  695.             { " *$"    , "$0 "      }
  696.         };
  697.         re.SetRange("^# ADD +LINK32 ");
  698.         for (size_t i = 0; i < sizeof(ksWxss)/sizeof(ksWxss[0]); i++) {
  699.             if ( re.ReplaceRange(ksWxss[i][0],
  700.                                  ksWxss[i][1] + "/subsystem:windows",
  701.                                  kDF, kDF, CRegexpUtil::eInside, 1) ) {
  702.                 break;
  703.             }
  704.         }
  705.         re.SetRange("^# ADD .*LINK32 ");
  706.         re.ReplaceRange(" *@s", kEmptyStr);
  707.         // Take care of libraries: remove all wxWindows ones.
  708.         string ksWxLib[][2] = {
  709.             { "jpegd{0,1}[.]lib" , ""     },
  710.             { "pngd{0,1}[.]lib"  , ""     },
  711.             { "tiffd{0,1}[.]lib" , ""     },
  712.             { "zpmd{0,1}[.]lib"  , ""     },
  713.             { "zlibd{0,1}[.]lib" , ""     },
  714.             { "wx[dl]{0,1}[.]lib", " @wx" }
  715.         };
  716.         re.SetRange("^# ADD .*LINK32 .*wx[dl]{0,1}[.]lib");
  717.         for (size_t i = 0; i < sizeof(ksWxLib)/sizeof(ksWxLib[0]); i++) {
  718.             re.ReplaceRange("  *" + ksWxLib[i][0], ksWxLib[i][1]);
  719.         }
  720.         // Insert them back but with correct names (which we use).
  721.         // Note that in DLL mode only one (import) library has to be included.
  722.         // The note above was true formely; now images libs are all static.
  723.         re.SetRange("^# ADD .*LINK32 .*@wx ");
  724.         re.ReplaceRange("@wx", "jpeg.lib png.lib tiff.lib zlib.lib wx.lib",
  725.                          kDF, kDF, CRegexpUtil::eInside, 1); 
  726.         re.ReplaceRange("@wx", kEmptyStr);
  727.     }
  728.     // FLTK specific changes from now on
  729.     if ( gui == "fltk" ) {
  730.         // Enforce /subsystem:windows.
  731.         re.SetRange("^# ADD .*LINK32 ");
  732.         re.ReplaceRange("/subsystem:[A-Za-z]*", "@s");
  733.         string ksWxss[][2] = {
  734.             { "@s"     , ""         },
  735.             { "/nologo", "/nologo " },
  736.             { " *$"    , "$0 "      }
  737.         };
  738.         re.SetRange("^# ADD LINK32 ");
  739.         for (size_t i = 0; i < sizeof(ksWxss)/sizeof(ksWxss[0]); i++) {
  740.             if ( re.ReplaceRange(ksWxss[i][0],
  741.                                  ksWxss[i][1] + "/subsystem:windows", 
  742.                                  kDF, kDF, CRegexpUtil::eInside, 1) ) {
  743.                 break;
  744.             }
  745.         }
  746.         re.SetRange("^# ADD .*LINK32 ");
  747.         re.ReplaceRange(" *@s", kEmptyStr);
  748.         // Take care of libraries: remove all FLTK ones
  749.         re.SetRange("^# ADD .*LINK32 * fltk[a-z]*[.]lib");
  750.         re.ReplaceRange("  *fltk[a-z]*[.]lib", " @fltk");
  751.         // Insert them back but with correct names (which we use).
  752.         // Note that in DLL mode only one (import) library has to be included.
  753.         string lib = "fltkdll.lib";
  754.         if ( suffix != eDLL ) {
  755.             lib = "fltkforms.lib fltkimages.lib fltkgl.lib " + lib;
  756.         }
  757.         re.SetRange("^# ADD .*LINK32 .*@fltk");
  758.         re.ReplaceRange("@fltk", "fltkdll.lib", kDF, kDF,
  759.                         CRegexpUtil::eInside, 1); 
  760.         re.ReplaceRange("@fltk", kEmptyStr);
  761.     }
  762.     // Get result;
  763.     cfg_str = re;
  764.     // Return name of configuration, which is created.
  765.    
  766.     if ( !gui.empty() ) {
  767.         cfg += " (" + gui + ")";
  768.     }
  769.     return cfg;
  770. }
  771.  
  772. int CMainApplication::Run(void)
  773. {
  774.     // Get and check arguments
  775.     ParseArguments();
  776.     // Run conversion
  777.     CDirEntry entry(m_Path);
  778.     if ( entry.IsFile() ) {
  779.         ProcessFile(m_Path);
  780.     }
  781.     else if ( entry.IsDir() ) {
  782.         LOG_POST("Begin converting directory "" << m_Path << "".");
  783.         ProcessDir(m_Path);
  784.     }
  785.     else {
  786.         ERR_POST(Fatal << "Path "" + m_Path + "" must exist.");
  787.     }
  788.     LOG_POST("Finished.");
  789.     return 0;
  790. }
  791.   
  792. /////////////////////////////////////////////////////////////////////////////
  793. //
  794. //  Main
  795. //
  796. static CMainApplication theApp;
  797. int main(int argc, const char* argv[])
  798. {
  799.     // Execute main application function
  800.     return theApp.AppMain(argc, argv, 0, eDS_Default, 0);
  801. }
  802. /*
  803.  * ===========================================================================
  804.  * $Log: one2all.cpp,v $
  805.  * Revision 1000.2  2004/06/01 19:42:05  gouriano
  806.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  807.  *
  808.  * Revision 1.10  2004/05/17 21:08:36  gorelenk
  809.  * Added include of PCH ncbi_pch.hpp
  810.  *
  811.  * Revision 1.9  2003/12/02 18:01:19  ivanov
  812.  * Fixed message for the previous commit
  813.  *
  814.  * Revision 1.8  2003/12/02 17:59:13  ivanov
  815.  * Remove ,bak file only if new one is created
  816.  *
  817.  * Revision 1.7  2003/11/28 16:53:23  ivanov
  818.  * Keep modification time for conveted file
  819.  *
  820.  * Revision 1.6  2003/11/10 17:29:05  ivanov
  821.  * Added option "-b" -- create backup files for projects (by default is off).
  822.  * wxWindows: make sure that incremental linking is on except for DLLs
  823.  * in the release mode (very slow).
  824.  *
  825.  * Revision 1.5  2003/11/10 14:59:51  ivanov
  826.  * Fixed array size determination after previous fix.
  827.  * Use caseless check for include/library paths, which refer to DIZZY.
  828.  *
  829.  * Revision 1.4  2003/11/07 17:14:56  ivanov
  830.  * Use array of SReplacement instead of two-dim arrays
  831.  *
  832.  * Revision 1.3  2003/11/07 13:42:27  ivanov
  833.  * Fixed lines wrapped at 79th columns. Get rid of compilation warnings on UNIX.
  834.  *
  835.  * Revision 1.2  2003/11/06 17:08:32  ivanov
  836.  * Remove ".bak" file before renaming
  837.  *
  838.  * Revision 1.1  2003/11/06 16:17:58  ivanov
  839.  * Initial revision. Based on one2all.sh script.
  840.  *
  841.  * ===========================================================================
  842.  */