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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: filecode.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:43:05  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: filecode.cpp,v 1000.1 2004/06/01 19:43: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. * Author: Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   File generator
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <corelib/ncbifile.hpp>
  42. #include <serial/datatool/exceptions.hpp>
  43. #include <serial/datatool/generate.hpp>
  44. #include <serial/datatool/filecode.hpp>
  45. #include <serial/datatool/type.hpp>
  46. #include <serial/datatool/typestr.hpp>
  47. #include <serial/datatool/fileutil.hpp>
  48. #include <serial/datatool/namespace.hpp>
  49. #include <serial/datatool/module.hpp>
  50. #include <serial/datatool/code.hpp>
  51. #include <util/checksum.hpp>
  52. #include <typeinfo>
  53. BEGIN_NCBI_SCOPE
  54. string CFileCode::m_PchHeader;
  55. CFileCode::CFileCode(const CCodeGenerator* codeGenerator,
  56.                      const string& baseName)
  57.     : m_CodeGenerator(codeGenerator),m_BaseName(baseName)
  58. {
  59.     m_UseQuotedForm = false;
  60.     return;
  61. }
  62. CFileCode::~CFileCode(void)
  63. {
  64.     return;
  65. }
  66. const string& CFileCode::ChangeFileBaseName(void)
  67. {
  68.     m_BaseName += "x";
  69.     return GetFileBaseName();
  70. }
  71. string CFileCode::GetBaseFileBaseName(void) const
  72. {
  73.     _ASSERT(BaseName(GetFileBaseName()).size() + 5 <= MAX_FILE_NAME_LENGTH);
  74.     return GetFileBaseName() + "_";
  75. }
  76. string CFileCode::GetUserFileBaseName(void) const
  77. {
  78.     return GetFileBaseName();
  79. }
  80. string CFileCode::GetBaseHPPName(void) const
  81. {
  82.     return GetBaseFileBaseName() + ".hpp";
  83. }
  84. string CFileCode::GetUserHPPName(void) const
  85. {
  86.     return GetUserFileBaseName() + ".hpp";
  87. }
  88. string CFileCode::GetBaseCPPName(void) const
  89. {
  90.     return GetBaseFileBaseName() + ".cpp";
  91. }
  92. string CFileCode::GetUserCPPName(void) const
  93. {
  94.     return GetUserFileBaseName() + ".cpp";
  95. }
  96. string CFileCode::GetDefineBase(void) const
  97. {
  98.     string s;
  99.     ITERATE ( string, i, GetFileBaseName() ) {
  100.         char c = *i;
  101.         if ( c >= 'a' && c <= 'z' )
  102.             c = c + ('A' - 'a');
  103.         else if ( (c < 'A' || c > 'Z') &&
  104.                   (c < '0' || c > '9') )
  105.             c = '_';
  106.         s += c;
  107.     }
  108.     return s;
  109. }
  110. string CFileCode::GetBaseHPPDefine(void) const
  111. {
  112.     return GetDefineBase() + "_BASE_HPP";
  113. }
  114. string CFileCode::GetUserHPPDefine(void) const
  115. {
  116.     return GetDefineBase() + "_HPP";
  117. }
  118. string CFileCode::Include(const string& s, bool addExt) const
  119. {
  120.     if ( s.empty() ) {
  121.         NCBI_THROW(CDatatoolException,eInvalidData,"Empty file name");
  122.     }
  123.     switch ( s[0] ) {
  124.     case '<':
  125.     case '"':
  126.         return s[0] + GetStdPath(s.substr(1, s.length()-2)) + s[s.length()-1];
  127.     default:
  128.     {
  129.         string result(1, m_UseQuotedForm ? '"' : '<');
  130.         result += GetStdPath(addExt ? (s + ".hpp") : s);
  131.         result += m_UseQuotedForm ? '"' : '>';
  132.         return result;
  133.     }
  134.     }
  135. }
  136. string CFileCode::GetMethodPrefix(void) const
  137. {
  138.     return kEmptyStr;
  139. }
  140. CFileCode::TIncludes& CFileCode::HPPIncludes(void)
  141. {
  142.     return m_HPPIncludes;
  143. }
  144. CFileCode::TIncludes& CFileCode::CPPIncludes(void)
  145. {
  146.     return m_CPPIncludes;
  147. }
  148. void CFileCode::AddForwardDeclaration(const string& cls, const CNamespace& ns)
  149. {
  150.     m_ForwardDeclarations[cls] = ns;
  151. }
  152. const CNamespace& CFileCode::GetNamespace(void) const
  153. {
  154.     _ASSERT(m_CurrentClass != 0);
  155.     return m_CurrentClass->ns;
  156. }
  157. void CFileCode::AddHPPCode(const CNcbiOstrstream& code)
  158. {
  159.     m_CurrentClass->hppCode =
  160.         CNcbiOstrstreamToString(const_cast<CNcbiOstrstream&>(code));
  161. }
  162. void CFileCode::AddINLCode(const CNcbiOstrstream& code)
  163. {
  164.     m_CurrentClass->inlCode = 
  165.         CNcbiOstrstreamToString(const_cast<CNcbiOstrstream&>(code));
  166. }
  167. void CFileCode::AddCPPCode(const CNcbiOstrstream& code)
  168. {
  169.     m_CurrentClass->cppCode = 
  170.         CNcbiOstrstreamToString(const_cast<CNcbiOstrstream&>(code));
  171. }
  172. void CFileCode::UseQuotedForm(bool use)
  173. {
  174.     m_UseQuotedForm = use;
  175. }
  176. void CFileCode::CreateFileFolder(const string& fileName) const
  177. {
  178.     CDirEntry entry(fileName);
  179.     CDir  dir(entry.GetDir());
  180.     dir.CreatePath();
  181. }
  182. void CFileCode::GenerateCode(void)
  183. {
  184.     if ( !m_Classes.empty() ) {
  185.         NON_CONST_ITERATE ( TClasses, i, m_Classes ) {
  186.             m_CurrentClass = &*i;
  187.             m_CurrentClass->code->GenerateCode(*this);
  188.         }
  189.         m_CurrentClass = 0;
  190.     }
  191.     m_HPPIncludes.erase(kEmptyStr);
  192.     m_CPPIncludes.erase(kEmptyStr);
  193. }
  194. CNcbiOstream& CFileCode::WriteCopyrightHeader(CNcbiOstream& out)
  195. {
  196.     return out <<
  197.         "/* $""Id$n"
  198.         " * ===========================================================================n"
  199.         " *n"
  200.         " *                            PUBLIC DOMAIN NOTICEn"
  201.         " *               National Center for Biotechnology Informationn"
  202.         " *n"
  203.         " *  This software/database is a "United States Government Work" under then"
  204.         " *  terms of the United States Copyright Act.  It was written as part ofn"
  205.         " *  the author's official duties as a United States Government employee andn"
  206.         " *  thus cannot be copyrighted.  This software/database is freely availablen"
  207.         " *  to the public for use. The National Library of Medicine and the U.S.n"
  208.         " *  Government have not placed any restriction on its use or reproduction.n"
  209.         " *n"
  210.         " *  Although all reasonable efforts have been taken to ensure the accuracyn"
  211.         " *  and reliability of the software and data, the NLM and the U.S.n"
  212.         " *  Government do not and cannot warrant the performance or results thatn"
  213.         " *  may be obtained by using this software or data. The NLM and the U.S.n"
  214.         " *  Government disclaim all warranties, express or implied, includingn"
  215.         " *  warranties of performance, merchantability or fitness for any particularn"
  216.         " *  purpose.n"
  217.         " *n"
  218.         " *  Please cite the author in any work or product based on this material.n"
  219.         " *n"
  220.         " * ===========================================================================n"
  221.         " *n";
  222. }
  223. CNcbiOstream& CFileCode::WriteSourceFile(CNcbiOstream& out) const
  224. {
  225.     ITERATE ( set<string>, i, m_SourceFiles ) {
  226.         if ( i != m_SourceFiles.begin() )
  227.             out << ", ";
  228.         {
  229.             CDirEntry entry(*i);
  230.             out << ''' << entry.GetName() << ''';
  231.         }
  232.     }
  233.     return out;
  234. }
  235. CNcbiOstream& CFileCode::WriteSpecRefs(CNcbiOstream& out) const
  236. {
  237.     string docroot = CClassCode::GetDocRootURL();
  238.     string rootdir = m_CodeGenerator->GetRootDir();
  239.     if (docroot.empty()) {
  240.         out << "/// ";
  241.         WriteSourceFile(out) << ".n";
  242.     } else {
  243.         out << "/// <a href="";
  244.         ITERATE ( set<string>, i, m_SourceFiles ) {
  245.             CDirEntry entry(*i);
  246.             string link;
  247.             if (!rootdir.empty()) {
  248.                 link = NStr::Replace(entry.GetPath(),rootdir,docroot);
  249.             } else {
  250.                 link = Path( docroot, entry.GetPath());
  251.             }
  252.             out << GetStdPath(link) << "">" << entry.GetName() << "</a>n";
  253.         }
  254.         string deffile = m_CodeGenerator->GetDefFile();
  255.         if (!deffile.empty()) {
  256.             CDirEntry entry(deffile);
  257.             out
  258.                 << "/// and additional tune-up parameters:n";
  259.             string link;
  260.             if (!rootdir.empty()) {
  261.                 link = NStr::Replace(entry.GetPath(),rootdir,docroot);
  262.             } else {
  263.                 link = Path( docroot, entry.GetPath());
  264.             }
  265.             out << "/// <a href="" << GetStdPath(link) << "">" << entry.GetName() << "</a>n";
  266.         }
  267.     }
  268.     return out;
  269. }
  270. CNcbiOstream& CFileCode::WriteCopyright(CNcbiOstream& out, bool header) const
  271. {
  272.     if (header) {
  273.         WriteCopyrightHeader(out)
  274.             << " */nn"
  275.             << "/// @" << CDirEntry(GetBaseHPPName()).GetName() << "n"
  276.             << "/// Data storage class.n"
  277.             << "///n"
  278.             << "/// This file was generated by application DATATOOLn"
  279.             << "/// using the following specifications:n";
  280.         WriteSpecRefs(out) <<
  281.             "///n"
  282.             "/// ATTENTION:n"
  283.             "///   Don't edit or commit this file into CVS as this file willn"
  284.             "///   be overridden (by DATATOOL) without warning!n";
  285.     } else {
  286.         WriteCopyrightHeader(out) <<
  287.             " * File Description:n"
  288.             " *   This code was generated by application DATATOOLn"
  289.             " *   using the following specifications:n"
  290.             " *   ";
  291.         WriteSourceFile(out) << ".n"
  292.             " *n"
  293.             " * ATTENTION:n"
  294.             " *   Don't edit or commit this file into CVS as this file willn"
  295.             " *   be overridden (by DATATOOL) without warning!n"
  296.             " * ===========================================================================n"
  297.             " */n";
  298.     }
  299.     return out;
  300. }
  301. CNcbiOstream& CFileCode::WriteUserCopyright(CNcbiOstream& out, bool header) const
  302. {
  303.     if (header) {
  304.         WriteCopyrightHeader(out)
  305.             << " */nn"
  306.             << "/// @" << CDirEntry(GetUserHPPName()).GetName() << "n"
  307.             << "/// User-defined methods of the data storage class.n"
  308.             << "///n"
  309.             << "/// This file was originally generated by application DATATOOLn"
  310.             << "/// using the following specifications:n";
  311.         string name = CDirEntry(GetBaseHPPName()).GetName();
  312.         WriteSpecRefs(out) <<
  313.             "///n"
  314.             "/// New methods or data members can be added to it if needed.n";
  315.         if (CClassCode::GetDocRootURL().empty()) {
  316.             out << "/// See also: " << name << "nn";
  317.         } else {
  318.             out << "/// See also: <a href="" << name << "">" << name << "</a>nn";
  319.         }
  320.     } else {
  321.         WriteCopyrightHeader(out) <<
  322.             " * Author:  .......n"
  323.             " *n"
  324.             " * File Description:n"
  325.             " *   .......n"
  326.             " *n"
  327.             " * Remark:n"
  328.             " *   This code was originally generated by application DATATOOLn"
  329.             " *   using the following specifications:n"
  330.             " *   ";
  331.         WriteSourceFile(out) << ".n"
  332.             " */n";
  333.     }
  334.     return out;
  335. }
  336. CNcbiOstream& CFileCode::WriteLogKeyword(CNcbiOstream& out)
  337. {
  338.     out << "n"
  339.         "/*n"
  340.         "* ===========================================================================n"
  341.         "*n"
  342.         "* $""Log$n"
  343.         "*n"
  344.         "* ===========================================================================n"
  345.         "*/n";
  346.     return out;
  347. }
  348. void CFileCode::GenerateHPP(const string& path, string& fileName) const
  349. {
  350.     fileName = Path(path, GetBaseHPPName());
  351.     CreateFileFolder(fileName);
  352.     CDelayedOfstream header(fileName);
  353.     if ( !header ) {
  354.         ERR_POST(Fatal << "Cannot create file: " << fileName);
  355.         return;
  356.     }
  357.     string hppDefine = GetBaseHPPDefine();
  358.     WriteCopyright(header, true) <<
  359.         "n"
  360.         "#ifndef " << hppDefine << "n"
  361.         "#define " << hppDefine << "n"
  362.         "n"
  363.         "// standard includesn"
  364.         "#include <serial/serialbase.hpp>n";
  365.     if ( !m_HPPIncludes.empty() ) {
  366.         header <<
  367.             "n"
  368.             "// generated includesn";
  369.         ITERATE ( TIncludes, i, m_HPPIncludes ) {
  370.             header <<
  371.                 "#include " << Include(*i, true) << "n";
  372.         }
  373.         header <<
  374.             'n';
  375.     }
  376.     CNamespace ns;
  377.     if ( !m_ForwardDeclarations.empty() ) {
  378.         bool begin = false;
  379.         ITERATE ( TForwards, i, m_ForwardDeclarations ) {
  380.             ns.Set(i->second, header);
  381.             if ( !begin ) {
  382.                 header <<
  383.                     "n"
  384.                     "// forward declarationsn";
  385.                 begin = true;
  386.             }
  387.             header <<
  388.                 "class " << i->first << ";n";
  389.         }
  390.         if ( begin )
  391.             header << 'n';
  392.     }
  393.     
  394.     if ( !m_Classes.empty() ) {
  395.         bool begin = false;
  396.         ITERATE ( TClasses, i, m_Classes ) {
  397.             if ( !i->hppCode.empty() ) {
  398.                 ns.Set(i->ns, header);
  399.                 if ( !begin ) {
  400.                     header <<
  401.                         "n"
  402.                         "// generated classesn"
  403.                         "n";
  404.                     if (CClassCode::GetDoxygenComments()) {
  405.                         header
  406.                             << "n"
  407.                             << "/** @addtogroup ";
  408.                         if (!CClassCode::GetDoxygenGroup().empty()) {
  409.                             header << CClassCode::GetDoxygenGroup();
  410.                         } else {
  411.                             header << "dataspec_" << i->code->GetModuleName();
  412.                         }
  413.                         header
  414.                             << "n *n"
  415.                             << " * @{n"
  416.                             << " */nn";
  417.                     }
  418.                     begin = true;
  419.                 }
  420.                 header << i->hppCode;
  421.             }
  422.         }
  423.         if ( begin ) {
  424.             if (CClassCode::GetDoxygenComments()) {
  425.                 header << "n/* @} */";
  426.             }
  427.             header << "n";
  428.         }
  429.     }
  430.     if ( !m_Classes.empty() ) {
  431.         bool begin = false;
  432.         ITERATE ( TClasses, i, m_Classes ) {
  433.             if ( !i->inlCode.empty() ) {
  434.                 ns.Set(i->ns, header, false);
  435.                 if ( !begin ) {
  436.                     // have inline methods
  437.                     header <<
  438.                         "n"
  439.                         "n"
  440.                         "n"
  441.                         "n"
  442.                         "n"
  443.                         "///////////////////////////////////////////////////////////n"
  444.                         "///////////////////// inline methods //////////////////////n"
  445.                         "///////////////////////////////////////////////////////////n";
  446.                     begin = true;
  447.                 }
  448.                 header << i->inlCode;
  449.             }
  450.         }
  451.         if ( begin ) {
  452.             header <<
  453.                 "///////////////////////////////////////////////////////////n"
  454.                 "////////////////// end of inline methods //////////////////n"
  455.                 "///////////////////////////////////////////////////////////n"
  456.                 "n"
  457.                 "n"
  458.                 "n"
  459.                 "n"
  460.                 "n";
  461.         }
  462.     }
  463.     ns.Reset(header);
  464.     header <<
  465.         "n"
  466.         "#endif // " << hppDefine << "n";
  467.     header.close();
  468.     if ( !header )
  469.         ERR_POST(Fatal << "Error writing file " << fileName);
  470. }
  471. void CFileCode::GenerateCPP(const string& path, string& fileName) const
  472. {
  473.     fileName = Path(path, GetBaseCPPName());
  474.     CreateFileFolder(fileName);
  475.     CDelayedOfstream code(fileName);
  476.     if ( !code ) {
  477.         ERR_POST(Fatal << "Cannot create file: " << fileName);
  478.         return;
  479.     }
  480.     WriteCopyright(code, false) <<
  481.         "n"
  482.         "// standard includesn";
  483.     if (!m_PchHeader.empty()) {
  484.         code <<
  485.             "#include <" << m_PchHeader << ">n";
  486.     }
  487.     code <<
  488.         "#include <serial/serialimpl.hpp>n"
  489.         "n"
  490.         "// generated includesn"
  491.         "#include " << Include(GetUserHPPName()) << "n";
  492.     if ( !m_CPPIncludes.empty() ) {
  493.         ITERATE ( TIncludes, i, m_CPPIncludes ) {
  494.             code <<
  495.                 "#include " <<
  496.                 Include(m_CodeGenerator->ResolveFileName(*i), true) <<
  497.                 "n";
  498.         }
  499.     }
  500.     CNamespace ns;
  501.     if ( !m_Classes.empty() ) {
  502.         bool begin = false;
  503.         ITERATE ( TClasses, i, m_Classes ) {
  504.             if ( !i->cppCode.empty() ) {
  505.                 ns.Set(i->ns, code, false);
  506.                 if ( !begin ) {
  507.                     code <<
  508.                         "n"
  509.                         "// generated classesn"
  510.                         "n";
  511.                     begin = true;
  512.                 }
  513.                 code << i->cppCode;
  514.             }
  515.         }
  516.         if ( begin )
  517.             code << 'n';
  518.     }
  519.     ns.Reset(code);
  520.     code.close();
  521.     if ( !code )
  522.         ERR_POST(Fatal << "Error writing file " << fileName);
  523. }
  524. bool CFileCode::GenerateUserHPP(const string& path, string& fileName) const
  525. {
  526.     return WriteUserFile(path, GetUserHPPName(), fileName,
  527.                          &CFileCode::GenerateUserHPPCode);
  528. }
  529. bool CFileCode::GenerateUserCPP(const string& path, string& fileName) const
  530. {
  531.     return WriteUserFile(path, GetUserCPPName(), fileName,
  532.                          &CFileCode::GenerateUserCPPCode);
  533. }
  534. bool CFileCode::ModifiedByUser(const string& fileName,
  535.                                const list<string>& newLines) const
  536. {
  537.     // first check if file exists
  538.     CNcbiIfstream in(fileName.c_str());
  539.     if ( !in ) {
  540.         // file doesn't exist -> was not modified by user
  541.         return false;
  542.     }
  543.     CChecksum checksum;
  544.     bool haveChecksum = false;
  545.     bool equal = true;
  546.     
  547.     list<string>::const_iterator newLinesI = newLines.begin();
  548.     SIZE_TYPE lineOffset = 0;
  549.     while ( in ) {
  550.         char buffer[1024]; // buffer must be as big as checksum line
  551.         in.getline(buffer, sizeof(buffer), 'n');
  552.         SIZE_TYPE count = in.gcount();
  553.         if ( count == 0 ) {
  554.             // end of file
  555.             break;
  556.         }
  557.         if ( haveChecksum || in.eof() ) {
  558.             // text after checksum -> modified by user
  559.             //    OR
  560.             // partial last line -> modified by user
  561.             ERR_POST(Info <<
  562.                      "Will not overwrite modified user file: "<<fileName);
  563.             return true;
  564.         }
  565.         bool eol;
  566.         // check where EOL was read
  567.         if ( in.fail() ) {
  568.             // very long line
  569.             // reset fail flag
  570.             in.clear(in.rdstate() & ~in.failbit);
  571.             eol = false;
  572.         }
  573.         else {
  574.             // full line was read
  575.             --count; // do not include EOL symbol
  576.             eol = true;
  577.         }
  578.         // check for checksum line
  579.         if ( lineOffset == 0 && eol ) {
  580.             haveChecksum = checksum.ValidChecksumLine(buffer, count);
  581.             if ( haveChecksum )
  582.                 continue;
  583.         }
  584.         // update checksum
  585.         checksum.AddChars(buffer, count);
  586.         // update equal flag
  587.         if ( equal ) {
  588.             if ( newLinesI == newLines.end() )
  589.                 equal = false;
  590.             else if ( newLinesI->size() < lineOffset + count )
  591.                 equal = false;
  592.             else {
  593.                 const char* ptr = newLinesI->data() + lineOffset;
  594.                 equal = memcmp(ptr, buffer, count) == 0;
  595.             }
  596.         }
  597.         lineOffset += count;
  598.         if ( eol ) {
  599.             checksum.NextLine();
  600.             if ( equal ) {
  601.                 // check for end of line in newLines
  602.                 equal = newLinesI->size() == lineOffset;
  603.                 ++newLinesI;
  604.             }
  605.             lineOffset = 0;
  606.         }
  607.     }
  608.     if ( haveChecksum ) {
  609.         // file contains valid checksum -> it was not modified by user
  610.         return false;
  611.     }
  612.     // file doesn't have checksum
  613.     // we assume it modified if its content different from newLines
  614.     return !equal  ||  newLinesI != newLines.end();
  615. }
  616. void CFileCode::LoadLines(TGenerateMethod method, list<string>& lines) const
  617. {
  618.     CNcbiOstrstream code;
  619.     // generate code
  620.     (this->*method)(code);
  621.     // get code length
  622.     size_t count = code.pcount();
  623.     if ( count == 0 ) {
  624.         NCBI_THROW(CDatatoolException,eInvalidData,"empty generated code");
  625.     }
  626.     // get code string pointer
  627.     const char* codePtr = code.str();
  628.     code.freeze(false);
  629.     // split code by lines
  630.     while ( count > 0 ) {
  631.         // find end of next line
  632.         const char* eolPtr = (const char*)memchr(codePtr, 'n', count);
  633.         if ( !eolPtr ) {
  634.             NCBI_THROW(CDatatoolException,eInvalidData,
  635.                        "unended line in generated code");
  636.         }
  637.         // add next line to list
  638.         lines.push_back(kEmptyStr);
  639.         lines.back().assign(codePtr, eolPtr);
  640.         // skip EOL symbol ('n')
  641.         ++eolPtr;
  642.         // update code length
  643.         count -= (eolPtr - codePtr);
  644.         // update code pointer
  645.         codePtr = eolPtr;
  646.     }
  647. }
  648. bool CFileCode::WriteUserFile(const string& path, const string& name,
  649.                               string& fileName, TGenerateMethod method) const
  650. {
  651.     // parse new code lines
  652.     list<string> newLines;
  653.     LoadLines(method, newLines);
  654.     fileName = Path(path, name);
  655.     CreateFileFolder(fileName);
  656.     if ( ModifiedByUser(fileName, newLines) ) {
  657.         // do nothing on user modified files
  658.         return false;
  659.     }
  660.     // write new contents of nonmodified file
  661.     CDelayedOfstream out(fileName);
  662.     if ( !out ) {
  663.         ERR_POST(Fatal << "Cannot create file: " << fileName);
  664.         return false;
  665.     }
  666.     CChecksum checksum;
  667.     ITERATE ( list<string>, i, newLines ) {
  668.         checksum.AddLine(*i);
  669.         out << *i << 'n';
  670.     }
  671.     out << checksum;
  672.     out.close();
  673.     if ( !out ) {
  674.         ERR_POST("Error writing file " << fileName);
  675.         return false;
  676.     }
  677.     return true;
  678. }
  679. void CFileCode::GenerateUserHPPCode(CNcbiOstream& header) const
  680. {
  681.     string hppDefine = GetUserHPPDefine();
  682.     WriteUserCopyright(header, true) <<
  683.         "n"
  684.         "#ifndef " << hppDefine << "n"
  685.         "#define " << hppDefine << "n"
  686.         "n";
  687.     header <<
  688.         "n"
  689.         "// generated includesn"
  690.         "#include " << Include(GetBaseHPPName()) << "n";
  691.     
  692.     CNamespace ns;
  693.     if ( !m_Classes.empty() ) {
  694.         header <<
  695.             "n"
  696.             "// generated classesn"
  697.             "n";
  698.         ITERATE ( TClasses, i, m_Classes ) {
  699.             ns.Set(i->ns, header, false);
  700.             i->code->GenerateUserHPPCode(header);
  701.         }
  702.     }
  703.     ns.Reset(header);
  704.     
  705.     WriteLogKeyword(header);
  706.     header <<
  707.         "n"
  708.         "#endif // " << hppDefine << "n";
  709. }
  710. void CFileCode::GenerateUserCPPCode(CNcbiOstream& code) const
  711. {
  712.     WriteUserCopyright(code, false) <<
  713.         "n"
  714.         "// standard includesn";
  715.     if (!m_PchHeader.empty()) {
  716.         code <<
  717.             "#include <" << m_PchHeader << ">n";
  718.     }
  719.     code <<
  720.         "n"
  721.         "// generated includesn"
  722.         "#include " << Include(GetUserHPPName()) << "n";
  723.     CNamespace ns;
  724.     if ( !m_Classes.empty() ) {
  725.         code <<
  726.             "n"
  727.             "// generated classesn"
  728.             "n";
  729.         ITERATE ( TClasses, i, m_Classes ) {
  730.             ns.Set(i->ns, code, false);
  731.             i->code->GenerateUserCPPCode(code);
  732.         }
  733.     }
  734.     ns.Reset(code);
  735.     WriteLogKeyword(code);
  736. }
  737. bool CFileCode::AddType(const CDataType* type)
  738. {
  739.     string idName = type->IdName();
  740.     if ( m_AddedClasses.find(idName) != m_AddedClasses.end() )
  741.         return false;
  742.     m_AddedClasses.insert(idName);
  743.     _TRACE("AddType: " << idName << ": " << typeid(*type).name());
  744.     m_SourceFiles.insert(type->GetSourceFileName());
  745.     AutoPtr<CTypeStrings> code = type->GenerateCode();
  746.     code->SetModuleName(type->GetModule()->GetName());
  747.     m_Classes.push_front(SClassInfo(type->Namespace(), code));
  748.     return true;
  749. }
  750. void CFileCode::GetModuleNames( map<string,string>& names) const
  751. {
  752.     CNcbiOstrstream ostr;
  753.     WriteSourceFile(ostr);
  754.     ostr.put('');
  755.     string src_file = string(CNcbiOstrstreamToString(ostr));
  756.     string module_name;
  757.     ITERATE ( TClasses, i, m_Classes ) {
  758.         module_name = i->code->GetModuleName();
  759.         if (names.find(module_name) == names.end()) {
  760.             names[module_name] = src_file;
  761.         }
  762.     }
  763. }
  764. END_NCBI_SCOPE
  765. /*
  766. * ===========================================================================
  767. * $Log: filecode.cpp,v $
  768. * Revision 1000.1  2004/06/01 19:43:05  gouriano
  769. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
  770. *
  771. * Revision 1.45  2004/05/17 21:03:14  gorelenk
  772. * Added include of PCH ncbi_pch.hpp
  773. *
  774. * Revision 1.44  2004/05/17 14:50:54  gouriano
  775. * Added possibility to include precompiled header
  776. *
  777. * Revision 1.43  2004/05/03 19:31:03  gouriano
  778. * Made generation of DOXYGEN-style comments optional
  779. *
  780. * Revision 1.42  2004/04/29 20:11:39  gouriano
  781. * Generate DOXYGEN-style comments in C++ headers
  782. *
  783. * Revision 1.41  2003/05/29 17:25:34  gouriano
  784. * added possibility of generation .cvsignore file
  785. *
  786. * Revision 1.40  2003/03/11 20:06:47  kuznets
  787. * iterate -> ITERATE
  788. *
  789. * Revision 1.39  2003/03/10 18:55:18  gouriano
  790. * use new structured exceptions (based on CException)
  791. *
  792. * Revision 1.38  2002/12/17 16:22:48  gouriano
  793. * separated class name from the name of the file in which it will be written
  794. *
  795. * Revision 1.37  2002/10/25 16:13:04  ucko
  796. * Tweak CFileCode::Include to avoid segfaulting when built with KCC
  797. * (presumably due to a compiler bug)
  798. *
  799. * Revision 1.36  2002/10/22 15:06:13  gouriano
  800. * added possibillity to use quoted syntax form for generated include files
  801. *
  802. * Revision 1.35  2002/10/15 13:56:15  gouriano
  803. * removed explicit reference to ASN (could be DTD now)
  804. *
  805. * Revision 1.34  2002/10/01 14:20:30  gouriano
  806. * added more generation report data
  807. *
  808. * Revision 1.33  2002/09/30 19:15:08  gouriano
  809. * write only the base name of the ASN file (in comments section)
  810. *
  811. * Revision 1.32  2002/06/13 15:41:17  ucko
  812. * Restore generated newline following Log keyword (accidentally dropped in
  813. * the previous revision).
  814. *
  815. * Revision 1.31  2002/06/11 02:46:49  vakatov
  816. * Fixed a compilation bug introduced in R1.30;  plus some code beautification.
  817. *
  818. * Revision 1.30  2002/06/10 18:41:30  ucko
  819. * Move CVS logs (both internal and generated) to the end.
  820. *
  821. * Revision 1.29  2001/08/31 20:05:46  ucko
  822. * Fix ICC build.
  823. *
  824. * Revision 1.28  2001/08/16 13:18:03  grichenk
  825. * Corrected calls to GetStdPath() -- moved '>' outside the call
  826. *
  827. * Revision 1.27  2001/08/15 20:27:14  juran
  828. * Convert native pathnames to unix-style for include directives.
  829. *
  830. * Revision 1.26  2001/01/05 20:10:57  vasilche
  831. * CByteSource, CIStrBuffer, COStrBuffer, CLightString, CChecksum, CWeakMap
  832. * were moved to util.
  833. *
  834. * Revision 1.25  2000/11/22 16:26:29  vasilche
  835. * Added generation/checking of checksum to user files.
  836. *
  837. * Revision 1.24  2000/11/07 17:26:25  vasilche
  838. * Added module names to CTypeInfo and CEnumeratedTypeValues
  839. * Added possibility to set include directory for whole module
  840. *
  841. * Revision 1.23  2000/08/25 15:59:21  vasilche
  842. * Renamed directory tool -> datatool.
  843. *
  844. * Revision 1.22  2000/06/16 16:31:39  vasilche
  845. * Changed implementation of choices and classes info to allow use of the
  846. * same classes in generated and user written classes.
  847. *
  848. * Revision 1.21  2000/04/28 16:58:16  vasilche
  849. * Added classes CByteSource and CByteSourceReader for generic reading.
  850. * Added delayed reading of choice variants.
  851. *
  852. * Revision 1.20  2000/04/17 19:11:08  vasilche
  853. * Fixed failed assertion.
  854. * Removed redundant namespace specifications.
  855. *
  856. * Revision 1.19  2000/04/12 15:36:51  vasilche
  857. * Added -on <namespace> argument to datatool.
  858. * Removed unnecessary namespace specifications in generated files.
  859. *
  860. * Revision 1.18  2000/04/07 19:26:26  vasilche
  861. * Added namespace support to datatool.
  862. * By default with argument -oR datatool will generate objects in namespace
  863. * NCBI_NS_NCBI::objects (aka ncbi::objects).
  864. * Datatool's classes also moved to NCBI namespace.
  865. *
  866. * Revision 1.17  2000/04/03 18:47:30  vasilche
  867. * Added main include file for generated headers.
  868. * serialimpl.hpp is included in generated sources with GetTypeInfo methods
  869. *
  870. * Revision 1.16  2000/03/29 15:52:26  vasilche
  871. * Generated files names limited to 31 symbols due to limitations of Mac.
  872. * Removed unions with only one member.
  873. *
  874. * Revision 1.15  2000/03/17 17:05:59  vasilche
  875. * String literal split to avoid influence of cvs.
  876. *
  877. * Revision 1.14  2000/03/17 16:49:55  vasilche
  878. * Added copyright message to generated files.
  879. * All objects pointers in choices now share the only CObject pointer.
  880. * All setters/getters made public until we'll find better solution.
  881. *
  882. * Revision 1.13  2000/03/07 14:06:31  vasilche
  883. * Added generation of reference counted objects.
  884. *
  885. * Revision 1.12  2000/02/17 21:26:18  vasilche
  886. * Inline methods now will be at the end of *_Base.hpp files.
  887. *
  888. * Revision 1.11  2000/02/17 20:05:07  vasilche
  889. * Inline methods now will be generated in *_Base.inl files.
  890. * Fixed processing of StringStore.
  891. * Renamed in choices: Selected() -> Which(), E_choice -> E_Choice.
  892. * Enumerated values now will preserve case as in ASN.1 definition.
  893. *
  894. * Revision 1.10  2000/02/01 21:47:58  vasilche
  895. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  896. * Removed CMemberInfo subclasses.
  897. * Added support for DEFAULT/OPTIONAL members.
  898. * Changed class generation.
  899. * Moved datatool headers to include/internal/serial/tool.
  900. *
  901. * Revision 1.9  2000/01/06 16:13:17  vasilche
  902. * Fail of file generation now fatal.
  903. *
  904. * Revision 1.8  1999/12/28 18:55:57  vasilche
  905. * Reduced size of compiled object files:
  906. * 1. avoid inline or implicit virtual methods (especially destructors).
  907. * 2. avoid std::string's methods usage in inline methods.
  908. * 3. avoid string literals ("xxx") in inline methods.
  909. *
  910. * Revision 1.7  1999/12/21 17:18:34  vasilche
  911. * Added CDelayedFostream class which rewrites file only if contents is changed.
  912. *
  913. * Revision 1.6  1999/12/20 21:00:17  vasilche
  914. * Added generation of sources in different directories.
  915. *
  916. * Revision 1.5  1999/12/03 21:42:12  vasilche
  917. * Fixed conflict of enums in choices.
  918. *
  919. * Revision 1.4  1999/12/01 17:36:25  vasilche
  920. * Fixed CHOICE processing.
  921. *
  922. * Revision 1.3  1999/11/22 21:04:49  vasilche
  923. * Cleaned main interface headers. Now generated files should include
  924. * serial/serialimpl.hpp and user code should include serial/serial.hpp
  925. * which became might lighter.
  926. *
  927. * Revision 1.2  1999/11/15 19:36:14  vasilche
  928. * Fixed warnings on GCC
  929. *
  930. * ===========================================================================
  931. */