You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

902 lines
33 KiB

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /*
  18. * $Id: Xlat.cpp 676911 2008-07-15 13:27:32Z amassari $
  19. */
  20. // ---------------------------------------------------------------------------
  21. // This program is designed to parse an XML file which holds error text
  22. // data. It will build a DOM tree from that source file and can output it
  23. // a number of different formats.
  24. //
  25. // In order to drastically simplify the program, it is designed only to run
  26. // on platforms/compilers that understand Unicode. It can output the data
  27. // in whatever format is required, so it can handle outputting for other
  28. // platforms. This also simplifies bootstrapping new releases up on other
  29. // platforms. Once the Win32 version is working, it can generate output for
  30. // the other platforms so that they can have loadable text from day one.
  31. // ---------------------------------------------------------------------------
  32. // ---------------------------------------------------------------------------
  33. // Includes
  34. // ---------------------------------------------------------------------------
  35. #include "Xlat.hpp"
  36. // ---------------------------------------------------------------------------
  37. // Static data
  38. //
  39. // gRelativeInputPath
  40. // This is the path, relative to the given input source root, to the
  41. // input file. The given local suffix must also be added to it.
  42. // ---------------------------------------------------------------------------
  43. XMLCh* gRelativeInputPath = 0;
  44. // ---------------------------------------------------------------------------
  45. // Global data
  46. // ---------------------------------------------------------------------------
  47. XMLCh* typePrefixes[MsgTypes_Count];
  48. // ---------------------------------------------------------------------------
  49. // temporary variables/conversion utility functions
  50. // We need different temps depending on treatment of wide characters
  51. // ---------------------------------------------------------------------------
  52. #ifdef longChars
  53. char* fTmpStr = 0;
  54. #else
  55. wchar_t fTmpWStr[256];
  56. #endif
  57. // ---------------------------------------------------------------------------
  58. // Local data
  59. //
  60. // gLocale
  61. // This is the locale suffix, e.g. US_EN, that is used to find the
  62. // correct file and can be used on output files as well. Its set via
  63. // the /Locale= parameter.
  64. //
  65. // gOutFormat
  66. // This is the output format, which is given on the command line as
  67. // /OutFmt= Its mapped to the internal enum which is stored here.
  68. //
  69. // gOutPath
  70. // This is the path to the output path, which is given on the command
  71. // line as /OutPath=. Its just the path, not a name, since the output
  72. // might consist of multiple output files. They will all be based on
  73. // the base part of the input name.
  74. //
  75. // gSrcRoot
  76. // This the path to the root of the build tree. The input files needed
  77. // are found in known places relative to it.
  78. // ---------------------------------------------------------------------------
  79. const XMLCh* gLocale = 0;
  80. OutFormats gOutFormat = OutFormat_Unknown;
  81. const XMLCh* gOutPath = 0;
  82. const XMLCh* gSrcRoot = 0;
  83. // ---------------------------------------------------------------------------
  84. // Local utility methods
  85. // ---------------------------------------------------------------------------
  86. // Initialize the global "constants" (that really require use of the transcoder)
  87. void init_Globals(void)
  88. {
  89. typePrefixes[0] = XMLString::transcode("W_");
  90. typePrefixes[1] = XMLString::transcode("E_");
  91. typePrefixes[2] = XMLString::transcode("F_");
  92. gRelativeInputPath = XMLString::transcode("src/xercesc/NLS/");
  93. }
  94. // Release the global "constants" (that really require use of the transcoder)
  95. void release_Globals(void)
  96. {
  97. for(int i=0; i<3; i++)
  98. {
  99. XMLString::release(&typePrefixes[i]);
  100. }
  101. XMLString::release(&gRelativeInputPath);
  102. }
  103. //
  104. // This method is called to parse the parameters. They must be in this
  105. // order and format, for simplicity:
  106. //
  107. // /SrcRoot=xxx /OutPath=xxx /OutFmt=xxx /Locale=xxx
  108. //
  109. //static bool parseParms(const int argC, XMLCh** argV)
  110. bool parseParms(const int argC, XMLCh** argV)
  111. {
  112. if (argC < 5)
  113. return false;
  114. unsigned int curParm = 1;
  115. XMLCh *tmpXMLStr = XMLString::transcode("/SrcRoot=");
  116. if (XMLString::startsWith(argV[curParm], tmpXMLStr))
  117. {
  118. gSrcRoot = &argV[curParm][9];
  119. }
  120. else
  121. {
  122. wprintf(L"\nExpected /SrcRoot=xxx. Got: %s\n", argV[curParm]);
  123. XMLString::release(&tmpXMLStr);
  124. return false;
  125. }
  126. XMLString::release(&tmpXMLStr);
  127. curParm++;
  128. tmpXMLStr = XMLString::transcode("/OutPath=");
  129. if (XMLString::startsWith(argV[curParm], tmpXMLStr ))
  130. {
  131. gOutPath = &argV[curParm][9];
  132. }
  133. else
  134. {
  135. wprintf(L"\nExpected /OutPath=xxx. Got: %s\n", argV[curParm]);
  136. XMLString::release(&tmpXMLStr);
  137. return false;
  138. }
  139. XMLString::release(&tmpXMLStr);
  140. curParm++;
  141. tmpXMLStr = XMLString::transcode("/OutFmt=");
  142. if (XMLString::startsWith(argV[curParm], tmpXMLStr ))
  143. {
  144. XMLString::release(&tmpXMLStr);
  145. const XMLCh* tmpFmt = &argV[curParm][8];
  146. tmpXMLStr = XMLString::transcode("ResBundle");
  147. XMLCh *tmpXMLStr2 = XMLString::transcode("Win32RC");
  148. XMLCh *tmpXMLStr3 = XMLString::transcode("CppSrc");
  149. XMLCh *tmpXMLStr4 = XMLString::transcode("MsgCat");
  150. if (!XMLString::compareIString(tmpFmt, tmpXMLStr ))
  151. gOutFormat = OutFormat_ResBundle;
  152. else if (!XMLString::compareIString(tmpFmt, tmpXMLStr2 ))
  153. gOutFormat = OutFormat_Win32RC;
  154. else if (!XMLString::compareIString(tmpFmt, tmpXMLStr3 ))
  155. gOutFormat = OutFormat_CppSrc;
  156. else if (!XMLString::compareIString(tmpFmt, tmpXMLStr4 ))
  157. gOutFormat = OutFormat_MsgCatalog;
  158. else
  159. {
  160. wprintf(L"\n'%s' is not a legal output format\n", tmpFmt);
  161. XMLString::release(&tmpXMLStr);
  162. XMLString::release(&tmpXMLStr2);
  163. XMLString::release(&tmpXMLStr3);
  164. XMLString::release(&tmpXMLStr4);
  165. return false;
  166. }
  167. XMLString::release(&tmpXMLStr);
  168. XMLString::release(&tmpXMLStr2);
  169. XMLString::release(&tmpXMLStr3);
  170. XMLString::release(&tmpXMLStr4);
  171. }
  172. else
  173. {
  174. wprintf(L"\nExpected /OutFmt=xxx. Got: %s\n", argV[curParm]);
  175. XMLString::release(&tmpXMLStr);
  176. return false;
  177. }
  178. curParm++;
  179. tmpXMLStr = XMLString::transcode("/Locale=");
  180. if (XMLString::startsWith(argV[curParm], tmpXMLStr ))
  181. {
  182. gLocale = &argV[curParm][8];
  183. }
  184. else
  185. {
  186. wprintf(L"\nExpected /Locale=xxx. Got: %s\n", argV[curParm]);
  187. XMLString::release(&tmpXMLStr);
  188. return false;
  189. }
  190. XMLString::release(&tmpXMLStr);
  191. return true;
  192. }
  193. //static void parseError(const XMLException& toCatch)
  194. void parseError(const XMLException& toCatch)
  195. {
  196. wprintf
  197. (
  198. L"Exception\n (Line.File):%d.%s\n ERROR: %s\n\n"
  199. , toCatch.getSrcLine()
  200. , toCatch.getSrcFile()
  201. , toCatch.getMessage()
  202. );
  203. throw ErrReturn_ParseErr;
  204. }
  205. //static void parseError(const SAXParseException& toCatch)
  206. void parseError(const SAXParseException& toCatch)
  207. {
  208. wprintf
  209. (
  210. L"SAX Parse Error:\n (Line.Col.SysId): %d.%d.%s\n ERROR: %s\n\n"
  211. , toCatch.getLineNumber()
  212. , toCatch.getColumnNumber()
  213. , toCatch.getSystemId()
  214. , toCatch.getMessage()
  215. );
  216. throw ErrReturn_ParseErr;
  217. }
  218. //static void
  219. void
  220. enumMessages( const DOMElement* srcElem
  221. , XlatFormatter* const toCall
  222. , FILE* const headerFl
  223. , const MsgTypes msgType
  224. , unsigned int& count)
  225. {
  226. fwprintf
  227. (
  228. headerFl
  229. , L" , %s%-30s = %d\n"
  230. , xmlStrToPrintable(typePrefixes[msgType])
  231. , longChars("LowBounds")
  232. , count++
  233. );
  234. releasePrintableStr
  235. //
  236. // We just run through each of the child elements, each of which is
  237. // a Message element. Each one represents a message to output. We keep
  238. // a count so that we can output a const value afterwards.
  239. //
  240. DOMNode* curNode = srcElem->getFirstChild();
  241. while (curNode)
  242. {
  243. // Skip over text nodes or comment nodes ect...
  244. if (curNode->getNodeType() != DOMNode::ELEMENT_NODE)
  245. {
  246. curNode = curNode->getNextSibling();
  247. continue;
  248. }
  249. // Convert it to an element node
  250. const DOMElement* curElem = (const DOMElement*)curNode;
  251. // Ok, this should be a Message node
  252. XMLCh *tmpXMLStr = XMLString::transcode("Message");
  253. if (XMLString::compareString(curElem->getTagName(), tmpXMLStr ))
  254. {
  255. wprintf(L"Expected a Message node\n\n");
  256. XMLString::release(&tmpXMLStr);
  257. throw ErrReturn_SrcFmtError;
  258. }
  259. XMLString::release(&tmpXMLStr);
  260. //
  261. // Ok, lets pull out the id, text value, and message type. These are
  262. // to be passed to the formatter. We have to translate the message
  263. // type into one of the offical enum values.
  264. //
  265. tmpXMLStr = XMLString::transcode("Text");
  266. const XMLCh* msgText = curElem->getAttribute(tmpXMLStr );
  267. XMLString::release(&tmpXMLStr);
  268. tmpXMLStr = XMLString::transcode("Id");
  269. const XMLCh* msgId = curElem->getAttribute(tmpXMLStr );
  270. XMLString::release(&tmpXMLStr);
  271. //
  272. // Write out an entry to the target header file. These are enums, so
  273. // we use the id as the enum name.
  274. //
  275. if (XMLString::stringLen(msgText) >= 128) {
  276. wprintf(L"Message text '%s' is too long (%d chars), 128 character limit\n\n", xmlStrToPrintable(msgText),XMLString::stringLen(msgText));
  277. throw ErrReturn_SrcFmtError;
  278. }
  279. fwprintf(headerFl, L" , %-32s = %d\n", xmlStrToPrintable(msgId), count);
  280. releasePrintableStr
  281. // And tell the formatter about this one
  282. toCall->nextMessage
  283. (
  284. msgText
  285. , msgId
  286. , count
  287. , count
  288. );
  289. // Bump the counter, which is also the id assigner
  290. count++;
  291. // Move to the next child of the source element
  292. curNode = curNode->getNextSibling();
  293. }
  294. // Write out an upper range bracketing id for this type of error
  295. fwprintf
  296. (
  297. headerFl
  298. , L" , %s%-30s = %d\n"
  299. , xmlStrToPrintable(typePrefixes[msgType])
  300. , longChars("HighBounds")
  301. , count++
  302. );
  303. releasePrintableStr
  304. }
  305. // ---------------------------------------------------------------------------
  306. // Program entry point
  307. // ---------------------------------------------------------------------------
  308. //
  309. // This is the program entry point. It checks the parms, parses the input
  310. // file to get a DOM tree, then passes the DOM tree to the appropriate
  311. // output method to output the info in a particular format.
  312. //
  313. int Xlat_main(int argC, XMLCh** argV);
  314. int main (int argC, char** argV) {
  315. try
  316. {
  317. XMLPlatformUtils::Initialize();
  318. }
  319. catch(const XMLException& toCatch)
  320. {
  321. wprintf(L"Parser init error.\n ERROR: %s\n\n", toCatch.getMessage());
  322. return ErrReturn_ParserInit;
  323. }
  324. int i;
  325. XMLCh** newArgV = new XMLCh*[argC];
  326. for(i=0;i<argC; i++)
  327. {
  328. newArgV[i] = XMLString::transcode(argV[i]);
  329. }
  330. int toReturn = (Xlat_main(argC,newArgV));
  331. for (i=0; i<argC; i++)
  332. {
  333. XMLString::release(&newArgV[i]);
  334. }
  335. delete [] newArgV;
  336. XMLPlatformUtils::Terminate();
  337. return toReturn;
  338. }
  339. int Xlat_main(int argC, XMLCh** argV)
  340. {
  341. init_Globals();
  342. //
  343. // Lets check the parameters and save them away in globals for use by
  344. // the processing code.
  345. //
  346. if (!parseParms(argC, argV))
  347. {
  348. wprintf(L"Usage:\n NLSXlat /SrcRoot=xx /OutPath=xx /OutFmt=xx /Locale=xx\n\n");
  349. return ErrReturn_BadParameters;
  350. }
  351. {
  352. // Nest entire code in an inner block.
  353. DOMDocument* srcDoc;
  354. const unsigned int bufSize = 4095;
  355. XMLCh *tmpFileBuf = new XMLCh [bufSize + 1];
  356. tmpFileBuf[0] = 0;
  357. XMLCh *tmpXMLStr = XMLString::transcode("/XMLErrList_");
  358. XMLCh *tmpXMLStr2 = XMLString::transcode(".Xml");
  359. try
  360. {
  361. try
  362. {
  363. // Build the input file name
  364. XMLString::catString(tmpFileBuf, gSrcRoot);
  365. XMLString::catString(tmpFileBuf, gRelativeInputPath);
  366. XMLString::catString(tmpFileBuf, gLocale);
  367. XMLString::catString(tmpFileBuf, tmpXMLStr );
  368. XMLString::catString(tmpFileBuf, gLocale);
  369. XMLString::catString(tmpFileBuf, tmpXMLStr2 );
  370. XMLString::release(&tmpXMLStr);
  371. XMLString::release(&tmpXMLStr2);
  372. //
  373. // Ok, lets invoke the DOM parser on the input file and build
  374. // a DOM tree. Turn on validation when we do this.
  375. //
  376. XercesDOMParser parser;
  377. parser.setValidationScheme(AbstractDOMParser::Val_Always);
  378. XlatErrHandler errHandler;
  379. parser.setErrorHandler(&errHandler);
  380. parser.parse(tmpFileBuf);
  381. srcDoc = parser.adoptDocument();
  382. }
  383. catch(const XMLException& toCatch)
  384. {
  385. parseError(toCatch);
  386. }
  387. delete tmpFileBuf;
  388. //
  389. // Use the output format parm to create the correct kind of output
  390. // formatter.
  391. //
  392. XlatFormatter* formatter = 0;
  393. switch(gOutFormat)
  394. {
  395. case OutFormat_CppSrc :
  396. formatter = new CppSrcFormatter;
  397. break;
  398. case OutFormat_Win32RC :
  399. formatter = new Win32RCFormatter;
  400. break;
  401. case OutFormat_MsgCatalog :
  402. formatter = new MsgCatFormatter;
  403. break;
  404. case OutFormat_ResBundle:
  405. formatter = new ICUResBundFormatter;
  406. break;
  407. default :
  408. wprintf(L"Unknown formatter type enum\n\n");
  409. throw ErrReturn_Internal;
  410. }
  411. //
  412. // Lets handle the root element stuff first. This one holds any over
  413. // all information.
  414. //
  415. DOMElement* rootElem = srcDoc->getDocumentElement();
  416. tmpXMLStr = XMLString::transcode("Locale");
  417. const XMLCh* localeStr = rootElem->getAttribute(tmpXMLStr);
  418. XMLString::release(&tmpXMLStr);
  419. // Make sure that the locale matches what we were given
  420. if (XMLString::compareString(localeStr, gLocale))
  421. {
  422. wprintf(L"The file's locale does not match the target locale\n");
  423. throw ErrReturn_LocaleErr;
  424. }
  425. //
  426. // Get a list of all the MsgDomain children. These each hold one of
  427. // the sets of (potentially separately) loadable messages. More
  428. // importantly they all have their own error id space.
  429. //
  430. tmpXMLStr = XMLString::transcode("MsgDomain");
  431. DOMNodeList* msgSetList = rootElem->getElementsByTagName(tmpXMLStr);
  432. XMLString::release(&tmpXMLStr);
  433. //
  434. // Loop through them and look for the domains that we know are
  435. // supposed to be there.
  436. //
  437. const XMLSize_t count = msgSetList->getLength();
  438. //
  439. // Normalize locale string
  440. //
  441. // locale = ll[[_CC][_VARIANT]]
  442. // where ll is language code
  443. // CC is country code
  444. // VARIANT is variant code
  445. //
  446. XMLCh normalizedLocale[256];
  447. normalizedLocale[0] = localeStr[0];
  448. normalizedLocale[1] = localeStr[1];
  449. normalizedLocale[2] = 0;
  450. XMLString::lowerCase(normalizedLocale);
  451. if (XMLString::stringLen(localeStr) > 2)
  452. {
  453. XMLString::catString(&(normalizedLocale[2]), &(localeStr[2]));
  454. XMLString::upperCase(&(normalizedLocale[2]));
  455. }
  456. //
  457. // Ok, its good enough to get started. So lets call the start output
  458. // method on the formatter.
  459. //
  460. formatter->startOutput(normalizedLocale, gOutPath);
  461. //
  462. // For each message domain element, we call start and end domain
  463. // events bracketed around the loop that sends out each message
  464. // in that domain.
  465. //
  466. // Within each domain, we check for the Warning, Error, and Validity
  467. // subelements, and then iterate all the messages in each one.
  468. //
  469. for (unsigned int index = 0; index < count; index++)
  470. {
  471. // We know its a DOM Element, so go ahead and cast it
  472. DOMNode* curNode = msgSetList->item(index);
  473. const DOMElement* curElem = (const DOMElement*)curNode;
  474. //
  475. // Get some of the attribute strings that we need, and transcode
  476. // couple that need to be in local format.
  477. //
  478. tmpXMLStr = XMLString::transcode("Domain");
  479. const XMLCh* domainStr = curElem->getAttribute(tmpXMLStr );
  480. XMLString::release(&tmpXMLStr);
  481. //
  482. // Look at the domain and set up our application specific info
  483. // that is on a per-domain basis. We need to indicate what the
  484. // name of the header is and what the namespace is that they
  485. // codes will go into
  486. //
  487. XMLCh* headerName = 0;
  488. XMLCh* errNameSpace = 0;
  489. if (!XMLString::compareString(domainStr, XMLUni::fgXMLErrDomain))
  490. {
  491. headerName = XMLString::transcode("XMLErrorCodes.hpp");
  492. errNameSpace = XMLString::transcode("XMLErrs");
  493. }
  494. else if (!XMLString::compareString(domainStr, XMLUni::fgValidityDomain))
  495. {
  496. headerName = XMLString::transcode("XMLValidityCodes.hpp");
  497. errNameSpace = XMLString::transcode("XMLValid");
  498. }
  499. else if (!XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
  500. {
  501. headerName = XMLString::transcode("XMLExceptMsgs.hpp");
  502. errNameSpace = XMLString::transcode("XMLExcepts");
  503. }
  504. else if (!XMLString::compareString(domainStr, XMLUni::fgXMLDOMMsgDomain))
  505. {
  506. headerName = XMLString::transcode("XMLDOMMsg.hpp");
  507. errNameSpace = XMLString::transcode("XMLDOMMsg");
  508. }
  509. else
  510. {
  511. // Not one of ours, so skip it
  512. continue;
  513. }
  514. //
  515. // Lets try to create the header file that was indicated for
  516. // this domain.
  517. //
  518. tmpFileBuf = new XMLCh [bufSize + 1];
  519. tmpFileBuf[0] = 0;
  520. XMLString::catString(tmpFileBuf, gOutPath);
  521. XMLString::catString(tmpFileBuf, headerName);
  522. char *tmpFileBufCh = XMLString::transcode(tmpFileBuf);
  523. FILE* outHeader = fopen(tmpFileBufCh, "wt+");
  524. XMLString::release(&tmpFileBufCh);
  525. if ((!outHeader) || (fwide(outHeader, 1) < 0))
  526. {
  527. wprintf(L"Could not open domain header file: %s\n\n", xmlStrToPrintable(tmpFileBuf));
  528. releasePrintableStr
  529. XMLString::release(&tmpFileBuf);
  530. XMLString::release(&headerName);
  531. XMLString::release(&errNameSpace);
  532. throw ErrReturn_OutFileOpenFailed;
  533. }
  534. delete tmpFileBuf;
  535. //
  536. // Write out the opening of the class they are nested within, and
  537. // the header protection define.
  538. //
  539. fwprintf(outHeader, L"// This file is generated, don't edit it!!\n\n");
  540. fwprintf(outHeader, L"#if !defined(XERCESC_INCLUDE_GUARD_ERRHEADER_%s)\n", xmlStrToPrintable(errNameSpace) );
  541. releasePrintableStr
  542. fwprintf(outHeader, L"#define XERCESC_INCLUDE_GUARD_ERRHEADER_%s\n\n", xmlStrToPrintable(errNameSpace) );
  543. releasePrintableStr
  544. // If its not the exception domain, then we need a header included
  545. if (XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
  546. fwprintf(outHeader, L"#include <xercesc/framework/XMLErrorReporter.hpp>\n");
  547. // Write out the namespace declaration
  548. fwprintf(outHeader, L"#include <xercesc/util/XercesDefs.hpp>\n");
  549. fwprintf(outHeader, L"#include <xercesc/dom/DOMError.hpp>\n\n");
  550. fwprintf(outHeader, L"XERCES_CPP_NAMESPACE_BEGIN\n\n");
  551. // Now the message codes
  552. fwprintf(outHeader, L"class %s\n{\npublic :\n enum Codes\n {\n", xmlStrToPrintable(errNameSpace) );
  553. releasePrintableStr
  554. // Tell the formatter that a new domain is starting
  555. formatter->startDomain
  556. (
  557. domainStr
  558. , errNameSpace
  559. );
  560. //
  561. // Force out the first message, which is always implicit and is
  562. // the 'no error' entry for that domain.
  563. //
  564. unsigned int count = 0;
  565. fwprintf(outHeader, L" %-32s = %d\n", longChars("NoError"), count++);
  566. //
  567. // Loop through the children of this node, which should take us
  568. // through the optional Warning, Error, and Validity subsections.
  569. //
  570. DOMNode* typeNode = curElem->getFirstChild();
  571. bool typeGotten[3] = { false, false, false };
  572. while (typeNode)
  573. {
  574. // Skip over text nodes or comment nodes ect...
  575. if (typeNode->getNodeType() != DOMNode::ELEMENT_NODE)
  576. {
  577. typeNode = typeNode->getNextSibling();
  578. continue;
  579. }
  580. // Convert it to an element node
  581. const DOMElement* typeElem = (const DOMElement*)typeNode;
  582. // Now get its tag name and convert that to a message type enum
  583. const XMLCh* typeName = typeElem->getTagName();
  584. MsgTypes type;
  585. tmpXMLStr = XMLString::transcode("Warning");
  586. XMLCh* tmpXMLStr2 = XMLString::transcode("Error");
  587. XMLCh* tmpXMLStr3 =XMLString::transcode("FatalError");
  588. if (!XMLString::compareString(typeName, tmpXMLStr ))
  589. {
  590. type = MsgType_Warning;
  591. typeGotten[0] = true;
  592. }
  593. else if (!XMLString::compareString(typeName, tmpXMLStr2 ))
  594. {
  595. type = MsgType_Error;
  596. typeGotten[1] = true;
  597. }
  598. else if (!XMLString::compareString(typeName, tmpXMLStr3 ))
  599. {
  600. type = MsgType_FatalError;
  601. typeGotten[2] = true;
  602. }
  603. else
  604. {
  605. wprintf(L"Expected a Warning, Error, or FatalError node\n\n");
  606. XMLString::release(&tmpXMLStr);
  607. XMLString::release(&tmpXMLStr2);
  608. XMLString::release(&tmpXMLStr3);
  609. throw ErrReturn_SrcFmtError;
  610. }
  611. XMLString::release(&tmpXMLStr);
  612. XMLString::release(&tmpXMLStr2);
  613. XMLString::release(&tmpXMLStr3);
  614. // Call the start message type event
  615. formatter->startMsgType(type);
  616. // Enumerate the messages under this subsection
  617. enumMessages
  618. (
  619. typeElem
  620. , formatter
  621. , outHeader
  622. , type
  623. , count
  624. );
  625. // Call the end message type event
  626. formatter->endMsgType(type);
  627. // Move to the next child of the source element
  628. typeNode = typeNode->getNextSibling();
  629. }
  630. //
  631. // For any that we did not get, spit out faux boundary
  632. // values for it.
  633. //
  634. for (unsigned int subIndex = 0; subIndex < 3; subIndex++)
  635. {
  636. if (!typeGotten[subIndex])
  637. {
  638. fwprintf
  639. (
  640. outHeader
  641. , L" , %s%-30s = %d\n"
  642. , xmlStrToPrintable(typePrefixes[subIndex])
  643. , longChars("LowBounds")
  644. , count++
  645. );
  646. releasePrintableStr
  647. fwprintf
  648. (
  649. outHeader
  650. , L" , %s%-30s = %d\n"
  651. , xmlStrToPrintable(typePrefixes[subIndex])
  652. , longChars("HighBounds")
  653. , count++
  654. );
  655. releasePrintableStr
  656. }
  657. }
  658. // Tell the formatter that this domain is ending
  659. formatter->endDomain(domainStr, count);
  660. // Close out the enum declaration
  661. fwprintf(outHeader, L" };\n\n");
  662. //
  663. // Generate the code that creates the simple static methods
  664. // for testing the error types. We don't do this for the
  665. // exceptions header.
  666. //
  667. if (XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
  668. {
  669. fwprintf
  670. (
  671. outHeader
  672. , L" static bool isFatal(const %s::Codes toCheck)\n"
  673. L" {\n"
  674. L" return ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds));\n"
  675. L" }\n\n"
  676. , xmlStrToPrintable(errNameSpace)
  677. );
  678. releasePrintableStr
  679. fwprintf
  680. (
  681. outHeader
  682. , L" static bool isWarning(const %s::Codes toCheck)\n"
  683. L" {\n"
  684. L" return ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds));\n"
  685. L" }\n\n"
  686. , xmlStrToPrintable(errNameSpace)
  687. );
  688. releasePrintableStr
  689. fwprintf
  690. (
  691. outHeader
  692. , L" static bool isError(const %s::Codes toCheck)\n"
  693. L" {\n"
  694. L" return ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds));\n"
  695. L" }\n\n"
  696. , xmlStrToPrintable(errNameSpace)
  697. );
  698. releasePrintableStr
  699. fwprintf
  700. (
  701. outHeader
  702. , L" static XMLErrorReporter::ErrTypes errorType(const %s::Codes toCheck)\n"
  703. L" {\n"
  704. L" if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds))\n"
  705. L" return XMLErrorReporter::ErrType_Warning;\n"
  706. L" else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds))\n"
  707. L" return XMLErrorReporter::ErrType_Fatal;\n"
  708. L" else if ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds))\n"
  709. L" return XMLErrorReporter::ErrType_Error;\n"
  710. L" return XMLErrorReporter::ErrTypes_Unknown;\n"
  711. L" }\n"
  712. , xmlStrToPrintable(errNameSpace)
  713. );
  714. releasePrintableStr
  715. fwprintf
  716. (
  717. outHeader
  718. , L" static DOMError::ErrorSeverity DOMErrorType(const %s::Codes toCheck)\n"
  719. L" {\n"
  720. L" if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds))\n"
  721. L" return DOMError::DOM_SEVERITY_WARNING;\n"
  722. L" else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds))\n"
  723. L" return DOMError::DOM_SEVERITY_FATAL_ERROR;\n"
  724. L" else return DOMError::DOM_SEVERITY_ERROR;\n"
  725. L" }\n"
  726. , xmlStrToPrintable(errNameSpace)
  727. );
  728. releasePrintableStr
  729. }
  730. // the private default ctor
  731. fwprintf(outHeader, L"\n");
  732. fwprintf(outHeader, L"private:\n");
  733. fwprintf(outHeader, L" // -----------------------------------------------------------------------\n");
  734. fwprintf(outHeader, L" // Unimplemented constructors and operators\n");
  735. fwprintf(outHeader, L" // -----------------------------------------------------------------------\n");
  736. fwprintf(outHeader, L" %s();\n", xmlStrToPrintable(errNameSpace));
  737. releasePrintableStr
  738. // And close out the class declaration, the namespace declaration and the header file
  739. fwprintf(outHeader, L"};\n\n");
  740. fwprintf(outHeader, L"XERCES_CPP_NAMESPACE_END\n\n");
  741. fwprintf(outHeader, L"#endif\n\n");
  742. fclose(outHeader);
  743. XMLString::release(&headerName);
  744. XMLString::release(&errNameSpace);
  745. }
  746. // Ok, we are done so call the end output method
  747. formatter->endOutput();
  748. // And clean up the stuff we allocated
  749. delete formatter;
  750. }
  751. catch(const ErrReturns retVal)
  752. {
  753. // And call the termination method
  754. if(srcDoc)
  755. delete srcDoc;
  756. return retVal;
  757. }
  758. delete srcDoc;
  759. }
  760. // And call the termination method
  761. release_Globals();
  762. // Went ok, so return success
  763. return ErrReturn_Success;
  764. }
  765. // -----------------------------------------------------------------------
  766. // XlatErrHandler: Implementation of the error handler interface
  767. // -----------------------------------------------------------------------
  768. void XlatErrHandler::warning(const SAXParseException& toCatch)
  769. {
  770. parseError(toCatch);
  771. }
  772. void XlatErrHandler::error(const SAXParseException& toCatch)
  773. {
  774. parseError(toCatch);
  775. }
  776. void XlatErrHandler::fatalError(const SAXParseException& toCatch)
  777. {
  778. parseError(toCatch);
  779. }
  780. void XlatErrHandler::resetErrors()
  781. {
  782. }
  783. // if longChars is a macro, don't bother
  784. #ifndef longChars
  785. wchar_t* longChars(const char *str)
  786. {
  787. mbstowcs(fTmpWStr, str, 255);
  788. return (fTmpWStr);
  789. }
  790. #endif