Xlat.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:37k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Log: Xlat.cpp,v $
  58.  * Revision 1.18  2003/05/14 19:11:34  gareth
  59.  * Added code creation for new method that returns error serverity the DOM way.
  60.  *
  61.  * Revision 1.17  2003/04/14 08:41:00  gareth
  62.  * Xlat now works under linux - Big thanks to Neil Graham (I no longer have to find a windows box). Still slight problems working with glibc before 2.2.4 (If you mess up the parameters it seg faults due to handling of wprintf)
  63.  *
  64.  * Revision 1.16  2002/12/12 23:40:39  peiyongz
  65.  * normlize locale string.
  66.  *
  67.  * Revision 1.15  2002/11/12 17:24:58  tng
  68.  * DOM Message: add new domain for DOM Messages.
  69.  *
  70.  * Revision 1.14  2002/11/04 15:24:50  tng
  71.  * C++ Namespace Support.
  72.  *
  73.  * Revision 1.13  2002/09/30 22:09:58  peiyongz
  74.  * To generate icu resource file (in text) for error message.
  75.  *
  76.  * Revision 1.12  2002/07/04 17:40:07  tng
  77.  * Use new DOM in Xlat.
  78.  *
  79.  * Revision 1.11  2002/03/01 16:18:38  tng
  80.  * Nest entire code in an inner block so that reference counting should recover
  81.  * all document and DOMString storage when this block exits.
  82.  *
  83.  * Revision 1.10  2002/02/07 16:19:40  knoaman
  84.  * sane_include update.
  85.  *
  86.  * Revision 1.9  2002/02/01 23:48:37  peiyongz
  87.  * sane_include
  88.  *
  89.  * Revision 1.8  2001/05/03 19:09:36  knoaman
  90.  * Support Warning/Error/FatalError messaging.
  91.  * Validity constraints errors are treated as errors, with the ability by user to set
  92.  * validity constraints as fatal errors.
  93.  *
  94.  * Revision 1.7  2000/03/18 00:00:58  roddey
  95.  * Improved error reporting
  96.  *
  97.  * Revision 1.6  2000/03/03 01:29:36  roddey
  98.  * Added a scanReset()/parseReset() method to the scanner and
  99.  * parsers, to allow for reset after early exit from a progressive parse.
  100.  * Added calls to new Terminate() call to all of the samples. Improved
  101.  * documentation in SAX and DOM parsers.
  102.  *
  103.  * Revision 1.5  2000/03/02 19:55:52  roddey
  104.  * This checkin includes many changes done while waiting for the
  105.  * 1.1.0 code to be finished. I can't list them all here, but a list is
  106.  * available elsewhere.
  107.  *
  108.  * Revision 1.4  2000/02/14 19:25:44  roddey
  109.  * Fixed some small bugs in how it used strings returned from DOM calls.
  110.  *
  111.  * Revision 1.3  2000/02/06 07:48:41  rahulj
  112.  * Year 2K copyright swat.
  113.  *
  114.  * Revision 1.2  2000/01/05 20:24:58  roddey
  115.  * Some changes to simplify life for the Messge Catalog message loader. The formatter
  116.  * for the message loader now spits out a simple header of ids that allows the loader to
  117.  * be independent of hard coded set numbers.
  118.  *
  119.  * Revision 1.1.1.1  1999/11/09 01:01:12  twl
  120.  * Initial checkin
  121.  *
  122.  * Revision 1.5  1999/11/08 20:42:04  rahul
  123.  * Swat for adding in Product name and CVS comment log variable.
  124.  *
  125.  */
  126. // ---------------------------------------------------------------------------
  127. //  This program is designed to parse an XML file which holds error text
  128. //  data. It will build a DOM tree from that source file and can output it
  129. //  a number of different formats.
  130. //
  131. //  In order to drastically simplify the program, it is designed only to run
  132. //  on platforms/compilers that understand Unicode. It can output the data
  133. //  in whatever format is required, so it can handle outputting for other
  134. //  platforms. This also simplifies bootstrapping new releases up on other
  135. //  platforms. Once the Win32 version is working, it can generate output for
  136. //  the other platforms so that they can have loadable text from day one.
  137. // ---------------------------------------------------------------------------
  138. // ---------------------------------------------------------------------------
  139. //  Includes
  140. // ---------------------------------------------------------------------------
  141. #include "Xlat.hpp"
  142. // ---------------------------------------------------------------------------
  143. //  Static data
  144. //
  145. //  gRelativeInputPath
  146. //      This is the path, relative to the given input source root, to the
  147. //      input file. The given local suffix must also be added to it.
  148. // ---------------------------------------------------------------------------
  149. XMLCh*      gRelativeInputPath = 0;
  150. // ---------------------------------------------------------------------------
  151. //  Global data
  152. // ---------------------------------------------------------------------------
  153. XMLCh* typePrefixes[MsgTypes_Count];
  154. // ---------------------------------------------------------------------------
  155. //  temporary variables/conversion utility functions
  156. //  We need different temps depending on treatment of wide characters
  157. // ---------------------------------------------------------------------------
  158. #ifdef longChars
  159.     char* fTmpStr = 0;
  160. #else 
  161.     wchar_t fTmpWStr[256];
  162. #endif 
  163. // ---------------------------------------------------------------------------
  164. //  Local data
  165. //
  166. //  gLocale
  167. //      This is the locale suffix, e.g. US_EN, that is used to find the
  168. //      correct file and can be used on output files as well. Its set via
  169. //      the /Locale= parameter.
  170. //
  171. //  gOutFormat
  172. //      This is the output format, which is given on the command line as
  173. //      /OutFmt= Its mapped to the internal enum which is stored here.
  174. //
  175. //  gOutPath
  176. //      This is the path to the output path, which is given on the command
  177. //      line as /OutPath=. Its just the path, not a name, since the output
  178. //      might consist of multiple output files. They will all be based on
  179. //      the base part of the input name.
  180. //
  181. //  gSrcRoot
  182. //      This the path to the root of the build tree. The input files needed
  183. //      are found in known places relative to it.
  184. // ---------------------------------------------------------------------------
  185. const XMLCh*    gLocale = 0;
  186. OutFormats      gOutFormat = OutFormat_Unknown;
  187. const XMLCh*    gOutPath = 0;
  188. const XMLCh*    gSrcRoot = 0;
  189. // ---------------------------------------------------------------------------
  190. //  Local utility methods
  191. // ---------------------------------------------------------------------------
  192.   
  193. // Initialize the global "constants" (that really require use of the transcoder)
  194. void init_Globals(void) 
  195. {
  196.     typePrefixes[0] = XMLString::transcode("W_");
  197.     typePrefixes[1] = XMLString::transcode("E_");
  198.     typePrefixes[2] = XMLString::transcode("F_");
  199.     gRelativeInputPath  = XMLString::transcode("src/xercesc/NLS/");
  200. }
  201. // Release the global "constants" (that really require use of the transcoder)
  202. void release_Globals(void) 
  203. {
  204.     for(int i=0; i<3; i++) 
  205.     {
  206.         XMLString::release(&typePrefixes[i]);
  207.     }
  208.     XMLString::release(&gRelativeInputPath);
  209. }
  210. //
  211. //  This method is called to parse the parameters. They must be in this
  212. //  order and format, for simplicity:
  213. //
  214. //  /SrcRoot=xxx /OutPath=xxx /OutFmt=xxx /Locale=xxx
  215. //
  216. //static bool parseParms(const int argC, XMLCh** argV)
  217. bool parseParms(const int argC, XMLCh** argV)
  218. {
  219.     if (argC < 5)
  220.         return false;
  221.     unsigned int curParm = 1;
  222.     XMLCh *tmpXMLStr = XMLString::transcode("/SrcRoot=");
  223.     if (XMLString::startsWith(argV[curParm], tmpXMLStr))
  224.     {
  225.         gSrcRoot = &argV[curParm][9];
  226.     }
  227.      else
  228.     {
  229.         wprintf(L"nExpected /SrcRoot=xxx. Got: %sn", argV[curParm]);
  230.         XMLString::release(&tmpXMLStr);
  231.         return false;
  232.     }
  233.     XMLString::release(&tmpXMLStr);
  234.     curParm++;
  235.     tmpXMLStr = XMLString::transcode("/OutPath=");
  236.     if (XMLString::startsWith(argV[curParm], tmpXMLStr ))
  237.     {
  238.         gOutPath = &argV[curParm][9];
  239.     }
  240.      else
  241.     {
  242.         wprintf(L"nExpected /OutPath=xxx. Got: %sn", argV[curParm]);
  243.         XMLString::release(&tmpXMLStr);
  244.         return false;
  245.     }
  246.     XMLString::release(&tmpXMLStr);
  247.     curParm++;
  248.     tmpXMLStr = XMLString::transcode("/OutFmt=");
  249.     if (XMLString::startsWith(argV[curParm], tmpXMLStr ))
  250.     {
  251.         XMLString::release(&tmpXMLStr);
  252.         const XMLCh* tmpFmt = &argV[curParm][8];
  253.         tmpXMLStr = XMLString::transcode("ResBundle");
  254.         XMLCh *tmpXMLStr2 = XMLString::transcode("Win32RC");
  255.         XMLCh *tmpXMLStr3 = XMLString::transcode("CppSrc");
  256.         XMLCh *tmpXMLStr4 = XMLString::transcode("MsgCat");
  257.         if (!XMLString::compareIString(tmpFmt, tmpXMLStr ))
  258.             gOutFormat = OutFormat_ResBundle;
  259.         else if (!XMLString::compareIString(tmpFmt, tmpXMLStr2 ))
  260.             gOutFormat = OutFormat_Win32RC;
  261.         else if (!XMLString::compareIString(tmpFmt, tmpXMLStr3 ))
  262.             gOutFormat = OutFormat_CppSrc;
  263.         else if (!XMLString::compareIString(tmpFmt, tmpXMLStr4 ))
  264.             gOutFormat = OutFormat_MsgCatalog;
  265.         else
  266.         {
  267.             wprintf(L"n'%s' is not a legal output formatn", tmpFmt);
  268.             XMLString::release(&tmpXMLStr);
  269.             XMLString::release(&tmpXMLStr2);
  270.             XMLString::release(&tmpXMLStr3);
  271.             XMLString::release(&tmpXMLStr4);
  272.             return false;
  273.         }
  274.         XMLString::release(&tmpXMLStr);
  275.         XMLString::release(&tmpXMLStr2);
  276.         XMLString::release(&tmpXMLStr3);
  277.         XMLString::release(&tmpXMLStr4);
  278.     }
  279.      else
  280.     {
  281.         wprintf(L"nExpected /OutFmt=xxx. Got: %sn", argV[curParm]);
  282.         XMLString::release(&tmpXMLStr);
  283.         return false;
  284.     }
  285.     curParm++;
  286.     tmpXMLStr = XMLString::transcode("/Locale=");
  287.     if (XMLString::startsWith(argV[curParm], tmpXMLStr ))
  288.     {
  289.         gLocale = &argV[curParm][8];
  290.     }
  291.      else
  292.     {
  293.         wprintf(L"nExpected /Locale=xxx. Got: %sn", argV[curParm]);
  294.         XMLString::release(&tmpXMLStr);
  295.         return false;
  296.     }
  297.     XMLString::release(&tmpXMLStr);
  298.     return true;
  299. }
  300. //static void parseError(const XMLException& toCatch)
  301. void parseError(const XMLException& toCatch)
  302. {
  303.     wprintf
  304.     (
  305.         L"Exceptionn   (Line.File):%d.%sn   ERROR: %snn"
  306.         , toCatch.getSrcLine()
  307.         , toCatch.getSrcFile()
  308.         , toCatch.getMessage()
  309.     );
  310.     throw ErrReturn_ParseErr;
  311. }
  312. //static void parseError(const SAXParseException& toCatch)
  313. void parseError(const SAXParseException& toCatch)
  314. {
  315.     wprintf
  316.     (
  317.         L"SAX Parse Error:n   (Line.Col.SysId): %d.%d.%sn   ERROR: %snn"
  318.         , toCatch.getLineNumber()
  319.         , toCatch.getColumnNumber()
  320.         , toCatch.getSystemId()
  321.         , toCatch.getMessage()
  322.     );
  323.     throw ErrReturn_ParseErr;
  324. }
  325. //static void
  326. void
  327. enumMessages(   const   DOMElement*             srcElem
  328.                 ,       XlatFormatter* const    toCall
  329.                 ,       FILE* const             headerFl
  330.                 , const MsgTypes                msgType
  331.                 ,       unsigned int&           count)
  332. {
  333.     fwprintf
  334.     (
  335.         headerFl
  336.         , L"      , %s%-30s   = %dn"
  337.         , xmlStrToPrintable(typePrefixes[msgType]) 
  338.         , longChars("LowBounds")
  339.         , count++
  340.     );
  341.     releasePrintableStr
  342.     //
  343.     //  We just run through each of the child elements, each of which is
  344.     //  a Message element. Each one represents a message to output. We keep
  345.     //  a count so that we can output a const value afterwards.
  346.     //
  347.     DOMNode* curNode = srcElem->getFirstChild();
  348.     while (curNode)
  349.     {
  350.         // Skip over text nodes or comment nodes ect...
  351.         if (curNode->getNodeType() != DOMNode::ELEMENT_NODE)
  352.         {
  353.             curNode = curNode->getNextSibling();
  354.             continue;
  355.         }
  356.         // Convert it to an element node
  357.         const DOMElement* curElem = (const DOMElement*)curNode;
  358.         // Ok, this should be a Message node
  359.         XMLCh *tmpXMLStr = XMLString::transcode("Message");
  360.         if (XMLString::compareString(curElem->getTagName(), tmpXMLStr ))
  361.         {
  362.             wprintf(L"Expected a Message nodenn");
  363.             XMLString::release(&tmpXMLStr);
  364.             throw ErrReturn_SrcFmtError;
  365.         }
  366.         XMLString::release(&tmpXMLStr);
  367.         //
  368.         //  Ok, lets pull out the id, text value, and message type. These are
  369.         //  to be passed to the formatter. We have to translate the message
  370.         //  type into one of the offical enum values.
  371.         //
  372.         tmpXMLStr = XMLString::transcode("Text");
  373.         const XMLCh* msgText = curElem->getAttribute(tmpXMLStr );
  374.         XMLString::release(&tmpXMLStr);
  375.         tmpXMLStr = XMLString::transcode("Id");
  376.         const XMLCh* msgId   = curElem->getAttribute(tmpXMLStr );
  377.         XMLString::release(&tmpXMLStr);
  378.         //
  379.         //  Write out an entry to the target header file. These are enums, so
  380.         //  we use the id as the enum name.
  381.         //
  382.         fwprintf(headerFl, L"      , %-32s   = %dn", xmlStrToPrintable(msgId), count);
  383.         releasePrintableStr
  384.         // And tell the formatter about this one
  385.         toCall->nextMessage
  386.         (
  387.             msgText
  388.             , msgId
  389.             , count
  390.             , count
  391.         );
  392.         // Bump the counter, which is also the id assigner
  393.         count++;
  394.         // Move to the next child of the source element
  395.         curNode = curNode->getNextSibling();
  396.     }
  397.     // Write out an upper range bracketing id for this type of error
  398.     fwprintf
  399.     (
  400.         headerFl
  401.         , L"      , %s%-30s   = %dn"
  402.         , xmlStrToPrintable(typePrefixes[msgType])
  403.         , longChars("HighBounds")
  404.         , count++
  405.     );
  406.     releasePrintableStr
  407. }
  408. // ---------------------------------------------------------------------------
  409. //  Program entry point
  410. // ---------------------------------------------------------------------------
  411. //
  412. //  This is the program entry point. It checks the parms, parses the input
  413. //  file to get a DOM tree, then passes the DOM tree to the appropriate
  414. //  output method to output the info in a particular format.
  415. //
  416. int Xlat_main(int argC, XMLCh** argV);
  417. int main (int argC, char** argV) {
  418.     try
  419.     {
  420.         XMLPlatformUtils::Initialize();
  421.     }
  422.     catch(const XMLException& toCatch)
  423.     {
  424.         wprintf(L"Parser init error.n  ERROR: %snn", toCatch.getMessage());
  425.         return ErrReturn_ParserInit;
  426.     }
  427.     
  428.     XMLCh** newArgV = new XMLCh*[argC];
  429.     for(int i=0;i<argC; i++) 
  430.     {
  431.         newArgV[i] = XMLString::transcode(argV[i]);
  432.     }
  433.     int toReturn = (Xlat_main(argC,newArgV));
  434.     for (int i=0; i<argC; i++) 
  435.     {
  436.         delete [] newArgV[i];
  437.     }
  438.     delete [] newArgV;
  439.     return toReturn;
  440. }
  441. int Xlat_main(int argC, XMLCh** argV)
  442. {
  443.     init_Globals();
  444.     //
  445.     //  Lets check the parameters and save them away in globals for use by
  446.     //  the processing code.
  447.     //
  448.     if (!parseParms(argC, argV))
  449.     {
  450.         wprintf(L"Usage:n  NLSXlat /SrcRoot=xx /OutPath=xx /OutFmt=xx /Locale=xxnn");
  451.         return ErrReturn_BadParameters;
  452.     }
  453.     {
  454.         //  Nest entire code in an inner block.
  455.         DOMDocument* srcDoc;
  456.         const unsigned int bufSize = 4095;
  457.         XMLCh *tmpFileBuf = new XMLCh [bufSize + 1];
  458.         tmpFileBuf[0] = 0;
  459.         XMLCh *tmpXMLStr = XMLString::transcode("/XMLErrList_");
  460.         XMLCh *tmpXMLStr2 = XMLString::transcode(".Xml");
  461.         try
  462.         {
  463.             try
  464.             {
  465.                 // Build the input file name
  466.                 XMLString::catString(tmpFileBuf, gSrcRoot);
  467.                 XMLString::catString(tmpFileBuf, gRelativeInputPath);
  468.                 XMLString::catString(tmpFileBuf, gLocale);
  469.                 XMLString::catString(tmpFileBuf, tmpXMLStr );
  470.                 XMLString::catString(tmpFileBuf, gLocale);
  471.                 XMLString::catString(tmpFileBuf, tmpXMLStr2 );
  472.                 XMLString::release(&tmpXMLStr);
  473.                 XMLString::release(&tmpXMLStr2);
  474.                 //
  475.                 //  Ok, lets invoke the DOM parser on the input file and build
  476.                 //  a DOM tree. Turn on validation when we do this.
  477.                 //
  478.                 XercesDOMParser parser;
  479.                 parser.setDoValidation(true);
  480.                 XlatErrHandler errHandler;
  481.                 parser.setErrorHandler(&errHandler);
  482.                 parser.parse(tmpFileBuf);
  483.                 srcDoc = parser.adoptDocument();
  484.             }
  485.             catch(const XMLException& toCatch)
  486.             {
  487.                 parseError(toCatch);
  488.             }
  489.             XMLString::release(&tmpFileBuf);
  490.             //
  491.             //  Use the output format parm to create the correct kind of output
  492.             //  formatter.
  493.             //
  494.             XlatFormatter* formatter = 0;
  495.             switch(gOutFormat)
  496.             {
  497.                 case OutFormat_CppSrc :
  498.                     formatter = new CppSrcFormatter;
  499.                     break;
  500.                 case OutFormat_Win32RC :
  501.                     formatter = new Win32RCFormatter;
  502.                     break;
  503.                 case OutFormat_MsgCatalog :
  504.                     formatter = new MsgCatFormatter;
  505.                     break;
  506.                 case OutFormat_ResBundle:
  507.                     formatter = new ICUResBundFormatter;
  508.                     break;
  509.                 default :
  510.                     wprintf(L"Unknown formatter type enumnn");
  511.                     throw ErrReturn_Internal;
  512.             }
  513.             //
  514.             //  Lets handle the root element stuff first. This one holds any over
  515.             //  all information.
  516.             //
  517.             DOMElement* rootElem = srcDoc->getDocumentElement();
  518.             tmpXMLStr = XMLString::transcode("Locale");
  519.             const XMLCh* localeStr = rootElem->getAttribute(tmpXMLStr);
  520.             XMLString::release(&tmpXMLStr);
  521.             // Make sure that the locale matches what we were given
  522.             if (XMLString::compareString(localeStr, gLocale))
  523.             {
  524.                 wprintf(L"The file's locale does not match the target localen");
  525.                 throw ErrReturn_LocaleErr;
  526.             }
  527.             //
  528.             //  Get a list of all the MsgDomain children. These each hold one of
  529.             //  the sets of (potentially separately) loadable messages. More
  530.             //  importantly they all have their own error id space.
  531.             //
  532.             tmpXMLStr = XMLString::transcode("MsgDomain");
  533.             DOMNodeList* msgSetList = rootElem->getElementsByTagName(tmpXMLStr);
  534.             XMLString::release(&tmpXMLStr);
  535.             //
  536.             //  Loop through them and look for the domains that we know are
  537.             //  supposed to be there.
  538.             //
  539.             const unsigned int count = msgSetList->getLength();
  540.             //
  541.             // Normalize locale string
  542.             //
  543.             // locale = ll[[_CC][_VARIANT]]
  544.             // where ll          is language code
  545.             //       CC          is country code
  546.             //       VARIANT     is variant code
  547.             //
  548.             XMLCh normalizedLocale[256];
  549.             normalizedLocale[0] = localeStr[0];
  550.             normalizedLocale[1] = localeStr[1];
  551.             normalizedLocale[2] = 0;
  552.             XMLString::lowerCase(normalizedLocale);
  553.             if (XMLString::stringLen(localeStr) > 2)
  554.             {
  555.                 XMLString::catString(&(normalizedLocale[2]), &(localeStr[2]));
  556.                 XMLString::upperCase(&(normalizedLocale[2]));
  557.             }
  558.             //
  559.             //  Ok, its good enough to get started. So lets call the start output
  560.             //  method on the formatter.
  561.             //
  562.     
  563.             formatter->startOutput(normalizedLocale, gOutPath);
  564.             //
  565.             //  For each message domain element, we call start and end domain
  566.             //  events bracketed around the loop that sends out each message
  567.             //  in that domain.
  568.             //
  569.             //  Within each domain, we check for the Warning, Error, and Validity
  570.             //  subelements, and then iterate all the messages in each one.
  571.             //
  572.             for (unsigned int index = 0; index < count; index++)
  573.             {
  574.                 // We know its a DOM Element, so go ahead and cast it
  575.                 DOMNode* curNode = msgSetList->item(index);
  576.                 const DOMElement* curElem = (const DOMElement*)curNode;
  577.                 //
  578.                 //  Get some of  the attribute strings that we need, and transcode
  579.                 //  couple that need to be in local format.
  580.                 //
  581.                 tmpXMLStr = XMLString::transcode("Domain");
  582.                 const XMLCh* domainStr = curElem->getAttribute(tmpXMLStr );
  583.                 XMLString::release(&tmpXMLStr);
  584.                 //
  585.                 //  Look at the domain and set up our application specific info
  586.                 //  that is on a per-domain basis. We need to indicate what the
  587.                 //  name of the header is and what the namespace is that they
  588.                 //  codes will go into
  589.                 //
  590.                 XMLCh* headerName = 0;
  591.                 XMLCh* errNameSpace = 0;
  592.                 if (!XMLString::compareString(domainStr, XMLUni::fgXMLErrDomain))
  593.                 {
  594.                     headerName = XMLString::transcode("XMLErrorCodes.hpp");
  595.                     errNameSpace = XMLString::transcode("XMLErrs");
  596.                 }
  597.                  else if (!XMLString::compareString(domainStr, XMLUni::fgValidityDomain))
  598.                 {
  599.                     headerName = XMLString::transcode("XMLValidityCodes.hpp");
  600.                     errNameSpace = XMLString::transcode("XMLValid");
  601.                 }
  602.                  else if (!XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
  603.                 {
  604.                     headerName = XMLString::transcode("XMLExceptMsgs.hpp");
  605.                     errNameSpace = XMLString::transcode("XMLExcepts");
  606.                 }
  607.                  else if (!XMLString::compareString(domainStr, XMLUni::fgXMLDOMMsgDomain))
  608.                 {
  609.                     headerName = XMLString::transcode("XMLDOMMsg.hpp");
  610.                     errNameSpace = XMLString::transcode("XMLDOMMsg");
  611.                 }
  612.                  else
  613.                 {
  614.                     // Not one of ours, so skip it
  615.                     continue;
  616.                 }
  617.                 //
  618.                 //  Lets try to create the header file that was indicated for
  619.                 //  this domain.
  620.                 //
  621.                 tmpFileBuf = new XMLCh [bufSize + 1];
  622.                 tmpFileBuf[0] = 0;
  623.                 XMLString::catString(tmpFileBuf, gOutPath);
  624.                 XMLString::catString(tmpFileBuf, headerName);
  625.                 char *tmpFileBufCh = XMLString::transcode(tmpFileBuf);                
  626.                 FILE* outHeader = fopen(tmpFileBufCh, "wt+");
  627.                 XMLString::release(&tmpFileBufCh);
  628.                 if ((!outHeader) || (fwide(outHeader, 1) < 0)) 
  629.                 {
  630.                     wprintf(L"Could not open domain header file: %snn", xmlStrToPrintable(tmpFileBuf));
  631.                     releasePrintableStr
  632.                     XMLString::release(&tmpFileBuf);
  633.                     XMLString::release(&headerName);
  634.                     XMLString::release(&errNameSpace);
  635.                     throw ErrReturn_OutFileOpenFailed;
  636.                 }
  637.                 XMLString::release(&tmpFileBuf);                
  638.                 //
  639.                 //  Write out the opening of the class they are nested within, and
  640.                 //  the header protection define.
  641.                 //                
  642.                 fwprintf(outHeader, L"// This file is generated, don't edit it!!nn");
  643.                 fwprintf(outHeader, L"#if !defined(ERRHEADER_%s)n", xmlStrToPrintable(errNameSpace) );
  644.                 fwprintf(outHeader, L"#define ERRHEADER_%snn", xmlStrToPrintable(errNameSpace) );
  645.                 releasePrintableStr
  646.                 // If its not the exception domain, then we need a header included
  647.                 if (XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
  648.                     fwprintf(outHeader, L"#include <xercesc/framework/XMLErrorReporter.hpp>n");
  649.                 //  Write out the namespace declaration
  650.                 fwprintf(outHeader, L"#include <xercesc/util/XercesDefs.hpp>n");
  651.                 fwprintf(outHeader, L"#include <xercesc/dom/DOMError.hpp>nn");
  652.                 fwprintf(outHeader, L"XERCES_CPP_NAMESPACE_BEGINnn");
  653.                 //  Now the message codes
  654.                 fwprintf(outHeader, L"class %sn{npublic :n    enum Codesn    {n", xmlStrToPrintable(errNameSpace) );
  655.                 releasePrintableStr
  656.                 // Tell the formatter that a new domain is starting
  657.                 formatter->startDomain
  658.                 (
  659.                     domainStr
  660.                     , errNameSpace
  661.                 );
  662.                 //
  663.                 //  Force out the first message, which is always implicit and is
  664.                 //  the 'no error' entry for that domain.
  665.                 //
  666.                 unsigned int count = 0;
  667.                 fwprintf(outHeader, L"        %-32s   = %dn", longChars("NoError"), count++);
  668.                 //
  669.                 //  Loop through the children of this node, which should take us
  670.                 //  through the optional Warning, Error, and Validity subsections.
  671.                 //
  672.                 DOMNode* typeNode = curElem->getFirstChild();
  673.                 bool typeGotten[3] = { false, false, false };
  674.                 while (typeNode)
  675.                 {
  676.                     // Skip over text nodes or comment nodes ect...
  677.                     if (typeNode->getNodeType() != DOMNode::ELEMENT_NODE)
  678.                     {
  679.                         typeNode = typeNode->getNextSibling();
  680.                         continue;
  681.                     }
  682.                     // Convert it to an element node
  683.                     const DOMElement* typeElem = (const DOMElement*)typeNode;
  684.                     // Now get its tag name and convert that to a message type enum
  685.                     const XMLCh* typeName = typeElem->getTagName();
  686.                     MsgTypes type;
  687.                     tmpXMLStr = XMLString::transcode("Warning");
  688.                     XMLCh* tmpXMLStr2 = XMLString::transcode("Error");
  689.                     XMLCh* tmpXMLStr3 =XMLString::transcode("FatalError");
  690.                     if (!XMLString::compareString(typeName, tmpXMLStr ))
  691.                     {
  692.                         type = MsgType_Warning;
  693.                         typeGotten[0] = true;
  694.                     }
  695.                      else if (!XMLString::compareString(typeName, tmpXMLStr2 ))
  696.                     {
  697.                         type = MsgType_Error;
  698.                         typeGotten[1] = true;
  699.                     }
  700.                      else if (!XMLString::compareString(typeName, tmpXMLStr3 ))
  701.                     {
  702.                         type = MsgType_FatalError;
  703.                         typeGotten[2] = true;
  704.                     }
  705.                      else
  706.                     {
  707.                         wprintf(L"Expected a Warning, Error, or FatalError nodenn");
  708.                         XMLString::release(&tmpXMLStr);
  709.                         XMLString::release(&tmpXMLStr2);
  710.                         XMLString::release(&tmpXMLStr3);
  711.                         throw ErrReturn_SrcFmtError;
  712.                     }
  713.                     XMLString::release(&tmpXMLStr);
  714.                     XMLString::release(&tmpXMLStr2);
  715.                     XMLString::release(&tmpXMLStr3);
  716.                     // Call the start message type event
  717.                     formatter->startMsgType(type);
  718.                     // Enumerate the messages under this subsection
  719.                     enumMessages
  720.                     (
  721.                         typeElem
  722.                         , formatter
  723.                         , outHeader
  724.                         , type
  725.                         , count
  726.                     );
  727.                     // Call the end message type event
  728.                     formatter->endMsgType(type);
  729.                     // Move to the next child of the source element
  730.                     typeNode = typeNode->getNextSibling();
  731.                 }
  732.                 //
  733.                 //  For any that we did not get, spit out faux boundary
  734.                 //  values for it.
  735.                 //
  736.                 for (unsigned int subIndex = 0; subIndex < 3; subIndex++)
  737.                 {
  738.                     if (!typeGotten[subIndex])
  739.                     {
  740.                         fwprintf
  741.                         (
  742.                             outHeader
  743.                             , L"      , %s%-30s   = %dn"
  744.                             , xmlStrToPrintable(typePrefixes[subIndex]) 
  745.                             , longChars("LowBounds")
  746.                             , count++
  747.                         );
  748.                         releasePrintableStr
  749.                         fwprintf
  750.                         (
  751.                             outHeader
  752.                             , L"      , %s%-30s   = %dn"
  753.                             , xmlStrToPrintable(typePrefixes[subIndex]) 
  754.                             , longChars("HighBounds")
  755.                             , count++
  756.                         );
  757.                         releasePrintableStr
  758.                     }
  759.                 }
  760.                 // Tell the formatter that this domain is ending
  761.                 formatter->endDomain(domainStr, count);
  762.                 // Close out the enum declaration
  763.                 fwprintf(outHeader, L"    };nn");
  764.                 //
  765.                 //  Generate the code that creates the simple static methods
  766.                 //  for testing the error types. We don't do this for the
  767.                 //  exceptions header.
  768.                 //
  769.                 if (XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
  770.                 {
  771.                     fwprintf
  772.                     (
  773.                         outHeader
  774.                         , L"    static bool isFatal(const %s::Codes toCheck)n"
  775.                           L"    {n"
  776.                           L"        return ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds));n"
  777.                           L"    }nn"
  778.                         , xmlStrToPrintable(errNameSpace) 
  779.                     );
  780.                     releasePrintableStr
  781.                     fwprintf
  782.                     (
  783.                         outHeader
  784.                         , L"    static bool isWarning(const %s::Codes toCheck)n"
  785.                           L"    {n"
  786.                           L"        return ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds));n"
  787.                           L"    }nn"
  788.                         , xmlStrToPrintable(errNameSpace) 
  789.                     );
  790.                     releasePrintableStr
  791.                     fwprintf
  792.                     (
  793.                         outHeader
  794.                         , L"    static bool isError(const %s::Codes toCheck)n"
  795.                           L"    {n"
  796.                           L"        return ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds));n"
  797.                           L"    }nn"
  798.                         , xmlStrToPrintable(errNameSpace) 
  799.                     );
  800.                     releasePrintableStr
  801.                     fwprintf
  802.                     (
  803.                         outHeader
  804.                         , L"    static XMLErrorReporter::ErrTypes errorType(const %s::Codes toCheck)n"
  805.                           L"    {n"
  806.                           L"       if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds))n"
  807.                           L"           return XMLErrorReporter::ErrType_Warning;n"
  808.                           L"       else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds))n"
  809.                           L"            return XMLErrorReporter::ErrType_Fatal;n"
  810.                           L"       else if ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds))n"
  811.                           L"            return XMLErrorReporter::ErrType_Error;n"
  812.                           L"       return XMLErrorReporter::ErrTypes_Unknown;n"
  813.                           L"    }n"
  814.                         , xmlStrToPrintable(errNameSpace)
  815.                     );
  816.                     releasePrintableStr
  817.                     fwprintf
  818.                     (
  819.                         outHeader
  820.                         , L"    static DOMError::ErrorSeverity  DOMErrorType(const %s::Codes toCheck)n"
  821.                           L"    {n"
  822.                           L"       if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds))n"
  823.                           L"           return DOMError::DOM_SEVERITY_WARNING;n"
  824.                           L"       else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds))n"
  825.                           L"            return DOMError::DOM_SEVERITY_FATAL_ERROR;n"
  826.                           L"       else return DOMError::DOM_SEVERITY_ERROR;n"
  827.                           L"    }n"
  828.                         , xmlStrToPrintable(errNameSpace)
  829.                     );
  830.                     releasePrintableStr
  831.                 }
  832.                 // And close out the class declaration, the namespace declaration and the header file
  833.                 fwprintf(outHeader, L"};nn");
  834.                 fwprintf(outHeader, L"XERCES_CPP_NAMESPACE_ENDnn");
  835.                 fwprintf(outHeader, L"#endifnn");
  836.                 fclose(outHeader);
  837.                 XMLString::release(&headerName);
  838.                 XMLString::release(&errNameSpace);
  839.             }
  840.             // Ok, we are done so call the end output method
  841.             formatter->endOutput();
  842.             // And clean up the stuff we allocated
  843.             delete formatter;
  844.         }
  845.         catch(const ErrReturns retVal)
  846.         {
  847.             // And call the termination method
  848.             if(srcDoc)
  849.                 delete srcDoc;
  850.             XMLPlatformUtils::Terminate();
  851.             return retVal;
  852.         }
  853.         delete srcDoc;
  854.     }
  855.     // And call the termination method
  856.     release_Globals();
  857.     XMLPlatformUtils::Terminate();
  858.     // Went ok, so return success
  859.     return ErrReturn_Success;
  860. }
  861. // -----------------------------------------------------------------------
  862. //  XlatErrHandler: Implementation of the error handler interface
  863. // -----------------------------------------------------------------------
  864. void XlatErrHandler::warning(const SAXParseException& toCatch)
  865. {
  866.     parseError(toCatch);
  867. }
  868. void XlatErrHandler::error(const SAXParseException& toCatch)
  869. {
  870.     parseError(toCatch);
  871. }
  872. void XlatErrHandler::fatalError(const SAXParseException& toCatch)
  873. {
  874.     parseError(toCatch);
  875. }
  876. void XlatErrHandler::resetErrors()
  877. {
  878. }
  879. // if longChars is a macro, don't bother
  880. #ifndef longChars
  881.     wchar_t* longChars(const char *str) 
  882.     {
  883.         mbstowcs(fTmpWStr, str, 255);
  884.         return (fTmpWStr);
  885.     }
  886. #endif