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