Guest

po3

By: a guest on Jan 28th, 2012  |  syntax: None  |  size: 11.47 KB  |  hits: 13  |  expires: Never
download  |  raw  |  embed  |  report abuse
Copied
  1. #include <cstdio>
  2. #include <cctype>
  3. #include <cstring>
  4. #include <fstream>
  5. #include <map>
  6. #include <string>
  7. #include <iostream>
  8.  
  9. using namespace std;
  10.  
  11. struct SLangInfo
  12. {
  13.     const char *pszPo;
  14.     const char *pszLang;
  15.     const char *pszOutput;
  16. } g_Languages[] = {
  17.     {"pl", "LANG_POLISH", "pl-PL"},
  18.     {"en", "LANG_ENGLISH", "en-US"},
  19. };
  20.  
  21. class CPoParser
  22. {
  23.     public:
  24.         CPoParser(ifstream &Stream)
  25.         {
  26.             Load(Stream);
  27.         }
  28.        
  29.         void Load(ifstream &Stream)
  30.         {
  31.             m_Line = 0;
  32.             m_szBuf[0] = 0;
  33.             m_Ptr = m_szBuf;
  34.            
  35.             while(Stream.good())
  36.             {
  37.                 string strName, strMsgId, strCtxt, strMsg;
  38.                
  39.                 if(!GetEntry(Stream, strName, strMsgId))
  40.                     break;
  41.                
  42.                 if(strName == "msgctxt")
  43.                 {
  44.                     strCtxt = strMsgId;
  45.                     if(!GetEntry(Stream, strName, strMsgId))
  46.                         break;
  47.                 }
  48.                
  49.                 if(strName != "msgid")
  50.                 {
  51.                     cerr << "Expected msgid at line " << m_Line << ", got " << strName << "\n";
  52.                     continue;
  53.                 }
  54.                
  55.                 if(!GetEntry(Stream, strName, strMsg) || strName != "msgstr")
  56.                 {
  57.                     cerr << "Expected msgstr at line " << m_Line << ", got " << strName << "\n";
  58.                     continue;
  59.                 }
  60.                
  61.                 if(!strCtxt.empty())
  62.                     strMsgId = string("#msgctxt#") + strCtxt + "#" + strMsgId;
  63.                 m_Messages[strMsgId] = strMsg;
  64.             }
  65.         }
  66.        
  67.         const char *GetMsg(const char *pszMsgId)
  68.         {
  69.             map<string, string>::iterator it = m_Messages.find(pszMsgId);
  70.             if(it == m_Messages.end())
  71.                 return NULL;
  72.             return it->second.c_str();
  73.         }
  74.    
  75.     private:
  76.         map<string, string> m_Messages;
  77.         unsigned m_Line;
  78.         char m_szBuf[256];
  79.         const char *m_Ptr;
  80.        
  81.         bool GetEntry(ifstream &Stream, string &strName, string &strValue)
  82.         {
  83.             if(!GetToken(Stream, strName, false))
  84.                 return false;
  85.            
  86.             if(!GetToken(Stream, strValue, true))
  87.             {
  88.                 cerr << "Expected string at line " << m_Line << ", got " << m_Ptr << "\n";
  89.                 return false;
  90.             }
  91.            
  92.             string strTemp;
  93.             while(GetToken(Stream, strTemp, true))
  94.                 strValue += strTemp;
  95.            
  96.             return true;
  97.         }
  98.        
  99.         bool LoadNextLine(ifstream &Stream)
  100.         {
  101.             while(Stream.good())
  102.             {
  103.                 Stream.getline(m_szBuf, sizeof(m_szBuf));
  104.                 ++m_Line;
  105.                 m_Ptr = m_szBuf;
  106.                
  107.                 IgnoreWhiteChars();
  108.                 if(m_Ptr[0] != '#')
  109.                     return true;
  110.             }
  111.            
  112.             return false;
  113.         }
  114.        
  115.         void IgnoreWhiteChars()
  116.         {
  117.             while(isspace(*m_Ptr))
  118.                 ++m_Ptr;
  119.         }
  120.        
  121.         bool GetToken(ifstream &Stream, string &strResult, bool bStr)
  122.         {
  123.             IgnoreWhiteChars();
  124.             if(!m_Ptr[0] && !LoadNextLine(Stream))
  125.                 return false;
  126.            
  127.             bool bIsStr = (*m_Ptr == '"');
  128.             if(bStr != bIsStr)
  129.                 return false;
  130.            
  131.             strResult = "";
  132.            
  133.             if(bIsStr)
  134.             {
  135.                 ++m_Ptr;
  136.                 while(*m_Ptr)
  137.                 {
  138.                     if(*m_Ptr == '"')
  139.                     {
  140.                         ++m_Ptr;
  141.                         break;
  142.                     }
  143.                     if(m_Ptr[0] == '\\' && m_Ptr[1] == '"')
  144.                     {
  145.                         strResult += '"';
  146.                         m_Ptr += 2;
  147.                     } else
  148.                         strResult += *(m_Ptr++);
  149.                 }
  150.             }
  151.             else
  152.             {
  153.                 while(*m_Ptr && !isspace(*m_Ptr))
  154.                     strResult += *(m_Ptr++);
  155.             }
  156.            
  157.             return true;
  158.         }
  159. };
  160.  
  161. class CRcTranslator
  162. {
  163.     public:
  164.         void Define(const char *pszName, const char *pszValue)
  165.         {
  166.             m_Defines[pszName] = pszValue;
  167.         }
  168.        
  169.         void Process(istream &Input, ostream &Output, CPoParser &PoParser)
  170.         {
  171.             LoadNextLine(Input);
  172.             string strTemp;
  173.            
  174.             while(Input.good())
  175.             {
  176.                 if(!m_Ptr[0])
  177.                 {
  178.                     Output << "\n";
  179.                     if(!LoadNextLine(Input))
  180.                         break;
  181.                     continue;
  182.                 }
  183.                
  184.                 if(IgnoreShortComment(Input, Output))
  185.                     continue;
  186.                
  187.                 if(IgnoreLongComment(Input, Output))
  188.                     continue;
  189.                
  190.                 if(GetString(Input, strTemp))
  191.                 {
  192.                     OutputTranslatedString(Output, PoParser, strTemp.c_str());
  193.                     continue;
  194.                 }
  195.                
  196.                 if(GetIdentifier(Input, strTemp))
  197.                 {
  198.                     map<string, string>::iterator it = m_Defines.find(strTemp);
  199.                     if(it == m_Defines.end())
  200.                         Output << strTemp;
  201.                     else
  202.                         Output << it->second;
  203.                     continue;
  204.                 }
  205.                
  206.                 Output << *(m_Ptr++);
  207.             }
  208.         }
  209.    
  210.     private:
  211.         char m_szBuf[256], *m_Ptr;
  212.         map<string, string> m_Defines;
  213.        
  214.         bool IgnoreShortComment(istream &Input, ostream &Output)
  215.         {
  216.             if(m_Ptr[0] != '/' || m_Ptr[1] != '/')
  217.                 return false;
  218.            
  219.             Output << m_Ptr << "\n";
  220.             LoadNextLine(Input);
  221.             return true;
  222.         }
  223.        
  224.         bool IgnoreLongComment(istream &Input, ostream &Output)
  225.         {
  226.             if(m_Ptr[0] != '/' || m_Ptr[1] != '*')
  227.                 return false;
  228.            
  229.             m_Ptr += 2;
  230.             Output << "/*";
  231.            
  232.             while(true)
  233.             {
  234.                 if(!m_Ptr[0])
  235.                 {
  236.                     Output << "\n";
  237.                     if(!LoadNextLine(Input))
  238.                         break;
  239.                 }
  240.                 else if(m_Ptr[0] == '*' && m_Ptr[1] == '/')
  241.                 {
  242.                     m_Ptr += 2;
  243.                     break;
  244.                 } else
  245.                     Output << *(m_Ptr++);
  246.             }
  247.             Output << "*/";
  248.             return true;
  249.         }
  250.        
  251.         bool GetString(istream &Input, string &strResult)
  252.         {
  253.             if(m_Ptr[0] != '"')
  254.                 return false;
  255.            
  256.             ++m_Ptr;
  257.             strResult = "";
  258.             while(true)
  259.             {
  260.                 if(m_Ptr[0] == '\\' && !m_Ptr[1])
  261.                 {
  262.                     if(!LoadNextLine(Input))
  263.                         break;
  264.                 }
  265.                 else if(!m_Ptr[0])
  266.                     return false;
  267.                 else if(m_Ptr[0] == '"')
  268.                 {
  269.                     m_Ptr++;
  270.                     break;
  271.                 } else
  272.                     strResult += *(m_Ptr++);
  273.             }
  274.            
  275.             return true;
  276.         }
  277.        
  278.         bool GetIdentifier(istream &Input, string &strResult)
  279.         {
  280.             strResult = "";
  281.             while(isalnum(*m_Ptr) || *m_Ptr == '_')
  282.                 strResult += *(m_Ptr++);
  283.            
  284.             return !strResult.empty();
  285.         }
  286.        
  287.         bool LoadNextLine(istream &Stream)
  288.         {
  289.             if(!Stream.good())
  290.                 return false;
  291.             Stream.getline(m_szBuf, sizeof(m_szBuf));
  292.             m_Ptr = m_szBuf;
  293.             return true;
  294.         }
  295.        
  296.         void OutputTranslatedString(ostream &Output, CPoParser &PoParser, const char *pszStr)
  297.         {
  298.             const char *pszMsg = pszStr[0] ? PoParser.GetMsg(pszStr) : NULL;
  299.             if(!pszMsg)
  300.                 pszMsg = pszStr;
  301.            
  302.             static char szSpecialCtxt[] = "#msgctxt#do not translate#";
  303.             if(strncmp(pszMsg, szSpecialCtxt, sizeof(szSpecialCtxt) - 1) == 0)
  304.                 pszMsg += sizeof(szSpecialCtxt) - 1;
  305.             Output << '"';
  306.             while(*pszMsg)
  307.             {
  308.                 if(pszMsg[0] == '\\' && pszMsg[1] == 'n')
  309.                 {
  310.                     Output << "\\n\\\n";
  311.                     pszMsg += 2;
  312.                 } else
  313.                     Output << *(pszMsg++);
  314.             }
  315.            
  316.             Output << '"';
  317.         }
  318. };
  319.  
  320. int main(int argc, const char *argv[])
  321. {
  322.     const char *pszPoPath = NULL, *pszRcPath = NULL, *pszOutputPath = "output.rc";
  323.     bool bUsage = false;
  324.     CRcTranslator Translator;
  325.    
  326.     for(int i = 1; i < argc; ++i)
  327.     {
  328.         const char *pszArg = argv[i];
  329.         if(pszArg[0] == '/' || pszArg[0] == '-')
  330.             ++pszArg;
  331.        
  332.         char chOpt = tolower(pszArg[0]);
  333.         if(chOpt && pszArg[1])
  334.             chOpt = 0;
  335.        
  336.         if(chOpt == 'p' && i + 1 < argc)
  337.             pszPoPath = argv[++i];
  338.         else if(chOpt == 'r' && i + 1 < argc)
  339.             pszRcPath = argv[++i];
  340.         else if(chOpt == 'o' && i + 1 < argc)
  341.             pszOutputPath = argv[++i];
  342.         else if(chOpt == 'h')
  343.             bUsage = true;
  344.         else if(tolower(pszArg[0]) == 'd')
  345.         {
  346.             const char *pszDef = pszArg + 1;
  347.             if(!pszDef[0] && i + 1 < argc)
  348.                 pszDef = argv[++i];
  349.            
  350.             const char *pszVal = strchr(pszDef, '=');
  351.             string strName;
  352.             if(pszVal)
  353.             {
  354.                 string strName(pszDef, pszVal - pszDef);
  355.                 Translator.Define(strName.c_str(), pszVal + 1);
  356.             }
  357.             else
  358.                 Translator.Define(pszDef, "1");
  359.         } else
  360.             cerr << "Warning! Unknown option: " << argv[i] << ".\n";
  361.     }
  362.    
  363.     if(!pszPoPath || !pszRcPath || !pszOutputPath || bUsage)
  364.     {
  365.         cout << "Usage:\n";
  366.         cout << argv[0] << " -r rc_path -p po_path [-o output_path] [-Dname=value]\n";
  367.         cout << "\t-r rc_path\tSets path of rc file to process\n";
  368.         cout << "\t-p po_path\tSets path to a po file for translation\n";
  369.         cout << "\t-o output_path\tSets path to output rc file\n";
  370.         cout << "\t-d name=value\tReplaces specified identifier in rc file\n";
  371.        
  372.         return 0;
  373.     }
  374.    
  375.     ifstream RcFile(pszRcPath);
  376.     if(!RcFile.good())
  377.     {
  378.         cerr << "Error! Cannot open " << pszRcPath << ".\n";
  379.         return -1;
  380.     }
  381.    
  382.     ifstream PoFile(pszPoPath);
  383.     if(!PoFile.good())
  384.     {
  385.         cerr << "Error! Cannot open " << pszPoPath << ".\n";
  386.         return -1;
  387.     }
  388.    
  389.     ofstream OutputFile(pszOutputPath);
  390.     if(!RcFile.good())
  391.     {
  392.         cerr << "Error! Cannot open " << pszOutputPath << ".\n";
  393.         return -1;
  394.     }
  395.    
  396.     CPoParser PoParser(PoFile);
  397.    
  398.     Translator.Process(RcFile, OutputFile, PoParser);
  399.     cout << "Done!\n";
  400.    
  401.     return 0;
  402. }